budibase/packages/bootstrap-components/src/Nav.svelte

133 lines
2.8 KiB
Svelte
Raw Normal View History

2019-10-14 09:32:20 +02:00
<script>
export let items = [];
export let hideNavBar=false;
export let selectedItem="";
export let orientation="horizontal"; // horizontal, verical
2019-10-18 18:32:03 +02:00
export let alignment="start"; // start, center, end
2019-10-14 09:32:20 +02:00
export let pills=false;
export let fill=false;
export let _bb;
let selectedIndex = -1;
let styleVars={};
let components = {};
2019-10-18 18:32:03 +02:00
let componentElement;
2019-10-14 09:32:20 +02:00
let orientationClass="";
let navClasses="";
2019-10-18 18:32:03 +02:00
let currentComponent;
let _selectedItem="";
2019-10-14 09:32:20 +02:00
const hasComponentElements = () =>
Object.getOwnPropertyNames(componentElements).length > 0;
2019-10-18 18:32:03 +02:00
const getSelectedItemByIndex = (index) =>
index >= 0
? items[index].title
: "";
2019-10-14 09:32:20 +02:00
$: {
let _navClasses = "";
if(orientation === "vertical") {
_navClasses += " flex-column";
} else {
_navClasses += ` justify-content-${alignment}`;
}
if(pills)
_navClasses += " nav-pills";
if(fill)
_navClasses += " nav-fill nav-justified";
navClasses = _navClasses;
2019-10-18 18:32:03 +02:00
if(items ) {
const currentSelectedItem = getSelectedItemByIndex(selectedIndex);
2019-10-14 09:32:20 +02:00
if(selectedItem && currentSelectedItem !== selectedItem) {
let i=0;
for(let item of items) {
if(item.title === selectedItem) {
2019-10-18 18:32:03 +02:00
SelectItem(i);
2019-10-14 09:32:20 +02:00
}
i++;
}
2019-10-18 18:32:03 +02:00
} else if(!selectedItem) {
SelectItem(-1);
2019-10-14 09:32:20 +02:00
}
}
}
2019-10-18 18:32:03 +02:00
const SelectItem = (index) => {
2019-10-14 09:32:20 +02:00
selectedIndex = index;
2019-10-18 18:32:03 +02:00
const newSelectedItem = getSelectedItemByIndex(index);
if(newSelectedItem !== selectedItem) {
selectedItem = newSelectedItem;
}
if(currentComponent) {
try {
currentComponent.$destroy();
} catch(_) {}
}
if(index >= 0)
currentComponent = _bb.hydrateComponent(
items[index].component, componentElement);
}
const onSelectItemClicked = index => () => {
if(_bb.bindings["selectedItem"]) {
// binding - call state, which should SelectItem(..)
const selectedItemBinding = _bb.bindings["selectedItem"];
_bb.setStateFromBinding(
selectedItemBinding, getSelectedItemByIndex(index))
} else {
// no binding - call this
SelectItem(index);
2019-10-14 09:32:20 +02:00
}
}
</script>
<div class="root">
{#if !hideNavBar}
2019-10-18 18:32:03 +02:00
<ul class="nav {navClasses}">
2019-10-14 09:32:20 +02:00
{#each items as navItem, index}
2019-10-18 18:32:03 +02:00
<li class="nav-item">
<button class="nav-link btn btn-link"
on:click={onSelectItemClicked(index)}
class:disabled={navItem.disabled}
class:active={selectedIndex === index}>
{navItem.title}
</button>
</li>
2019-10-14 09:32:20 +02:00
{/each}
2019-10-18 18:32:03 +02:00
</ul>
2019-10-14 09:32:20 +02:00
{/if}
{#each items as navItem, index}
2019-10-18 18:32:03 +02:00
<div bind:this={componentElement}>
2019-10-14 09:32:20 +02:00
</div>
{/each}
</div>
<style>
.root {
height: 100%;
width:100%;
}
</style>