@svadmin/ui 0.72.0 → 0.74.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 +62 -22
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/app.css +8488 -6297
- package/dist/app.theme.css +8514 -6374
- 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/component-registry.d.ts +14977 -0
- package/dist/component-registry.js +216 -0
- package/dist/components/AboutSettings.svelte +7 -1
- package/dist/components/AboutSettings.svelte.d.ts +4 -1
- package/dist/components/ActivityFeed.svelte +9 -3
- package/dist/components/ActivityFeed.svelte.d.ts +3 -0
- package/dist/components/AdminApp.svelte +19 -10
- package/dist/components/AdminApp.svelte.d.ts +6 -0
- package/dist/components/ApiSettings.svelte +41 -5
- package/dist/components/ApprovalCenter.svelte +283 -0
- package/dist/components/ApprovalCenter.svelte.d.ts +10 -0
- package/dist/components/AuditLogViewer.svelte +3 -1
- package/dist/components/AutoForm.svelte +53 -9
- package/dist/components/AutoForm.svelte.d.ts +3 -0
- package/dist/components/AutoTable.svelte +846 -43
- package/dist/components/AutoTable.svelte.d.ts +22 -1
- package/dist/components/BoundRecordDetailDrawer.svelte +17 -2
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +4 -0
- package/dist/components/Breadcrumbs.svelte +11 -1
- package/dist/components/CancelTaskButton.svelte +12 -42
- package/dist/components/ColorPicker.svelte +73 -0
- package/dist/components/ColorPicker.svelte.d.ts +15 -0
- package/dist/components/ComboboxField.svelte +143 -34
- package/dist/components/ComboboxField.svelte.d.ts +4 -2
- package/dist/components/CreatePage.svelte +4 -0
- package/dist/components/CreatePage.svelte.d.ts +2 -0
- package/dist/components/DashboardView.svelte +99 -0
- package/dist/components/DashboardView.svelte.d.ts +14 -0
- package/dist/components/DatePicker.svelte +10 -0
- package/dist/components/DatePicker.svelte.d.ts +6 -0
- package/dist/components/DateRangeInput.svelte +155 -0
- package/dist/components/DateRangeInput.svelte.d.ts +35 -0
- package/dist/components/DateRangePicker.svelte +10 -0
- package/dist/components/DateRangePicker.svelte.d.ts +6 -0
- package/dist/components/DateTimeInput.svelte +134 -0
- package/dist/components/DateTimeInput.svelte.d.ts +27 -0
- package/dist/components/DateTimePicker.svelte +10 -0
- package/dist/components/DateTimePicker.svelte.d.ts +6 -0
- package/dist/components/DevTools.svelte +36 -28
- package/dist/components/DevframePanel.svelte +123 -0
- package/dist/components/DevframePanel.svelte.d.ts +3 -0
- package/dist/components/EditPage.svelte +4 -0
- package/dist/components/EditPage.svelte.d.ts +2 -0
- package/dist/components/ErrorSummary.svelte +52 -0
- package/dist/components/ErrorSummary.svelte.d.ts +14 -0
- package/dist/components/FieldRenderer.svelte +172 -99
- package/dist/components/FileUpload.svelte +412 -0
- package/dist/components/FileUpload.svelte.d.ts +43 -0
- package/dist/components/FilterBuilder.svelte +244 -265
- package/dist/components/FilterBuilder.svelte.d.ts +3 -0
- package/dist/components/FilterCollectionInput.svelte +80 -0
- package/dist/components/FilterCollectionInput.svelte.d.ts +10 -0
- package/dist/components/GanttChart.svelte +66 -14
- package/dist/components/GanttChart.svelte.d.ts +6 -0
- package/dist/components/Header.svelte +18 -2
- package/dist/components/ImportWizard.svelte +509 -100
- package/dist/components/ImportWizard.svelte.d.ts +11 -0
- package/dist/components/JsonSchemaForm.svelte +322 -98
- package/dist/components/JsonSchemaForm.svelte.d.ts +18 -1
- package/dist/components/KanbanBoard.svelte +195 -40
- package/dist/components/KanbanBoard.svelte.d.ts +9 -2
- package/dist/components/Layout.svelte +4 -3
- package/dist/components/LazyAutoForm.svelte +28 -0
- package/dist/components/LazyAutoForm.svelte.d.ts +8 -0
- package/dist/components/LazyAutoTable.svelte +28 -0
- package/dist/components/LazyAutoTable.svelte.d.ts +8 -0
- package/dist/components/LazySettingsPage.svelte +28 -0
- package/dist/components/LazySettingsPage.svelte.d.ts +8 -0
- package/dist/components/LazyShowPage.svelte +28 -0
- package/dist/components/LazyShowPage.svelte.d.ts +8 -0
- package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +1 -1
- package/dist/components/ListPage.svelte +9 -1
- package/dist/components/ListPage.svelte.d.ts +5 -0
- package/dist/components/LoginPage.svelte +2 -2
- package/dist/components/MoneyInput.svelte +25 -0
- package/dist/components/MoneyInput.svelte.d.ts +20 -0
- package/dist/components/MultiTabKeepAlive.svelte +11 -6
- package/dist/components/NotificationsSettings.svelte +69 -2
- package/dist/components/NotificationsSettings.svelte.d.ts +25 -1
- 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/PermissionMatrix.svelte +20 -1
- package/dist/components/PivotExportButton.svelte +157 -0
- package/dist/components/PivotExportButton.svelte.d.ts +16 -0
- package/dist/components/PivotTable.svelte +229 -74
- package/dist/components/PivotTable.svelte.d.ts +19 -2
- package/dist/components/QuickEditDrawer.svelte +4 -1
- package/dist/components/QuickEditDrawer.svelte.d.ts +2 -0
- package/dist/components/RadioGroup.svelte +121 -0
- package/dist/components/RadioGroup.svelte.d.ts +43 -0
- package/dist/components/RangeSlider.svelte +127 -0
- package/dist/components/RangeSlider.svelte.d.ts +22 -0
- package/dist/components/Rate.svelte +121 -0
- package/dist/components/Rate.svelte.d.ts +16 -0
- package/dist/components/RecordDetailDrawer.svelte +6 -2
- package/dist/components/RecordDetailDrawer.svelte.d.ts +4 -0
- package/dist/components/RelationPicker.svelte +341 -0
- package/dist/components/RelationPicker.svelte.d.ts +26 -0
- package/dist/components/ResourceOperationsPage.svelte +25 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
- package/dist/components/RetryTaskButton.svelte +12 -42
- package/dist/components/SecuritySettings.svelte +29 -5
- package/dist/components/SegmentedControl.svelte +145 -0
- package/dist/components/SegmentedControl.svelte.d.ts +38 -0
- package/dist/components/SettingsPage.svelte +3 -1
- package/dist/components/SettingsPage.svelte.d.ts +1 -0
- package/dist/components/ShowInferencer.svelte +4 -2
- package/dist/components/ShowInferencer.svelte.d.ts +2 -0
- package/dist/components/ShowPage.svelte +25 -6
- package/dist/components/ShowPage.svelte.d.ts +5 -0
- package/dist/components/Sidebar.svelte +5 -5
- package/dist/components/Slider.svelte +100 -0
- package/dist/components/Slider.svelte.d.ts +19 -0
- package/dist/components/SpreadsheetView.svelte +1037 -124
- package/dist/components/SpreadsheetView.svelte.d.ts +19 -0
- 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/TagsInput.svelte +178 -0
- package/dist/components/TagsInput.svelte.d.ts +17 -0
- package/dist/components/TaskQueueDrawer.svelte +72 -16
- package/dist/components/TimePicker.svelte +10 -0
- package/dist/components/TimePicker.svelte.d.ts +6 -0
- package/dist/components/TreeSelect.svelte +440 -46
- package/dist/components/TreeSelect.svelte.d.ts +6 -1
- package/dist/components/TreeTable.svelte +484 -82
- package/dist/components/TreeTable.svelte.d.ts +24 -1
- package/dist/components/TwoFactorAuthPage.svelte +85 -48
- package/dist/components/TwoFactorAuthPage.svelte.d.ts +12 -1
- package/dist/components/VirtualTable.svelte +116 -20
- package/dist/components/VirtualTable.svelte.d.ts +5 -0
- package/dist/components/account/CompanyProfilePage.svelte +74 -38
- package/dist/components/account/GetStartedPage.svelte +2 -1
- package/dist/components/account/ImportMembersPage.svelte +22 -167
- package/dist/components/account/ImportMembersPage.svelte.d.ts +4 -1
- package/dist/components/account/MemberDirectory.svelte +156 -0
- package/dist/components/account/MemberDirectory.svelte.d.ts +19 -0
- package/dist/components/account/MembersStarterPage.svelte +9 -55
- package/dist/components/account/MembersStarterPage.svelte.d.ts +5 -1
- package/dist/components/account/SecurityLogPage.svelte +4 -1
- package/dist/components/account/SettingsPlainPage.svelte +7 -38
- package/dist/components/account/SettingsPlainPage.svelte.d.ts +4 -1
- package/dist/components/account/SettingsSidebarPage.svelte +7 -20
- package/dist/components/account/TeamMembersPage.svelte +4 -20
- package/dist/components/account/TeamMembersPage.svelte.d.ts +5 -1
- package/dist/components/account/UserProfilePage.svelte +3 -25
- package/dist/components/account/UserProfilePage.svelte.d.ts +17 -2
- package/dist/components/auto-table-grid.d.ts +26 -0
- package/dist/components/auto-table-grid.js +1 -0
- package/dist/components/buttons/ExportButton.svelte +56 -12
- package/dist/components/buttons/ExportButton.svelte.d.ts +11 -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/ReferenceNotice.svelte +5 -0
- package/dist/components/content/ReferenceNotice.svelte.d.ts +18 -0
- 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/export-reference.d.ts +2 -0
- package/dist/components/export-reference.js +9 -0
- package/dist/components/fieldComponentMap.js +2 -0
- package/dist/components/fields/DateField.svelte +12 -12
- package/dist/components/fields/date-display.d.ts +6 -0
- package/dist/components/fields/date-display.js +24 -0
- 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/network/TeamCrewTablePage.svelte +6 -1
- package/dist/components/network/UserCardsNFTPage.svelte +2 -0
- package/dist/components/profile/PublicProfilePage.svelte +2 -0
- package/dist/components/record-detail.svelte.d.ts +3 -0
- package/dist/components/record-detail.svelte.js +10 -4
- package/dist/components/saved-list-views.d.ts +74 -1
- package/dist/components/saved-list-views.js +191 -3
- 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/table-contract.d.ts +12 -1
- package/dist/components/task-action.svelte.d.ts +13 -0
- package/dist/components/task-action.svelte.js +73 -0
- package/dist/components/ui/DesignSystemShowcase.svelte +164 -0
- package/dist/components/ui/DesignSystemShowcase.svelte.d.ts +3 -0
- package/dist/components/ui/badge/badge-variants.d.ts +3 -2
- package/dist/components/ui/badge/badge-variants.js +2 -1
- package/dist/components/ui/badge/badge.svelte +3 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +1 -0
- package/dist/components/ui/button/button-variants.d.ts +5 -4
- package/dist/components/ui/button/button-variants.js +7 -2
- package/dist/components/ui/checkbox/checkbox.svelte +5 -1
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +5 -1
- package/dist/components/ui/input/input.svelte +8 -6
- package/dist/components/ui/input/input.svelte.d.ts +4 -1
- package/dist/components/ui/select/select.svelte +4 -1
- package/dist/components/ui/select/select.svelte.d.ts +2 -1
- package/dist/components/ui/textarea/textarea.svelte +2 -1
- package/dist/components.css +3110 -0
- package/dist/date-input-policy.d.ts +4 -0
- package/dist/date-input-policy.js +35 -0
- package/dist/design-contract.d.ts +13 -0
- package/dist/design-contract.js +11 -0
- package/dist/design-system-components.d.ts +100 -0
- package/dist/design-system-components.js +101 -0
- package/dist/design-system.d.ts +15 -0
- package/dist/design-system.js +7 -0
- package/dist/devtools-bridge.d.ts +80 -0
- package/dist/devtools-bridge.js +92 -0
- package/dist/index.d.ts +50 -1
- package/dist/index.js +32 -2
- package/dist/page-chrome.css +12 -49
- package/dist/recipes.d.ts +960 -0
- package/dist/recipes.js +264 -0
- package/dist/rendering/index.d.ts +87 -0
- package/dist/rendering/index.js +117 -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/tree-table-model.d.ts +24 -0
- package/dist/tree-table-model.js +111 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +40 -10
- package/styles-compatibility.json +12 -0
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import { type ResourceRendering } from '../rendering/index.js';
|
|
2
|
+
import type { AutoTableGridState } from './auto-table-grid.js';
|
|
3
|
+
import { type ExportFormat, type TaskProvider } from '@svadmin/core';
|
|
4
|
+
import { type BatchSelection } from './table-contract';
|
|
1
5
|
import type { BaseRecord, FieldDefinition, Sort } from '@svadmin/core';
|
|
6
|
+
import { type SavedListViewProvider } from './saved-list-views.js';
|
|
2
7
|
import type { Snippet } from 'svelte';
|
|
3
8
|
interface Props {
|
|
4
9
|
resourceName: string;
|
|
10
|
+
rendering?: ResourceRendering | undefined;
|
|
11
|
+
/** 可选主体渲染器:不替换资源、权限、工具栏和持久化逻辑。 */
|
|
12
|
+
gridBody?: Snippet<[AutoTableGridState]>;
|
|
5
13
|
selectable?: boolean;
|
|
14
|
+
/** 仅在业务回调支持按查询执行服务端命令时启用。 */
|
|
15
|
+
allowSelectAllMatching?: boolean;
|
|
6
16
|
density?: 'compact' | 'comfortable';
|
|
7
17
|
showHeader?: boolean;
|
|
8
18
|
title?: string;
|
|
@@ -40,9 +50,10 @@ interface Props {
|
|
|
40
50
|
};
|
|
41
51
|
/** Externally controlled sorters */
|
|
42
52
|
sorters?: Sort[];
|
|
43
|
-
/**
|
|
53
|
+
/** 批量操作必须按 selection.scope 区分明确 ID 与全部查询结果。 */
|
|
44
54
|
batchActions?: Snippet<[{
|
|
45
55
|
selectedIds: (string | number)[];
|
|
56
|
+
selection: BatchSelection;
|
|
46
57
|
}]>;
|
|
47
58
|
/** Summary row rendered at table footer */
|
|
48
59
|
summary?: Snippet<[{
|
|
@@ -51,6 +62,16 @@ interface Props {
|
|
|
51
62
|
visibleColumnsCount: number;
|
|
52
63
|
}]>;
|
|
53
64
|
deleteVariables?: unknown;
|
|
65
|
+
/** 团队/系统视图;写入需要 Provider 能力和显式可写标记。 */
|
|
66
|
+
savedViewProvider?: SavedListViewProvider;
|
|
67
|
+
/** 显式允许唯一的远程默认视图在无 URL/个人活动视图时初始化页面。 */
|
|
68
|
+
applyRemoteDefaultView?: boolean;
|
|
69
|
+
/** 提供任务名后按当前筛选/排序提交全量导出;未提供时仍导出当前已加载页。 */
|
|
70
|
+
exportTaskName?: string;
|
|
71
|
+
exportTaskProvider?: TaskProvider;
|
|
72
|
+
exportTaskIdempotencyKey?: string;
|
|
73
|
+
exportFormat?: ExportFormat;
|
|
74
|
+
exportMaxItemCount?: number;
|
|
54
75
|
}
|
|
55
76
|
declare const AutoTable: import("svelte").Component<Props, {}, "">;
|
|
56
77
|
type AutoTable = ReturnType<typeof AutoTable>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { ResourceRendering } from '../rendering/index.js';
|
|
2
3
|
import { definedOptions } from '@svadmin/core/options';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
3
5
|
|
|
4
6
|
import { useCan, useNavigation, type FieldDefinition } from '@svadmin/core';
|
|
5
7
|
import { useRecordDetail } from './record-detail.svelte';
|
|
@@ -12,19 +14,23 @@
|
|
|
12
14
|
|
|
13
15
|
let {
|
|
14
16
|
resourceName,
|
|
17
|
+
rendering,
|
|
15
18
|
open = $bindable(false),
|
|
16
19
|
recordId,
|
|
17
20
|
onClose,
|
|
21
|
+
extraSections,
|
|
18
22
|
}: {
|
|
19
23
|
resourceName: string;
|
|
24
|
+
rendering?: ResourceRendering | undefined;
|
|
20
25
|
open?: boolean;
|
|
21
26
|
recordId: string | number;
|
|
22
27
|
onClose?: () => void;
|
|
28
|
+
extraSections?: Snippet;
|
|
23
29
|
} = $props();
|
|
24
30
|
|
|
25
31
|
const i18n = useTranslation();
|
|
26
32
|
const navigation = useNavigation();
|
|
27
|
-
const detail = useRecordDetail(() => ({ resourceName, id: recordId }));
|
|
33
|
+
const detail = useRecordDetail(() => ({ resourceName, id: recordId, rendering }));
|
|
28
34
|
const resource = $derived(detail.resource);
|
|
29
35
|
const showFields = $derived(detail.fields);
|
|
30
36
|
const fieldGroups = $derived.by(() => {
|
|
@@ -68,12 +74,13 @@
|
|
|
68
74
|
|
|
69
75
|
{#snippet fieldsList(fields: FieldDefinition[])}
|
|
70
76
|
{#if query.isSuccess}
|
|
77
|
+
{@const record = detail.rendering ? detail.rendering.record(query.data.data) : query.data.data}
|
|
71
78
|
<dl class="svadmin-u-fa6acbf81d74 svadmin-u-d2c3932343f5">
|
|
72
79
|
{#each fields as field (field.key)}
|
|
73
80
|
<div class="svadmin-u-f3c543ad5fe9 svadmin-u-58284b4ea568 svadmin-u-cb11fec3bb46 svadmin-u-d9bdd3d643a2 svadmin-u-022e8076dfea">
|
|
74
81
|
<dt class="svadmin-u-359090c2d529 svadmin-u-2689f3958069 svadmin-u-bfa603190748 svadmin-u-e2327d142859">{field.label}</dt>
|
|
75
82
|
<dd class="svadmin-u-7e0b7cdf1a94 svadmin-u-170cee3ff4e4 svadmin-u-fc7473ca09eb svadmin-u-d4108abe6359">
|
|
76
|
-
<FieldDisplay type={field.type} value={
|
|
83
|
+
<FieldDisplay type={field.type} value={record[field.key]} options={field.options} resourceName={field.resource} />
|
|
77
84
|
</dd>
|
|
78
85
|
</div>
|
|
79
86
|
{/each}
|
|
@@ -83,6 +90,8 @@
|
|
|
83
90
|
|
|
84
91
|
<DetailDrawer
|
|
85
92
|
bind:open
|
|
93
|
+
data-svadmin-rendering-resource={detail.rendering?.resource.name}
|
|
94
|
+
data-svadmin-rendering-kind={detail.rendering ? 'detail-drawer' : undefined}
|
|
86
95
|
title="{resource.label} {i18n.t('common.detail')}"
|
|
87
96
|
description={`#${recordId}`}
|
|
88
97
|
closeLabel={i18n.t('common.close')}
|
|
@@ -143,6 +152,12 @@
|
|
|
143
152
|
</div>
|
|
144
153
|
{/if}
|
|
145
154
|
|
|
155
|
+
{#if extraSections && canReadRecord && query.isSuccess}
|
|
156
|
+
<section data-svadmin-detail-extensions aria-label={i18n.t('common.additionalDetails')}>
|
|
157
|
+
{@render extraSections()}
|
|
158
|
+
</section>
|
|
159
|
+
{/if}
|
|
160
|
+
|
|
146
161
|
{#snippet footer()}
|
|
147
162
|
{#if canReadRecord && query.isSuccess}
|
|
148
163
|
<Button type="button" variant="outline" onclick={() => navigateTo('show')}>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import type { ResourceRendering } from '../rendering/index.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
1
3
|
type $$ComponentProps = {
|
|
2
4
|
resourceName: string;
|
|
5
|
+
rendering?: ResourceRendering | undefined;
|
|
3
6
|
open?: boolean;
|
|
4
7
|
recordId: string | number;
|
|
5
8
|
onClose?: () => void;
|
|
9
|
+
extraSections?: Snippet;
|
|
6
10
|
};
|
|
7
11
|
declare const BoundRecordDetailDrawer: import("svelte").Component<$$ComponentProps, {}, "open">;
|
|
8
12
|
type BoundRecordDetailDrawer = ReturnType<typeof BoundRecordDetailDrawer>;
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
interface Crumb { label: string; href?: string; }
|
|
19
19
|
|
|
20
|
+
// 仅复用 AdminApp 明确支持的成员页别名,宿主精确菜单项始终优先。
|
|
21
|
+
const memberAliases: Readonly<Record<string, string>> = {
|
|
22
|
+
'/account/members-starter': '/account/members/members-starter',
|
|
23
|
+
'/account/team-members': '/account/members/team-members',
|
|
24
|
+
};
|
|
25
|
+
|
|
20
26
|
function normalizePath(path: string): string {
|
|
21
27
|
const normalized = path.replace(/^#/, '').replace(/[?#].*$/, '').replace(/\/$/, '');
|
|
22
28
|
return normalized || '/';
|
|
@@ -38,7 +44,11 @@
|
|
|
38
44
|
const currentPathname = normalizePath(getPath());
|
|
39
45
|
if (currentPathname === '/') return result;
|
|
40
46
|
|
|
41
|
-
const
|
|
47
|
+
const canonicalPath = memberAliases[currentPathname];
|
|
48
|
+
const menuTrail = menu
|
|
49
|
+
? findMenuTrail(menu, currentPathname)
|
|
50
|
+
?? (canonicalPath ? findMenuTrail(menu, canonicalPath) : undefined)
|
|
51
|
+
: undefined;
|
|
42
52
|
if (menuTrail) {
|
|
43
53
|
for (const item of menuTrail) {
|
|
44
54
|
result.push(definedOptions({
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { captureAdminContext, queryKeyMatches, withValidatedTaskProvider } from '@svadmin/core';
|
|
3
|
-
import { useQueryClient } from '@tanstack/svelte-query';
|
|
4
2
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
3
|
|
|
6
4
|
import { Button } from './ui/button/index.js';
|
|
7
5
|
import { Loader2, Ban } from '@lucide/svelte';
|
|
6
|
+
import { createTaskAction } from './task-action.svelte.js';
|
|
8
7
|
|
|
9
8
|
const i18n = useTranslation();
|
|
10
|
-
const adminContext = captureAdminContext();
|
|
11
9
|
|
|
12
10
|
let {
|
|
13
11
|
taskId,
|
|
14
|
-
taskProvider
|
|
12
|
+
taskProvider,
|
|
15
13
|
onSuccess,
|
|
16
14
|
onError,
|
|
17
15
|
disabled = false,
|
|
@@ -29,46 +27,18 @@
|
|
|
29
27
|
children?: import('svelte').Snippet;
|
|
30
28
|
}>();
|
|
31
29
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const provider = withValidatedTaskProvider(taskProvider);
|
|
42
|
-
if (!provider.cancel) return;
|
|
43
|
-
await provider.cancel(scopedTaskId);
|
|
44
|
-
await Promise.all([
|
|
45
|
-
queryClient.invalidateQueries({
|
|
46
|
-
predicate: (query) => queryKeyMatches(query.queryKey, {
|
|
47
|
-
...scope,
|
|
48
|
-
kind: 'task',
|
|
49
|
-
action: 'list',
|
|
50
|
-
}),
|
|
51
|
-
}),
|
|
52
|
-
queryClient.invalidateQueries({
|
|
53
|
-
predicate: (query) => queryKeyMatches(query.queryKey, {
|
|
54
|
-
...scope,
|
|
55
|
-
kind: 'task',
|
|
56
|
-
action: 'one',
|
|
57
|
-
id: scopedTaskId,
|
|
58
|
-
}),
|
|
59
|
-
}),
|
|
60
|
-
]);
|
|
61
|
-
onSuccess?.();
|
|
62
|
-
} catch (error) {
|
|
63
|
-
onError?.(error);
|
|
64
|
-
} finally {
|
|
65
|
-
pending = false;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
30
|
+
const action = createTaskAction({
|
|
31
|
+
action: 'cancel',
|
|
32
|
+
get taskId() { return taskId; },
|
|
33
|
+
get provider() { return taskProvider; },
|
|
34
|
+
get disabled() { return disabled; },
|
|
35
|
+
get onSuccess() { return onSuccess; },
|
|
36
|
+
get onError() { return onError; },
|
|
37
|
+
});
|
|
68
38
|
</script>
|
|
69
39
|
|
|
70
|
-
<Button {variant} {size} onclick={
|
|
71
|
-
{#if pending}
|
|
40
|
+
<Button {variant} {size} onclick={action.run} disabled={!action.available || action.pending}>
|
|
41
|
+
{#if action.pending}
|
|
72
42
|
<Loader2 class="svadmin-u-82cc6c6581cd svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-afbdd13a380e" />
|
|
73
43
|
{:else}
|
|
74
44
|
<Ban class="svadmin-u-82cc6c6581cd svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" />
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../utils.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
value?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
invalid?: boolean;
|
|
11
|
+
describedby?: string;
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
onchange?: (value: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
value = $bindable(''),
|
|
19
|
+
name,
|
|
20
|
+
id,
|
|
21
|
+
disabled = false,
|
|
22
|
+
required = false,
|
|
23
|
+
invalid = false,
|
|
24
|
+
describedby,
|
|
25
|
+
ariaLabel,
|
|
26
|
+
class: className = '',
|
|
27
|
+
onchange,
|
|
28
|
+
}: Props = $props();
|
|
29
|
+
|
|
30
|
+
function handleInput(event: Event): void {
|
|
31
|
+
const input = event.currentTarget;
|
|
32
|
+
if (!(input instanceof HTMLInputElement) || disabled) return;
|
|
33
|
+
value = input.value;
|
|
34
|
+
onchange?.(input.value);
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<input
|
|
39
|
+
class={cn('svadmin-color-picker', className)}
|
|
40
|
+
{id}
|
|
41
|
+
{name}
|
|
42
|
+
type="color"
|
|
43
|
+
value={value}
|
|
44
|
+
{disabled}
|
|
45
|
+
{required}
|
|
46
|
+
aria-label={ariaLabel}
|
|
47
|
+
aria-invalid={invalid || undefined}
|
|
48
|
+
aria-describedby={describedby}
|
|
49
|
+
oninput={handleInput}
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<style>
|
|
53
|
+
.svadmin-color-picker {
|
|
54
|
+
display: block;
|
|
55
|
+
inline-size: 40px;
|
|
56
|
+
block-size: 32px;
|
|
57
|
+
padding: 2px;
|
|
58
|
+
border: 1px solid var(--border);
|
|
59
|
+
border-radius: 6px;
|
|
60
|
+
background: var(--background);
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.svadmin-color-picker:focus-visible {
|
|
65
|
+
outline: 2px solid var(--ring);
|
|
66
|
+
outline-offset: 2px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.svadmin-color-picker:disabled {
|
|
70
|
+
cursor: not-allowed;
|
|
71
|
+
opacity: 0.5;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
invalid?: boolean;
|
|
8
|
+
describedby?: string;
|
|
9
|
+
ariaLabel?: string;
|
|
10
|
+
class?: string;
|
|
11
|
+
onchange?: (value: string) => void;
|
|
12
|
+
}
|
|
13
|
+
declare const ColorPicker: import("svelte").Component<Props, {}, "value">;
|
|
14
|
+
type ColorPicker = ReturnType<typeof ColorPicker>;
|
|
15
|
+
export default ColorPicker;
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { definedReactiveOptions } from '@svadmin/core/options';
|
|
3
3
|
|
|
4
4
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
|
-
import { useResourceContract, useSelect } from '@svadmin/core';
|
|
5
|
+
import { captureAdminContext, captureAuthSession, useResourceContract, useSelect } from '@svadmin/core';
|
|
6
|
+
import { onDestroy, untrack } from 'svelte';
|
|
6
7
|
import type { BaseRecord, Filter } from '@svadmin/core';
|
|
7
8
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
8
9
|
import type { ButtonProps } from './ui/button/index.js';
|
|
@@ -23,13 +24,15 @@
|
|
|
23
24
|
|
|
24
25
|
interface Props extends Omit<HTMLButtonAttributes, 'value' | 'onchange' | 'children' | 'onclick' | 'type'> {
|
|
25
26
|
resource: string;
|
|
26
|
-
value?: string | number | null;
|
|
27
|
-
onchange?: (value: string | number | null) => void;
|
|
27
|
+
value?: string | number | null | (string | number)[];
|
|
28
|
+
onchange?: (value: string | number | null | (string | number)[]) => void;
|
|
28
29
|
optionLabel?: string;
|
|
29
30
|
optionValue?: string;
|
|
30
31
|
placeholder?: string;
|
|
31
32
|
searchable?: boolean;
|
|
33
|
+
multiple?: boolean;
|
|
32
34
|
onSearch?: (value: string) => Filter[];
|
|
35
|
+
fetchSize?: number;
|
|
33
36
|
id?: string;
|
|
34
37
|
class?: string;
|
|
35
38
|
}
|
|
@@ -40,20 +43,51 @@
|
|
|
40
43
|
onchange,
|
|
41
44
|
optionLabel = 'title',
|
|
42
45
|
optionValue = 'id',
|
|
43
|
-
placeholder
|
|
46
|
+
placeholder,
|
|
44
47
|
searchable = true,
|
|
48
|
+
multiple = false,
|
|
45
49
|
onSearch,
|
|
50
|
+
fetchSize = 50,
|
|
46
51
|
disabled = false,
|
|
47
52
|
...restProps
|
|
48
53
|
}: Props = $props();
|
|
49
54
|
|
|
50
55
|
const buttonRestProps = $derived(restProps as Omit<ButtonProps, 'children' | 'variant' | 'size'>);
|
|
56
|
+
let open = $state(false);
|
|
57
|
+
let searchInputValue = $state('');
|
|
58
|
+
let page = $state(1);
|
|
59
|
+
let appliedSearch = $state('');
|
|
60
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
61
|
+
onDestroy(() => clearTimeout(timer));
|
|
62
|
+
const normalizedFetchSize = $derived(
|
|
63
|
+
Number.isSafeInteger(fetchSize) && fetchSize >= 10 && fetchSize <= 200 ? fetchSize : 50,
|
|
64
|
+
);
|
|
51
65
|
|
|
52
66
|
const binding = useResourceContract(() => resource);
|
|
67
|
+
const context = captureAdminContext();
|
|
68
|
+
const sourceScope = $derived({
|
|
69
|
+
contract: binding.resource, provider: context.providers?.[binding.dataProviderName],
|
|
70
|
+
meta: JSON.stringify(binding.meta), tenant: context.tenantCacheKey?.__svadminTenant,
|
|
71
|
+
auth: context.authProvider, session: captureAuthSession(context.authProvider).cacheKey,
|
|
72
|
+
access: context.accessControlProvider, router: context.routerProvider,
|
|
73
|
+
optionLabel, optionValue, onSearch, searchable, normalizedFetchSize,
|
|
74
|
+
});
|
|
75
|
+
type Option = { value: string | number; label: string };
|
|
76
|
+
let loaded = $state.raw<{ scope: typeof sourceScope; search: string; options: Option[] }>();
|
|
53
77
|
const defaultSearch = $derived.by(() => {
|
|
54
78
|
const field = optionLabel;
|
|
55
79
|
return (v: string): Filter[] => v ? [{ field, operator: 'contains', value: v }] : [];
|
|
56
80
|
});
|
|
81
|
+
const searchFilters = $derived.by(() => {
|
|
82
|
+
try {
|
|
83
|
+
return {
|
|
84
|
+
filters: appliedSearch && (onSearch || searchable)
|
|
85
|
+
? (onSearch ?? defaultSearch)(appliedSearch)
|
|
86
|
+
: [],
|
|
87
|
+
invalid: false,
|
|
88
|
+
};
|
|
89
|
+
} catch { return { filters: [], invalid: true }; }
|
|
90
|
+
});
|
|
57
91
|
const select = useSelect(definedReactiveOptions({
|
|
58
92
|
get resource() { return binding.resource; },
|
|
59
93
|
get dataProviderName() { return binding.dataProviderName; },
|
|
@@ -67,44 +101,108 @@
|
|
|
67
101
|
};
|
|
68
102
|
},
|
|
69
103
|
get projectionKey() { return `combobox:${optionLabel}:${optionValue}`; },
|
|
70
|
-
get
|
|
71
|
-
get
|
|
104
|
+
get fetchSize() { return normalizedFetchSize; },
|
|
105
|
+
get pagination() { return { current: page, pageSize: normalizedFetchSize }; },
|
|
106
|
+
get defaultValue() {
|
|
107
|
+
if (Array.isArray(value)) return value;
|
|
108
|
+
return value === null || value === undefined || value === '' ? [] : [value];
|
|
109
|
+
},
|
|
110
|
+
get filters() { return searchFilters.filters; },
|
|
111
|
+
get queryOptions() { return { enabled: !searchFilters.invalid }; },
|
|
72
112
|
}));
|
|
73
113
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
void binding.dataProviderName;
|
|
79
|
-
void binding.meta;
|
|
80
|
-
searchInputValue = '';
|
|
114
|
+
$effect.pre(() => {
|
|
115
|
+
void sourceScope;
|
|
116
|
+
clearTimeout(timer);
|
|
117
|
+
searchInputValue = appliedSearch = '';
|
|
81
118
|
open = false;
|
|
119
|
+
page = 1;
|
|
120
|
+
loaded = undefined;
|
|
121
|
+
});
|
|
122
|
+
$effect(() => {
|
|
123
|
+
const data = select.query.data;
|
|
124
|
+
if (!data || select.query.isFetching || select.isError || searchFilters.invalid) return;
|
|
125
|
+
const scope = sourceScope;
|
|
126
|
+
const search = appliedSearch;
|
|
127
|
+
const previous = untrack(() => loaded);
|
|
128
|
+
const options = new Map<string | number, Option>(
|
|
129
|
+
page > 1 && previous?.scope === scope && previous.search === search
|
|
130
|
+
? previous.options.map(option => [option.value, option]) : [],
|
|
131
|
+
);
|
|
132
|
+
for (const option of data.options) options.set(option.value, option);
|
|
133
|
+
loaded = { scope, search, options: [...options.values()] };
|
|
82
134
|
});
|
|
83
135
|
|
|
84
|
-
const
|
|
85
|
-
|
|
136
|
+
const selectedValues = $derived(
|
|
137
|
+
Array.isArray(value) ? value : value === null || value === undefined ? [] : [value],
|
|
86
138
|
);
|
|
139
|
+
const availableOptions = $derived.by(() => {
|
|
140
|
+
if (select.isError || searchFilters.invalid) return [];
|
|
141
|
+
const options = new Map<string | number, Option>(
|
|
142
|
+
loaded?.scope === sourceScope && loaded.search === appliedSearch
|
|
143
|
+
? loaded.options.map(option => [option.value, option]) : [],
|
|
144
|
+
);
|
|
145
|
+
for (const option of select.options) options.set(option.value, option);
|
|
146
|
+
return [...options.values()];
|
|
147
|
+
});
|
|
148
|
+
const totalOptions = $derived(select.query.data?.total ?? availableOptions.length);
|
|
149
|
+
const hasMore = $derived(totalOptions > page * normalizedFetchSize && !select.isError
|
|
150
|
+
&& !searchFilters.invalid && searchInputValue === appliedSearch);
|
|
151
|
+
const invalidOptions = $derived(select.isError || searchFilters.invalid);
|
|
152
|
+
const selectedLabels = $derived(selectedValues.flatMap(selectedValue => {
|
|
153
|
+
const option = availableOptions.find(candidate => candidate.value === selectedValue);
|
|
154
|
+
return option ? [option.label] : [];
|
|
155
|
+
}));
|
|
156
|
+
const selectedLabel = $derived(selectedLabels.join(', '));
|
|
87
157
|
|
|
88
158
|
function handleSelect(optValue: string | number) {
|
|
159
|
+
if (disabled || invalidOptions || select.isFetching || searchInputValue !== appliedSearch) return;
|
|
160
|
+
if (multiple) {
|
|
161
|
+
const next = selectedValues.includes(optValue)
|
|
162
|
+
? selectedValues.filter(selectedValue => selectedValue !== optValue)
|
|
163
|
+
: [...selectedValues, optValue];
|
|
164
|
+
onchange?.(next);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
89
167
|
onchange?.(optValue === value ? null : optValue);
|
|
90
168
|
open = false;
|
|
91
|
-
|
|
92
|
-
select.onSearchChange('');
|
|
169
|
+
resetSearch();
|
|
93
170
|
}
|
|
94
171
|
|
|
95
172
|
function handleClear(e: Event) {
|
|
96
173
|
e.stopPropagation();
|
|
97
|
-
|
|
174
|
+
if (disabled) return;
|
|
175
|
+
onchange?.(multiple ? [] : null);
|
|
98
176
|
open = false;
|
|
99
|
-
|
|
100
|
-
|
|
177
|
+
resetSearch();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function resetSearch(): void {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
searchInputValue = appliedSearch = '';
|
|
183
|
+
page = 1;
|
|
184
|
+
loaded = undefined;
|
|
101
185
|
}
|
|
102
186
|
|
|
103
187
|
function handleSearchInput(e: Event) {
|
|
104
188
|
if (!(e.currentTarget instanceof HTMLInputElement)) return;
|
|
105
189
|
const v = e.currentTarget.value;
|
|
106
190
|
searchInputValue = v;
|
|
107
|
-
|
|
191
|
+
clearTimeout(timer);
|
|
192
|
+
const scope = sourceScope;
|
|
193
|
+
const apply = () => {
|
|
194
|
+
if (scope !== sourceScope || disabled) return;
|
|
195
|
+
appliedSearch = v;
|
|
196
|
+
page = 1;
|
|
197
|
+
loaded = undefined;
|
|
198
|
+
};
|
|
199
|
+
if (!v) apply();
|
|
200
|
+
else timer = setTimeout(apply, 300);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function loadMore(): void {
|
|
204
|
+
if (disabled || select.isFetching || !hasMore) return;
|
|
205
|
+
page += 1;
|
|
108
206
|
}
|
|
109
207
|
</script>
|
|
110
208
|
|
|
@@ -119,26 +217,27 @@
|
|
|
119
217
|
{disabled}
|
|
120
218
|
aria-haspopup="listbox"
|
|
121
219
|
aria-expanded={open}
|
|
220
|
+
aria-multiselectable={multiple || undefined}
|
|
122
221
|
aria-busy={select.isFetching}
|
|
123
|
-
aria-invalid={
|
|
222
|
+
aria-invalid={invalidOptions || restProps['aria-invalid']}
|
|
124
223
|
>
|
|
125
224
|
{#if selectedLabel}
|
|
126
225
|
<span class="svadmin-u-f283ea9bea0e">{selectedLabel}</span>
|
|
127
226
|
{:else}
|
|
128
|
-
<span class="svadmin-u-bfa603190748">{placeholder}</span>
|
|
227
|
+
<span class="svadmin-u-bfa603190748">{placeholder ?? i18n.t('field.selectPlaceholder')}</span>
|
|
129
228
|
{/if}
|
|
130
229
|
<ChevronsUpDown class="svadmin-u-fb56d9cff341 svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3 svadmin-u-012fbd121f37 svadmin-u-0b8c506a0596" />
|
|
131
230
|
</Button>
|
|
132
|
-
{#if
|
|
231
|
+
{#if selectedValues.length}
|
|
133
232
|
<Button type="button" variant="ghost" size="icon-sm" {disabled}
|
|
134
233
|
title={i18n.t('common.clear')} aria-label={i18n.t('common.clear')} onclick={handleClear}>
|
|
135
234
|
<X class="svadmin-u-6a60c09e6aaa svadmin-u-9cea05671a29" />
|
|
136
235
|
</Button>
|
|
137
236
|
{/if}
|
|
138
237
|
</div>
|
|
139
|
-
{#if
|
|
238
|
+
{#if invalidOptions}
|
|
140
239
|
<div role="alert" class="select-error">
|
|
141
|
-
<span>
|
|
240
|
+
<span>{i18n.t('select.loadFailed')}</span>
|
|
142
241
|
<Button type="button" variant="ghost" size="icon-sm" disabled={disabled || select.isFetching}
|
|
143
242
|
title={i18n.t('common.retry')} aria-label={i18n.t('common.retry')} onclick={() => select.refetch()}>
|
|
144
243
|
<RotateCw class="svadmin-u-6a60c09e6aaa svadmin-u-9cea05671a29" />
|
|
@@ -146,7 +245,7 @@
|
|
|
146
245
|
</div>
|
|
147
246
|
{/if}
|
|
148
247
|
|
|
149
|
-
{#if open}
|
|
248
|
+
{#if open && !disabled}
|
|
150
249
|
<div class="svadmin-u-da4dbfbc4fdc svadmin-u-181b286668b5 svadmin-u-b6b02c0ebef6 svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e541d86d1ec8 svadmin-u-06bbb43166db">
|
|
151
250
|
<Command.Root shouldFilter={false} class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-2cd02d11d1af svadmin-u-421ac2be5045 svadmin-u-e541d86d1ec8 svadmin-u-9b13e8ae5c9c">
|
|
152
251
|
{#if searchable}
|
|
@@ -155,34 +254,44 @@
|
|
|
155
254
|
<Command.Input
|
|
156
255
|
bind:value={searchInputValue}
|
|
157
256
|
oninput={handleSearchInput}
|
|
158
|
-
placeholder=
|
|
257
|
+
placeholder={i18n.t('common.search')}
|
|
159
258
|
class="svadmin-u-60fbb7713999 svadmin-u-e7a768f922d2 svadmin-u-6da6a3c3f741 svadmin-u-7f19cdf4c5bb svadmin-u-03b4dd7f172b svadmin-u-fc7473ca09eb svadmin-u-df37b1fd9495 svadmin-u-9c24ab70af61"
|
|
160
259
|
/>
|
|
161
260
|
</div>
|
|
162
261
|
{/if}
|
|
163
|
-
<Command.List
|
|
262
|
+
<Command.List
|
|
263
|
+
role="listbox"
|
|
264
|
+
aria-multiselectable={multiple || undefined}
|
|
265
|
+
class="svadmin-u-558f64349245 svadmin-u-92bf82f493b1 svadmin-u-eb6a3cef9686"
|
|
266
|
+
>
|
|
164
267
|
{#if select.isLoading}
|
|
165
268
|
{#each Array(3) as _, _i (_i)}
|
|
166
269
|
<div class="svadmin-u-d5eab218aa34 svadmin-u-ec0091ee009b"><Skeleton class="svadmin-u-cd0d9c512cdc svadmin-u-6da6a3c3f741" /></div>
|
|
167
270
|
{/each}
|
|
168
|
-
{:else if !
|
|
169
|
-
{#if !
|
|
271
|
+
{:else if !invalidOptions}
|
|
272
|
+
{#if !availableOptions.length}
|
|
170
273
|
<Command.Empty class="svadmin-u-cb11fec3bb46 svadmin-u-ca6bf63030aa svadmin-u-359090c2d529 svadmin-u-bfa603190748">
|
|
171
|
-
|
|
274
|
+
{i18n.t('select.noResults')}
|
|
172
275
|
</Command.Empty>
|
|
173
276
|
{/if}
|
|
174
|
-
{#each
|
|
277
|
+
{#each availableOptions as opt (`${typeof opt.value}:${opt.value}`)}
|
|
175
278
|
<Command.Item
|
|
279
|
+
disabled={select.isFetching || searchInputValue !== appliedSearch}
|
|
176
280
|
value={`${typeof opt.value}:${opt.value}`}
|
|
177
281
|
onSelect={() => handleSelect(opt.value)}
|
|
178
282
|
class="svadmin-u-d89972fe17d6 svadmin-u-60fbb7713999 svadmin-u-50ca6ba56aa3 svadmin-u-7f6912283f11 svadmin-u-3960ffc248d9 svadmin-u-36d4469299aa svadmin-u-d5eab218aa34 svadmin-u-ec0091ee009b svadmin-u-fc7473ca09eb svadmin-u-df37b1fd9495 svadmin-u-99afb1cc3b47 svadmin-u-529780e25268"
|
|
179
283
|
>
|
|
180
|
-
<Check class="svadmin-u-d2347e8497a9 svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c {
|
|
284
|
+
<Check class="svadmin-u-d2347e8497a9 svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c {selectedValues.includes(opt.value) ? 'svadmin-u-3972e98dc84f' : 'svadmin-u-7065497e1ca0'}" />
|
|
181
285
|
{opt.label}
|
|
182
286
|
</Command.Item>
|
|
183
287
|
{/each}
|
|
184
288
|
{/if}
|
|
185
289
|
</Command.List>
|
|
290
|
+
{#if hasMore}
|
|
291
|
+
<Button type="button" variant="ghost" size="sm" disabled={select.isFetching} onclick={loadMore}>
|
|
292
|
+
{i18n.t('select.loadMore')}
|
|
293
|
+
</Button>
|
|
294
|
+
{/if}
|
|
186
295
|
</Command.Root>
|
|
187
296
|
</div>
|
|
188
297
|
{/if}
|
|
@@ -2,13 +2,15 @@ import type { Filter } from '@svadmin/core';
|
|
|
2
2
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
3
|
interface Props extends Omit<HTMLButtonAttributes, 'value' | 'onchange' | 'children' | 'onclick' | 'type'> {
|
|
4
4
|
resource: string;
|
|
5
|
-
value?: string | number | null;
|
|
6
|
-
onchange?: (value: string | number | null) => void;
|
|
5
|
+
value?: string | number | null | (string | number)[];
|
|
6
|
+
onchange?: (value: string | number | null | (string | number)[]) => void;
|
|
7
7
|
optionLabel?: string;
|
|
8
8
|
optionValue?: string;
|
|
9
9
|
placeholder?: string;
|
|
10
10
|
searchable?: boolean;
|
|
11
|
+
multiple?: boolean;
|
|
11
12
|
onSearch?: (value: string) => Filter[];
|
|
13
|
+
fetchSize?: number;
|
|
12
14
|
id?: string;
|
|
13
15
|
class?: string;
|
|
14
16
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { ResourceRendering } from '../rendering/index.js';
|
|
2
3
|
import { definedOptions } from '@svadmin/core/options';
|
|
3
4
|
|
|
4
5
|
import { getResource, captureAdminContext } from '@svadmin/core';
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
|
|
13
14
|
interface Props {
|
|
14
15
|
resourceName: string;
|
|
16
|
+
rendering?: ResourceRendering | undefined;
|
|
15
17
|
title?: string;
|
|
16
18
|
density?: 'compact' | 'comfortable';
|
|
17
19
|
columns?: 1 | 2 | 3 | 4;
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
|
|
23
25
|
let {
|
|
24
26
|
resourceName,
|
|
27
|
+
rendering,
|
|
25
28
|
title,
|
|
26
29
|
density = 'comfortable',
|
|
27
30
|
columns = 1,
|
|
@@ -51,6 +54,7 @@
|
|
|
51
54
|
</PageHeader>
|
|
52
55
|
|
|
53
56
|
<AutoForm
|
|
57
|
+
{rendering}
|
|
54
58
|
{resourceName}
|
|
55
59
|
mode="create"
|
|
56
60
|
{density}
|