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

120 lines
2.8 KiB
Svelte
Raw Normal View History

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