@svadmin/ui 0.73.0 → 0.75.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 +53 -28
- package/dist/app.css +3733 -4119
- package/dist/app.theme.css +3733 -4119
- 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 +24 -15
- 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 +33 -3
- package/dist/components/AutoForm.svelte.d.ts +1 -0
- package/dist/components/AutoTable.svelte +610 -47
- package/dist/components/AutoTable.svelte.d.ts +17 -1
- package/dist/components/BoundRecordDetailDrawer.svelte +9 -0
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +2 -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 +114 -27
- package/dist/components/ComboboxField.svelte.d.ts +1 -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 +85 -5
- package/dist/components/DateRangeInput.svelte.d.ts +10 -0
- package/dist/components/DateRangePicker.svelte +10 -0
- package/dist/components/DateRangePicker.svelte.d.ts +6 -0
- package/dist/components/DateTimeInput.svelte +85 -16
- package/dist/components/DateTimeInput.svelte.d.ts +19 -11
- package/dist/components/DateTimePicker.svelte +10 -0
- package/dist/components/DateTimePicker.svelte.d.ts +6 -0
- package/dist/components/DevTools.svelte +34 -26
- package/dist/components/DevframePanel.svelte +123 -0
- package/dist/components/DevframePanel.svelte.d.ts +3 -0
- package/dist/components/ErrorSummary.svelte +52 -0
- package/dist/components/ErrorSummary.svelte.d.ts +14 -0
- package/dist/components/FieldRenderer.svelte +82 -81
- package/dist/components/FileUpload.svelte +214 -52
- package/dist/components/FileUpload.svelte.d.ts +11 -0
- package/dist/components/FilterBuilder.svelte +88 -66
- 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 +339 -17
- package/dist/components/ImportWizard.svelte.d.ts +11 -0
- package/dist/components/JsonSchemaForm.svelte +120 -52
- package/dist/components/JsonSchemaForm.svelte.d.ts +7 -1
- package/dist/components/KanbanBoard.svelte +195 -40
- package/dist/components/KanbanBoard.svelte.d.ts +9 -2
- package/dist/components/Layout.svelte +4 -2
- 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/LazyPage.svelte +3 -3
- package/dist/components/LazyPage.svelte.d.ts +2 -2
- 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/ListPage.svelte +5 -1
- package/dist/components/ListPage.svelte.d.ts +3 -0
- package/dist/components/LoginPage.svelte +1 -1
- 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/PasswordInput.svelte +3 -3
- package/dist/components/PasswordInput.svelte.d.ts +2 -1
- 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/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 +4 -2
- package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
- package/dist/components/RelationPicker.svelte +341 -0
- package/dist/components/RelationPicker.svelte.d.ts +26 -0
- package/dist/components/ResourceOperationsPage.svelte +23 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +2 -2
- 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/ShowPage.svelte +18 -3
- package/dist/components/ShowPage.svelte.d.ts +3 -0
- package/dist/components/Sidebar.svelte +2 -2
- package/dist/components/Slider.svelte +100 -0
- package/dist/components/Slider.svelte.d.ts +19 -0
- package/dist/components/SpreadsheetView.svelte +1213 -95
- package/dist/components/SpreadsheetView.svelte.d.ts +19 -0
- package/dist/components/TagsInput.svelte +178 -0
- package/dist/components/TagsInput.svelte.d.ts +17 -0
- package/dist/components/TimePicker.svelte +10 -0
- package/dist/components/TimePicker.svelte.d.ts +6 -0
- package/dist/components/TooltipButton.svelte +3 -4
- package/dist/components/TreeSelect.svelte +267 -53
- package/dist/components/TreeSelect.svelte.d.ts +3 -0
- 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/buttons/ExportButton.svelte +56 -12
- package/dist/components/buttons/ExportButton.svelte.d.ts +11 -0
- package/dist/components/content/ContentPageHeader.svelte +1 -1
- package/dist/components/content/ContentPageShell.svelte +1 -1
- package/dist/components/content/MetricBlock.svelte +1 -1
- package/dist/components/content/PageToolbar.svelte +1 -1
- package/dist/components/content/ReferenceNotice.svelte +5 -0
- package/dist/components/content/ReferenceNotice.svelte.d.ts +18 -0
- package/dist/components/content/SectionHeader.svelte +1 -1
- package/dist/components/content/SettingsFieldRow.svelte +1 -1
- package/dist/components/content/SettingsGroup.svelte +1 -1
- package/dist/components/content/StatusBadge.svelte +1 -1
- package/dist/components/content/WorkspaceLayout.svelte +1 -1
- package/dist/components/export-reference.d.ts +2 -0
- package/dist/components/export-reference.js +9 -0
- package/dist/components/fieldComponentMap.js +2 -5
- package/dist/components/fields/DateField.svelte +12 -13
- package/dist/components/fields/MarkdownField.svelte +14 -5
- package/dist/components/fields/date-display.d.ts +6 -0
- package/dist/components/fields/date-display.js +24 -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/saved-list-views.d.ts +74 -1
- package/dist/components/saved-list-views.js +191 -3
- 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 -3
- 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 -5
- package/dist/components/ui/checkbox/checkbox.svelte +5 -1
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +5 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +1 -2
- package/dist/components/ui/input/input.svelte +7 -2
- 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 -2
- package/dist/components.css +33 -2
- package/dist/date-input-policy.d.ts +4 -0
- package/dist/date-input-policy.js +35 -0
- package/dist/design-system-components.d.ts +100 -0
- package/dist/design-system-components.js +101 -0
- package/dist/design-system.js +1 -1
- package/dist/devtools-bridge.d.ts +80 -0
- package/dist/devtools-bridge.js +92 -0
- package/dist/editor-config.svelte.d.ts +4 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +23 -2
- package/dist/recipes.d.ts +960 -4
- package/dist/recipes.js +264 -4
- package/dist/tree-table-model.d.ts +24 -0
- package/dist/tree-table-model.js +111 -0
- package/dist/types.d.ts +4 -4
- package/package.json +22 -10
- package/dist/styled-system/css/conditions.js +0 -36
- package/dist/styled-system/css/css.d.ts +0 -22
- package/dist/styled-system/css/css.js +0 -45
- package/dist/styled-system/css/cva.d.ts +0 -6
- package/dist/styled-system/css/cva.js +0 -87
- package/dist/styled-system/css/cx.d.ts +0 -5
- package/dist/styled-system/css/cx.js +0 -15
- package/dist/styled-system/css/index.d.ts +0 -5
- package/dist/styled-system/css/index.js +0 -4
- package/dist/styled-system/css/sva.d.ts +0 -4
- package/dist/styled-system/css/sva.js +0 -46
- package/dist/styled-system/helpers.js +0 -316
- package/dist/styled-system/patterns/aspect-ratio.d.ts +0 -20
- package/dist/styled-system/patterns/aspect-ratio.js +0 -38
- package/dist/styled-system/patterns/bleed.d.ts +0 -21
- package/dist/styled-system/patterns/bleed.js +0 -24
- package/dist/styled-system/patterns/box.d.ts +0 -20
- package/dist/styled-system/patterns/box.js +0 -15
- package/dist/styled-system/patterns/center.d.ts +0 -20
- package/dist/styled-system/patterns/center.js +0 -21
- package/dist/styled-system/patterns/circle.d.ts +0 -20
- package/dist/styled-system/patterns/circle.js +0 -25
- package/dist/styled-system/patterns/container.d.ts +0 -20
- package/dist/styled-system/patterns/container.js +0 -21
- package/dist/styled-system/patterns/cq.d.ts +0 -21
- package/dist/styled-system/patterns/cq.js +0 -21
- package/dist/styled-system/patterns/divider.d.ts +0 -22
- package/dist/styled-system/patterns/divider.js +0 -25
- package/dist/styled-system/patterns/flex.d.ts +0 -26
- package/dist/styled-system/patterns/flex.js +0 -26
- package/dist/styled-system/patterns/float.d.ts +0 -23
- package/dist/styled-system/patterns/float.js +0 -52
- package/dist/styled-system/patterns/grid-item.d.ts +0 -25
- package/dist/styled-system/patterns/grid-item.js +0 -25
- package/dist/styled-system/patterns/grid.d.ts +0 -24
- package/dist/styled-system/patterns/grid.js +0 -27
- package/dist/styled-system/patterns/hstack.d.ts +0 -21
- package/dist/styled-system/patterns/hstack.js +0 -24
- package/dist/styled-system/patterns/index.d.ts +0 -21
- package/dist/styled-system/patterns/index.js +0 -20
- package/dist/styled-system/patterns/link-overlay.d.ts +0 -20
- package/dist/styled-system/patterns/link-overlay.js +0 -24
- package/dist/styled-system/patterns/spacer.d.ts +0 -20
- package/dist/styled-system/patterns/spacer.js +0 -25
- package/dist/styled-system/patterns/square.d.ts +0 -20
- package/dist/styled-system/patterns/square.js +0 -24
- package/dist/styled-system/patterns/stack.d.ts +0 -23
- package/dist/styled-system/patterns/stack.js +0 -24
- package/dist/styled-system/patterns/visually-hidden.d.ts +0 -20
- package/dist/styled-system/patterns/visually-hidden.js +0 -18
- package/dist/styled-system/patterns/vstack.d.ts +0 -21
- package/dist/styled-system/patterns/vstack.js +0 -24
- package/dist/styled-system/patterns/wrap.d.ts +0 -24
- package/dist/styled-system/patterns/wrap.js +0 -25
- package/dist/styled-system/recipes/content-header.d.ts +0 -31
- package/dist/styled-system/recipes/content-header.js +0 -65
- package/dist/styled-system/recipes/content-page.d.ts +0 -34
- package/dist/styled-system/recipes/content-page.js +0 -43
- package/dist/styled-system/recipes/create-recipe.js +0 -82
- package/dist/styled-system/recipes/index.d.ts +0 -17
- package/dist/styled-system/recipes/index.js +0 -16
- package/dist/styled-system/recipes/metric-block.d.ts +0 -34
- package/dist/styled-system/recipes/metric-block.js +0 -76
- package/dist/styled-system/recipes/product-list.d.ts +0 -31
- package/dist/styled-system/recipes/product-list.js +0 -73
- package/dist/styled-system/recipes/product-section.d.ts +0 -31
- package/dist/styled-system/recipes/product-section.js +0 -49
- package/dist/styled-system/recipes/product-settings-row.d.ts +0 -34
- package/dist/styled-system/recipes/product-settings-row.js +0 -58
- package/dist/styled-system/recipes/product-settings.d.ts +0 -31
- package/dist/styled-system/recipes/product-settings.js +0 -57
- package/dist/styled-system/recipes/product-status.d.ts +0 -34
- package/dist/styled-system/recipes/product-status.js +0 -45
- package/dist/styled-system/recipes/product-toolbar.d.ts +0 -31
- package/dist/styled-system/recipes/product-toolbar.js +0 -41
- package/dist/styled-system/recipes/product-workspace.d.ts +0 -34
- package/dist/styled-system/recipes/product-workspace.js +0 -58
- package/dist/styled-system/recipes/surface-metric.d.ts +0 -38
- package/dist/styled-system/recipes/surface-metric.js +0 -63
- package/dist/styled-system/recipes/surface-table.d.ts +0 -34
- package/dist/styled-system/recipes/surface-table.js +0 -62
- package/dist/styled-system/recipes/ui-badge.d.ts +0 -31
- package/dist/styled-system/recipes/ui-badge.js +0 -38
- package/dist/styled-system/recipes/ui-button.d.ts +0 -32
- package/dist/styled-system/recipes/ui-button.js +0 -43
- package/dist/styled-system/recipes/ui-input.d.ts +0 -31
- package/dist/styled-system/recipes/ui-input.js +0 -49
- package/dist/styled-system/recipes/ui-textarea.d.ts +0 -31
- package/dist/styled-system/recipes/ui-textarea.js +0 -24
- package/dist/styled-system/styles.css +0 -1257
- package/dist/styled-system/tokens/index.d.ts +0 -9
- package/dist/styled-system/tokens/index.js +0 -268
- package/dist/styled-system/tokens/tokens.d.ts +0 -36
- package/dist/styled-system/types/composition.d.ts +0 -227
- package/dist/styled-system/types/conditions.d.ts +0 -236
- package/dist/styled-system/types/csstype.d.ts +0 -22570
- package/dist/styled-system/types/index.d.ts +0 -6
- package/dist/styled-system/types/parts.d.ts +0 -8
- package/dist/styled-system/types/pattern.d.ts +0 -78
- package/dist/styled-system/types/prop-type.d.ts +0 -223
- package/dist/styled-system/types/recipe.d.ts +0 -181
- package/dist/styled-system/types/selectors.d.ts +0 -59
- package/dist/styled-system/types/static-css.d.ts +0 -56
- package/dist/styled-system/types/style-props.d.ts +0 -8088
- package/dist/styled-system/types/system-types.d.ts +0 -151
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Button } from './ui/button/index.js';
|
|
3
3
|
import { Badge } from './ui/badge/index.js';
|
|
4
|
-
import { Plus, GripVertical } from '@lucide/svelte';
|
|
4
|
+
import { Plus, GripVertical, RotateCw, ArrowUp, ArrowDown } from '@lucide/svelte';
|
|
5
5
|
import { cn } from '../utils.js';
|
|
6
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
7
|
+
import { onDestroy } from 'svelte';
|
|
6
8
|
|
|
7
9
|
export interface KanbanCard {
|
|
8
10
|
id: string;
|
|
@@ -25,9 +27,16 @@
|
|
|
25
27
|
columns: KanbanColumn[];
|
|
26
28
|
cards?: KanbanCard[];
|
|
27
29
|
allowAddCard?: boolean;
|
|
28
|
-
oncardmove?: (cardId: string, targetColumnId: string) => void
|
|
30
|
+
oncardmove?: (cardId: string, targetColumnId: string, targetIndex: number) => void | Promise<void>;
|
|
31
|
+
canMoveCard?: (card: KanbanCard, targetColumnId: string) => boolean;
|
|
32
|
+
oncardmoveerror?: (error: unknown) => void;
|
|
29
33
|
oncardclick?: (card: KanbanCard) => void;
|
|
30
|
-
oncardadd?: (columnId: string, title: string) =>
|
|
34
|
+
oncardadd?: (columnId: string, title: string) => KanbanCard | Promise<KanbanCard>;
|
|
35
|
+
scopeKey?: string | number;
|
|
36
|
+
loading?: boolean;
|
|
37
|
+
error?: string | undefined;
|
|
38
|
+
onRetry?: () => void;
|
|
39
|
+
ariaLabel?: string;
|
|
31
40
|
class?: string;
|
|
32
41
|
}
|
|
33
42
|
|
|
@@ -36,16 +45,80 @@
|
|
|
36
45
|
cards = $bindable([]),
|
|
37
46
|
allowAddCard = true,
|
|
38
47
|
oncardmove,
|
|
48
|
+
canMoveCard,
|
|
49
|
+
oncardmoveerror,
|
|
39
50
|
oncardclick,
|
|
40
51
|
oncardadd,
|
|
52
|
+
scopeKey,
|
|
53
|
+
loading = false,
|
|
54
|
+
error,
|
|
55
|
+
onRetry,
|
|
56
|
+
ariaLabel,
|
|
41
57
|
class: className = '',
|
|
42
58
|
}: Props = $props();
|
|
43
59
|
|
|
44
60
|
let draggedCardId = $state<string | null>(null);
|
|
45
61
|
let addingColumnId = $state<string | null>(null);
|
|
46
62
|
let newCardTitle = $state('');
|
|
63
|
+
let movingCardId = $state<string | null>(null);
|
|
64
|
+
let moveError = $state<string | null>(null);
|
|
65
|
+
let adding = $state(false);
|
|
66
|
+
let mounted = true;
|
|
67
|
+
const i18n = useTranslation();
|
|
68
|
+
const invalidData = $derived.by(() => {
|
|
69
|
+
if (!Array.isArray(columns) || !Array.isArray(cards)) return 'kanban.invalidData';
|
|
70
|
+
if (columns.length > 200 || cards.length > 1000) return 'kanban.limit';
|
|
71
|
+
if (columns.some(column => !column || !validText(column.id) || !validText(column.title))) return 'kanban.invalidData';
|
|
72
|
+
const columnIds = new Set(columns.map(column => column.id));
|
|
73
|
+
if (columnIds.size !== columns.length) return 'kanban.invalidData';
|
|
74
|
+
const cardIds = new Set<string>();
|
|
75
|
+
for (const card of cards) {
|
|
76
|
+
if (!validCard(card) || cardIds.has(card.id) || !columnIds.has(card.columnId)) return 'kanban.invalidData';
|
|
77
|
+
cardIds.add(card.id);
|
|
78
|
+
}
|
|
79
|
+
return '';
|
|
80
|
+
});
|
|
81
|
+
const displayError = $derived(error || (invalidData ? i18n.t(invalidData) : ''));
|
|
82
|
+
const fingerprint = $derived(invalidData ? '' : JSON.stringify([columns.map(column => ({ id: column.id, title: column.title })), cards.map(card => ({
|
|
83
|
+
id: card.id, title: card.title, columnId: card.columnId, description: card.description,
|
|
84
|
+
priority: card.priority, tags: card.tags, assignee: card.assignee?.name, dueDate: card.dueDate,
|
|
85
|
+
}))]));
|
|
86
|
+
const scope = $derived({ scopeKey, cards, columns, fingerprint, loading, error, oncardmove, oncardadd, canMoveCard, allowAddCard });
|
|
87
|
+
let operation = $state.raw<{ scope: typeof scope; preview?: KanbanCard[] }>();
|
|
88
|
+
const currentOperation = $derived(operation?.scope === scope);
|
|
89
|
+
const busy = $derived(currentOperation && (movingCardId !== null || adding));
|
|
90
|
+
const visibleCards = $derived(currentOperation && operation?.preview ? operation.preview : cards);
|
|
91
|
+
|
|
92
|
+
function validText(value: unknown): value is string {
|
|
93
|
+
return typeof value === 'string' && value.trim().length > 0 && value.length <= 1000;
|
|
94
|
+
}
|
|
95
|
+
function validCard(card: KanbanCard): boolean {
|
|
96
|
+
return !!card && validText(card.id) && validText(card.title) && validText(card.columnId)
|
|
97
|
+
&& (card.description === undefined || (typeof card.description === 'string' && card.description.length <= 10_000))
|
|
98
|
+
&& (card.tags === undefined || (Array.isArray(card.tags) && card.tags.length <= 100 && card.tags.every(validText)))
|
|
99
|
+
&& (card.assignee === undefined || (!!card.assignee && validText(card.assignee.name)))
|
|
100
|
+
&& (card.dueDate === undefined || typeof card.dueDate === 'string')
|
|
101
|
+
&& (card.priority === undefined || ['low', 'medium', 'high', 'urgent'].includes(card.priority));
|
|
102
|
+
}
|
|
103
|
+
function moveAllowed(card: KanbanCard, targetColumn: string): boolean {
|
|
104
|
+
if (!oncardmove || loading || displayError || busy || !columns.some(column => column.id === targetColumn)) return false;
|
|
105
|
+
try { return canMoveCard === undefined || canMoveCard(card, targetColumn) === true; }
|
|
106
|
+
catch { return false; }
|
|
107
|
+
}
|
|
108
|
+
function active(origin: typeof scope): boolean {
|
|
109
|
+
return mounted && origin === scope;
|
|
110
|
+
}
|
|
111
|
+
$effect.pre(() => {
|
|
112
|
+
void scope;
|
|
113
|
+
draggedCardId = null;
|
|
114
|
+
addingColumnId = null;
|
|
115
|
+
newCardTitle = '';
|
|
116
|
+
moveError = null;
|
|
117
|
+
});
|
|
118
|
+
onDestroy(() => { mounted = false; });
|
|
47
119
|
|
|
48
120
|
function handleDragStart(e: DragEvent, cardId: string) {
|
|
121
|
+
if (!oncardmove || busy || loading || displayError) { e.preventDefault(); return; }
|
|
49
122
|
draggedCardId = cardId;
|
|
50
123
|
if (e.dataTransfer) {
|
|
51
124
|
e.dataTransfer.effectAllowed = 'move';
|
|
@@ -60,32 +133,65 @@
|
|
|
60
133
|
}
|
|
61
134
|
}
|
|
62
135
|
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
136
|
+
async function moveCard(cardId: string, targetColId: string, targetIndex = Number.MAX_SAFE_INTEGER) {
|
|
137
|
+
const card = cards.find((c) => c.id === cardId);
|
|
138
|
+
if (!card || !moveAllowed(card, targetColId)) return;
|
|
139
|
+
const source = [...cards];
|
|
140
|
+
const without = source.filter(item => item.id !== card.id);
|
|
141
|
+
const targetCards = without.filter(item => item.columnId === targetColId);
|
|
142
|
+
const index = Math.min(Math.max(0, targetIndex), targetCards.length);
|
|
143
|
+
if (card.columnId === targetColId && source.filter(item => item.columnId === targetColId).findIndex(item => item.id === card.id) === index) return;
|
|
144
|
+
const destination = { ...card, columnId: targetColId };
|
|
145
|
+
const optimistic = [...without.filter(item => item.columnId !== targetColId), ...targetCards.slice(0, index), destination, ...targetCards.slice(index)];
|
|
146
|
+
const changed = source.length !== optimistic.length || source.some((item, i) => item.id !== optimistic[i]?.id || item.columnId !== optimistic[i]?.columnId);
|
|
147
|
+
if (!changed) return;
|
|
148
|
+
const origin = scope;
|
|
149
|
+
const current = { scope: origin, preview: optimistic };
|
|
150
|
+
operation = current;
|
|
151
|
+
adding = false;
|
|
152
|
+
movingCardId = card.id;
|
|
153
|
+
moveError = null;
|
|
154
|
+
try {
|
|
155
|
+
await origin.oncardmove?.(card.id, targetColId, index);
|
|
156
|
+
if (active(origin) && operation === current) cards = optimistic;
|
|
157
|
+
} catch (cause) {
|
|
158
|
+
if (active(origin) && operation === current) {
|
|
159
|
+
moveError = i18n.t('kanban.moveFailed');
|
|
160
|
+
try { oncardmoveerror?.(cause); } catch { /* 错误观察者不能再次触发写入。 */ }
|
|
161
|
+
}
|
|
162
|
+
} finally {
|
|
163
|
+
if (operation === current) { operation = undefined; movingCardId = null; }
|
|
71
164
|
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function handleDrop(targetColId: string, index?: number) {
|
|
168
|
+
const id = draggedCardId;
|
|
72
169
|
draggedCardId = null;
|
|
170
|
+
if (id) void moveCard(id, targetColId, index);
|
|
73
171
|
}
|
|
74
172
|
|
|
75
|
-
function submitAddCard(columnId: string) {
|
|
76
|
-
if (!newCardTitle.
|
|
173
|
+
async function submitAddCard(columnId: string) {
|
|
174
|
+
if (!validText(newCardTitle) || !oncardadd || !allowAddCard || busy || loading || displayError || cards.length >= 1000) return;
|
|
175
|
+
const origin = scope;
|
|
176
|
+
const current = { scope: origin };
|
|
177
|
+
operation = current;
|
|
178
|
+
movingCardId = null;
|
|
179
|
+
adding = true;
|
|
180
|
+
moveError = null;
|
|
181
|
+
try {
|
|
182
|
+
const newCard = await origin.oncardadd?.(columnId, newCardTitle.trim());
|
|
183
|
+
if (!active(origin) || operation !== current) return;
|
|
184
|
+
if (!newCard || !validCard(newCard) || newCard.columnId !== columnId || cards.some(card => card.id === newCard.id)) {
|
|
185
|
+
throw new Error('Invalid card receipt');
|
|
186
|
+
}
|
|
187
|
+
cards = [...cards, newCard];
|
|
188
|
+
newCardTitle = '';
|
|
77
189
|
addingColumnId = null;
|
|
78
|
-
|
|
190
|
+
} catch {
|
|
191
|
+
if (active(origin) && operation === current) moveError = i18n.t('kanban.addFailed');
|
|
192
|
+
} finally {
|
|
193
|
+
if (operation === current) { operation = undefined; adding = false; }
|
|
79
194
|
}
|
|
80
|
-
const newCard: KanbanCard = {
|
|
81
|
-
id: `k_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
|
|
82
|
-
title: newCardTitle.trim(),
|
|
83
|
-
columnId,
|
|
84
|
-
};
|
|
85
|
-
cards = [...cards, newCard];
|
|
86
|
-
oncardadd?.(columnId, newCardTitle.trim());
|
|
87
|
-
newCardTitle = '';
|
|
88
|
-
addingColumnId = null;
|
|
89
195
|
}
|
|
90
196
|
|
|
91
197
|
function getPriorityClass(priority?: string) {
|
|
@@ -102,15 +208,27 @@
|
|
|
102
208
|
}
|
|
103
209
|
</script>
|
|
104
210
|
|
|
105
|
-
<div
|
|
211
|
+
{#if moveError}<div role="alert">{moveError}</div>{/if}
|
|
212
|
+
<div role="region" aria-label={ariaLabel ?? i18n.t('kanban.label')} aria-busy={loading || busy}
|
|
213
|
+
class={cn('svadmin-u-60fbb7713999 svadmin-u-0c3bc98565dd svadmin-u-1384f66f41d0 svadmin-u-9fcd8a13827e svadmin-u-359090c2d529 svadmin-u-7f6912283f11', className)}>
|
|
214
|
+
{#if loading}
|
|
215
|
+
<div role="status">{i18n.t('common.loading')}</div>
|
|
216
|
+
{:else if displayError}
|
|
217
|
+
<div role="alert">{displayError}</div>
|
|
218
|
+
{#if error && onRetry}
|
|
219
|
+
<Button type="button" variant="ghost" size="sm" onclick={onRetry}><RotateCw aria-hidden="true" />{i18n.t('common.retry')}</Button>
|
|
220
|
+
{/if}
|
|
221
|
+
{:else if columns.length === 0}
|
|
222
|
+
<div role="status">{i18n.t('common.noData')}</div>
|
|
223
|
+
{:else}
|
|
106
224
|
{#each columns as col (col.id)}
|
|
107
|
-
{@const colCards =
|
|
225
|
+
{@const colCards = visibleCards.filter((c) => c.columnId === col.id)}
|
|
108
226
|
<div
|
|
109
227
|
role="region"
|
|
110
228
|
aria-label={col.title}
|
|
111
229
|
class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-92e13d146fd7 svadmin-u-012fbd121f37 svadmin-u-a217b4eaa918 svadmin-u-ca6bcd4b6f3f svadmin-u-22bb278694b4 svadmin-u-7f351d50b6e6 svadmin-u-cef5b893cf23 svadmin-u-a4805b5f5b63"
|
|
112
230
|
ondragover={handleDragOver}
|
|
113
|
-
ondrop={() => handleDrop(col.id)}
|
|
231
|
+
ondrop={(event) => { event.preventDefault(); handleDrop(col.id); }}
|
|
114
232
|
>
|
|
115
233
|
<!-- Column Header -->
|
|
116
234
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-eb6e8b881acd svadmin-u-65fdbade2025 svadmin-u-591f378e24a1">
|
|
@@ -121,8 +239,12 @@
|
|
|
121
239
|
</span>
|
|
122
240
|
</div>
|
|
123
241
|
|
|
124
|
-
{#if allowAddCard}
|
|
242
|
+
{#if allowAddCard && oncardadd}
|
|
125
243
|
<Button
|
|
244
|
+
type="button"
|
|
245
|
+
disabled={busy || cards.length >= 1000}
|
|
246
|
+
aria-label={i18n.t('kanban.addTo', { column: col.title })}
|
|
247
|
+
title={i18n.t('kanban.addTo', { column: col.title })}
|
|
126
248
|
variant="ghost"
|
|
127
249
|
size="sm"
|
|
128
250
|
class="svadmin-u-f6fe902450dc svadmin-u-7ec10f86d9b1 svadmin-u-8a539c7fe216 svadmin-u-bfa603190748 svadmin-u-ea7b2e9e070e"
|
|
@@ -138,22 +260,28 @@
|
|
|
138
260
|
|
|
139
261
|
<!-- Column Card List -->
|
|
140
262
|
<div class="svadmin-u-36e579c0b41c svadmin-u-92bf82f493b1 svadmin-u-7660b450905a svadmin-u-6f7e013d6499 svadmin-u-53ecdb131b58">
|
|
141
|
-
{#each colCards as card (card.id)}
|
|
263
|
+
{#each colCards as card, cardIndex (card.id)}
|
|
142
264
|
<div
|
|
143
|
-
role="
|
|
144
|
-
|
|
145
|
-
|
|
265
|
+
role="group"
|
|
266
|
+
aria-label={card.title}
|
|
267
|
+
aria-busy={busy && movingCardId === card.id}
|
|
268
|
+
draggable={!!oncardmove && !busy}
|
|
146
269
|
class={cn(
|
|
147
270
|
'group svadmin-u-d89972fe17d6 svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-77a2a20e90d4 svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-05faf5c801ff svadmin-u-cd0ad9a56558 svadmin-u-eb6e8b881acd svadmin-u-cef5b893cf23 svadmin-u-0fe7d7d814d0 svadmin-u-8d08385288a6 svadmin-u-d9bff91ef7ee svadmin-u-512e82e6a68f svadmin-u-ab1dd417ce7d svadmin-u-2eba0d65d059',
|
|
148
271
|
draggedCardId === card.id ? 'svadmin-u-2a2db4667b27 svadmin-u-16b1efa5875e svadmin-u-2691847b25ed' : ''
|
|
149
272
|
)}
|
|
150
273
|
ondragstart={(e) => handleDragStart(e, card.id)}
|
|
151
|
-
|
|
152
|
-
|
|
274
|
+
ondragend={() => { draggedCardId = null; }}
|
|
275
|
+
ondragover={handleDragOver}
|
|
276
|
+
ondrop={(e) => { e.preventDefault(); e.stopPropagation(); handleDrop(col.id, cardIndex); }}
|
|
153
277
|
>
|
|
154
278
|
<div class="svadmin-u-60fbb7713999 svadmin-u-60541e1e26f8 svadmin-u-8ef2268efbbc svadmin-u-77a2a20e90d4">
|
|
155
|
-
|
|
156
|
-
|
|
279
|
+
{#if oncardclick}
|
|
280
|
+
<button type="button" disabled={busy} onclick={() => oncardclick?.(card)} class="svadmin-u-2689f3958069 svadmin-u-d4108abe6359 svadmin-u-e25ca6535dea">{card.title}</button>
|
|
281
|
+
{:else}
|
|
282
|
+
<div class="svadmin-u-2689f3958069 svadmin-u-d4108abe6359 svadmin-u-e25ca6535dea">{card.title}</div>
|
|
283
|
+
{/if}
|
|
284
|
+
{#if oncardmove}<GripVertical aria-hidden="true" class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-52183a1cca53 svadmin-u-7065497e1ca0 svadmin-u-181f3d6c9821 svadmin-u-67d6184a0024 svadmin-u-012fbd121f37" />{/if}
|
|
157
285
|
</div>
|
|
158
286
|
|
|
159
287
|
{#if card.description}
|
|
@@ -167,7 +295,7 @@
|
|
|
167
295
|
{card.priority}
|
|
168
296
|
</Badge>
|
|
169
297
|
{/if}
|
|
170
|
-
{#each card.tags ?? [] as tag (
|
|
298
|
+
{#each card.tags ?? [] as tag, tagIndex (tagIndex)}
|
|
171
299
|
<span class="svadmin-u-07389a777c1f svadmin-u-706701550477 svadmin-u-d8e0e382c67b svadmin-u-465609a240a8 svadmin-u-bfa603190748">#{tag}</span>
|
|
172
300
|
{/each}
|
|
173
301
|
</div>
|
|
@@ -181,18 +309,44 @@
|
|
|
181
309
|
</div>
|
|
182
310
|
{/if}
|
|
183
311
|
</div>
|
|
312
|
+
{#if oncardmove}
|
|
313
|
+
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">
|
|
314
|
+
<select aria-label={i18n.t('kanban.move', { card: card.title })} value={card.columnId} disabled={busy}
|
|
315
|
+
style="min-width: 0; max-width: 100%;"
|
|
316
|
+
onchange={(event) => {
|
|
317
|
+
const target = event.currentTarget.value;
|
|
318
|
+
event.currentTarget.value = card.columnId;
|
|
319
|
+
void moveCard(card.id, target);
|
|
320
|
+
}}>
|
|
321
|
+
{#each columns as destination (destination.id)}
|
|
322
|
+
<option value={destination.id} disabled={destination.id !== card.columnId && !moveAllowed(card, destination.id)}>{destination.title}</option>
|
|
323
|
+
{/each}
|
|
324
|
+
</select>
|
|
325
|
+
<Button type="button" variant="ghost" size="icon-sm" title={i18n.t('common.moveUp')}
|
|
326
|
+
aria-label={i18n.t('common.moveUp')} disabled={cardIndex === 0 || !moveAllowed(card, col.id)}
|
|
327
|
+
onclick={() => void moveCard(card.id, col.id, cardIndex - 1)}><ArrowUp aria-hidden="true" /></Button>
|
|
328
|
+
<Button type="button" variant="ghost" size="icon-sm" title={i18n.t('common.moveDown')}
|
|
329
|
+
aria-label={i18n.t('common.moveDown')} disabled={cardIndex === colCards.length - 1 || !moveAllowed(card, col.id)}
|
|
330
|
+
onclick={() => void moveCard(card.id, col.id, cardIndex + 1)}><ArrowDown aria-hidden="true" /></Button>
|
|
331
|
+
</div>
|
|
332
|
+
{/if}
|
|
184
333
|
</div>
|
|
334
|
+
{:else}
|
|
335
|
+
<div role="status">{i18n.t('common.noData')}</div>
|
|
185
336
|
{/each}
|
|
186
337
|
|
|
187
338
|
{#if addingColumnId === col.id}
|
|
188
339
|
<div class="svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-f5583b2907be svadmin-u-cd0ad9a56558 svadmin-u-9fe52d5d506c svadmin-u-6f7e013d6499 svadmin-u-cef5b893cf23">
|
|
189
340
|
<textarea
|
|
190
341
|
bind:value={newCardTitle}
|
|
191
|
-
|
|
342
|
+
aria-label={i18n.t('kanban.cardTitle')}
|
|
343
|
+
placeholder={i18n.t('kanban.cardTitle')}
|
|
344
|
+
maxlength={1000}
|
|
345
|
+
disabled={busy}
|
|
192
346
|
rows={2}
|
|
193
347
|
class="svadmin-u-6da6a3c3f741 svadmin-u-07389a777c1f svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-cd009d7d208c svadmin-u-359090c2d529 svadmin-u-d4108abe6359 svadmin-u-9c24ab70af61 svadmin-u-f10f771f87e9 svadmin-u-3e94a98e1466 svadmin-u-9c1295a6914a svadmin-u-6aef32016896"
|
|
194
348
|
onkeydown={(e) => {
|
|
195
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
349
|
+
if (e.key === 'Enter' && !e.shiftKey && !e.isComposing && !e.repeat) {
|
|
196
350
|
e.preventDefault();
|
|
197
351
|
submitAddCard(col.id);
|
|
198
352
|
} else if (e.key === 'Escape') {
|
|
@@ -201,12 +355,13 @@
|
|
|
201
355
|
}}
|
|
202
356
|
></textarea>
|
|
203
357
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77c08e015d14 svadmin-u-58284b4ea568">
|
|
204
|
-
<Button variant="ghost" size="sm" class="svadmin-u-f6fe902450dc svadmin-u-d058ca6de60f svadmin-u-d5eab218aa34" onclick={() => { addingColumnId = null; }}>
|
|
205
|
-
<Button size="sm" class="svadmin-u-f6fe902450dc svadmin-u-d058ca6de60f svadmin-u-d5eab218aa34" onclick={() => submitAddCard(col.id)}>
|
|
358
|
+
<Button type="button" disabled={busy} variant="ghost" size="sm" class="svadmin-u-f6fe902450dc svadmin-u-d058ca6de60f svadmin-u-d5eab218aa34" onclick={() => { addingColumnId = null; }}>{i18n.t('common.cancel')}</Button>
|
|
359
|
+
<Button type="button" disabled={busy || !validText(newCardTitle)} size="sm" class="svadmin-u-f6fe902450dc svadmin-u-d058ca6de60f svadmin-u-d5eab218aa34" onclick={() => submitAddCard(col.id)}>{i18n.t('common.add')}</Button>
|
|
206
360
|
</div>
|
|
207
361
|
</div>
|
|
208
362
|
{/if}
|
|
209
363
|
</div>
|
|
210
364
|
</div>
|
|
211
365
|
{/each}
|
|
366
|
+
{/if}
|
|
212
367
|
</div>
|
|
@@ -20,9 +20,16 @@ interface Props {
|
|
|
20
20
|
columns: KanbanColumn[];
|
|
21
21
|
cards?: KanbanCard[];
|
|
22
22
|
allowAddCard?: boolean;
|
|
23
|
-
oncardmove?: (cardId: string, targetColumnId: string) => void
|
|
23
|
+
oncardmove?: (cardId: string, targetColumnId: string, targetIndex: number) => void | Promise<void>;
|
|
24
|
+
canMoveCard?: (card: KanbanCard, targetColumnId: string) => boolean;
|
|
25
|
+
oncardmoveerror?: (error: unknown) => void;
|
|
24
26
|
oncardclick?: (card: KanbanCard) => void;
|
|
25
|
-
oncardadd?: (columnId: string, title: string) =>
|
|
27
|
+
oncardadd?: (columnId: string, title: string) => KanbanCard | Promise<KanbanCard>;
|
|
28
|
+
scopeKey?: string | number;
|
|
29
|
+
loading?: boolean;
|
|
30
|
+
error?: string | undefined;
|
|
31
|
+
onRetry?: () => void;
|
|
32
|
+
ariaLabel?: string;
|
|
26
33
|
class?: string;
|
|
27
34
|
}
|
|
28
35
|
declare const KanbanBoard: import("svelte").Component<Props, {}, "cards">;
|
|
@@ -203,8 +203,9 @@
|
|
|
203
203
|
|
|
204
204
|
<div
|
|
205
205
|
class="svadmin-u-36e579c0b41c svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-2cd02d11d1af svadmin-u-0fe7d7d814d0 svadmin-u-7890552ecd63"
|
|
206
|
-
|
|
206
|
+
class:svadmin-sidebar-content-expanded={!collapsed}
|
|
207
207
|
class:sidebar-content-expanded={!collapsed}
|
|
208
|
+
class:svadmin-sidebar-content-collapsed={collapsed}
|
|
208
209
|
class:sidebar-content-collapsed={collapsed}
|
|
209
210
|
>
|
|
210
211
|
<!-- Header with mobile hamburger -->
|
|
@@ -243,7 +244,8 @@
|
|
|
243
244
|
<main id={mainContentId} tabindex="-1" data-svadmin-main class="svadmin-u-36e579c0b41c svadmin-u-92bf82f493b1 svadmin-u-2859c861d7de svadmin-u-f0faeb26d656 svadmin-u-c9b99cd93450 svadmin-u-cc06a6575385 svadmin-u-daf5dc5fac2b svadmin-u-e86fadb84483">
|
|
244
245
|
<div class="svadmin-u-0e12dc7de920 svadmin-u-6da6a3c3f741 svadmin-u-9e3dc30c26a3">
|
|
245
246
|
{#key getPath()}
|
|
246
|
-
|
|
247
|
+
<!-- 路由切换立即释放旧页面,避免退出期间继续读取已失效的路由派生状态。 -->
|
|
248
|
+
<div in:fly={{ x: 20, duration: 150 }}>
|
|
247
249
|
{@render children()}
|
|
248
250
|
</div>
|
|
249
251
|
{/key}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ComponentProps } from 'svelte';
|
|
3
|
+
import type AutoForm from './AutoForm.svelte';
|
|
4
|
+
export interface LazyAutoFormProps extends ComponentProps<typeof AutoForm> {
|
|
5
|
+
resourceName: ComponentProps<typeof AutoForm>['resourceName'];
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
11
|
+
|
|
12
|
+
let props: LazyAutoFormProps = $props();
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
let page = $state.raw(import('./AutoForm.svelte'));
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#await page}
|
|
18
|
+
<p role="status" aria-live="polite">{i18n.t('common.loading')}</p>
|
|
19
|
+
{:then module}
|
|
20
|
+
<module.default {...props} />
|
|
21
|
+
{:catch}
|
|
22
|
+
<div role="alert">
|
|
23
|
+
<p>{i18n.t('common.operationFailed')}</p>
|
|
24
|
+
<button type="button" onclick={() => page = import('./AutoForm.svelte')}>
|
|
25
|
+
{i18n.t('common.retry')}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
{/await}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentProps } from 'svelte';
|
|
2
|
+
import type AutoForm from './AutoForm.svelte';
|
|
3
|
+
export interface LazyAutoFormProps extends ComponentProps<typeof AutoForm> {
|
|
4
|
+
resourceName: ComponentProps<typeof AutoForm>['resourceName'];
|
|
5
|
+
}
|
|
6
|
+
declare const LazyAutoForm: import("svelte").Component<LazyAutoFormProps, {}, "">;
|
|
7
|
+
type LazyAutoForm = ReturnType<typeof LazyAutoForm>;
|
|
8
|
+
export default LazyAutoForm;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ComponentProps } from 'svelte';
|
|
3
|
+
import type AutoTable from './AutoTable.svelte';
|
|
4
|
+
export interface LazyAutoTableProps extends ComponentProps<typeof AutoTable> {
|
|
5
|
+
resourceName: ComponentProps<typeof AutoTable>['resourceName'];
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
11
|
+
|
|
12
|
+
let props: LazyAutoTableProps = $props();
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
let page = $state.raw(import('./AutoTable.svelte'));
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#await page}
|
|
18
|
+
<p role="status" aria-live="polite">{i18n.t('common.loading')}</p>
|
|
19
|
+
{:then module}
|
|
20
|
+
<module.default {...props} />
|
|
21
|
+
{:catch}
|
|
22
|
+
<div role="alert">
|
|
23
|
+
<p>{i18n.t('common.operationFailed')}</p>
|
|
24
|
+
<button type="button" onclick={() => page = import('./AutoTable.svelte')}>
|
|
25
|
+
{i18n.t('common.retry')}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
{/await}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentProps } from 'svelte';
|
|
2
|
+
import type AutoTable from './AutoTable.svelte';
|
|
3
|
+
export interface LazyAutoTableProps extends ComponentProps<typeof AutoTable> {
|
|
4
|
+
resourceName: ComponentProps<typeof AutoTable>['resourceName'];
|
|
5
|
+
}
|
|
6
|
+
declare const LazyAutoTable: import("svelte").Component<LazyAutoTableProps, {}, "">;
|
|
7
|
+
type LazyAutoTable = ReturnType<typeof LazyAutoTable>;
|
|
8
|
+
export default LazyAutoTable;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import type { Component } from 'svelte';
|
|
3
3
|
|
|
4
|
+
export type LazyPageRenderable = Component<never>;
|
|
4
5
|
export type LazyPageModule = {
|
|
5
|
-
default:
|
|
6
|
+
default: LazyPageRenderable;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
|
-
export type LazyPageRenderable = Component<Record<string, unknown>>;
|
|
9
9
|
export type LazyPageLoader = () => Promise<LazyPageModule>;
|
|
10
10
|
|
|
11
11
|
const pagePromises = new WeakMap<object, Promise<unknown>>();
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<span class="svadmin-u-fc7473ca09eb svadmin-u-bfa603190748">Loading...</span>
|
|
39
39
|
</div>
|
|
40
40
|
{:then pageModule}
|
|
41
|
-
{@const Page = pageModule.default as unknown as
|
|
41
|
+
{@const Page = pageModule.default as unknown as Component<Record<string, unknown>>}
|
|
42
42
|
<Page {...props} />
|
|
43
43
|
{:catch}
|
|
44
44
|
<div class="svadmin-u-60fbb7713999 svadmin-u-8a7a926578c8 svadmin-u-3960ffc248d9 svadmin-u-86843cf1e227" role="alert">
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
+
export type LazyPageRenderable = Component<never>;
|
|
2
3
|
export type LazyPageModule = {
|
|
3
|
-
default:
|
|
4
|
+
default: LazyPageRenderable;
|
|
4
5
|
};
|
|
5
|
-
export type LazyPageRenderable = Component<Record<string, unknown>>;
|
|
6
6
|
export type LazyPageLoader = () => Promise<LazyPageModule>;
|
|
7
7
|
export declare function loadLazyPage(loader: LazyPageLoader): Promise<LazyPageModule>;
|
|
8
8
|
type $$ComponentProps = {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ComponentProps } from 'svelte';
|
|
3
|
+
import type SettingsPage from './SettingsPage.svelte';
|
|
4
|
+
export interface LazySettingsPageProps extends ComponentProps<typeof SettingsPage> {
|
|
5
|
+
preferencesProvider?: NonNullable<ComponentProps<typeof SettingsPage>['preferencesProvider']>;
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
11
|
+
|
|
12
|
+
let props: LazySettingsPageProps = $props();
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
let page = $state.raw(import('./SettingsPage.svelte'));
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#await page}
|
|
18
|
+
<p role="status" aria-live="polite">{i18n.t('common.loading')}</p>
|
|
19
|
+
{:then module}
|
|
20
|
+
<module.default {...props} />
|
|
21
|
+
{:catch}
|
|
22
|
+
<div role="alert">
|
|
23
|
+
<p>{i18n.t('common.operationFailed')}</p>
|
|
24
|
+
<button type="button" onclick={() => page = import('./SettingsPage.svelte')}>
|
|
25
|
+
{i18n.t('common.retry')}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
{/await}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentProps } from 'svelte';
|
|
2
|
+
import type SettingsPage from './SettingsPage.svelte';
|
|
3
|
+
export interface LazySettingsPageProps extends ComponentProps<typeof SettingsPage> {
|
|
4
|
+
preferencesProvider?: NonNullable<ComponentProps<typeof SettingsPage>['preferencesProvider']>;
|
|
5
|
+
}
|
|
6
|
+
declare const LazySettingsPage: import("svelte").Component<LazySettingsPageProps, {}, "">;
|
|
7
|
+
type LazySettingsPage = ReturnType<typeof LazySettingsPage>;
|
|
8
|
+
export default LazySettingsPage;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ComponentProps } from 'svelte';
|
|
3
|
+
import type ShowPage from './ShowPage.svelte';
|
|
4
|
+
export interface LazyShowPageProps extends ComponentProps<typeof ShowPage> {
|
|
5
|
+
resourceName: ComponentProps<typeof ShowPage>['resourceName'];
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
11
|
+
|
|
12
|
+
let props: LazyShowPageProps = $props();
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
let page = $state.raw(import('./ShowPage.svelte'));
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#await page}
|
|
18
|
+
<p role="status" aria-live="polite">{i18n.t('common.loading')}</p>
|
|
19
|
+
{:then module}
|
|
20
|
+
<module.default {...props} />
|
|
21
|
+
{:catch}
|
|
22
|
+
<div role="alert">
|
|
23
|
+
<p>{i18n.t('common.operationFailed')}</p>
|
|
24
|
+
<button type="button" onclick={() => page = import('./ShowPage.svelte')}>
|
|
25
|
+
{i18n.t('common.retry')}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
{/await}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentProps } from 'svelte';
|
|
2
|
+
import type ShowPage from './ShowPage.svelte';
|
|
3
|
+
export interface LazyShowPageProps extends ComponentProps<typeof ShowPage> {
|
|
4
|
+
resourceName: ComponentProps<typeof ShowPage>['resourceName'];
|
|
5
|
+
}
|
|
6
|
+
declare const LazyShowPage: import("svelte").Component<LazyShowPageProps, {}, "">;
|
|
7
|
+
type LazyShowPage = ReturnType<typeof LazyShowPage>;
|
|
8
|
+
export default LazyShowPage;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import type { FieldDefinition } from '@svadmin/core';
|
|
9
9
|
import PageHeader from './PageHeader.svelte';
|
|
10
10
|
import AutoTable from './AutoTable.svelte';
|
|
11
|
+
import type { BatchSelection } from './table-contract';
|
|
11
12
|
import CreateButton from './buttons/CreateButton.svelte';
|
|
12
13
|
|
|
13
14
|
interface Props {
|
|
@@ -18,6 +19,7 @@
|
|
|
18
19
|
density?: 'compact' | 'comfortable';
|
|
19
20
|
/** Passthrough: enable row selection checkboxes */
|
|
20
21
|
selectable?: boolean;
|
|
22
|
+
allowSelectAllMatching?: boolean;
|
|
21
23
|
/** Passthrough: custom header actions */
|
|
22
24
|
headerActions?: Snippet;
|
|
23
25
|
/** Optional status tabs slot above filter/table */
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
/** Optional filter toolbar slot between status tabs and table */
|
|
26
28
|
filterToolbar?: Snippet;
|
|
27
29
|
/** Passthrough: custom batch actions to render when rows are selected */
|
|
28
|
-
batchActions?: Snippet<[{ selectedIds: (string | number)[] }]>;
|
|
30
|
+
batchActions?: Snippet<[{ selectedIds: (string | number)[]; selection: BatchSelection }]>;
|
|
29
31
|
/** Passthrough: custom cell renderer per field */
|
|
30
32
|
cellRenderer?: Snippet<[{ field: FieldDefinition; value: unknown; record: Record<string, unknown> }]>;
|
|
31
33
|
/** Passthrough: custom row actions */
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
canCreate,
|
|
45
47
|
density = 'comfortable',
|
|
46
48
|
selectable,
|
|
49
|
+
allowSelectAllMatching,
|
|
47
50
|
headerActions,
|
|
48
51
|
statusTabs,
|
|
49
52
|
filterToolbar,
|
|
@@ -89,6 +92,7 @@
|
|
|
89
92
|
showHeader={false}
|
|
90
93
|
{density}
|
|
91
94
|
{...definedOptions({ "selectable": selectable })}
|
|
95
|
+
{...definedOptions({ allowSelectAllMatching })}
|
|
92
96
|
{...definedOptions({ batchActions })}
|
|
93
97
|
{...definedOptions({ "defaultCellRenderer": cellRenderer })}
|
|
94
98
|
{...definedOptions({ "rowActions": rowActions })}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResourceRendering } from '../rendering/index.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { FieldDefinition } from '@svadmin/core';
|
|
4
|
+
import type { BatchSelection } from './table-contract';
|
|
4
5
|
interface Props {
|
|
5
6
|
resourceName: string;
|
|
6
7
|
rendering?: ResourceRendering | undefined;
|
|
@@ -9,6 +10,7 @@ interface Props {
|
|
|
9
10
|
density?: 'compact' | 'comfortable';
|
|
10
11
|
/** Passthrough: enable row selection checkboxes */
|
|
11
12
|
selectable?: boolean;
|
|
13
|
+
allowSelectAllMatching?: boolean;
|
|
12
14
|
/** Passthrough: custom header actions */
|
|
13
15
|
headerActions?: Snippet;
|
|
14
16
|
/** Optional status tabs slot above filter/table */
|
|
@@ -18,6 +20,7 @@ interface Props {
|
|
|
18
20
|
/** Passthrough: custom batch actions to render when rows are selected */
|
|
19
21
|
batchActions?: Snippet<[{
|
|
20
22
|
selectedIds: (string | number)[];
|
|
23
|
+
selection: BatchSelection;
|
|
21
24
|
}]>;
|
|
22
25
|
/** Passthrough: custom cell renderer per field */
|
|
23
26
|
cellRenderer?: Snippet<[{
|