@streamscloud/kit 0.17.0 → 0.19.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/dist/ui/badge/cmp.badge.svelte +4 -0
- package/dist/ui/badge/cmp.badge.svelte.d.ts +1 -0
- package/dist/ui/page-toolbar/cmp.reorderable-checkbox-list.svelte +131 -0
- package/dist/ui/page-toolbar/cmp.reorderable-checkbox-list.svelte.d.ts +31 -0
- package/dist/ui/page-toolbar/cmp.toolbar-checkbox.svelte +14 -0
- package/dist/ui/page-toolbar/cmp.toolbar-checkbox.svelte.d.ts +19 -0
- package/dist/ui/page-toolbar/cmp.toolbar-divider.svelte +19 -0
- package/dist/ui/page-toolbar/cmp.toolbar-divider.svelte.d.ts +35 -0
- package/dist/ui/page-toolbar/cmp.toolbar-filter-select.svelte +143 -0
- package/dist/ui/page-toolbar/cmp.toolbar-filter-select.svelte.d.ts +68 -0
- package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte +71 -0
- package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte.d.ts +32 -0
- package/dist/ui/page-toolbar/cmp.toolbar-option.svelte +189 -0
- package/dist/ui/page-toolbar/cmp.toolbar-option.svelte.d.ts +47 -0
- package/dist/ui/page-toolbar/cmp.toolbar-popover.svelte +23 -8
- package/dist/ui/page-toolbar/cmp.toolbar-popover.svelte.d.ts +14 -6
- package/dist/ui/page-toolbar/cmp.toolbar-section-title.svelte +46 -0
- package/dist/ui/page-toolbar/cmp.toolbar-section-title.svelte.d.ts +24 -0
- package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte +31 -0
- package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte.d.ts +44 -0
- package/dist/ui/page-toolbar/{cmp.toolbar-switch-item.svelte → cmp.toolbar-switch.svelte} +10 -10
- package/dist/ui/page-toolbar/{cmp.toolbar-switch-item.svelte.d.ts → cmp.toolbar-switch.svelte.d.ts} +2 -2
- package/dist/ui/page-toolbar/cmp.toolbar-toggle.svelte +14 -0
- package/dist/ui/page-toolbar/cmp.toolbar-toggle.svelte.d.ts +19 -0
- package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte +51 -0
- package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte.d.ts +27 -0
- package/dist/ui/page-toolbar/index.d.ts +12 -7
- package/dist/ui/page-toolbar/index.js +11 -6
- package/dist/ui/page-toolbar/reorderable-checkbox-list-localization.d.ts +5 -0
- package/dist/ui/page-toolbar/reorderable-checkbox-list-localization.js +17 -0
- package/dist/ui/page-toolbar/toolbar-filter-select-localization.d.ts +5 -0
- package/dist/ui/page-toolbar/toolbar-filter-select-localization.js +20 -0
- package/dist/ui/page-toolbar/toolbar-sort-select-localization.d.ts +3 -0
- package/dist/ui/page-toolbar/toolbar-sort-select-localization.js +9 -0
- package/dist/ui/page-toolbar/toolbar-view-controls-localization.d.ts +5 -0
- package/dist/ui/page-toolbar/toolbar-view-controls-localization.js +17 -0
- package/dist/ui/page-toolbar/types.d.ts +1 -1
- package/dist/ui/select/index.d.ts +1 -0
- package/dist/ui/select/index.js +1 -0
- package/dist/ui/select/select-listbox.svelte +11 -5
- package/dist/ui/select/select-listbox.svelte.d.ts +1 -1
- package/dist/ui/table/_table-styles.scss +156 -0
- package/dist/ui/table/cmp.table-draggable.svelte +338 -0
- package/dist/ui/table/cmp.table-draggable.svelte.d.ts +79 -0
- package/dist/ui/table/cmp.table.svelte +96 -265
- package/dist/ui/table/cmp.table.svelte.d.ts +16 -8
- package/dist/ui/table/index.d.ts +1 -0
- package/dist/ui/table/index.js +1 -0
- package/dist/ui/table/table-cells/index.d.ts +1 -12
- package/dist/ui/table/table-cells/index.js +1 -12
- package/dist/ui/table/table-cells/table-cell.svelte +77 -0
- package/dist/ui/table/table-cells/{table-select-cell.svelte.d.ts → table-cell.svelte.d.ts} +12 -6
- package/dist/ui/table/table-column-models.svelte.d.ts +1 -2
- package/dist/ui/table/table-column-models.svelte.js +0 -1
- package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte +20 -47
- package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte.d.ts +3 -7
- package/dist/ui/table/table-columns-manager/table-columns-manager-localization.d.ts +1 -1
- package/dist/ui/table/table-columns-manager/table-columns-manager-localization.js +7 -7
- package/dist/ui/table/table-localization.d.ts +0 -2
- package/dist/ui/table/table-localization.js +0 -14
- package/dist/ui/table/table-model.svelte.d.ts +2 -3
- package/dist/ui/table/table-model.svelte.js +5 -35
- package/dist/ui/table/table-view.svelte.d.ts +14 -0
- package/dist/ui/table/table-view.svelte.js +32 -0
- package/dist/ui/table/types.d.ts +5 -28
- package/dist/ui/toggle/cmp.toggle.svelte +32 -26
- package/dist/ui/toggle/cmp.toggle.svelte.d.ts +2 -0
- package/dist/ui/tree/cmp.tree-node-view.svelte +16 -10
- package/dist/ui/tree/cmp.tree-node-view.svelte.d.ts +2 -2
- package/dist/ui/tree/cmp.tree.svelte +14 -30
- package/dist/ui/tree/cmp.tree.svelte.d.ts +5 -5
- package/dist/ui/tree/tree-keyboard.svelte.d.ts +9 -0
- package/dist/ui/tree/tree-keyboard.svelte.js +107 -0
- package/dist/ui/tree/tree-node.svelte.d.ts +7 -3
- package/dist/ui/tree/tree-node.svelte.js +32 -16
- package/package.json +1 -1
- package/dist/ui/page-toolbar/cmp.reorderable-toggle-list.svelte +0 -153
- package/dist/ui/page-toolbar/cmp.reorderable-toggle-list.svelte.d.ts +0 -20
- package/dist/ui/page-toolbar/cmp.toolbar-checkbox-item.svelte +0 -19
- package/dist/ui/page-toolbar/cmp.toolbar-checkbox-item.svelte.d.ts +0 -12
- package/dist/ui/page-toolbar/cmp.toolbar-panel-button.svelte +0 -42
- package/dist/ui/page-toolbar/cmp.toolbar-panel-button.svelte.d.ts +0 -20
- package/dist/ui/page-toolbar/cmp.toolbar-panel.svelte +0 -57
- package/dist/ui/page-toolbar/cmp.toolbar-panel.svelte.d.ts +0 -19
- package/dist/ui/page-toolbar/cmp.toolbar-toggle-item.svelte +0 -16
- package/dist/ui/page-toolbar/cmp.toolbar-toggle-item.svelte.d.ts +0 -12
- package/dist/ui/table/table-cells/table-select-cell.svelte +0 -28
- package/dist/ui/table/table-cells/table-text-input-cell.svelte +0 -69
- package/dist/ui/table/table-cells/table-text-input-cell.svelte.d.ts +0 -38
- package/dist/ui/tree/tree-navigation.svelte.d.ts +0 -14
- package/dist/ui/tree/tree-navigation.svelte.js +0 -99
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
<script lang="ts">import NodeView from './cmp.tree-node-view.svelte';
|
|
2
|
-
import {
|
|
3
|
-
let { nodes, showSelectedCheckmark,
|
|
2
|
+
import { createTreeKeyboard } from './tree-keyboard.svelte';
|
|
3
|
+
let { nodes, showSelectedCheckmark, header } = $props();
|
|
4
4
|
const nodesComputed = $derived(nodes ? (Array.isArray(nodes) ? nodes : [nodes]) : []);
|
|
5
5
|
const hideExpandIcon = $derived(nodesComputed.every((f) => !f.children.length));
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
e.currentTarget.focus();
|
|
13
|
-
};
|
|
6
|
+
$effect(() => {
|
|
7
|
+
for (const root of nodesComputed) {
|
|
8
|
+
root.setForest(() => nodesComputed);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const keyboard = createTreeKeyboard(() => nodesComputed);
|
|
14
12
|
</script>
|
|
15
13
|
|
|
16
14
|
<div class="tree">
|
|
17
|
-
{@render
|
|
18
|
-
<div
|
|
19
|
-
class="tree__nodes"
|
|
20
|
-
role="tree"
|
|
21
|
-
tabindex="0"
|
|
22
|
-
aria-activedescendant={nav.activeId ? `tree-item-${nav.activeId}` : undefined}
|
|
23
|
-
onfocusin={() => nav.focus()}
|
|
24
|
-
onfocusout={(e) => {
|
|
25
|
-
if (!(e.relatedTarget instanceof Node) || !e.currentTarget.contains(e.relatedTarget)) {
|
|
26
|
-
nav.blur();
|
|
27
|
-
}
|
|
28
|
-
}}
|
|
29
|
-
onkeydown={handleKeydown}>
|
|
15
|
+
{@render header?.()}
|
|
16
|
+
<div class="tree__nodes" role="tree">
|
|
30
17
|
{#each nodesComputed as node (node.id)}
|
|
31
|
-
<NodeView node={node}
|
|
18
|
+
<NodeView node={node} keyboard={keyboard} hideExpandIcon={hideExpandIcon} showSelectedCheckmark={showSelectedCheckmark} />
|
|
32
19
|
{/each}
|
|
33
20
|
</div>
|
|
34
21
|
</div>
|
|
@@ -40,9 +27,9 @@ holds its own expanded / selected state, children, optional icon / count / actio
|
|
|
40
27
|
drag config (reorder or move-to-folder). Build the model with `new TreeNode({ … })` and pass the
|
|
41
28
|
root(s) as `nodes`.
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
↑/↓ move between visible
|
|
45
|
-
Enter/Space select.
|
|
30
|
+
Click selects a node — selection is the single source of truth. Keyboard: the current row is the tab
|
|
31
|
+
stop (native focus + `:focus-visible`), ↑/↓ move between visible rows, →/← expand-or-enter / collapse-or-leave,
|
|
32
|
+
Home/End jump to first/last, Enter/Space select.
|
|
46
33
|
|
|
47
34
|
### CSS Custom Properties
|
|
48
35
|
| Property | Description | Default |
|
|
@@ -59,7 +46,4 @@ Enter/Space select.
|
|
|
59
46
|
}
|
|
60
47
|
.tree :global([contenteditable]) {
|
|
61
48
|
user-select: text;
|
|
62
|
-
}
|
|
63
|
-
.tree__nodes:focus-visible {
|
|
64
|
-
outline: none;
|
|
65
49
|
}</style>
|
|
@@ -2,11 +2,11 @@ import type { TreeNode } from './tree-node.svelte';
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
type Props = {
|
|
4
4
|
/** Root node, or array of root nodes. */
|
|
5
|
-
nodes: TreeNode | TreeNode[];
|
|
5
|
+
nodes: TreeNode | readonly TreeNode[];
|
|
6
6
|
/** Show a success checkmark on the selected node when it has no actions. */
|
|
7
7
|
showSelectedCheckmark?: boolean;
|
|
8
8
|
/** Optional content rendered above the nodes (e.g. a header). */
|
|
9
|
-
|
|
9
|
+
header?: Snippet;
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
12
|
* Tree — hierarchical, collapsible node list driven by `TreeNode` model instances. Each `TreeNode`
|
|
@@ -14,9 +14,9 @@ type Props = {
|
|
|
14
14
|
* drag config (reorder or move-to-folder). Build the model with `new TreeNode({ … })` and pass the
|
|
15
15
|
* root(s) as `nodes`.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* ↑/↓ move between visible
|
|
19
|
-
* Enter/Space select.
|
|
17
|
+
* Click selects a node — selection is the single source of truth. Keyboard: the current row is the tab
|
|
18
|
+
* stop (native focus + `:focus-visible`), ↑/↓ move between visible rows, →/← expand-or-enter / collapse-or-leave,
|
|
19
|
+
* Home/End jump to first/last, Enter/Space select.
|
|
20
20
|
*
|
|
21
21
|
* ### CSS Custom Properties
|
|
22
22
|
* | Property | Description | Default |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TreeNode } from './tree-node.svelte';
|
|
2
|
+
/** Native-focus roving keyboard navigation for the tree (single tab stop + arrows / Home / End / Enter). */
|
|
3
|
+
export declare const createTreeKeyboard: (getRoots: () => readonly TreeNode[]) => {
|
|
4
|
+
anchorId: (node: TreeNode) => string;
|
|
5
|
+
readonly currentId: string | null;
|
|
6
|
+
setFocused: (id: string) => void;
|
|
7
|
+
handleKeydown: (node: TreeNode, e: KeyboardEvent) => void;
|
|
8
|
+
};
|
|
9
|
+
export type TreeKeyboard = ReturnType<typeof createTreeKeyboard>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { randomNanoid } from '../../core/utils';
|
|
2
|
+
import { tick } from 'svelte';
|
|
3
|
+
/** Native-focus roving keyboard navigation for the tree (single tab stop + arrows / Home / End / Enter). */
|
|
4
|
+
export const createTreeKeyboard = (getRoots) => {
|
|
5
|
+
const treeId = randomNanoid(6);
|
|
6
|
+
const anchorDomId = (node) => `tree-${treeId}-anchor-${node.id}`;
|
|
7
|
+
let focusedId = $state(null);
|
|
8
|
+
const visible = () => {
|
|
9
|
+
const out = [];
|
|
10
|
+
const walk = (list) => {
|
|
11
|
+
for (const node of list) {
|
|
12
|
+
out.push(node);
|
|
13
|
+
if (node.expanded && node.children.length) {
|
|
14
|
+
walk(node.children);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
walk(getRoots());
|
|
19
|
+
return out;
|
|
20
|
+
};
|
|
21
|
+
const currentId = $derived.by(() => {
|
|
22
|
+
const rows = visible();
|
|
23
|
+
if (focusedId && rows.some((n) => n.id === focusedId)) {
|
|
24
|
+
return focusedId;
|
|
25
|
+
}
|
|
26
|
+
return (rows.find((n) => n.selected) ?? rows[0])?.id ?? null;
|
|
27
|
+
});
|
|
28
|
+
const focusNode = (node) => {
|
|
29
|
+
focusedId = node.id;
|
|
30
|
+
document.getElementById(anchorDomId(node))?.focus();
|
|
31
|
+
};
|
|
32
|
+
const focusAfterTick = async (node) => {
|
|
33
|
+
await tick();
|
|
34
|
+
focusNode(node);
|
|
35
|
+
};
|
|
36
|
+
const step = (node, delta) => {
|
|
37
|
+
const rows = visible();
|
|
38
|
+
const index = rows.findIndex((n) => n.id === node.id);
|
|
39
|
+
if (index < 0) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const next = rows[Math.min(Math.max(index + delta, 0), rows.length - 1)];
|
|
43
|
+
if (next.id !== node.id) {
|
|
44
|
+
focusNode(next);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
anchorId: anchorDomId,
|
|
49
|
+
get currentId() {
|
|
50
|
+
return currentId;
|
|
51
|
+
},
|
|
52
|
+
setFocused: (id) => {
|
|
53
|
+
focusedId = id;
|
|
54
|
+
},
|
|
55
|
+
handleKeydown: (node, e) => {
|
|
56
|
+
switch (e.key) {
|
|
57
|
+
case 'ArrowDown':
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
step(node, 1);
|
|
60
|
+
break;
|
|
61
|
+
case 'ArrowUp':
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
step(node, -1);
|
|
64
|
+
break;
|
|
65
|
+
case 'ArrowRight':
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
if (node.children.length && !node.expanded) {
|
|
68
|
+
node.expand();
|
|
69
|
+
}
|
|
70
|
+
else if (node.children.length) {
|
|
71
|
+
void focusAfterTick(node.children[0]);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
case 'ArrowLeft':
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
if (node.expanded && node.children.length) {
|
|
77
|
+
node.collapse();
|
|
78
|
+
}
|
|
79
|
+
else if (node.parent) {
|
|
80
|
+
focusNode(node.parent);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case 'Home': {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
const rows = visible();
|
|
86
|
+
if (rows.length) {
|
|
87
|
+
focusNode(rows[0]);
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'End': {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
const rows = visible();
|
|
94
|
+
if (rows.length) {
|
|
95
|
+
focusNode(rows[rows.length - 1]);
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'Enter':
|
|
100
|
+
case ' ':
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
node.select({ explicitly: true });
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
};
|
|
@@ -45,6 +45,7 @@ export declare class TreeNode {
|
|
|
45
45
|
private _nonSelectable;
|
|
46
46
|
private _children;
|
|
47
47
|
private _parent?;
|
|
48
|
+
private _forestRoots?;
|
|
48
49
|
private _dirty;
|
|
49
50
|
constructor(init: TreeNodeInitializer);
|
|
50
51
|
/** Whether this node has unsaved changes; set via `setDirty` and propagated up to ancestors. */
|
|
@@ -62,6 +63,8 @@ export declare class TreeNode {
|
|
|
62
63
|
select(options?: {
|
|
63
64
|
explicitly?: boolean;
|
|
64
65
|
}): void;
|
|
66
|
+
/** Register the full set of forest roots so single-select clears across sibling roots, not just this node's own root. Set by the `Tree` component. */
|
|
67
|
+
setForest(getRoots: () => readonly TreeNode[]): void;
|
|
65
68
|
setChildren(value: TreeNode[]): void;
|
|
66
69
|
addChild(child: TreeNode): void;
|
|
67
70
|
insertChildAt(index: number, child: TreeNode): void;
|
|
@@ -74,8 +77,9 @@ export declare class TreeNode {
|
|
|
74
77
|
flatten(): TreeNode[];
|
|
75
78
|
canMoveToParent(targetParent: TreeNode): boolean;
|
|
76
79
|
moveToFolder(targetFolder: TreeNode): boolean;
|
|
77
|
-
private
|
|
80
|
+
private _refreshParentRefs;
|
|
78
81
|
private _select;
|
|
79
|
-
private
|
|
80
|
-
private
|
|
82
|
+
private _firstSelectable;
|
|
83
|
+
private _unselectNodeAndChildren;
|
|
84
|
+
private _buildChainToCurrentNode;
|
|
81
85
|
}
|
|
@@ -20,6 +20,7 @@ export class TreeNode {
|
|
|
20
20
|
_nonSelectable;
|
|
21
21
|
_children = $state([]);
|
|
22
22
|
_parent;
|
|
23
|
+
_forestRoots;
|
|
23
24
|
_dirty = $state(false);
|
|
24
25
|
constructor(init) {
|
|
25
26
|
this.id = init.id || this.id;
|
|
@@ -76,9 +77,13 @@ export class TreeNode {
|
|
|
76
77
|
select(options) {
|
|
77
78
|
this._select(options?.explicitly ?? false);
|
|
78
79
|
}
|
|
80
|
+
/** Register the full set of forest roots so single-select clears across sibling roots, not just this node's own root. Set by the `Tree` component. */
|
|
81
|
+
setForest(getRoots) {
|
|
82
|
+
this._forestRoots = getRoots;
|
|
83
|
+
}
|
|
79
84
|
setChildren(value) {
|
|
80
85
|
this._children = value;
|
|
81
|
-
this.
|
|
86
|
+
this._refreshParentRefs(value);
|
|
82
87
|
}
|
|
83
88
|
addChild(child) {
|
|
84
89
|
child._parent = this;
|
|
@@ -105,7 +110,7 @@ export class TreeNode {
|
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
notifyHover(mouseOver) {
|
|
108
|
-
const selectionPath = this.
|
|
113
|
+
const selectionPath = this._buildChainToCurrentNode(this);
|
|
109
114
|
for (const item of selectionPath) {
|
|
110
115
|
if (item._onNodeHover) {
|
|
111
116
|
if (mouseOver) {
|
|
@@ -128,7 +133,7 @@ export class TreeNode {
|
|
|
128
133
|
this._expanded = true;
|
|
129
134
|
}
|
|
130
135
|
unselect() {
|
|
131
|
-
this.
|
|
136
|
+
this._unselectNodeAndChildren(this);
|
|
132
137
|
}
|
|
133
138
|
flatten() {
|
|
134
139
|
const result = [];
|
|
@@ -168,26 +173,25 @@ export class TreeNode {
|
|
|
168
173
|
this._dragConfig.onNodeMovedToFolder({ movedNode: this, targetFolder });
|
|
169
174
|
return true;
|
|
170
175
|
}
|
|
171
|
-
|
|
176
|
+
_refreshParentRefs(children) {
|
|
172
177
|
for (const child of children) {
|
|
173
178
|
child._parent = this;
|
|
174
179
|
if (child._children.length) {
|
|
175
|
-
child.
|
|
180
|
+
child._refreshParentRefs(child._children);
|
|
176
181
|
}
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
_select(selectedExplicitly) {
|
|
180
185
|
if (this._nonSelectable) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
return this._children[0]._select(selectedExplicitly);
|
|
186
|
+
this._firstSelectable()?._select(selectedExplicitly);
|
|
187
|
+
return;
|
|
185
188
|
}
|
|
186
|
-
|
|
187
|
-
const selectionPath = this.buildChainToCurrentNode(this);
|
|
188
|
-
// unselect previously selected values
|
|
189
|
+
const selectionPath = this._buildChainToCurrentNode(this);
|
|
189
190
|
const root = selectionPath[selectionPath.length - 1];
|
|
190
|
-
|
|
191
|
+
const roots = root._forestRoots?.() ?? [root];
|
|
192
|
+
for (const r of roots) {
|
|
193
|
+
this._unselectNodeAndChildren(r);
|
|
194
|
+
}
|
|
191
195
|
// process selection path
|
|
192
196
|
this._selected = true;
|
|
193
197
|
if (selectionPath.length > 1) {
|
|
@@ -209,7 +213,19 @@ export class TreeNode {
|
|
|
209
213
|
}
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
|
-
|
|
216
|
+
_firstSelectable() {
|
|
217
|
+
if (!this._nonSelectable) {
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
for (const child of this._children) {
|
|
221
|
+
const found = child._firstSelectable();
|
|
222
|
+
if (found) {
|
|
223
|
+
return found;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
_unselectNodeAndChildren(node) {
|
|
213
229
|
node._involvedIntoActivePath = false;
|
|
214
230
|
node._selected = false;
|
|
215
231
|
const children = node._children;
|
|
@@ -217,10 +233,10 @@ export class TreeNode {
|
|
|
217
233
|
return;
|
|
218
234
|
}
|
|
219
235
|
children.forEach((f) => {
|
|
220
|
-
this.
|
|
236
|
+
this._unselectNodeAndChildren(f);
|
|
221
237
|
});
|
|
222
238
|
}
|
|
223
|
-
|
|
239
|
+
_buildChainToCurrentNode(node) {
|
|
224
240
|
const chain = [];
|
|
225
241
|
let current = node;
|
|
226
242
|
while (current) {
|
package/package.json
CHANGED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { Icon } from '../icon';
|
|
2
|
-
import { Toggle } from '../toggle';
|
|
3
|
-
import IconReorderDotsVertical from '@fluentui/svg-icons/icons/re_order_dots_vertical_20_regular.svg?raw';
|
|
4
|
-
import { flip } from 'svelte/animate';
|
|
5
|
-
import { dndzone } from 'svelte-dnd-action';
|
|
6
|
-
let { items, on } = $props();
|
|
7
|
-
const reorderableItems = $derived(items.filter((i) => !i.fixed));
|
|
8
|
-
const fixedItems = $derived(items.filter((i) => i.fixed));
|
|
9
|
-
let dndItems = $state.raw([]);
|
|
10
|
-
$effect(() => {
|
|
11
|
-
dndItems = reorderableItems.map(({ id, label, enabled }) => ({ id, label, enabled }));
|
|
12
|
-
});
|
|
13
|
-
const flipDurationMs = 200;
|
|
14
|
-
const emitChange = (reordered) => {
|
|
15
|
-
const merged = [
|
|
16
|
-
...fixedItems.map(({ id, label, enabled, fixed }) => ({ id, label, enabled, fixed })),
|
|
17
|
-
...reordered.map(({ id, label, enabled }) => ({ id, label, enabled }))
|
|
18
|
-
];
|
|
19
|
-
on.change(merged);
|
|
20
|
-
};
|
|
21
|
-
const handleConsider = (e) => {
|
|
22
|
-
dndItems = e.detail.items;
|
|
23
|
-
};
|
|
24
|
-
const handleFinalize = (e) => {
|
|
25
|
-
emitChange(e.detail.items);
|
|
26
|
-
};
|
|
27
|
-
const handleToggle = (id, enabled) => {
|
|
28
|
-
emitChange(dndItems.map((i) => (i.id === id ? { ...i, enabled } : i)));
|
|
29
|
-
};
|
|
30
|
-
const handleFixedToggle = (id, enabled) => {
|
|
31
|
-
const updatedFixed = fixedItems.map(({ id: fId, label, enabled: fEnabled, fixed }) => ({
|
|
32
|
-
id: fId,
|
|
33
|
-
label,
|
|
34
|
-
enabled: fId === id ? enabled : fEnabled,
|
|
35
|
-
fixed
|
|
36
|
-
}));
|
|
37
|
-
on.change([...updatedFixed, ...dndItems.map(({ id, label, enabled }) => ({ id, label, enabled }))]);
|
|
38
|
-
};
|
|
39
|
-
</script>
|
|
40
|
-
|
|
41
|
-
<div class="reorderable-toggle-list">
|
|
42
|
-
{#each fixedItems as item (item.id)}
|
|
43
|
-
<div class="reorderable-toggle-list__item">
|
|
44
|
-
<div class="reorderable-toggle-list__drag-handle reorderable-toggle-list__drag-handle--hidden">
|
|
45
|
-
<Icon src={IconReorderDotsVertical} />
|
|
46
|
-
</div>
|
|
47
|
-
<div class="reorderable-toggle-list__label">
|
|
48
|
-
{item.label}
|
|
49
|
-
</div>
|
|
50
|
-
<div class="reorderable-toggle-list__toggle">
|
|
51
|
-
<Toggle
|
|
52
|
-
checked={item.enabled}
|
|
53
|
-
on={{
|
|
54
|
-
change: (value) => handleFixedToggle(item.id, value)
|
|
55
|
-
}} />
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
{/each}
|
|
59
|
-
<div
|
|
60
|
-
class="reorderable-toggle-list__dnd"
|
|
61
|
-
use:dndzone={{
|
|
62
|
-
items: dndItems,
|
|
63
|
-
dropTargetStyle: {},
|
|
64
|
-
flipDurationMs,
|
|
65
|
-
morphDisabled: true
|
|
66
|
-
}}
|
|
67
|
-
onconsider={handleConsider}
|
|
68
|
-
onfinalize={handleFinalize}>
|
|
69
|
-
{#each dndItems as item (item.id)}
|
|
70
|
-
<div class="reorderable-toggle-list__item" animate:flip={{ duration: flipDurationMs }}>
|
|
71
|
-
<div class="reorderable-toggle-list__drag-handle">
|
|
72
|
-
<Icon src={IconReorderDotsVertical} />
|
|
73
|
-
</div>
|
|
74
|
-
<div class="reorderable-toggle-list__label">
|
|
75
|
-
{item.label}
|
|
76
|
-
</div>
|
|
77
|
-
<div class="reorderable-toggle-list__toggle">
|
|
78
|
-
<Toggle
|
|
79
|
-
checked={item.enabled}
|
|
80
|
-
on={{
|
|
81
|
-
change: (value) => handleToggle(item.id, value)
|
|
82
|
-
}} />
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
{/each}
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<!--
|
|
90
|
-
@component
|
|
91
|
-
A reorderable list of toggle items with drag-and-drop support. Fixed items appear above the reorderable zone.
|
|
92
|
-
|
|
93
|
-
### CSS Custom Properties
|
|
94
|
-
| Property | Description | Default |
|
|
95
|
-
|---|---|---|
|
|
96
|
-
| `--sc-kit--reorderable-toggle-list--label--color` | Label text color | `var(--sc-kit--color--text--primary)` |
|
|
97
|
-
| `--sc-kit--reorderable-toggle-list--handle--color` | Drag handle icon color | `var(--sc-kit--color--text--secondary)` |
|
|
98
|
-
| `--sc-kit--reorderable-toggle-list--handle--background` | Drag handle background | `var(--sc-kit--color--bg--element)` |
|
|
99
|
-
-->
|
|
100
|
-
|
|
101
|
-
<style>.reorderable-toggle-list {
|
|
102
|
-
--_reorderable-toggle-list--label--color: var(--sc-kit--reorderable-toggle-list--label--color, var(--sc-kit--color--text--primary));
|
|
103
|
-
--_reorderable-toggle-list--handle--color: var(--sc-kit--reorderable-toggle-list--handle--color, var(--sc-kit--color--text--secondary));
|
|
104
|
-
--_reorderable-toggle-list--handle--background: var(--sc-kit--reorderable-toggle-list--handle--background, var(--sc-kit--color--bg--element));
|
|
105
|
-
display: flex;
|
|
106
|
-
flex-direction: column;
|
|
107
|
-
gap: var(--sc-kit--space--3);
|
|
108
|
-
}
|
|
109
|
-
.reorderable-toggle-list__dnd {
|
|
110
|
-
display: flex;
|
|
111
|
-
flex-direction: column;
|
|
112
|
-
gap: var(--sc-kit--space--3);
|
|
113
|
-
}
|
|
114
|
-
.reorderable-toggle-list__item {
|
|
115
|
-
display: flex;
|
|
116
|
-
align-items: center;
|
|
117
|
-
gap: var(--sc-kit--space--3);
|
|
118
|
-
padding: var(--sc-kit--space--1) var(--sc-kit--space--2);
|
|
119
|
-
}
|
|
120
|
-
.reorderable-toggle-list__drag-handle {
|
|
121
|
-
--sc-kit--icon--size: 1rem;
|
|
122
|
-
--sc-kit--icon--color: var(--_reorderable-toggle-list--handle--color);
|
|
123
|
-
display: flex;
|
|
124
|
-
align-items: center;
|
|
125
|
-
justify-content: center;
|
|
126
|
-
height: 1.375rem;
|
|
127
|
-
padding-inline: 0.1875rem;
|
|
128
|
-
border-radius: var(--sc-kit--radius--sm) 0 0 var(--sc-kit--radius--sm);
|
|
129
|
-
cursor: grab;
|
|
130
|
-
background: var(--_reorderable-toggle-list--handle--background);
|
|
131
|
-
}
|
|
132
|
-
.reorderable-toggle-list__drag-handle:active {
|
|
133
|
-
cursor: grabbing;
|
|
134
|
-
}
|
|
135
|
-
.reorderable-toggle-list__drag-handle--hidden {
|
|
136
|
-
visibility: hidden;
|
|
137
|
-
}
|
|
138
|
-
.reorderable-toggle-list__label {
|
|
139
|
-
flex: 1;
|
|
140
|
-
min-width: 0;
|
|
141
|
-
font-size: var(--sc-kit--font-size--md);
|
|
142
|
-
font-weight: var(--sc-kit--font-weight--regular);
|
|
143
|
-
line-height: var(--sc-kit--line-height--md);
|
|
144
|
-
color: var(--_reorderable-toggle-list--label--color);
|
|
145
|
-
text-overflow: ellipsis;
|
|
146
|
-
max-width: 100%;
|
|
147
|
-
white-space: nowrap;
|
|
148
|
-
overflow: hidden;
|
|
149
|
-
}
|
|
150
|
-
.reorderable-toggle-list__toggle {
|
|
151
|
-
flex-shrink: 0;
|
|
152
|
-
margin-left: auto;
|
|
153
|
-
}</style>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ReorderableToggleItem } from './types';
|
|
2
|
-
type Props = {
|
|
3
|
-
items: ReorderableToggleItem[];
|
|
4
|
-
on: {
|
|
5
|
-
change: (items: ReorderableToggleItem[]) => void;
|
|
6
|
-
};
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* A reorderable list of toggle items with drag-and-drop support. Fixed items appear above the reorderable zone.
|
|
10
|
-
*
|
|
11
|
-
* ### CSS Custom Properties
|
|
12
|
-
* | Property | Description | Default |
|
|
13
|
-
* |---|---|---|
|
|
14
|
-
* | `--sc-kit--reorderable-toggle-list--label--color` | Label text color | `var(--sc-kit--color--text--primary)` |
|
|
15
|
-
* | `--sc-kit--reorderable-toggle-list--handle--color` | Drag handle icon color | `var(--sc-kit--color--text--secondary)` |
|
|
16
|
-
* | `--sc-kit--reorderable-toggle-list--handle--background` | Drag handle background | `var(--sc-kit--color--bg--element)` |
|
|
17
|
-
*/
|
|
18
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
19
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
20
|
-
export default Cmp;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { Checkbox } from '../checkbox';
|
|
2
|
-
const { checked, children, on } = $props();
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="toolbar-checkbox-item">
|
|
6
|
-
<Checkbox checked={checked} label={children} on={{ change: (value) => on?.change?.(value) }} />
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<!--
|
|
10
|
-
@component
|
|
11
|
-
A checkbox item for toolbar panels. Wraps the kit Checkbox with toolbar-appropriate sizing.
|
|
12
|
-
-->
|
|
13
|
-
|
|
14
|
-
<style>.toolbar-checkbox-item {
|
|
15
|
-
padding: var(--sc-kit--space--1) var(--sc-kit--space--2);
|
|
16
|
-
overflow: hidden;
|
|
17
|
-
--sc-kit--checkbox--gap: var(--sc-kit--space--5);
|
|
18
|
-
--sc-kit--checkbox--icon--size: 1.125rem;
|
|
19
|
-
}</style>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type Props = {
|
|
3
|
-
checked: boolean;
|
|
4
|
-
children: Snippet;
|
|
5
|
-
on?: {
|
|
6
|
-
change?: (value: boolean) => void;
|
|
7
|
-
};
|
|
8
|
-
};
|
|
9
|
-
/** A checkbox item for toolbar panels. Wraps the kit Checkbox with toolbar-appropriate sizing. */
|
|
10
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
11
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
12
|
-
export default Cmp;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<script lang="ts">const { children, on } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<button type="button" class="toolbar-panel-button" onclick={() => on?.click?.()}>
|
|
6
|
-
{@render children()}
|
|
7
|
-
</button>
|
|
8
|
-
|
|
9
|
-
<!--
|
|
10
|
-
@component
|
|
11
|
-
A text-row button for toolbar panels / popovers (rendered inside `<ToolbarPanel>` / `<ToolbarPopover>`).
|
|
12
|
-
For the toolbar's primary action area use `<ToolbarButton>` instead.
|
|
13
|
-
|
|
14
|
-
### CSS Custom Properties
|
|
15
|
-
| Property | Description | Default |
|
|
16
|
-
|---|---|---|
|
|
17
|
-
| `--sc-kit--toolbar-panel-button--color` | Text color | `var(--sc-kit--color--text--primary)` |
|
|
18
|
-
| `--sc-kit--toolbar-panel-button--color-hover` | Text color on hover | `var(--sc-kit--color--accent)` |
|
|
19
|
-
-->
|
|
20
|
-
|
|
21
|
-
<style>.toolbar-panel-button {
|
|
22
|
-
--_toolbar-panel-button--color: var(--sc-kit--toolbar-panel-button--color, var(--sc-kit--color--text--primary));
|
|
23
|
-
--_toolbar-panel-button--color-hover: var(--sc-kit--toolbar-panel-button--color-hover, var(--sc-kit--color--accent));
|
|
24
|
-
appearance: none;
|
|
25
|
-
background: transparent;
|
|
26
|
-
border: 0;
|
|
27
|
-
text-align: inherit;
|
|
28
|
-
cursor: pointer;
|
|
29
|
-
font-size: var(--sc-kit--font-size--md);
|
|
30
|
-
font-weight: var(--sc-kit--font-weight--regular);
|
|
31
|
-
line-height: var(--sc-kit--line-height--md);
|
|
32
|
-
color: var(--_toolbar-panel-button--color);
|
|
33
|
-
padding: var(--sc-kit--space--1) var(--sc-kit--space--2);
|
|
34
|
-
max-width: 100%;
|
|
35
|
-
text-overflow: ellipsis;
|
|
36
|
-
max-width: 100%;
|
|
37
|
-
white-space: nowrap;
|
|
38
|
-
overflow: hidden;
|
|
39
|
-
}
|
|
40
|
-
.toolbar-panel-button:hover {
|
|
41
|
-
color: var(--_toolbar-panel-button--color-hover);
|
|
42
|
-
}</style>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type Props = {
|
|
3
|
-
children: Snippet;
|
|
4
|
-
on?: {
|
|
5
|
-
click?: () => void;
|
|
6
|
-
};
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* A text-row button for toolbar panels / popovers (rendered inside `<ToolbarPanel>` / `<ToolbarPopover>`).
|
|
10
|
-
* For the toolbar's primary action area use `<ToolbarButton>` instead.
|
|
11
|
-
*
|
|
12
|
-
* ### CSS Custom Properties
|
|
13
|
-
* | Property | Description | Default |
|
|
14
|
-
* |---|---|---|
|
|
15
|
-
* | `--sc-kit--toolbar-panel-button--color` | Text color | `var(--sc-kit--color--text--primary)` |
|
|
16
|
-
* | `--sc-kit--toolbar-panel-button--color-hover` | Text color on hover | `var(--sc-kit--color--accent)` |
|
|
17
|
-
*/
|
|
18
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
19
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
20
|
-
export default Cmp;
|