Skip to content

Commit a46fb0e

Browse files
committed
make treeNode required, update tests & components
1 parent 1b03a30 commit a46fb0e

File tree

8 files changed

+60
-162
lines changed

8 files changed

+60
-162
lines changed
Lines changed: 10 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
<script lang="ts">
2+
import { DefaultNode } from 'svelte-tree-view'
3+
24
import type { NodeProps } from 'svelte-tree-view'
35
4-
let {
5-
node,
6-
TreeViewNode,
7-
getTreeContext,
8-
handleLogNode,
9-
handleCopyNodeToClipboard,
10-
handleToggleCollapse
11-
}: NodeProps = $props()
6+
let props: NodeProps = $props()
7+
128
const {
13-
propsStore: { props: propsObj, formatValue }
14-
} = getTreeContext()
15-
let hasChildren = $derived(node.children.length > 0)
16-
let descend = $derived(!node.collapsed && hasChildren)
17-
let value = $derived(node.getValue())
9+
propsStore: { formatValue }
10+
} = props.getTreeContext()
1811
1912
function replaceSpacesWithNonBreakingSpace(value: string) {
2013
return value.replace(/\s/gm, ' ')
@@ -46,29 +39,8 @@
4639
}
4740
</script>
4841

49-
<li class="row" class:collapsed={node.collapsed && hasChildren} data-tree-id={node.id}>
50-
{#if hasChildren}
51-
<button class={`arrow-btn ${node.collapsed ? 'collapsed' : ''}`} onclick={handleToggleCollapse}>
52-
53-
</button>
54-
{/if}
55-
<div
56-
class="node-key"
57-
class:has-children={hasChildren}
58-
class:p-left={!hasChildren}
59-
onclick={handleToggleCollapse}
60-
role="presentation"
61-
>
62-
{node.key}:
63-
</div>
64-
<div
65-
class="node-value"
66-
data-type={node.type}
67-
class:expanded={!node.collapsed && hasChildren}
68-
class:has-children={hasChildren}
69-
onclick={handleToggleCollapse}
70-
role="presentation"
71-
>
42+
<DefaultNode {...props}>
43+
{#snippet value(node)}
7244
{#if Array.isArray(value)}
7345
<!-- The why https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md -->
7446
{#if value.length === 1}
@@ -97,25 +69,8 @@
9769
{:else}
9870
{formatValue(value, node)}
9971
{/if}
100-
</div>
101-
<div class="buttons">
102-
{#if $propsObj.showLogButton}
103-
<button class="log-copy-button" onclick={handleLogNode}>log</button>
104-
{/if}
105-
{#if $propsObj.showCopyButton}
106-
<button class="log-copy-button" onclick={handleCopyNodeToClipboard}>copy</button>
107-
{/if}
108-
</div>
109-
</li>
110-
{#if descend}
111-
<li class="row">
112-
<ul>
113-
{#each node.children as id}
114-
<TreeViewNode {id} />
115-
{/each}
116-
</ul>
117-
</li>
118-
{/if}
72+
{/snippet}
73+
</DefaultNode>
11974

12075
<style lang="postcss">
12176
.added {
@@ -146,92 +101,4 @@
146101
.arrow {
147102
color: #87cc86;
148103
}
149-
150-
ul {
151-
display: flex;
152-
flex-direction: column;
153-
height: max-content;
154-
list-style: none;
155-
padding: 0;
156-
padding-left: var(--tree-view-left-indent);
157-
margin: 0;
158-
width: 100%;
159-
}
160-
li {
161-
align-items: baseline;
162-
display: flex;
163-
height: max-content;
164-
line-height: var(--tree-view-line-height);
165-
list-style: none;
166-
width: 100%;
167-
}
168-
li + li {
169-
margin-top: 0.25em;
170-
}
171-
.empty-block {
172-
visibility: hidden;
173-
}
174-
.node-key {
175-
color: var(--tree-view-base0D);
176-
margin-right: var(--tree-view-key-margin-right);
177-
&.has-children {
178-
cursor: pointer;
179-
}
180-
&.p-left {
181-
padding-left: 1.1em;
182-
}
183-
}
184-
.node-value {
185-
color: var(--tree-view-base0B);
186-
margin-right: 0.5em;
187-
word-break: break-all;
188-
&[data-type='number'],
189-
&[data-type='boolean'] {
190-
color: var(--tree-view-base09);
191-
}
192-
&[data-type='null'],
193-
&[data-type='undefined'] {
194-
color: var(--tree-view-base08);
195-
}
196-
&.expanded {
197-
color: var(--tree-view-base03);
198-
}
199-
&.has-children {
200-
cursor: pointer;
201-
}
202-
}
203-
.arrow-btn {
204-
background: transparent;
205-
border: 0;
206-
color: var(--tree-view-base0D);
207-
cursor: pointer;
208-
margin-right: 0.7em;
209-
padding: 0;
210-
transition: all 150ms ease 0s;
211-
transform: rotateZ(90deg);
212-
transform-origin: 47% 43%;
213-
position: relative;
214-
line-height: 1.1em;
215-
font-size: 0.75em;
216-
&.collapsed {
217-
transform: rotateZ(0deg);
218-
}
219-
}
220-
.buttons {
221-
display: flex;
222-
flex-wrap: wrap;
223-
}
224-
.log-copy-button {
225-
background: transparent;
226-
border: 0;
227-
color: var(--tree-view-base0D);
228-
cursor: pointer;
229-
margin: 0;
230-
padding: 0 0.5em;
231-
&:hover {
232-
background: rgba(rgb(255, 162, 177), 0.4);
233-
border-radius: 2px;
234-
color: var(--tree-view-base07);
235-
}
236-
}
237104
</style>

packages/site/src/routes/+page.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { onMount } from 'svelte'
3-
import TreeView from 'svelte-tree-view'
3+
import TreeView, { DefaultNode } from 'svelte-tree-view'
44
55
import { mapDocDeltaChildren } from '$lib/mapDocDeltaChildren'
66
import {
@@ -36,6 +36,9 @@
3636
{@render children()}
3737
</ul>
3838
{/snippet}
39+
{#snippet treeNode(props)}
40+
<DefaultNode {...props} />
41+
{/snippet}
3942
</TreeView>
4043

4144
<style lang="postcss">

packages/site/src/routes/circular/+page.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { onMount } from 'svelte'
3-
import TreeView from 'svelte-tree-view'
3+
import TreeView, { DefaultNode } from 'svelte-tree-view'
44
55
import { mapDocDeltaChildren } from '$lib/mapDocDeltaChildren'
66
import {
@@ -39,6 +39,9 @@
3939
{@render children()}
4040
</ul>
4141
{/snippet}
42+
{#snippet treeNode(props)}
43+
<DefaultNode {...props} />
44+
{/snippet}
4245
</TreeView>
4346

4447
<style lang="postcss">

packages/svelte-tree-view/src/lib/DefaultNode.svelte

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
<script lang="ts">
2-
import type { NodeProps } from './types'
2+
import type { Snippet } from 'svelte'
3+
import type { NodeProps, TreeNode } from './types'
4+
5+
type DefaultNodeProps = NodeProps & {
6+
key?: Snippet<[TreeNode]>
7+
value?: Snippet<[TreeNode]>
8+
}
39
410
let {
511
node,
12+
key,
13+
value,
614
TreeViewNode,
715
getTreeContext,
816
handleLogNode,
917
handleCopyNodeToClipboard,
1018
handleToggleCollapse
11-
}: NodeProps = $props()
19+
}: DefaultNodeProps = $props()
1220
const {
1321
propsStore: { props: propsObj, formatValue }
1422
} = getTreeContext()
@@ -30,7 +38,11 @@
3038
onclick={handleToggleCollapse}
3139
role="presentation"
3240
>
33-
{node.key}:
41+
{#if key}
42+
{@render key(node)}
43+
{:else}
44+
{node.key}:
45+
{/if}
3446
</div>
3547
<div
3648
class="node-value"
@@ -40,7 +52,11 @@
4052
onclick={handleToggleCollapse}
4153
role="presentation"
4254
>
43-
{valueStr}
55+
{#if value}
56+
{@render value(node)}
57+
{:else}
58+
{valueStr}
59+
{/if}
4460
</div>
4561
<div class="buttons">
4662
{#if $propsObj.showLogButton}

packages/svelte-tree-view/src/lib/TreeViewNode.svelte

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script lang="ts">
22
import { getContext } from 'svelte'
33
4-
import DefaultNode from './DefaultNode.svelte'
54
import TreeViewNode from './TreeViewNode.svelte'
65
76
import type { Stores } from './stores'
@@ -50,8 +49,4 @@
5049
})
5150
</script>
5251

53-
{#if $propsObj.treeNode}
54-
{@render $propsObj.treeNode(nodeProps)}
55-
{:else}
56-
<DefaultNode {...nodeProps} />
57-
{/if}
52+
{@render $propsObj.treeNode(nodeProps)}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import TreeView from '../TreeView.svelte'
3+
import DefaultNode from '../DefaultNode.svelte'
4+
5+
import type { Props } from '../types'
6+
7+
let props: Props = $props()
8+
</script>
9+
10+
<TreeView {...props}>
11+
{#snippet treeNode(props)}
12+
<DefaultNode {...props} />
13+
{/snippet}
14+
</TreeView>

packages/svelte-tree-view/src/lib/__tests__/TreeView.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { render, fireEvent, findAllByText } from '@testing-library/svelte'
22
import { describe, expect, it, vi } from 'vitest'
33

4-
import TreeView from '../TreeView.svelte'
4+
import DefaultTree from './DefaultTree.svelte'
55

66
import example1 from './__fixtures__/example1.json'
77
import { generateObj } from './generateObj'
@@ -27,7 +27,7 @@ async function clickByText(container: HTMLElement, text: string, index = 0) {
2727

2828
describe('TreeView', () => {
2929
it('should render', async () => {
30-
const results = render(TreeView, {
30+
const results = render(DefaultTree, {
3131
data: example1,
3232
recursionOpts: {
3333
shouldExpandNode: () => true
@@ -40,7 +40,7 @@ describe('TreeView', () => {
4040
})
4141

4242
it('should render with almost all props defined', async () => {
43-
const results = render(TreeView, {
43+
const results = render(DefaultTree, {
4444
data: generateObj(0, 4),
4545
showLogButton: true,
4646
showCopyButton: true,
@@ -119,7 +119,7 @@ describe('TreeView', () => {
119119
])
120120
}
121121
let map: any
122-
const results = render(TreeView, {
122+
const results = render(DefaultTree, {
123123
data,
124124
recursionOpts: {
125125
maxDepth: 4
@@ -198,7 +198,7 @@ describe('TreeView', () => {
198198
})
199199

200200
it('should not map primitive values and renders them correctly in list', async () => {
201-
const results = render(TreeView, {
201+
const results = render(DefaultTree, {
202202
data: undefined
203203
})
204204
window.HTMLElement.prototype.scrollIntoView = vi.fn()

packages/svelte-tree-view/src/lib/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type Component, type Snippet } from 'svelte'
1+
import type { Component, Snippet } from 'svelte'
22
import type { HTMLAttributes } from 'svelte/elements'
33
import type { Stores } from './stores'
44

@@ -174,7 +174,7 @@ export interface TreeViewProps<T = any> {
174174
/**
175175
* Custom tree node. Uses DefaultNode.svelte by default
176176
*/
177-
treeNode?: Snippet<[NodeProps<T>]>
177+
treeNode: Snippet<[NodeProps<T>]>
178178
theme?: Base16Theme
179179
showLogButton?: boolean
180180
showCopyButton?: boolean

0 commit comments

Comments
 (0)