@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.
Files changed (91) hide show
  1. package/dist/ui/badge/cmp.badge.svelte +4 -0
  2. package/dist/ui/badge/cmp.badge.svelte.d.ts +1 -0
  3. package/dist/ui/page-toolbar/cmp.reorderable-checkbox-list.svelte +131 -0
  4. package/dist/ui/page-toolbar/cmp.reorderable-checkbox-list.svelte.d.ts +31 -0
  5. package/dist/ui/page-toolbar/cmp.toolbar-checkbox.svelte +14 -0
  6. package/dist/ui/page-toolbar/cmp.toolbar-checkbox.svelte.d.ts +19 -0
  7. package/dist/ui/page-toolbar/cmp.toolbar-divider.svelte +19 -0
  8. package/dist/ui/page-toolbar/cmp.toolbar-divider.svelte.d.ts +35 -0
  9. package/dist/ui/page-toolbar/cmp.toolbar-filter-select.svelte +143 -0
  10. package/dist/ui/page-toolbar/cmp.toolbar-filter-select.svelte.d.ts +68 -0
  11. package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte +71 -0
  12. package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte.d.ts +32 -0
  13. package/dist/ui/page-toolbar/cmp.toolbar-option.svelte +189 -0
  14. package/dist/ui/page-toolbar/cmp.toolbar-option.svelte.d.ts +47 -0
  15. package/dist/ui/page-toolbar/cmp.toolbar-popover.svelte +23 -8
  16. package/dist/ui/page-toolbar/cmp.toolbar-popover.svelte.d.ts +14 -6
  17. package/dist/ui/page-toolbar/cmp.toolbar-section-title.svelte +46 -0
  18. package/dist/ui/page-toolbar/cmp.toolbar-section-title.svelte.d.ts +24 -0
  19. package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte +31 -0
  20. package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte.d.ts +44 -0
  21. package/dist/ui/page-toolbar/{cmp.toolbar-switch-item.svelte → cmp.toolbar-switch.svelte} +10 -10
  22. package/dist/ui/page-toolbar/{cmp.toolbar-switch-item.svelte.d.ts → cmp.toolbar-switch.svelte.d.ts} +2 -2
  23. package/dist/ui/page-toolbar/cmp.toolbar-toggle.svelte +14 -0
  24. package/dist/ui/page-toolbar/cmp.toolbar-toggle.svelte.d.ts +19 -0
  25. package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte +51 -0
  26. package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte.d.ts +27 -0
  27. package/dist/ui/page-toolbar/index.d.ts +12 -7
  28. package/dist/ui/page-toolbar/index.js +11 -6
  29. package/dist/ui/page-toolbar/reorderable-checkbox-list-localization.d.ts +5 -0
  30. package/dist/ui/page-toolbar/reorderable-checkbox-list-localization.js +17 -0
  31. package/dist/ui/page-toolbar/toolbar-filter-select-localization.d.ts +5 -0
  32. package/dist/ui/page-toolbar/toolbar-filter-select-localization.js +20 -0
  33. package/dist/ui/page-toolbar/toolbar-sort-select-localization.d.ts +3 -0
  34. package/dist/ui/page-toolbar/toolbar-sort-select-localization.js +9 -0
  35. package/dist/ui/page-toolbar/toolbar-view-controls-localization.d.ts +5 -0
  36. package/dist/ui/page-toolbar/toolbar-view-controls-localization.js +17 -0
  37. package/dist/ui/page-toolbar/types.d.ts +1 -1
  38. package/dist/ui/select/index.d.ts +1 -0
  39. package/dist/ui/select/index.js +1 -0
  40. package/dist/ui/select/select-listbox.svelte +11 -5
  41. package/dist/ui/select/select-listbox.svelte.d.ts +1 -1
  42. package/dist/ui/table/_table-styles.scss +156 -0
  43. package/dist/ui/table/cmp.table-draggable.svelte +338 -0
  44. package/dist/ui/table/cmp.table-draggable.svelte.d.ts +79 -0
  45. package/dist/ui/table/cmp.table.svelte +96 -265
  46. package/dist/ui/table/cmp.table.svelte.d.ts +16 -8
  47. package/dist/ui/table/index.d.ts +1 -0
  48. package/dist/ui/table/index.js +1 -0
  49. package/dist/ui/table/table-cells/index.d.ts +1 -12
  50. package/dist/ui/table/table-cells/index.js +1 -12
  51. package/dist/ui/table/table-cells/table-cell.svelte +77 -0
  52. package/dist/ui/table/table-cells/{table-select-cell.svelte.d.ts → table-cell.svelte.d.ts} +12 -6
  53. package/dist/ui/table/table-column-models.svelte.d.ts +1 -2
  54. package/dist/ui/table/table-column-models.svelte.js +0 -1
  55. package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte +20 -47
  56. package/dist/ui/table/table-columns-manager/cmp.table-columns-manager.svelte.d.ts +3 -7
  57. package/dist/ui/table/table-columns-manager/table-columns-manager-localization.d.ts +1 -1
  58. package/dist/ui/table/table-columns-manager/table-columns-manager-localization.js +7 -7
  59. package/dist/ui/table/table-localization.d.ts +0 -2
  60. package/dist/ui/table/table-localization.js +0 -14
  61. package/dist/ui/table/table-model.svelte.d.ts +2 -3
  62. package/dist/ui/table/table-model.svelte.js +5 -35
  63. package/dist/ui/table/table-view.svelte.d.ts +14 -0
  64. package/dist/ui/table/table-view.svelte.js +32 -0
  65. package/dist/ui/table/types.d.ts +5 -28
  66. package/dist/ui/toggle/cmp.toggle.svelte +32 -26
  67. package/dist/ui/toggle/cmp.toggle.svelte.d.ts +2 -0
  68. package/dist/ui/tree/cmp.tree-node-view.svelte +16 -10
  69. package/dist/ui/tree/cmp.tree-node-view.svelte.d.ts +2 -2
  70. package/dist/ui/tree/cmp.tree.svelte +14 -30
  71. package/dist/ui/tree/cmp.tree.svelte.d.ts +5 -5
  72. package/dist/ui/tree/tree-keyboard.svelte.d.ts +9 -0
  73. package/dist/ui/tree/tree-keyboard.svelte.js +107 -0
  74. package/dist/ui/tree/tree-node.svelte.d.ts +7 -3
  75. package/dist/ui/tree/tree-node.svelte.js +32 -16
  76. package/package.json +1 -1
  77. package/dist/ui/page-toolbar/cmp.reorderable-toggle-list.svelte +0 -153
  78. package/dist/ui/page-toolbar/cmp.reorderable-toggle-list.svelte.d.ts +0 -20
  79. package/dist/ui/page-toolbar/cmp.toolbar-checkbox-item.svelte +0 -19
  80. package/dist/ui/page-toolbar/cmp.toolbar-checkbox-item.svelte.d.ts +0 -12
  81. package/dist/ui/page-toolbar/cmp.toolbar-panel-button.svelte +0 -42
  82. package/dist/ui/page-toolbar/cmp.toolbar-panel-button.svelte.d.ts +0 -20
  83. package/dist/ui/page-toolbar/cmp.toolbar-panel.svelte +0 -57
  84. package/dist/ui/page-toolbar/cmp.toolbar-panel.svelte.d.ts +0 -19
  85. package/dist/ui/page-toolbar/cmp.toolbar-toggle-item.svelte +0 -16
  86. package/dist/ui/page-toolbar/cmp.toolbar-toggle-item.svelte.d.ts +0 -12
  87. package/dist/ui/table/table-cells/table-select-cell.svelte +0 -28
  88. package/dist/ui/table/table-cells/table-text-input-cell.svelte +0 -69
  89. package/dist/ui/table/table-cells/table-text-input-cell.svelte.d.ts +0 -38
  90. package/dist/ui/tree/tree-navigation.svelte.d.ts +0 -14
  91. 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 { TreeNavigation } from './tree-navigation.svelte';
3
- let { nodes, showSelectedCheckmark, children } = $props();
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
- const nav = new TreeNavigation(() => nodesComputed);
7
- const handleKeydown = (e) => {
8
- nav.handleKeydown(e);
9
- // ArrowLeft collapses a subtree; if focus sat on a treeitem inside it, the unmount would drop focus
10
- // to <body> and arrow keys would die. Re-grab the container before the unmount so the single
11
- // aria-activedescendant focus owner stays put.
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 children?.()}
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} nav={nav} hideExpandIcon={hideExpandIcon} showSelectedCheckmark={showSelectedCheckmark} />
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
- Exposes an ARIA `tree` / `treeitem` / `group` structure with `aria-activedescendant` focus. Keyboard:
44
- ↑/↓ move between visible items, →/← expand-or-enter / collapse-or-leave, Home/End jump to first/last,
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
- children?: Snippet;
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
- * Exposes an ARIA `tree` / `treeitem` / `group` structure with `aria-activedescendant` focus. Keyboard:
18
- * ↑/↓ move between visible items, →/← expand-or-enter / collapse-or-leave, Home/End jump to first/last,
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 refreshParentRefs;
80
+ private _refreshParentRefs;
78
81
  private _select;
79
- private unselectNodeAndChildren;
80
- private buildChainToCurrentNode;
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.refreshParentRefs(value);
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.buildChainToCurrentNode(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.unselectNodeAndChildren(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
- refreshParentRefs(children) {
176
+ _refreshParentRefs(children) {
172
177
  for (const child of children) {
173
178
  child._parent = this;
174
179
  if (child._children.length) {
175
- child.refreshParentRefs(child._children);
180
+ child._refreshParentRefs(child._children);
176
181
  }
177
182
  }
178
183
  }
179
184
  _select(selectedExplicitly) {
180
185
  if (this._nonSelectable) {
181
- if (!this._children.length) {
182
- return;
183
- }
184
- return this._children[0]._select(selectedExplicitly);
186
+ this._firstSelectable()?._select(selectedExplicitly);
187
+ return;
185
188
  }
186
- // generate selection path (all nodes involved into current path)
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
- this.unselectNodeAndChildren(root);
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
- unselectNodeAndChildren(node) {
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.unselectNodeAndChildren(f);
236
+ this._unselectNodeAndChildren(f);
221
237
  });
222
238
  }
223
- buildChainToCurrentNode(node) {
239
+ _buildChainToCurrentNode(node) {
224
240
  const chain = [];
225
241
  let current = node;
226
242
  while (current) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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;