@svadmin/ui 0.29.0 → 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 -519
  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,32 +0,0 @@
1
- <script lang="ts">
2
- import { getAdminOptions } from '@svadmin/core';
3
-
4
- let {
5
- collapsed = false,
6
- icon,
7
- text,
8
- wrapperStyles = '',
9
- } = $props<{
10
- collapsed?: boolean;
11
- icon?: string;
12
- text?: string;
13
- wrapperStyles?: string;
14
- }>();
15
-
16
- const adminOptions = getAdminOptions();
17
- const titleText = $derived(text ?? adminOptions.title?.text ?? 'Admin');
18
- const titleIcon = $derived(icon ?? adminOptions.title?.icon);
19
- </script>
20
-
21
- <div class="flex items-center gap-2 {wrapperStyles}">
22
- {#if titleIcon}
23
- <img src={titleIcon} alt="" class="h-6 w-6 shrink-0" />
24
- {:else}
25
- <div class="flex h-7 w-7 items-center justify-center rounded-lg bg-primary text-primary-foreground text-sm font-bold">
26
- {titleText.charAt(0).toUpperCase()}
27
- </div>
28
- {/if}
29
- {#if !collapsed}
30
- <span class="text-lg font-semibold text-foreground truncate">{titleText}</span>
31
- {/if}
32
- </div>
@@ -1,46 +0,0 @@
1
- <script lang="ts">
2
- import { Toaster, toast as sonner } from 'sonner-svelte';
3
- import { getResolvedTheme, getToastQueue, consumeToastQueue, getPromiseQueue, consumePromiseQueue } from '@svadmin/core';
4
-
5
- const theme = $derived(getResolvedTheme() === 'dark' ? 'dark' : 'light');
6
-
7
- $effect(() => {
8
- const queue = getToastQueue();
9
- if (queue.length > 0) {
10
- for (const t of queue) {
11
- switch (t.type) {
12
- case 'success': sonner.success(t.message, { duration: t.duration }); break;
13
- case 'error': sonner.error(t.message, { duration: t.duration }); break;
14
- case 'warning': sonner.warning(t.message, { duration: t.duration }); break;
15
- case 'info': sonner.info(t.message, { duration: t.duration }); break;
16
- }
17
- }
18
- consumeToastQueue();
19
- }
20
- });
21
-
22
- $effect(() => {
23
- const pQueue = getPromiseQueue();
24
- if (pQueue.length > 0) {
25
- for (const p of pQueue) {
26
- sonner.promise(p.promise, p.opts);
27
- }
28
- consumePromiseQueue();
29
- }
30
- });
31
-
32
- const toasterProps = $derived({
33
- position: "top-right",
34
- richColors: true,
35
- closeButton: true,
36
- expand: true,
37
- theme,
38
- toastOptions: {
39
- classes: {
40
- toast: 'font-sans',
41
- },
42
- }
43
- } as any);
44
- </script>
45
-
46
- <Toaster {...toasterProps} />
@@ -1,42 +0,0 @@
1
- <script lang="ts">
2
- import * as Tooltip from './ui/tooltip/index.js';
3
- import { Button } from './ui/button/index.js';
4
- import type { Snippet } from 'svelte';
5
- import type { HTMLButtonAttributes } from 'svelte/elements';
6
-
7
- interface Props extends Omit<HTMLButtonAttributes, 'class' | 'children'> {
8
- tooltip: string;
9
- variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
10
- size?: 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm';
11
- side?: 'top' | 'right' | 'bottom' | 'left';
12
- class?: string;
13
- onclick?: (e: MouseEvent) => void;
14
- children: Snippet;
15
- }
16
-
17
- let {
18
- tooltip,
19
- variant = 'ghost',
20
- size = 'icon',
21
- side = 'top',
22
- class: className = '',
23
- onclick,
24
- disabled = false,
25
- type = 'button',
26
- tabindex,
27
- children,
28
- ...restProps
29
- }: Props = $props();
30
- </script>
31
-
32
- <Tooltip.Root>
33
- <Tooltip.Trigger>
34
- {#snippet child({ props })}
35
- {@const buttonProps = { ...props, ...restProps, variant, size, type, class: className, 'aria-label': restProps['aria-label'] ?? tooltip, onclick, disabled, tabindex } as any}
36
- <Button {...buttonProps}>
37
- {@render children()}
38
- </Button>
39
- {/snippet}
40
- </Tooltip.Trigger>
41
- <Tooltip.Content {side}>{tooltip}</Tooltip.Content>
42
- </Tooltip.Root>
@@ -1,69 +0,0 @@
1
- <script lang="ts">
2
- import { Button } from './ui/button/index.js';
3
- import { Progress } from './ui/progress/index.js';
4
- import { t } from '@svadmin/core/i18n';
5
- import { slide } from 'svelte/transition';
6
- import { X, Undo2 } from '@lucide/svelte';
7
-
8
- let { message, duration = 5000, onUndo, onTimeout } = $props<{
9
- message: string;
10
- duration?: number;
11
- onUndo: () => void;
12
- onTimeout: () => void;
13
- }>();
14
-
15
- let remaining = $state(0);
16
- let dismissed = $state(false);
17
-
18
- // Initialize remaining from prop
19
- $effect.pre(() => {
20
- remaining = duration;
21
- });
22
-
23
- $effect(() => {
24
- const interval = setInterval(() => {
25
- remaining -= 100;
26
- if (remaining <= 0) {
27
- clearInterval(interval);
28
- if (!dismissed) {
29
- dismissed = true;
30
- onTimeout();
31
- }
32
- }
33
- }, 100);
34
- return () => clearInterval(interval);
35
- });
36
-
37
- function handleUndo() {
38
- dismissed = true;
39
- onUndo();
40
- }
41
-
42
- function handleDismiss() {
43
- dismissed = true;
44
- onTimeout();
45
- }
46
-
47
- const progressValue = $derived(remaining / duration * 100);
48
- </script>
49
-
50
- {#if !dismissed}
51
- <div
52
- class="fixed bottom-6 left-1/2 -translate-x-1/2 z-[100] min-w-80 max-w-lg rounded-lg border bg-card shadow-lg overflow-hidden"
53
- transition:slide={{ duration: 250 }}
54
- >
55
- <div class="flex items-center justify-between px-4 py-3 gap-3">
56
- <p class="text-sm text-foreground">{message}</p>
57
- <div class="flex items-center gap-1 flex-shrink-0">
58
- <Button variant="ghost" size="sm" onclick={handleUndo} class="font-semibold text-primary">
59
- <Undo2 class="h-3.5 w-3.5 mr-1" />
60
- {t('common.undo')}
61
- </Button>
62
- <Button variant="ghost" size="icon" class="h-7 w-7" onclick={handleDismiss}>
63
- <X class="h-3.5 w-3.5" />
64
- </Button>
65
- </div>
66
- </div>
67
- <Progress value={progressValue} class="h-1 rounded-none" />
68
- </div>
69
- {/if}
@@ -1,89 +0,0 @@
1
- <script lang="ts">
2
- import { useUpdatePassword } from '@svadmin/core';
3
- import { t } from '@svadmin/core/i18n';
4
- import { navigate } from '@svadmin/core/router';
5
- import { Button } from './ui/button/index.js';
6
- import * as Card from './ui/card/index.js';
7
- import * as Alert from './ui/alert/index.js';
8
- import PasswordInput from './PasswordInput.svelte';
9
- import { ShieldCheck, Loader2, AlertCircle } from '@lucide/svelte';
10
-
11
- let { title = 'Admin' } = $props<{
12
- title?: string;
13
- }>();
14
-
15
- const updatePw = useUpdatePassword();
16
-
17
- let password = $state('');
18
- let confirmPassword = $state('');
19
- let error = $state('');
20
-
21
- async function handleSubmit(e: SubmitEvent) {
22
- e.preventDefault();
23
- error = '';
24
-
25
- if (!password) { error = t('auth.passwordRequired'); return; }
26
- if (password !== confirmPassword) { error = t('auth.passwordMismatch'); return; }
27
-
28
- const result = await updatePw.mutate({ password, confirmPassword });
29
- if (!result.success) {
30
- error = result.error?.message ?? t('common.operationFailed');
31
- }
32
- }
33
- </script>
34
-
35
- <div class="min-h-screen flex items-center justify-center bg-background p-4">
36
- <div class="w-full max-w-[380px]">
37
- <Card.Card>
38
- <Card.CardHeader class="text-center pb-2">
39
- <div class="inline-flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10 text-primary mx-auto mb-3">
40
- <ShieldCheck class="h-5 w-5" />
41
- </div>
42
- <Card.CardTitle class="text-xl">{t('auth.resetPassword')}</Card.CardTitle>
43
- <p class="text-sm text-muted-foreground">{t('auth.resetPasswordDescription')}</p>
44
- </Card.CardHeader>
45
- <Card.CardContent>
46
- <form onsubmit={handleSubmit} class="space-y-4">
47
- {#if error}
48
- <Alert.Root variant="destructive">
49
- <AlertCircle class="h-4 w-4" />
50
- <Alert.Description>{error}</Alert.Description>
51
- </Alert.Root>
52
- {/if}
53
-
54
- <PasswordInput
55
- id="new-password"
56
- label={t('auth.password')}
57
- bind:value={password}
58
- autocomplete="new-password"
59
- showStrength
60
- />
61
-
62
- <PasswordInput
63
- id="confirm-password"
64
- label={t('auth.confirmPassword')}
65
- bind:value={confirmPassword}
66
- autocomplete="new-password"
67
- />
68
-
69
- <Button type="submit" class="w-full" disabled={updatePw.isLoading}>
70
- {#if updatePw.isLoading}
71
- <Loader2 class="h-4 w-4 animate-spin mr-2" />
72
- {/if}
73
- {t('auth.resetPassword')}
74
- </Button>
75
-
76
- <div class="flex items-center justify-center mt-2">
77
- <Button variant="link" class="text-sm h-auto p-0 font-medium" onclick={() => navigate('/login')}>
78
- {t('auth.backToLogin')}
79
- </Button>
80
- </div>
81
- </form>
82
- </Card.CardContent>
83
- </Card.Card>
84
-
85
- <p class="text-xs text-muted-foreground mt-4 text-center opacity-60">
86
- Powered by {title}
87
- </p>
88
- </div>
89
- </div>
@@ -1,76 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * VirtualTable — A lightweight virtual scrolling wrapper for large datasets.
4
- * Uses IntersectionObserver-based approach instead of a heavy dependency.
5
- *
6
- * Usage:
7
- * <VirtualTable items={rows} rowHeight={40} containerHeight={500}>
8
- * {#snippet row(item, index)}
9
- * <tr>...</tr>
10
- * {/snippet}
11
- * </VirtualTable>
12
- */
13
- import type { Snippet } from 'svelte';
14
-
15
- interface Props<T> {
16
- items: T[];
17
- /** Estimated row height in pixels */
18
- rowHeight?: number;
19
- /** Container height in pixels */
20
- containerHeight?: number;
21
- /** Number of extra rows to render above/below visible area */
22
- overscan?: number;
23
- /** Row rendering snippet */
24
- row: Snippet<[T, number]>;
25
- class?: string;
26
- }
27
-
28
- let {
29
- items,
30
- rowHeight = 40,
31
- containerHeight = 500,
32
- overscan = 5,
33
- row,
34
- class: className = '',
35
- }: Props<unknown> = $props();
36
-
37
- let scrollTop = $state(0);
38
- let containerRef = $state<HTMLDivElement | null>(null);
39
-
40
- const totalHeight = $derived(items.length * rowHeight);
41
-
42
- const visibleRange = $derived.by(() => {
43
- const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
44
- const visibleCount = Math.ceil(containerHeight / rowHeight);
45
- const end = Math.min(items.length - 1, start + visibleCount + overscan * 2);
46
- return { start, end };
47
- });
48
-
49
- const visibleItems = $derived(
50
- items.slice(visibleRange.start, visibleRange.end + 1).map((item, i) => ({
51
- item,
52
- index: visibleRange.start + i,
53
- offsetY: (visibleRange.start + i) * rowHeight,
54
- }))
55
- );
56
-
57
- function handleScroll(e: Event) {
58
- const target = e.target as HTMLDivElement;
59
- scrollTop = target.scrollTop;
60
- }
61
- </script>
62
-
63
- <div
64
- bind:this={containerRef}
65
- class="overflow-auto {className}"
66
- style="height: {containerHeight}px;"
67
- onscroll={handleScroll}
68
- >
69
- <div style="position: relative; height: {totalHeight}px; width: 100%;">
70
- {#each visibleItems as { item, index, offsetY } (index)}
71
- <div style="position: absolute; top: {offsetY}px; left: 0; right: 0; height: {rowHeight}px;">
72
- {@render row(item, index)}
73
- </div>
74
- {/each}
75
- </div>
76
- </div>
@@ -1,120 +0,0 @@
1
- <script lang="ts">
2
- import { Mic, MicOff, Loader2 } from '@lucide/svelte';
3
- import TooltipButton from './TooltipButton.svelte';
4
-
5
- // Web Speech API type declarations
6
- interface SpeechRecognitionEvent extends Event {
7
- results: SpeechRecognitionResultList;
8
- }
9
- interface SpeechRecognitionErrorEvent extends Event {
10
- error: string;
11
- }
12
- interface SpeechRecognitionInstance extends EventTarget {
13
- continuous: boolean;
14
- interimResults: boolean;
15
- lang: string;
16
- onstart: (() => void) | null;
17
- onresult: ((event: SpeechRecognitionEvent) => void) | null;
18
- onerror: ((event: SpeechRecognitionErrorEvent) => void) | null;
19
- onend: (() => void) | null;
20
- start(): void;
21
- stop(): void;
22
- }
23
-
24
- interface Props {
25
- /** Called when a speech recognition result is finalized */
26
- onresult?: (text: string) => void;
27
- /** Called when the engine starts listening */
28
- onstart?: () => void;
29
- /** Called when the engine stops listening */
30
- onend?: () => void;
31
- /** Standard button size */
32
- size?: 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm';
33
- /** Custom class for the button */
34
- class?: string;
35
- }
36
-
37
- let {
38
- onresult,
39
- onstart,
40
- onend,
41
- size = 'icon',
42
- class: className = ''
43
- }: Props = $props();
44
-
45
- let isListening = $state(false);
46
- let notSupported = $state(false);
47
- let recognition: SpeechRecognitionInstance | null = null;
48
-
49
- // Initialize SpeechRecognition on mount
50
- $effect(() => {
51
- const SpeechRecognitionCtor = (
52
- (globalThis as Record<string, unknown>).SpeechRecognition ||
53
- (globalThis as Record<string, unknown>).webkitSpeechRecognition
54
- ) as (new () => SpeechRecognitionInstance) | undefined;
55
-
56
- if (!SpeechRecognitionCtor) {
57
- notSupported = true;
58
- return;
59
- }
60
-
61
- recognition = new SpeechRecognitionCtor();
62
- recognition.continuous = false;
63
- recognition.interimResults = false;
64
- recognition.lang = navigator.language || 'en-US';
65
-
66
- recognition.onstart = () => {
67
- isListening = true;
68
- if (onstart) onstart();
69
- };
70
-
71
- recognition.onresult = (event: SpeechRecognitionEvent) => {
72
- const transcript = Array.from(event.results)
73
- .map((result: SpeechRecognitionResult) => result[0])
74
- .map((result: SpeechRecognitionAlternative) => result.transcript)
75
- .join('');
76
-
77
- if (onresult && transcript) {
78
- onresult(transcript);
79
- }
80
- };
81
-
82
- recognition.onerror = (event: SpeechRecognitionErrorEvent) => {
83
- console.warn('SpeechRecognition error:', event.error);
84
- isListening = false;
85
- if (onend) onend();
86
- };
87
-
88
- recognition.onend = () => {
89
- isListening = false;
90
- if (onend) onend();
91
- };
92
- });
93
-
94
- function toggleListening(e?: MouseEvent) {
95
- if (e) e.preventDefault();
96
- if (!recognition) return;
97
-
98
- if (isListening) {
99
- recognition.stop();
100
- } else {
101
- recognition.start();
102
- }
103
- }
104
- </script>
105
-
106
- <TooltipButton
107
- tooltip={notSupported ? "Voice input not supported in this browser" : (isListening ? "Stop listening" : "Start voice input")}
108
- variant={isListening ? "destructive" : "ghost"}
109
- {size}
110
- class="{isListening ? 'animate-pulse' : ''} {className}"
111
- onclick={toggleListening}
112
- disabled={notSupported}
113
- >
114
- {#if isListening}
115
- <Loader2 class="h-4 w-4 animate-spin -ml-1 mr-1.5 inline-block sm:hidden" />
116
- <MicOff class="h-4 w-4" />
117
- {:else}
118
- <Mic class="h-4 w-4" />
119
- {/if}
120
- </TooltipButton>
@@ -1,30 +0,0 @@
1
- <script lang="ts">
2
- import { useNavigation, useCan, t } from '@svadmin/core';
3
- import { Button } from '../ui/button/index.js';
4
- import { Copy } from '@lucide/svelte';
5
-
6
- let { resource, recordItemId, hideText = false, accessControl = { enabled: true, hideIfUnauthorized: true }, class: className = '' } = $props<{
7
- resource: string;
8
- recordItemId: string | number;
9
- hideText?: boolean;
10
- accessControl?: { enabled?: boolean; hideIfUnauthorized?: boolean };
11
- class?: string;
12
- }>();
13
-
14
- const nav = useNavigation();
15
- const can = useCan(() => ({ resource, action: 'create', queryOptions: { enabled: accessControl?.enabled ?? true } }));
16
- const hidden = $derived(accessControl?.hideIfUnauthorized && !can.allowed);
17
- </script>
18
-
19
- {#if !hidden}
20
- <Button
21
- variant="outline"
22
- size={hideText ? 'icon' : 'sm'}
23
- class={className}
24
- disabled={!can.allowed}
25
- onclick={() => nav.clone(resource, recordItemId)}
26
- >
27
- <Copy class="h-4 w-4" />
28
- {#if !hideText}<span class="ml-1">{t('common.clone')}</span>{/if}
29
- </Button>
30
- {/if}
@@ -1,29 +0,0 @@
1
- <script lang="ts">
2
- import { useNavigation, useCan, t } from '@svadmin/core';
3
- import { Button } from '../ui/button/index.js';
4
- import { Plus } from '@lucide/svelte';
5
-
6
- let { resource, hideText = false, accessControl = { enabled: true, hideIfUnauthorized: true }, class: className = '' } = $props<{
7
- resource: string;
8
- hideText?: boolean;
9
- accessControl?: { enabled?: boolean; hideIfUnauthorized?: boolean };
10
- class?: string;
11
- }>();
12
-
13
- const nav = useNavigation();
14
- const can = useCan(() => ({ resource, action: 'create', queryOptions: { enabled: accessControl?.enabled ?? true } }));
15
- const hidden = $derived(accessControl?.hideIfUnauthorized && !can.allowed);
16
- </script>
17
-
18
- {#if !hidden}
19
- <Button
20
- variant="default"
21
- size={hideText ? 'icon' : 'default'}
22
- class={className}
23
- disabled={!can.allowed}
24
- onclick={() => nav.create(resource)}
25
- >
26
- <Plus class="h-4 w-4" />
27
- {#if !hideText}<span class="ml-1">{t('common.create')}</span>{/if}
28
- </Button>
29
- {/if}
@@ -1,59 +0,0 @@
1
- <script lang="ts">
2
- import { useDelete, useCan, t } from '@svadmin/core';
3
- import { Button } from '../ui/button/index.js';
4
- import { Trash2 } from '@lucide/svelte';
5
-
6
- let {
7
- resource, recordItemId, hideText = false,
8
- accessControl = { enabled: true, hideIfUnauthorized: true }, onSuccess, undoable = false, class: className = '',
9
- } = $props<{
10
- resource: string;
11
- recordItemId: string | number;
12
- hideText?: boolean;
13
- accessControl?: { enabled?: boolean; hideIfUnauthorized?: boolean };
14
- onSuccess?: () => void;
15
- undoable?: boolean;
16
- class?: string;
17
- }>();
18
-
19
- const deleteMut = useDelete({ get resource() { return resource; }, get mutationMode() { return undoable ? 'undoable' as const : 'pessimistic' as const; } });
20
- const can = useCan(() => ({ resource, action: 'delete', queryOptions: { enabled: accessControl?.enabled ?? true } }));
21
- const hidden = $derived(accessControl?.hideIfUnauthorized && !can.allowed);
22
- let confirming = $state(false);
23
-
24
- async function handleDelete() {
25
- if (!confirming) {
26
- confirming = true;
27
- return;
28
- }
29
- confirming = false;
30
- await deleteMut.mutation.mutateAsync({ id: recordItemId, resource });
31
- onSuccess?.();
32
- }
33
-
34
- function cancel() { confirming = false; }
35
- </script>
36
-
37
- {#if !hidden}
38
- {#if confirming}
39
- <div class="inline-flex items-center gap-1">
40
- <Button variant="destructive" size="sm" onclick={handleDelete}>
41
- {t('common.confirm')}
42
- </Button>
43
- <Button variant="ghost" size="sm" onclick={cancel}>
44
- {t('common.cancel')}
45
- </Button>
46
- </div>
47
- {:else}
48
- <Button
49
- variant="ghost"
50
- size={hideText ? 'icon' : 'sm'}
51
- class="text-destructive hover:text-destructive {className}"
52
- disabled={!can.allowed}
53
- onclick={handleDelete}
54
- >
55
- <Trash2 class="h-4 w-4" />
56
- {#if !hideText}<span class="ml-1">{t('common.delete')}</span>{/if}
57
- </Button>
58
- {/if}
59
- {/if}
@@ -1,30 +0,0 @@
1
- <script lang="ts">
2
- import { useNavigation, useCan, t } from '@svadmin/core';
3
- import { Button } from '../ui/button/index.js';
4
- import { Pencil } from '@lucide/svelte';
5
-
6
- let { resource, recordItemId, hideText = false, accessControl = { enabled: true, hideIfUnauthorized: true }, class: className = '' } = $props<{
7
- resource: string;
8
- recordItemId: string | number;
9
- hideText?: boolean;
10
- accessControl?: { enabled?: boolean; hideIfUnauthorized?: boolean };
11
- class?: string;
12
- }>();
13
-
14
- const nav = useNavigation();
15
- const can = useCan(() => ({ resource, action: 'edit', queryOptions: { enabled: accessControl?.enabled ?? true } }));
16
- const hidden = $derived(accessControl?.hideIfUnauthorized && !can.allowed);
17
- </script>
18
-
19
- {#if !hidden}
20
- <Button
21
- variant="outline"
22
- size={hideText ? 'icon' : 'sm'}
23
- class={className}
24
- disabled={!can.allowed}
25
- onclick={() => nav.edit(resource, recordItemId)}
26
- >
27
- <Pencil class="h-4 w-4" />
28
- {#if !hideText}<span class="ml-1">{t('common.edit')}</span>{/if}
29
- </Button>
30
- {/if}
@@ -1,30 +0,0 @@
1
- <script lang="ts">
2
- import { useExport, useCan, t } from '@svadmin/core';
3
- import { Button } from '../ui/button/index.js';
4
- import { Download } from '@lucide/svelte';
5
-
6
- let { resource, hideText = false, accessControl = { enabled: true, hideIfUnauthorized: true }, class: className = '' } = $props<{
7
- resource: string;
8
- hideText?: boolean;
9
- accessControl?: { enabled?: boolean; hideIfUnauthorized?: boolean };
10
- class?: string;
11
- }>();
12
-
13
- const { triggerExport, isLoading } = useExport({ get resource() { return resource; } });
14
- const can = useCan(() => ({ resource, action: 'export', queryOptions: { enabled: accessControl?.enabled ?? true } }));
15
- const hidden = $derived(accessControl?.hideIfUnauthorized && !can.allowed);
16
- </script>
17
-
18
- {#if !hidden}
19
-
20
- <Button
21
- variant="outline"
22
- size={hideText ? 'icon' : 'sm'}
23
- class={className}
24
- disabled={isLoading || !can.allowed}
25
- onclick={triggerExport}
26
- >
27
- <Download class="h-4 w-4" />
28
- {#if !hideText}<span class="ml-1">{t('common.export')}</span>{/if}
29
- </Button>
30
- {/if}