141 lines
4.0 KiB
Svelte
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}
|