@svadmin/ui 0.72.0 → 0.73.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 (252) hide show
  1. package/README.md +40 -25
  2. package/THIRD_PARTY_NOTICES.md +52 -0
  3. package/dist/app.css +7694 -5117
  4. package/dist/app.theme.css +7645 -5119
  5. package/dist/class-properties.generated.d.ts +1 -0
  6. package/dist/class-properties.generated.js +2 -0
  7. package/dist/classnames.d.ts +8 -0
  8. package/dist/classnames.js +26 -0
  9. package/dist/components/AutoForm.svelte +20 -6
  10. package/dist/components/AutoForm.svelte.d.ts +2 -0
  11. package/dist/components/AutoTable.svelte +249 -9
  12. package/dist/components/AutoTable.svelte.d.ts +5 -0
  13. package/dist/components/BoundRecordDetailDrawer.svelte +8 -2
  14. package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +2 -0
  15. package/dist/components/ComboboxField.svelte +31 -9
  16. package/dist/components/ComboboxField.svelte.d.ts +3 -2
  17. package/dist/components/CreatePage.svelte +4 -0
  18. package/dist/components/CreatePage.svelte.d.ts +2 -0
  19. package/dist/components/DateRangeInput.svelte +75 -0
  20. package/dist/components/DateRangeInput.svelte.d.ts +25 -0
  21. package/dist/components/DateTimeInput.svelte +65 -0
  22. package/dist/components/DateTimeInput.svelte.d.ts +19 -0
  23. package/dist/components/DevTools.svelte +2 -2
  24. package/dist/components/EditPage.svelte +4 -0
  25. package/dist/components/EditPage.svelte.d.ts +2 -0
  26. package/dist/components/FieldRenderer.svelte +90 -18
  27. package/dist/components/FileUpload.svelte +250 -0
  28. package/dist/components/FileUpload.svelte.d.ts +32 -0
  29. package/dist/components/FilterBuilder.svelte +236 -279
  30. package/dist/components/FilterBuilder.svelte.d.ts +3 -0
  31. package/dist/components/ImportWizard.svelte +181 -94
  32. package/dist/components/JsonSchemaForm.svelte +255 -99
  33. package/dist/components/JsonSchemaForm.svelte.d.ts +12 -1
  34. package/dist/components/Layout.svelte +1 -2
  35. package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +1 -1
  36. package/dist/components/ListPage.svelte +4 -0
  37. package/dist/components/ListPage.svelte.d.ts +2 -0
  38. package/dist/components/LoginPage.svelte +1 -1
  39. package/dist/components/MoneyInput.svelte +25 -0
  40. package/dist/components/MoneyInput.svelte.d.ts +20 -0
  41. package/dist/components/NumberInput.svelte +25 -0
  42. package/dist/components/NumberInput.svelte.d.ts +19 -0
  43. package/dist/components/NumericInput.svelte +110 -0
  44. package/dist/components/NumericInput.svelte.d.ts +23 -0
  45. package/dist/components/PercentInput.svelte +25 -0
  46. package/dist/components/PercentInput.svelte.d.ts +20 -0
  47. package/dist/components/QuickEditDrawer.svelte +4 -1
  48. package/dist/components/QuickEditDrawer.svelte.d.ts +2 -0
  49. package/dist/components/RecordDetailDrawer.svelte +4 -2
  50. package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
  51. package/dist/components/ResourceOperationsPage.svelte +25 -19
  52. package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
  53. package/dist/components/ShowInferencer.svelte +4 -2
  54. package/dist/components/ShowInferencer.svelte.d.ts +2 -0
  55. package/dist/components/ShowPage.svelte +7 -3
  56. package/dist/components/ShowPage.svelte.d.ts +2 -0
  57. package/dist/components/Sidebar.svelte +5 -5
  58. package/dist/components/SpreadsheetView.svelte +81 -286
  59. package/dist/components/StepsForm.svelte +5 -5
  60. package/dist/components/SvarAutoTable.svelte +39 -0
  61. package/dist/components/SvarAutoTable.svelte.d.ts +13 -0
  62. package/dist/components/SvarDataGrid.svelte +362 -0
  63. package/dist/components/SvarDataGrid.svelte.d.ts +57 -0
  64. package/dist/components/SvarGridCell.svelte +10 -0
  65. package/dist/components/SvarGridCell.svelte.d.ts +7 -0
  66. package/dist/components/SvarResourceRead.svelte +50 -0
  67. package/dist/components/SvarResourceRead.svelte.d.ts +23 -0
  68. package/dist/components/SvarResourceTable.svelte +63 -0
  69. package/dist/components/SvarResourceTable.svelte.d.ts +42 -0
  70. package/dist/components/SvarResourceTableView.svelte +364 -0
  71. package/dist/components/SvarResourceTableView.svelte.d.ts +4 -0
  72. package/dist/components/TaskQueueDrawer.svelte +72 -16
  73. package/dist/components/TreeSelect.svelte +208 -28
  74. package/dist/components/TreeSelect.svelte.d.ts +3 -1
  75. package/dist/components/auto-table-grid.d.ts +26 -0
  76. package/dist/components/auto-table-grid.js +1 -0
  77. package/dist/components/content/ContentPageHeader.svelte +12 -9
  78. package/dist/components/content/ContentPageShell.svelte +6 -9
  79. package/dist/components/content/FileBrowser.svelte +35 -0
  80. package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
  81. package/dist/components/content/MetricBlock.svelte +10 -13
  82. package/dist/components/content/NetworkTable.svelte +3 -3
  83. package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
  84. package/dist/components/content/PageToolbar.svelte +6 -10
  85. package/dist/components/content/SectionHeader.svelte +8 -13
  86. package/dist/components/content/SettingsFieldRow.svelte +9 -23
  87. package/dist/components/content/SettingsGroup.svelte +11 -27
  88. package/dist/components/content/StatusBadge.svelte +3 -8
  89. package/dist/components/content/WorkspaceLayout.svelte +8 -12
  90. package/dist/components/enterprise/filter-tree.d.ts +48 -0
  91. package/dist/components/enterprise/filter-tree.js +224 -0
  92. package/dist/components/enterprise/json-schema-form.d.ts +39 -0
  93. package/dist/components/enterprise/json-schema-form.js +195 -0
  94. package/dist/components/enterprise/recursive-schema-form.d.ts +30 -0
  95. package/dist/components/enterprise/recursive-schema-form.js +196 -0
  96. package/dist/components/enterprise/spreadsheet-formula.d.ts +12 -0
  97. package/dist/components/enterprise/spreadsheet-formula.js +245 -0
  98. package/dist/components/fieldComponentMap.js +5 -0
  99. package/dist/components/fields/DateField.svelte +4 -3
  100. package/dist/components/fields/date-field-value.d.ts +2 -0
  101. package/dist/components/fields/date-field-value.js +13 -0
  102. package/dist/components/json-schema-form-state.d.ts +37 -0
  103. package/dist/components/json-schema-form-state.js +168 -0
  104. package/dist/components/record-detail.svelte.d.ts +3 -0
  105. package/dist/components/record-detail.svelte.js +10 -4
  106. package/dist/components/svar-grid-cells.d.ts +14 -0
  107. package/dist/components/svar-grid-cells.js +2 -0
  108. package/dist/components/svar-grid-contract.d.ts +80 -0
  109. package/dist/components/svar-grid-contract.js +159 -0
  110. package/dist/components/svar-grid-interactions.d.ts +54 -0
  111. package/dist/components/svar-grid-interactions.js +174 -0
  112. package/dist/components/svar-grid-loading.d.ts +40 -0
  113. package/dist/components/svar-grid-loading.js +180 -0
  114. package/dist/components/svar-grid-operations.d.ts +37 -0
  115. package/dist/components/svar-grid-operations.js +186 -0
  116. package/dist/components/svar-grid-panes.d.ts +34 -0
  117. package/dist/components/svar-grid-panes.js +66 -0
  118. package/dist/components/svar-grid-resource-loading.d.ts +18 -0
  119. package/dist/components/svar-grid-resource-loading.js +68 -0
  120. package/dist/components/svar-grid-resource-session.svelte.d.ts +29 -0
  121. package/dist/components/svar-grid-resource-session.svelte.js +61 -0
  122. package/dist/components/ui/badge/badge-variants.js +3 -1
  123. package/dist/components/ui/button/button-variants.js +5 -2
  124. package/dist/components/ui/input/input.svelte +1 -4
  125. package/dist/components/ui/textarea/textarea.svelte +2 -1
  126. package/dist/components.css +3079 -0
  127. package/dist/design-contract.d.ts +13 -0
  128. package/dist/design-contract.js +11 -0
  129. package/dist/design-system.d.ts +15 -0
  130. package/dist/design-system.js +7 -0
  131. package/dist/index.d.ts +14 -0
  132. package/dist/index.js +9 -0
  133. package/dist/page-chrome.css +12 -49
  134. package/dist/recipes.d.ts +4 -0
  135. package/dist/recipes.js +4 -0
  136. package/dist/rendering/index.d.ts +87 -0
  137. package/dist/rendering/index.js +117 -0
  138. package/dist/styled-system/css/conditions.js +36 -0
  139. package/dist/styled-system/css/css.d.ts +22 -0
  140. package/dist/styled-system/css/css.js +45 -0
  141. package/dist/styled-system/css/cva.d.ts +6 -0
  142. package/dist/styled-system/css/cva.js +87 -0
  143. package/dist/styled-system/css/cx.d.ts +5 -0
  144. package/dist/styled-system/css/cx.js +15 -0
  145. package/dist/styled-system/css/index.d.ts +5 -0
  146. package/dist/styled-system/css/index.js +4 -0
  147. package/dist/styled-system/css/sva.d.ts +4 -0
  148. package/dist/styled-system/css/sva.js +46 -0
  149. package/dist/styled-system/helpers.js +316 -0
  150. package/dist/styled-system/patterns/aspect-ratio.d.ts +20 -0
  151. package/dist/styled-system/patterns/aspect-ratio.js +38 -0
  152. package/dist/styled-system/patterns/bleed.d.ts +21 -0
  153. package/dist/styled-system/patterns/bleed.js +24 -0
  154. package/dist/styled-system/patterns/box.d.ts +20 -0
  155. package/dist/styled-system/patterns/box.js +15 -0
  156. package/dist/styled-system/patterns/center.d.ts +20 -0
  157. package/dist/styled-system/patterns/center.js +21 -0
  158. package/dist/styled-system/patterns/circle.d.ts +20 -0
  159. package/dist/styled-system/patterns/circle.js +25 -0
  160. package/dist/styled-system/patterns/container.d.ts +20 -0
  161. package/dist/styled-system/patterns/container.js +21 -0
  162. package/dist/styled-system/patterns/cq.d.ts +21 -0
  163. package/dist/styled-system/patterns/cq.js +21 -0
  164. package/dist/styled-system/patterns/divider.d.ts +22 -0
  165. package/dist/styled-system/patterns/divider.js +25 -0
  166. package/dist/styled-system/patterns/flex.d.ts +26 -0
  167. package/dist/styled-system/patterns/flex.js +26 -0
  168. package/dist/styled-system/patterns/float.d.ts +23 -0
  169. package/dist/styled-system/patterns/float.js +52 -0
  170. package/dist/styled-system/patterns/grid-item.d.ts +25 -0
  171. package/dist/styled-system/patterns/grid-item.js +25 -0
  172. package/dist/styled-system/patterns/grid.d.ts +24 -0
  173. package/dist/styled-system/patterns/grid.js +27 -0
  174. package/dist/styled-system/patterns/hstack.d.ts +21 -0
  175. package/dist/styled-system/patterns/hstack.js +24 -0
  176. package/dist/styled-system/patterns/index.d.ts +21 -0
  177. package/dist/styled-system/patterns/index.js +20 -0
  178. package/dist/styled-system/patterns/link-overlay.d.ts +20 -0
  179. package/dist/styled-system/patterns/link-overlay.js +24 -0
  180. package/dist/styled-system/patterns/spacer.d.ts +20 -0
  181. package/dist/styled-system/patterns/spacer.js +25 -0
  182. package/dist/styled-system/patterns/square.d.ts +20 -0
  183. package/dist/styled-system/patterns/square.js +24 -0
  184. package/dist/styled-system/patterns/stack.d.ts +23 -0
  185. package/dist/styled-system/patterns/stack.js +24 -0
  186. package/dist/styled-system/patterns/visually-hidden.d.ts +20 -0
  187. package/dist/styled-system/patterns/visually-hidden.js +18 -0
  188. package/dist/styled-system/patterns/vstack.d.ts +21 -0
  189. package/dist/styled-system/patterns/vstack.js +24 -0
  190. package/dist/styled-system/patterns/wrap.d.ts +24 -0
  191. package/dist/styled-system/patterns/wrap.js +25 -0
  192. package/dist/styled-system/recipes/content-header.d.ts +31 -0
  193. package/dist/styled-system/recipes/content-header.js +65 -0
  194. package/dist/styled-system/recipes/content-page.d.ts +34 -0
  195. package/dist/styled-system/recipes/content-page.js +43 -0
  196. package/dist/styled-system/recipes/create-recipe.js +82 -0
  197. package/dist/styled-system/recipes/index.d.ts +17 -0
  198. package/dist/styled-system/recipes/index.js +16 -0
  199. package/dist/styled-system/recipes/metric-block.d.ts +34 -0
  200. package/dist/styled-system/recipes/metric-block.js +76 -0
  201. package/dist/styled-system/recipes/product-list.d.ts +31 -0
  202. package/dist/styled-system/recipes/product-list.js +73 -0
  203. package/dist/styled-system/recipes/product-section.d.ts +31 -0
  204. package/dist/styled-system/recipes/product-section.js +49 -0
  205. package/dist/styled-system/recipes/product-settings-row.d.ts +34 -0
  206. package/dist/styled-system/recipes/product-settings-row.js +58 -0
  207. package/dist/styled-system/recipes/product-settings.d.ts +31 -0
  208. package/dist/styled-system/recipes/product-settings.js +57 -0
  209. package/dist/styled-system/recipes/product-status.d.ts +34 -0
  210. package/dist/styled-system/recipes/product-status.js +45 -0
  211. package/dist/styled-system/recipes/product-toolbar.d.ts +31 -0
  212. package/dist/styled-system/recipes/product-toolbar.js +41 -0
  213. package/dist/styled-system/recipes/product-workspace.d.ts +34 -0
  214. package/dist/styled-system/recipes/product-workspace.js +58 -0
  215. package/dist/styled-system/recipes/surface-metric.d.ts +38 -0
  216. package/dist/styled-system/recipes/surface-metric.js +63 -0
  217. package/dist/styled-system/recipes/surface-table.d.ts +34 -0
  218. package/dist/styled-system/recipes/surface-table.js +62 -0
  219. package/dist/styled-system/recipes/ui-badge.d.ts +31 -0
  220. package/dist/styled-system/recipes/ui-badge.js +38 -0
  221. package/dist/styled-system/recipes/ui-button.d.ts +32 -0
  222. package/dist/styled-system/recipes/ui-button.js +43 -0
  223. package/dist/styled-system/recipes/ui-input.d.ts +31 -0
  224. package/dist/styled-system/recipes/ui-input.js +49 -0
  225. package/dist/styled-system/recipes/ui-textarea.d.ts +31 -0
  226. package/dist/styled-system/recipes/ui-textarea.js +24 -0
  227. package/dist/styled-system/styles.css +1257 -0
  228. package/dist/styled-system/tokens/index.d.ts +9 -0
  229. package/dist/styled-system/tokens/index.js +268 -0
  230. package/dist/styled-system/tokens/tokens.d.ts +36 -0
  231. package/dist/styled-system/types/composition.d.ts +227 -0
  232. package/dist/styled-system/types/conditions.d.ts +236 -0
  233. package/dist/styled-system/types/csstype.d.ts +22570 -0
  234. package/dist/styled-system/types/index.d.ts +6 -0
  235. package/dist/styled-system/types/parts.d.ts +8 -0
  236. package/dist/styled-system/types/pattern.d.ts +78 -0
  237. package/dist/styled-system/types/prop-type.d.ts +223 -0
  238. package/dist/styled-system/types/recipe.d.ts +181 -0
  239. package/dist/styled-system/types/selectors.d.ts +59 -0
  240. package/dist/styled-system/types/static-css.d.ts +56 -0
  241. package/dist/styled-system/types/style-props.d.ts +8088 -0
  242. package/dist/styled-system/types/system-types.d.ts +151 -0
  243. package/dist/styles/aliases.css +49 -0
  244. package/dist/styles/compatibility.epilogue.css +384 -0
  245. package/dist/styles/compatibility.prelude.css +5513 -0
  246. package/dist/styles/conditional-states.css +28 -0
  247. package/dist/styles/conditional-utilities.css +22 -0
  248. package/dist/styles/recipes.css +1262 -0
  249. package/dist/utils.d.ts +1 -1
  250. package/dist/utils.js +1 -1
  251. package/package.json +31 -13
  252. package/styles-compatibility.json +12 -0
@@ -2,7 +2,8 @@
2
2
  import { definedOptions } from '@svadmin/core/options';
3
3
 
4
4
  import { SvelteSet } from 'svelte/reactivity';
5
- import { ChevronRight, ChevronDown, Check, X, Search, ChevronsUpDown } from '@lucide/svelte';
5
+ import { onDestroy } from 'svelte';
6
+ import { ChevronRight, ChevronDown, Check, X, Search, ChevronsUpDown, Loader2, Minus, RotateCw } from '@lucide/svelte';
6
7
  import { cn } from '../utils.js';
7
8
  import * as Popover from './ui/popover/index.js';
8
9
  import { Input } from './ui/input/index.js';
@@ -13,6 +14,7 @@
13
14
  value: string | number;
14
15
  label: string;
15
16
  children?: TreeSelectOption[];
17
+ hasChildren?: boolean;
16
18
  disabled?: boolean;
17
19
  expanded?: boolean;
18
20
  }
@@ -28,12 +30,13 @@
28
30
  onlyLeafSelectable?: boolean;
29
31
  disabled?: boolean;
30
32
  allowClear?: boolean;
33
+ loadChildren?: (node: TreeSelectOption) => Promise<TreeSelectOption[]>;
31
34
  class?: string;
32
35
  onchange?: (value: string | number | (string | number)[] | undefined) => void;
33
36
  }
34
37
 
35
38
  let {
36
- options = [],
39
+ options = $bindable([]),
37
40
  value = $bindable(undefined),
38
41
  multiple = false,
39
42
  placeholder,
@@ -41,13 +44,22 @@
41
44
  onlyLeafSelectable = false,
42
45
  disabled = false,
43
46
  allowClear = true,
47
+ loadChildren,
44
48
  class: className,
45
49
  onchange,
46
50
  }: Props = $props();
47
51
 
48
52
  let open = $state(false);
49
53
  let searchQuery = $state('');
54
+ let loadingValues = new SvelteSet<string | number>();
55
+ let loadErrors = new SvelteSet<string | number>();
50
56
  let expandedNodes = new SvelteSet<string | number>();
57
+ let mounted = true;
58
+ const loads = new Map<string | number, {
59
+ node: TreeSelectOption;
60
+ loader: NonNullable<Props['loadChildren']>;
61
+ }>();
62
+ onDestroy(() => { mounted = false; loads.clear(); });
51
63
 
52
64
  // Map to quickly look up option info by value
53
65
  const optionMap = $derived.by(() => {
@@ -72,6 +84,19 @@
72
84
  return selectedValues.map((v) => optionMap.get(v)?.label ?? String(v));
73
85
  });
74
86
 
87
+ $effect.pre(() => {
88
+ const nodes = optionMap;
89
+ const loader = loadChildren;
90
+ const unavailable = disabled;
91
+ for (const [key, request] of loads) {
92
+ if (unavailable || nodes.get(key) !== request.node || loader !== request.loader) {
93
+ loads.delete(key);
94
+ loadingValues.delete(key);
95
+ loadErrors.delete(key);
96
+ }
97
+ }
98
+ });
99
+
75
100
  function toggleExpand(nodeValue: string | number, event?: MouseEvent) {
76
101
  event?.stopPropagation();
77
102
  if (expandedNodes.has(nodeValue)) {
@@ -81,32 +106,121 @@
81
106
  }
82
107
  }
83
108
 
109
+ function hasChildren(node: TreeSelectOption): boolean {
110
+ return Boolean(node.hasChildren ?? (node.children && node.children.length > 0));
111
+ }
112
+
84
113
  function isNodeExpanded(node: TreeSelectOption): boolean {
85
114
  if (searchQuery.trim()) return true; // Auto expand all on search
86
115
  return expandedNodes.has(node.value) || !!node.expanded;
87
116
  }
88
117
 
118
+ function selectableLeaves(node: TreeSelectOption): TreeSelectOption[] {
119
+ if (!hasChildren(node)) return node.disabled ? [] : [node];
120
+ if (!node.children) return [];
121
+ return (node.children ?? []).flatMap(selectableLeaves);
122
+ }
123
+
89
124
  function isSelected(val: string | number): boolean {
90
125
  return selectedValues.includes(val);
91
126
  }
92
127
 
93
- function handleSelect(node: TreeSelectOption) {
128
+ function isNodeSelected(node: TreeSelectOption): boolean {
129
+ if (!multiple || !hasChildren(node)) return isSelected(node.value);
130
+ const leaves = selectableLeaves(node);
131
+ return leaves.length > 0 && leaves.every((leaf) => isSelected(leaf.value));
132
+ }
133
+
134
+ function isPartiallySelected(node: TreeSelectOption): boolean {
135
+ if (!multiple || !hasChildren(node)) return false;
136
+ const leaves = selectableLeaves(node);
137
+ const count = leaves.filter((leaf) => isSelected(leaf.value)).length;
138
+ return count > 0 && count < leaves.length;
139
+ }
140
+
141
+ function updateOptionsChildren(nodes: TreeSelectOption[], target: string | number, children: TreeSelectOption[]): TreeSelectOption[] {
142
+ let changed = false;
143
+ const next = nodes.map((node) => {
144
+ if (node.value === target) {
145
+ changed = true;
146
+ return { ...node, children, hasChildren: children.length > 0 };
147
+ }
148
+ if (!node.children) return node;
149
+ const updated = updateOptionsChildren(node.children, target, children);
150
+ if (updated === node.children) return node;
151
+ changed = true;
152
+ return { ...node, children: updated };
153
+ });
154
+ return changed ? next : nodes;
155
+ }
156
+
157
+ async function ensureChildren(node: TreeSelectOption): Promise<boolean> {
158
+ if (!mounted || disabled || loadingValues.has(node.value)) return false;
159
+ if (!node.hasChildren || node.children) return true;
160
+ const currentNode = optionMap.get(node.value);
161
+ if (!loadChildren || !currentNode) return false;
162
+ const request = { node: currentNode, loader: loadChildren };
163
+ loads.set(node.value, request);
164
+ const current = () => mounted && !disabled && loads.get(node.value) === request
165
+ && optionMap.get(node.value) === request.node && loadChildren === request.loader;
166
+ loadingValues.add(node.value);
167
+ loadErrors.delete(node.value);
168
+ try {
169
+ const children = await request.loader(request.node);
170
+ if (!current()) return false;
171
+ options = updateOptionsChildren(options, node.value, children);
172
+ return true;
173
+ } catch {
174
+ if (current()) loadErrors.add(node.value);
175
+ return false;
176
+ } finally {
177
+ if (mounted && loads.get(node.value) === request) {
178
+ loads.delete(node.value);
179
+ loadingValues.delete(node.value);
180
+ }
181
+ }
182
+ }
183
+
184
+ async function toggleExpandAsync(node: TreeSelectOption, event?: MouseEvent): Promise<void> {
185
+ event?.stopPropagation();
186
+ if (!await ensureChildren(node)) return;
187
+ if (!mounted || disabled) return;
188
+ toggleExpand(node.value);
189
+ }
190
+
191
+ function retryChildren(node: TreeSelectOption, event: MouseEvent): void {
192
+ event.stopPropagation();
193
+ void toggleExpandAsync(node);
194
+ }
195
+
196
+ function setMultipleSelection(node: TreeSelectOption): void {
197
+ const leaves = selectableLeaves(node);
198
+ const leafValues = new Set(leaves.map((leaf) => leaf.value));
199
+ const shouldRemove = leaves.length > 0 && leaves.every((leaf) => isSelected(leaf.value));
200
+ const next = shouldRemove
201
+ ? selectedValues.filter((value) => !leafValues.has(value))
202
+ : [...selectedValues, ...leaves.map((leaf) => leaf.value).filter((value) => !isSelected(value))];
203
+ value = next;
204
+ onchange?.(next);
205
+ }
206
+
207
+ async function handleSelect(node: TreeSelectOption): Promise<void> {
94
208
  if (node.disabled) return;
95
- const hasChildren = node.children && node.children.length > 0;
96
- if (onlyLeafSelectable && hasChildren) {
97
- toggleExpand(node.value);
209
+ const nodeHasChildren = hasChildren(node);
210
+ if (onlyLeafSelectable && nodeHasChildren) {
211
+ await toggleExpandAsync(node);
98
212
  return;
99
213
  }
100
214
 
101
215
  if (multiple) {
102
- let next: (string | number)[];
103
- if (isSelected(node.value)) {
104
- next = selectedValues.filter((v) => v !== node.value);
105
- } else {
106
- next = [...selectedValues, node.value];
216
+ if (nodeHasChildren) setMultipleSelection(node);
217
+ else {
218
+ const next = isSelected(node.value)
219
+ ? selectedValues.filter((selected) => selected !== node.value)
220
+ : [...selectedValues, node.value];
221
+ value = next;
222
+ onchange?.(next);
107
223
  }
108
- value = next;
109
- onchange?.(next);
110
224
  } else {
111
225
  const next = node.value;
112
226
  value = next;
@@ -115,6 +229,59 @@
115
229
  }
116
230
  }
117
231
 
232
+ function findParent(nodes: TreeSelectOption[], target: string | number, parent?: TreeSelectOption): TreeSelectOption | undefined {
233
+ for (const node of nodes) {
234
+ if (node.value === target) return parent;
235
+ const match = node.children ? findParent(node.children, target, node) : undefined;
236
+ if (match) return match;
237
+ }
238
+ return undefined;
239
+ }
240
+
241
+ function focusTreeNode(valueToFocus: string | number): void {
242
+ const element = document.querySelector<HTMLElement>(`[data-tree-value="${CSS.escape(String(valueToFocus))}"]`);
243
+ element?.focus();
244
+ }
245
+
246
+ function focusSibling(nodeValue: string | number, offset: number): void {
247
+ const nodes = Array.from(document.querySelectorAll<HTMLElement>('[data-tree-value]'));
248
+ const index = nodes.findIndex((node) => node.dataset['treeValue'] === String(nodeValue));
249
+ const target = nodes[index + offset];
250
+ target?.focus();
251
+ }
252
+
253
+ function handleTreeKeydown(event: KeyboardEvent, node: TreeSelectOption, expanded: boolean): void {
254
+ const nodeHasChildren = hasChildren(node);
255
+ if (event.key === 'Enter' || event.key === ' ') {
256
+ event.preventDefault();
257
+ void handleSelect(node);
258
+ } else if (event.key === 'ArrowDown') {
259
+ event.preventDefault();
260
+ focusSibling(node.value, 1);
261
+ } else if (event.key === 'ArrowUp') {
262
+ event.preventDefault();
263
+ focusSibling(node.value, -1);
264
+ } else if (event.key === 'Home') {
265
+ event.preventDefault();
266
+ document.querySelector<HTMLElement>('[data-tree-value]')?.focus();
267
+ } else if (event.key === 'End') {
268
+ event.preventDefault();
269
+ const nodes = document.querySelectorAll<HTMLElement>('[data-tree-value]');
270
+ nodes[nodes.length - 1]?.focus();
271
+ } else if (event.key === 'ArrowRight' && nodeHasChildren) {
272
+ event.preventDefault();
273
+ if (!expanded) void toggleExpandAsync(node);
274
+ else focusTreeNode(node.children?.[0]?.value ?? node.value);
275
+ } else if (event.key === 'ArrowLeft') {
276
+ event.preventDefault();
277
+ if (nodeHasChildren && expanded) toggleExpand(node.value);
278
+ else {
279
+ const parent = findParent(options, node.value);
280
+ if (parent) focusTreeNode(parent.value);
281
+ }
282
+ }
283
+ }
284
+
118
285
  function clearAll(event?: MouseEvent) {
119
286
  event?.stopPropagation();
120
287
  const next = multiple ? [] : undefined;
@@ -155,17 +322,21 @@
155
322
  </script>
156
323
 
157
324
  {#snippet treeNode(node: TreeSelectOption, level: number)}
158
- {@const hasChildren = Boolean(node.children && node.children.length > 0)}
325
+ {@const nodeHasChildren = hasChildren(node)}
159
326
  {@const expanded = isNodeExpanded(node)}
160
- {@const selected = isSelected(node.value)}
161
- {@const selectable = !node.disabled && (!onlyLeafSelectable || !hasChildren)}
327
+ {@const selected = isNodeSelected(node)}
328
+ {@const partial = isPartiallySelected(node)}
329
+ {@const selectable = !node.disabled && (!onlyLeafSelectable || !nodeHasChildren)}
162
330
 
163
331
  <div class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed">
164
332
  <div
165
333
  role="treeitem"
166
334
  tabindex="0"
167
335
  aria-selected={selected}
168
- aria-expanded={hasChildren ? expanded : undefined}
336
+ aria-checked={multiple ? (partial ? 'mixed' : selected) : undefined}
337
+ aria-level={level + 1}
338
+ aria-expanded={nodeHasChildren ? expanded : undefined}
339
+ data-tree-value={String(node.value)}
169
340
  class={cn(
170
341
  'group svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-58284b4ea568 svadmin-u-421ac2be5045 svadmin-u-d5eab218aa34 svadmin-u-ec0091ee009b svadmin-u-359090c2d529 svadmin-u-ceb69a6b0e5f svadmin-u-34516836730d svadmin-u-7f6912283f11',
171
342
  selected ? 'svadmin-u-375dc44df6e9 svadmin-u-20aaf08a7ed1 svadmin-u-2689f3958069' : 'svadmin-u-68646cdcc246 svadmin-u-d4108abe6359',
@@ -175,21 +346,20 @@
175
346
  onclick={() => {
176
347
  if (selectable) handleSelect(node);
177
348
  }}
178
- onkeydown={(e) => {
179
- if (e.key === 'Enter' || e.key === ' ') {
180
- e.preventDefault();
181
- if (selectable) handleSelect(node);
182
- }
183
- }}
349
+ onkeydown={(e) => handleTreeKeydown(e, node, expanded)}
184
350
  >
185
351
  <div class="svadmin-u-60fbb7713999 svadmin-u-7e0b7cdf1a94 svadmin-u-3960ffc248d9 svadmin-u-58284b4ea568">
186
- {#if hasChildren}
352
+ {#if nodeHasChildren}
187
353
  <button
188
354
  type="button"
355
+ aria-label={`${node.label}: ${i18n.t('tree.toggleChildren')}`}
356
+ aria-busy={loadingValues.has(node.value)}
189
357
  class="svadmin-u-60fbb7713999 svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3 svadmin-u-012fbd121f37 svadmin-u-3960ffc248d9 svadmin-u-86843cf1e227 svadmin-u-07389a777c1f svadmin-u-bfa603190748 svadmin-u-8e551981c8d7"
190
- onclick={(e) => toggleExpand(node.value, e)}
358
+ onclick={(e) => void toggleExpandAsync(node, e)}
191
359
  >
192
- {#if expanded}
360
+ {#if loadingValues.has(node.value)}
361
+ <Loader2 class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-afbdd13a380e" />
362
+ {:else if expanded}
193
363
  <ChevronDown class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" />
194
364
  {:else}
195
365
  <ChevronRight class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" />
@@ -202,12 +372,22 @@
202
372
  <span class="svadmin-u-f283ea9bea0e">{node.label}</span>
203
373
  </div>
204
374
 
205
- {#if selected}
375
+ {#if loadErrors.has(node.value)}
376
+ <span role="alert" class="svadmin-u-bfa603190748">{i18n.t('tree.loadFailed')}</span>
377
+ <button type="button" aria-label={`${node.label}: ${i18n.t('common.retry')}`}
378
+ title={i18n.t('common.retry')} onclick={(e) => retryChildren(node, e)}>
379
+ <RotateCw class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" />
380
+ </button>
381
+ {/if}
382
+
383
+ {#if partial}
384
+ <Minus class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-012fbd121f37 svadmin-u-20aaf08a7ed1" />
385
+ {:else if selected}
206
386
  <Check class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-012fbd121f37 svadmin-u-20aaf08a7ed1" />
207
387
  {/if}
208
388
  </div>
209
389
 
210
- {#if hasChildren && expanded && node.children}
390
+ {#if nodeHasChildren && expanded && node.children}
211
391
  <div role="group" class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed">
212
392
  {#each node.children as child (child.value)}
213
393
  {@render treeNode(child, level + 1)}
@@ -2,6 +2,7 @@ export interface TreeSelectOption {
2
2
  value: string | number;
3
3
  label: string;
4
4
  children?: TreeSelectOption[];
5
+ hasChildren?: boolean;
5
6
  disabled?: boolean;
6
7
  expanded?: boolean;
7
8
  }
@@ -14,9 +15,10 @@ interface Props {
14
15
  onlyLeafSelectable?: boolean;
15
16
  disabled?: boolean;
16
17
  allowClear?: boolean;
18
+ loadChildren?: (node: TreeSelectOption) => Promise<TreeSelectOption[]>;
17
19
  class?: string;
18
20
  onchange?: (value: string | number | (string | number)[] | undefined) => void;
19
21
  }
20
- declare const TreeSelect: import("svelte").Component<Props, {}, "value">;
22
+ declare const TreeSelect: import("svelte").Component<Props, {}, "value" | "options">;
21
23
  type TreeSelect = ReturnType<typeof TreeSelect>;
22
24
  export default TreeSelect;
@@ -0,0 +1,26 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { Sort } from '@svadmin/core';
3
+ /** 可信宿主的渲染扩展;资源查询、权限、操作和偏好状态仍由 AutoTable 持有。 */
4
+ export interface AutoTableGridState {
5
+ readonly records: readonly Record<string, unknown>[];
6
+ readonly columns: readonly {
7
+ key: string;
8
+ label: string;
9
+ width: number;
10
+ sortable: boolean;
11
+ }[];
12
+ readonly primaryKey: string;
13
+ readonly sorters: readonly Sort[];
14
+ readonly density: 'compact' | 'comfortable';
15
+ readonly locale: string;
16
+ readonly label: string;
17
+ readonly scopeKey: string;
18
+ readonly disabled: boolean;
19
+ readonly onSortChange: (sorters: readonly Sort[]) => void;
20
+ readonly cell: Snippet<[{
21
+ id: string | number;
22
+ field: string;
23
+ }]>;
24
+ readonly controls: Snippet;
25
+ readonly after: Snippet;
26
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
+ import { contentHeader } from '../../styled-system/recipes/index.js';
4
+
3
5
  interface Props {
4
6
  title: string;
5
7
  eyebrow?: string;
@@ -9,23 +11,24 @@
9
11
  class?: string;
10
12
  }
11
13
  let { title, eyebrow, description, breadcrumbs = [], actions, class: className = '' }: Props = $props();
14
+ const styles = contentHeader();
12
15
  </script>
13
16
 
14
- <header class={'svadmin-u-6ed543e2fbbb ' + className} data-svadmin-page-header>
17
+ <header class={styles.root + ' ' + className} data-svadmin-page-header>
15
18
  {#if breadcrumbs.length > 0}
16
- <nav aria-label="Breadcrumb" class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4 svadmin-u-359090c2d529 svadmin-u-bfa603190748">
19
+ <nav aria-label="Breadcrumb" class={styles.breadcrumbs}>
17
20
  {#each breadcrumbs as crumb, index (crumb)}
18
21
  {#if index > 0}<span aria-hidden="true">/</span>{/if}
19
- <span class={index === breadcrumbs.length - 1 ? 'svadmin-u-d4108abe6359' : ''}>{crumb}</span>
22
+ <span class={index === breadcrumbs.length - 1 ? styles.currentCrumb : ''}>{crumb}</span>
20
23
  {/each}
21
24
  </nav>
22
25
  {/if}
23
- <div class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-0c3bc98565dd svadmin-u-020ba687fa12 svadmin-u-64cac80d2e9a svadmin-u-3b9871a0bf93">
24
- <div class="svadmin-u-7e0b7cdf1a94 svadmin-u-da7c36cd8867">
25
- {#if eyebrow}<p class="svadmin-u-359090c2d529 svadmin-u-2689f3958069 svadmin-u-bfa603190748">{eyebrow}</p>{/if}
26
- <h1 class="svadmin-u-d5c9b0001e7e svadmin-u-e83a7042bc91 svadmin-u-e9fadafbd4a2 svadmin-u-d9256981a032 svadmin-u-d4108abe6359">{title}</h1>
27
- {#if description}<p class="svadmin-u-2cc8041eca99 svadmin-u-fc7473ca09eb svadmin-u-18550d5945ae svadmin-u-bfa603190748">{description}</p>{/if}
26
+ <div class={styles.row}>
27
+ <div class={styles.heading}>
28
+ {#if eyebrow}<p class={styles.eyebrow}>{eyebrow}</p>{/if}
29
+ <h1 class={styles.title}>{title}</h1>
30
+ {#if description}<p class={styles.description}>{description}</p>{/if}
28
31
  </div>
29
- {#if actions}<div class="svadmin-u-60fbb7713999 svadmin-u-012fbd121f37 svadmin-u-1eb5c6df38c1 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">{@render actions()}</div>{/if}
32
+ {#if actions}<div class={styles.actions}>{@render actions()}</div>{/if}
30
33
  </div>
31
34
  </header>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { definedOptions } from '@svadmin/core/options';
3
-
4
3
  import type { Snippet } from 'svelte';
4
+ import { contentPage } from '../../styled-system/recipes/index.js';
5
5
  import ContentPageHeader from './ContentPageHeader.svelte';
6
6
 
7
7
  interface Props {
@@ -26,16 +26,13 @@
26
26
  class: className = '',
27
27
  }: Props = $props();
28
28
 
29
- const widthClass = $derived(
30
- width === 'narrow'
31
- ? 'svadmin-u-fa3f7111e53b'
32
- : width === 'wide'
33
- ? 'max-w-[92rem]'
34
- : 'max-w-[74rem]',
35
- );
29
+ // 保留旧组件对非窄屏/宽屏输入的默认宽度回退。
30
+ const styles = $derived(contentPage({
31
+ width: width === 'narrow' || width === 'wide' ? width : 'default',
32
+ }));
36
33
  </script>
37
34
 
38
- <div data-svadmin-content-page={pageId} class={'svadmin-u-0e12dc7de920 svadmin-u-6da6a3c3f741 ' + widthClass + ' svadmin-u-b3542e058833 ' + className}>
35
+ <div data-svadmin-content-page={pageId} class={styles.root + ' ' + className}>
39
36
  {#if title}<ContentPageHeader {title} {...definedOptions({ "eyebrow": eyebrow })} {...definedOptions({ "description": description })} {...definedOptions({ "actions": actions })} />{/if}
40
37
  {@render children()}
41
38
  </div>
@@ -0,0 +1,35 @@
1
+ <script module lang="ts">
2
+ import type { ComponentProps } from 'svelte';
3
+ import { Filemanager, Willow } from '@svar-ui/svelte-filemanager';
4
+ import { Locale } from '@svar-ui/svelte-core';
5
+
6
+ export type FileBrowserData = ComponentProps<typeof Filemanager>['data'];
7
+ export type FileBrowserInit = ComponentProps<typeof Filemanager>['init'];
8
+ export type FileBrowserMenuOptions = ComponentProps<typeof Filemanager>['menuOptions'];
9
+ export type FileBrowserProps = ComponentProps<typeof Filemanager> & {
10
+ words?: ComponentProps<typeof Locale>['words'];
11
+ fonts?: boolean;
12
+ class?: string;
13
+ };
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ let {
18
+ words, fonts = false, class: className = '',
19
+ mode = 'table', icons = 'simple', readonly = true,
20
+ ...managerProps
21
+ }: FileBrowserProps = $props();
22
+ </script>
23
+
24
+ <div class={'svadmin-file-browser ' + className} data-slot="file-browser">
25
+ <Willow {fonts}>
26
+ <Locale words={words ?? {}}>
27
+ <Filemanager {...managerProps} {mode} {icons} {readonly} />
28
+ </Locale>
29
+ </Willow>
30
+ </div>
31
+
32
+ <style>
33
+ .svadmin-file-browser { height: 32rem; min-width: 0; max-width: 100%; overflow: hidden; }
34
+ .svadmin-file-browser :global(.wx-willow-theme) { --wx-font-family: inherit; --wx-fm-box-shadow: none; }
35
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { ComponentProps } from 'svelte';
2
+ import { Filemanager } from '@svar-ui/svelte-filemanager';
3
+ import { Locale } from '@svar-ui/svelte-core';
4
+ export type FileBrowserData = ComponentProps<typeof Filemanager>['data'];
5
+ export type FileBrowserInit = ComponentProps<typeof Filemanager>['init'];
6
+ export type FileBrowserMenuOptions = ComponentProps<typeof Filemanager>['menuOptions'];
7
+ export type FileBrowserProps = ComponentProps<typeof Filemanager> & {
8
+ words?: ComponentProps<typeof Locale>['words'];
9
+ fonts?: boolean;
10
+ class?: string;
11
+ };
12
+ declare const FileBrowser: import("svelte").Component<FileBrowserProps, {}, "">;
13
+ type FileBrowser = ReturnType<typeof FileBrowser>;
14
+ export default FileBrowser;
@@ -1,6 +1,8 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
+ import { metricBlock } from '../../styled-system/recipes/index.js';
3
4
  import { Skeleton } from '../ui/skeleton/index.js';
5
+
4
6
  export type MetricTrendTone = 'positive' | 'negative' | 'warning' | 'neutral';
5
7
  interface Props {
6
8
  label: string;
@@ -22,23 +24,18 @@
22
24
  loading = false,
23
25
  class: className = '',
24
26
  }: Props = $props();
25
- const trendClass: Record<MetricTrendTone, string> = {
26
- positive: 'text-success',
27
- negative: 'text-destructive',
28
- warning: 'text-warning-foreground',
29
- neutral: 'text-muted-foreground',
30
- };
27
+ const styles = $derived(metricBlock({ trendTone }));
31
28
  </script>
32
29
 
33
- <div data-svadmin-metric-card role="region" aria-label={label} class={'svadmin-u-7e0b7cdf1a94 svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-18049387f0af svadmin-u-cd0ad9a56558 svadmin-u-8e63407b5ceb svadmin-u-438b2237b8d6 ' + className}>
34
- <div class="svadmin-u-60fbb7713999 svadmin-u-60541e1e26f8 svadmin-u-8ef2268efbbc svadmin-u-1004c0c3954c">
35
- <p class="svadmin-u-fc7473ca09eb svadmin-u-bfa603190748">{label}</p>
36
- {#if icon}<span class="svadmin-u-bfa603190748" aria-hidden="true">{@render icon()}</span>{/if}
30
+ <div data-svadmin-metric-card role="region" aria-label={label} class={styles.root + ' ' + className}>
31
+ <div class={styles.header}>
32
+ <p class={styles.label}>{label}</p>
33
+ {#if icon}<span class={styles.icon} aria-hidden="true">{@render icon()}</span>{/if}
37
34
  </div>
38
35
  {#if loading}
39
- <Skeleton class="svadmin-u-eccd13ef4f2f svadmin-u-ed8a5df7b2fb svadmin-u-69da7e4ff95d" />
36
+ <Skeleton class={styles.skeleton} />
40
37
  {:else}
41
- <p class="svadmin-u-50d0d216a2f8 svadmin-u-f283ea9bea0e svadmin-u-3febee094e85 svadmin-u-e83a7042bc91 svadmin-u-d9256981a032 svadmin-u-d4108abe6359 svadmin-u-3032cae0badb">{value}</p>
42
- {#if detail || trend}<div class="svadmin-u-50d0d216a2f8 svadmin-u-60fbb7713999 svadmin-u-1eb5c6df38c1 svadmin-u-77a2a20e90d4 svadmin-u-359090c2d529">{#if trend}<span class={'svadmin-u-2689f3958069 svadmin-u-3032cae0badb ' + trendClass[trendTone]}>{trend}</span>{/if}{#if detail}<span class="svadmin-u-bfa603190748">{detail}</span>{/if}</div>{/if}
38
+ <p class={styles.value}>{value}</p>
39
+ {#if detail || trend}<div class={styles.meta}>{#if trend}<span class={styles.trend}>{trend}</span>{/if}{#if detail}<span class={styles.detail}>{detail}</span>{/if}</div>{/if}
43
40
  {/if}
44
41
  </div>
@@ -6,15 +6,15 @@
6
6
  import DataState from './DataState.svelte';
7
7
  import type { DataStateKind } from './DataState.svelte';
8
8
  import type { NetworkColumn } from './NetworkTable.types.js';
9
- interface Props { rows?: T[]; columns: NetworkColumn<T>[]; row?: Snippet<[T]>; state?: DataStateKind; stateTitle?: string; stateDescription?: string; emptyTitle?: string; emptyDescription?: string; retry?: () => void; retryLabel?: string; loadingLabel?: string; class?: string; }
10
- let { rows = [], columns, row, state, stateTitle, stateDescription, emptyTitle, emptyDescription, retry, retryLabel, loadingLabel, class: className = '' }: Props = $props();
9
+ interface Props { rows?: T[]; columns: NetworkColumn<T>[]; row?: Snippet<[T]>; state?: DataStateKind; stateTitle?: string; stateDescription?: string; emptyTitle?: string; emptyDescription?: string; retry?: () => void; retryLabel?: string; loadingLabel?: string; class?: string; density?: 'comfortable' | 'compact'; }
10
+ let { rows = [], columns, row, state, stateTitle, stateDescription, emptyTitle, emptyDescription, retry, retryLabel, loadingLabel, class: className = '', density = 'comfortable' }: Props = $props();
11
11
  const resolvedState = $derived(state ?? (rows.length === 0 ? 'empty' : undefined));
12
12
  </script>
13
13
  {#if resolvedState}
14
14
  <DataState state={resolvedState} {...definedOptions({ title: stateTitle ?? emptyTitle, description: stateDescription ?? emptyDescription, retry, retryLabel, loadingLabel })} class={className} />
15
15
  {:else}
16
16
  <div class={'svadmin-u-1384f66f41d0 svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-18049387f0af svadmin-u-cd0ad9a56558 ' + className}>
17
- <Table.Root data-svadmin-datatable>
17
+ <Table.Root {density} data-svadmin-datatable>
18
18
  <Table.Header data-svadmin-table-head><Table.Row>{#each columns as column (String(column.key))}<Table.Head>{column.label}</Table.Head>{/each}</Table.Row></Table.Header>
19
19
  <Table.Body>
20
20
  {#each rows as item, index (String('id' in item ? item.id : index))}
@@ -15,6 +15,7 @@ declare function $$render<T extends object>(): {
15
15
  retryLabel?: string;
16
16
  loadingLabel?: string;
17
17
  class?: string;
18
+ density?: "comfortable" | "compact";
18
19
  };
19
20
  exports: {};
20
21
  bindings: "";
@@ -1,18 +1,14 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
- interface Props {
4
- leading?: Snippet;
5
- trailing?: Snippet;
6
- children?: Snippet;
7
- class?: string;
8
- }
3
+ import { productToolbar } from '../../styled-system/recipes/index.js';
4
+ interface Props { leading?: Snippet; trailing?: Snippet; children?: Snippet; class?: string; }
9
5
  let { leading, trailing, children, class: className = '' }: Props = $props();
6
+ const styles = productToolbar();
10
7
  </script>
11
-
12
- <div data-svadmin-table-toolbar class={'svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-1004c0c3954c svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-18049387f0af svadmin-u-cd0ad9a56558 svadmin-u-eb6e8b881acd svadmin-u-438b2237b8d6 svadmin-u-020ba687fa12 svadmin-u-9f76a62f4f44 svadmin-u-3b9871a0bf93 ' + className}>
13
- <div class="svadmin-u-60fbb7713999 svadmin-u-7e0b7cdf1a94 svadmin-u-36e579c0b41c svadmin-u-1eb5c6df38c1 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">
8
+ <div data-svadmin-table-toolbar class={styles.root + ' ' + className}>
9
+ <div class={styles.leading}>
14
10
  {#if leading}{@render leading()}{/if}
15
11
  {#if children}{@render children()}{/if}
16
12
  </div>
17
- {#if trailing}<div class="svadmin-u-60fbb7713999 svadmin-u-012fbd121f37 svadmin-u-1eb5c6df38c1 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">{@render trailing()}</div>{/if}
13
+ {#if trailing}<div class={styles.trailing}>{@render trailing()}</div>{/if}
18
14
  </div>
@@ -1,19 +1,14 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
- interface Props {
4
- title: string;
5
- description?: string;
6
- actions?: Snippet;
7
- id?: string;
8
- class?: string;
9
- }
3
+ import { productSection } from '../../styled-system/recipes/index.js';
4
+ interface Props { title: string; description?: string; actions?: Snippet; id?: string; class?: string; }
10
5
  let { title, description, actions, id, class: className = '' }: Props = $props();
6
+ const styles = productSection();
11
7
  </script>
12
-
13
- <div class={'svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-1004c0c3954c svadmin-u-020ba687fa12 svadmin-u-64cac80d2e9a svadmin-u-3b9871a0bf93 ' + className}>
14
- <div class="svadmin-u-7e0b7cdf1a94 svadmin-u-da7c36cd8867">
15
- <h2 {id} class="svadmin-u-4ee734926ff6 svadmin-u-e83a7042bc91 svadmin-u-d4108abe6359">{title}</h2>
16
- {#if description}<p class="svadmin-u-fc7473ca09eb svadmin-u-bfa603190748">{description}</p>{/if}
8
+ <div class={styles.root + ' ' + className} data-svadmin-section-header>
9
+ <div class={styles.heading}>
10
+ <h2 {id} class={styles.title}>{title}</h2>
11
+ {#if description}<p class={styles.description}>{description}</p>{/if}
17
12
  </div>
18
- {#if actions}<div class="svadmin-u-60fbb7713999 svadmin-u-012fbd121f37 svadmin-u-1eb5c6df38c1 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">{@render actions()}</div>{/if}
13
+ {#if actions}<div class={styles.actions}>{@render actions()}</div>{/if}
19
14
  </div>