@keenmate/svelte-treeview 5.0.0-rc07 → 5.0.0-rc09

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,339 +1,336 @@
1
- BASIC SETUP
2
- ===========
3
-
4
- CRITICAL: This is a Svelte 5 component using runes
5
- - Requires Svelte 5.0.0 or higher
6
- - Uses $state, $derived, $effect runes
7
- - NOT compatible with Svelte 4 or earlier
8
- - Works with SvelteKit, Vite, or any Svelte 5 setup
9
-
10
- INSTALLATION
11
- ------------
12
- npm install @keenmate/svelte-treeview
13
-
14
- # Or yarn
15
- yarn add @keenmate/svelte-treeview
16
-
17
- # Or pnpm
18
- pnpm add @keenmate/svelte-treeview
19
-
20
- IMPORT STYLES
21
- -------------
22
- The component requires CSS to display correctly:
23
-
24
- // In your main.js/main.ts or +layout.svelte
25
- import '@keenmate/svelte-treeview/styles.css';
26
-
27
- // Or SCSS (if you have sass configured)
28
- import '@keenmate/svelte-treeview/styles.scss';
29
-
30
- MINIMAL EXAMPLE
31
- ---------------
32
- <script lang="ts">
33
- import { Tree } from '@keenmate/svelte-treeview';
34
-
35
- const data = [
36
- { id: '1', path: '1', name: 'Documents' },
37
- { id: '1.1', path: '1.1', name: 'Projects' },
38
- { id: '1.1.1', path: '1.1.1', name: 'Project A' },
39
- { id: '2', path: '2', name: 'Pictures' }
40
- ];
41
- </script>
42
-
43
- <Tree
44
- {data}
45
- idMember="id"
46
- pathMember="path"
47
- displayValueMember="name"
48
- />
49
-
50
- REQUIRED PROPS
51
- --------------
52
- These props are required for the tree to work:
53
-
54
- | Prop | Type | Description |
55
- |------|------|-------------|
56
- | data | T[] | Array of data objects |
57
- | idMember | string | Property name for unique ID |
58
- | pathMember | string | Property name for hierarchical path |
59
-
60
- RECOMMENDED PROPS
61
- -----------------
62
- | Prop | Type | Default | Description |
63
- |------|------|---------|-------------|
64
- | displayValueMember | string | null | Property for display text |
65
- | sortCallback | function | built-in | Custom sort function |
66
- | expandLevel | number | 2 | Auto-expand nodes to this depth |
67
-
68
- PATH STRUCTURE
69
- --------------
70
- CRITICAL: Data must use path-based hierarchy
71
-
72
- The path defines the tree structure:
73
- - Root level: "1", "2", "3"
74
- - Second level: "1.1", "1.2", "2.1"
75
- - Third level: "1.1.1", "1.2.1"
76
-
77
- Parent path is derived from child path:
78
- - "1.2.3" → parent is "1.2"
79
- - "1.2" → parent is "1"
80
- - "1" no parent (root)
81
-
82
- Custom separators:
83
- <Tree treePathSeparator="/" ... />
84
- // Paths: "1/2/3", "files/docs/readme"
85
-
86
- BINDING SELECTED NODE
87
- ---------------------
88
- <script>
89
- let selectedNode = $state(null);
90
- </script>
91
-
92
- <Tree
93
- {data}
94
- idMember="id"
95
- pathMember="path"
96
- bind:focusedNode
97
- />
98
-
99
- {#if selectedNode}
100
- <p>Selected: {selectedNode.data.name}</p>
101
- {/if}
102
-
103
- BINDING SEARCH TEXT
104
- -------------------
105
- <script>
106
- let searchText = $state('');
107
- </script>
108
-
109
- <input bind:value={searchText} placeholder="Search..." />
110
-
111
- <Tree
112
- {data}
113
- idMember="id"
114
- pathMember="path"
115
- bind:searchText
116
- shouldUseInternalSearchIndex={true}
117
- searchValueMember="name"
118
- />
119
-
120
- CUSTOM NODE TEMPLATE
121
- --------------------
122
- <Tree
123
- {data}
124
- idMember="id"
125
- pathMember="path"
126
- >
127
- {#snippet nodeTemplate(node)}
128
- <div class="custom-node">
129
- <span class="icon">{node.data.icon}</span>
130
- <span class="name">{node.data.name}</span>
131
- {#if node.data.count}
132
- <span class="badge">{node.data.count}</span>
133
- {/if}
134
- </div>
135
- {/snippet}
136
- </Tree>
137
-
138
- IMPORTANT: The snippet name is nodeTemplate (not nodeContent)
139
-
140
- EXPAND/COLLAPSE CONTROL
141
- -----------------------
142
- Control initial expansion:
143
-
144
- <Tree
145
- {data}
146
- expandLevel={3} <!-- Expand first 3 levels -->
147
- />
148
-
149
- Programmatic control:
150
-
151
- <script>
152
- let treeRef;
153
- </script>
154
-
155
- <Tree bind:this={treeRef} {data} ... />
156
-
157
- <button onclick={() => treeRef.expandAll()}>Expand All</button>
158
- <button onclick={() => treeRef.collapseAll()}>Collapse All</button>
159
- <button onclick={() => treeRef.expandNodes('1.2')}>Expand 1.2</button>
160
-
161
- CLICK HANDLING
162
- --------------
163
- <Tree
164
- {data}
165
- idMember="id"
166
- pathMember="path"
167
- onNodeClicked={(node) => {
168
- console.log('Clicked:', node.data.name);
169
- console.log('Path:', node.path);
170
- }}
171
- />
172
-
173
- Click behavior (default 'expand-and-focus'):
174
- <Tree clickBehavior="select" ... />
175
- <!-- 'select' = click selects, dblclick expands -->
176
- <!-- 'expand' = click expands only -->
177
- <!-- 'expand-and-focus' = click selects + expands -->
178
-
179
- SCROLL TO NODE
180
- --------------
181
- <script>
182
- let treeRef;
183
-
184
- async function goToNode() {
185
- await treeRef.scrollToPath('1.2.3', {
186
- expand: true, // Expand parents first
187
- highlight: true, // Highlight the node
188
- containerScroll: true // Scroll only within container
189
- });
190
- }
191
- </script>
192
-
193
- <Tree bind:this={treeRef} {data} ... />
194
- <button onclick={goToNode}>Go to 1.2.3</button>
195
-
196
- TREE STATISTICS
197
- ---------------
198
- <script>
199
- let treeRef;
200
-
201
- function showStats() {
202
- const stats = treeRef.statistics;
203
- console.log('Total nodes:', stats.nodeCount);
204
- console.log('Max depth:', stats.maxLevel);
205
- console.log('Filtered:', stats.filteredNodeCount);
206
- console.log('Indexing:', stats.isIndexing);
207
- }
208
- </script>
209
-
210
- DEBUG MODE
211
- ----------
212
- Enable debug panel and console logging:
213
-
214
- <Tree
215
- {data}
216
- shouldDisplayDebugInformation={true}
217
- />
218
-
219
- Shows:
220
- - Tree ID
221
- - Node count
222
- - Max depth
223
- - Filtered count
224
- - Indexing status
225
- - Currently dragged node
226
-
227
- EMPTY STATE
228
- -----------
229
- Custom message when tree is empty:
230
-
231
- <Tree {data} ...>
232
- {#snippet noDataFound()}
233
- <div class="empty-state">
234
- <p>No items found</p>
235
- <button>Add First Item</button>
236
- </div>
237
- {/snippet}
238
- </Tree>
239
-
240
- LOADING STATE
241
- -------------
242
- Show a loading placeholder while data is being fetched:
243
-
244
- <Tree {data} isLoading={isLoading}>
245
- {#snippet loadingPlaceholder()}
246
- <div class="loading">Loading tree data...</div>
247
- {/snippet}
248
- </Tree>
249
-
250
- DROP PLACEHOLDER
251
- ----------------
252
- Custom placeholder for empty trees that accept drops:
253
-
254
- <Tree {data} dragDropMode="both">
255
- {#snippet dropPlaceholder()}
256
- <div class="drop-here">Drop items here to start</div>
257
- {/snippet}
258
- </Tree>
259
-
260
- FRAMEWORK INTEGRATION
261
- ---------------------
262
- SvelteKit:
263
- // +page.svelte
264
- <script>
265
- import { Tree } from '@keenmate/svelte-treeview';
266
- import '@keenmate/svelte-treeview/styles.css';
267
- </script>
268
-
269
- Vite + Svelte:
270
- // App.svelte
271
- <script>
272
- import { Tree } from '@keenmate/svelte-treeview';
273
- </script>
274
-
275
- // main.js
276
- import '@keenmate/svelte-treeview/styles.css';
277
-
278
- COMMON SETUP PATTERNS
279
- ---------------------
280
- File explorer:
281
- <Tree
282
- {data}
283
- idMember="id"
284
- pathMember="path"
285
- displayValueMember="name"
286
- expandLevel={1}
287
- treePathSeparator="/"
288
- />
289
-
290
- Organization tree:
291
- <Tree
292
- {data}
293
- idMember="employeeId"
294
- pathMember="orgPath"
295
- displayValueMember="fullName"
296
- expandLevel={3}
297
- />
298
-
299
- With search and drag-drop:
300
- <Tree
301
- {data}
302
- idMember="id"
303
- pathMember="path"
304
- bind:searchText
305
- shouldUseInternalSearchIndex={true}
306
- searchValueMember="name"
307
- dragOverNodeClass="ltree-dragover-glow"
308
- onNodeDrop={handleDrop}
309
- />
310
-
311
- BROWSER SUPPORT
312
- ---------------
313
- Requires modern browsers:
314
- - Chrome/Edge 88+
315
- - Firefox 78+
316
- - Safari 14+
317
-
318
- No IE11 support (Svelte 5 requirement)
319
-
320
- CRITICAL REMINDERS
321
- ------------------
322
- Import styles (CSS or SCSS)
323
- ✅ Use Svelte 5.0.0 or higher
324
- ✅ Use path-based hierarchical data
325
- Set idMember and pathMember
326
- Use $state.raw() for large datasets (1000+ items)
327
-
328
- ❌ Don't use with Svelte 4 or earlier
329
- ❌ Don't forget to import styles
330
- Don't use non-path-based data structures
331
- ❌ Don't use $state() for large datasets (causes slowdown)
332
-
333
- NEXT STEPS
334
- ----------
335
- - Custom data structuredata-handling.txt
336
- - Add drag and drop drag-drop.txt
337
- - Add search → search-features.txt
338
- - Add context menu → context-menu.txt
339
- - Optimize performance → performance.txt
1
+ BASIC SETUP
2
+ ===========
3
+
4
+ CRITICAL: This is a Svelte 5 component using runes
5
+ - Requires Svelte 5.0.0 or higher
6
+ - Uses $state, $derived, $effect runes
7
+ - NOT compatible with Svelte 4 or earlier
8
+ - Works with SvelteKit, Vite, or any Svelte 5 setup
9
+
10
+ INSTALLATION
11
+ ------------
12
+ npm install @keenmate/svelte-treeview
13
+
14
+ # Or yarn
15
+ yarn add @keenmate/svelte-treeview
16
+
17
+ # Or pnpm
18
+ pnpm add @keenmate/svelte-treeview
19
+
20
+ IMPORT STYLES
21
+ -------------
22
+ The component requires CSS to display correctly:
23
+
24
+ // In your main.js/main.ts or +layout.svelte
25
+ import '@keenmate/svelte-treeview/styles.css';
26
+
27
+ MINIMAL EXAMPLE
28
+ ---------------
29
+ <script lang="ts">
30
+ import { Tree } from '@keenmate/svelte-treeview';
31
+
32
+ const data = [
33
+ { id: '1', path: '1', name: 'Documents' },
34
+ { id: '1.1', path: '1.1', name: 'Projects' },
35
+ { id: '1.1.1', path: '1.1.1', name: 'Project A' },
36
+ { id: '2', path: '2', name: 'Pictures' }
37
+ ];
38
+ </script>
39
+
40
+ <Tree
41
+ {data}
42
+ idMember="id"
43
+ pathMember="path"
44
+ displayValueMember="name"
45
+ />
46
+
47
+ REQUIRED PROPS
48
+ --------------
49
+ These props are required for the tree to work:
50
+
51
+ | Prop | Type | Description |
52
+ |------|------|-------------|
53
+ | data | T[] | Array of data objects |
54
+ | idMember | string | Property name for unique ID |
55
+ | pathMember | string | Property name for hierarchical path |
56
+
57
+ RECOMMENDED PROPS
58
+ -----------------
59
+ | Prop | Type | Default | Description |
60
+ |------|------|---------|-------------|
61
+ | displayValueMember | string | null | Property for display text |
62
+ | sortCallback | function | built-in | Custom sort function |
63
+ | expandLevel | number | 2 | Auto-expand nodes to this depth |
64
+
65
+ PATH STRUCTURE
66
+ --------------
67
+ CRITICAL: Data must use path-based hierarchy
68
+
69
+ The path defines the tree structure:
70
+ - Root level: "1", "2", "3"
71
+ - Second level: "1.1", "1.2", "2.1"
72
+ - Third level: "1.1.1", "1.2.1"
73
+
74
+ Parent path is derived from child path:
75
+ - "1.2.3" → parent is "1.2"
76
+ - "1.2" → parent is "1"
77
+ - "1" no parent (root)
78
+
79
+ Custom separators:
80
+ <Tree treePathSeparator="/" ... />
81
+ // Paths: "1/2/3", "files/docs/readme"
82
+
83
+ BINDING SELECTED NODE
84
+ ---------------------
85
+ <script>
86
+ let selectedNode = $state(null);
87
+ </script>
88
+
89
+ <Tree
90
+ {data}
91
+ idMember="id"
92
+ pathMember="path"
93
+ bind:focusedNode
94
+ />
95
+
96
+ {#if selectedNode}
97
+ <p>Selected: {selectedNode.data.name}</p>
98
+ {/if}
99
+
100
+ BINDING SEARCH TEXT
101
+ -------------------
102
+ <script>
103
+ let searchText = $state('');
104
+ </script>
105
+
106
+ <input bind:value={searchText} placeholder="Search..." />
107
+
108
+ <Tree
109
+ {data}
110
+ idMember="id"
111
+ pathMember="path"
112
+ bind:searchText
113
+ shouldUseInternalSearchIndex={true}
114
+ searchValueMember="name"
115
+ />
116
+
117
+ CUSTOM NODE TEMPLATE
118
+ --------------------
119
+ <Tree
120
+ {data}
121
+ idMember="id"
122
+ pathMember="path"
123
+ >
124
+ {#snippet nodeTemplate(node)}
125
+ <div class="custom-node">
126
+ <span class="icon">{node.data.icon}</span>
127
+ <span class="name">{node.data.name}</span>
128
+ {#if node.data.count}
129
+ <span class="badge">{node.data.count}</span>
130
+ {/if}
131
+ </div>
132
+ {/snippet}
133
+ </Tree>
134
+
135
+ IMPORTANT: The snippet name is nodeTemplate (not nodeContent)
136
+
137
+ EXPAND/COLLAPSE CONTROL
138
+ -----------------------
139
+ Control initial expansion:
140
+
141
+ <Tree
142
+ {data}
143
+ expandLevel={3} <!-- Expand first 3 levels -->
144
+ />
145
+
146
+ Programmatic control:
147
+
148
+ <script>
149
+ let treeRef;
150
+ </script>
151
+
152
+ <Tree bind:this={treeRef} {data} ... />
153
+
154
+ <button onclick={() => treeRef.expandAll()}>Expand All</button>
155
+ <button onclick={() => treeRef.collapseAll()}>Collapse All</button>
156
+ <button onclick={() => treeRef.expandNodes('1.2')}>Expand 1.2</button>
157
+
158
+ CLICK HANDLING
159
+ --------------
160
+ <Tree
161
+ {data}
162
+ idMember="id"
163
+ pathMember="path"
164
+ onNodeClicked={(node) => {
165
+ console.log('Clicked:', node.data.name);
166
+ console.log('Path:', node.path);
167
+ }}
168
+ />
169
+
170
+ Click behavior (default 'expand-and-focus'):
171
+ <Tree clickBehavior="select" ... />
172
+ <!-- 'select' = click selects, dblclick expands -->
173
+ <!-- 'expand' = click expands only -->
174
+ <!-- 'expand-and-focus' = click selects + expands -->
175
+
176
+ SCROLL TO NODE
177
+ --------------
178
+ <script>
179
+ let treeRef;
180
+
181
+ async function goToNode() {
182
+ await treeRef.scrollToPath('1.2.3', {
183
+ expand: true, // Expand parents first
184
+ highlight: true, // Highlight the node
185
+ containerScroll: true // Scroll only within container
186
+ });
187
+ }
188
+ </script>
189
+
190
+ <Tree bind:this={treeRef} {data} ... />
191
+ <button onclick={goToNode}>Go to 1.2.3</button>
192
+
193
+ TREE STATISTICS
194
+ ---------------
195
+ <script>
196
+ let treeRef;
197
+
198
+ function showStats() {
199
+ const stats = treeRef.statistics;
200
+ console.log('Total nodes:', stats.nodeCount);
201
+ console.log('Max depth:', stats.maxLevel);
202
+ console.log('Filtered:', stats.filteredNodeCount);
203
+ console.log('Indexing:', stats.isIndexing);
204
+ }
205
+ </script>
206
+
207
+ DEBUG MODE
208
+ ----------
209
+ Enable debug panel and console logging:
210
+
211
+ <Tree
212
+ {data}
213
+ shouldDisplayDebugInformation={true}
214
+ />
215
+
216
+ Shows:
217
+ - Tree ID
218
+ - Node count
219
+ - Max depth
220
+ - Filtered count
221
+ - Indexing status
222
+ - Currently dragged node
223
+
224
+ EMPTY STATE
225
+ -----------
226
+ Custom message when tree is empty:
227
+
228
+ <Tree {data} ...>
229
+ {#snippet noDataFound()}
230
+ <div class="empty-state">
231
+ <p>No items found</p>
232
+ <button>Add First Item</button>
233
+ </div>
234
+ {/snippet}
235
+ </Tree>
236
+
237
+ LOADING STATE
238
+ -------------
239
+ Show a loading placeholder while data is being fetched:
240
+
241
+ <Tree {data} isLoading={isLoading}>
242
+ {#snippet loadingPlaceholder()}
243
+ <div class="loading">Loading tree data...</div>
244
+ {/snippet}
245
+ </Tree>
246
+
247
+ DROP PLACEHOLDER
248
+ ----------------
249
+ Custom placeholder for empty trees that accept drops:
250
+
251
+ <Tree {data} dragDropMode="both">
252
+ {#snippet dropPlaceholder()}
253
+ <div class="drop-here">Drop items here to start</div>
254
+ {/snippet}
255
+ </Tree>
256
+
257
+ FRAMEWORK INTEGRATION
258
+ ---------------------
259
+ SvelteKit:
260
+ // +page.svelte
261
+ <script>
262
+ import { Tree } from '@keenmate/svelte-treeview';
263
+ import '@keenmate/svelte-treeview/styles.css';
264
+ </script>
265
+
266
+ Vite + Svelte:
267
+ // App.svelte
268
+ <script>
269
+ import { Tree } from '@keenmate/svelte-treeview';
270
+ </script>
271
+
272
+ // main.js
273
+ import '@keenmate/svelte-treeview/styles.css';
274
+
275
+ COMMON SETUP PATTERNS
276
+ ---------------------
277
+ File explorer:
278
+ <Tree
279
+ {data}
280
+ idMember="id"
281
+ pathMember="path"
282
+ displayValueMember="name"
283
+ expandLevel={1}
284
+ treePathSeparator="/"
285
+ />
286
+
287
+ Organization tree:
288
+ <Tree
289
+ {data}
290
+ idMember="employeeId"
291
+ pathMember="orgPath"
292
+ displayValueMember="fullName"
293
+ expandLevel={3}
294
+ />
295
+
296
+ With search and drag-drop:
297
+ <Tree
298
+ {data}
299
+ idMember="id"
300
+ pathMember="path"
301
+ bind:searchText
302
+ shouldUseInternalSearchIndex={true}
303
+ searchValueMember="name"
304
+ dragOverNodeClass="ltree-dragover-glow"
305
+ onNodeDrop={handleDrop}
306
+ />
307
+
308
+ BROWSER SUPPORT
309
+ ---------------
310
+ Requires modern browsers:
311
+ - Chrome/Edge 88+
312
+ - Firefox 78+
313
+ - Safari 14+
314
+
315
+ No IE11 support (Svelte 5 requirement)
316
+
317
+ CRITICAL REMINDERS
318
+ ------------------
319
+ ✅ Import styles (CSS or SCSS)
320
+ Use Svelte 5.0.0 or higher
321
+ ✅ Use path-based hierarchical data
322
+ Set idMember and pathMember
323
+ ✅ Use $state.raw() for large datasets (1000+ items)
324
+
325
+ Don't use with Svelte 4 or earlier
326
+ Don't forget to import styles
327
+ ❌ Don't use non-path-based data structures
328
+ ❌ Don't use $state() for large datasets (causes slowdown)
329
+
330
+ NEXT STEPS
331
+ ----------
332
+ - Custom data structure → data-handling.txt
333
+ - Add drag and drop → drag-drop.txt
334
+ - Add search → search-features.txt
335
+ - Add context menucontext-menu.txt
336
+ - Optimize performanceperformance.txt