@keenmate/svelte-treeview 4.7.0 → 4.8.0

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.
package/README.md CHANGED
@@ -2,7 +2,41 @@
2
2
 
3
3
  A high-performance, feature-rich hierarchical tree view component for Svelte 5 with drag & drop support, search functionality, and flexible data structures using LTree.
4
4
 
5
- ## 📢 New in v4.7: Per-Node Drop Position Restrictions
5
+ ## Live Demo
6
+
7
+ Browse interactive code examples and the full API reference at **[svelte-treeview.keenmate.dev](https://svelte-treeview.keenmate.dev)**
8
+
9
+ ## New in v4.8: Virtual Scroll & Unified Rendering
10
+
11
+ > [!NOTE]
12
+ > **New virtual scroll mode renders only visible nodes — handle 50,000+ items without DOM bloat.**
13
+
14
+ Three rendering modes, one consistent look:
15
+
16
+ | Mode | Best for | How it works |
17
+ |------|----------|-------------|
18
+ | **Recursive** | Small trees (<500 nodes) | Traditional nested Svelte components |
19
+ | **Progressive** (default) | Medium trees (500–10,000) | Flat rendering with exponential batching |
20
+ | **Virtual Scroll** | Large trees (10,000+) | Only visible rows + overscan are in the DOM |
21
+
22
+ ```svelte
23
+ <Tree
24
+ {data}
25
+ virtualScroll={true}
26
+ virtualRowHeight={28}
27
+ virtualOverscan={5}
28
+ virtualContainerHeight="600px"
29
+ />
30
+ ```
31
+
32
+ **Also in this release:**
33
+ - **Search result navigation** — dual-mode filter/search with result counter, prev/next (Enter/Shift+Enter), round-robin cycling
34
+ - **Floating drop zones auto-expand** when positions are restricted — pure CSS `:not(:has())`, zero JS overhead
35
+ - **Cross-tree drop positioning fixed** — above/below placement now works correctly between trees
36
+ - **Unified indentation & gaps** across all three rendering modes
37
+ - **Drag & drop disabled by default** — set `dragDropMode="both"` to enable
38
+
39
+ ## v4.7: Per-Node Drop Position Restrictions
6
40
 
7
41
  > [!NOTE]
8
42
  > **You can now restrict which drop positions (above/below/child) are allowed per node.**
@@ -17,7 +51,7 @@ function getAllowedDropPositions(node) {
17
51
  }
18
52
  ```
19
53
 
20
- ## 📢 v4.6: Progressive Flat Rendering
54
+ ## v4.6: Progressive Flat Rendering
21
55
 
22
56
  > [!NOTE]
23
57
  > **The tree now uses progressive flat rendering by default for significantly improved performance.**
@@ -51,7 +85,7 @@ function getAllowedDropPositions(node) {
51
85
 
52
86
  Recursive mode may be preferred for very small trees or when you need the `{#key changeTracker}` behavior that recreates all nodes on any change.
53
87
 
54
- ## 🚀 Features
88
+ ## Features
55
89
 
56
90
  - **Svelte 5 Native**: Built specifically for Svelte 5 with full support for runes and modern Svelte patterns
57
91
  - **High Performance**: Flat rendering mode with progressive loading for 5000+ nodes
@@ -64,77 +98,34 @@ Recursive mode may be preferred for very small trees or when you need the `{#key
64
98
  - **TypeScript Support**: Full TypeScript support with comprehensive type definitions
65
99
  - **Accessibility**: Built with accessibility in mind
66
100
 
67
- ## 📦 Installation
101
+ ## Installation
68
102
 
69
103
  ```bash
70
104
  npm install @keenmate/svelte-treeview
71
105
  ```
72
106
 
73
- ## 🔨 Development Setup
74
-
75
- For developers working on the project, you can use either standard npm commands or the provided Makefile (which provides a unified interface for all contributors):
76
-
77
- ```bash
78
- # Using Makefile (recommended for consistency)
79
- make setup # or make install
80
- make dev
81
-
82
- # Or using standard npm commands
83
- npm install
84
- npm run dev
85
- ```
86
-
87
- ## 🎨 Importing Styles
107
+ ### Importing Styles
88
108
 
89
109
  The component requires CSS to display correctly. Import the styles in your app:
90
110
 
91
- ### Option 1: Import SCSS in your main app file
111
+ **JavaScript import** (in your main.js/main.ts or Vite/Webpack entry):
92
112
  ```javascript
93
- // In your main.js or main.ts
94
113
  import '@keenmate/svelte-treeview/styles.scss';
95
114
  ```
96
115
 
97
- ### Option 2: Import in your Svelte component
116
+ **Svelte component import:**
98
117
  ```svelte
99
118
  <style>
100
119
  @import '@keenmate/svelte-treeview/styles.scss';
101
120
  </style>
102
121
  ```
103
122
 
104
- ### Option 3: Use with your build system
105
- If using Vite, Webpack, or similar, you can import the SCSS:
106
- ```javascript
107
- import '@keenmate/svelte-treeview/styles.scss';
108
- ```
109
-
110
- ## ⚠️ Performance Warning: Use `$state.raw()` for Large Datasets
111
-
112
- > [!WARNING]
113
- > **When passing large arrays (1000+ items) to the Tree component, use `$state.raw()` instead of `$state()` to avoid severe performance issues.**
114
-
115
- Svelte 5's `$state()` creates deep proxies for all nested objects. With thousands of items, this causes massive overhead during tree operations.
116
-
117
- ```typescript
118
- // ❌ SLOW - Each item becomes a Proxy (5000x slower with large datasets)
119
- let treeData = $state<TreeNode[]>([])
120
-
121
- // ✅ FAST - Items remain plain objects
122
- let treeData = $state.raw<TreeNode[]>([])
123
- ```
124
-
125
- **Symptoms of this issue:**
126
- - Tree takes 15-90+ seconds to render with thousands of items
127
- - Console shows `[Violation] 'message' handler took XXXXms`
128
- - Same data loads instantly in isolated test
129
-
130
- The array itself remains reactive - only individual items lose deep reactivity (which Tree doesn't need).
131
-
132
- ## 🎯 Quick Start
123
+ ## Quick Start
133
124
 
134
125
  ```svelte
135
126
  <script lang="ts">
136
127
  import { Tree } from '@keenmate/svelte-treeview';
137
-
128
+
138
129
  const data = [
139
130
  { path: '1', name: 'Documents', type: 'folder' },
140
131
  { path: '1.1', name: 'Projects', type: 'folder' },
@@ -153,14 +144,24 @@ The array itself remains reactive - only individual items lose deep reactivity (
153
144
  />
154
145
  ```
155
146
 
156
- ## 🔧 Advanced Usage
147
+ > [!TIP]
148
+ > **Performance tip:** When passing large arrays (1000+ items) to the Tree component, use `$state.raw()` instead of `$state()` to avoid severe performance issues. Svelte 5's `$state()` creates deep proxies — with thousands of items this causes up to 5,000x slowdown. The array itself remains reactive; only individual items lose deep reactivity (which Tree doesn't need).
149
+ > ```typescript
150
+ > // BAD - Each item becomes a Proxy
151
+ > let treeData = $state<TreeNode[]>([])
152
+ >
153
+ > // GOOD - Items remain plain objects
154
+ > let treeData = $state.raw<TreeNode[]>([])
155
+ > ```
156
+
157
+ ## Advanced Usage
157
158
 
158
159
  ### With Custom Node Templates
159
160
 
160
161
  ```svelte
161
162
  <script lang="ts">
162
163
  import { Tree } from '@keenmate/svelte-treeview';
163
-
164
+
164
165
  const fileData = [
165
166
  { path: '1', name: 'Documents', type: 'folder', icon: '📁' },
166
167
  { path: '1.1', name: 'report.pdf', type: 'file', icon: '📄', size: '2.3 MB' },
@@ -193,15 +194,15 @@ The array itself remains reactive - only individual items lose deep reactivity (
193
194
  ```svelte
194
195
  <script lang="ts">
195
196
  import { Tree } from '@keenmate/svelte-treeview';
196
-
197
+
197
198
  let searchText = $state('');
198
199
  const data = [/* your data */];
199
200
  </script>
200
201
 
201
- <input
202
- type="text"
203
- placeholder="Search..."
204
- bind:value={searchText}
202
+ <input
203
+ type="text"
204
+ placeholder="Search..."
205
+ bind:value={searchText}
205
206
  />
206
207
 
207
208
  <Tree
@@ -220,29 +221,29 @@ The array itself remains reactive - only individual items lose deep reactivity (
220
221
  <script lang="ts">
221
222
  import { Tree } from '@keenmate/svelte-treeview';
222
223
  import type { SearchOptions } from 'flexsearch';
223
-
224
+
224
225
  let treeRef;
225
226
  const data = [/* your data */];
226
-
227
+
227
228
  // Programmatic search with FlexSearch options
228
229
  function performAdvancedSearch(searchTerm: string) {
229
230
  const searchOptions: SearchOptions = {
230
231
  suggest: true, // Enable suggestions for typos
231
- limit: 10, // Limit results to 10 items
232
+ limit: 10, // Limit results to 10 items
232
233
  bool: "and" // Use AND logic for multiple terms
233
234
  };
234
-
235
+
235
236
  const results = treeRef.searchNodes(searchTerm, searchOptions);
236
237
  console.log('Advanced search results:', results);
237
238
  }
238
-
239
+
239
240
  // Programmatic filtering with options
240
241
  function filterWithOptions(searchTerm: string) {
241
242
  const searchOptions: SearchOptions = {
242
243
  threshold: 0.8, // Similarity threshold
243
244
  depth: 2 // Search depth
244
245
  };
245
-
246
+
246
247
  treeRef.filterNodes(searchTerm, searchOptions);
247
248
  }
248
249
  </script>
@@ -281,6 +282,8 @@ For complete FlexSearch documentation, visit: [FlexSearch Options](https://githu
281
282
 
282
283
  ### With Drag & Drop
283
284
 
285
+ **Note:** Drag and drop is disabled by default. Set `dragDropMode` to enable it.
286
+
284
287
  ```svelte
285
288
  <script lang="ts">
286
289
  import { Tree } from '@keenmate/svelte-treeview';
@@ -288,9 +291,9 @@ For complete FlexSearch documentation, visit: [FlexSearch Options](https://githu
288
291
  let treeRef: Tree<MyNode>;
289
292
 
290
293
  const data = [
291
- { path: '1', name: 'Folder 1', isDraggable: true },
292
- { path: '1.1', name: 'Item 1', isDraggable: true },
293
- { path: '2', name: 'Folder 2', isDraggable: true }
294
+ { path: '1', name: 'Folder 1' },
295
+ { path: '1.1', name: 'Item 1' },
296
+ { path: '2', name: 'Folder 2' }
294
297
  ];
295
298
 
296
299
  function onDragStart(node, event) {
@@ -310,6 +313,7 @@ For complete FlexSearch documentation, visit: [FlexSearch Options](https://githu
310
313
  {data}
311
314
  idMember="path"
312
315
  pathMember="path"
316
+ dragDropMode="both"
313
317
  orderMember="sortOrder"
314
318
  dragOverNodeClass="ltree-dragover-highlight"
315
319
  onNodeDragStart={onDragStart}
@@ -539,7 +543,7 @@ The tree supports context menus with two approaches: callback-based (recommended
539
543
  - **Auto-close**: Closes on scroll, click outside, or programmatically
540
544
  - **Type safety**: Full TypeScript support with `ContextMenuItem` interface
541
545
 
542
- ## 🎨 Styling and Customization
546
+ ## Styling and Customization
543
547
 
544
548
  The component comes with default styles that provide a clean, modern look. You can customize it extensively:
545
549
 
@@ -609,7 +613,7 @@ The component includes several pre-built classes for styling selected nodes:
609
613
  |-------|-------------|---------------|
610
614
  | `ltree-selected-bold` | Bold text with primary color | **Bold text** in theme primary color |
611
615
  | `ltree-selected-border` | Border and background highlight | Solid border with light background |
612
- | `ltree-selected-brackets` | Decorative brackets around text | **Node Text** |
616
+ | `ltree-selected-brackets` | Decorative brackets around text | > **Node Text** < |
613
617
 
614
618
  **Available Drag-over Node Classes:**
615
619
 
@@ -631,17 +635,17 @@ The component includes several pre-built classes for styling selected nodes:
631
635
  />
632
636
  ```
633
637
 
634
- ## 📚 API Reference
638
+ ## API Reference
635
639
 
636
640
  ### Tree Component Props
637
641
 
638
- #### Core Required Properties
639
- | Prop | Type | Required | Description |
640
- |------|------|----------|-------------|
641
- | `data` | `T[]` | | Array of data objects |
642
- | `idMember` | `string` | | Property name for unique identifiers |
643
- | `pathMember` | `string` | | Property name for hierarchical paths |
644
- | `sortCallback` | `(items: T[]) => T[]` | | Function to sort items |
642
+ #### Core Properties
643
+ | Prop | Type | Default | Description |
644
+ |------|------|---------|-------------|
645
+ | `data` | `T[]` | **required** | Array of data objects |
646
+ | `idMember` | `string` | **required** | Property name for unique identifiers |
647
+ | `pathMember` | `string` | **required** | Property name for hierarchical paths |
648
+ | `sortCallback` | `(items: T[]) => T[]` | default sort | Function to sort items (optional) |
645
649
 
646
650
  #### Data Mapping Properties
647
651
  | Prop | Type | Default | Description |
@@ -670,13 +674,13 @@ The component includes several pre-built classes for styling selected nodes:
670
674
 
671
675
  **Note**: When `shouldUseInternalSearchIndex` is enabled, node indexing is performed asynchronously using `requestIdleCallback` (with fallback to `setTimeout`). This ensures the tree renders immediately while search indexing happens during browser idle time, providing better performance for large datasets.
672
676
 
673
- **⚠️ Important**: For internal search indexing to work, you must:
677
+ **Important**: For internal search indexing to work, you must:
674
678
  1. Set `shouldUseInternalSearchIndex={true}`
675
679
  2. Provide either `searchValueMember` (property name) or `getSearchValueCallback` (function)
676
680
 
677
681
  Without both requirements, no search indexing will occur.
678
682
 
679
- **Performance Tuning**:
683
+ **Performance Tuning**:
680
684
  - `indexerBatchSize` controls how many nodes are processed per idle callback. Lower values (10-25) provide smoother UI performance but slower indexing, while higher values (50-100) index faster but may cause brief UI pauses. Default: 25.
681
685
  - `indexerTimeout` sets the maximum wait time before forcing indexing when the browser is busy. Lower values (25-50ms) ensure more responsive indexing, while higher values (100-200ms) give more time for genuine idle periods. Default: 50ms.
682
686
 
@@ -693,24 +697,41 @@ Without both requirements, no search indexing will occur.
693
697
  |------|------|---------|-------------|
694
698
  | `expandLevel` | `number \| null` | `2` | Automatically expand nodes up to this level |
695
699
  | `shouldToggleOnNodeClick` | `boolean` | `true` | Toggle expansion on node click |
696
- | `useFlatRendering` | `boolean` | `true` | Use flat rendering mode (faster for large trees) |
697
- | `progressiveRender` | `boolean` | `true` | Progressively render nodes in batches |
698
- | `renderBatchSize` | `number` | `50` | Number of nodes to render per batch |
699
700
  | `orderMember` | `string \| null` | `null` | Property name for sort order (enables above/below positioning in drag-drop) |
700
701
  | `indexerBatchSize` | `number \| null` | `25` | Number of nodes to process per batch during search indexing |
701
702
  | `indexerTimeout` | `number \| null` | `50` | Maximum time (ms) to wait for idle callback before forcing indexing |
702
- | `shouldDisplayDebugInformation` | `boolean` | `false` | Show debug information panel with tree statistics and enable console debug logging for tree operations and async search indexing |
703
+ | `shouldDisplayDebugInformation` | `boolean` | `false` | Show debug information panel with tree statistics and enable console debug logging |
703
704
  | `shouldDisplayContextMenuInDebugMode` | `boolean` | `false` | Display persistent context menu at fixed position for styling development |
704
705
 
706
+ #### Rendering Properties
707
+ | Prop | Type | Default | Description |
708
+ |------|------|---------|-------------|
709
+ | `useFlatRendering` | `boolean` | `true` | Use flat rendering mode (faster for large trees) |
710
+ | `progressiveRender` | `boolean` | `true` | Progressively render nodes in batches |
711
+ | `initialBatchSize` | `number` | `20` | First batch size for progressive rendering |
712
+ | `maxBatchSize` | `number` | `500` | Maximum batch size cap |
713
+
714
+ #### Drag & Drop Properties
715
+ | Prop | Type | Default | Description |
716
+ |------|------|---------|-------------|
717
+ | `dragDropMode` | `DragDropMode` | `'none'` | Controls allowed drag operations: `'none'`, `'self'`, `'cross'`, `'both'` |
718
+ | `dropZoneMode` | `string` | `'glow'` | Drop indicator style: `'floating'` or `'glow'` |
719
+ | `dropZoneLayout` | `string` | `'around'` | Zone arrangement: `'around'`, `'above'`, `'below'`, `'wave'`, `'wave2'` |
720
+ | `dropZoneStart` | `number \| string` | `33` | Where zones start horizontally (number=%, string=CSS value) |
721
+ | `dropZoneMaxWidth` | `number` | `120` | Max width in pixels for wave layouts |
722
+ | `allowCopy` | `boolean` | `false` | Enable Ctrl+drag to copy instead of move |
723
+ | `autoHandleCopy` | `boolean` | `true` | Auto-handle same-tree copies (false for external DB/API) |
724
+ | `allowedDropPositionsMember` | `string \| null` | `null` | Property name for allowed drop positions array |
725
+ | `getAllowedDropPositionsCallback` | `(node) => DropPosition[] \| null` | `undefined` | Callback returning allowed drop positions per node |
726
+ | `beforeDropCallback` | `(dropNode, draggedNode, position, event, operation) => ...` | `undefined` | Async-capable callback to validate/modify drops |
727
+
705
728
  #### Event Handler Properties
706
729
  | Prop | Type | Default | Description |
707
730
  |------|------|---------|-------------|
708
731
  | `onNodeClicked` | `(node) => void` | `undefined` | Node click event handler |
709
732
  | `onNodeDragStart` | `(node, event) => void` | `undefined` | Drag start event handler |
710
733
  | `onNodeDragOver` | `(node, event) => void` | `undefined` | Drag over event handler |
711
- | `getAllowedDropPositionsCallback` | `(node) => DropPosition[] \| null` | `undefined` | Callback returning allowed drop positions per node |
712
- | `beforeDropCallback` | `(dropNode, draggedNode, position, event, operation) => boolean \| { position?, operation? } \| Promise<...>` | `undefined` | Async-capable callback to validate/modify drops before they happen |
713
- | `onNodeDrop` | `(dropNode, draggedNode, position, event, operation) => void` | `undefined` | Drop event handler. Position is 'above', 'below', or 'child'. Operation is 'move' or 'copy' |
734
+ | `onNodeDrop` | `(dropNode, draggedNode, position, event, operation) => void` | `undefined` | Drop event handler. Position is `'above'`, `'below'`, or `'child'`. Operation is `'move'` or `'copy'` |
714
735
 
715
736
  #### Visual Styling Properties
716
737
  | Prop | Type | Default | Description |
@@ -724,15 +745,15 @@ Without both requirements, no search indexing will occur.
724
745
  | `scrollHighlightTimeout` | `number \| null` | `4000` | Duration (ms) for scroll highlight animation |
725
746
  | `scrollHighlightClass` | `string \| null` | `'ltree-scroll-highlight'` | CSS class to apply for scroll highlight effect |
726
747
 
727
- #### Available Slots
728
- | Slot | Description |
729
- |------|-------------|
730
- | `nodeTemplate` | Custom node template |
731
- | `treeHeader` | Tree header content |
732
- | `treeBody` | Tree body content |
733
- | `treeFooter` | Tree footer content |
734
- | `noDataFound` | No data template |
735
- | `contextMenu` | Context menu template |
748
+ #### Snippets
749
+ | Snippet | Parameters | Description |
750
+ |---------|------------|-------------|
751
+ | `nodeTemplate` | `(node)` | Custom node template |
752
+ | `treeHeader` | | Tree header content |
753
+ | `treeBody` | | Tree body content |
754
+ | `treeFooter` | | Tree footer content |
755
+ | `noDataFound` | | No data template |
756
+ | `contextMenu` | `(node, closeMenu)` | Context menu template |
736
757
 
737
758
  #### Public Methods
738
759
  | Method | Parameters | Description |
@@ -905,99 +926,7 @@ When enabled, the component will log detailed information to the browser console
905
926
 
906
927
  This provides valuable insights for performance optimization and troubleshooting, especially when working with large datasets or complex search operations.
907
928
 
908
- ### Events
909
-
910
- #### onNodeClicked(node)
911
- Triggered when a node is clicked.
912
-
913
- #### onNodeDragStart(node, event)
914
- Triggered when drag operation starts.
915
-
916
- #### onNodeDragOver(node, event)
917
- Triggered when dragging over a potential drop target.
918
-
919
- #### beforeDropCallback(dropNode, draggedNode, position, event, operation)
920
- Called before a drop is processed. Can be async for showing dialogs.
921
- - Return `false` to cancel the drop
922
- - Return `{ position: 'above'|'below'|'child' }` to override position
923
- - Return `{ operation: 'move'|'copy' }` to override operation
924
- - Return `true` or `undefined` to proceed normally
925
-
926
- #### onNodeDrop(dropNode, draggedNode, position, event, operation)
927
- Triggered when a node is dropped. For same-tree moves, the tree auto-handles the move and this callback is for notification.
928
- - `position`: 'above', 'below', or 'child'
929
- - `operation`: 'move' or 'copy' (Ctrl+drag)
930
-
931
- ### Slots
932
-
933
- #### nodeTemplate
934
- Custom template for rendering node content.
935
-
936
- ```svelte
937
- {#snippet nodeTemplate(node)}
938
- <!-- Your custom node content -->
939
- {/snippet}
940
- ```
941
-
942
- #### contextMenu
943
- Custom context menu template (snippet-based approach).
944
-
945
- ```svelte
946
- {#snippet contextMenu(node, closeMenu)}
947
- <button onclick={() => { /* action */ closeMenu(); }}>
948
- Action
949
- </button>
950
- {/snippet}
951
- ```
952
-
953
- ### Context Menu Properties
954
-
955
- #### contextMenuCallback
956
- Function that generates context menu items dynamically.
957
-
958
- ```typescript
959
- contextMenuCallback: (node: LTreeNode<T>) => ContextMenuItem[]
960
- ```
961
-
962
- Where `ContextMenuItem` is:
963
- ```typescript
964
- interface ContextMenuItem {
965
- icon?: string; // Optional icon (emoji or text)
966
- title: string; // Menu item text
967
- isDisabled?: boolean; // Whether item is disabled
968
- callback: () => void; // Action to perform
969
- isDivider?: boolean; // Render as divider instead of item
970
- }
971
- ```
972
-
973
- #### contextMenuXOffset
974
- Horizontal offset from cursor position (default: 8px).
975
-
976
- #### contextMenuYOffset
977
- Vertical offset from cursor position (default: 0px).
978
-
979
- #### shouldDisplayContextMenuInDebugMode
980
- When enabled, displays a persistent context menu at a fixed position for styling development (default: false).
981
-
982
- ```svelte
983
- <Tree
984
- {data}
985
- contextMenuCallback={createContextMenu}
986
- shouldDisplayContextMenuInDebugMode={true}
987
- shouldDisplayDebugInformation={true}
988
- contextMenuXOffset={10}
989
- contextMenuYOffset={5}
990
- />
991
- ```
992
-
993
- **Debug Mode Features:**
994
- - Shows context menu for the second node (or first if only one exists)
995
- - Positions menu 200px right and 100px down from tree's top-left corner
996
- - Persistent display - no need to right-click repeatedly
997
- - Perfect for CSS styling and position testing
998
- - Works with both callback-based and snippet-based context menus
999
-
1000
- ## 🏗️ Data Structure
929
+ ## Data Structure
1001
930
 
1002
931
  The component expects hierarchical data with path-based organization:
1003
932
 
@@ -1057,21 +986,21 @@ interface InsertArrayResult<T> {
1057
986
  ```svelte
1058
987
  <script lang="ts">
1059
988
  import { Tree } from '@keenmate/svelte-treeview';
1060
-
989
+
1061
990
  let insertResult = $state();
1062
-
991
+
1063
992
  const data = [
1064
993
  { id: '1', path: '1', name: 'Root' },
1065
994
  { id: '1.2', path: '1.2', name: 'Child' }, // Missing parent "1.1"
1066
995
  { id: '1.1.1', path: '1.1.1', name: 'Deep' } // Missing parent "1.1"
1067
996
  ];
1068
-
997
+
1069
998
  // Check results after tree processes data
1070
999
  $effect(() => {
1071
1000
  if (insertResult) {
1072
- console.log(`✅ ${insertResult.successful} nodes inserted successfully`);
1073
- console.log(`❌ ${insertResult.failed.length} nodes failed to insert`);
1074
-
1001
+ console.log(`${insertResult.successful} nodes inserted successfully`);
1002
+ console.log(`${insertResult.failed.length} nodes failed to insert`);
1003
+
1075
1004
  insertResult.failed.forEach(failure => {
1076
1005
  console.log(`Failed: ${failure.originalData.name} - ${failure.error}`);
1077
1006
  });
@@ -1079,10 +1008,10 @@ interface InsertArrayResult<T> {
1079
1008
  });
1080
1009
  </script>
1081
1010
 
1082
- <Tree
1083
- {data}
1084
- idMember="id"
1085
- pathMember="path"
1011
+ <Tree
1012
+ {data}
1013
+ idMember="id"
1014
+ pathMember="path"
1086
1015
  displayValueMember="name"
1087
1016
  bind:insertResult
1088
1017
  />
@@ -1096,7 +1025,7 @@ interface InsertArrayResult<T> {
1096
1025
  - **Search Accuracy**: Failed nodes are excluded from search index, ensuring search results match visible tree
1097
1026
  - **User Feedback**: Inform users about data issues with detailed failure information
1098
1027
 
1099
- ## 🚀 Performance
1028
+ ## Performance
1100
1029
 
1101
1030
  The component is optimized for large datasets:
1102
1031
 
@@ -1138,20 +1067,34 @@ enablePerfLogging();
1138
1067
  window.components['svelte-treeview'].perf.enable()
1139
1068
  ```
1140
1069
 
1141
- **Important**: See the [$state.raw() warning](#%EF%B8%8F-performance-warning-use-stateraw-for-large-datasets) above - using `$state()` instead of `$state.raw()` for tree data can cause 5,000x slowdown!
1070
+ **Important**: See the [$state.raw() tip](#quick-start) above - using `$state()` instead of `$state.raw()` for tree data can cause 5,000x slowdown!
1071
+
1072
+ ## Development Setup & Contributing
1142
1073
 
1143
- ## 🤝 Contributing
1074
+ For developers working on the project, you can use either standard npm commands or the provided Makefile:
1075
+
1076
+ ```bash
1077
+ # Using Makefile (recommended for consistency)
1078
+ make setup # or make install
1079
+ make dev
1080
+
1081
+ # Or using standard npm commands
1082
+ npm install
1083
+ npm run dev
1084
+ ```
1144
1085
 
1145
1086
  We welcome contributions! Please see our contributing guidelines for details.
1146
1087
 
1147
- ## 📄 License
1088
+ > **For AI Agents / LLMs**: Comprehensive documentation is available in the `ai/` folder with topic-specific files (basic-setup.txt, drag-drop.txt, performance.txt, etc.). Start with `ai/INDEX.txt` for navigation.
1089
+
1090
+ ## License
1148
1091
 
1149
1092
  MIT License - see LICENSE file for details.
1150
1093
 
1151
- ## 🆘 Support
1094
+ ## Support
1152
1095
 
1153
1096
  - **GitHub Issues**: [Report bugs or request features](https://github.com/keenmate/svelte-treeview/issues)
1154
- - **Documentation**: [Full documentation](https://github.com/keenmate/svelte-treeview#readme)
1097
+ - **Live demo & docs**: [svelte-treeview.keenmate.dev](https://svelte-treeview.keenmate.dev)
1155
1098
 
1156
1099
  ---
1157
1100