You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.0 KiB
Svelte

<script>import TreeViewItem from "./TreeViewItem.svelte";
import RecursiveTreeViewItem from "./RecursiveTreeViewItem.svelte";
import { createEventDispatcher, getContext, onMount, tick } from "svelte";
export let nodes = [];
export let expandedNodes = [];
export let disabledNodes = [];
export let checkedNodes = [];
export let indeterminateNodes = [];
let selection = getContext("selection");
let multiple = getContext("multiple");
let relational = getContext("relational");
let tempCheckedNodes = [];
let group;
let name = "";
const dispatch = createEventDispatcher();
function toggleNode(node, open) {
if (!node.children?.length)
return;
if (open) {
if (!expandedNodes.includes(node.id)) {
expandedNodes.push(node.id);
expandedNodes = expandedNodes;
}
} else {
if (expandedNodes.includes(node.id)) {
expandedNodes.splice(expandedNodes.indexOf(node.id), 1);
expandedNodes = expandedNodes;
}
}
}
function checkNode(node, checked, indeterminate) {
if (checked) {
if (!checkedNodes.includes(node.id)) {
checkedNodes.push(node.id);
checkedNodes = checkedNodes;
}
if (!indeterminate && indeterminateNodes.includes(node.id)) {
indeterminateNodes.splice(indeterminateNodes.indexOf(node.id), 1);
indeterminateNodes = indeterminateNodes;
}
} else {
if (checkedNodes.includes(node.id)) {
checkedNodes.splice(checkedNodes.indexOf(node.id), 1);
checkedNodes = checkedNodes;
}
if (indeterminate && !indeterminateNodes.includes(node.id)) {
indeterminateNodes.push(node.id);
indeterminateNodes = indeterminateNodes;
} else if (!indeterminate && indeterminateNodes.includes(node.id)) {
indeterminateNodes.splice(indeterminateNodes.indexOf(node.id), 1);
indeterminateNodes = indeterminateNodes;
}
}
}
tempCheckedNodes = [...checkedNodes];
onMount(async () => {
if (selection) {
name = String(Math.random());
if (group === void 0) {
if (multiple) {
group = [];
nodes.forEach((node) => {
if (checkedNodes.includes(node.id) && Array.isArray(group))
group.push(node.id);
});
group = group;
} else if (!nodes.some((node) => checkedNodes.includes(node.id))) {
group = "";
}
}
if (!relational)
treeItems = [];
checkedNodes = [];
await tick();
checkedNodes = [...tempCheckedNodes];
}
});
export let treeItems = [];
let children = [];
</script>
{#if nodes && nodes.length > 0}
{#each nodes as node, i}
<TreeViewItem
bind:this={treeItems[i]}
bind:children={children[i]}
bind:group
bind:name
bind:value={node.id}
hideLead={!node.lead}
hideChildren={!node.children || node.children.length === 0}
open={expandedNodes.includes(node.id)}
disabled={disabledNodes.includes(node.id)}
checked={checkedNodes.includes(node.id)}
indeterminate={indeterminateNodes.includes(node.id)}
on:toggle={(e) => toggleNode(node, e.detail.open)}
on:groupChange={(e) => checkNode(node, e.detail.checked, e.detail.indeterminate)}
on:click={() =>
dispatch('click', {
id: node.id
})}
on:toggle={() => {
dispatch('toggle', {
id: node.id
});
}}
>
{#if typeof node.content === 'string'}
{@html node.content}
{:else}
<svelte:component this={node.content} {...node.contentProps} />
{/if}
<svelte:fragment slot="lead">
{#if typeof node.lead === 'string'}
{@html node.lead}
{:else}
<svelte:component this={node.lead} {...node.leadProps} />
{/if}
</svelte:fragment>
<svelte:fragment slot="children">
<RecursiveTreeViewItem
nodes={node.children}
bind:expandedNodes
bind:disabledNodes
bind:checkedNodes
bind:indeterminateNodes
bind:treeItems={children[i]}
on:click={(e) =>
dispatch('click', {
id: e.detail.id
})}
on:toggle={(e) =>
dispatch('toggle', {
id: e.detail.id
})}
/>
</svelte:fragment>
</TreeViewItem>
{/each}
{/if}