@svadmin/ui 0.29.1 → 0.29.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/package.json +20 -9
  2. package/src/README.md +0 -18
  3. package/src/actions.ts +0 -110
  4. package/src/app.css +0 -673
  5. package/src/component-registry.svelte.ts +0 -60
  6. package/src/components/AICommandBar.svelte +0 -180
  7. package/src/components/AboutSettings.svelte +0 -106
  8. package/src/components/AdminApp.svelte +0 -199
  9. package/src/components/AnimatedCounter.svelte +0 -46
  10. package/src/components/AnomalyBadge.svelte +0 -65
  11. package/src/components/AppearanceSettings.svelte +0 -183
  12. package/src/components/AuditLogDrawer.svelte +0 -93
  13. package/src/components/AuditLogViewer.svelte +0 -226
  14. package/src/components/Authenticated.svelte +0 -51
  15. package/src/components/AutoForm.svelte +0 -242
  16. package/src/components/AutoSaveIndicator.svelte +0 -35
  17. package/src/components/AutoTable.svelte +0 -839
  18. package/src/components/Breadcrumbs.svelte +0 -58
  19. package/src/components/CanAccess.svelte +0 -23
  20. package/src/components/CatchAllNavigate.svelte +0 -21
  21. package/src/components/ChatDialog.svelte +0 -535
  22. package/src/components/ComboboxField.svelte +0 -129
  23. package/src/components/CommandPalette.svelte +0 -135
  24. package/src/components/ConfigErrorScreen.svelte +0 -126
  25. package/src/components/ConfirmDialog.svelte +0 -53
  26. package/src/components/CopilotPanel.svelte +0 -163
  27. package/src/components/CreatePage.svelte +0 -39
  28. package/src/components/DevTools.svelte +0 -149
  29. package/src/components/DraggableGrid.svelte +0 -86
  30. package/src/components/DraggableHeader.svelte +0 -112
  31. package/src/components/DrawerForm.svelte +0 -35
  32. package/src/components/EditPage.svelte +0 -52
  33. package/src/components/EmptyState.svelte +0 -31
  34. package/src/components/ErrorBoundary.svelte +0 -49
  35. package/src/components/ErrorComponent.svelte +0 -36
  36. package/src/components/FieldRenderer.svelte +0 -357
  37. package/src/components/ForgotPasswordPage.svelte +0 -112
  38. package/src/components/Header.svelte +0 -94
  39. package/src/components/InferencerPanel.svelte +0 -192
  40. package/src/components/InfiniteList.svelte +0 -93
  41. package/src/components/InlineEdit.svelte +0 -88
  42. package/src/components/InsightCard.svelte +0 -98
  43. package/src/components/KeyboardShortcuts.svelte +0 -61
  44. package/src/components/Layout.svelte +0 -167
  45. package/src/components/ListPage.svelte +0 -71
  46. package/src/components/LiveIndicator.svelte +0 -58
  47. package/src/components/LoginPage.svelte +0 -163
  48. package/src/components/MarkdownRenderer.svelte +0 -127
  49. package/src/components/ModalForm.svelte +0 -38
  50. package/src/components/NavigateToResource.svelte +0 -20
  51. package/src/components/PageHeader.svelte +0 -39
  52. package/src/components/PageSkeleton.svelte +0 -71
  53. package/src/components/PasswordInput.svelte +0 -96
  54. package/src/components/PermissionMatrix.svelte +0 -185
  55. package/src/components/ProfilePage.svelte +0 -284
  56. package/src/components/RegisterPage.svelte +0 -112
  57. package/src/components/RolesSettings.svelte +0 -146
  58. package/src/components/SettingsPage.svelte +0 -113
  59. package/src/components/ShowPage.svelte +0 -73
  60. package/src/components/Sidebar.svelte +0 -417
  61. package/src/components/SidebarItem.svelte +0 -129
  62. package/src/components/SmartSuggest.svelte +0 -158
  63. package/src/components/StatsCard.svelte +0 -79
  64. package/src/components/StepsForm.svelte +0 -192
  65. package/src/components/TaskQueueDrawer.svelte +0 -158
  66. package/src/components/TenantSwitcher.svelte +0 -84
  67. package/src/components/ThemedTitle.svelte +0 -32
  68. package/src/components/Toast.svelte +0 -46
  69. package/src/components/TooltipButton.svelte +0 -42
  70. package/src/components/UndoableNotification.svelte +0 -69
  71. package/src/components/UpdatePasswordPage.svelte +0 -89
  72. package/src/components/VirtualTable.svelte +0 -76
  73. package/src/components/VoiceInput.svelte +0 -120
  74. package/src/components/buttons/CloneButton.svelte +0 -30
  75. package/src/components/buttons/CreateButton.svelte +0 -29
  76. package/src/components/buttons/DeleteButton.svelte +0 -59
  77. package/src/components/buttons/EditButton.svelte +0 -30
  78. package/src/components/buttons/ExportButton.svelte +0 -30
  79. package/src/components/buttons/ImportButton.svelte +0 -56
  80. package/src/components/buttons/ListButton.svelte +0 -23
  81. package/src/components/buttons/RefreshButton.svelte +0 -36
  82. package/src/components/buttons/SaveButton.svelte +0 -27
  83. package/src/components/buttons/ShowButton.svelte +0 -31
  84. package/src/components/buttons/index.ts +0 -10
  85. package/src/components/charts/BarChart.svelte +0 -69
  86. package/src/components/charts/LineChart.svelte +0 -115
  87. package/src/components/charts/PieChart.svelte +0 -95
  88. package/src/components/charts/index.ts +0 -3
  89. package/src/components/fieldComponentMap.ts +0 -79
  90. package/src/components/fields/ArrayField.svelte +0 -86
  91. package/src/components/fields/BooleanField.svelte +0 -13
  92. package/src/components/fields/DateField.svelte +0 -6
  93. package/src/components/fields/EmailField.svelte +0 -9
  94. package/src/components/fields/FileField.svelte +0 -14
  95. package/src/components/fields/ImageField.svelte +0 -9
  96. package/src/components/fields/JsonField.svelte +0 -72
  97. package/src/components/fields/MarkdownField.svelte +0 -9
  98. package/src/components/fields/MultiSelectField.svelte +0 -21
  99. package/src/components/fields/NumberField.svelte +0 -6
  100. package/src/components/fields/RelationField.svelte +0 -24
  101. package/src/components/fields/RichTextField.svelte +0 -35
  102. package/src/components/fields/SelectField.svelte +0 -14
  103. package/src/components/fields/TagField.svelte +0 -12
  104. package/src/components/fields/TextField.svelte +0 -11
  105. package/src/components/fields/UrlField.svelte +0 -14
  106. package/src/components/ui/alert/alert-description.svelte +0 -17
  107. package/src/components/ui/alert/alert-title.svelte +0 -17
  108. package/src/components/ui/alert/alert.svelte +0 -44
  109. package/src/components/ui/alert/index.ts +0 -15
  110. package/src/components/ui/alert-dialog/alert-dialog-content.svelte +0 -29
  111. package/src/components/ui/alert-dialog/alert-dialog-description.svelte +0 -16
  112. package/src/components/ui/alert-dialog/alert-dialog-footer.svelte +0 -11
  113. package/src/components/ui/alert-dialog/alert-dialog-header.svelte +0 -11
  114. package/src/components/ui/alert-dialog/alert-dialog-overlay.svelte +0 -16
  115. package/src/components/ui/alert-dialog/alert-dialog-portal.svelte +0 -6
  116. package/src/components/ui/alert-dialog/alert-dialog-title.svelte +0 -16
  117. package/src/components/ui/alert-dialog/index.ts +0 -20
  118. package/src/components/ui/avatar/avatar.svelte +0 -63
  119. package/src/components/ui/avatar/index.ts +0 -2
  120. package/src/components/ui/badge/badge.svelte +0 -49
  121. package/src/components/ui/badge/index.ts +0 -3
  122. package/src/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +0 -18
  123. package/src/components/ui/breadcrumb/breadcrumb-item.svelte +0 -15
  124. package/src/components/ui/breadcrumb/breadcrumb-link.svelte +0 -15
  125. package/src/components/ui/breadcrumb/breadcrumb-list.svelte +0 -15
  126. package/src/components/ui/breadcrumb/breadcrumb-page.svelte +0 -18
  127. package/src/components/ui/breadcrumb/breadcrumb-separator.svelte +0 -22
  128. package/src/components/ui/breadcrumb/breadcrumb.svelte +0 -11
  129. package/src/components/ui/breadcrumb/index.ts +0 -7
  130. package/src/components/ui/button/button.svelte +0 -90
  131. package/src/components/ui/button/index.ts +0 -18
  132. package/src/components/ui/card/card-action.svelte +0 -23
  133. package/src/components/ui/card/card-content.svelte +0 -20
  134. package/src/components/ui/card/card-description.svelte +0 -20
  135. package/src/components/ui/card/card-footer.svelte +0 -20
  136. package/src/components/ui/card/card-header.svelte +0 -23
  137. package/src/components/ui/card/card-title.svelte +0 -15
  138. package/src/components/ui/card/card.svelte +0 -22
  139. package/src/components/ui/card/index.ts +0 -25
  140. package/src/components/ui/checkbox/checkbox.svelte +0 -39
  141. package/src/components/ui/checkbox/index.ts +0 -6
  142. package/src/components/ui/collapsible/index.ts +0 -7
  143. package/src/components/ui/command/command-dialog.svelte +0 -31
  144. package/src/components/ui/command/index.ts +0 -2
  145. package/src/components/ui/context-menu/index.ts +0 -11
  146. package/src/components/ui/dialog/dialog-close.svelte +0 -11
  147. package/src/components/ui/dialog/dialog-content.svelte +0 -48
  148. package/src/components/ui/dialog/dialog-description.svelte +0 -17
  149. package/src/components/ui/dialog/dialog-footer.svelte +0 -32
  150. package/src/components/ui/dialog/dialog-header.svelte +0 -20
  151. package/src/components/ui/dialog/dialog-overlay.svelte +0 -17
  152. package/src/components/ui/dialog/dialog-portal.svelte +0 -7
  153. package/src/components/ui/dialog/dialog-title.svelte +0 -17
  154. package/src/components/ui/dialog/dialog-trigger.svelte +0 -11
  155. package/src/components/ui/dialog/dialog.svelte +0 -7
  156. package/src/components/ui/dialog/index.ts +0 -34
  157. package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -43
  158. package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -35
  159. package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -36
  160. package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -10
  161. package/src/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -27
  162. package/src/components/ui/dropdown-menu/dropdown-menu.svelte +0 -45
  163. package/src/components/ui/dropdown-menu/index.ts +0 -21
  164. package/src/components/ui/input/index.ts +0 -7
  165. package/src/components/ui/input/input.svelte +0 -48
  166. package/src/components/ui/label/index.ts +0 -1
  167. package/src/components/ui/label/label.svelte +0 -18
  168. package/src/components/ui/pagination/index.ts +0 -7
  169. package/src/components/ui/pagination/pagination-content.svelte +0 -11
  170. package/src/components/ui/pagination/pagination-ellipsis.svelte +0 -12
  171. package/src/components/ui/pagination/pagination-item.svelte +0 -11
  172. package/src/components/ui/pagination/pagination-link.svelte +0 -26
  173. package/src/components/ui/pagination/pagination-next.svelte +0 -22
  174. package/src/components/ui/pagination/pagination-previous.svelte +0 -22
  175. package/src/components/ui/pagination/pagination.svelte +0 -11
  176. package/src/components/ui/popover/index.ts +0 -12
  177. package/src/components/ui/popover/popover-content.svelte +0 -25
  178. package/src/components/ui/progress/index.ts +0 -1
  179. package/src/components/ui/progress/progress.svelte +0 -22
  180. package/src/components/ui/scroll-area/index.ts +0 -1
  181. package/src/components/ui/scroll-area/scroll-area.svelte +0 -20
  182. package/src/components/ui/select/index.ts +0 -2
  183. package/src/components/ui/select/select.svelte +0 -36
  184. package/src/components/ui/separator/index.ts +0 -7
  185. package/src/components/ui/separator/separator.svelte +0 -23
  186. package/src/components/ui/sheet/index.ts +0 -16
  187. package/src/components/ui/sheet/sheet-content.svelte +0 -28
  188. package/src/components/ui/sheet/sheet-description.svelte +0 -22
  189. package/src/components/ui/sheet/sheet-footer.svelte +0 -22
  190. package/src/components/ui/sheet/sheet-header.svelte +0 -22
  191. package/src/components/ui/sheet/sheet-title.svelte +0 -22
  192. package/src/components/ui/sheet/sheet.svelte +0 -78
  193. package/src/components/ui/skeleton/index.ts +0 -2
  194. package/src/components/ui/skeleton/skeleton.svelte +0 -21
  195. package/src/components/ui/switch/index.ts +0 -2
  196. package/src/components/ui/switch/switch.svelte +0 -49
  197. package/src/components/ui/table/index.ts +0 -28
  198. package/src/components/ui/table/table-body.svelte +0 -15
  199. package/src/components/ui/table/table-caption.svelte +0 -20
  200. package/src/components/ui/table/table-cell.svelte +0 -15
  201. package/src/components/ui/table/table-footer.svelte +0 -20
  202. package/src/components/ui/table/table-head.svelte +0 -15
  203. package/src/components/ui/table/table-header.svelte +0 -20
  204. package/src/components/ui/table/table-row.svelte +0 -15
  205. package/src/components/ui/table/table.svelte +0 -17
  206. package/src/components/ui/tabs/index.ts +0 -15
  207. package/src/components/ui/tabs/tabs-content.svelte +0 -30
  208. package/src/components/ui/tabs/tabs-list.svelte +0 -26
  209. package/src/components/ui/tabs/tabs-trigger.svelte +0 -37
  210. package/src/components/ui/tabs/tabs.svelte +0 -27
  211. package/src/components/ui/textarea/index.ts +0 -2
  212. package/src/components/ui/textarea/textarea.svelte +0 -24
  213. package/src/components/ui/tooltip/index.ts +0 -19
  214. package/src/components/ui/tooltip/tooltip-content.svelte +0 -52
  215. package/src/components/ui/tooltip/tooltip-portal.svelte +0 -7
  216. package/src/components/ui/tooltip/tooltip-provider.svelte +0 -7
  217. package/src/components/ui/tooltip/tooltip-trigger.svelte +0 -7
  218. package/src/components/ui/tooltip/tooltip.svelte +0 -10
  219. package/src/editor-config.svelte.ts +0 -23
  220. package/src/index.ts +0 -155
  221. package/src/markdown-deps.d.ts +0 -21
  222. package/src/router-state.svelte.ts +0 -65
  223. package/src/types.ts +0 -33
  224. package/src/utils.ts +0 -28
@@ -1,149 +0,0 @@
1
- <script lang="ts">
2
- import { fly, scale } from 'svelte/transition';
3
- import { getResources } from '@svadmin/core';
4
- import { getTheme, getColorTheme } from '@svadmin/core';
5
- import { getLocale, t } from '@svadmin/core/i18n';
6
- import { currentPath } from '@svadmin/core/router';
7
- import { Button } from './ui/button/index.js';
8
- import TooltipButton from './TooltipButton.svelte';
9
- import * as Tabs from './ui/tabs/index.js';
10
- import { Badge } from './ui/badge/index.js';
11
- import { ScrollArea } from './ui/scroll-area/index.js';
12
- import { Separator } from './ui/separator/index.js';
13
- import { X, Bug, ChevronDown, ChevronUp, Wand2 } from '@lucide/svelte';
14
- import InferencerPanel from './InferencerPanel.svelte';
15
-
16
- let visible = $state(false);
17
- let collapsed = $state(false);
18
-
19
- function toggle() {
20
- visible = !visible;
21
- }
22
-
23
- function handleKeydown(e: KeyboardEvent) {
24
- if (e.ctrlKey && e.shiftKey && e.key === 'D') {
25
- e.preventDefault();
26
- toggle();
27
- }
28
- }
29
-
30
- const resources = $derived.by(() => { try { return getResources(); } catch { return []; } });
31
- const path = $derived(currentPath());
32
- const theme = $derived(getTheme());
33
- const colorTheme = $derived(getColorTheme());
34
- const locale = $derived(getLocale());
35
-
36
- // Auto-trace state changes in dev mode via Svelte 5 $inspect
37
- if ((import.meta as any).env?.DEV) {
38
- $inspect({ path, theme, colorTheme, locale, resourceCount: resources.length });
39
- }
40
- </script>
41
-
42
- <svelte:window onkeydown={handleKeydown} />
43
-
44
- {#if (import.meta as any).env?.DEV}
45
- {#if visible}
46
- <div
47
- class="fixed bottom-0 right-4 z-[9999] w-[420px] max-w-[95vw] rounded-t-xl border border-b-0 bg-card shadow-2xl text-[0.8125rem] overflow-hidden"
48
- class:w-auto={collapsed} class:min-w-[200px]={collapsed}
49
- transition:fly={{ y: 400, duration: 300 }}
50
- >
51
- <!-- Header -->
52
- <div class="flex items-center justify-between px-3 py-2 bg-muted border-b">
53
- <div class="flex items-center gap-1.5 font-semibold text-xs uppercase tracking-wider text-foreground">
54
- <Bug class="h-4 w-4" />
55
- <span>svadmin DevTools</span>
56
- </div>
57
- <div class="flex gap-1">
58
- <TooltipButton tooltip={collapsed ? t('common.expand') : t('common.collapse')} variant="ghost" size="icon" class="h-6 w-6" onclick={() => collapsed = !collapsed}>
59
- {#if collapsed}
60
- <ChevronUp class="h-3.5 w-3.5" />
61
- {:else}
62
- <ChevronDown class="h-3.5 w-3.5" />
63
- {/if}
64
- </TooltipButton>
65
- <TooltipButton tooltip={t('common.close')} variant="ghost" size="icon" class="h-6 w-6" onclick={toggle}>
66
- <X class="h-3.5 w-3.5" />
67
- </TooltipButton>
68
- </div>
69
- </div>
70
-
71
- {#if !collapsed}
72
- <Tabs.Root value="state" class="w-full">
73
- <Tabs.List class="grid w-full grid-cols-2 h-8 rounded-none border-b">
74
- <Tabs.Trigger value="state" class="text-xs data-[state=active]:shadow-none rounded-none border-b-2 border-transparent data-[state=active]:border-primary">State</Tabs.Trigger>
75
- <Tabs.Trigger value="inferencer" class="text-xs data-[state=active]:shadow-none rounded-none border-b-2 border-transparent data-[state=active]:border-primary">
76
- <Wand2 class="h-3 w-3 mr-1" /> Inferencer
77
- </Tabs.Trigger>
78
- </Tabs.List>
79
- <Tabs.Content value="state" class="p-0">
80
- <ScrollArea class="max-h-[400px]">
81
- <div class="p-2 space-y-1">
82
- <!-- Router -->
83
- <div class="py-1">
84
- <h4 class="text-[0.6875rem] font-bold uppercase tracking-widest text-muted-foreground mb-1 px-1">Router</h4>
85
- <div class="flex items-center justify-between px-1 py-0.5 rounded hover:bg-muted/50">
86
- <span class="text-xs text-foreground">Path</span>
87
- <Badge variant="secondary" class="font-mono text-[0.6875rem]">{path}</Badge>
88
- </div>
89
- </div>
90
-
91
- <Separator />
92
-
93
- <!-- Theme -->
94
- <div class="py-1">
95
- <h4 class="text-[0.6875rem] font-bold uppercase tracking-widest text-muted-foreground mb-1 px-1">Theme</h4>
96
- <div class="flex items-center justify-between px-1 py-0.5 rounded hover:bg-muted/50">
97
- <span class="text-xs text-foreground">Mode</span>
98
- <Badge variant="secondary" class="font-mono text-[0.6875rem]">{theme}</Badge>
99
- </div>
100
- <div class="flex items-center justify-between px-1 py-0.5 rounded hover:bg-muted/50">
101
- <span class="text-xs text-foreground">Color</span>
102
- <Badge variant="secondary" class="font-mono text-[0.6875rem]">{colorTheme}</Badge>
103
- </div>
104
- </div>
105
-
106
- <Separator />
107
-
108
- <!-- i18n -->
109
- <div class="py-1">
110
- <h4 class="text-[0.6875rem] font-bold uppercase tracking-widest text-muted-foreground mb-1 px-1">i18n</h4>
111
- <div class="flex items-center justify-between px-1 py-0.5 rounded hover:bg-muted/50">
112
- <span class="text-xs text-foreground">Locale</span>
113
- <Badge variant="secondary" class="font-mono text-[0.6875rem]">{locale}</Badge>
114
- </div>
115
- </div>
116
-
117
- <Separator />
118
-
119
- <!-- Resources -->
120
- <div class="py-1">
121
- <h4 class="text-[0.6875rem] font-bold uppercase tracking-widest text-muted-foreground mb-1 px-1">Resources ({resources.length})</h4>
122
- {#each resources as r}
123
- <div class="flex items-center justify-between px-1 py-0.5 rounded hover:bg-muted/50">
124
- <span class="text-xs text-foreground">{r.name}</span>
125
- <Badge variant="outline" class="font-mono text-[0.6875rem]">{r.fields.length} fields</Badge>
126
- </div>
127
- {/each}
128
- </div>
129
- </div>
130
- </ScrollArea>
131
- </Tabs.Content>
132
- <Tabs.Content value="inferencer" class="p-0">
133
- <InferencerPanel />
134
- </Tabs.Content>
135
- </Tabs.Root>
136
- {/if}
137
- </div>
138
- {:else}
139
- <TooltipButton
140
- tooltip={t('devtools.title')}
141
- variant="default"
142
- size="icon"
143
- class="fixed bottom-4 right-4 z-[9999] h-9 w-9 rounded-full shadow-lg opacity-60 hover:opacity-100 hover:scale-110 transition-all"
144
- onclick={toggle}
145
- >
146
- <Bug class="h-4 w-4" />
147
- </TooltipButton>
148
- {/if}
149
- {/if}
@@ -1,86 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { GridModule } from '../types.js';
4
-
5
- let {
6
- modules = $bindable<GridModule[]>([]),
7
- onOrderSave,
8
- renderItem,
9
- class: className = '',
10
- columns = 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
11
- gap = 'gap-4',
12
- }: {
13
- modules?: GridModule[];
14
- onOrderSave?: (orderedIds: string[]) => void;
15
- renderItem: Snippet<[{ module: GridModule; index: number; dragging: boolean }]>;
16
- class?: string;
17
- columns?: string;
18
- gap?: string;
19
- } = $props();
20
-
21
- let draggingId = $state<string | null>(null);
22
- let dragOverId = $state<string | null>(null);
23
-
24
- function handleDragStart(e: DragEvent, id: string) {
25
- draggingId = id;
26
- if (e.dataTransfer) {
27
- e.dataTransfer.effectAllowed = 'move';
28
- e.dataTransfer.setData('text/plain', id);
29
- }
30
- }
31
-
32
- function handleDragOver(e: DragEvent, id: string) {
33
- e.preventDefault();
34
- if (draggingId && draggingId !== id) {
35
- dragOverId = id;
36
- }
37
- }
38
-
39
- function handleDrop(e: DragEvent, targetId: string) {
40
- e.preventDefault();
41
- if (!draggingId || draggingId === targetId) {
42
- dragOverId = null;
43
- return;
44
- }
45
-
46
- const sourceIdx = modules.findIndex(m => m.id === draggingId);
47
- const targetIdx = modules.findIndex(m => m.id === targetId);
48
-
49
- if (sourceIdx === -1 || targetIdx === -1) {
50
- dragOverId = null;
51
- return;
52
- }
53
-
54
- const newModules = [...modules];
55
- const [dragged] = newModules.splice(sourceIdx, 1);
56
- newModules.splice(targetIdx, 0, dragged);
57
-
58
- modules = newModules;
59
- dragOverId = null;
60
- onOrderSave?.(modules.map(m => m.id));
61
- }
62
-
63
- function handleDragEnd() {
64
- draggingId = null;
65
- dragOverId = null;
66
- }
67
- </script>
68
-
69
- <div class="grid {columns} {gap} {className}">
70
- {#each modules as mod, i (mod.id)}
71
- <!-- svelte-ignore a11y_no_static_element_interactions -->
72
- <div
73
- draggable="true"
74
- ondragstart={(e) => handleDragStart(e, mod.id)}
75
- ondragover={(e) => handleDragOver(e, mod.id)}
76
- ondrop={(e) => handleDrop(e, mod.id)}
77
- ondragend={handleDragEnd}
78
- ondragleave={() => { if (dragOverId === mod.id) dragOverId = null; }}
79
- class="transition-all duration-200
80
- {draggingId === mod.id ? 'opacity-40 scale-[0.97] cursor-grabbing' : 'cursor-grab'}
81
- {dragOverId === mod.id ? 'ring-2 ring-primary/40 ring-offset-2 ring-offset-background rounded-lg scale-[1.02]' : ''}"
82
- >
83
- {@render renderItem({ module: mod, index: i, dragging: draggingId === mod.id })}
84
- </div>
85
- {/each}
86
- </div>
@@ -1,112 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * DraggableHeader — Wraps table header cells with HTML5 Drag and Drop
4
- * to enable column reorder. Persists order to localStorage.
5
- *
6
- * Usage:
7
- * <DraggableHeader columns={columns} resourceName="posts" onReorder={handleReorder}>
8
- * {#snippet header(column, index)}
9
- * <th>...</th>
10
- * {/snippet}
11
- * </DraggableHeader>
12
- */
13
- import type { Snippet } from 'svelte';
14
-
15
- interface Column {
16
- id: string;
17
- [key: string]: unknown;
18
- }
19
-
20
- interface Props {
21
- columns: Column[];
22
- resourceName: string;
23
- onReorder: (newOrder: Column[]) => void;
24
- header: Snippet<[Column, number, Record<string, any>]>;
25
- }
26
-
27
- let { columns, resourceName, onReorder, header }: Props = $props();
28
-
29
- let dragIndex = $state<number | null>(null);
30
- let dropIndex = $state<number | null>(null);
31
-
32
- // Restore saved order from localStorage
33
- $effect(() => {
34
- const storageKey = `svadmin-colorder-${resourceName}`;
35
- if (typeof localStorage === 'undefined') return;
36
- try {
37
- const saved = localStorage.getItem(storageKey);
38
- if (saved) {
39
- const savedOrder: string[] = JSON.parse(saved);
40
- const reordered = savedOrder
41
- .map(id => columns.find(c => c.id === id))
42
- .filter((c): c is Column => c !== undefined);
43
- // Add any new columns not in saved order
44
- const remaining = columns.filter(c => !savedOrder.includes(c.id));
45
- if (reordered.length > 0) {
46
- onReorder([...reordered, ...remaining]);
47
- }
48
- }
49
- } catch { /* ignore */ }
50
- });
51
-
52
- function handleDragStart(e: DragEvent, index: number) {
53
- dragIndex = index;
54
- if (e.dataTransfer) {
55
- e.dataTransfer.effectAllowed = 'move';
56
- e.dataTransfer.setData('text/plain', String(index));
57
- }
58
- }
59
-
60
- function handleDragOver(e: DragEvent, index: number) {
61
- e.preventDefault();
62
- dropIndex = index;
63
- if (e.dataTransfer) {
64
- e.dataTransfer.dropEffect = 'move';
65
- }
66
- }
67
-
68
- function handleDrop(e: DragEvent, index: number) {
69
- e.preventDefault();
70
- if (dragIndex === null || dragIndex === index) {
71
- dragIndex = null;
72
- dropIndex = null;
73
- return;
74
- }
75
-
76
- const newColumns = [...columns];
77
- const [moved] = newColumns.splice(dragIndex, 1);
78
- newColumns.splice(index, 0, moved);
79
-
80
- // Persist to localStorage
81
- const storageKey = `svadmin-colorder-${resourceName}`;
82
- if (typeof localStorage !== 'undefined') {
83
- try {
84
- localStorage.setItem(storageKey, JSON.stringify(newColumns.map(c => c.id)));
85
- } catch { /* ignore */ }
86
- }
87
-
88
- onReorder(newColumns);
89
- dragIndex = null;
90
- dropIndex = null;
91
- }
92
-
93
- function handleDragEnd() {
94
- dragIndex = null;
95
- dropIndex = null;
96
- }
97
- </script>
98
-
99
- <tr class="hover:bg-muted/50 data-[state=selected]:bg-muted transition-colors bg-muted/50">
100
- {#each columns as column, index}
101
- {@render header(column, index, {
102
- draggable: true,
103
- ondragstart: (e: DragEvent) => handleDragStart(e, index),
104
- ondragover: (e: DragEvent) => handleDragOver(e, index),
105
- ondrop: (e: DragEvent) => handleDrop(e, index),
106
- ondragend: handleDragEnd,
107
- 'data-dragging': dragIndex === index,
108
- 'data-drop-target': dropIndex === index && dropIndex !== dragIndex,
109
- class: `cursor-grab active:cursor-grabbing select-none transition-opacity ${dragIndex === index ? 'opacity-50' : ''} ${dropIndex === index && dropIndex !== dragIndex ? 'border-l-2 border-primary' : ''}`
110
- })}
111
- {/each}
112
- </tr>
@@ -1,35 +0,0 @@
1
- <script lang="ts">
2
- import { getResource } from '@svadmin/core';
3
- import { t } from '@svadmin/core/i18n';
4
- import * as Sheet from './ui/sheet/index.js';
5
- import AutoForm from './AutoForm.svelte';
6
-
7
- let { resourceName, mode = 'create', id, open = $bindable(false), side = 'right', onSuccess } = $props<{
8
- resourceName: string;
9
- mode?: 'create' | 'edit';
10
- id?: string | number;
11
- open: boolean;
12
- side?: 'left' | 'right';
13
- onSuccess?: () => void;
14
- }>();
15
-
16
- const resource = $derived(getResource(resourceName));
17
-
18
- function handleClose() {
19
- open = false;
20
- onSuccess?.();
21
- }
22
- </script>
23
-
24
- <Sheet.Root bind:open {side}>
25
- <Sheet.Content>
26
- <Sheet.Header>
27
- <Sheet.Title>
28
- {mode === 'create' ? `${t('common.create')}${resource.label}` : `${t('common.edit')}${resource.label}`}
29
- </Sheet.Title>
30
- </Sheet.Header>
31
- <div class="flex-1 overflow-y-auto">
32
- <AutoForm {resourceName} {mode} {id} />
33
- </div>
34
- </Sheet.Content>
35
- </Sheet.Root>
@@ -1,52 +0,0 @@
1
- <script lang="ts">
2
- import { getResource, useDelete } from '@svadmin/core';
3
- import { navigate } from '@svadmin/core/router';
4
- import { t } from '@svadmin/core/i18n';
5
- import type { Snippet } from 'svelte';
6
- import PageHeader from './PageHeader.svelte';
7
- import AutoForm from './AutoForm.svelte';
8
- import ListButton from './buttons/ListButton.svelte';
9
- import ShowButton from './buttons/ShowButton.svelte';
10
- import RefreshButton from './buttons/RefreshButton.svelte';
11
- import DeleteButton from './buttons/DeleteButton.svelte';
12
-
13
- interface Props {
14
- resourceName: string;
15
- id: string | number;
16
- title?: string;
17
- canDelete?: boolean;
18
- headerActions?: Snippet;
19
- class?: string;
20
- }
21
-
22
- let {
23
- resourceName,
24
- id,
25
- title,
26
- canDelete,
27
- headerActions,
28
- class: className = '',
29
- }: Props = $props();
30
-
31
- const resource = $derived(getResource(resourceName));
32
- const pageTitle = $derived(title ?? `${t('common.edit')} ${resource.label} #${id}`);
33
- const showDelete = $derived(canDelete ?? resource.canDelete !== false);
34
- </script>
35
-
36
- <div class="space-y-6 {className}">
37
- <PageHeader title={pageTitle}>
38
- {#snippet actions()}
39
- <ListButton resource={resourceName} hideText />
40
- <ShowButton resource={resourceName} recordItemId={id} hideText />
41
- <RefreshButton resource={resourceName} hideText />
42
- {#if showDelete !== false}
43
- <DeleteButton resource={resourceName} recordItemId={id} hideText onSuccess={() => navigate(`/${resourceName}`)} />
44
- {/if}
45
- {#if headerActions}
46
- {@render headerActions()}
47
- {/if}
48
- {/snippet}
49
- </PageHeader>
50
-
51
- <AutoForm {resourceName} mode="edit" {id} />
52
- </div>
@@ -1,31 +0,0 @@
1
- <script lang="ts">
2
- import { fade, scale } from 'svelte/transition';
3
- import { PackageOpen } from '@lucide/svelte';
4
- import { t } from '@svadmin/core';
5
-
6
- let {
7
- title = t('empty.title'),
8
- description = t('empty.description'),
9
- children,
10
- } = $props<{
11
- title?: string;
12
- description?: string;
13
- children?: import('svelte').Snippet;
14
- }>();
15
- </script>
16
-
17
- <div
18
- class="flex flex-col items-center justify-center p-8 text-center min-h-[300px] bg-card/50 rounded-lg shadow-sm"
19
- in:scale={{ start: 0.95, duration: 250, opacity: 0 }}
20
- >
21
- <div class="h-20 w-20 rounded-full bg-muted flex items-center justify-center mb-4">
22
- <PackageOpen class="h-10 w-10 text-muted-foreground" />
23
- </div>
24
- <h3 class="text-lg font-semibold tracking-tight">{title}</h3>
25
- <p class="text-sm text-muted-foreground mt-2 max-w-sm">{description}</p>
26
- {#if children}
27
- <div class="mt-6">
28
- {@render children()}
29
- </div>
30
- {/if}
31
- </div>
@@ -1,49 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import { AlertTriangle } from '@lucide/svelte';
4
- import { Button } from './ui/button/index.js';
5
- import * as Alert from './ui/alert/index.js';
6
- import { t } from '@svadmin/core/i18n';
7
-
8
- let {
9
- children,
10
- fallback,
11
- }: {
12
- children: Snippet;
13
- /** Optional custom error UI snippet */
14
- fallback?: Snippet<[{ error: Error; reset: () => void }]>;
15
- } = $props();
16
-
17
- function handleError(error: unknown) {
18
- console.error('[svadmin] Uncaught error:', error);
19
- }
20
- </script>
21
-
22
- <svelte:boundary onerror={handleError}>
23
- {@render children()}
24
-
25
- {#snippet failed(error, reset)}
26
- {#if fallback}
27
- {@render fallback({ error: error instanceof Error ? error : new Error(String(error)), reset })}
28
- {:else}
29
- <div class="flex h-screen items-center justify-center bg-background">
30
- <div class="max-w-md w-full px-4">
31
- <Alert.Root variant="destructive" class="space-y-4">
32
- <div class="flex items-start gap-3">
33
- <AlertTriangle class="h-5 w-5 mt-0.5 shrink-0" />
34
- <div class="space-y-2">
35
- <Alert.Title>{t('common.error')}</Alert.Title>
36
- <Alert.Description class="text-sm">
37
- {error instanceof Error ? error.message : String(error)}
38
- </Alert.Description>
39
- </div>
40
- </div>
41
- <Button variant="outline" size="sm" onclick={reset} class="w-full">
42
- {t('common.retry')}
43
- </Button>
44
- </Alert.Root>
45
- </div>
46
- </div>
47
- {/if}
48
- {/snippet}
49
- </svelte:boundary>
@@ -1,36 +0,0 @@
1
- <script lang="ts">
2
- import { AlertTriangle, RefreshCw } from '@lucide/svelte';
3
- import { t } from '@svadmin/core';
4
- import { Button } from './ui/button';
5
- import * as Alert from './ui/alert/index.js';
6
-
7
- let {
8
- error,
9
- title = t('error.title'),
10
- description = t('error.description'),
11
- retry,
12
- } = $props<{
13
- error?: Error | null;
14
- title?: string;
15
- description?: string;
16
- retry?: () => void;
17
- }>();
18
- </script>
19
-
20
- <div class="flex flex-col items-center justify-center p-8 text-center min-h-[300px]">
21
- <Alert.Root variant="destructive" class="max-w-md text-left">
22
- <AlertTriangle class="h-5 w-5" />
23
- <Alert.Title>{title}</Alert.Title>
24
- <Alert.Description>
25
- {error?.message || description}
26
- </Alert.Description>
27
- {#if retry}
28
- <div class="mt-4">
29
- <Button variant="outline" size="sm" onclick={retry}>
30
- <RefreshCw class="h-3 w-3" data-icon="inline-start" />
31
- {t('buttons.retry')}
32
- </Button>
33
- </div>
34
- {/if}
35
- </Alert.Root>
36
- </div>