From 7b9e7953ffdcc5e874644bd6c52ddee75f3db819 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Sun, 13 Jul 2025 12:30:21 +0300 Subject: [PATCH 01/13] rename tree, tree-utils with svelte prefix --- packages/svelte-tree-view/src/lib/stores/index.ts | 4 ++-- .../src/lib/stores/{tree.ts => tree.svelte.ts} | 2 +- .../src/lib/{tree-utils.ts => tree-utils.svelte.ts} | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename packages/svelte-tree-view/src/lib/stores/{tree.ts => tree.svelte.ts} (99%) rename packages/svelte-tree-view/src/lib/{tree-utils.ts => tree-utils.svelte.ts} (100%) diff --git a/packages/svelte-tree-view/src/lib/stores/index.ts b/packages/svelte-tree-view/src/lib/stores/index.ts index ef5d5f9..d261522 100644 --- a/packages/svelte-tree-view/src/lib/stores/index.ts +++ b/packages/svelte-tree-view/src/lib/stores/index.ts @@ -1,10 +1,10 @@ import type { PropsStore } from './props' import type { RootElementStore } from './root-element' -import type { TreeStore } from './tree' +import type { TreeStore } from './tree.svelte' export { createPropsStore } from './props' export { createRootElementStore } from './root-element' -export { createTreeStore } from './tree' +export { createTreeStore } from './tree.svelte' export interface Stores { propsStore: PropsStore diff --git a/packages/svelte-tree-view/src/lib/stores/tree.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts similarity index 99% rename from packages/svelte-tree-view/src/lib/stores/tree.ts rename to packages/svelte-tree-view/src/lib/stores/tree.svelte.ts index eedfdf4..5561a14 100644 --- a/packages/svelte-tree-view/src/lib/stores/tree.ts +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts @@ -1,6 +1,6 @@ import { get, writable } from 'svelte/store' -import { createNode, recomputeTree, recurseObjectProperties } from '../tree-utils' +import { createNode, recomputeTree, recurseObjectProperties } from '../tree-utils.svelte' import type { TreeNode, TreeRecursionOpts } from '../types' import type { PropsStore } from './props' diff --git a/packages/svelte-tree-view/src/lib/tree-utils.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts similarity index 100% rename from packages/svelte-tree-view/src/lib/tree-utils.ts rename to packages/svelte-tree-view/src/lib/tree-utils.svelte.ts From 7a2204decf84c292f6c85774e63e6a69adee19b9 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Sun, 13 Jul 2025 20:38:56 +0300 Subject: [PATCH 02/13] refactor site state to treeOpts --- .../site/src/components/DataSelector.svelte | 4 ++-- packages/site/src/components/PropsForm.svelte | 22 +++++++++---------- packages/site/src/lib/store.ts | 6 ++--- packages/site/src/routes/+layout.svelte | 14 ++++++------ packages/site/src/routes/+page.svelte | 6 ++--- .../site/src/routes/circular/+page.svelte | 6 ++--- packages/site/src/routes/diff/+page.svelte | 6 ++--- .../site/src/routes/tailwind/+page.svelte | 6 ++--- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/packages/site/src/components/DataSelector.svelte b/packages/site/src/components/DataSelector.svelte index fb49c54..2af3141 100644 --- a/packages/site/src/components/DataSelector.svelte +++ b/packages/site/src/components/DataSelector.svelte @@ -1,5 +1,5 @@
@@ -7,7 +7,7 @@
+
- +
- +
- +
- +
- +
@@ -52,7 +52,7 @@
@@ -61,7 +61,7 @@
@@ -78,7 +78,7 @@ diff --git a/packages/site/src/lib/store.ts b/packages/site/src/lib/store.ts index 24d2162..eff34fa 100644 --- a/packages/site/src/lib/store.ts +++ b/packages/site/src/lib/store.ts @@ -136,7 +136,7 @@ const testNode = { children: [] } -export const state = writable(DEFAULT_STATE) +export const treeOpts = writable(DEFAULT_STATE) export const parsedData = writable(example1) export const parsedRecursionOpts = writable( parser.parseRecursionOpts(DEFAULT_STATE.recursionOpts, testNode) @@ -149,11 +149,11 @@ export const parsedTheme = writable(parser.parseTheme(DEFAULT_STATE.theme)) export function setExampleData(str: string) { const opt = str as DataOption parsedData.set(DATA[opt]) - state.update(s => ({ ...s, selectedData: opt })) + treeOpts.update(s => ({ ...s, selectedData: opt })) } export function update(key: K, val: FormState[K]) { - state.update(o => { + treeOpts.update(o => { o[key] = val if (key === 'data') { o.selectedData = null diff --git a/packages/site/src/routes/+layout.svelte b/packages/site/src/routes/+layout.svelte index 18df138..59e077b 100644 --- a/packages/site/src/routes/+layout.svelte +++ b/packages/site/src/routes/+layout.svelte @@ -3,17 +3,17 @@ import DataSelector from '$components/DataSelector.svelte' import PropsForm from '$components/PropsForm.svelte' - import { state, parsedTheme, update } from '$lib/store' + import { treeOpts, parsedTheme, update } from '$lib/store' import '../app.css' let { children } = $props() - let leftIndent = $derived($state.leftIndent) - let lineHeight = $derived($state.lineHeight) - let fontFamily = $derived($state.fontFamily) - let fontSize = $derived($state.fontSize) - let keyMarginRight = $derived($state.keyMarginRight) + let leftIndent = $derived($treeOpts.leftIndent) + let lineHeight = $derived($treeOpts.lineHeight) + let fontFamily = $derived($treeOpts.fontFamily) + let fontSize = $derived($treeOpts.fontSize) + let keyMarginRight = $derived($treeOpts.keyMarginRight) $effect(() => { leftIndent && document.documentElement.style.setProperty(`--tree-view-left-indent`, leftIndent) @@ -84,7 +84,7 @@ diff --git a/packages/site/src/routes/+page.svelte b/packages/site/src/routes/+page.svelte index de7fd01..be86c3a 100644 --- a/packages/site/src/routes/+page.svelte +++ b/packages/site/src/routes/+page.svelte @@ -4,7 +4,7 @@ import { mapDocDeltaChildren } from '$lib/mapDocDeltaChildren' import { - state, + treeOpts, parsedData, parsedRecursionOpts, parsedTheme, @@ -25,8 +25,8 @@ Date: Sun, 13 Jul 2025 22:38:24 +0300 Subject: [PATCH 03/13] change value to getValue, add onUpdate without breaking tests --- packages/site/src/components/DiffValue.svelte | 2 +- .../site/src/components/TailwindNode.svelte | 5 +- .../src/lib/DefaultNode.svelte | 5 +- .../svelte-tree-view/src/lib/TreeView.svelte | 8 +- .../src/lib/TreeViewNode.svelte | 7 +- .../src/lib/__tests__/TreeView.spec.ts | 19 +- .../__tests__/__snapshots__/1-0-treemap.json | 247 +++++++ .../__tests__/__snapshots__/1-1-treemap.json | 580 ++++++++++++++++ .../__tests__/__snapshots__/1-2-treemap.json | 644 ++++++++++++++++++ .../src/lib/stores/tree.svelte.ts | 30 +- .../src/lib/tree-utils.svelte.ts | 6 +- packages/svelte-tree-view/src/lib/types.ts | 3 +- 12 files changed, 1519 insertions(+), 37 deletions(-) create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-0-treemap.json create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-1-treemap.json create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-2-treemap.json diff --git a/packages/site/src/components/DiffValue.svelte b/packages/site/src/components/DiffValue.svelte index bd5422d..5a9c0db 100644 --- a/packages/site/src/components/DiffValue.svelte +++ b/packages/site/src/components/DiffValue.svelte @@ -14,7 +14,7 @@ } = getTreeContext() let hasChildren = $derived(node.children.length > 0) let descend = $derived(!node.collapsed && hasChildren) - let value = $derived(node.value) + let value = $derived(node.getValue()) function replaceSpacesWithNonBreakingSpace(value: string) { return value.replace(/\s/gm, ' ') diff --git a/packages/site/src/components/TailwindNode.svelte b/packages/site/src/components/TailwindNode.svelte index e1d78c3..fc6b77a 100644 --- a/packages/site/src/components/TailwindNode.svelte +++ b/packages/site/src/components/TailwindNode.svelte @@ -65,12 +65,13 @@ // Get the appropriate value to display function getDisplayValue(): string { + const val = node.getValue() if (hasChildren && node.collapsed) { // Show truncated preview when collapsed - return createTruncatedPreview(node.value, node.type) + return createTruncatedPreview(val, node.type) } else { // Show full value when expanded or for leaf nodes - return $propsObj.valueFormatter?.(node.value, node) ?? String(node.value) + return $propsObj.valueFormatter?.(val, node) ?? String(val) } } diff --git a/packages/svelte-tree-view/src/lib/DefaultNode.svelte b/packages/svelte-tree-view/src/lib/DefaultNode.svelte index 91d0f07..89caa7e 100644 --- a/packages/svelte-tree-view/src/lib/DefaultNode.svelte +++ b/packages/svelte-tree-view/src/lib/DefaultNode.svelte @@ -12,8 +12,9 @@ const { propsStore: { props: propsObj } } = getTreeContext() - let hasChildren = $derived(node && node.children.length > 0) + let hasChildren = $derived(node.children.length > 0) let descend = $derived(!node.collapsed && hasChildren) + let valueStr = $derived($propsObj.valueFormatter?.(node.getValue(), node))
  • @@ -39,7 +40,7 @@ onclick={handleToggleCollapse} role="presentation" > - {$propsObj.valueFormatter?.(node.value, node)} + {valueStr}
    {#if $propsObj.showLogButton} diff --git a/packages/svelte-tree-view/src/lib/TreeView.svelte b/packages/svelte-tree-view/src/lib/TreeView.svelte index 5b86ad0..c2bae51 100644 --- a/packages/svelte-tree-view/src/lib/TreeView.svelte +++ b/packages/svelte-tree-view/src/lib/TreeView.svelte @@ -24,6 +24,7 @@ showCopyButton, recursionOpts, valueFormatter, + onUpdate, ...rest }: Props = $props() @@ -33,13 +34,15 @@ showLogButton, showCopyButton, recursionOpts: { ...DEFAULT_RECURSION_OPTS, ...recursionOpts }, - valueFormatter + valueFormatter, + onUpdate } let rootElement: HTMLElement const propsStore = createPropsStore(propsObj) const rootElementStore = createRootElementStore() const treeStore = createTreeStore(propsStore) const newRecOpts = $derived({ ...DEFAULT_RECURSION_OPTS, ...recursionOpts }) + // const treeChildren = $derived(treeStore.treeMap['[]']?.children) const tree = treeStore.tree setContext('svelte-tree-view', { @@ -61,7 +64,8 @@ showLogButton, showCopyButton, recursionOpts: propsObj.recursionOpts, - valueFormatter + valueFormatter, + onUpdate } propsStore.setProps(propsObj) }) diff --git a/packages/svelte-tree-view/src/lib/TreeViewNode.svelte b/packages/svelte-tree-view/src/lib/TreeViewNode.svelte index 6438d0e..c5f0b72 100644 --- a/packages/svelte-tree-view/src/lib/TreeViewNode.svelte +++ b/packages/svelte-tree-view/src/lib/TreeViewNode.svelte @@ -16,6 +16,7 @@ const { treeStore, propsStore, rootElementStore } = getContext('svelte-tree-view') let { props: propsObj } = propsStore + // let node = $state(treeStore.treeMap[id] as TreeNode) let node = $state(get(treeStore.treeMap)[id] as TreeNode) let hasChildren = $derived(node && node.children.length > 0) let nodeProps = $derived({ @@ -24,16 +25,16 @@ TreeViewNode: TreeViewNode, handleLogNode() { console.info('%c [svelte-tree-view]: Property added to window._node', 'color: #b8e248') - console.log(node.value) + console.log(node.getValue()) try { - if (typeof window !== 'undefined') window._node = node.value + if (typeof window !== 'undefined') window._node = node.getValue() } catch (err) { console.error('Failed to set _node, window was undefined') } }, handleCopyNodeToClipboard() { try { - navigator.clipboard.writeText(JSON.stringify(node.value)) + navigator.clipboard.writeText(JSON.stringify(node.getValue())) } catch (err) { console.error('Copying node to clipboard failed: ', err) } diff --git a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts index faa32d0..e8c3abd 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts +++ b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts @@ -8,6 +8,9 @@ import { generateObj } from './generateObj' import type { TreeNode } from '../types' +const snapPath = (i: number, j: number, name?: string) => + `./__snapshots__/${i}-${j}${name ? '-' + name : ''}.json` + // https://sveltesociety.dev/recipes/testing-and-debugging/unit-testing-svelte-component/ async function clickByText(container: HTMLElement, text: string, index = 0) { @@ -48,12 +51,13 @@ describe('TreeView', () => { stopCircularRecursion: true, isCircularNode(node: TreeNode, iteratedValues: Map) { if (node.type === 'object' || node.type === 'array') { - const existingNodeWithValue = iteratedValues.get(node.value) + const val = node.getValue() + const existingNodeWithValue = iteratedValues.get(val) if (existingNodeWithValue) { node.circularOfId = existingNodeWithValue.id return false } - iteratedValues.set(node.value, node) + iteratedValues.set(val, node) } return true }, @@ -115,13 +119,18 @@ describe('TreeView', () => { ['e', { f: [9, 8, 7] }] ]) } + let map: any const results = render(TreeView, { data, recursionOpts: { maxDepth: 4 + }, + onUpdate: v => { + map = v } }) window.HTMLElement.prototype.scrollIntoView = vi.fn() + await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(0, 0, 'treemap')) expect(results.container.querySelectorAll('li').length).toEqual(2) @@ -155,6 +164,9 @@ describe('TreeView', () => { maxDepth: 5, stopCircularRecursion: true, shouldExpandNode: () => false + }, + onUpdate: v => { + map = v } }) @@ -164,7 +176,10 @@ describe('TreeView', () => { await clickByText(results.container, 'b:') expect(results.container.querySelectorAll('li').length).toEqual(6) + await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(0, 1, 'treemap')) await clickByText(results.container, '[map entry 1]:') + await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(0, 2, 'treemap')) + expect(results.container.querySelectorAll('li').length).toEqual(9) await clickByText(results.container, '[value]:') diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-0-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-0-treemap.json new file mode 100644 index 0000000..63a6926 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-0-treemap.json @@ -0,0 +1,247 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": true, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": true, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-1-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-1-treemap.json new file mode 100644 index 0000000..9c62476 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-1-treemap.json @@ -0,0 +1,580 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,2]": { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0,0]": { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,0,1]": { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,1,0]": { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,1,1]": { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,2,0]": { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,2,1]": { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-2-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-2-treemap.json new file mode 100644 index 0000000..6cddc11 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/1-2-treemap.json @@ -0,0 +1,644 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,2]": { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0,0]": { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,0,1]": { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,1,0]": { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,1,1]": { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,2,0]": { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,2,1]": { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,1,1,0]": { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts index 5561a14..986ea53 100644 --- a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts @@ -17,20 +17,6 @@ export const createTreeStore = (propsStore: PropsStore) => { treeMap, defaultRootNode, - init( - newTree: TreeNode | null, - newTreeMap: Record, - iterated: Map - ) { - if (newTree) { - tree.set(newTree) - } else { - tree.set(defaultRootNode) - } - treeMap.set(newTreeMap) - iteratedValues.set(iterated) - }, - update(data: unknown, recursionOpts: TreeRecursionOpts, recomputeExpandNode: boolean) { const oldTreeMap = get(treeMap) const recomputed = recomputeTree(data, oldTreeMap, recursionOpts, recomputeExpandNode) @@ -41,14 +27,11 @@ export const createTreeStore = (propsStore: PropsStore) => { } treeMap.set(recomputed.treeMap) iteratedValues.set(recomputed.iteratedValues) + get(propsStore.props).onUpdate?.(recomputed.treeMap) // console.log('recomputed', recomputed.treeMap) // treeStore.init(tree, treeMap, iteratedValues) }, - getNode(id: string) { - return get(treeMap)[id] - }, - toggleCollapse(id: string) { const node = get(treeMap)[id] if (!node) { @@ -56,15 +39,18 @@ export const createTreeStore = (propsStore: PropsStore) => { return } const updatedNode = { ...node, collapsed: !node.collapsed } - treeMap.update(m => ({ ...m, [node.id]: updatedNode })) + const newMap = { ...get(treeMap), [node.id]: updatedNode } + treeMap.set(newMap) const recursionOpts = get(propsStore.recursionOpts) if (recursionOpts) { this.expandNodeChildren(updatedNode, recursionOpts) + } else { + get(propsStore.props).onUpdate?.(newMap) } }, expandNodeChildren(node: TreeNode, recursionOpts: TreeRecursionOpts) { - const parent = this.getNode(node?.parentId || '') || null + const parent = get(treeMap)[node?.parentId || ''] || null if (!parent) { // Only root node has no parent and it should not be expandable throw Error('No parent in expandNodeChildren for node: ' + node) @@ -75,7 +61,7 @@ export const createTreeStore = (propsStore: PropsStore) => { const nodeWithUpdatedChildren = recurseObjectProperties( node.index, node.key, - node.value, + node.getValue(), node.depth, !node.collapsed, // Ensure that when uncollapsed the node's children are always recursed parent, @@ -93,6 +79,7 @@ export const createTreeStore = (propsStore: PropsStore) => { newTreeMap[parent.id] = parent treeMap.set(newTreeMap) iteratedValues.set(previouslyIterated) + get(propsStore.props).onUpdate?.(newTreeMap) }, expandAllNodesToNode(id: string) { @@ -109,6 +96,7 @@ export const createTreeStore = (propsStore: PropsStore) => { const updated = { ...get(treeMap) } recurseNodeUpwards(updated, updated[id]) treeMap.set(updated) + get(propsStore.props).onUpdate?.(updated) } } } diff --git a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts index 5b2189b..3f8ff87 100644 --- a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts +++ b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts @@ -12,7 +12,7 @@ export function createNode( id: `[${path.join(',')}]`, index, key, - value, + getValue: () => value, depth, collapsed: true, type: getValueType(value), @@ -114,12 +114,12 @@ function shouldRecurseChildren( } else if (opts.isCircularNode) { return opts.isCircularNode(node, iteratedValues) } else if (node.type === 'object' || node.type === 'array') { - const existingNodeWithValue = iteratedValues.get(node.value) + const existingNodeWithValue = iteratedValues.get(node.getValue()) if (existingNodeWithValue && node.id !== existingNodeWithValue.id) { node.circularOfId = existingNodeWithValue.id return false } - iteratedValues.set(node.value, node) + iteratedValues.set(node.getValue(), node) } return true } diff --git a/packages/svelte-tree-view/src/lib/types.ts b/packages/svelte-tree-view/src/lib/types.ts index 0408b32..0b122fd 100644 --- a/packages/svelte-tree-view/src/lib/types.ts +++ b/packages/svelte-tree-view/src/lib/types.ts @@ -33,7 +33,7 @@ export interface TreeNode { /** * The value mapped to this key */ - value: T + getValue: () => T depth: number collapsed: boolean type: ValueType @@ -179,6 +179,7 @@ export interface TreeViewProps { showLogButton?: boolean showCopyButton?: boolean recursionOpts?: TreeRecursionOpts + onUpdate?: (newMap: Record) => void /** * For custom formatting of the value string. Returning undefined will pass the value to the default formatter * @param val From ddc2012f6efdc1f18f1d1b08e4d173b01f1b3859 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Sun, 13 Jul 2025 22:59:07 +0300 Subject: [PATCH 04/13] reuse old node in createNode --- .../__tests__/__snapshots__/0-0-treemap.json | 247 +++++++ .../__tests__/__snapshots__/0-1-treemap.json | 580 ++++++++++++++++ .../__tests__/__snapshots__/0-2-treemap.json | 644 ++++++++++++++++++ .../src/lib/stores/tree.svelte.ts | 8 +- .../src/lib/tree-utils.svelte.ts | 24 +- 5 files changed, 1493 insertions(+), 10 deletions(-) create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-0-treemap.json create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json create mode 100644 packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-0-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-0-treemap.json new file mode 100644 index 0000000..63a6926 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-0-treemap.json @@ -0,0 +1,247 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": true, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": true, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json new file mode 100644 index 0000000..9c62476 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json @@ -0,0 +1,580 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,2]": { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0,0]": { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,0,1]": { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,1,0]": { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,1,1]": { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,2,0]": { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,2,1]": { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json new file mode 100644 index 0000000..6cddc11 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json @@ -0,0 +1,644 @@ +{ + "[]": { + "id": "[]", + "index": -1, + "key": "root", + "depth": 0, + "collapsed": false, + "type": "object", + "path": [], + "parentId": null, + "circularOfId": null, + "children": [ + { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + } + ] + }, + "[0]": { + "id": "[0]", + "index": 0, + "key": "a", + "depth": 1, + "collapsed": true, + "type": "array", + "path": [0], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[0,0]": { + "id": "[0,0]", + "index": 0, + "key": "0", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 0], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,1]": { + "id": "[0,1]", + "index": 1, + "key": "1", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 1], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[0,2]": { + "id": "[0,2]", + "index": 2, + "key": "2", + "depth": 2, + "collapsed": true, + "type": "number", + "path": [0, 2], + "parentId": "[0]", + "circularOfId": null, + "children": [] + }, + "[1]": { + "id": "[1]", + "index": 1, + "key": "b", + "depth": 1, + "collapsed": false, + "type": "map", + "path": [1], + "parentId": "[]", + "circularOfId": null, + "children": [ + { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,0]": { + "id": "[1,0]", + "index": 0, + "key": "[map entry 0]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 0], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,1]": { + "id": "[1,1]", + "index": 1, + "key": "[map entry 1]", + "depth": 2, + "collapsed": false, + "type": "object", + "path": [1, 1], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + } + ] + }, + "[1,2]": { + "id": "[1,2]", + "index": 2, + "key": "[map entry 2]", + "depth": 2, + "collapsed": true, + "type": "object", + "path": [1, 2], + "parentId": "[1]", + "circularOfId": null, + "children": [ + { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,0,0]": { + "id": "[1,0,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 0, 0], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,0,1]": { + "id": "[1,0,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 0, 1], + "parentId": "[1,0]", + "circularOfId": null, + "children": [] + }, + "[1,1,0]": { + "id": "[1,1,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 1, 0], + "parentId": "[1,1]", + "circularOfId": null, + "children": [] + }, + "[1,1,1]": { + "id": "[1,1,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 1, 1], + "parentId": "[1,1]", + "circularOfId": null, + "children": [ + { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } + ] + }, + "[1,2,0]": { + "id": "[1,2,0]", + "index": 0, + "key": "[key]", + "depth": 3, + "collapsed": true, + "type": "string", + "path": [1, 2, 0], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,2,1]": { + "id": "[1,2,1]", + "index": 1, + "key": "[value]", + "depth": 3, + "collapsed": true, + "type": "object", + "path": [1, 2, 1], + "parentId": "[1,2]", + "circularOfId": null, + "children": [] + }, + "[1,1,1,0]": { + "id": "[1,1,1,0]", + "index": 0, + "key": "f", + "depth": 4, + "collapsed": true, + "type": "array", + "path": [1, 1, 1, 0], + "parentId": "[1,1,1]", + "circularOfId": null, + "children": [] + } +} diff --git a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts index 986ea53..5ecd2cb 100644 --- a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts @@ -7,7 +7,7 @@ import type { PropsStore } from './props' export type TreeStore = ReturnType export const createTreeStore = (propsStore: PropsStore) => { - const defaultRootNode = createNode(0, 'root', [], 0, null) + const [defaultRootNode] = createNode(0, 'root', [], 0, null, {}) const tree = writable(defaultRootNode) const treeMap = writable>({}) const iteratedValues = writable>(new Map()) @@ -50,13 +50,13 @@ export const createTreeStore = (propsStore: PropsStore) => { }, expandNodeChildren(node: TreeNode, recursionOpts: TreeRecursionOpts) { - const parent = get(treeMap)[node?.parentId || ''] || null + const oldTreeMap = get(treeMap) + const parent = oldTreeMap[node?.parentId || ''] || null if (!parent) { // Only root node has no parent and it should not be expandable throw Error('No parent in expandNodeChildren for node: ' + node) } - const newTreeMap: Record = { ...get(treeMap) } - const oldTreeMap = get(treeMap) + const newTreeMap = { ...oldTreeMap } const previouslyIterated = get(iteratedValues) const nodeWithUpdatedChildren = recurseObjectProperties( node.index, diff --git a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts index 3f8ff87..9010c1c 100644 --- a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts +++ b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts @@ -5,11 +5,23 @@ export function createNode( key: string, value: any, depth: number, - parent: TreeNode | null -): TreeNode { + parent: TreeNode | null, + treeMap: Record +): [TreeNode, TreeNode | undefined] { const path = parent ? [...parent.path, index] : [] - return { - id: `[${path.join(',')}]`, + const id = `[${path.join(',')}]` + const oldNode = treeMap[id] + if (oldNode) { + oldNode.key = key + oldNode.getValue = () => value + oldNode.depth = depth + oldNode.type = getValueType(value) + oldNode.circularOfId = null + oldNode.children = [] + return [oldNode, oldNode] + } + const node = { + id, index, key, getValue: () => value, @@ -21,6 +33,7 @@ export function createNode( circularOfId: null, children: [] } + return [node, undefined] } export function getValueType(value: any): ValueType { @@ -140,8 +153,7 @@ export function recurseObjectProperties( if (opts.omitKeys?.includes(key) || (opts.maxDepth && depth > opts.maxDepth)) { return null } - const node = createNode(index, key, value, depth, parent) - const oldNode = oldTreeMap[node.id] + const [node, oldNode] = createNode(index, key, value, depth, parent, oldTreeMap) if (ensureNotCollapsed) { // Used to ensure that either root node is always uncollapsed or when uncollapsing new nodes // with expandNodeChildren the node children are recursed (if applicable) with mapChildren From 5c58405daee1951b83eb6ab9d6ab4de01db057d3 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Sun, 13 Jul 2025 23:47:10 +0300 Subject: [PATCH 05/13] update --- packages/svelte-tree-view/src/lib/stores/tree.svelte.ts | 1 - packages/svelte-tree-view/src/lib/tree-utils.svelte.ts | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts index 5ecd2cb..aa5df2a 100644 --- a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts @@ -29,7 +29,6 @@ export const createTreeStore = (propsStore: PropsStore) => { iteratedValues.set(recomputed.iteratedValues) get(propsStore.props).onUpdate?.(recomputed.treeMap) // console.log('recomputed', recomputed.treeMap) - // treeStore.init(tree, treeMap, iteratedValues) }, toggleCollapse(id: string) { diff --git a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts index 9010c1c..4872927 100644 --- a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts +++ b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts @@ -33,7 +33,7 @@ export function createNode( circularOfId: null, children: [] } - return [node, undefined] + return [node, oldNode] } export function getValueType(value: any): ValueType { @@ -167,6 +167,9 @@ export function recurseObjectProperties( } treeMap[node.id] = node + // if (!oldNode) { + // oldTreeMap[node.id] = node + // } if (shouldRecurseChildren(node, parent, iteratedValues, opts)) { const mappedChildren = opts.mapChildren && opts.mapChildren(value, getValueType(value), node) From 1ce6b70b0ef5fa04bb2efa2758421166a32c4156 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Mon, 14 Jul 2025 01:02:00 +0300 Subject: [PATCH 06/13] wip --- .../src/lib/TreeView copy.svelte | 128 ++++++++++ .../src/lib/TreeViewNode copy.svelte | 68 ++++++ .../src/lib/__tests__/TreeView.spec.ts | 5 +- .../src/lib/stores/tree.svelte copy.ts | 102 ++++++++ .../src/lib/tree-utils.svelte copy.ts | 225 ++++++++++++++++++ 5 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 packages/svelte-tree-view/src/lib/TreeView copy.svelte create mode 100644 packages/svelte-tree-view/src/lib/TreeViewNode copy.svelte create mode 100644 packages/svelte-tree-view/src/lib/stores/tree.svelte copy.ts create mode 100644 packages/svelte-tree-view/src/lib/tree-utils.svelte copy.ts diff --git a/packages/svelte-tree-view/src/lib/TreeView copy.svelte b/packages/svelte-tree-view/src/lib/TreeView copy.svelte new file mode 100644 index 0000000..6a7badd --- /dev/null +++ b/packages/svelte-tree-view/src/lib/TreeView copy.svelte @@ -0,0 +1,128 @@ + + +{#snippet children()} + {#each treeChildren as child} + + {/each} +{/snippet} + +{#if rootNode} + {@render rootNode(children)} +{:else} +
      + {@render children()} +
    +{/if} + + diff --git a/packages/svelte-tree-view/src/lib/TreeViewNode copy.svelte b/packages/svelte-tree-view/src/lib/TreeViewNode copy.svelte new file mode 100644 index 0000000..7e7bbd1 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/TreeViewNode copy.svelte @@ -0,0 +1,68 @@ + + +{#if $propsObj.treeNode} + {@render $propsObj.treeNode(nodeProps)} +{:else} + +{/if} diff --git a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts index e8c3abd..53fece7 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts +++ b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts @@ -111,7 +111,7 @@ describe('TreeView', () => { expect(results.container).toMatchSnapshot() }) - it('should respect maxDepth and collapse nodes correctly', async () => { + it.only('should respect maxDepth and collapse nodes correctly', async () => { const data = { a: [1, 2, 3], b: new Map([ @@ -130,14 +130,15 @@ describe('TreeView', () => { } }) window.HTMLElement.prototype.scrollIntoView = vi.fn() - await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(0, 0, 'treemap')) expect(results.container.querySelectorAll('li').length).toEqual(2) await clickByText(results.container, 'b:') expect(results.container.querySelectorAll('li').length).toEqual(5) + await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(50, 0, 'treemap')) await clickByText(results.container, '[map entry 1]:') + await expect(JSON.stringify(map)).toMatchFileSnapshot(snapPath(50, 1, 'treemap')) expect(results.container.querySelectorAll('li').length).toEqual(8) await clickByText(results.container, '[value]:') diff --git a/packages/svelte-tree-view/src/lib/stores/tree.svelte copy.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte copy.ts new file mode 100644 index 0000000..a9b3674 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte copy.ts @@ -0,0 +1,102 @@ +import { get, writable } from 'svelte/store' + +import { createNode, recomputeTree, recurseObjectProperties } from '../tree-utils.svelte' +import type { TreeNode, TreeRecursionOpts } from '../types' +import type { PropsStore } from './props' + +export type TreeStore = ReturnType + +export const createTreeStore = (propsStore: PropsStore) => { + const [defaultRootNode] = createNode(0, 'root', [], 0, null, {}) + const tree = writable(defaultRootNode) + const treeMap = $state>({}) + const iteratedValues = writable>(new Map()) + + return { + tree, + treeMap, + defaultRootNode, + + update(data: unknown, recursionOpts: TreeRecursionOpts, recomputeExpandNode: boolean) { + const recomputed = recomputeTree(data, treeMap, recursionOpts, recomputeExpandNode) + if (recomputed.tree) { + tree.set(recomputed.tree) + } else { + tree.set(defaultRootNode) + } + // treeMap = recomputed.treeMap + // treeMap.set(recomputed.treeMap) + iteratedValues.set(recomputed.iteratedValues) + get(propsStore.props).onUpdate?.(treeMap) + // console.log('recomputed', $state.snapshot(recomputed.treeMap)) + }, + + toggleCollapse(id: string) { + const node = treeMap[id] + if (!node) { + console.warn(`Attempted to collapse non-existent node: ${id}`) + return + } + node.collapsed = !node.collapsed + // const updatedNode = { ...node, collapsed: !node.collapsed } + // const newMap = { ...treeMap, [node.id]: updatedNode } + // treeMap.set(newMap) + const recursionOpts = get(propsStore.recursionOpts) + if (recursionOpts) { + this.expandNodeChildren(node, recursionOpts) + } else { + get(propsStore.props).onUpdate?.(treeMap) + } + }, + + expandNodeChildren(node: TreeNode, recursionOpts: TreeRecursionOpts) { + const oldTreeMap = treeMap + const parent = oldTreeMap[node?.parentId || ''] || null + if (!parent) { + // Only root node has no parent and it should not be expandable + throw Error('No parent in expandNodeChildren for node: ' + node) + } + const newTreeMap = { ...oldTreeMap } + const previouslyIterated = get(iteratedValues) + const nodeWithUpdatedChildren = recurseObjectProperties( + node.index, + node.key, + node.getValue(), + node.depth, + !node.collapsed, // Ensure that when uncollapsed the node's children are always recursed + parent, + newTreeMap, + new Set(), + previouslyIterated, + false, // Never recompute shouldExpandNode since it may override the collapsing of this node + recursionOpts + ) + if (!nodeWithUpdatedChildren) return + parent.children = parent.children.map(c => + c.id === nodeWithUpdatedChildren.id ? nodeWithUpdatedChildren : c + ) + newTreeMap[nodeWithUpdatedChildren.id] = nodeWithUpdatedChildren + newTreeMap[parent.id] = parent + // treeMap.set(newTreeMap) + iteratedValues.set(previouslyIterated) + get(propsStore.props).onUpdate?.(newTreeMap) + }, + + expandAllNodesToNode(id: string) { + function recurseNodeUpwards( + updated: Record, + node?: TreeNode | null + ) { + if (!node) return + updated[node.id] = { ...node, collapsed: false } + if (node.parentId) { + recurseNodeUpwards(updated, updated[node.parentId]) + } + } + const updated = treeMap + recurseNodeUpwards(updated, updated[id]) + // treeMap.set(updated) + get(propsStore.props).onUpdate?.(updated) + } + } +} diff --git a/packages/svelte-tree-view/src/lib/tree-utils.svelte copy.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte copy.ts new file mode 100644 index 0000000..0066b66 --- /dev/null +++ b/packages/svelte-tree-view/src/lib/tree-utils.svelte copy.ts @@ -0,0 +1,225 @@ +import type { TreeNode, TreeRecursionOpts, ValueType } from './types' + +export function createNode( + index: number, + key: string, + value: any, + depth: number, + parent: TreeNode | null, + treeMap: Record +): [TreeNode, TreeNode | undefined] { + const path = parent ? [...parent.path, index] : [] + const id = `[${path.join(',')}]` + const oldNode = treeMap[id] + // if (oldNode) { + // oldNode.key = key + // oldNode.getValue = () => value + // oldNode.depth = depth + // oldNode.type = getValueType(value) + // oldNode.circularOfId = null + // // oldNode.children = [] + // return [oldNode, oldNode] + // } + const node = $state({ + id, + index, + key, + getValue: () => value, + depth, + collapsed: true, + type: getValueType(value), + path, + parentId: parent ? parent.id : null, + circularOfId: null, + children: [] + }) + return [node, oldNode] +} + +export function getValueType(value: any): ValueType { + if (Array.isArray(value)) { + return 'array' + } else if (value instanceof Map) { + return 'map' + } else if (value instanceof Set) { + return 'set' + } else if (value instanceof Date) { + return 'date' + } else if (value === null) { + return 'null' + } else { + return typeof value + } +} + +// From redux-dev-tools +// case 'Object': +// case 'Error': +// case 'Array': +// case 'Iterable': +// case 'Map': +// case 'Set': +// case 'MapEntry': +// case 'Number': +// return undefined; +// case 'String': +// return raw => `"${raw}"`; +// case 'Boolean': +// return raw => (raw ? 'true' : 'false'); +// case 'Date': +// return raw => raw.toISOString(); +// case 'Null': +// return () => 'null'; +// case 'Undefined': +// return () => 'undefined'; +// case 'Function': +// case 'Symbol': +// export function objType(obj: any) { +// const type = Object.prototype.toString.call(obj).slice(8, -1) +// if (type === 'Object') { +// if (typeof obj[Symbol.iterator] === 'function') { +// return 'Iterable' +// } +// return obj.constructor.name +// } +// return type +// } + +function getChildren(value: any, type: ValueType): [string, any][] { + switch (type) { + case 'array': + return value.map((v: any, i: number) => [i.toString(), v]) + case 'map': + // eslint-disable-next-line no-case-declarations + const entries: [any, any][] = Array.from(value.entries()) + return entries.map(([key, value], i: number) => [ + `[map entry ${i}]`, + { + '[key]': key, + '[value]': value + } + ]) + case 'set': + return Array.from(value.values()).map((v: any, i: number) => [`[set entry ${i}]`, v]) + case 'object': + return Object.entries(value) + default: + return [] + } +} + +function shouldRecurseChildren( + node: TreeNode, + parent: TreeNode | null, + iteratedValues: Map, + opts: TreeRecursionOpts +) { + if (!parent) { + // The root node's children should always be recursed + return true + } else if (node.collapsed && parent?.collapsed) { + // If the node's parent is uncollapsed the node's children should still be recursed + // in order to compute its value properly eg "{} 4 keys" and to place clickable arrow caret. + // Only when the node is completely hidden it should not be recursed + return false + } else if (!opts.stopCircularRecursion) { + return true + } else if (opts.isCircularNode) { + return opts.isCircularNode(node, iteratedValues) + } else if (node.type === 'object' || node.type === 'array') { + const existingNodeWithValue = iteratedValues.get(node.getValue()) + if (existingNodeWithValue && node.id !== existingNodeWithValue.id) { + node.circularOfId = existingNodeWithValue.id + return false + } + iteratedValues.set(node.getValue(), node) + } + return true +} + +export function recurseObjectProperties( + index: number, + key: string, + value: any, + depth: number, + ensureNotCollapsed: boolean, + parent: TreeNode | null, + treeMap: Record, + oldIds: Set, + iteratedValues: Map, + recomputeExpandNode: boolean, + opts: TreeRecursionOpts +): TreeNode | null { + if (opts.omitKeys?.includes(key) || (opts.maxDepth && depth > opts.maxDepth)) { + return null + } + const [node, oldNode] = createNode(index, key, value, depth, parent, treeMap) + if (ensureNotCollapsed) { + // Used to ensure that either root node is always uncollapsed or when uncollapsing new nodes + // with expandNodeChildren the node children are recursed (if applicable) with mapChildren + node.collapsed = false + } else if (oldNode && !recomputeExpandNode) { + // Maintain the same expanded/collapsed toggle for a node in this path/id + // EXCEPT when the shouldExpandNode prop is changed... + node.collapsed = oldNode.collapsed + } else if (opts.shouldExpandNode) { + node.collapsed = !opts.shouldExpandNode(node) + } + + // treeMap[node.id] = node + // if (!oldNode) { + // } + treeMap[node.id] = node + oldIds.delete(node.id) + + if (shouldRecurseChildren(node, parent, iteratedValues, opts)) { + const mappedChildren = opts.mapChildren && opts.mapChildren(value, getValueType(value), node) + const children = mappedChildren ?? getChildren(value, getValueType(value)) + node.children = children + .map(([key, val], idx) => + recurseObjectProperties( + idx, + key, + val, + depth + 1, + false, + node, + treeMap, + oldIds, + iteratedValues, + recomputeExpandNode, + opts + ) + ) + .filter(n => n !== null) as TreeNode[] + } + + return node +} + +export function recomputeTree( + data: unknown, + oldTreeMap: Record, + recursionOpts: TreeRecursionOpts, + recomputeExpandNode: boolean +) { + const oldIds = new Set(Object.keys(oldTreeMap)) + const iteratedValues = new Map() + const newTree = recurseObjectProperties( + -1, + 'root', + data, + 0, + true, + null, + oldTreeMap, + oldIds, + iteratedValues, + recomputeExpandNode, + recursionOpts + ) + for (const id of oldIds) { + delete oldTreeMap[id] + } + return { tree: newTree, iteratedValues } +} From dd3fb61f9891b1c22ef41cce6220ac4dc0b0144c Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Thu, 17 Jul 2025 21:31:40 +0300 Subject: [PATCH 07/13] change children to list of ids, fix recurOpts in site --- packages/site/src/components/DiffValue.svelte | 4 +- .../site/src/components/TailwindNode.svelte | 4 +- packages/site/src/lib/parser.ts | 5 +- packages/site/src/lib/store.ts | 68 +++++++++++++------ .../src/lib/DefaultNode.svelte | 8 +-- .../svelte-tree-view/src/lib/TreeView.svelte | 4 +- .../src/lib/stores/tree.svelte.ts | 3 - .../src/lib/tree-utils.svelte.ts | 38 ++++++----- packages/svelte-tree-view/src/lib/types.ts | 2 +- 9 files changed, 83 insertions(+), 53 deletions(-) diff --git a/packages/site/src/components/DiffValue.svelte b/packages/site/src/components/DiffValue.svelte index 5a9c0db..9d4d87e 100644 --- a/packages/site/src/components/DiffValue.svelte +++ b/packages/site/src/components/DiffValue.svelte @@ -110,8 +110,8 @@ {#if descend}
    • - {#each node.children as child} - + {#each node.children as id} + {/each}
  • diff --git a/packages/site/src/components/TailwindNode.svelte b/packages/site/src/components/TailwindNode.svelte index fc6b77a..dafae89 100644 --- a/packages/site/src/components/TailwindNode.svelte +++ b/packages/site/src/components/TailwindNode.svelte @@ -191,8 +191,8 @@ {#if descend}
    - {#each node.children as child} - + {#each node.children as id} + {/each}
    {/if} diff --git a/packages/site/src/lib/parser.ts b/packages/site/src/lib/parser.ts index 8e8e6e9..859c0c4 100644 --- a/packages/site/src/lib/parser.ts +++ b/packages/site/src/lib/parser.ts @@ -13,13 +13,16 @@ export const parseRecursionOpts = ( ): Record | undefined => { try { const parsed = new Function(`return ${str}`)() + console.log('parsed', parsed) if (parsed && typeof parsed === 'object') { parsed.isCircularNode(testNode, new Map()) parsed.shouldExpandNode(testNode) parsed.mapChildren([], 'array', testNode) return parsed } - } catch (e) {} + } catch (e) { + console.log('e', e) + } return undefined } diff --git a/packages/site/src/lib/store.ts b/packages/site/src/lib/store.ts index eff34fa..8702c7d 100644 --- a/packages/site/src/lib/store.ts +++ b/packages/site/src/lib/store.ts @@ -1,5 +1,5 @@ import { writable } from 'svelte/store' -import type { TreeRecursionOpts } from 'svelte-tree-view' +import type { TreeNode, TreeRecursionOpts } from 'svelte-tree-view' import * as parser from './parser' @@ -31,56 +31,80 @@ export interface FormState { theme: string } -export const DEFAULT_STATE: FormState = { - data: '', - selectedData: null, - leftIndent: '0.875em', - lineHeight: '1.1', - fontFamily: 'Helvetica Neue', - fontSize: '13px', - keyMarginRight: '0.5em', - showLogButton: false, - showCopyButton: false, - recursionOpts: `{ +const DEFAULT_RECUR_OPTS: TreeRecursionOpts = { maxDepth: 16, omitKeys: [], stopCircularRecursion: false, isCircularNode(node, iteratedValues) { if (node.type === 'object' || node.type === 'array') { - const existingNodeWithValue = iteratedValues.get(node.value) + const existingNodeWithValue = iteratedValues.get(node.getValue()) if (existingNodeWithValue && node.id !== existingNodeWithValue.id) { node.circularOfId = existingNodeWithValue.id return false } - iteratedValues.set(node.value, node) + iteratedValues.set(node.getValue(), node) } return true }, - shouldExpandNode: (node) => { + shouldExpandNode(node) { return true }, mapChildren(value, type, parent) { switch (type) { case 'array': - return value.map((v, i) => [i.toString(), v]) + return (value as Array).map((v, i) => [i.toString(), v]) case 'map': - const entries = Array.from(value.entries()) + const entries = Array.from((value as Map).entries()) return entries.map(([key, value], i) => [ - \`[map entry \${i}]\`, + `[map entry ${i}]`, { '[key]': key, '[value]': value } ]) case 'set': - return Array.from(value.values()).map((v, i) => [\`[set entry \${i}]\`, v]) + return Array.from(value.values()).map((v, i) => [`[set entry ${i}]`, v]) case 'object': return Object.entries(value) default: return [] } } -}`, +} + +const recurOptsToString = () => + Object.entries(DEFAULT_RECUR_OPTS) + .reduce((acc, [key, val], idx) => { + if (idx === 0) { + acc.push('{') + } + let str + if (Array.isArray(val)) { + str = ` ${key}: [${val}],` + } else if (typeof val === 'function') { + str = ` ${val},` + } else { + str = ` ${key}: ${val},` + } + acc.push(str) + if (key === 'mapChildren') { + acc.push('}') + } + return acc + }, []) + .join('\n') + +export const DEFAULT_STATE: FormState = { + data: '', + selectedData: null, + leftIndent: '0.875em', + lineHeight: '1.1', + fontFamily: 'Helvetica Neue', + fontSize: '13px', + keyMarginRight: '0.5em', + showLogButton: false, + showCopyButton: false, + recursionOpts: recurOptsToString(), valueFormatter: `(val, node) => { switch (node.type) { case 'array': @@ -122,11 +146,11 @@ export const DEFAULT_STATE: FormState = { base0F: '#D6724C' }` } -const testNode = { +const testNode: TreeNode = { id: '[1]', index: 0, key: `test`, - value: [1, 2, 3], + getValue: () => [1, 2, 3], depth: 0, collapsed: false, type: 'array', diff --git a/packages/svelte-tree-view/src/lib/DefaultNode.svelte b/packages/svelte-tree-view/src/lib/DefaultNode.svelte index 89caa7e..1e1db5b 100644 --- a/packages/svelte-tree-view/src/lib/DefaultNode.svelte +++ b/packages/svelte-tree-view/src/lib/DefaultNode.svelte @@ -10,11 +10,11 @@ handleToggleCollapse }: NodeProps = $props() const { - propsStore: { props: propsObj } + propsStore: { props: propsObj, formatValue } } = getTreeContext() let hasChildren = $derived(node.children.length > 0) let descend = $derived(!node.collapsed && hasChildren) - let valueStr = $derived($propsObj.valueFormatter?.(node.getValue(), node)) + let valueStr = $derived(formatValue(node.getValue(), node))
  • @@ -54,8 +54,8 @@ {#if descend}
    • - {#each node.children as child} - + {#each node.children as id} + {/each}
  • diff --git a/packages/svelte-tree-view/src/lib/TreeView.svelte b/packages/svelte-tree-view/src/lib/TreeView.svelte index c2bae51..e26012c 100644 --- a/packages/svelte-tree-view/src/lib/TreeView.svelte +++ b/packages/svelte-tree-view/src/lib/TreeView.svelte @@ -95,8 +95,8 @@ {#snippet children()} - {#each $tree.children as child} - + {#each $tree.children as id} + {/each} {/snippet} diff --git a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts index aa5df2a..229c2f8 100644 --- a/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts +++ b/packages/svelte-tree-view/src/lib/stores/tree.svelte.ts @@ -71,9 +71,6 @@ export const createTreeStore = (propsStore: PropsStore) => { recursionOpts ) if (!nodeWithUpdatedChildren) return - parent.children = parent.children.map(c => - c.id === nodeWithUpdatedChildren.id ? nodeWithUpdatedChildren : c - ) newTreeMap[nodeWithUpdatedChildren.id] = nodeWithUpdatedChildren newTreeMap[parent.id] = parent treeMap.set(newTreeMap) diff --git a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts index 4872927..c86c61c 100644 --- a/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts +++ b/packages/svelte-tree-view/src/lib/tree-utils.svelte.ts @@ -174,23 +174,29 @@ export function recurseObjectProperties( if (shouldRecurseChildren(node, parent, iteratedValues, opts)) { const mappedChildren = opts.mapChildren && opts.mapChildren(value, getValueType(value), node) const children = mappedChildren ?? getChildren(value, getValueType(value)) - node.children = children - .map(([key, val], idx) => - recurseObjectProperties( - idx, - key, - val, - depth + 1, - false, - node, - treeMap, - oldTreeMap, - iteratedValues, - recomputeExpandNode, - opts - ) + const ids: string[] = [] + for (let i = 0; i < children.length; i += 1) { + const [key, val] = children[i] + const child = recurseObjectProperties( + i, + key, + val, + depth + 1, + false, + node, + treeMap, + oldTreeMap, + iteratedValues, + recomputeExpandNode, + opts ) - .filter(n => n !== null) as TreeNode[] + if (child) { + ids.push(child.id) + } else { + console.error(`recurseObjectProperties produced unexpected null TreeNode for parent`, node) + } + } + node.children = ids } return node diff --git a/packages/svelte-tree-view/src/lib/types.ts b/packages/svelte-tree-view/src/lib/types.ts index 0b122fd..ef9dfba 100644 --- a/packages/svelte-tree-view/src/lib/types.ts +++ b/packages/svelte-tree-view/src/lib/types.ts @@ -43,7 +43,7 @@ export interface TreeNode { * Circularity is checked by object identity to prevent recursing the same values again */ circularOfId: string | null - children: TreeNode[] + children: string[] } export interface Base16Theme { From 82e28a5ae453ebc7113a674914d50ea87cf9a608 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Thu, 17 Jul 2025 21:41:11 +0300 Subject: [PATCH 08/13] fix parseValueFormatter --- packages/site/src/lib/parser.ts | 6 +++-- packages/site/src/lib/store.ts | 42 +++++++++++++++++---------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/packages/site/src/lib/parser.ts b/packages/site/src/lib/parser.ts index 859c0c4..1d0ce3b 100644 --- a/packages/site/src/lib/parser.ts +++ b/packages/site/src/lib/parser.ts @@ -33,10 +33,12 @@ export const parseValueFormatter = ( try { const parsed = new Function(`return ${str}`)() if (typeof parsed === 'function') { - parsed(testNode.value, testNode) + parsed(testNode.getValue(), testNode) return parsed } - } catch (e) {} + } catch (e) { + console.log('e', e) + } return undefined } diff --git a/packages/site/src/lib/store.ts b/packages/site/src/lib/store.ts index 8702c7d..348684f 100644 --- a/packages/site/src/lib/store.ts +++ b/packages/site/src/lib/store.ts @@ -1,5 +1,5 @@ import { writable } from 'svelte/store' -import type { TreeNode, TreeRecursionOpts } from 'svelte-tree-view' +import type { TreeNode, TreeRecursionOpts, TreeViewProps } from 'svelte-tree-view' import * as parser from './parser' @@ -94,38 +94,40 @@ const recurOptsToString = () => }, []) .join('\n') -export const DEFAULT_STATE: FormState = { - data: '', - selectedData: null, - leftIndent: '0.875em', - lineHeight: '1.1', - fontFamily: 'Helvetica Neue', - fontSize: '13px', - keyMarginRight: '0.5em', - showLogButton: false, - showCopyButton: false, - recursionOpts: recurOptsToString(), - valueFormatter: `(val, node) => { +const valueFormatter: TreeViewProps['valueFormatter'] = (val, node) => { switch (node.type) { case 'array': - return \u0060\${node.circularOfId ? 'circular' : ''} [] \${val.length} items\u0060 + return `${node.circularOfId ? 'circular' : ''} [] ${val.length} items` case 'object': - return \u0060\${node.circularOfId ? 'circular' : ''} {} \${Object.keys(val).length} keys\u0060 + return `${node.circularOfId ? 'circular' : ''} {} ${Object.keys(val).length} keys` case 'map': case 'set': - return \u0060\${node.circularOfId ? 'circular' : ''} () \${val.size} entries\u0060 + return `${node.circularOfId ? 'circular' : ''} () ${val.size} entries` case 'date': - return \u0060\${val.toISOString()}\u0060 + return `${val.toISOString()}` case 'string': - return \u0060"\${val}"\u0060 + return `"${val}"` case 'boolean': return val ? 'true' : 'false' case 'symbol': return String(val) default: - return val + return node.type } -}`, +} + +export const DEFAULT_STATE: FormState = { + data: '', + selectedData: null, + leftIndent: '0.875em', + lineHeight: '1.1', + fontFamily: 'Helvetica Neue', + fontSize: '13px', + keyMarginRight: '0.5em', + showLogButton: false, + showCopyButton: false, + recursionOpts: recurOptsToString(), + valueFormatter: valueFormatter.toString(), theme: `{ scheme: 'monokai', base00: '#363755', // main blue bg From e2c42f45a717f9408c70c75e7cd2e14005d476b0 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Thu, 17 Jul 2025 21:47:40 +0300 Subject: [PATCH 09/13] update snapshots --- .../src/lib/__tests__/TreeView.spec.ts | 2 +- .../__tests__/__snapshots__/0-1-treemap.json | 410 +-------------- .../__tests__/__snapshots__/0-2-treemap.json | 464 +---------------- .../__snapshots__/TreeView.spec.ts.snap | 486 +++++++++--------- 4 files changed, 260 insertions(+), 1102 deletions(-) diff --git a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts index 53fece7..b5a56fc 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts +++ b/packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts @@ -111,7 +111,7 @@ describe('TreeView', () => { expect(results.container).toMatchSnapshot() }) - it.only('should respect maxDepth and collapse nodes correctly', async () => { + it('should respect maxDepth and collapse nodes correctly', async () => { const data = { a: [1, 2, 3], b: new Map([ diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json index 9c62476..c68df72 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-1-treemap.json @@ -9,181 +9,7 @@ "path": [], "parentId": null, "circularOfId": null, - "children": [ - { - "id": "[0]", - "index": 0, - "key": "a", - "depth": 1, - "collapsed": true, - "type": "array", - "path": [0], - "parentId": "[]", - "circularOfId": null, - "children": [ - { - "id": "[0,0]", - "index": 0, - "key": "0", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 0], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,1]", - "index": 1, - "key": "1", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 1], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,2]", - "index": 2, - "key": "2", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 2], - "parentId": "[0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1]", - "index": 1, - "key": "b", - "depth": 1, - "collapsed": false, - "type": "map", - "path": [1], - "parentId": "[]", - "circularOfId": null, - "children": [ - { - "id": "[1,0]", - "index": 0, - "key": "[map entry 0]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 0], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,1]", - "index": 1, - "key": "[map entry 1]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 1], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,2]", - "index": 2, - "key": "[map entry 2]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 2], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] - } - ] - } - ] + "children": ["[0]", "[1]"] }, "[0]": { "id": "[0]", @@ -195,44 +21,7 @@ "path": [0], "parentId": "[]", "circularOfId": null, - "children": [ - { - "id": "[0,0]", - "index": 0, - "key": "0", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 0], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,1]", - "index": 1, - "key": "1", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 1], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,2]", - "index": 2, - "key": "2", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 2], - "parentId": "[0]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[0,0]", "[0,1]", "[0,2]"] }, "[0,0]": { "id": "[0,0]", @@ -280,119 +69,7 @@ "path": [1], "parentId": "[]", "circularOfId": null, - "children": [ - { - "id": "[1,0]", - "index": 0, - "key": "[map entry 0]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 0], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,1]", - "index": 1, - "key": "[map entry 1]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 1], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,2]", - "index": 2, - "key": "[map entry 2]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 2], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] - } - ] + "children": ["[1,0]", "[1,1]", "[1,2]"] }, "[1,0]": { "id": "[1,0]", @@ -404,32 +81,7 @@ "path": [1, 0], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,0,0]", "[1,0,1]"] }, "[1,1]": { "id": "[1,1]", @@ -441,32 +93,7 @@ "path": [1, 1], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,1,0]", "[1,1,1]"] }, "[1,2]": { "id": "[1,2]", @@ -478,32 +105,7 @@ "path": [1, 2], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,2,0]", "[1,2,1]"] }, "[1,0,0]": { "id": "[1,0,0]", diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json index 6cddc11..827b429 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/0-2-treemap.json @@ -9,194 +9,7 @@ "path": [], "parentId": null, "circularOfId": null, - "children": [ - { - "id": "[0]", - "index": 0, - "key": "a", - "depth": 1, - "collapsed": true, - "type": "array", - "path": [0], - "parentId": "[]", - "circularOfId": null, - "children": [ - { - "id": "[0,0]", - "index": 0, - "key": "0", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 0], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,1]", - "index": 1, - "key": "1", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 1], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,2]", - "index": 2, - "key": "2", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 2], - "parentId": "[0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1]", - "index": 1, - "key": "b", - "depth": 1, - "collapsed": false, - "type": "map", - "path": [1], - "parentId": "[]", - "circularOfId": null, - "children": [ - { - "id": "[1,0]", - "index": 0, - "key": "[map entry 0]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 0], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,1]", - "index": 1, - "key": "[map entry 1]", - "depth": 2, - "collapsed": false, - "type": "object", - "path": [1, 1], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,1,0]", - "index": 0, - "key": "f", - "depth": 4, - "collapsed": true, - "type": "array", - "path": [1, 1, 1, 0], - "parentId": "[1,1,1]", - "circularOfId": null, - "children": [] - } - ] - } - ] - }, - { - "id": "[1,2]", - "index": 2, - "key": "[map entry 2]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 2], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] - } - ] - } - ] + "children": ["[0]", "[1]"] }, "[0]": { "id": "[0]", @@ -208,44 +21,7 @@ "path": [0], "parentId": "[]", "circularOfId": null, - "children": [ - { - "id": "[0,0]", - "index": 0, - "key": "0", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 0], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,1]", - "index": 1, - "key": "1", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 1], - "parentId": "[0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[0,2]", - "index": 2, - "key": "2", - "depth": 2, - "collapsed": true, - "type": "number", - "path": [0, 2], - "parentId": "[0]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[0,0]", "[0,1]", "[0,2]"] }, "[0,0]": { "id": "[0,0]", @@ -293,132 +69,7 @@ "path": [1], "parentId": "[]", "circularOfId": null, - "children": [ - { - "id": "[1,0]", - "index": 0, - "key": "[map entry 0]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 0], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] - }, - { - "id": "[1,1]", - "index": 1, - "key": "[map entry 1]", - "depth": 2, - "collapsed": false, - "type": "object", - "path": [1, 1], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,1,0]", - "index": 0, - "key": "f", - "depth": 4, - "collapsed": true, - "type": "array", - "path": [1, 1, 1, 0], - "parentId": "[1,1,1]", - "circularOfId": null, - "children": [] - } - ] - } - ] - }, - { - "id": "[1,2]", - "index": 2, - "key": "[map entry 2]", - "depth": 2, - "collapsed": true, - "type": "object", - "path": [1, 2], - "parentId": "[1]", - "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] - } - ] + "children": ["[1,0]", "[1,1]", "[1,2]"] }, "[1,0]": { "id": "[1,0]", @@ -430,32 +81,7 @@ "path": [1, 0], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,0,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 0, 0], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,0,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 0, 1], - "parentId": "[1,0]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,0,0]", "[1,0,1]"] }, "[1,1]": { "id": "[1,1]", @@ -467,45 +93,7 @@ "path": [1, 1], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,1,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 1, 0], - "parentId": "[1,1]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,1,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 1, 1], - "parentId": "[1,1]", - "circularOfId": null, - "children": [ - { - "id": "[1,1,1,0]", - "index": 0, - "key": "f", - "depth": 4, - "collapsed": true, - "type": "array", - "path": [1, 1, 1, 0], - "parentId": "[1,1,1]", - "circularOfId": null, - "children": [] - } - ] - } - ] + "children": ["[1,1,0]", "[1,1,1]"] }, "[1,2]": { "id": "[1,2]", @@ -517,32 +105,7 @@ "path": [1, 2], "parentId": "[1]", "circularOfId": null, - "children": [ - { - "id": "[1,2,0]", - "index": 0, - "key": "[key]", - "depth": 3, - "collapsed": true, - "type": "string", - "path": [1, 2, 0], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - }, - { - "id": "[1,2,1]", - "index": 1, - "key": "[value]", - "depth": 3, - "collapsed": true, - "type": "object", - "path": [1, 2, 1], - "parentId": "[1,2]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,2,0]", "[1,2,1]"] }, "[1,0,0]": { "id": "[1,0,0]", @@ -590,20 +153,7 @@ "path": [1, 1, 1], "parentId": "[1,1]", "circularOfId": null, - "children": [ - { - "id": "[1,1,1,0]", - "index": 0, - "key": "f", - "depth": 4, - "collapsed": true, - "type": "array", - "path": [1, 1, 1, 0], - "parentId": "[1,1,1]", - "circularOfId": null, - "children": [] - } - ] + "children": ["[1,1,1,0]"] }, "[1,2,0]": { "id": "[1,2,0]", diff --git a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/TreeView.spec.ts.snap b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/TreeView.spec.ts.snap index 55d226e..489d934 100644 --- a/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/TreeView.spec.ts.snap +++ b/packages/svelte-tree-view/src/lib/__tests__/__snapshots__/TreeView.spec.ts.snap @@ -31,7 +31,7 @@ exports[`TreeView > should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77c7d2ff4113f24ab5c"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "6e72c4da-c871-4aa1-aa44-1465920b90ae"
    should render 1`] = ` data-type="boolean" role="presentation" > - + false
    should render 1`] = ` data-type="string" role="presentation" > - + "$2,256.26"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "blue"
    should render 1`] = ` data-type="string" role="presentation" > - + "Branch Mcintosh"
    should render 1`] = ` data-type="string" role="presentation" > - + "male"
    should render 1`] = ` data-type="string" role="presentation" > - + "ENTOGROK"
    should render 1`] = ` data-type="string" role="presentation" > - + "branchmcintosh@entogrok.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (843) 489-2199"
    should render 1`] = ` data-type="string" role="presentation" > - + "196 Gerry Street, Sylvanite, Colorado, 3630"
    should render 1`] = ` data-type="string" role="presentation" > - + "Deserunt et laborum proident commodo. Irure mollit voluptate minim ut eiusmod qui deserunt culpa est nostrud. Ex duis aute ad eu. Ex in culpa culpa nulla non voluptate velit ex sint pariatur exercitation labore. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2018-07-23T07:01:58 -03:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "tempor"
    should render 1`] = ` data-type="string" role="presentation" > - + "laboris"
    should render 1`] = ` data-type="string" role="presentation" > - + "reprehenderit"
    should render 1`] = ` data-type="string" role="presentation" > - + "veniam"
    should render 1`] = ` data-type="string" role="presentation" > - + "exercitation"
    should render 1`] = ` data-type="string" role="presentation" > - + "velit"
    should render 1`] = ` data-type="string" role="presentation" > - + "voluptate"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Shanna Shannon"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Lindsey Reed"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Elinor Hendricks"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Branch Mcintosh! You have 1 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "strawberry"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77cdce2ef8b8b42aae8"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "8e33bdb8-d5e6-49fb-b229-ea24501c9ba3"
    should render 1`] = ` data-type="boolean" role="presentation" > - + true
    should render 1`] = ` data-type="string" role="presentation" > - + "$3,880.84"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "brown"
    should render 1`] = ` data-type="string" role="presentation" > - + "Amy Cannon"
    should render 1`] = ` data-type="string" role="presentation" > - + "female"
    should render 1`] = ` data-type="string" role="presentation" > - + "QUILITY"
    should render 1`] = ` data-type="string" role="presentation" > - + "amycannon@quility.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (842) 547-2756"
    should render 1`] = ` data-type="string" role="presentation" > - + "564 Dahlgreen Place, Sims, Washington, 9571"
    should render 1`] = ` data-type="string" role="presentation" > - + "In enim aliqua sint dolor laboris. Sunt veniam officia elit magna Lorem nulla occaecat culpa anim enim. Irure velit labore dolore incididunt. Aute aliquip elit ut duis anim elit esse dolor esse in nisi eiusmod tempor eiusmod. Proident eiusmod id nulla voluptate fugiat dolore do tempor dolor sunt. Adipisicing culpa quis elit enim aliquip. Tempor exercitation aute excepteur in. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2020-09-23T10:54:44 -03:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "commodo"
    should render 1`] = ` data-type="string" role="presentation" > - + "ex"
    should render 1`] = ` data-type="string" role="presentation" > - + "elit"
    should render 1`] = ` data-type="string" role="presentation" > - + "ad"
    should render 1`] = ` data-type="string" role="presentation" > - + "magna"
    should render 1`] = ` data-type="string" role="presentation" > - + "laboris"
    should render 1`] = ` data-type="string" role="presentation" > - + "veniam"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Barron Gonzales"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Therese Ramos"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Kirby Knight"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Amy Cannon! You have 9 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "apple"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77c36bbb0fbc6f1e367"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "75500a41-98ec-4050-854f-33dfef40297c"
    should render 1`] = ` data-type="boolean" role="presentation" > - + false
    should render 1`] = ` data-type="string" role="presentation" > - + "$2,367.73"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "blue"
    should render 1`] = ` data-type="string" role="presentation" > - + "Whitley Zamora"
    should render 1`] = ` data-type="string" role="presentation" > - + "male"
    should render 1`] = ` data-type="string" role="presentation" > - + "MEDALERT"
    should render 1`] = ` data-type="string" role="presentation" > - + "whitleyzamora@medalert.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (825) 435-2054"
    should render 1`] = ` data-type="string" role="presentation" > - + "619 Macon Street, Cresaptown, Rhode Island, 2046"
    should render 1`] = ` data-type="string" role="presentation" > - + "Reprehenderit velit cillum anim commodo est ex est deserunt quis consectetur ex proident do dolore. Pariatur minim enim ipsum nulla quis deserunt duis nisi. Excepteur occaecat quis dolor commodo consectetur. Officia laborum dolore tempor reprehenderit sit. Sit consectetur consequat aliquip qui. Est irure enim ex voluptate non aute. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2016-03-01T09:46:19 -02:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "minim"
    should render 1`] = ` data-type="string" role="presentation" > - + "consequat"
    should render 1`] = ` data-type="string" role="presentation" > - + "dolor"
    should render 1`] = ` data-type="string" role="presentation" > - + "duis"
    should render 1`] = ` data-type="string" role="presentation" > - + "consectetur"
    should render 1`] = ` data-type="string" role="presentation" > - + "et"
    should render 1`] = ` data-type="string" role="presentation" > - + "elit"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Wynn Foster"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Gloria Saunders"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Vega Mcclain"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Whitley Zamora! You have 9 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "strawberry"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77cab3b02db4e3558ef"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "3e68ae9a-4943-47ac-819f-2acf5f5267a9"
    should render 1`] = ` data-type="boolean" role="presentation" > - + true
    should render 1`] = ` data-type="string" role="presentation" > - + "$3,167.93"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "blue"
    should render 1`] = ` data-type="string" role="presentation" > - + "Winters Kirk"
    should render 1`] = ` data-type="string" role="presentation" > - + "male"
    should render 1`] = ` data-type="string" role="presentation" > - + "SIGNITY"
    should render 1`] = ` data-type="string" role="presentation" > - + "winterskirk@signity.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (820) 591-2943"
    should render 1`] = ` data-type="string" role="presentation" > - + "733 Mill Lane, Loma, Wyoming, 5006"
    should render 1`] = ` data-type="string" role="presentation" > - + "Magna nulla et in dolore anim aliqua occaecat aliqua pariatur. Ut commodo duis officia minim labore. Officia aliquip ad esse commodo ea nisi Lorem esse in. Ipsum nulla ea nisi ea magna tempor veniam. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2020-07-15T11:06:26 -03:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "occaecat"
    should render 1`] = ` data-type="string" role="presentation" > - + "pariatur"
    should render 1`] = ` data-type="string" role="presentation" > - + "dolor"
    should render 1`] = ` data-type="string" role="presentation" > - + "irure"
    should render 1`] = ` data-type="string" role="presentation" > - + "sit"
    should render 1`] = ` data-type="string" role="presentation" > - + "eu"
    should render 1`] = ` data-type="string" role="presentation" > - + "et"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Suarez Hale"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Helen Pearson"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Misty Rosario"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Winters Kirk! You have 3 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "banana"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77cb75a6937b0cf29dc"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "bbb12452-3b75-4d3e-b36b-6fcfff003537"
    should render 1`] = ` data-type="boolean" role="presentation" > - + true
    should render 1`] = ` data-type="string" role="presentation" > - + "$2,406.91"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "green"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hill Levine"
    should render 1`] = ` data-type="string" role="presentation" > - + "male"
    should render 1`] = ` data-type="string" role="presentation" > - + "ZAJ"
    should render 1`] = ` data-type="string" role="presentation" > - + "hilllevine@zaj.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (987) 429-2624"
    should render 1`] = ` data-type="string" role="presentation" > - + "434 Cooke Court, Elfrida, Utah, 9346"
    should render 1`] = ` data-type="string" role="presentation" > - + "Pariatur elit est eiusmod aliquip eu ad consectetur velit qui proident sit. Elit irure magna ex voluptate occaecat. Amet veniam voluptate laboris Lorem minim id irure. Laborum eu proident qui est ex nulla deserunt commodo adipisicing qui irure ea cillum nulla. Ut culpa mollit Lorem fugiat laboris duis fugiat. Sint magna anim voluptate irure aliqua magna incididunt reprehenderit aute mollit reprehenderit quis mollit. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2015-11-20T07:07:25 -02:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "id"
    should render 1`] = ` data-type="string" role="presentation" > - + "pariatur"
    should render 1`] = ` data-type="string" role="presentation" > - + "commodo"
    should render 1`] = ` data-type="string" role="presentation" > - + "laboris"
    should render 1`] = ` data-type="string" role="presentation" > - + "occaecat"
    should render 1`] = ` data-type="string" role="presentation" > - + "nulla"
    should render 1`] = ` data-type="string" role="presentation" > - + "nostrud"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Gladys Matthews"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Pittman Lewis"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Marci Pugh"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Hill Levine! You have 4 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "strawberry"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 22 keys
    should render 1`] = ` data-type="string" role="presentation" > - + "6127d77c8e3565e495329780"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "e6b6f813-4081-4aae-a0bb-2dba74f15368"
    should render 1`] = ` data-type="boolean" role="presentation" > - + false
    should render 1`] = ` data-type="string" role="presentation" > - + "$3,874.14"
    should render 1`] = ` data-type="string" role="presentation" > - + "http://placehold.it/32x32"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "green"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hawkins Benton"
    should render 1`] = ` data-type="string" role="presentation" > - + "male"
    should render 1`] = ` data-type="string" role="presentation" > - + "COMVEYER"
    should render 1`] = ` data-type="string" role="presentation" > - + "hawkinsbenton@comveyer.com"
    should render 1`] = ` data-type="string" role="presentation" > - + "+1 (863) 401-3632"
    should render 1`] = ` data-type="string" role="presentation" > - + "994 Havens Place, Cazadero, Arizona, 7731"
    should render 1`] = ` data-type="string" role="presentation" > - + "Deserunt culpa magna culpa sit aliqua eu ut enim ex aliquip quis sit ut qui. Id Lorem tempor Lorem do enim tempor tempor. Nisi proident commodo ea voluptate. Sint ad laborum proident nostrud incididunt deserunt quis amet. Anim exercitation do irure do eiusmod ad consequat aliqua et. +"
    should render 1`] = ` data-type="string" role="presentation" > - + "2016-12-24T11:40:01 -02:00"
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="array" role="presentation" > - + [] 7 items
    should render 1`] = ` data-type="string" role="presentation" > - + "irure"
    should render 1`] = ` data-type="string" role="presentation" > - + "velit"
    should render 1`] = ` data-type="string" role="presentation" > - + "excepteur"
    should render 1`] = ` data-type="string" role="presentation" > - + "cillum"
    should render 1`] = ` data-type="string" role="presentation" > - + "magna"
    should render 1`] = ` data-type="string" role="presentation" > - + "culpa"
    should render 1`] = ` data-type="string" role="presentation" > - + "ullamco"
    should render 1`] = ` data-type="array" role="presentation" > - + [] 3 items
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Meyers Harrell"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Rachael Rodriquez"
    should render 1`] = ` data-type="object" role="presentation" > - + {} 2 keys
    should render 1`] = ` data-type="number" role="presentation" > - + number
    should render 1`] = ` data-type="string" role="presentation" > - + "Ila Vaughn"
    should render 1`] = ` data-type="string" role="presentation" > - + "Hello, Hawkins Benton! You have 10 unread messages."
    should render 1`] = ` data-type="string" role="presentation" > - + "strawberry"
    should render with almost all props defined 1`] = ` data-type="undefined" role="presentation" > - + undefined
    should render with almost all props defined 1`] = ` data-type="null" role="presentation" > - + null
    should render with almost all props defined 1`] = ` data-type="number" role="presentation" > - 0 + number
    should render with almost all props defined 1`] = ` data-type="undefined" role="presentation" > - + undefined
    should render with almost all props defined 1`] = ` data-type="null" role="presentation" > - + null
    should render with almost all props defined 1`] = ` data-type="number" role="presentation" > - 0 + number
    Date: Thu, 17 Jul 2025 22:22:10 +0300 Subject: [PATCH 10/13] fix valueFormat number as value --- packages/site/src/lib/store.ts | 2 ++ packages/svelte-tree-view/src/lib/stores/props.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/site/src/lib/store.ts b/packages/site/src/lib/store.ts index 348684f..d775088 100644 --- a/packages/site/src/lib/store.ts +++ b/packages/site/src/lib/store.ts @@ -107,6 +107,8 @@ const valueFormatter: TreeViewProps['valueFormatter'] = (val, node) => { return `${val.toISOString()}` case 'string': return `"${val}"` + case 'number': + return val case 'boolean': return val ? 'true' : 'false' case 'symbol': diff --git a/packages/svelte-tree-view/src/lib/stores/props.ts b/packages/svelte-tree-view/src/lib/stores/props.ts index 38b22fc..44c7672 100644 --- a/packages/svelte-tree-view/src/lib/stores/props.ts +++ b/packages/svelte-tree-view/src/lib/stores/props.ts @@ -34,6 +34,8 @@ export const createPropsStore = (initialProps: Omit) => { return `${val.toISOString()}` case 'string': return `"${val}"` + case 'number': + return val case 'boolean': return val ? 'true' : 'false' case 'symbol': From a987455691ab09fc56e71996192ee16fdfba4629 Mon Sep 17 00:00:00 2001 From: Teemu Koivisto Date: Thu, 17 Jul 2025 22:28:11 +0300 Subject: [PATCH 11/13] working $proxy version of treemap, wee --- .../site/src/components/TailwindNode.svelte | 18 +++------ .../svelte-tree-view/src/lib/TreeView.svelte | 6 +-- .../src/lib/TreeViewNode.svelte | 20 +++++----- .../src/lib/stores/tree.svelte.ts | 38 ++++++++----------- .../src/lib/tree-utils.svelte.ts | 23 +++++------ 5 files changed, 45 insertions(+), 60 deletions(-) diff --git a/packages/site/src/components/TailwindNode.svelte b/packages/site/src/components/TailwindNode.svelte index dafae89..6d8884b 100644 --- a/packages/site/src/components/TailwindNode.svelte +++ b/packages/site/src/components/TailwindNode.svelte @@ -14,7 +14,7 @@ propsStore: { props: propsObj } } = getTreeContext() - let hasChildren = $derived(node && node.children.length > 0) + let hasChildren = $derived(node.children.length > 0) let descend = $derived(!node.collapsed && hasChildren) // Function to create truncated preview of objects and arrays @@ -130,11 +130,7 @@ {/if} -