@keenmate/svelte-treeview 5.0.0-rc08 → 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.
- package/CHANGELOG.md +41 -0
- package/README.md +33 -23
- package/ai/basic-setup.txt +336 -339
- package/ai/import-patterns.txt +290 -271
- package/ai/styling-theming.txt +355 -354
- package/component-variables.manifest.json +142 -0
- package/dist/components/Node.svelte +36 -26
- package/dist/components/Tree.svelte +49 -1
- package/dist/components/Tree.svelte.d.ts +36 -3
- package/dist/constants.generated.d.ts +1 -1
- package/dist/constants.generated.js +1 -1
- package/dist/core/TreeController.svelte.d.ts +45 -4
- package/dist/core/TreeController.svelte.js +270 -69
- package/dist/index.d.ts +1 -1
- package/dist/ltree/ltree.svelte.d.ts +1 -1
- package/dist/ltree/ltree.svelte.js +28 -7
- package/dist/ltree/types.d.ts +4 -0
- package/dist/styles/_base.css +41 -0
- package/dist/styles/_checkbox.css +83 -0
- package/dist/styles/_context-menu.css +134 -0
- package/dist/styles/_debug.css +45 -0
- package/dist/styles/_drag-drop.css +174 -0
- package/dist/styles/_drop-zones.css +270 -0
- package/dist/styles/_loading.css +40 -0
- package/dist/styles/_node.css +60 -0
- package/dist/styles/_states.css +92 -0
- package/dist/styles/_toggle-icons.css +97 -0
- package/dist/styles/_variables.css +189 -0
- package/dist/styles/main.css +37 -0
- package/dist/styles.css +651 -470
- package/package.json +103 -102
- package/dist/styles/main.scss +0 -1074
- package/dist/styles.css.map +0 -1
- package/dist/styles.scss +0 -2
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/keenmate/schemas/main/component-variables.schema.json",
|
|
3
|
+
"component": "@keenmate/svelte-treeview",
|
|
4
|
+
"prefix": "ltree",
|
|
5
|
+
"baseVariables": [
|
|
6
|
+
{ "name": "base-accent-color", "required": true, "usage": "Primary accent — selection, drop-zones, focus rings, debug panel. Tints derived via color-mix()." },
|
|
7
|
+
{ "name": "base-success-color", "required": false, "usage": "Drop-valid border and dragover highlight" },
|
|
8
|
+
{ "name": "base-danger-color", "required": false, "usage": "Drop-invalid border, danger context-menu items, scroll-highlight arrows" },
|
|
9
|
+
{ "name": "base-main-bg", "required": false, "usage": "Used for --ltree-light (context-menu hover tint, debug stat chips)" },
|
|
10
|
+
{ "name": "base-border-color", "required": true, "usage": "Default border color (checkbox, context-menu, spinner track)" },
|
|
11
|
+
{ "name": "base-hover-bg", "required": false, "usage": "Node row hover background" },
|
|
12
|
+
{ "name": "base-text-color-1", "required": true, "usage": "Primary body text color (node labels, context-menu items)" },
|
|
13
|
+
{ "name": "base-text-color-3", "required": false, "usage": "Muted text (path, toggle icon, loading 'more', node-path)" },
|
|
14
|
+
{ "name": "base-text-color-4", "required": false, "usage": "Subtle text (context-menu shortcut, submenu arrow, divider label)" },
|
|
15
|
+
{ "name": "base-text-color-on-accent", "required": false, "usage": "Text on accent backgrounds — checkbox checkmark color" },
|
|
16
|
+
{ "name": "base-input-bg", "required": false, "usage": "Checkbox background (unchecked)" },
|
|
17
|
+
{ "name": "base-dropdown-bg", "required": false, "usage": "Context-menu and submenu background" },
|
|
18
|
+
{ "name": "base-dropdown-box-shadow", "required": false, "usage": "Context-menu shadow" },
|
|
19
|
+
{ "name": "base-font-family", "required": false, "usage": "All text in component" },
|
|
20
|
+
{ "name": "base-font-size-xs", "required": false, "usage": "Small text — node path, context-menu shortcut, icon font-size (multiplier × --ltree-rem)" },
|
|
21
|
+
{ "name": "base-font-size-sm", "required": false, "usage": "Default node text and context-menu items (multiplier × --ltree-rem)" },
|
|
22
|
+
{ "name": "base-font-weight-medium", "required": false, "usage": "Node label weight" },
|
|
23
|
+
{ "name": "base-border-radius-sm", "required": false, "usage": "Checkbox, context-menu, node-content border radius (multiplier × --ltree-rem)" }
|
|
24
|
+
],
|
|
25
|
+
"componentVariables": [
|
|
26
|
+
{ "name": "ltree-rem", "category": "sizing", "usage": "Base sizing unit for proportional scaling (default 10px). Set to 1rem to scale with document font-size." },
|
|
27
|
+
|
|
28
|
+
{ "name": "ltree-primary", "category": "color", "usage": "Primary accent color (selection, focus, links). Tints derived via color-mix()." },
|
|
29
|
+
{ "name": "ltree-success", "category": "color", "usage": "Success color (drop-valid border, dragover-highlight)" },
|
|
30
|
+
{ "name": "ltree-danger", "category": "color", "usage": "Danger color (drop-invalid, scroll-highlight arrows, danger menu items)" },
|
|
31
|
+
{ "name": "ltree-light", "category": "color", "usage": "Light surface (context-menu hover, debug stat chips)" },
|
|
32
|
+
{ "name": "ltree-border", "category": "color", "usage": "Default border color" },
|
|
33
|
+
{ "name": "ltree-body-color", "category": "color", "usage": "Default body text color" },
|
|
34
|
+
|
|
35
|
+
{ "name": "ltree-font-family", "category": "typography", "usage": "Font family for all tree text" },
|
|
36
|
+
{ "name": "ltree-node-font-size", "category": "typography", "usage": "Node row text size" },
|
|
37
|
+
{ "name": "ltree-node-icon-font-size", "category": "typography", "usage": "Per-node icon font size (emoji, etc.)" },
|
|
38
|
+
{ "name": "ltree-node-icon-margin-right", "category": "spacing", "usage": "Gap between node icon and label" },
|
|
39
|
+
{ "name": "ltree-node-label-font-weight", "category": "typography", "usage": "Node label weight" },
|
|
40
|
+
{ "name": "ltree-node-label-margin-right", "category": "spacing", "usage": "Gap after node label" },
|
|
41
|
+
{ "name": "ltree-node-path-font-size", "category": "typography", "usage": "Path / debug muted text size" },
|
|
42
|
+
{ "name": "ltree-node-path-color", "category": "color", "usage": "Path / debug muted text color" },
|
|
43
|
+
|
|
44
|
+
{ "name": "ltree-node-indent-per-level", "category": "spacing", "usage": "Indentation added per nesting level" },
|
|
45
|
+
{ "name": "ltree-node-content-padding", "category": "spacing", "usage": "Inner padding of a node row" },
|
|
46
|
+
{ "name": "ltree-node-content-border-radius", "category": "border", "usage": "Node row corner rounding" },
|
|
47
|
+
{ "name": "ltree-node-hover-bg", "category": "surface", "usage": "Node row hover background" },
|
|
48
|
+
{ "name": "ltree-children-margin-top", "category": "spacing", "usage": "Top margin of nested child list" },
|
|
49
|
+
|
|
50
|
+
{ "name": "ltree-toggle-icon-size", "category": "sizing", "usage": "Toggle icon (chevron / +/- / arrow / leaf) SVG size" },
|
|
51
|
+
{ "name": "ltree-toggle-icon-width", "category": "sizing", "usage": "Width reserved for the toggle column" },
|
|
52
|
+
{ "name": "ltree-toggle-icon-color", "category": "color", "usage": "Toggle icon color (via currentColor mask)" },
|
|
53
|
+
{ "name": "ltree-toggle-icon-margin-right", "category": "spacing", "usage": "Gap between toggle and node content" },
|
|
54
|
+
{ "name": "ltree-toggle-icon-transition", "category": "animation", "usage": "Rotation animation timing" },
|
|
55
|
+
|
|
56
|
+
{ "name": "ltree-checkbox-size", "category": "sizing", "usage": "Checkbox square dimension" },
|
|
57
|
+
{ "name": "ltree-checkbox-border-width", "category": "border", "usage": "Checkbox border thickness (hairline, does not scale)" },
|
|
58
|
+
{ "name": "ltree-checkbox-border-color", "category": "color", "usage": "Unchecked checkbox border" },
|
|
59
|
+
{ "name": "ltree-checkbox-border-radius", "category": "border", "usage": "Checkbox corner rounding" },
|
|
60
|
+
{ "name": "ltree-checkbox-bg", "category": "surface", "usage": "Unchecked checkbox background" },
|
|
61
|
+
{ "name": "ltree-checkbox-checked-bg", "category": "surface", "usage": "Checked / indeterminate checkbox background" },
|
|
62
|
+
{ "name": "ltree-checkbox-checked-border-color", "category": "color", "usage": "Checked checkbox border" },
|
|
63
|
+
{ "name": "ltree-checkbox-checkmark-color", "category": "color", "usage": "Tick / dash glyph color" },
|
|
64
|
+
{ "name": "ltree-checkbox-focus-ring-width", "category": "border", "usage": "Focus-visible ring thickness" },
|
|
65
|
+
{ "name": "ltree-checkbox-focus-ring-color", "category": "color", "usage": "Focus-visible ring color (defaults to a 25% tint of --ltree-primary)" },
|
|
66
|
+
{ "name": "ltree-checkbox-focus-ring", "category": "border", "usage": "Composed focus-visible box-shadow (uses the two parts above; override directly for full control)" },
|
|
67
|
+
|
|
68
|
+
{ "name": "ltree-highlight-bg", "category": "state", "usage": "Explorer-style highlighted node background" },
|
|
69
|
+
{ "name": "ltree-highlight-color", "category": "state", "usage": "Highlighted node text color" },
|
|
70
|
+
{ "name": "ltree-multi-selected-bg", "category": "state", "usage": "Multi-select tint background" },
|
|
71
|
+
{ "name": "ltree-multi-selected-outline", "category": "state", "usage": "Multi-select outline" },
|
|
72
|
+
|
|
73
|
+
{ "name": "ltree-dragover-bg", "category": "state", "usage": "Drag-over background tint" },
|
|
74
|
+
{ "name": "ltree-dragover-shadow", "category": "state", "usage": "Drag-over glow shadow" },
|
|
75
|
+
{ "name": "ltree-drop-placeholder-bg", "category": "state", "usage": "Empty-tree drop placeholder background" },
|
|
76
|
+
{ "name": "ltree-drop-placeholder-color", "category": "state", "usage": "Placeholder text color" },
|
|
77
|
+
{ "name": "ltree-drop-placeholder-border-radius", "category": "border", "usage": "Placeholder corner rounding" },
|
|
78
|
+
{ "name": "ltree-drop-placeholder-min-height", "category": "sizing", "usage": "Placeholder min height" },
|
|
79
|
+
|
|
80
|
+
{ "name": "ltree-drop-zone-border-radius", "category": "border", "usage": "Drop zone corner rounding" },
|
|
81
|
+
{ "name": "ltree-drop-zone-before-bg", "category": "drop-zone", "usage": "Before zone resting background (sage)" },
|
|
82
|
+
{ "name": "ltree-drop-zone-before-color", "category": "drop-zone", "usage": "Before zone resting text" },
|
|
83
|
+
{ "name": "ltree-drop-zone-before-active-bg", "category": "drop-zone", "usage": "Before zone active background" },
|
|
84
|
+
{ "name": "ltree-drop-zone-before-active-color", "category": "drop-zone", "usage": "Before zone active text" },
|
|
85
|
+
{ "name": "ltree-drop-zone-before-active-shadow", "category": "drop-zone", "usage": "Before zone active shadow" },
|
|
86
|
+
{ "name": "ltree-drop-zone-after-bg", "category": "drop-zone", "usage": "After zone resting background (coral)" },
|
|
87
|
+
{ "name": "ltree-drop-zone-after-color", "category": "drop-zone", "usage": "After zone resting text" },
|
|
88
|
+
{ "name": "ltree-drop-zone-after-active-bg", "category": "drop-zone", "usage": "After zone active background" },
|
|
89
|
+
{ "name": "ltree-drop-zone-after-active-color", "category": "drop-zone", "usage": "After zone active text" },
|
|
90
|
+
{ "name": "ltree-drop-zone-after-active-shadow", "category": "drop-zone", "usage": "After zone active shadow" },
|
|
91
|
+
{ "name": "ltree-drop-zone-child-bg", "category": "drop-zone", "usage": "Child zone resting background (lavender)" },
|
|
92
|
+
{ "name": "ltree-drop-zone-child-color", "category": "drop-zone", "usage": "Child zone resting text" },
|
|
93
|
+
{ "name": "ltree-drop-zone-child-active-bg", "category": "drop-zone", "usage": "Child zone active background" },
|
|
94
|
+
{ "name": "ltree-drop-zone-child-active-color", "category": "drop-zone", "usage": "Child zone active text" },
|
|
95
|
+
{ "name": "ltree-drop-zone-child-active-shadow", "category": "drop-zone", "usage": "Child zone active shadow" },
|
|
96
|
+
|
|
97
|
+
{ "name": "ltree-drop-glow-before-color", "category": "drop-zone", "usage": "Border glow color for 'before' position" },
|
|
98
|
+
{ "name": "ltree-drop-glow-after-color", "category": "drop-zone", "usage": "Border glow color for 'after' position" },
|
|
99
|
+
{ "name": "ltree-drop-glow-child-color", "category": "drop-zone", "usage": "Border glow color for 'child' position" },
|
|
100
|
+
{ "name": "ltree-drop-glow-child-bg", "category": "drop-zone", "usage": "Child zone glow background tint" },
|
|
101
|
+
{ "name": "ltree-drop-glow-size", "category": "border", "usage": "Glow border thickness (hairline, does not scale)" },
|
|
102
|
+
{ "name": "ltree-drop-arrow-size", "category": "sizing", "usage": "Direction arrow size in glow mode" },
|
|
103
|
+
{ "name": "ltree-drop-arrow-position", "category": "spacing", "usage": "Horizontal arrow position (% of node width)" },
|
|
104
|
+
{ "name": "ltree-drop-arrow-before-rotation", "category": "animation", "usage": "Arrow rotation for 'before' position" },
|
|
105
|
+
{ "name": "ltree-drop-arrow-after-rotation", "category": "animation", "usage": "Arrow rotation for 'after' position" },
|
|
106
|
+
{ "name": "ltree-drop-arrow-child-rotation", "category": "animation", "usage": "Arrow rotation for 'child' position (45deg by default)" },
|
|
107
|
+
{ "name": "ltree-drop-arrow-before-image", "category": "icon", "usage": "SVG data URL for the 'before' direction arrow" },
|
|
108
|
+
{ "name": "ltree-drop-arrow-after-image", "category": "icon", "usage": "SVG data URL for the 'after' direction arrow" },
|
|
109
|
+
{ "name": "ltree-drop-arrow-child-image", "category": "icon", "usage": "SVG data URL for the 'child' direction arrow" },
|
|
110
|
+
|
|
111
|
+
{ "name": "tree-ghost-bg", "category": "state", "usage": "Touch drag ghost background (legacy prefix, kept for backward compat)" },
|
|
112
|
+
{ "name": "tree-ghost-color", "category": "state", "usage": "Touch drag ghost text color (legacy prefix)" },
|
|
113
|
+
|
|
114
|
+
{ "name": "ltree-context-menu-bg", "category": "context-menu", "usage": "Menu background" },
|
|
115
|
+
{ "name": "ltree-context-menu-border-color", "category": "context-menu", "usage": "Menu border color" },
|
|
116
|
+
{ "name": "ltree-context-menu-border-radius", "category": "border", "usage": "Menu corner rounding" },
|
|
117
|
+
{ "name": "ltree-context-menu-shadow", "category": "context-menu", "usage": "Menu drop shadow" },
|
|
118
|
+
{ "name": "ltree-context-menu-min-width", "category": "sizing", "usage": "Menu minimum width" },
|
|
119
|
+
{ "name": "ltree-context-menu-padding", "category": "spacing", "usage": "Menu inner padding" },
|
|
120
|
+
{ "name": "ltree-context-menu-item-padding", "category": "spacing", "usage": "Menu item padding" },
|
|
121
|
+
{ "name": "ltree-context-menu-item-font-size", "category": "typography", "usage": "Menu item font size" },
|
|
122
|
+
{ "name": "ltree-context-menu-item-color", "category": "color", "usage": "Menu item text color" },
|
|
123
|
+
{ "name": "ltree-context-menu-item-hover-bg", "category": "surface", "usage": "Menu item hover background" },
|
|
124
|
+
{ "name": "ltree-context-menu-icon-size", "category": "sizing", "usage": "Menu icon column width" },
|
|
125
|
+
{ "name": "ltree-context-menu-icon-font-size", "category": "typography", "usage": "Menu icon font size" },
|
|
126
|
+
{ "name": "ltree-context-menu-shortcut-color", "category": "color", "usage": "Keyboard shortcut hint color" },
|
|
127
|
+
{ "name": "ltree-context-menu-shortcut-font-size", "category": "typography", "usage": "Keyboard shortcut hint font size" },
|
|
128
|
+
{ "name": "ltree-context-menu-arrow-color", "category": "color", "usage": "Submenu arrow color" },
|
|
129
|
+
{ "name": "ltree-context-menu-divider-color", "category": "color", "usage": "Divider line color" },
|
|
130
|
+
{ "name": "ltree-context-menu-divider-label-color", "category": "color", "usage": "Named divider label color" },
|
|
131
|
+
|
|
132
|
+
{ "name": "ltree-loading-bg", "category": "surface", "usage": "Loading overlay background" },
|
|
133
|
+
{ "name": "ltree-loading-color", "category": "color", "usage": "'Loading more…' text color" },
|
|
134
|
+
{ "name": "ltree-spinner-size", "category": "sizing", "usage": "Spinner diameter" },
|
|
135
|
+
{ "name": "ltree-spinner-track", "category": "color", "usage": "Spinner background ring color" },
|
|
136
|
+
{ "name": "ltree-spinner-color", "category": "color", "usage": "Spinner active color" },
|
|
137
|
+
|
|
138
|
+
{ "name": "ltree-scroll-highlight-bg", "category": "state", "usage": "scrollToPath highlight background flash" },
|
|
139
|
+
{ "name": "ltree-scroll-highlight-shadow", "category": "state", "usage": "scrollToPath highlight glow" },
|
|
140
|
+
{ "name": "ltree-scroll-highlight-arrow-color", "category": "state", "usage": "scrollToPath direction arrow color" }
|
|
141
|
+
]
|
|
142
|
+
}
|
|
@@ -54,21 +54,21 @@
|
|
|
54
54
|
const callbacks = getContext<NodeCallbacks<T>>('NodeCallbacks');
|
|
55
55
|
const config = getContext<NodeConfig>('NodeConfig');
|
|
56
56
|
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
} = config;
|
|
57
|
+
// Read every config field through $derived so updates from controller.update()
|
|
58
|
+
// or the controller's runtime $effect syncs propagate into this Node's render.
|
|
59
|
+
// Plain destructuring would snapshot primitives once and never react.
|
|
60
|
+
const expandIconClass = $derived(config.expandIconClass);
|
|
61
|
+
const collapseIconClass = $derived(config.collapseIconClass);
|
|
62
|
+
const leafIconClass = $derived(config.leafIconClass);
|
|
63
|
+
const highlightedNodeClass = $derived(config.highlightedNodeClass);
|
|
64
|
+
const focusedNodeClass = $derived(config.focusedNodeClass);
|
|
65
|
+
// dragOverNodeClass is applied to the DOM directly by the controller
|
|
66
|
+
// (see hoveredNodeForDrop $effect in TreeController) — no per-Node binding.
|
|
67
|
+
const allowCopy = $derived(config.allowCopy);
|
|
69
68
|
const clickBehavior = $derived(config.clickBehavior);
|
|
70
69
|
const showCheckboxes = $derived(config.showCheckboxes);
|
|
71
70
|
const checkboxMode = $derived(config.checkboxMode);
|
|
71
|
+
const clickTogglesCheckbox = $derived(config.clickTogglesCheckbox);
|
|
72
72
|
|
|
73
73
|
// Indeterminate state: driven by controller's _updateAncestorVisualStates
|
|
74
74
|
const isIndeterminate = $derived(checkboxMode === 'cascade' && node.visualState === 'indeterminate');
|
|
@@ -81,15 +81,15 @@
|
|
|
81
81
|
const accordionExpand = $derived(config.accordionExpand);
|
|
82
82
|
const toggleIconMode = $derived(config.toggleIconMode);
|
|
83
83
|
|
|
84
|
-
// Compute if THIS node is the one being hovered for drop
|
|
84
|
+
// Compute if THIS node is the one being hovered for drop.
|
|
85
|
+
// Single source of truth from the controller — guarantees exactly one highlighted
|
|
86
|
+
// row at a time, unlike the per-node local flag we used before (HTML5 dragleave
|
|
87
|
+
// is unreliable and leaked stale highlights when moving fast between rows).
|
|
85
88
|
const isHoveredForDrop = $derived(hoveredNodeForDropPath === node.path);
|
|
86
89
|
|
|
87
90
|
const tree = getContext<Ltree<T>>("Ltree")
|
|
88
91
|
const renderCoordinator = getContext<RenderCoordinator | null>("RenderCoordinator")
|
|
89
92
|
|
|
90
|
-
// Drag over state
|
|
91
|
-
let isDraggedOver = $state(false);
|
|
92
|
-
|
|
93
93
|
// Track glow position for glow mode
|
|
94
94
|
let glowPosition = $state<'before' | 'after' | 'child' | null>(null);
|
|
95
95
|
|
|
@@ -177,8 +177,8 @@
|
|
|
177
177
|
// — only applied before first-child nodes (where level > previous node's level).
|
|
178
178
|
const indentStyle = $derived(
|
|
179
179
|
flatMode
|
|
180
|
-
? `margin-left: calc(${node?.level || 1} * var(--
|
|
181
|
-
: `margin-left: var(--
|
|
180
|
+
? `margin-left: calc(${node?.level || 1} * var(--ltree-node-indent-per-level, 0.5rem))${flatGap ? '; margin-top: 2px' : ''}`
|
|
181
|
+
: `margin-left: var(--ltree-node-indent-per-level, 0.5rem)`,
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
// Progressive rendering state - only used in recursive mode
|
|
@@ -296,14 +296,27 @@
|
|
|
296
296
|
function _onNodeClicked(event?: MouseEvent) {
|
|
297
297
|
uiLogger.debug(`Node clicked: ${node.path}`, { id: node.id, hasChildren: node.hasChildren })
|
|
298
298
|
const modifiers = event ? { ctrl: event.ctrlKey || event.metaKey, shift: event.shiftKey } : undefined;
|
|
299
|
+
const hasModifiers = !!(modifiers?.ctrl || modifiers?.shift);
|
|
300
|
+
|
|
301
|
+
// Plain click on a selectable node with checkboxes shown → toggle the checkbox
|
|
302
|
+
// instead of focusing/highlighting. Expand still happens if clickBehavior asks for it.
|
|
303
|
+
// Modified clicks (Ctrl/Shift) fall through to the normal multi-highlight path.
|
|
304
|
+
if (clickTogglesCheckbox && showCheckboxes && node.isSelectable && !hasModifiers) {
|
|
305
|
+
callbacks.onCheckboxToggle(node, { skipFocus: true });
|
|
306
|
+
if (clickBehavior !== 'select') toggleExpanded();
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
299
309
|
|
|
300
310
|
if (clickBehavior === 'expand') {
|
|
301
|
-
// Expand only — no selection callback
|
|
302
|
-
|
|
311
|
+
// Expand only — no selection callback. Ctrl/Shift have no meaning here
|
|
312
|
+
// (no selection to extend), so they shouldn't toggle expand either.
|
|
313
|
+
if (!hasModifiers) toggleExpanded()
|
|
303
314
|
} else if (clickBehavior === 'expand-and-focus') {
|
|
304
|
-
// Select + expand on single click
|
|
315
|
+
// Select + expand on single click. Modified clicks are reserved for
|
|
316
|
+
// highlight management — don't also toggle expand (matches OS file
|
|
317
|
+
// explorers where Ctrl/Shift+click manages selection without opening).
|
|
305
318
|
callbacks.onNodeClicked(node, modifiers)
|
|
306
|
-
toggleExpanded()
|
|
319
|
+
if (!hasModifiers) toggleExpanded()
|
|
307
320
|
} else {
|
|
308
321
|
// 'select' — single click selects only
|
|
309
322
|
callbacks.onNodeClicked(node, modifiers)
|
|
@@ -365,7 +378,7 @@
|
|
|
365
378
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
366
379
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
367
380
|
<div
|
|
368
|
-
class="ltree-node-content {node.isHighlighted ? highlightedNodeClass : ''} {node.isFocused && focusedNodeClass ? focusedNodeClass : ''}
|
|
381
|
+
class="ltree-node-content {node.isHighlighted ? highlightedNodeClass : ''} {node.isFocused && focusedNodeClass ? focusedNodeClass : ''}"
|
|
369
382
|
class:ltree-clickable={node.isSelectable}
|
|
370
383
|
class:ltree-dragged={isDraggedNode}
|
|
371
384
|
class:ltree-draggable={node?.isDraggable}
|
|
@@ -403,7 +416,6 @@
|
|
|
403
416
|
if (e.dataTransfer) {
|
|
404
417
|
e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move';
|
|
405
418
|
}
|
|
406
|
-
isDraggedOver = true;
|
|
407
419
|
// In glow mode, calculate and update the glow position
|
|
408
420
|
if (dropZoneMode === 'glow') {
|
|
409
421
|
glowPosition = calculateGlowPosition(e, e.currentTarget as HTMLElement);
|
|
@@ -417,7 +429,6 @@
|
|
|
417
429
|
const y = e.clientY;
|
|
418
430
|
|
|
419
431
|
if (x < rect.left || x >= rect.right || y < rect.top || y >= rect.bottom) {
|
|
420
|
-
isDraggedOver = false;
|
|
421
432
|
glowPosition = null;
|
|
422
433
|
callbacks.onNodeDragLeave(node, e);
|
|
423
434
|
}
|
|
@@ -428,7 +439,6 @@
|
|
|
428
439
|
if (e.dataTransfer) {
|
|
429
440
|
e.dataTransfer.dropEffect = (allowCopy && e.ctrlKey) ? 'copy' : 'move';
|
|
430
441
|
}
|
|
431
|
-
isDraggedOver = false;
|
|
432
442
|
// In glow mode, use the calculated glowPosition for the drop
|
|
433
443
|
if (dropZoneMode === 'glow' && glowPosition) {
|
|
434
444
|
callbacks.onZoneDrop(node, glowPosition, e);
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
type DropOperation,
|
|
13
13
|
type ClickBehavior,
|
|
14
14
|
type CheckboxMode,
|
|
15
|
+
type SelectionMode,
|
|
15
16
|
type TreeChange,
|
|
16
17
|
type ApplyChangesResult
|
|
17
18
|
} from '../ltree/types.js';
|
|
@@ -31,8 +32,11 @@
|
|
|
31
32
|
parentPathMember?: string | null | undefined;
|
|
32
33
|
levelMember?: string | null | undefined;
|
|
33
34
|
isExpandedMember?: string | null | undefined;
|
|
35
|
+
getIsExpandedCallback?: (node: LTreeNode<T>) => boolean;
|
|
34
36
|
isSelectableMember?: string | null | undefined;
|
|
37
|
+
getIsSelectableCallback?: (node: LTreeNode<T>) => boolean;
|
|
35
38
|
isSelectedMember?: string | null | undefined;
|
|
39
|
+
getIsSelectedCallback?: (node: LTreeNode<T>) => boolean;
|
|
36
40
|
isDraggableMember?: string | null | undefined;
|
|
37
41
|
getIsDraggableCallback?: (node: LTreeNode<T>) => boolean;
|
|
38
42
|
isDropAllowedMember?: string | null | undefined;
|
|
@@ -76,8 +80,16 @@
|
|
|
76
80
|
// BEHAVIOUR
|
|
77
81
|
expandLevel?: number | null | undefined;
|
|
78
82
|
clickBehavior?: ClickBehavior | null | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* `'single'` (default): plain click highlights one node; Ctrl/Shift+click
|
|
85
|
+
* degrade to plain click; Shift+Arrow / Enter are no-ops.
|
|
86
|
+
* `'multi'`: Ctrl-toggle, Shift-range, Shift+Arrow extend, Enter toggles
|
|
87
|
+
* highlight on the focused node.
|
|
88
|
+
*/
|
|
89
|
+
selectionMode?: SelectionMode | null | undefined;
|
|
79
90
|
showCheckboxes?: boolean | null | undefined;
|
|
80
91
|
checkboxMode?: CheckboxMode | null | undefined;
|
|
92
|
+
clickTogglesCheckbox?: boolean | null | undefined;
|
|
81
93
|
beforeCheckboxToggleCallback?: (node: LTreeNode<T>, checked: boolean, affectedPaths: string[]) => boolean | string[] | void;
|
|
82
94
|
rangeSelectionMode?: 'visual' | 'logical';
|
|
83
95
|
initializeIndexCallback?: () => Index;
|
|
@@ -185,8 +197,11 @@
|
|
|
185
197
|
hasChildrenMember,
|
|
186
198
|
|
|
187
199
|
isExpandedMember,
|
|
200
|
+
getIsExpandedCallback,
|
|
188
201
|
isSelectableMember,
|
|
202
|
+
getIsSelectableCallback,
|
|
189
203
|
isSelectedMember,
|
|
204
|
+
getIsSelectedCallback,
|
|
190
205
|
isDraggableMember,
|
|
191
206
|
getIsDraggableCallback,
|
|
192
207
|
isDropAllowedMember,
|
|
@@ -223,8 +238,10 @@
|
|
|
223
238
|
expandLevel = 2,
|
|
224
239
|
|
|
225
240
|
clickBehavior = 'expand-and-focus',
|
|
241
|
+
selectionMode = 'single',
|
|
226
242
|
showCheckboxes = false,
|
|
227
243
|
checkboxMode = 'independent',
|
|
244
|
+
clickTogglesCheckbox = false,
|
|
228
245
|
beforeCheckboxToggleCallback,
|
|
229
246
|
rangeSelectionMode = 'visual',
|
|
230
247
|
shouldUseInternalSearchIndex = true,
|
|
@@ -306,8 +323,11 @@
|
|
|
306
323
|
levelMember,
|
|
307
324
|
hasChildrenMember,
|
|
308
325
|
isExpandedMember,
|
|
326
|
+
getIsExpandedCallback,
|
|
309
327
|
isSelectableMember,
|
|
328
|
+
getIsSelectableCallback,
|
|
310
329
|
isSelectedMember,
|
|
330
|
+
getIsSelectedCallback,
|
|
311
331
|
isDraggableMember,
|
|
312
332
|
getIsDraggableCallback,
|
|
313
333
|
isDropAllowedMember,
|
|
@@ -330,8 +350,10 @@
|
|
|
330
350
|
selectedPaths,
|
|
331
351
|
expandLevel,
|
|
332
352
|
clickBehavior,
|
|
353
|
+
selectionMode,
|
|
333
354
|
showCheckboxes,
|
|
334
355
|
checkboxMode,
|
|
356
|
+
clickTogglesCheckbox,
|
|
335
357
|
beforeCheckboxToggleCallback,
|
|
336
358
|
rangeSelectionMode,
|
|
337
359
|
shouldUseInternalSearchIndex,
|
|
@@ -440,8 +462,10 @@
|
|
|
440
462
|
|
|
441
463
|
// Visual config sync (drives nodeConfig update via controller's internal effect)
|
|
442
464
|
$effect(() => { controller.clickBehavior = clickBehavior ?? 'expand-and-focus'; });
|
|
465
|
+
$effect(() => { controller.selectionMode = selectionMode ?? 'single'; });
|
|
443
466
|
$effect(() => { controller.showCheckboxes = showCheckboxes ?? false; });
|
|
444
467
|
$effect(() => { controller.checkboxMode = checkboxMode ?? 'independent'; });
|
|
468
|
+
$effect(() => { controller.clickTogglesCheckbox = clickTogglesCheckbox ?? false; });
|
|
445
469
|
$effect(() => { controller.beforeCheckboxToggleHandler = beforeCheckboxToggleCallback; });
|
|
446
470
|
$effect(() => { controller.rangeSelectionMode = rangeSelectionMode ?? 'visual'; });
|
|
447
471
|
$effect(() => { controller.expandIconClass = expandIconClass ?? 'ltree-icon-expand'; });
|
|
@@ -683,8 +707,11 @@
|
|
|
683
707
|
| "levelMember"
|
|
684
708
|
| "hasChildrenMember"
|
|
685
709
|
| "isExpandedMember"
|
|
710
|
+
| "getIsExpandedCallback"
|
|
686
711
|
| "isSelectableMember"
|
|
712
|
+
| "getIsSelectableCallback"
|
|
687
713
|
| "isSelectedMember"
|
|
714
|
+
| "getIsSelectedCallback"
|
|
688
715
|
| "isDraggableMember"
|
|
689
716
|
| "getIsDraggableCallback"
|
|
690
717
|
| "isDropAllowedMember"
|
|
@@ -703,8 +730,10 @@
|
|
|
703
730
|
| "selectedPaths"
|
|
704
731
|
| "expandLevel"
|
|
705
732
|
| "clickBehavior"
|
|
733
|
+
| "selectionMode"
|
|
706
734
|
| "showCheckboxes"
|
|
707
735
|
| "checkboxMode"
|
|
736
|
+
| "clickTogglesCheckbox"
|
|
708
737
|
| "beforeCheckboxToggleCallback"
|
|
709
738
|
| "rangeSelectionMode"
|
|
710
739
|
| "shouldUseInternalSearchIndex"
|
|
@@ -756,8 +785,11 @@
|
|
|
756
785
|
if (updates.levelMember !== undefined) levelMember = updates.levelMember;
|
|
757
786
|
if (updates.hasChildrenMember !== undefined) hasChildrenMember = updates.hasChildrenMember;
|
|
758
787
|
if (updates.isExpandedMember !== undefined) isExpandedMember = updates.isExpandedMember;
|
|
788
|
+
if (updates.getIsExpandedCallback !== undefined) getIsExpandedCallback = updates.getIsExpandedCallback;
|
|
759
789
|
if (updates.isSelectableMember !== undefined) isSelectableMember = updates.isSelectableMember;
|
|
790
|
+
if (updates.getIsSelectableCallback !== undefined) getIsSelectableCallback = updates.getIsSelectableCallback;
|
|
760
791
|
if (updates.isSelectedMember !== undefined) isSelectedMember = updates.isSelectedMember;
|
|
792
|
+
if (updates.getIsSelectedCallback !== undefined) getIsSelectedCallback = updates.getIsSelectedCallback;
|
|
761
793
|
if (updates.isDraggableMember !== undefined) isDraggableMember = updates.isDraggableMember;
|
|
762
794
|
if (updates.getIsDraggableCallback !== undefined) getIsDraggableCallback = updates.getIsDraggableCallback;
|
|
763
795
|
if (updates.isDropAllowedMember !== undefined) isDropAllowedMember = updates.isDropAllowedMember;
|
|
@@ -776,8 +808,10 @@
|
|
|
776
808
|
if (updates.selectedPaths !== undefined) selectedPaths = updates.selectedPaths;
|
|
777
809
|
if (updates.expandLevel !== undefined) expandLevel = updates.expandLevel;
|
|
778
810
|
if (updates.clickBehavior !== undefined) clickBehavior = updates.clickBehavior;
|
|
811
|
+
if (updates.selectionMode !== undefined) selectionMode = updates.selectionMode;
|
|
779
812
|
if (updates.showCheckboxes !== undefined) showCheckboxes = updates.showCheckboxes;
|
|
780
813
|
if (updates.checkboxMode !== undefined) checkboxMode = updates.checkboxMode;
|
|
814
|
+
if (updates.clickTogglesCheckbox !== undefined) clickTogglesCheckbox = updates.clickTogglesCheckbox;
|
|
781
815
|
if (updates.beforeCheckboxToggleCallback !== undefined) beforeCheckboxToggleCallback = updates.beforeCheckboxToggleCallback;
|
|
782
816
|
if (updates.rangeSelectionMode !== undefined) rangeSelectionMode = updates.rangeSelectionMode;
|
|
783
817
|
if (updates.shouldUseInternalSearchIndex !== undefined) shouldUseInternalSearchIndex = updates.shouldUseInternalSearchIndex;
|
|
@@ -837,6 +871,8 @@
|
|
|
837
871
|
|
|
838
872
|
let handled = true;
|
|
839
873
|
|
|
874
|
+
// Shift+nav extends the highlight range. In single mode the controller
|
|
875
|
+
// short-circuits these to no-ops (see _navHighlightTo).
|
|
840
876
|
switch (event.key) {
|
|
841
877
|
case 'ArrowDown': event.shiftKey ? controller.navHighlightNext() : controller.navNextSibling(); break;
|
|
842
878
|
case 'ArrowUp': event.shiftKey ? controller.navHighlightPrev() : controller.navPrevSibling(); break;
|
|
@@ -848,7 +884,19 @@
|
|
|
848
884
|
case 'PageDown': event.shiftKey ? controller.navHighlightPageDown() : controller.navPageDown(); break;
|
|
849
885
|
case 'PageUp': event.shiftKey ? controller.navHighlightPageUp() : controller.navPageUp(); break;
|
|
850
886
|
case 'Enter':
|
|
851
|
-
|
|
887
|
+
// single: no-op (per spec); multi: toggle highlight on focused node.
|
|
888
|
+
if (controller.selectionMode === 'multi') controller.toggleFocusedHighlight();
|
|
889
|
+
else handled = false;
|
|
890
|
+
break;
|
|
891
|
+
case ' ':
|
|
892
|
+
// With checkboxes: toggle the focused node's checkbox.
|
|
893
|
+
// Without: keep the legacy expand/collapse behaviour as a useful fallback.
|
|
894
|
+
if (controller.showCheckboxes && controller.focusedNode?.isSelectable) {
|
|
895
|
+
controller.nodeCallbacks.onCheckboxToggle(controller.focusedNode);
|
|
896
|
+
} else {
|
|
897
|
+
controller.navToggle();
|
|
898
|
+
}
|
|
899
|
+
break;
|
|
852
900
|
default: handled = false;
|
|
853
901
|
}
|
|
854
902
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Index, SearchOptions } from 'flexsearch';
|
|
2
2
|
import { type LTreeNode } from '../ltree/ltree-node.svelte.js';
|
|
3
|
-
import { type InsertArrayResult, type InsertBranchResult, type DeleteBranchResult, type ContextMenuEntry, type DropPosition, type DragDropMode, type DropOperation, type ClickBehavior, type CheckboxMode, type TreeChange, type ApplyChangesResult } from '../ltree/types.js';
|
|
3
|
+
import { type InsertArrayResult, type InsertBranchResult, type DeleteBranchResult, type ContextMenuEntry, type DropPosition, type DragDropMode, type DropOperation, type ClickBehavior, type CheckboxMode, type SelectionMode, type TreeChange, type ApplyChangesResult } from '../ltree/types.js';
|
|
4
4
|
import type { RenderStats } from './RenderCoordinator.svelte.js';
|
|
5
5
|
import { TreeController } from '../core/TreeController.svelte.js';
|
|
6
6
|
import type { TreeNavigationOverrides } from '../core/navigation.js';
|
|
@@ -11,8 +11,11 @@ declare function $$render<T>(): {
|
|
|
11
11
|
parentPathMember?: string | null | undefined;
|
|
12
12
|
levelMember?: string | null | undefined;
|
|
13
13
|
isExpandedMember?: string | null | undefined;
|
|
14
|
+
getIsExpandedCallback?: (node: LTreeNode<T>) => boolean;
|
|
14
15
|
isSelectableMember?: string | null | undefined;
|
|
16
|
+
getIsSelectableCallback?: (node: LTreeNode<T>) => boolean;
|
|
15
17
|
isSelectedMember?: string | null | undefined;
|
|
18
|
+
getIsSelectedCallback?: (node: LTreeNode<T>) => boolean;
|
|
16
19
|
isDraggableMember?: string | null | undefined;
|
|
17
20
|
getIsDraggableCallback?: (node: LTreeNode<T>) => boolean;
|
|
18
21
|
isDropAllowedMember?: string | null | undefined;
|
|
@@ -45,8 +48,16 @@ declare function $$render<T>(): {
|
|
|
45
48
|
loadingPlaceholder?: any;
|
|
46
49
|
expandLevel?: number | null | undefined;
|
|
47
50
|
clickBehavior?: ClickBehavior | null | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* `'single'` (default): plain click highlights one node; Ctrl/Shift+click
|
|
53
|
+
* degrade to plain click; Shift+Arrow / Enter are no-ops.
|
|
54
|
+
* `'multi'`: Ctrl-toggle, Shift-range, Shift+Arrow extend, Enter toggles
|
|
55
|
+
* highlight on the focused node.
|
|
56
|
+
*/
|
|
57
|
+
selectionMode?: SelectionMode | null | undefined;
|
|
48
58
|
showCheckboxes?: boolean | null | undefined;
|
|
49
59
|
checkboxMode?: CheckboxMode | null | undefined;
|
|
60
|
+
clickTogglesCheckbox?: boolean | null | undefined;
|
|
50
61
|
beforeCheckboxToggleCallback?: (node: LTreeNode<T>, checked: boolean, affectedPaths: string[]) => boolean | string[] | void;
|
|
51
62
|
rangeSelectionMode?: "visual" | "logical";
|
|
52
63
|
initializeIndexCallback?: () => Index;
|
|
@@ -221,8 +232,11 @@ declare function $$render<T>(): {
|
|
|
221
232
|
parentPathMember?: string | null | undefined;
|
|
222
233
|
levelMember?: string | null | undefined;
|
|
223
234
|
isExpandedMember?: string | null | undefined;
|
|
235
|
+
getIsExpandedCallback?: (node: LTreeNode<T>) => boolean;
|
|
224
236
|
isSelectableMember?: string | null | undefined;
|
|
237
|
+
getIsSelectableCallback?: (node: LTreeNode<T>) => boolean;
|
|
225
238
|
isSelectedMember?: string | null | undefined;
|
|
239
|
+
getIsSelectedCallback?: (node: LTreeNode<T>) => boolean;
|
|
226
240
|
isDraggableMember?: string | null | undefined;
|
|
227
241
|
getIsDraggableCallback?: (node: LTreeNode<T>) => boolean;
|
|
228
242
|
isDropAllowedMember?: string | null | undefined;
|
|
@@ -255,8 +269,16 @@ declare function $$render<T>(): {
|
|
|
255
269
|
loadingPlaceholder?: any;
|
|
256
270
|
expandLevel?: number | null | undefined;
|
|
257
271
|
clickBehavior?: ClickBehavior | null | undefined;
|
|
272
|
+
/**
|
|
273
|
+
* `'single'` (default): plain click highlights one node; Ctrl/Shift+click
|
|
274
|
+
* degrade to plain click; Shift+Arrow / Enter are no-ops.
|
|
275
|
+
* `'multi'`: Ctrl-toggle, Shift-range, Shift+Arrow extend, Enter toggles
|
|
276
|
+
* highlight on the focused node.
|
|
277
|
+
*/
|
|
278
|
+
selectionMode?: SelectionMode | null | undefined;
|
|
258
279
|
showCheckboxes?: boolean | null | undefined;
|
|
259
280
|
checkboxMode?: CheckboxMode | null | undefined;
|
|
281
|
+
clickTogglesCheckbox?: boolean | null | undefined;
|
|
260
282
|
beforeCheckboxToggleCallback?: (node: LTreeNode<T>, checked: boolean, affectedPaths: string[]) => boolean | string[] | void;
|
|
261
283
|
rangeSelectionMode?: "visual" | "logical";
|
|
262
284
|
initializeIndexCallback?: () => Index;
|
|
@@ -342,7 +364,7 @@ declare function $$render<T>(): {
|
|
|
342
364
|
onTreeKeydown?: (event: KeyboardEvent, controller: TreeController<T>) => boolean | void;
|
|
343
365
|
/** Override individual navigation methods (e.g. for custom ArrowDown/Up behavior) */
|
|
344
366
|
navigationOverrides?: TreeNavigationOverrides<T>;
|
|
345
|
-
}, "treeId" | "treePathSeparator" | "idMember" | "pathMember" | "parentPathMember" | "levelMember" | "hasChildrenMember" | "isExpandedMember" | "isSelectableMember" | "isSelectedMember" | "isDraggableMember" | "getIsDraggableCallback" | "isDropAllowedMember" | "displayValueMember" | "getDisplayValueCallback" | "searchValueMember" | "getSearchValueCallback" | "isCollapsibleMember" | "getIsCollapsibleCallback" | "orderMember" | "isSorted" | "sortCallback" | "data" | "focusedNode" | "highlightedPaths" | "selectedPaths" | "expandLevel" | "clickBehavior" | "showCheckboxes" | "checkboxMode" | "beforeCheckboxToggleCallback" | "rangeSelectionMode" | "shouldUseInternalSearchIndex" | "initializeIndexCallback" | "searchText" | "indexerBatchSize" | "indexerTimeout" | "shouldDisplayDebugInformation" | "shouldDisplayContextMenuInDebugMode" | "onNodeClick" | "onHighlightChange" | "onSelectionChange" | "onNodeDragStart" | "onNodeDragOver" | "onNodeDrop" | "beforeDropCallback" | "beforeCopyCallback" | "beforeCutCallback" | "beforePasteCallback" | "getContextMenuItemsCallback" | "virtualScroll" | "virtualRowHeight" | "virtualOverscan" | "virtualContainerHeight" | "dragDropMode" | "dropZoneMode" | "bodyClass" | "expandIconClass" | "collapseIconClass" | "leafIconClass" | "toggleIconMode" | "highlightedNodeClass" | "focusedNodeClass" | "dragOverNodeClass" | "scrollHighlightTimeout" | "scrollHighlightClass" | "contextMenuXOffset" | "contextMenuYOffset" | "accordionExpand">>) => void;
|
|
367
|
+
}, "treeId" | "treePathSeparator" | "idMember" | "pathMember" | "parentPathMember" | "levelMember" | "hasChildrenMember" | "isExpandedMember" | "getIsExpandedCallback" | "isSelectableMember" | "getIsSelectableCallback" | "isSelectedMember" | "getIsSelectedCallback" | "isDraggableMember" | "getIsDraggableCallback" | "isDropAllowedMember" | "displayValueMember" | "getDisplayValueCallback" | "searchValueMember" | "getSearchValueCallback" | "isCollapsibleMember" | "getIsCollapsibleCallback" | "orderMember" | "isSorted" | "sortCallback" | "data" | "focusedNode" | "highlightedPaths" | "selectedPaths" | "expandLevel" | "clickBehavior" | "selectionMode" | "showCheckboxes" | "checkboxMode" | "clickTogglesCheckbox" | "beforeCheckboxToggleCallback" | "rangeSelectionMode" | "shouldUseInternalSearchIndex" | "initializeIndexCallback" | "searchText" | "indexerBatchSize" | "indexerTimeout" | "shouldDisplayDebugInformation" | "shouldDisplayContextMenuInDebugMode" | "onNodeClick" | "onHighlightChange" | "onSelectionChange" | "onNodeDragStart" | "onNodeDragOver" | "onNodeDrop" | "beforeDropCallback" | "beforeCopyCallback" | "beforeCutCallback" | "beforePasteCallback" | "getContextMenuItemsCallback" | "virtualScroll" | "virtualRowHeight" | "virtualOverscan" | "virtualContainerHeight" | "dragDropMode" | "dropZoneMode" | "bodyClass" | "expandIconClass" | "collapseIconClass" | "leafIconClass" | "toggleIconMode" | "highlightedNodeClass" | "focusedNodeClass" | "dragOverNodeClass" | "scrollHighlightTimeout" | "scrollHighlightClass" | "contextMenuXOffset" | "contextMenuYOffset" | "accordionExpand">>) => void;
|
|
346
368
|
};
|
|
347
369
|
bindings: "data" | "focusedNode" | "highlightedPaths" | "selectedPaths" | "searchText" | "insertResult" | "isRendering";
|
|
348
370
|
slots: {};
|
|
@@ -441,8 +463,11 @@ declare class __sveltets_Render<T> {
|
|
|
441
463
|
parentPathMember?: string | null | undefined;
|
|
442
464
|
levelMember?: string | null | undefined;
|
|
443
465
|
isExpandedMember?: string | null | undefined;
|
|
466
|
+
getIsExpandedCallback?: ((node: LTreeNode<T>) => boolean) | undefined;
|
|
444
467
|
isSelectableMember?: string | null | undefined;
|
|
468
|
+
getIsSelectableCallback?: ((node: LTreeNode<T>) => boolean) | undefined;
|
|
445
469
|
isSelectedMember?: string | null | undefined;
|
|
470
|
+
getIsSelectedCallback?: ((node: LTreeNode<T>) => boolean) | undefined;
|
|
446
471
|
isDraggableMember?: string | null | undefined;
|
|
447
472
|
getIsDraggableCallback?: ((node: LTreeNode<T>) => boolean) | undefined;
|
|
448
473
|
isDropAllowedMember?: string | null | undefined;
|
|
@@ -475,8 +500,16 @@ declare class __sveltets_Render<T> {
|
|
|
475
500
|
loadingPlaceholder?: any;
|
|
476
501
|
expandLevel?: number | null | undefined;
|
|
477
502
|
clickBehavior?: ClickBehavior | null | undefined;
|
|
503
|
+
/**
|
|
504
|
+
* `'single'` (default): plain click highlights one node; Ctrl/Shift+click
|
|
505
|
+
* degrade to plain click; Shift+Arrow / Enter are no-ops.
|
|
506
|
+
* `'multi'`: Ctrl-toggle, Shift-range, Shift+Arrow extend, Enter toggles
|
|
507
|
+
* highlight on the focused node.
|
|
508
|
+
*/
|
|
509
|
+
selectionMode?: SelectionMode | null | undefined;
|
|
478
510
|
showCheckboxes?: boolean | null | undefined;
|
|
479
511
|
checkboxMode?: CheckboxMode | null | undefined;
|
|
512
|
+
clickTogglesCheckbox?: boolean | null | undefined;
|
|
480
513
|
beforeCheckboxToggleCallback?: ((node: LTreeNode<T>, checked: boolean, affectedPaths: string[]) => boolean | string[] | void) | undefined;
|
|
481
514
|
rangeSelectionMode?: "visual" | "logical";
|
|
482
515
|
initializeIndexCallback?: (() => Index) | undefined;
|
|
@@ -562,7 +595,7 @@ declare class __sveltets_Render<T> {
|
|
|
562
595
|
onTreeKeydown?: ((event: KeyboardEvent, controller: TreeController<T>) => boolean | void) | undefined;
|
|
563
596
|
/** Override individual navigation methods (e.g. for custom ArrowDown/Up behavior) */
|
|
564
597
|
navigationOverrides?: Partial<import("../core/navigation.js").TreeNavigation<T>> | undefined;
|
|
565
|
-
}, "treeId" | "data" | "treePathSeparator" | "idMember" | "pathMember" | "parentPathMember" | "levelMember" | "hasChildrenMember" | "isExpandedMember" | "displayValueMember" | "getDisplayValueCallback" | "searchValueMember" | "getSearchValueCallback" | "orderMember" | "isSorted" | "sortCallback" | "isSelectableMember" | "isSelectedMember" | "isDraggableMember" | "getIsDraggableCallback" | "isDropAllowedMember" | "isCollapsibleMember" | "getIsCollapsibleCallback" | "shouldDisplayDebugInformation" | "onNodeDrop" | "beforeDropCallback" | "beforeCopyCallback" | "beforeCutCallback" | "beforePasteCallback" | "beforeCheckboxToggleCallback" | "getContextMenuItemsCallback" | "focusedNode" | "highlightedPaths" | "selectedPaths" | "expandLevel" | "clickBehavior" | "showCheckboxes" | "checkboxMode" | "rangeSelectionMode" | "initializeIndexCallback" | "searchText" | "shouldUseInternalSearchIndex" | "indexerBatchSize" | "indexerTimeout" | "shouldDisplayContextMenuInDebugMode" | "virtualScroll" | "virtualRowHeight" | "virtualOverscan" | "virtualContainerHeight" | "dragDropMode" | "dropZoneMode" | "accordionExpand" | "onNodeClick" | "onNodeDragStart" | "onNodeDragOver" | "onHighlightChange" | "onSelectionChange" | "bodyClass" | "highlightedNodeClass" | "focusedNodeClass" | "dragOverNodeClass" | "expandIconClass" | "collapseIconClass" | "leafIconClass" | "toggleIconMode" | "scrollHighlightTimeout" | "scrollHighlightClass" | "contextMenuXOffset" | "contextMenuYOffset">>) => void;
|
|
598
|
+
}, "treeId" | "data" | "treePathSeparator" | "idMember" | "pathMember" | "parentPathMember" | "levelMember" | "hasChildrenMember" | "isExpandedMember" | "getIsExpandedCallback" | "displayValueMember" | "getDisplayValueCallback" | "searchValueMember" | "getSearchValueCallback" | "orderMember" | "isSorted" | "sortCallback" | "isSelectableMember" | "getIsSelectableCallback" | "isSelectedMember" | "getIsSelectedCallback" | "isDraggableMember" | "getIsDraggableCallback" | "isDropAllowedMember" | "isCollapsibleMember" | "getIsCollapsibleCallback" | "shouldDisplayDebugInformation" | "onNodeDrop" | "beforeDropCallback" | "beforeCopyCallback" | "beforeCutCallback" | "beforePasteCallback" | "beforeCheckboxToggleCallback" | "getContextMenuItemsCallback" | "focusedNode" | "highlightedPaths" | "selectedPaths" | "expandLevel" | "clickBehavior" | "selectionMode" | "showCheckboxes" | "checkboxMode" | "clickTogglesCheckbox" | "rangeSelectionMode" | "initializeIndexCallback" | "searchText" | "shouldUseInternalSearchIndex" | "indexerBatchSize" | "indexerTimeout" | "shouldDisplayContextMenuInDebugMode" | "virtualScroll" | "virtualRowHeight" | "virtualOverscan" | "virtualContainerHeight" | "dragDropMode" | "dropZoneMode" | "accordionExpand" | "onNodeClick" | "onNodeDragStart" | "onNodeDragOver" | "onHighlightChange" | "onSelectionChange" | "bodyClass" | "highlightedNodeClass" | "focusedNodeClass" | "dragOverNodeClass" | "expandIconClass" | "collapseIconClass" | "leafIconClass" | "toggleIconMode" | "scrollHighlightTimeout" | "scrollHighlightClass" | "contextMenuXOffset" | "contextMenuYOffset">>) => void;
|
|
566
599
|
};
|
|
567
600
|
}
|
|
568
601
|
interface $$IsomorphicComponent {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated file - do not edit manually
|
|
2
2
|
// Generated by scripts/generate-constants.js
|
|
3
|
-
export const VERSION = "5.0.0-
|
|
3
|
+
export const VERSION = "5.0.0-rc09";
|
|
4
4
|
export const PACKAGE_NAME = "@keenmate/svelte-treeview";
|
|
5
5
|
export const AUTHOR = "KeenMate";
|
|
6
6
|
export const LICENSE = "MIT";
|