@svadmin/ui 0.70.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/actions.js +1 -1
- package/dist/app.css +7804 -5188
- package/dist/app.theme.css +7738 -5173
- 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.svelte.d.ts +33 -19
- package/dist/component-registry.svelte.js +6 -4
- package/dist/components/AdminApp.svelte +55 -53
- package/dist/components/AdminApp.svelte.d.ts +2 -2
- package/dist/components/ApiSettings.svelte +19 -1
- package/dist/components/AuditLogDrawer.svelte +14 -3
- package/dist/components/AutoForm.svelte +162 -50
- package/dist/components/AutoForm.svelte.d.ts +4 -0
- package/dist/components/AutoTable.svelte +599 -259
- package/dist/components/AutoTable.svelte.d.ts +6 -0
- package/dist/components/BoundRecordDetailDrawer.svelte +172 -0
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +11 -0
- package/dist/components/Breadcrumbs.svelte +7 -4
- package/dist/components/CancelTaskButton.svelte +9 -5
- package/dist/components/ColumnHeaderFilter.svelte +4 -3
- package/dist/components/ColumnSettings.svelte +1 -0
- package/dist/components/ComboboxField.svelte +118 -36
- package/dist/components/ComboboxField.svelte.d.ts +5 -4
- package/dist/components/CreatePage.svelte +7 -1
- 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/DetailDrawer.svelte +4 -0
- package/dist/components/DetailDrawer.svelte.d.ts +1 -0
- package/dist/components/DevTools.svelte +8 -21
- package/dist/components/DraggableGrid.svelte +1 -0
- package/dist/components/DraggableHeader.svelte +5 -9
- package/dist/components/DraggableHeader.svelte.d.ts +43 -18
- package/dist/components/DraggableRowTable.svelte +2 -2
- package/dist/components/DynamicFormList.svelte +17 -17
- package/dist/components/DynamicFormList.svelte.d.ts +2 -1
- package/dist/components/EditPage.svelte +7 -1
- package/dist/components/EditPage.svelte.d.ts +2 -0
- package/dist/components/EditableTable.svelte +4 -0
- package/dist/components/ErrorPage.svelte +3 -1
- package/dist/components/FieldDisplay.svelte +14 -0
- package/dist/components/FieldDisplay.svelte.d.ts +7 -0
- package/dist/components/FieldRenderer.svelte +96 -20
- package/dist/components/FileUpload.svelte +250 -0
- package/dist/components/FileUpload.svelte.d.ts +32 -0
- package/dist/components/FilterBuilder.svelte +236 -268
- package/dist/components/FilterBuilder.svelte.d.ts +3 -0
- package/dist/components/FilterDropdown.svelte.d.ts +1 -1
- package/dist/components/Header.svelte +5 -6
- package/dist/components/ImportWizard.svelte +182 -94
- package/dist/components/InfiniteList.svelte +22 -8
- package/dist/components/InfiniteList.svelte.d.ts +5 -3
- package/dist/components/InlineEdit.svelte +114 -44
- package/dist/components/JsonSchemaForm.svelte +256 -95
- package/dist/components/JsonSchemaForm.svelte.d.ts +12 -1
- package/dist/components/Layout.svelte +20 -17
- package/dist/components/LazyTaskQueueDrawer.svelte +26 -0
- package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +8 -0
- package/dist/components/ListPage.svelte +11 -6
- package/dist/components/ListPage.svelte.d.ts +2 -0
- package/dist/components/LoginPage.svelte +1 -1
- package/dist/components/MasterDetailView.svelte +3 -3
- package/dist/components/MediaLibraryModal.svelte +5 -2
- package/dist/components/MentionsInput.svelte +4 -3
- package/dist/components/MoneyInput.svelte +25 -0
- package/dist/components/MoneyInput.svelte.d.ts +20 -0
- package/dist/components/NavigateToResource.svelte +3 -2
- 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 +4 -3
- package/dist/components/ProfilePage.svelte +2 -2
- package/dist/components/QuickEditDrawer.svelte +42 -0
- package/dist/components/QuickEditDrawer.svelte.d.ts +10 -0
- package/dist/components/RecordDetailDrawer.svelte +16 -108
- package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
- package/dist/components/RecordRowActions.svelte +41 -0
- package/dist/components/RecordRowActions.svelte.d.ts +14 -0
- package/dist/components/ResourceAccessGuard.svelte +7 -5
- package/dist/components/ResourceOperationsPage.svelte +25 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
- package/dist/components/RetryTaskButton.svelte +9 -5
- package/dist/components/RowActions.svelte +5 -3
- package/dist/components/SensitiveDataMask.svelte +3 -3
- package/dist/components/SettingsPage.svelte +1 -1
- package/dist/components/ShowInferencer.svelte +4 -2
- package/dist/components/ShowInferencer.svelte.d.ts +2 -0
- package/dist/components/ShowPage.svelte +49 -39
- package/dist/components/ShowPage.svelte.d.ts +2 -0
- package/dist/components/Sidebar.svelte +15 -13
- package/dist/components/SplitPaneLayout.svelte +4 -2
- package/dist/components/SpreadsheetView.svelte +81 -286
- package/dist/components/StepsForm.svelte +166 -49
- package/dist/components/StepsForm.svelte.d.ts +1 -0
- 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/TaskDetails.svelte +20 -7
- package/dist/components/TaskList.svelte +19 -7
- package/dist/components/TaskQueueDrawer.svelte +92 -37
- package/dist/components/Toast.svelte +4 -2
- package/dist/components/TooltipButton.svelte +1 -1
- package/dist/components/TreeSelect.svelte +212 -30
- package/dist/components/TreeSelect.svelte.d.ts +3 -1
- package/dist/components/ValidatedField.svelte +27 -0
- package/dist/components/ValidatedField.svelte.d.ts +35 -0
- package/dist/components/account/ImportMembersPage.svelte +2 -2
- package/dist/components/account/SecurityLogPage.svelte +3 -1
- package/dist/components/account/SettingsEnterprisePage.svelte +7 -5
- package/dist/components/account/TeamMembersPage.svelte +1 -1
- package/dist/components/auto-table-grid.d.ts +26 -0
- package/dist/components/auto-table-grid.js +1 -0
- package/dist/components/buttons/CloneButton.svelte +6 -4
- package/dist/components/buttons/DeleteButton.svelte +95 -29
- package/dist/components/buttons/DeleteButton.svelte.d.ts +2 -0
- package/dist/components/buttons/EditButton.svelte +6 -4
- package/dist/components/buttons/ExportButton.svelte +22 -4
- package/dist/components/buttons/ImportButton.svelte +83 -38
- package/dist/components/buttons/ImportButton.svelte.d.ts +6 -10
- package/dist/components/buttons/RefreshButton.svelte +48 -8
- package/dist/components/buttons/ShowButton.svelte +6 -4
- package/dist/components/content/ApiKeyList.svelte +3 -1
- package/dist/components/content/ContentPageHeader.svelte +12 -9
- package/dist/components/content/ContentPageShell.svelte +8 -9
- package/dist/components/content/FileBrowser.svelte +35 -0
- package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
- package/dist/components/content/FileList.svelte +3 -1
- package/dist/components/content/MemberList.svelte +3 -1
- package/dist/components/content/MetricBlock.svelte +10 -13
- package/dist/components/content/NetworkTable.svelte +6 -4
- 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/SecurityEventTable.svelte +3 -1
- 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/StatusTabs.svelte +2 -2
- 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.d.ts +18 -13
- package/dist/components/fieldComponentMap.js +100 -47
- package/dist/components/fields/AvatarField.svelte +1 -1
- package/dist/components/fields/ChoiceField.svelte +16 -0
- package/dist/components/fields/ChoiceField.svelte.d.ts +10 -0
- package/dist/components/fields/CodeField.svelte +11 -12
- package/dist/components/fields/CodeField.svelte.d.ts +1 -1
- package/dist/components/fields/DateField.svelte +4 -3
- package/dist/components/fields/DateRangeField.svelte +2 -4
- package/dist/components/fields/ImageField.svelte +3 -1
- package/dist/components/fields/ImagesField.svelte +23 -0
- package/dist/components/fields/ImagesField.svelte.d.ts +6 -0
- package/dist/components/fields/JsonField.svelte +19 -13
- package/dist/components/fields/PasswordField.svelte +5 -0
- package/dist/components/fields/PasswordField.svelte.d.ts +6 -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/fields/json-value.d.ts +11 -0
- package/dist/components/fields/json-value.js +28 -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/profile/ActivityTimeline.svelte +2 -2
- package/dist/components/record-detail.svelte.d.ts +19 -0
- package/dist/components/record-detail.svelte.js +34 -0
- package/dist/components/saved-list-views.js +29 -29
- 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 +13 -0
- package/dist/components/table-contract.js +42 -0
- package/dist/components/task-utils.js +4 -2
- package/dist/components/ui/alert/alert-variants.d.ts +2 -3
- package/dist/components/ui/alert/alert-variants.js +1 -2
- package/dist/components/ui/alert/alert.svelte +4 -5
- package/dist/components/ui/alert/alert.svelte.d.ts +3 -8
- package/dist/components/ui/alert/index.js +0 -2
- package/dist/components/ui/avatar/avatar-variants.d.ts +2 -3
- package/dist/components/ui/avatar/avatar-variants.js +1 -2
- package/dist/components/ui/avatar/avatar.svelte +5 -6
- package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -8
- package/dist/components/ui/badge/badge-variants.d.ts +2 -3
- package/dist/components/ui/badge/badge-variants.js +3 -2
- package/dist/components/ui/badge/badge.svelte +4 -5
- package/dist/components/ui/badge/badge.svelte.d.ts +3 -8
- package/dist/components/ui/badge/index.js +0 -2
- package/dist/components/ui/button/button-variants.d.ts +2 -3
- package/dist/components/ui/button/button-variants.js +5 -3
- package/dist/components/ui/button/button.svelte +100 -44
- package/dist/components/ui/button/button.svelte.d.ts +8 -12
- package/dist/components/ui/button/index.js +0 -2
- package/dist/components/ui/command/command-dialog.svelte +3 -1
- package/dist/components/ui/command/command-dialog.svelte.d.ts +1 -1
- package/dist/components/ui/command/command-group.svelte +4 -2
- package/dist/components/ui/command/command-item.svelte +4 -2
- package/dist/components/ui/command/command-separator.svelte +3 -1
- package/dist/components/ui/command/index.d.ts +5 -5
- package/dist/components/ui/input/input.svelte +41 -24
- package/dist/components/ui/input/input.svelte.d.ts +5 -4
- package/dist/components/ui/sheet/sheet.svelte +9 -3
- package/dist/components/ui/sheet/sheet.svelte.d.ts +1 -0
- package/dist/components/ui/textarea/textarea.svelte +2 -1
- package/dist/components/ui/tooltip/tooltip.svelte +4 -2
- 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 +15 -1
- package/dist/index.js +9 -0
- package/dist/inline-value.d.ts +5 -0
- package/dist/inline-value.js +24 -0
- package/dist/numeric-input.d.ts +2 -0
- package/dist/numeric-input.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/types.d.ts +3 -3
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +38 -14
- package/styles-compatibility.json +12 -0
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
+
import { type Static, type TSchema } from '@sinclair/typebox';
|
|
4
|
+
import { type SafeSchema } from '@svadmin/core/schema';
|
|
5
|
+
export interface FieldDisplayProps {
|
|
6
|
+
value: unknown;
|
|
7
|
+
options?: {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string | number;
|
|
10
|
+
}[] | undefined;
|
|
11
|
+
resourceName?: string | undefined;
|
|
4
12
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
export declare const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* The component will be used by ShowPage and any other display contexts.
|
|
13
|
-
*/
|
|
14
|
-
export declare function registerDisplayComponent(fieldType: string, component: Component<any>): void;
|
|
13
|
+
export type FieldComponentMap = Readonly<Record<string, Component<FieldDisplayProps>>>;
|
|
14
|
+
/** Every dynamic renderer validates its complete projected props before mounting. */
|
|
15
|
+
export declare const builtinDisplayComponents: FieldComponentMap & Readonly<Record<FieldDefinition['type'], Component<FieldDisplayProps>>>;
|
|
16
|
+
/** Custom renderers receive only values proven by their closed schema. */
|
|
17
|
+
export declare function registerDisplayComponent<const S extends TSchema>(fieldType: string, schema: S & SafeSchema<S>, component: Component<{
|
|
18
|
+
value: Static<NoInfer<S>>;
|
|
19
|
+
}>): void;
|
|
15
20
|
/**
|
|
16
21
|
* Get the display component for a field type.
|
|
17
22
|
* Custom components take precedence over built-in ones.
|
|
18
23
|
* Returns undefined if no component is registered for the type.
|
|
19
24
|
*/
|
|
20
|
-
export declare function getDisplayComponent(fieldType: string): Component<
|
|
25
|
+
export declare function getDisplayComponent(fieldType: string): Component<FieldDisplayProps> | undefined;
|
|
21
26
|
/**
|
|
22
27
|
* Check if a field type has a display component (custom or built-in).
|
|
23
28
|
*/
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// Pre-import all field display components (tree-shaken by bundler)
|
|
1
|
+
import { Type } from '@sinclair/typebox';
|
|
2
|
+
import { closeContractSchema, createExactSchemaValidator } from '@svadmin/core/schema';
|
|
3
|
+
import { definedOptions } from '@svadmin/core/options';
|
|
4
|
+
import ValidatedField from './ValidatedField.svelte';
|
|
6
5
|
import TextField from './fields/TextField.svelte';
|
|
7
6
|
import BooleanField from './fields/BooleanField.svelte';
|
|
8
7
|
import ImageField from './fields/ImageField.svelte';
|
|
8
|
+
import ImagesField from './fields/ImagesField.svelte';
|
|
9
9
|
import TagField from './fields/TagField.svelte';
|
|
10
10
|
import DateField from './fields/DateField.svelte';
|
|
11
11
|
import DateRangeField from './fields/DateRangeField.svelte';
|
|
@@ -26,47 +26,99 @@ import AvatarField from './fields/AvatarField.svelte';
|
|
|
26
26
|
import CopyField from './fields/CopyField.svelte';
|
|
27
27
|
import FileField from './fields/FileField.svelte';
|
|
28
28
|
import MarkdownField from './fields/MarkdownField.svelte';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
29
|
+
import { jsonValueSchema } from './fields/json-value';
|
|
30
|
+
import PasswordField from './fields/PasswordField.svelte';
|
|
31
|
+
import ChoiceField from './fields/ChoiceField.svelte';
|
|
32
|
+
function validatedDisplay(schema, component, project = input => ({ value: input.value })) {
|
|
33
|
+
const validator = createExactSchemaValidator(schema);
|
|
34
|
+
const resolve = (input) => {
|
|
35
|
+
const props = project(input);
|
|
36
|
+
return validator.Check(props) ? { ok: true, props } : { ok: false };
|
|
37
|
+
};
|
|
38
|
+
// The host owns the reactive validation; evaluating here would only check mount.
|
|
39
|
+
return (internals, input) => ValidatedField(internals, { component, resolve, input });
|
|
40
|
+
}
|
|
41
|
+
const nullable = (schema) => Type.Union([schema, Type.Null(), Type.Undefined()]);
|
|
42
|
+
const text = nullable(Type.String());
|
|
43
|
+
const numeric = nullable(Type.Number());
|
|
44
|
+
const scalar = nullable(Type.Union([Type.String(), Type.Number()]));
|
|
45
|
+
const date = nullable(Type.Union([Type.String(), Type.Number(), Type.Date()]));
|
|
46
|
+
const dateProperty = Type.Optional(Type.Union([Type.String(), Type.Number(), Type.Date(), Type.Null()]));
|
|
47
|
+
const choices = Type.Optional(Type.Array(Type.Object({
|
|
48
|
+
label: Type.String(), value: Type.Union([Type.String(), Type.Number()]),
|
|
49
|
+
}, { additionalProperties: false })));
|
|
50
|
+
const props = (value) => Type.Object({ value }, { additionalProperties: false });
|
|
51
|
+
const choiceProps = (input) => definedOptions({
|
|
52
|
+
value: input.value,
|
|
53
|
+
options: input.options?.map(({ label, value }) => ({ label, value })),
|
|
54
|
+
});
|
|
55
|
+
const textDisplay = validatedDisplay(props(text), TextField);
|
|
56
|
+
const multiChoiceDisplay = validatedDisplay(Type.Object({
|
|
57
|
+
value: nullable(Type.Array(Type.Union([Type.String(), Type.Number()]))), options: choices,
|
|
58
|
+
}), MultiSelectField, choiceProps);
|
|
59
|
+
const treeChoiceDisplay = validatedDisplay(Type.Object({
|
|
60
|
+
value: nullable(Type.Union([Type.String(), Type.Number(), Type.Array(Type.Union([Type.String(), Type.Number()]))])),
|
|
61
|
+
options: choices,
|
|
62
|
+
}), ChoiceField, choiceProps);
|
|
63
|
+
const ratingDisplay = validatedDisplay(props(numeric), RatingField);
|
|
64
|
+
/** Every dynamic renderer validates its complete projected props before mounting. */
|
|
65
|
+
export const builtinDisplayComponents = Object.freeze({
|
|
66
|
+
text: textDisplay,
|
|
67
|
+
string: textDisplay,
|
|
68
|
+
boolean: validatedDisplay(props(nullable(Type.Boolean())), BooleanField),
|
|
69
|
+
image: validatedDisplay(props(text), ImageField),
|
|
70
|
+
images: validatedDisplay(props(nullable(Type.Array(Type.String()))), ImagesField),
|
|
71
|
+
tags: validatedDisplay(props(nullable(Type.Union([Type.String(), Type.Array(Type.String())]))), TagField),
|
|
72
|
+
date: validatedDisplay(props(date), DateField),
|
|
73
|
+
datetime: validatedDisplay(Type.Object({
|
|
74
|
+
value: date, format: Type.Literal('datetime'),
|
|
75
|
+
}, { additionalProperties: false }), DateField, input => ({ value: input.value, format: 'datetime' })),
|
|
76
|
+
// 原生 time 值没有日期或时区,不能交给 Date 解析。
|
|
77
|
+
time: textDisplay,
|
|
78
|
+
daterange: validatedDisplay(props(nullable(Type.Union([
|
|
79
|
+
Type.Tuple([date, date]),
|
|
80
|
+
Type.Object({ start: dateProperty, end: dateProperty, from: dateProperty, to: dateProperty }, { additionalProperties: false }),
|
|
81
|
+
]))), DateRangeField),
|
|
82
|
+
email: validatedDisplay(props(text), EmailField),
|
|
83
|
+
url: validatedDisplay(props(text), UrlField),
|
|
84
|
+
select: validatedDisplay(Type.Object({ value: scalar, options: choices }), SelectField, choiceProps),
|
|
85
|
+
multiselect: multiChoiceDisplay,
|
|
86
|
+
'tree-select': treeChoiceDisplay,
|
|
87
|
+
treeselect: treeChoiceDisplay,
|
|
88
|
+
cascader: multiChoiceDisplay,
|
|
89
|
+
transfer: multiChoiceDisplay,
|
|
90
|
+
relation: validatedDisplay(Type.Object({
|
|
91
|
+
value: scalar, resourceName: Type.Optional(Type.String()),
|
|
92
|
+
}), RelationField, input => definedOptions({ value: input.value, resourceName: input.resourceName })),
|
|
93
|
+
json: validatedDisplay(props(nullable(jsonValueSchema)), JsonField),
|
|
94
|
+
array: validatedDisplay(props(nullable(Type.Array(jsonValueSchema))), JsonField),
|
|
95
|
+
color: textDisplay,
|
|
96
|
+
password: validatedDisplay(props(text), PasswordField),
|
|
97
|
+
richtext: validatedDisplay(props(text), RichTextField),
|
|
98
|
+
textarea: validatedDisplay(props(text), RichTextField),
|
|
99
|
+
number: validatedDisplay(props(numeric), NumberField),
|
|
100
|
+
currency: validatedDisplay(props(numeric), CurrencyField),
|
|
101
|
+
phone: validatedDisplay(props(scalar), PhoneField),
|
|
102
|
+
percent: validatedDisplay(props(numeric), PercentField),
|
|
103
|
+
rating: ratingDisplay,
|
|
104
|
+
rate: ratingDisplay,
|
|
105
|
+
code: validatedDisplay(props(nullable(jsonValueSchema)), CodeField),
|
|
106
|
+
avatar: validatedDisplay(Type.Object({ src: text }), AvatarField, input => ({ src: input.value })),
|
|
107
|
+
copy: validatedDisplay(props(scalar), CopyField),
|
|
108
|
+
file: validatedDisplay(props(text), FileField),
|
|
109
|
+
markdown: validatedDisplay(props(text), MarkdownField),
|
|
110
|
+
});
|
|
63
111
|
const customDisplayComponents = new Map();
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
112
|
+
/** Custom renderers receive only values proven by their closed schema. */
|
|
113
|
+
export function registerDisplayComponent(fieldType, schema, component) {
|
|
114
|
+
if (!fieldType.trim())
|
|
115
|
+
throw new TypeError('A field type is required');
|
|
116
|
+
const validator = createExactSchemaValidator(closeContractSchema(schema));
|
|
117
|
+
const resolve = (input) => {
|
|
118
|
+
const value = input.value;
|
|
119
|
+
return validator.Check(value) ? { ok: true, props: { value } } : { ok: false };
|
|
120
|
+
};
|
|
121
|
+
customDisplayComponents.set(fieldType, (internals, input) => ValidatedField(internals, { component, resolve, input }));
|
|
70
122
|
}
|
|
71
123
|
/**
|
|
72
124
|
* Get the display component for a field type.
|
|
@@ -74,11 +126,12 @@ export function registerDisplayComponent(fieldType, component) {
|
|
|
74
126
|
* Returns undefined if no component is registered for the type.
|
|
75
127
|
*/
|
|
76
128
|
export function getDisplayComponent(fieldType) {
|
|
77
|
-
return customDisplayComponents.get(fieldType)
|
|
129
|
+
return customDisplayComponents.get(fieldType)
|
|
130
|
+
?? (Object.hasOwn(builtinDisplayComponents, fieldType) ? builtinDisplayComponents[fieldType] : undefined);
|
|
78
131
|
}
|
|
79
132
|
/**
|
|
80
133
|
* Check if a field type has a display component (custom or built-in).
|
|
81
134
|
*/
|
|
82
135
|
export function hasDisplayComponent(fieldType) {
|
|
83
|
-
return
|
|
136
|
+
return getDisplayComponent(fieldType) !== undefined;
|
|
84
137
|
}
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
|
|
62
62
|
const parts = trimmed.split(/\s+/);
|
|
63
63
|
if (parts.length >= 2) {
|
|
64
|
-
return `${
|
|
64
|
+
return `${trimmed.charAt(0)}${parts.at(-1)?.charAt(0) ?? ''}`.toUpperCase();
|
|
65
65
|
}
|
|
66
66
|
return trimmed.slice(0, 2).toUpperCase();
|
|
67
67
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { definedOptions } from '@svadmin/core/options';
|
|
3
|
+
import SelectField from './SelectField.svelte';
|
|
4
|
+
import MultiSelectField from './MultiSelectField.svelte';
|
|
5
|
+
|
|
6
|
+
let { value, options }: {
|
|
7
|
+
value: string | number | (string | number)[] | null | undefined;
|
|
8
|
+
options?: { label: string; value: string | number }[];
|
|
9
|
+
} = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if Array.isArray(value)}
|
|
13
|
+
<MultiSelectField {value} {...definedOptions({ options })} />
|
|
14
|
+
{:else}
|
|
15
|
+
<SelectField {value} {...definedOptions({ options })} />
|
|
16
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
value: string | number | (string | number)[] | null | undefined;
|
|
3
|
+
options?: {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string | number;
|
|
6
|
+
}[];
|
|
7
|
+
};
|
|
8
|
+
declare const ChoiceField: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type ChoiceField = ReturnType<typeof ChoiceField>;
|
|
10
|
+
export default ChoiceField;
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import { Copy, Check } from '@lucide/svelte';
|
|
4
4
|
import { Badge } from '../ui/badge/index.js';
|
|
5
5
|
import { cn } from '../../utils.js';
|
|
6
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
7
|
+
import { formatJsonValue } from './json-value';
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
8
|
-
value?: string | number | Record<string, unknown> | unknown[] | null | undefined;
|
|
10
|
+
value?: string | number | boolean | Record<string, unknown> | unknown[] | null | undefined;
|
|
9
11
|
language?: string;
|
|
10
12
|
copyable?: boolean;
|
|
11
13
|
title?: string;
|
|
@@ -29,22 +31,17 @@
|
|
|
29
31
|
let copied = $state(false);
|
|
30
32
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
31
33
|
let destroyed = false;
|
|
34
|
+
const i18n = useTranslation();
|
|
32
35
|
|
|
33
36
|
onDestroy(() => {
|
|
34
37
|
destroyed = true;
|
|
35
38
|
if (timeoutId) clearTimeout(timeoutId);
|
|
36
39
|
});
|
|
37
40
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
return JSON.stringify(value, null, 2);
|
|
44
|
-
} catch {
|
|
45
|
-
return String(value);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
41
|
+
const display = $derived(formatJsonValue(value));
|
|
42
|
+
const formattedCode = $derived(display.status === 'valid'
|
|
43
|
+
? typeof value === 'string' ? value : display.formatted
|
|
44
|
+
: '');
|
|
48
45
|
|
|
49
46
|
async function handleCopy(event: MouseEvent) {
|
|
50
47
|
event.stopPropagation();
|
|
@@ -69,7 +66,9 @@
|
|
|
69
66
|
}
|
|
70
67
|
</script>
|
|
71
68
|
|
|
72
|
-
{#if
|
|
69
|
+
{#if display.status === 'invalid'}
|
|
70
|
+
<span role="status" data-svadmin-invalid-field>{i18n.t('validation.invalidFormat')}</span>
|
|
71
|
+
{:else if !formattedCode}
|
|
73
72
|
<span class={cn('field-code svadmin-u-bfa603190748 svadmin-u-fc7473ca09eb', className)}>{nullLabel}</span>
|
|
74
73
|
{:else}
|
|
75
74
|
<div class={cn('field-code svadmin-u-d89972fe17d6 group svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-c9ed8c5f79ae svadmin-u-b00f43c30c2b svadmin-u-359090c2d529 svadmin-u-0e65706bcccd', className)}>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script lang="ts">
|
|
6
|
+
import { dateFieldValue } from './date-field-value.js';
|
|
6
7
|
import { cn } from '../../utils.js';
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
|
|
46
47
|
const formatted = $derived.by(() => {
|
|
47
48
|
if (value == null || value === '') return nullLabel;
|
|
48
|
-
const d = value
|
|
49
|
+
const d = dateFieldValue(value, format === 'time');
|
|
49
50
|
if (isNaN(d.getTime())) return nullLabel;
|
|
50
51
|
|
|
51
52
|
if (format === 'iso') return d.toISOString();
|
|
@@ -68,8 +69,8 @@
|
|
|
68
69
|
|
|
69
70
|
const fullIsoTitle = $derived.by(() => {
|
|
70
71
|
if (value == null || value === '') return undefined;
|
|
71
|
-
const d = value
|
|
72
|
-
return isNaN(d.getTime()) ? undefined : d.toISOString();
|
|
72
|
+
const d = dateFieldValue(value, format === 'time');
|
|
73
|
+
return isNaN(d.getTime()) ? undefined : format === 'time' && typeof value === 'string' && /^\d{2}:/u.test(value) ? value : d.toISOString();
|
|
73
74
|
});
|
|
74
75
|
</script>
|
|
75
76
|
|
|
@@ -41,8 +41,7 @@
|
|
|
41
41
|
if (startDate !== undefined) return startDate;
|
|
42
42
|
if (Array.isArray(value)) return value[0];
|
|
43
43
|
if (value && typeof value === 'object') {
|
|
44
|
-
|
|
45
|
-
return (obj.start ?? obj.from) as string | number | Date | null | undefined;
|
|
44
|
+
return value.start ?? value.from;
|
|
46
45
|
}
|
|
47
46
|
return undefined;
|
|
48
47
|
});
|
|
@@ -51,8 +50,7 @@
|
|
|
51
50
|
if (endDate !== undefined) return endDate;
|
|
52
51
|
if (Array.isArray(value)) return value[1];
|
|
53
52
|
if (value && typeof value === 'object') {
|
|
54
|
-
|
|
55
|
-
return (obj.end ?? obj.to) as string | number | Date | null | undefined;
|
|
53
|
+
return value.end ?? value.to;
|
|
56
54
|
}
|
|
57
55
|
return undefined;
|
|
58
56
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { definedOptions } from '@svadmin/core/options';
|
|
3
|
+
|
|
2
4
|
import MediaThumbnail from '../content/MediaThumbnail.svelte';
|
|
3
5
|
|
|
4
6
|
interface Props {
|
|
@@ -17,7 +19,7 @@
|
|
|
17
19
|
|
|
18
20
|
{#if value}
|
|
19
21
|
<div style={`width: ${width}px; height: ${height}px;`} class="svadmin-u-bb0c4bfc52bd svadmin-u-012fbd121f37">
|
|
20
|
-
<MediaThumbnail src={value} {alt} {title} size="full" fit="cover" showOverlay={previewable} class={className} />
|
|
22
|
+
<MediaThumbnail src={value} {alt} {...definedOptions({ "title": title })} size="full" fit="cover" showOverlay={previewable} class={className} />
|
|
21
23
|
</div>
|
|
22
24
|
{:else}
|
|
23
25
|
<MediaThumbnail src={null} {emptyLabel} class={className} />
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ImageField from './ImageField.svelte';
|
|
3
|
+
|
|
4
|
+
let { value }: { value: string[] | null | undefined } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
{#if value?.length}
|
|
8
|
+
<div class="field-images">
|
|
9
|
+
{#each value as image, index (index)}
|
|
10
|
+
<ImageField value={image} />
|
|
11
|
+
{/each}
|
|
12
|
+
</div>
|
|
13
|
+
{:else}
|
|
14
|
+
<ImageField value={null} />
|
|
15
|
+
{/if}
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.field-images {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-wrap: wrap;
|
|
21
|
+
gap: 8px;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
3
|
import { Button } from '../ui/button/index.js';
|
|
4
4
|
import { Copy, Check, ChevronDown, ChevronRight } from '@lucide/svelte';
|
|
5
|
+
import { formatJsonValue } from './json-value';
|
|
5
6
|
|
|
6
7
|
const i18n = useTranslation();
|
|
7
8
|
|
|
@@ -12,29 +13,34 @@
|
|
|
12
13
|
let expanded = $state(false);
|
|
13
14
|
let copied = $state(false);
|
|
14
15
|
let copyTimer: ReturnType<typeof setTimeout> | undefined;
|
|
16
|
+
let destroyed = false;
|
|
15
17
|
|
|
16
18
|
$effect(() => {
|
|
17
|
-
return () => { if (copyTimer) clearTimeout(copyTimer); };
|
|
19
|
+
return () => { destroyed = true; if (copyTimer) clearTimeout(copyTimer); };
|
|
18
20
|
});
|
|
19
21
|
|
|
20
|
-
const
|
|
21
|
-
value != null ? JSON.stringify(value, null, 2) : '—'
|
|
22
|
-
);
|
|
22
|
+
const display = $derived(formatJsonValue(value));
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
async function copyJson() {
|
|
25
|
+
if (display.status !== 'valid') return;
|
|
26
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
27
|
+
if (!clipboard?.writeText) return;
|
|
28
|
+
try {
|
|
29
|
+
await clipboard.writeText(display.formatted);
|
|
30
|
+
} catch {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (destroyed) return;
|
|
30
34
|
copied = true;
|
|
31
35
|
if (copyTimer) clearTimeout(copyTimer);
|
|
32
36
|
copyTimer = setTimeout(() => { copied = false; }, 2000);
|
|
33
37
|
}
|
|
34
38
|
</script>
|
|
35
39
|
|
|
36
|
-
{#if
|
|
40
|
+
{#if display.status === 'empty'}
|
|
37
41
|
<span class="svadmin-u-bfa603190748">—</span>
|
|
42
|
+
{:else if display.status === 'invalid'}
|
|
43
|
+
<span role="status" data-svadmin-invalid-field>{i18n.t('validation.invalidFormat')}</span>
|
|
38
44
|
{:else}
|
|
39
45
|
<div class="svadmin-u-da7c36cd8867">
|
|
40
46
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">
|
|
@@ -66,9 +72,9 @@
|
|
|
66
72
|
</Button>
|
|
67
73
|
</div>
|
|
68
74
|
{#if expanded}
|
|
69
|
-
<pre class="svadmin-u-5f22e64f2282 svadmin-u-2ef11f1cb219 svadmin-u-eb6e8b881acd svadmin-u-359090c2d529 svadmin-u-73fc3fb18ceb svadmin-u-8aee2b07b47d svadmin-u-0e65706bcccd">{formatted}</pre>
|
|
75
|
+
<pre class="svadmin-u-5f22e64f2282 svadmin-u-2ef11f1cb219 svadmin-u-eb6e8b881acd svadmin-u-359090c2d529 svadmin-u-73fc3fb18ceb svadmin-u-8aee2b07b47d svadmin-u-0e65706bcccd">{display.formatted}</pre>
|
|
70
76
|
{:else}
|
|
71
|
-
<code class="svadmin-u-359090c2d529 svadmin-u-0e65706bcccd svadmin-u-2ef11f1cb219 svadmin-u-45d828117213 svadmin-u-465609a240a8 svadmin-u-07389a777c1f">{preview}</code>
|
|
77
|
+
<code class="svadmin-u-359090c2d529 svadmin-u-0e65706bcccd svadmin-u-2ef11f1cb219 svadmin-u-45d828117213 svadmin-u-465609a240a8 svadmin-u-07389a777c1f">{display.preview}</code>
|
|
72
78
|
{/if}
|
|
73
79
|
</div>
|
|
74
80
|
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 原生 time 输入没有日期/时区;使用本地锚点格式化,不能按 ISO 时间戳解析。 */
|
|
2
|
+
export function dateFieldValue(value, timeOnly) {
|
|
3
|
+
if (timeOnly && typeof value === 'string') {
|
|
4
|
+
const match = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/u.exec(value);
|
|
5
|
+
if (match) {
|
|
6
|
+
const hour = Number(match[1]), minute = Number(match[2]), second = Number(match[3] ?? 0);
|
|
7
|
+
if (hour > 23 || minute > 59 || second > 59)
|
|
8
|
+
return new Date(NaN);
|
|
9
|
+
return new Date(1970, 0, 1, hour, minute, second, Number((match[4] ?? '').padEnd(3, '0')));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return value instanceof Date ? value : new Date(value);
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const jsonValueSchema: import("@sinclair/typebox").TRecursive<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TNull, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TString, import("@sinclair/typebox").TArray<import("@sinclair/typebox").TThis>, import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TThis>]>>;
|
|
2
|
+
export type JsonDisplay = {
|
|
3
|
+
status: 'empty';
|
|
4
|
+
} | {
|
|
5
|
+
status: 'invalid';
|
|
6
|
+
} | {
|
|
7
|
+
status: 'valid';
|
|
8
|
+
formatted: string;
|
|
9
|
+
preview: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function formatJsonValue(value: unknown): JsonDisplay;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Type } from '@sinclair/typebox';
|
|
2
|
+
import { createExactSchemaValidator } from '@svadmin/core/schema';
|
|
3
|
+
export const jsonValueSchema = Type.Recursive(Self => Type.Union([
|
|
4
|
+
Type.Null(), Type.Boolean(), Type.Number(), Type.String(),
|
|
5
|
+
Type.Array(Self), Type.Record(Type.String(), Self),
|
|
6
|
+
]));
|
|
7
|
+
const validator = createExactSchemaValidator(jsonValueSchema);
|
|
8
|
+
export function formatJsonValue(value) {
|
|
9
|
+
if (value == null)
|
|
10
|
+
return { status: 'empty' };
|
|
11
|
+
try {
|
|
12
|
+
// Serialization rejects circular graphs before recursive schema traversal.
|
|
13
|
+
const compact = JSON.stringify(value);
|
|
14
|
+
if (typeof compact !== 'string' || !validator.Check(value))
|
|
15
|
+
return { status: 'invalid' };
|
|
16
|
+
const formatted = JSON.stringify(value, null, 2);
|
|
17
|
+
if (typeof formatted !== 'string')
|
|
18
|
+
return { status: 'invalid' };
|
|
19
|
+
return {
|
|
20
|
+
status: 'valid',
|
|
21
|
+
formatted,
|
|
22
|
+
preview: compact.slice(0, 80) + (compact.length > 80 ? '...' : ''),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { status: 'invalid' };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** 嵌套表单的草稿与传输语义;不是替代服务端的 JSON Schema 校验器。 */
|
|
2
|
+
export interface JsonSchemaFormSchema {
|
|
3
|
+
type?: string | string[];
|
|
4
|
+
const?: string | number | boolean | null;
|
|
5
|
+
readOnly?: boolean;
|
|
6
|
+
minimum?: number;
|
|
7
|
+
maximum?: number;
|
|
8
|
+
exclusiveMinimum?: number;
|
|
9
|
+
exclusiveMaximum?: number;
|
|
10
|
+
multipleOf?: number;
|
|
11
|
+
minLength?: number;
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
minItems?: number;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
additionalProperties?: boolean;
|
|
16
|
+
title?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
properties?: Record<string, JsonSchemaFormSchema>;
|
|
19
|
+
items?: JsonSchemaFormSchema;
|
|
20
|
+
enum?: Array<string | number | boolean | null>;
|
|
21
|
+
default?: unknown;
|
|
22
|
+
required?: string[];
|
|
23
|
+
}
|
|
24
|
+
export declare const SCHEMA_FORM_LIMITS: Readonly<{
|
|
25
|
+
depth: 32;
|
|
26
|
+
nodes: 10000;
|
|
27
|
+
characters: 1048576;
|
|
28
|
+
}>;
|
|
29
|
+
/** Svelte 代理也通过普通数据属性读取;回调永远收不到活跃草稿的引用。 */
|
|
30
|
+
export declare function schemaFormSnapshot(value: unknown): Record<string, unknown>;
|
|
31
|
+
/** 默认值只填“缺失的键”;显式 undefined/null/false/0/空串都表示调用方的决定。 */
|
|
32
|
+
export declare function initializeSchemaForm(schema: JsonSchemaFormSchema, value: Record<string, unknown>): Record<string, unknown>;
|
|
33
|
+
export declare function schemaFormArrayItem(schema: JsonSchemaFormSchema): unknown;
|
|
34
|
+
export declare function writeSchemaFormPath(value: Record<string, unknown>, path: readonly string[], nextValue: unknown): Record<string, unknown>;
|
|
35
|
+
/** option.value 是索引,不是 String(value):1 与 "1"、null 与 "null" 必须可区分。 */
|
|
36
|
+
export declare function schemaFormEnumIndex(choices: readonly unknown[], value: unknown): string;
|
|
37
|
+
export declare function schemaFormEnumValue(choices: readonly unknown[], index: string): unknown;
|