@keenmate/svelte-treeview 4.5.0 → 4.7.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 +247 -45
- package/dist/components/Node.svelte +136 -136
- package/dist/components/Node.svelte.d.ts +3 -22
- package/dist/components/Tree.svelte +341 -41
- package/dist/components/Tree.svelte.d.ts +64 -7
- package/dist/constants.generated.d.ts +1 -1
- package/dist/constants.generated.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/ltree/indexer.js +2 -1
- package/dist/ltree/ltree-node.svelte.d.ts +2 -0
- package/dist/ltree/ltree-node.svelte.js +1 -0
- package/dist/ltree/ltree.svelte.d.ts +1 -1
- package/dist/ltree/ltree.svelte.js +87 -6
- package/dist/ltree/types.d.ts +7 -3
- package/package.json +1 -1
|
@@ -4,102 +4,73 @@
|
|
|
4
4
|
import {getContext, onDestroy, type Snippet} from "svelte"
|
|
5
5
|
import type {Ltree, DropPosition, DropOperation} from "../ltree/types.js"
|
|
6
6
|
import type {RenderCoordinator} from "./RenderCoordinator.svelte.js"
|
|
7
|
+
import type {NodeCallbacks, NodeConfig} from "./Tree.svelte"
|
|
7
8
|
import { uiLogger } from "../logger.js"
|
|
8
9
|
|
|
9
10
|
// Define component props interface
|
|
11
|
+
// Callbacks and config come from context, drag state comes as props
|
|
10
12
|
interface Props {
|
|
11
13
|
node: LTreeNode<T>;
|
|
12
14
|
children?: Snippet<[T]>; // Keep the general children slot for backward compatibility
|
|
13
|
-
onNodeClicked?: (node: LTreeNode<T>) => void;
|
|
14
|
-
onNodeRightClicked?: (node: LTreeNode<T>, event: MouseEvent) => void;
|
|
15
|
-
onNodeDragStart?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
16
|
-
onNodeDragOver?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
17
|
-
onNodeDragLeave?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
18
|
-
onNodeDrop?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
19
|
-
onZoneDrop?: (node: LTreeNode<T>, position: DropPosition, event: DragEvent) => void;
|
|
20
|
-
|
|
21
|
-
// Touch drag handlers for mobile support
|
|
22
|
-
onTouchDragStart?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
23
|
-
onTouchDragMove?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
24
|
-
onTouchDragEnd?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
25
|
-
|
|
26
|
-
// BEHAVIOUR
|
|
27
|
-
shouldToggleOnNodeClick?: boolean | null | undefined;
|
|
28
15
|
|
|
29
16
|
// Progressive rendering
|
|
30
17
|
progressiveRender?: boolean;
|
|
31
18
|
renderBatchSize?: number;
|
|
32
19
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
collapseIconClass?: string | null | undefined;
|
|
36
|
-
leafIconClass?: string | null | undefined;
|
|
37
|
-
selectedNodeClass?: string | null | undefined;
|
|
38
|
-
dragOverNodeClass?: string | null | undefined;
|
|
39
|
-
isDraggedNode?: boolean | null | undefined;
|
|
40
|
-
|
|
41
|
-
// Drag position indicators
|
|
20
|
+
// Drag state (passed as props for efficient Svelte diffing)
|
|
21
|
+
isDraggedNode?: boolean;
|
|
42
22
|
isDragInProgress?: boolean;
|
|
43
|
-
hoveredNodeForDropPath?: string | null;
|
|
23
|
+
hoveredNodeForDropPath?: string | null;
|
|
44
24
|
activeDropPosition?: DropPosition | null;
|
|
25
|
+
dropOperation?: DropOperation;
|
|
45
26
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
dropZoneStart?: number | string; // number = percentage (0-100), string = any CSS value ("33%", "50px", "3rem")
|
|
50
|
-
dropZoneMaxWidth?: number; // max width in pixels for wave layouts
|
|
51
|
-
dropOperation?: DropOperation; // Current drag operation ('move' or 'copy')
|
|
52
|
-
allowCopy?: boolean; // Whether copy operation is allowed (Ctrl+drag)
|
|
27
|
+
// Flat rendering mode
|
|
28
|
+
flatMode?: boolean; // When true, don't render children (Tree handles flat rendering)
|
|
29
|
+
flatIndentSize?: string; // CSS value for per-level indentation in flat mode
|
|
53
30
|
}
|
|
54
31
|
|
|
55
32
|
// Destructure props using Svelte 5 syntax
|
|
56
33
|
let {
|
|
57
34
|
node,
|
|
58
35
|
children = undefined,
|
|
59
|
-
onNodeClicked,
|
|
60
|
-
onNodeRightClicked,
|
|
61
|
-
onNodeDragStart,
|
|
62
|
-
onNodeDragOver,
|
|
63
|
-
onNodeDragLeave,
|
|
64
|
-
onNodeDrop,
|
|
65
|
-
onZoneDrop,
|
|
66
|
-
|
|
67
|
-
// Touch drag handlers for mobile support
|
|
68
|
-
onTouchDragStart,
|
|
69
|
-
onTouchDragMove,
|
|
70
|
-
onTouchDragEnd,
|
|
71
|
-
|
|
72
|
-
// BEHAVIOUR
|
|
73
|
-
shouldToggleOnNodeClick = true,
|
|
74
36
|
|
|
75
37
|
// Progressive rendering
|
|
76
38
|
progressiveRender = false,
|
|
77
39
|
renderBatchSize = 50,
|
|
78
40
|
|
|
79
|
-
//
|
|
80
|
-
expandIconClass = "ltree-icon-expand",
|
|
81
|
-
collapseIconClass = "ltree-icon-collapse",
|
|
82
|
-
leafIconClass = "ltree-icon-leaf",
|
|
83
|
-
selectedNodeClass,
|
|
84
|
-
dragOverNodeClass,
|
|
41
|
+
// Drag state
|
|
85
42
|
isDraggedNode = false,
|
|
86
|
-
|
|
87
|
-
// Drag position indicators
|
|
88
43
|
isDragInProgress = false,
|
|
89
44
|
hoveredNodeForDropPath = null,
|
|
90
45
|
activeDropPosition = null,
|
|
91
|
-
|
|
92
|
-
// Drop zone configuration
|
|
93
|
-
dropZoneMode = 'glow',
|
|
94
|
-
dropZoneLayout = 'around',
|
|
95
|
-
dropZoneStart = 33,
|
|
96
|
-
dropZoneMaxWidth = 120,
|
|
97
46
|
dropOperation = 'move',
|
|
98
|
-
|
|
47
|
+
|
|
48
|
+
// Flat rendering mode
|
|
49
|
+
flatMode = false,
|
|
50
|
+
flatIndentSize = '1.5rem',
|
|
99
51
|
}: Props = $props()
|
|
100
52
|
|
|
53
|
+
// Get stable references from context (avoids prop drilling and re-renders from inline functions)
|
|
54
|
+
const callbacks = getContext<NodeCallbacks<T>>('NodeCallbacks');
|
|
55
|
+
const config = getContext<NodeConfig>('NodeConfig');
|
|
56
|
+
|
|
57
|
+
// Destructure config for convenience (these are stable references)
|
|
58
|
+
const {
|
|
59
|
+
shouldToggleOnNodeClick,
|
|
60
|
+
expandIconClass,
|
|
61
|
+
collapseIconClass,
|
|
62
|
+
leafIconClass,
|
|
63
|
+
selectedNodeClass,
|
|
64
|
+
dragOverNodeClass,
|
|
65
|
+
dropZoneMode,
|
|
66
|
+
dropZoneLayout,
|
|
67
|
+
dropZoneStart,
|
|
68
|
+
dropZoneMaxWidth,
|
|
69
|
+
allowCopy,
|
|
70
|
+
} = config;
|
|
71
|
+
|
|
101
72
|
// Compute if THIS node is the one being hovered for drop
|
|
102
|
-
const isHoveredForDrop = $derived(hoveredNodeForDropPath === node.path)
|
|
73
|
+
const isHoveredForDrop = $derived(hoveredNodeForDropPath === node.path);
|
|
103
74
|
|
|
104
75
|
// Format dropZoneStart - number = percentage, string = as-is
|
|
105
76
|
const formattedDropZoneStart = $derived(
|
|
@@ -118,53 +89,96 @@
|
|
|
118
89
|
// Track glow position for glow mode
|
|
119
90
|
let glowPosition = $state<'above' | 'below' | 'child' | null>(null);
|
|
120
91
|
|
|
92
|
+
// Get allowed drop positions for this node (empty/undefined = all allowed)
|
|
93
|
+
// Uses tree.getNodeAllowedDropPositions which checks callback > member > node property
|
|
94
|
+
const allowedPositions = $derived(tree.getNodeAllowedDropPositions(node));
|
|
95
|
+
|
|
96
|
+
// Check if a position is allowed for this node
|
|
97
|
+
function isPositionAllowed(position: DropPosition): boolean {
|
|
98
|
+
if (!allowedPositions || allowedPositions.length === 0) {
|
|
99
|
+
return true; // All positions allowed by default
|
|
100
|
+
}
|
|
101
|
+
return allowedPositions.includes(position);
|
|
102
|
+
}
|
|
103
|
+
|
|
121
104
|
// Calculate glow position based on mouse position in the node row
|
|
122
|
-
|
|
105
|
+
// Respects allowedDropPositions - snaps to nearest allowed position
|
|
106
|
+
function calculateGlowPosition(event: DragEvent, element: HTMLElement): 'above' | 'below' | 'child' | null {
|
|
123
107
|
const rect = element.getBoundingClientRect();
|
|
124
108
|
const x = event.clientX - rect.left;
|
|
125
109
|
const y = event.clientY - rect.top;
|
|
126
110
|
const width = rect.width;
|
|
127
111
|
const height = rect.height;
|
|
128
112
|
|
|
129
|
-
//
|
|
113
|
+
// Calculate the ideal position based on mouse position
|
|
114
|
+
let idealPosition: DropPosition;
|
|
130
115
|
if (x > width / 2) {
|
|
131
|
-
|
|
116
|
+
idealPosition = 'child';
|
|
117
|
+
} else if (y < height / 2) {
|
|
118
|
+
idealPosition = 'above';
|
|
119
|
+
} else {
|
|
120
|
+
idealPosition = 'below';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// If no restrictions, return the ideal position
|
|
124
|
+
if (!allowedPositions || allowedPositions.length === 0) {
|
|
125
|
+
return idealPosition;
|
|
132
126
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
|
|
128
|
+
// If the ideal position is allowed, use it
|
|
129
|
+
if (allowedPositions.includes(idealPosition)) {
|
|
130
|
+
return idealPosition;
|
|
136
131
|
}
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
|
|
133
|
+
// Otherwise, snap to the nearest allowed position
|
|
134
|
+
// Priority: if only one position allowed, use that
|
|
135
|
+
if (allowedPositions.length === 1) {
|
|
136
|
+
return allowedPositions[0];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Multiple positions allowed but not the ideal one
|
|
140
|
+
// For above/below: pick based on Y position
|
|
141
|
+
// For child: pick based on what's available
|
|
142
|
+
if (allowedPositions.includes('above') && allowedPositions.includes('below')) {
|
|
143
|
+
// Both above and below allowed, pick based on Y
|
|
144
|
+
return y < height / 2 ? 'above' : 'below';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Return the first allowed position
|
|
148
|
+
return allowedPositions[0];
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
// Convert reactive statements to derived values
|
|
142
|
-
|
|
143
|
-
const
|
|
152
|
+
// In flat mode, children rendering is handled by Tree.svelte, so we skip these computations
|
|
153
|
+
const childrenArray = $derived(!flatMode ? Object.values(node?.children || []) : [])
|
|
144
154
|
const hasChildren = $derived(node?.hasChildren || false)
|
|
145
155
|
const indentStyle = $derived(
|
|
146
|
-
|
|
156
|
+
flatMode
|
|
157
|
+
? `margin-left: calc(${(node?.level || 1) - 1} * ${flatIndentSize})`
|
|
158
|
+
: `margin-left: var(--tree-node-indent-per-level, 0.5rem)`,
|
|
147
159
|
)
|
|
148
160
|
|
|
149
|
-
// Progressive rendering state
|
|
161
|
+
// Progressive rendering state - only used in recursive mode
|
|
150
162
|
let renderedCount = $state(0);
|
|
151
163
|
let unregisterFromCoordinator: (() => void) | null = null;
|
|
152
164
|
let lastExpandedState = false;
|
|
153
165
|
let lastChildrenLength = 0;
|
|
154
166
|
|
|
155
|
-
// Get the children to render (all or progressive slice)
|
|
167
|
+
// Get the children to render (all or progressive slice) - only used in recursive mode
|
|
156
168
|
const childrenToRender = $derived(
|
|
157
|
-
progressiveRender && renderCoordinator
|
|
169
|
+
!flatMode && progressiveRender && renderCoordinator
|
|
158
170
|
? childrenArray.slice(0, renderedCount)
|
|
159
171
|
: childrenArray
|
|
160
172
|
);
|
|
161
173
|
const hasMoreToRender = $derived(
|
|
162
|
-
progressiveRender && renderCoordinator && renderedCount < childrenArray.length
|
|
174
|
+
!flatMode && progressiveRender && renderCoordinator && renderedCount < childrenArray.length
|
|
163
175
|
);
|
|
164
176
|
|
|
165
177
|
// Handle expansion state changes - use coordinator for progressive rendering
|
|
166
|
-
//
|
|
178
|
+
// Skip entirely in flat mode since Tree.svelte handles children rendering
|
|
167
179
|
$effect(() => {
|
|
180
|
+
if (flatMode) return; // Skip in flat mode - children handled by Tree
|
|
181
|
+
|
|
168
182
|
const isExpanded = node?.isExpanded ?? false;
|
|
169
183
|
const childCount = childrenArray.length;
|
|
170
184
|
const shouldRenderProgressively = progressiveRender && renderCoordinator && childCount > 0;
|
|
@@ -232,7 +246,7 @@
|
|
|
232
246
|
|
|
233
247
|
function _onNodeClicked() {
|
|
234
248
|
uiLogger.debug(`Node clicked: ${node.path}`, { id: node.id, hasChildren: node.hasChildren })
|
|
235
|
-
onNodeClicked
|
|
249
|
+
callbacks.onNodeClicked(node)
|
|
236
250
|
if (shouldToggleOnNodeClick) {
|
|
237
251
|
toggleExpanded()
|
|
238
252
|
}
|
|
@@ -269,9 +283,9 @@
|
|
|
269
283
|
class:ltree-clickable={node.isSelectable}
|
|
270
284
|
class:ltree-dragged={isDraggedNode}
|
|
271
285
|
class:ltree-draggable={node?.isDraggable}
|
|
272
|
-
class:ltree-glow-above={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'above'}
|
|
273
|
-
class:ltree-glow-below={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'below'}
|
|
274
|
-
class:ltree-glow-child={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'child'}
|
|
286
|
+
class:ltree-glow-above={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'above' && isPositionAllowed('above')}
|
|
287
|
+
class:ltree-glow-below={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'below' && isPositionAllowed('below')}
|
|
288
|
+
class:ltree-glow-child={dropZoneMode === 'glow' && isDragInProgress && isHoveredForDrop && glowPosition === 'child' && isPositionAllowed('child')}
|
|
275
289
|
class:ltree-drop-copy={isDragInProgress && isHoveredForDrop && dropOperation === 'copy'}
|
|
276
290
|
draggable={node?.isDraggable}
|
|
277
291
|
onclick={(e) => {
|
|
@@ -280,7 +294,7 @@
|
|
|
280
294
|
}}
|
|
281
295
|
oncontextmenu={(e) => {
|
|
282
296
|
e.stopPropagation();
|
|
283
|
-
onNodeRightClicked
|
|
297
|
+
callbacks.onNodeRightClicked(node, e);
|
|
284
298
|
}}
|
|
285
299
|
ondragstart={(e) => {
|
|
286
300
|
if (node?.isDraggable && e.dataTransfer) {
|
|
@@ -289,7 +303,7 @@
|
|
|
289
303
|
"application/svelte-treeview",
|
|
290
304
|
JSON.stringify(node),
|
|
291
305
|
);
|
|
292
|
-
onNodeDragStart
|
|
306
|
+
callbacks.onNodeDragStart(node, e);
|
|
293
307
|
}
|
|
294
308
|
}}
|
|
295
309
|
ondragover={(e) => {
|
|
@@ -305,7 +319,7 @@
|
|
|
305
319
|
glowPosition = calculateGlowPosition(e, e.currentTarget as HTMLElement);
|
|
306
320
|
}
|
|
307
321
|
}
|
|
308
|
-
onNodeDragOver
|
|
322
|
+
callbacks.onNodeDragOver(node, e);
|
|
309
323
|
}}
|
|
310
324
|
ondragleave={(e) => {
|
|
311
325
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
@@ -315,7 +329,7 @@
|
|
|
315
329
|
if (x < rect.left || x >= rect.right || y < rect.top || y >= rect.bottom) {
|
|
316
330
|
isDraggedOver = false;
|
|
317
331
|
glowPosition = null;
|
|
318
|
-
onNodeDragLeave
|
|
332
|
+
callbacks.onNodeDragLeave(node, e);
|
|
319
333
|
}
|
|
320
334
|
}}
|
|
321
335
|
ondrop={(e) => {
|
|
@@ -327,15 +341,15 @@
|
|
|
327
341
|
isDraggedOver = false;
|
|
328
342
|
// In glow mode, use the calculated glowPosition for the drop
|
|
329
343
|
if (dropZoneMode === 'glow' && glowPosition) {
|
|
330
|
-
onZoneDrop
|
|
344
|
+
callbacks.onZoneDrop(node, glowPosition, e);
|
|
331
345
|
} else {
|
|
332
|
-
onNodeDrop
|
|
346
|
+
callbacks.onNodeDrop(node, e);
|
|
333
347
|
}
|
|
334
348
|
glowPosition = null;
|
|
335
349
|
}}
|
|
336
|
-
ontouchstart={(e) => onTouchDragStart
|
|
337
|
-
ontouchmove={(e) => onTouchDragMove
|
|
338
|
-
ontouchend={(e) => onTouchDragEnd
|
|
350
|
+
ontouchstart={(e) => callbacks.onTouchDragStart(node, e)}
|
|
351
|
+
ontouchmove={(e) => callbacks.onTouchDragMove(node, e)}
|
|
352
|
+
ontouchend={(e) => callbacks.onTouchDragEnd(node, e)}
|
|
339
353
|
>
|
|
340
354
|
{#if children}
|
|
341
355
|
{@render children(node)}
|
|
@@ -345,71 +359,57 @@
|
|
|
345
359
|
</div>
|
|
346
360
|
|
|
347
361
|
<!-- Drop zones: positioned relative to .ltree-node-row (outside content to avoid padding issues) -->
|
|
348
|
-
<!-- Only render floating drop zones when in 'floating' mode -->
|
|
362
|
+
<!-- Only render floating drop zones when in 'floating' mode, filtered by allowedDropPositions -->
|
|
349
363
|
{#if dropZoneMode === 'floating' && isDragInProgress && isHoveredForDrop}
|
|
350
364
|
<div
|
|
351
365
|
class="ltree-drop-zones ltree-drop-zones-{dropZoneLayout}"
|
|
352
366
|
style="--drop-zone-start: {formattedDropZoneStart}; --drop-zone-max-width: {dropZoneMaxWidth}px;"
|
|
353
367
|
>
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
368
|
+
{#if isPositionAllowed('above')}
|
|
369
|
+
<div
|
|
370
|
+
class="ltree-drop-zone ltree-drop-above"
|
|
371
|
+
class:ltree-drop-zone-active={hoveredZone === 'above'}
|
|
372
|
+
ondragover={(e) => { e.preventDefault(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = 'above'; callbacks.onNodeDragOver(node, e); }}
|
|
373
|
+
ondragleave={() => { hoveredZone = null; }}
|
|
374
|
+
ondrop={(e) => { e.stopPropagation(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = null; callbacks.onZoneDrop(node, 'above', e); }}
|
|
375
|
+
>↑ Above</div>
|
|
376
|
+
{/if}
|
|
377
|
+
{#if isPositionAllowed('below')}
|
|
378
|
+
<div
|
|
379
|
+
class="ltree-drop-zone ltree-drop-below"
|
|
380
|
+
class:ltree-drop-zone-active={hoveredZone === 'below'}
|
|
381
|
+
ondragover={(e) => { e.preventDefault(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = 'below'; callbacks.onNodeDragOver(node, e); }}
|
|
382
|
+
ondragleave={() => { hoveredZone = null; }}
|
|
383
|
+
ondrop={(e) => { e.stopPropagation(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = null; callbacks.onZoneDrop(node, 'below', e); }}
|
|
384
|
+
>↓ Below</div>
|
|
385
|
+
{/if}
|
|
386
|
+
{#if isPositionAllowed('child')}
|
|
387
|
+
<div
|
|
388
|
+
class="ltree-drop-zone ltree-drop-child"
|
|
389
|
+
class:ltree-drop-zone-active={hoveredZone === 'child'}
|
|
390
|
+
ondragover={(e) => { e.preventDefault(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = 'child'; callbacks.onNodeDragOver(node, e); }}
|
|
391
|
+
ondragleave={() => { hoveredZone = null; }}
|
|
392
|
+
ondrop={(e) => { e.stopPropagation(); if (e.dataTransfer) e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move'; hoveredZone = null; callbacks.onZoneDrop(node, 'child', e); }}
|
|
393
|
+
>→ Child</div>
|
|
394
|
+
{/if}
|
|
375
395
|
</div>
|
|
376
396
|
{/if}
|
|
377
397
|
</div>
|
|
378
398
|
|
|
379
|
-
|
|
399
|
+
<!-- In flat mode, children are rendered by Tree.svelte, not recursively here -->
|
|
400
|
+
{#if !flatMode && node?.isExpanded && node?.hasChildren}
|
|
380
401
|
<div class="ltree-children">
|
|
381
402
|
{#each childrenToRender as item (item.id)}
|
|
382
403
|
<Node
|
|
383
404
|
node={item}
|
|
384
405
|
{children}
|
|
385
|
-
{shouldToggleOnNodeClick}
|
|
386
|
-
{onNodeClicked}
|
|
387
|
-
{onNodeRightClicked}
|
|
388
|
-
{onNodeDragStart}
|
|
389
|
-
{onNodeDragOver}
|
|
390
|
-
{onNodeDragLeave}
|
|
391
|
-
{onNodeDrop}
|
|
392
|
-
{onZoneDrop}
|
|
393
|
-
{onTouchDragStart}
|
|
394
|
-
{onTouchDragMove}
|
|
395
|
-
{onTouchDragEnd}
|
|
396
406
|
{progressiveRender}
|
|
397
407
|
{renderBatchSize}
|
|
398
|
-
{expandIconClass}
|
|
399
|
-
{collapseIconClass}
|
|
400
|
-
{leafIconClass}
|
|
401
|
-
{selectedNodeClass}
|
|
402
|
-
{dragOverNodeClass}
|
|
403
408
|
{isDraggedNode}
|
|
404
409
|
{isDragInProgress}
|
|
405
410
|
{hoveredNodeForDropPath}
|
|
406
411
|
{activeDropPosition}
|
|
407
|
-
{dropZoneMode}
|
|
408
|
-
{dropZoneLayout}
|
|
409
|
-
{dropZoneStart}
|
|
410
|
-
{dropZoneMaxWidth}
|
|
411
412
|
{dropOperation}
|
|
412
|
-
{allowCopy}
|
|
413
413
|
/>
|
|
414
414
|
{/each}
|
|
415
415
|
{#if hasMoreToRender}
|
|
@@ -6,34 +6,15 @@ declare function $$render<T>(): {
|
|
|
6
6
|
props: {
|
|
7
7
|
node: LTreeNode<T>;
|
|
8
8
|
children?: Snippet<[T]>;
|
|
9
|
-
onNodeClicked?: (node: LTreeNode<T>) => void;
|
|
10
|
-
onNodeRightClicked?: (node: LTreeNode<T>, event: MouseEvent) => void;
|
|
11
|
-
onNodeDragStart?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
12
|
-
onNodeDragOver?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
13
|
-
onNodeDragLeave?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
14
|
-
onNodeDrop?: (node: LTreeNode<T>, event: DragEvent) => void;
|
|
15
|
-
onZoneDrop?: (node: LTreeNode<T>, position: DropPosition, event: DragEvent) => void;
|
|
16
|
-
onTouchDragStart?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
17
|
-
onTouchDragMove?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
18
|
-
onTouchDragEnd?: (node: LTreeNode<T>, event: TouchEvent) => void;
|
|
19
|
-
shouldToggleOnNodeClick?: boolean | null | undefined;
|
|
20
9
|
progressiveRender?: boolean;
|
|
21
10
|
renderBatchSize?: number;
|
|
22
|
-
|
|
23
|
-
collapseIconClass?: string | null | undefined;
|
|
24
|
-
leafIconClass?: string | null | undefined;
|
|
25
|
-
selectedNodeClass?: string | null | undefined;
|
|
26
|
-
dragOverNodeClass?: string | null | undefined;
|
|
27
|
-
isDraggedNode?: boolean | null | undefined;
|
|
11
|
+
isDraggedNode?: boolean;
|
|
28
12
|
isDragInProgress?: boolean;
|
|
29
13
|
hoveredNodeForDropPath?: string | null;
|
|
30
14
|
activeDropPosition?: DropPosition | null;
|
|
31
|
-
dropZoneMode?: "floating" | "glow";
|
|
32
|
-
dropZoneLayout?: "around" | "above" | "below" | "wave" | "wave2";
|
|
33
|
-
dropZoneStart?: number | string;
|
|
34
|
-
dropZoneMaxWidth?: number;
|
|
35
15
|
dropOperation?: DropOperation;
|
|
36
|
-
|
|
16
|
+
flatMode?: boolean;
|
|
17
|
+
flatIndentSize?: string;
|
|
37
18
|
};
|
|
38
19
|
exports: {};
|
|
39
20
|
bindings: "";
|