From ef4c0abaa5113fd94ec5add6862373ba0712132f Mon Sep 17 00:00:00 2001 From: Bram Date: Tue, 26 Nov 2024 21:51:07 +0100 Subject: [PATCH 1/9] Added nodesFlat property and updated docs --- docs/src/pages/components/TreeView.svx | 9 +++ .../framed/TreeView/TreeViewFlatArray.svelte | 69 +++++++++++++++++++ src/TreeView/TreeView.svelte | 51 +++++++++++++- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte diff --git a/docs/src/pages/components/TreeView.svx b/docs/src/pages/components/TreeView.svx index c7c97c92de..e95b782852 100644 --- a/docs/src/pages/components/TreeView.svx +++ b/docs/src/pages/components/TreeView.svx @@ -58,12 +58,21 @@ To render a node with an icon, define an `icon` property with a Carbon Svelte ic +## Flat data structure + +Provide a flat data structure through the `nodesFlat` property. Child object needs to have a `pid` property +to reference its parent. Optionally the key for the parent can be provided. +When no parent id is available the object is assumed to be at the root of the tree. + + + ## Initial expanded nodes Expanded nodes can be set using `expandedIds`. + ## Initial multiple selected nodes Initial multiple selected nodes can be set using `selectedIds`. diff --git a/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte b/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte new file mode 100644 index 0000000000..a508b092ff --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte @@ -0,0 +1,69 @@ + + + console.log("select", detail)} + on:toggle={({ detail }) => console.log("toggle", detail)} + on:focus={({ detail }) => console.log("focus", detail)} +/> + +
Active node id: {activeId}
+
Selected ids: {JSON.stringify(selectedIds)}
+ + diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte index 31e3f26795..e32e3c53b0 100644 --- a/src/TreeView/TreeView.svelte +++ b/src/TreeView/TreeView.svelte @@ -37,11 +37,17 @@ */ /** - * Provide an array of nodes to render + * Provide a nested array of nodes to render * @type {Array} */ export let nodes = []; + /** + * Provide a flat array of nodes to render + * @type {Array[]} + */ + export let nodesFlat = []; + /** * Set the current active node id * Only one node can be active @@ -195,6 +201,48 @@ } } + /** + * Create a nested array from a flat array + * TODO: accept a parent key + * @type {(flatArray: TreeNode[] & { pid: any }[]) => TreeNode[]} + */ + function createNestedArray(flatArray) { + /** @type TreeNode[] */ + const tree = []; + /** @type TreeNode[] */ + const childrenOf = []; + + flatArray.forEach((dstItem) => { + const { id, pid } = dstItem; + childrenOf[id] = childrenOf[id] || []; + dstItem["nodes"] = childrenOf[id]; + + if (pid) { + // objects without pid are root level objects. + childrenOf[pid] = childrenOf[pid] || []; + delete dstItem.pid; // TreeNode type doesn't have pid. + childrenOf[pid].push(dstItem); + } else { + delete dstItem.pid; + tree.push(dstItem); + } + }); + + // Remove the empty nodes props that make TreeView render a twistie. + // Maybe this should actually be taken care of in TreeView itself? It makes + // no sense i think that an empty nodes property render a twistie. + function removeEmptyNodes(element) { + element.forEach((elmt) => { + if (elmt.nodes?.length === 0) delete elmt.nodes; + else { + removeEmptyNodes(elmt.nodes); + } + }); + } + removeEmptyNodes(tree); + return tree; + } + onMount(() => { const firstFocusableNode = ref.querySelector( "li.bx--tree-node:not(.bx--tree-node--disabled)", @@ -220,6 +268,7 @@ }, []); } + $: nodes = createNestedArray(nodesFlat); $: flattenedNodes = traverse(nodes); $: nodeIds = flattenedNodes.map((node) => node.id); $: activeNodeId.set(activeId); From b754b990e720d58de261cc2a493418bf3d69bf8f Mon Sep 17 00:00:00 2001 From: Bram Date: Tue, 26 Nov 2024 23:08:03 +0100 Subject: [PATCH 2/9] Fix to only set nodes prop when nodesFlat is provided --- COMPONENT_INDEX.md | 3 ++- docs/src/COMPONENT_API.json | 14 +++++++++++++- src/TreeView/TreeView.svelte | 4 +++- types/TreeView/TreeView.svelte.d.ts | 8 +++++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/COMPONENT_INDEX.md b/COMPONENT_INDEX.md index c7c72fca87..a84ab632aa 100644 --- a/COMPONENT_INDEX.md +++ b/COMPONENT_INDEX.md @@ -4704,7 +4704,8 @@ export interface TreeNode { | expandedIds | No | let | Yes | ReadonlyArray | [] | Set the node ids to be expanded | | selectedIds | No | let | Yes | ReadonlyArray | [] | Set the node ids to be selected | | activeId | No | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | -| nodes | No | let | No | Array | [] | Provide an array of nodes to render | +| nodes | No | let | Yes | Array | [] | Provide a nested array of nodes to render | +| nodesFlat | No | let | No | Array[] | [] | Provide a flat array of nodes to render | | size | No | let | No | "default" | "compact" | "default" | Specify the TreeView size | | labelText | No | let | No | string | "" | Specify the label text | | hideLabel | No | let | No | boolean | false | Set to `true` to visually hide the label text | diff --git a/docs/src/COMPONENT_API.json b/docs/src/COMPONENT_API.json index c6ceb31d19..9bd04e0d5d 100644 --- a/docs/src/COMPONENT_API.json +++ b/docs/src/COMPONENT_API.json @@ -17770,13 +17770,25 @@ { "name": "nodes", "kind": "let", - "description": "Provide an array of nodes to render", + "description": "Provide a nested array of nodes to render", "type": "Array", "value": "[]", "isFunction": false, "isFunctionDeclaration": false, "isRequired": false, "constant": false, + "reactive": true + }, + { + "name": "nodesFlat", + "kind": "let", + "description": "Provide a flat array of nodes to render", + "type": "Array[]", + "value": "[]", + "isFunction": false, + "isFunctionDeclaration": false, + "isRequired": false, + "constant": false, "reactive": false }, { diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte index e32e3c53b0..aae3e1b74b 100644 --- a/src/TreeView/TreeView.svelte +++ b/src/TreeView/TreeView.svelte @@ -268,7 +268,9 @@ }, []); } - $: nodes = createNestedArray(nodesFlat); + $: if (nodesFlat.length > 0) { + nodes = createNestedArray(nodesFlat); + } $: flattenedNodes = traverse(nodes); $: nodeIds = flattenedNodes.map((node) => node.id); $: activeNodeId.set(activeId); diff --git a/types/TreeView/TreeView.svelte.d.ts b/types/TreeView/TreeView.svelte.d.ts index 342f24c95b..546cb86c47 100644 --- a/types/TreeView/TreeView.svelte.d.ts +++ b/types/TreeView/TreeView.svelte.d.ts @@ -15,11 +15,17 @@ type $RestProps = SvelteHTMLElements["ul"]; type $Props = { /** - * Provide an array of nodes to render + * Provide a nested array of nodes to render * @default [] */ nodes?: Array; + /** + * Provide a flat array of nodes to render + * @default [] + */ + nodesFlat?: Array[]; + /** * Set the current active node id * Only one node can be active From 655a205b0a31bb6f1f111d823ae2d04c0f42c331 Mon Sep 17 00:00:00 2001 From: Bram Date: Tue, 26 Nov 2024 23:11:57 +0100 Subject: [PATCH 3/9] Fix: updated doc, removed [] on type definition for nodesFlat --- COMPONENT_INDEX.md | 2 +- docs/src/COMPONENT_API.json | 2 +- src/TreeView/TreeView.svelte | 2 +- types/TreeView/TreeView.svelte.d.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/COMPONENT_INDEX.md b/COMPONENT_INDEX.md index a84ab632aa..7c99aaed75 100644 --- a/COMPONENT_INDEX.md +++ b/COMPONENT_INDEX.md @@ -4705,7 +4705,7 @@ export interface TreeNode { | selectedIds | No | let | Yes | ReadonlyArray | [] | Set the node ids to be selected | | activeId | No | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | | nodes | No | let | Yes | Array | [] | Provide a nested array of nodes to render | -| nodesFlat | No | let | No | Array[] | [] | Provide a flat array of nodes to render | +| nodesFlat | No | let | No | Array | [] | Provide a flat array of nodes to render | | size | No | let | No | "default" | "compact" | "default" | Specify the TreeView size | | labelText | No | let | No | string | "" | Specify the label text | | hideLabel | No | let | No | boolean | false | Set to `true` to visually hide the label text | diff --git a/docs/src/COMPONENT_API.json b/docs/src/COMPONENT_API.json index 9bd04e0d5d..cdd9b20eca 100644 --- a/docs/src/COMPONENT_API.json +++ b/docs/src/COMPONENT_API.json @@ -17783,7 +17783,7 @@ "name": "nodesFlat", "kind": "let", "description": "Provide a flat array of nodes to render", - "type": "Array[]", + "type": "Array", "value": "[]", "isFunction": false, "isFunctionDeclaration": false, diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte index aae3e1b74b..8ad02f40b7 100644 --- a/src/TreeView/TreeView.svelte +++ b/src/TreeView/TreeView.svelte @@ -44,7 +44,7 @@ /** * Provide a flat array of nodes to render - * @type {Array[]} + * @type {Array} */ export let nodesFlat = []; diff --git a/types/TreeView/TreeView.svelte.d.ts b/types/TreeView/TreeView.svelte.d.ts index 546cb86c47..7a013fa9da 100644 --- a/types/TreeView/TreeView.svelte.d.ts +++ b/types/TreeView/TreeView.svelte.d.ts @@ -24,7 +24,7 @@ type $Props = { * Provide a flat array of nodes to render * @default [] */ - nodesFlat?: Array[]; + nodesFlat?: Array; /** * Set the current active node id From 56ebbb4cbfa89c850d2b4c6a2ddc4bb85f755ca0 Mon Sep 17 00:00:00 2001 From: Bram Date: Tue, 26 Nov 2024 23:57:44 +0100 Subject: [PATCH 4/9] Added test for flat array input data --- src/TreeView/TreeView.svelte | 5 +- tests/TreeView/TreeView.test.ts | 11 +++ tests/TreeView/TreeViewFlatArray.test.svelte | 75 ++++++++++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 tests/TreeView/TreeViewFlatArray.test.svelte diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte index 8ad02f40b7..80c769edac 100644 --- a/src/TreeView/TreeView.svelte +++ b/src/TreeView/TreeView.svelte @@ -44,7 +44,7 @@ /** * Provide a flat array of nodes to render - * @type {Array} + * @type {Array} */ export let nodesFlat = []; @@ -203,8 +203,7 @@ /** * Create a nested array from a flat array - * TODO: accept a parent key - * @type {(flatArray: TreeNode[] & { pid: any }[]) => TreeNode[]} + * @type {(flatArray: TreeNode[] & { pid?: any }[]) => TreeNode[]} */ function createNestedArray(flatArray) { /** @type TreeNode[] */ diff --git a/tests/TreeView/TreeView.test.ts b/tests/TreeView/TreeView.test.ts index b2a0a6a3f2..0e29a9d9c4 100644 --- a/tests/TreeView/TreeView.test.ts +++ b/tests/TreeView/TreeView.test.ts @@ -1,6 +1,7 @@ import { render, screen } from "@testing-library/svelte"; import { user } from "../setup-tests"; import TreeView from "./TreeView.test.svelte"; +import TreeViewFlatArray from "./TreeViewFlatArray.test.svelte"; describe("TreeView", () => { const getItemByName = (name: RegExp) => { @@ -37,4 +38,14 @@ describe("TreeView", () => { text: "AI / Machine learning", }); }); + + it("can turn flat array into nested array", async () => { + const consoleLog = vi.spyOn(console, "log"); + render(TreeViewFlatArray); + const firstItem = getItemByName(/Blockchain/); + expect(firstItem).toBeInTheDocument(); + await user.click(firstItem); + expect(getSelectedItemByName(/Blockchain/)).toBeInTheDocument(); + expect(consoleLog).toBeCalledWith("selectedIds", [7]); + }); }); diff --git a/tests/TreeView/TreeViewFlatArray.test.svelte b/tests/TreeView/TreeViewFlatArray.test.svelte new file mode 100644 index 0000000000..86b7fe718f --- /dev/null +++ b/tests/TreeView/TreeViewFlatArray.test.svelte @@ -0,0 +1,75 @@ + + + console.log("select", detail)} + on:toggle={({ detail }) => console.log("toggle", detail)} + on:focus={({ detail }) => console.log("focus", detail)} + let:node +> + {node.text} + + + From f453af437ad88f499b69674d047490c88643e0fe Mon Sep 17 00:00:00 2001 From: Bram Date: Thu, 28 Nov 2024 21:34:10 +0100 Subject: [PATCH 5/9] Fix typescript error on test with better TreeView typing definition for nodesFlat --- COMPONENT_INDEX.md | 2 +- docs/src/COMPONENT_API.json | 2 +- types/TreeView/TreeView.svelte.d.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/COMPONENT_INDEX.md b/COMPONENT_INDEX.md index 7c99aaed75..a82d811969 100644 --- a/COMPONENT_INDEX.md +++ b/COMPONENT_INDEX.md @@ -4705,7 +4705,7 @@ export interface TreeNode { | selectedIds | No | let | Yes | ReadonlyArray | [] | Set the node ids to be selected | | activeId | No | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | | nodes | No | let | Yes | Array | [] | Provide a nested array of nodes to render | -| nodesFlat | No | let | No | Array | [] | Provide a flat array of nodes to render | +| nodesFlat | No | let | No | Array | [] | Provide a flat array of nodes to render | | size | No | let | No | "default" | "compact" | "default" | Specify the TreeView size | | labelText | No | let | No | string | "" | Specify the label text | | hideLabel | No | let | No | boolean | false | Set to `true` to visually hide the label text | diff --git a/docs/src/COMPONENT_API.json b/docs/src/COMPONENT_API.json index cdd9b20eca..005acb7678 100644 --- a/docs/src/COMPONENT_API.json +++ b/docs/src/COMPONENT_API.json @@ -17783,7 +17783,7 @@ "name": "nodesFlat", "kind": "let", "description": "Provide a flat array of nodes to render", - "type": "Array", + "type": "Array", "value": "[]", "isFunction": false, "isFunctionDeclaration": false, diff --git a/types/TreeView/TreeView.svelte.d.ts b/types/TreeView/TreeView.svelte.d.ts index 7a013fa9da..bfca22a464 100644 --- a/types/TreeView/TreeView.svelte.d.ts +++ b/types/TreeView/TreeView.svelte.d.ts @@ -24,7 +24,7 @@ type $Props = { * Provide a flat array of nodes to render * @default [] */ - nodesFlat?: Array; + nodesFlat?: Array; /** * Set the current active node id From 491b319078112bcfb67673bc63b9f3a1ae0b6595 Mon Sep 17 00:00:00 2001 From: Bram Date: Sun, 1 Dec 2024 21:27:12 +0100 Subject: [PATCH 6/9] Moved function to treeview.js --- .../framed/TreeView/TreeViewFlatArray.svelte | 4 +- src/TreeView/TreeView.svelte | 50 ------------------- src/TreeView/index.d.ts | 2 + src/TreeView/index.js | 1 + src/TreeView/treeview.d.ts | 9 ++++ src/TreeView/treeview.js | 42 ++++++++++++++++ 6 files changed, 56 insertions(+), 52 deletions(-) create mode 100644 src/TreeView/index.d.ts create mode 100644 src/TreeView/treeview.d.ts create mode 100644 src/TreeView/treeview.js diff --git a/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte b/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte index a508b092ff..0f14cc36ef 100644 --- a/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte +++ b/docs/src/pages/framed/TreeView/TreeViewFlatArray.svelte @@ -1,5 +1,5 @@