@keenmate/svelte-treeview 4.8.0 → 5.0.0-rc02
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 +106 -117
- package/ai/INDEX.txt +310 -0
- package/ai/advanced-patterns.txt +506 -0
- package/ai/basic-setup.txt +336 -0
- package/ai/context-menu.txt +349 -0
- package/ai/data-handling.txt +390 -0
- package/ai/drag-drop.txt +397 -0
- package/ai/events-callbacks.txt +382 -0
- package/ai/import-patterns.txt +271 -0
- package/ai/performance.txt +349 -0
- package/ai/search-features.txt +359 -0
- package/ai/styling-theming.txt +354 -0
- package/ai/tree-editing.txt +423 -0
- package/ai/typescript-types.txt +357 -0
- package/dist/components/Node.svelte +47 -40
- package/dist/components/Node.svelte.d.ts +1 -1
- package/dist/components/Tree.svelte +384 -1479
- package/dist/components/Tree.svelte.d.ts +30 -28
- package/dist/components/TreeProvider.svelte +28 -0
- package/dist/components/TreeProvider.svelte.d.ts +28 -0
- package/dist/constants.generated.d.ts +1 -1
- package/dist/constants.generated.js +1 -1
- package/dist/core/TreeController.svelte.d.ts +353 -0
- package/dist/core/TreeController.svelte.js +1503 -0
- package/dist/core/createTreeController.d.ts +9 -0
- package/dist/core/createTreeController.js +11 -0
- package/dist/global-api.d.ts +1 -1
- package/dist/global-api.js +5 -5
- package/dist/index.d.ts +10 -6
- package/dist/index.js +7 -3
- package/dist/logger.d.ts +7 -6
- package/dist/logger.js +0 -2
- package/dist/ltree/indexer.js +2 -4
- package/dist/ltree/ltree-node.svelte.d.ts +2 -1
- package/dist/ltree/ltree-node.svelte.js +1 -0
- package/dist/ltree/ltree.svelte.d.ts +1 -1
- package/dist/ltree/ltree.svelte.js +168 -175
- package/dist/ltree/types.d.ts +12 -8
- package/dist/perf-logger.d.ts +2 -1
- package/dist/perf-logger.js +0 -2
- package/dist/styles/main.scss +78 -78
- package/dist/styles.css +41 -41
- package/dist/styles.css.map +1 -1
- package/dist/vendor/loglevel/index.d.ts +55 -2
- package/dist/vendor/loglevel/prefix.d.ts +23 -2
- package/package.json +96 -95
- package/dist/ltree/ltree-demo.d.ts +0 -2
- package/dist/ltree/ltree-demo.js +0 -90
- package/dist/vendor/loglevel/loglevel-esm.d.ts +0 -2
- package/dist/vendor/loglevel/loglevel-plugin-prefix-esm.d.ts +0 -7
- package/dist/vendor/loglevel/loglevel-plugin-prefix.d.ts +0 -2
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
STYLING AND THEMING
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
CRITICAL: Styles must be imported separately
|
|
5
|
+
- Component has no embedded styles
|
|
6
|
+
- Import CSS or SCSS
|
|
7
|
+
- Extensive CSS variables for theming
|
|
8
|
+
|
|
9
|
+
IMPORT STYLES
|
|
10
|
+
-------------
|
|
11
|
+
// CSS (compiled)
|
|
12
|
+
import '@keenmate/svelte-treeview/styles.css';
|
|
13
|
+
|
|
14
|
+
// SCSS (with variable overrides)
|
|
15
|
+
import '@keenmate/svelte-treeview/styles.scss';
|
|
16
|
+
|
|
17
|
+
CSS VARIABLES
|
|
18
|
+
-------------
|
|
19
|
+
Override in your CSS:
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
/* Indentation */
|
|
23
|
+
--tree-node-indent-per-level: 0.5rem;
|
|
24
|
+
|
|
25
|
+
/* Colors */
|
|
26
|
+
--ltree-primary: #0d6efd;
|
|
27
|
+
--ltree-primary-rgb: 13, 110, 253;
|
|
28
|
+
--ltree-success: #198754;
|
|
29
|
+
--ltree-success-rgb: 25, 135, 84;
|
|
30
|
+
--ltree-danger: #dc3545;
|
|
31
|
+
--ltree-danger-rgb: 220, 53, 69;
|
|
32
|
+
--ltree-light: #f8f9fa;
|
|
33
|
+
--ltree-border: #dee2e6;
|
|
34
|
+
--ltree-body-color: #212529;
|
|
35
|
+
|
|
36
|
+
/* Touch ghost */
|
|
37
|
+
--tree-ghost-bg: rgba(59, 130, 246, 0.9);
|
|
38
|
+
--tree-ghost-color: white;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
SCSS VARIABLES
|
|
42
|
+
--------------
|
|
43
|
+
Override BEFORE importing:
|
|
44
|
+
|
|
45
|
+
<style lang="scss">
|
|
46
|
+
// Override variables
|
|
47
|
+
$tree-node-indent-per-level: 1rem;
|
|
48
|
+
$ltree-primary: #6366f1;
|
|
49
|
+
$tree-node-font-family: 'Inter', sans-serif;
|
|
50
|
+
|
|
51
|
+
// Then import
|
|
52
|
+
@import '@keenmate/svelte-treeview/styles.scss';
|
|
53
|
+
</style>
|
|
54
|
+
|
|
55
|
+
Available SCSS variables:
|
|
56
|
+
- $tree-node-indent-per-level
|
|
57
|
+
- $tree-node-font-family
|
|
58
|
+
- $tree-node-content-border-radius
|
|
59
|
+
- $ltree-primary, $ltree-success, $ltree-danger
|
|
60
|
+
- $drop-zone-* variables (see below)
|
|
61
|
+
|
|
62
|
+
SELECTED NODE CLASSES
|
|
63
|
+
---------------------
|
|
64
|
+
<Tree selectedNodeClass="ltree-selected-bold" />
|
|
65
|
+
|
|
66
|
+
Built-in classes:
|
|
67
|
+
- ltree-selected-bold - Bold text with primary color
|
|
68
|
+
- ltree-selected-border - Border and background highlight
|
|
69
|
+
- ltree-selected-brackets - Decorative brackets ❯ Node ❮
|
|
70
|
+
|
|
71
|
+
Custom selected style:
|
|
72
|
+
.my-selected {
|
|
73
|
+
background: #e0f2fe;
|
|
74
|
+
border-left: 3px solid #0284c7;
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
<Tree selectedNodeClass="my-selected" />
|
|
79
|
+
|
|
80
|
+
DRAG-OVER CLASSES
|
|
81
|
+
-----------------
|
|
82
|
+
<Tree dragOverNodeClass="ltree-dragover-glow" />
|
|
83
|
+
|
|
84
|
+
Built-in classes:
|
|
85
|
+
- ltree-dragover-highlight - Dashed border with background
|
|
86
|
+
- ltree-dragover-glow - Shadow glow effect
|
|
87
|
+
|
|
88
|
+
Custom drag-over style:
|
|
89
|
+
.my-drag-over {
|
|
90
|
+
outline: 2px dashed #3b82f6;
|
|
91
|
+
outline-offset: 2px;
|
|
92
|
+
background: rgba(59, 130, 246, 0.1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
<Tree dragOverNodeClass="my-drag-over" />
|
|
96
|
+
|
|
97
|
+
ICON CLASSES
|
|
98
|
+
------------
|
|
99
|
+
<Tree
|
|
100
|
+
expandIconClass="ltree-icon-expand"
|
|
101
|
+
collapseIconClass="ltree-icon-collapse"
|
|
102
|
+
leafIconClass="ltree-icon-leaf"
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
Custom icons with CSS:
|
|
106
|
+
.my-expand::before { content: '▶'; }
|
|
107
|
+
.my-collapse::before { content: '▼'; }
|
|
108
|
+
.my-leaf::before { content: '•'; }
|
|
109
|
+
|
|
110
|
+
<Tree
|
|
111
|
+
expandIconClass="my-expand"
|
|
112
|
+
collapseIconClass="my-collapse"
|
|
113
|
+
leafIconClass="my-leaf"
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
SCROLL HIGHLIGHT CLASSES
|
|
117
|
+
------------------------
|
|
118
|
+
<Tree
|
|
119
|
+
scrollHighlightClass="ltree-scroll-highlight"
|
|
120
|
+
scrollHighlightTimeout={4000}
|
|
121
|
+
/>
|
|
122
|
+
|
|
123
|
+
Built-in classes:
|
|
124
|
+
- ltree-scroll-highlight - Blue background glow
|
|
125
|
+
- ltree-scroll-highlight-arrow - Red arrow indicator
|
|
126
|
+
|
|
127
|
+
Custom highlight:
|
|
128
|
+
.my-highlight {
|
|
129
|
+
animation: pulse 0.5s ease-in-out 3;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@keyframes pulse {
|
|
133
|
+
0%, 100% { background: transparent; }
|
|
134
|
+
50% { background: #fef08a; }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
<Tree scrollHighlightClass="my-highlight" />
|
|
138
|
+
|
|
139
|
+
DROP ZONE STYLING
|
|
140
|
+
-----------------
|
|
141
|
+
SCSS variables for drop zones:
|
|
142
|
+
|
|
143
|
+
// Border radius
|
|
144
|
+
$drop-zone-border-radius: 4px;
|
|
145
|
+
|
|
146
|
+
// Before zone
|
|
147
|
+
$drop-zone-before-bg: rgba(134, 239, 172, 0.25);
|
|
148
|
+
$drop-zone-before-color: #166534;
|
|
149
|
+
$drop-zone-before-active-bg: rgba(134, 239, 172, 0.85);
|
|
150
|
+
$drop-zone-before-active-color: #14532d;
|
|
151
|
+
$drop-zone-before-active-shadow: 0 2px 8px rgba(34, 197, 94, 0.4);
|
|
152
|
+
|
|
153
|
+
// After zone
|
|
154
|
+
$drop-zone-after-bg: rgba(253, 186, 116, 0.25);
|
|
155
|
+
$drop-zone-after-color: #9a3412;
|
|
156
|
+
$drop-zone-after-active-bg: rgba(253, 186, 116, 0.85);
|
|
157
|
+
$drop-zone-after-active-color: #7c2d12;
|
|
158
|
+
$drop-zone-after-active-shadow: 0 2px 8px rgba(249, 115, 22, 0.4);
|
|
159
|
+
|
|
160
|
+
// Child zone
|
|
161
|
+
$drop-zone-child-bg: rgba(196, 181, 253, 0.25);
|
|
162
|
+
$drop-zone-child-color: #5b21b6;
|
|
163
|
+
$drop-zone-child-active-bg: rgba(196, 181, 253, 0.85);
|
|
164
|
+
$drop-zone-child-active-color: #4c1d95;
|
|
165
|
+
$drop-zone-child-active-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);
|
|
166
|
+
|
|
167
|
+
// Arrow indicators
|
|
168
|
+
$drop-arrow-size: 24px;
|
|
169
|
+
$drop-arrow-position: 66%;
|
|
170
|
+
|
|
171
|
+
GLOW MODE STYLING
|
|
172
|
+
-----------------
|
|
173
|
+
CSS classes for glow indicators:
|
|
174
|
+
|
|
175
|
+
.ltree-glow-before {
|
|
176
|
+
border-top: 3px solid #22c55e;
|
|
177
|
+
box-shadow: 0 -4px 8px rgba(34, 197, 94, 0.3);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.ltree-glow-after {
|
|
181
|
+
border-bottom: 3px solid #f97316;
|
|
182
|
+
box-shadow: 0 4px 8px rgba(249, 115, 22, 0.3);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.ltree-glow-child {
|
|
186
|
+
border: 3px solid #8b5cf6;
|
|
187
|
+
box-shadow: 0 0 12px rgba(139, 92, 246, 0.4);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
CONTEXT MENU STYLING
|
|
191
|
+
--------------------
|
|
192
|
+
.ltree-context-menu {
|
|
193
|
+
background: white;
|
|
194
|
+
border: 1px solid #e5e7eb;
|
|
195
|
+
border-radius: 8px;
|
|
196
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
197
|
+
padding: 4px;
|
|
198
|
+
min-width: 160px;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.ltree-context-menu-item {
|
|
202
|
+
display: flex;
|
|
203
|
+
align-items: center;
|
|
204
|
+
padding: 8px 12px;
|
|
205
|
+
border-radius: 4px;
|
|
206
|
+
cursor: pointer;
|
|
207
|
+
gap: 8px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.ltree-context-menu-item:hover {
|
|
211
|
+
background: #f3f4f6;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.ltree-context-menu-item-disabled {
|
|
215
|
+
opacity: 0.5;
|
|
216
|
+
cursor: not-allowed;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.ltree-context-menu-divider {
|
|
220
|
+
height: 1px;
|
|
221
|
+
background: #e5e7eb;
|
|
222
|
+
margin: 4px 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
TOUCH GHOST STYLING
|
|
226
|
+
-------------------
|
|
227
|
+
.ltree-touch-ghost {
|
|
228
|
+
background: var(--tree-ghost-bg, rgba(59, 130, 246, 0.9));
|
|
229
|
+
color: var(--tree-ghost-color, white);
|
|
230
|
+
padding: 8px 16px;
|
|
231
|
+
border-radius: 6px;
|
|
232
|
+
font-size: 14px;
|
|
233
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
CSS CLASS REFERENCE
|
|
237
|
+
-------------------
|
|
238
|
+
Tree structure:
|
|
239
|
+
- .ltree-tree - Main container
|
|
240
|
+
- .ltree-tree-body - Tree body
|
|
241
|
+
- .ltree-node - Node container
|
|
242
|
+
- .ltree-node-row - Node row wrapper
|
|
243
|
+
- .ltree-node-content - Node content area
|
|
244
|
+
- .ltree-toggle-icon - Expand/collapse icon
|
|
245
|
+
- .ltree-children - Children container
|
|
246
|
+
|
|
247
|
+
States:
|
|
248
|
+
- .ltree-expanded - Expanded node
|
|
249
|
+
- .ltree-collapsed - Collapsed node
|
|
250
|
+
- .ltree-selected - Selected node
|
|
251
|
+
- .ltree-draggable - Draggable node
|
|
252
|
+
- .ltree-drag-over - Drop target during drag
|
|
253
|
+
|
|
254
|
+
Drop zones:
|
|
255
|
+
- .ltree-drop-zones - Drop zone container
|
|
256
|
+
- .ltree-drop-zone - Individual drop zone
|
|
257
|
+
- .ltree-drop-before - Before position
|
|
258
|
+
- .ltree-drop-after - After position
|
|
259
|
+
- .ltree-drop-child - Child position
|
|
260
|
+
- .ltree-drop-copy - Copy operation active
|
|
261
|
+
|
|
262
|
+
Context menu:
|
|
263
|
+
- .ltree-context-menu - Menu container
|
|
264
|
+
- .ltree-context-menu-item - Menu item
|
|
265
|
+
- .ltree-context-menu-icon - Item icon
|
|
266
|
+
- .ltree-context-menu-divider - Divider
|
|
267
|
+
|
|
268
|
+
Empty/loading:
|
|
269
|
+
- .ltree-empty-state - Empty tree state
|
|
270
|
+
- .ltree-drop-placeholder - Drop placeholder
|
|
271
|
+
|
|
272
|
+
BODY CLASS
|
|
273
|
+
----------
|
|
274
|
+
<Tree bodyClass="my-tree-body" />
|
|
275
|
+
|
|
276
|
+
Adds class to tree body element for scoped styling:
|
|
277
|
+
|
|
278
|
+
.my-tree-body .ltree-node-content {
|
|
279
|
+
padding: 4px 8px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
DARK THEME EXAMPLE
|
|
283
|
+
------------------
|
|
284
|
+
.dark-theme {
|
|
285
|
+
--ltree-body-color: #e5e7eb;
|
|
286
|
+
--ltree-border: #374151;
|
|
287
|
+
--ltree-light: #1f2937;
|
|
288
|
+
--ltree-primary: #60a5fa;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.dark-theme .ltree-tree {
|
|
292
|
+
background: #111827;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.dark-theme .ltree-node-content:hover {
|
|
296
|
+
background: #1f2937;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.dark-theme .ltree-context-menu {
|
|
300
|
+
background: #1f2937;
|
|
301
|
+
border-color: #374151;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
INDENTATION
|
|
305
|
+
-----------
|
|
306
|
+
Control node indentation:
|
|
307
|
+
|
|
308
|
+
:root {
|
|
309
|
+
--tree-node-indent-per-level: 1rem;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
Each level gets this fixed indent.
|
|
313
|
+
Level 1 = 1rem, Level 2 = 2rem, etc.
|
|
314
|
+
|
|
315
|
+
NODE TEMPLATE STYLING
|
|
316
|
+
---------------------
|
|
317
|
+
<Tree {data}>
|
|
318
|
+
{#snippet nodeTemplate(node)}
|
|
319
|
+
<div class="custom-node">
|
|
320
|
+
<span class="icon">{node.data.icon}</span>
|
|
321
|
+
<span class="name">{node.data.name}</span>
|
|
322
|
+
<span class="badge">{node.data.count}</span>
|
|
323
|
+
</div>
|
|
324
|
+
{/snippet}
|
|
325
|
+
</Tree>
|
|
326
|
+
|
|
327
|
+
<style>
|
|
328
|
+
.custom-node {
|
|
329
|
+
display: flex;
|
|
330
|
+
align-items: center;
|
|
331
|
+
gap: 8px;
|
|
332
|
+
}
|
|
333
|
+
.icon { font-size: 1.2em; }
|
|
334
|
+
.name { flex: 1; }
|
|
335
|
+
.badge {
|
|
336
|
+
background: #e5e7eb;
|
|
337
|
+
padding: 2px 6px;
|
|
338
|
+
border-radius: 9999px;
|
|
339
|
+
font-size: 0.75em;
|
|
340
|
+
}
|
|
341
|
+
</style>
|
|
342
|
+
|
|
343
|
+
BEST PRACTICES
|
|
344
|
+
--------------
|
|
345
|
+
✅ Import styles at app level (once)
|
|
346
|
+
✅ Use CSS variables for theming
|
|
347
|
+
✅ Override SCSS variables before import
|
|
348
|
+
✅ Use built-in classes when possible
|
|
349
|
+
✅ Scope custom styles properly
|
|
350
|
+
|
|
351
|
+
❌ Don't import styles multiple times
|
|
352
|
+
❌ Don't override built-in classes globally
|
|
353
|
+
❌ Don't use !important unless necessary
|
|
354
|
+
❌ Don't forget to test dark mode
|