@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.
- package/README.md +40 -25
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/app.css +7694 -5117
- package/dist/app.theme.css +7645 -5119
- package/dist/class-properties.generated.d.ts +1 -0
- package/dist/class-properties.generated.js +2 -0
- package/dist/classnames.d.ts +8 -0
- package/dist/classnames.js +26 -0
- package/dist/components/AutoForm.svelte +20 -6
- package/dist/components/AutoForm.svelte.d.ts +2 -0
- package/dist/components/AutoTable.svelte +249 -9
- package/dist/components/AutoTable.svelte.d.ts +5 -0
- package/dist/components/BoundRecordDetailDrawer.svelte +8 -2
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +2 -0
- package/dist/components/ComboboxField.svelte +31 -9
- package/dist/components/ComboboxField.svelte.d.ts +3 -2
- package/dist/components/CreatePage.svelte +4 -0
- package/dist/components/CreatePage.svelte.d.ts +2 -0
- package/dist/components/DateRangeInput.svelte +75 -0
- package/dist/components/DateRangeInput.svelte.d.ts +25 -0
- package/dist/components/DateTimeInput.svelte +65 -0
- package/dist/components/DateTimeInput.svelte.d.ts +19 -0
- package/dist/components/DevTools.svelte +2 -2
- package/dist/components/EditPage.svelte +4 -0
- package/dist/components/EditPage.svelte.d.ts +2 -0
- package/dist/components/FieldRenderer.svelte +90 -18
- package/dist/components/FileUpload.svelte +250 -0
- package/dist/components/FileUpload.svelte.d.ts +32 -0
- package/dist/components/FilterBuilder.svelte +236 -279
- package/dist/components/FilterBuilder.svelte.d.ts +3 -0
- package/dist/components/ImportWizard.svelte +181 -94
- package/dist/components/JsonSchemaForm.svelte +255 -99
- package/dist/components/JsonSchemaForm.svelte.d.ts +12 -1
- package/dist/components/Layout.svelte +1 -2
- package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +1 -1
- package/dist/components/ListPage.svelte +4 -0
- package/dist/components/ListPage.svelte.d.ts +2 -0
- package/dist/components/LoginPage.svelte +1 -1
- package/dist/components/MoneyInput.svelte +25 -0
- package/dist/components/MoneyInput.svelte.d.ts +20 -0
- package/dist/components/NumberInput.svelte +25 -0
- package/dist/components/NumberInput.svelte.d.ts +19 -0
- package/dist/components/NumericInput.svelte +110 -0
- package/dist/components/NumericInput.svelte.d.ts +23 -0
- package/dist/components/PercentInput.svelte +25 -0
- package/dist/components/PercentInput.svelte.d.ts +20 -0
- package/dist/components/QuickEditDrawer.svelte +4 -1
- package/dist/components/QuickEditDrawer.svelte.d.ts +2 -0
- package/dist/components/RecordDetailDrawer.svelte +4 -2
- package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
- package/dist/components/ResourceOperationsPage.svelte +25 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
- package/dist/components/ShowInferencer.svelte +4 -2
- package/dist/components/ShowInferencer.svelte.d.ts +2 -0
- package/dist/components/ShowPage.svelte +7 -3
- package/dist/components/ShowPage.svelte.d.ts +2 -0
- package/dist/components/Sidebar.svelte +5 -5
- package/dist/components/SpreadsheetView.svelte +81 -286
- package/dist/components/StepsForm.svelte +5 -5
- package/dist/components/SvarAutoTable.svelte +39 -0
- package/dist/components/SvarAutoTable.svelte.d.ts +13 -0
- package/dist/components/SvarDataGrid.svelte +362 -0
- package/dist/components/SvarDataGrid.svelte.d.ts +57 -0
- package/dist/components/SvarGridCell.svelte +10 -0
- package/dist/components/SvarGridCell.svelte.d.ts +7 -0
- package/dist/components/SvarResourceRead.svelte +50 -0
- package/dist/components/SvarResourceRead.svelte.d.ts +23 -0
- package/dist/components/SvarResourceTable.svelte +63 -0
- package/dist/components/SvarResourceTable.svelte.d.ts +42 -0
- package/dist/components/SvarResourceTableView.svelte +364 -0
- package/dist/components/SvarResourceTableView.svelte.d.ts +4 -0
- package/dist/components/TaskQueueDrawer.svelte +72 -16
- package/dist/components/TreeSelect.svelte +208 -28
- package/dist/components/TreeSelect.svelte.d.ts +3 -1
- package/dist/components/auto-table-grid.d.ts +26 -0
- package/dist/components/auto-table-grid.js +1 -0
- package/dist/components/content/ContentPageHeader.svelte +12 -9
- package/dist/components/content/ContentPageShell.svelte +6 -9
- package/dist/components/content/FileBrowser.svelte +35 -0
- package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
- package/dist/components/content/MetricBlock.svelte +10 -13
- package/dist/components/content/NetworkTable.svelte +3 -3
- package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
- package/dist/components/content/PageToolbar.svelte +6 -10
- package/dist/components/content/SectionHeader.svelte +8 -13
- package/dist/components/content/SettingsFieldRow.svelte +9 -23
- package/dist/components/content/SettingsGroup.svelte +11 -27
- package/dist/components/content/StatusBadge.svelte +3 -8
- package/dist/components/content/WorkspaceLayout.svelte +8 -12
- package/dist/components/enterprise/filter-tree.d.ts +48 -0
- package/dist/components/enterprise/filter-tree.js +224 -0
- package/dist/components/enterprise/json-schema-form.d.ts +39 -0
- package/dist/components/enterprise/json-schema-form.js +195 -0
- package/dist/components/enterprise/recursive-schema-form.d.ts +30 -0
- package/dist/components/enterprise/recursive-schema-form.js +196 -0
- package/dist/components/enterprise/spreadsheet-formula.d.ts +12 -0
- package/dist/components/enterprise/spreadsheet-formula.js +245 -0
- package/dist/components/fieldComponentMap.js +5 -0
- package/dist/components/fields/DateField.svelte +4 -3
- package/dist/components/fields/date-field-value.d.ts +2 -0
- package/dist/components/fields/date-field-value.js +13 -0
- package/dist/components/json-schema-form-state.d.ts +37 -0
- package/dist/components/json-schema-form-state.js +168 -0
- package/dist/components/record-detail.svelte.d.ts +3 -0
- package/dist/components/record-detail.svelte.js +10 -4
- package/dist/components/svar-grid-cells.d.ts +14 -0
- package/dist/components/svar-grid-cells.js +2 -0
- package/dist/components/svar-grid-contract.d.ts +80 -0
- package/dist/components/svar-grid-contract.js +159 -0
- package/dist/components/svar-grid-interactions.d.ts +54 -0
- package/dist/components/svar-grid-interactions.js +174 -0
- package/dist/components/svar-grid-loading.d.ts +40 -0
- package/dist/components/svar-grid-loading.js +180 -0
- package/dist/components/svar-grid-operations.d.ts +37 -0
- package/dist/components/svar-grid-operations.js +186 -0
- package/dist/components/svar-grid-panes.d.ts +34 -0
- package/dist/components/svar-grid-panes.js +66 -0
- package/dist/components/svar-grid-resource-loading.d.ts +18 -0
- package/dist/components/svar-grid-resource-loading.js +68 -0
- package/dist/components/svar-grid-resource-session.svelte.d.ts +29 -0
- package/dist/components/svar-grid-resource-session.svelte.js +61 -0
- package/dist/components/ui/badge/badge-variants.js +3 -1
- package/dist/components/ui/button/button-variants.js +5 -2
- package/dist/components/ui/input/input.svelte +1 -4
- package/dist/components/ui/textarea/textarea.svelte +2 -1
- package/dist/components.css +3079 -0
- package/dist/design-contract.d.ts +13 -0
- package/dist/design-contract.js +11 -0
- package/dist/design-system.d.ts +15 -0
- package/dist/design-system.js +7 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +9 -0
- package/dist/page-chrome.css +12 -49
- package/dist/recipes.d.ts +4 -0
- package/dist/recipes.js +4 -0
- package/dist/rendering/index.d.ts +87 -0
- package/dist/rendering/index.js +117 -0
- package/dist/styled-system/css/conditions.js +36 -0
- package/dist/styled-system/css/css.d.ts +22 -0
- package/dist/styled-system/css/css.js +45 -0
- package/dist/styled-system/css/cva.d.ts +6 -0
- package/dist/styled-system/css/cva.js +87 -0
- package/dist/styled-system/css/cx.d.ts +5 -0
- package/dist/styled-system/css/cx.js +15 -0
- package/dist/styled-system/css/index.d.ts +5 -0
- package/dist/styled-system/css/index.js +4 -0
- package/dist/styled-system/css/sva.d.ts +4 -0
- package/dist/styled-system/css/sva.js +46 -0
- package/dist/styled-system/helpers.js +316 -0
- package/dist/styled-system/patterns/aspect-ratio.d.ts +20 -0
- package/dist/styled-system/patterns/aspect-ratio.js +38 -0
- package/dist/styled-system/patterns/bleed.d.ts +21 -0
- package/dist/styled-system/patterns/bleed.js +24 -0
- package/dist/styled-system/patterns/box.d.ts +20 -0
- package/dist/styled-system/patterns/box.js +15 -0
- package/dist/styled-system/patterns/center.d.ts +20 -0
- package/dist/styled-system/patterns/center.js +21 -0
- package/dist/styled-system/patterns/circle.d.ts +20 -0
- package/dist/styled-system/patterns/circle.js +25 -0
- package/dist/styled-system/patterns/container.d.ts +20 -0
- package/dist/styled-system/patterns/container.js +21 -0
- package/dist/styled-system/patterns/cq.d.ts +21 -0
- package/dist/styled-system/patterns/cq.js +21 -0
- package/dist/styled-system/patterns/divider.d.ts +22 -0
- package/dist/styled-system/patterns/divider.js +25 -0
- package/dist/styled-system/patterns/flex.d.ts +26 -0
- package/dist/styled-system/patterns/flex.js +26 -0
- package/dist/styled-system/patterns/float.d.ts +23 -0
- package/dist/styled-system/patterns/float.js +52 -0
- package/dist/styled-system/patterns/grid-item.d.ts +25 -0
- package/dist/styled-system/patterns/grid-item.js +25 -0
- package/dist/styled-system/patterns/grid.d.ts +24 -0
- package/dist/styled-system/patterns/grid.js +27 -0
- package/dist/styled-system/patterns/hstack.d.ts +21 -0
- package/dist/styled-system/patterns/hstack.js +24 -0
- package/dist/styled-system/patterns/index.d.ts +21 -0
- package/dist/styled-system/patterns/index.js +20 -0
- package/dist/styled-system/patterns/link-overlay.d.ts +20 -0
- package/dist/styled-system/patterns/link-overlay.js +24 -0
- package/dist/styled-system/patterns/spacer.d.ts +20 -0
- package/dist/styled-system/patterns/spacer.js +25 -0
- package/dist/styled-system/patterns/square.d.ts +20 -0
- package/dist/styled-system/patterns/square.js +24 -0
- package/dist/styled-system/patterns/stack.d.ts +23 -0
- package/dist/styled-system/patterns/stack.js +24 -0
- package/dist/styled-system/patterns/visually-hidden.d.ts +20 -0
- package/dist/styled-system/patterns/visually-hidden.js +18 -0
- package/dist/styled-system/patterns/vstack.d.ts +21 -0
- package/dist/styled-system/patterns/vstack.js +24 -0
- package/dist/styled-system/patterns/wrap.d.ts +24 -0
- package/dist/styled-system/patterns/wrap.js +25 -0
- package/dist/styled-system/recipes/content-header.d.ts +31 -0
- package/dist/styled-system/recipes/content-header.js +65 -0
- package/dist/styled-system/recipes/content-page.d.ts +34 -0
- package/dist/styled-system/recipes/content-page.js +43 -0
- package/dist/styled-system/recipes/create-recipe.js +82 -0
- package/dist/styled-system/recipes/index.d.ts +17 -0
- package/dist/styled-system/recipes/index.js +16 -0
- package/dist/styled-system/recipes/metric-block.d.ts +34 -0
- package/dist/styled-system/recipes/metric-block.js +76 -0
- package/dist/styled-system/recipes/product-list.d.ts +31 -0
- package/dist/styled-system/recipes/product-list.js +73 -0
- package/dist/styled-system/recipes/product-section.d.ts +31 -0
- package/dist/styled-system/recipes/product-section.js +49 -0
- package/dist/styled-system/recipes/product-settings-row.d.ts +34 -0
- package/dist/styled-system/recipes/product-settings-row.js +58 -0
- package/dist/styled-system/recipes/product-settings.d.ts +31 -0
- package/dist/styled-system/recipes/product-settings.js +57 -0
- package/dist/styled-system/recipes/product-status.d.ts +34 -0
- package/dist/styled-system/recipes/product-status.js +45 -0
- package/dist/styled-system/recipes/product-toolbar.d.ts +31 -0
- package/dist/styled-system/recipes/product-toolbar.js +41 -0
- package/dist/styled-system/recipes/product-workspace.d.ts +34 -0
- package/dist/styled-system/recipes/product-workspace.js +58 -0
- package/dist/styled-system/recipes/surface-metric.d.ts +38 -0
- package/dist/styled-system/recipes/surface-metric.js +63 -0
- package/dist/styled-system/recipes/surface-table.d.ts +34 -0
- package/dist/styled-system/recipes/surface-table.js +62 -0
- package/dist/styled-system/recipes/ui-badge.d.ts +31 -0
- package/dist/styled-system/recipes/ui-badge.js +38 -0
- package/dist/styled-system/recipes/ui-button.d.ts +32 -0
- package/dist/styled-system/recipes/ui-button.js +43 -0
- package/dist/styled-system/recipes/ui-input.d.ts +31 -0
- package/dist/styled-system/recipes/ui-input.js +49 -0
- package/dist/styled-system/recipes/ui-textarea.d.ts +31 -0
- package/dist/styled-system/recipes/ui-textarea.js +24 -0
- package/dist/styled-system/styles.css +1257 -0
- package/dist/styled-system/tokens/index.d.ts +9 -0
- package/dist/styled-system/tokens/index.js +268 -0
- package/dist/styled-system/tokens/tokens.d.ts +36 -0
- package/dist/styled-system/types/composition.d.ts +227 -0
- package/dist/styled-system/types/conditions.d.ts +236 -0
- package/dist/styled-system/types/csstype.d.ts +22570 -0
- package/dist/styled-system/types/index.d.ts +6 -0
- package/dist/styled-system/types/parts.d.ts +8 -0
- package/dist/styled-system/types/pattern.d.ts +78 -0
- package/dist/styled-system/types/prop-type.d.ts +223 -0
- package/dist/styled-system/types/recipe.d.ts +181 -0
- package/dist/styled-system/types/selectors.d.ts +59 -0
- package/dist/styled-system/types/static-css.d.ts +56 -0
- package/dist/styled-system/types/style-props.d.ts +8088 -0
- package/dist/styled-system/types/system-types.d.ts +151 -0
- package/dist/styles/aliases.css +49 -0
- package/dist/styles/compatibility.epilogue.css +384 -0
- package/dist/styles/compatibility.prelude.css +5513 -0
- package/dist/styles/conditional-states.css +28 -0
- package/dist/styles/conditional-utilities.css +22 -0
- package/dist/styles/recipes.css +1262 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +31 -13
- 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 {
|
|
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
|
|
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
|
|
96
|
-
if (onlyLeafSelectable &&
|
|
97
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
next =
|
|
105
|
-
|
|
106
|
-
|
|
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
|
|
325
|
+
{@const nodeHasChildren = hasChildren(node)}
|
|
159
326
|
{@const expanded = isNodeExpanded(node)}
|
|
160
|
-
{@const selected =
|
|
161
|
-
{@const
|
|
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-
|
|
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
|
|
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) =>
|
|
358
|
+
onclick={(e) => void toggleExpandAsync(node, e)}
|
|
191
359
|
>
|
|
192
|
-
{#if
|
|
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
|
|
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
|
|
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={'
|
|
17
|
+
<header class={styles.root + ' ' + className} data-svadmin-page-header>
|
|
15
18
|
{#if breadcrumbs.length > 0}
|
|
16
|
-
<nav aria-label="Breadcrumb" class=
|
|
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 ?
|
|
22
|
+
<span class={index === breadcrumbs.length - 1 ? styles.currentCrumb : ''}>{crumb}</span>
|
|
20
23
|
{/each}
|
|
21
24
|
</nav>
|
|
22
25
|
{/if}
|
|
23
|
-
<div class=
|
|
24
|
-
<div class=
|
|
25
|
-
{#if eyebrow}<p class=
|
|
26
|
-
<h1 class=
|
|
27
|
-
{#if description}<p class=
|
|
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=
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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={
|
|
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
|
|
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={
|
|
34
|
-
<div class=
|
|
35
|
-
<p class=
|
|
36
|
-
{#if icon}<span class=
|
|
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=
|
|
36
|
+
<Skeleton class={styles.skeleton} />
|
|
40
37
|
{:else}
|
|
41
|
-
<p class=
|
|
42
|
-
{#if detail || trend}<div class=
|
|
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))}
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
4
|
-
|
|
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
|
|
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=
|
|
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
|
-
|
|
4
|
-
|
|
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={
|
|
14
|
-
|
|
15
|
-
|
|
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=
|
|
13
|
+
{#if actions}<div class={styles.actions}>{@render actions()}</div>{/if}
|
|
19
14
|
</div>
|