@svadmin/ui 0.38.2 → 0.38.7
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/dist/app.css +8 -4
- package/dist/app.theme.css +8 -4
- package/dist/components/AICommandBar.svelte +16 -15
- package/dist/components/AboutSettings.svelte +12 -11
- package/dist/components/AdminApp.svelte +144 -70
- package/dist/components/AdminApp.svelte.d.ts +6 -3
- package/dist/components/ApiSettings.svelte +19 -16
- package/dist/components/AppearanceSettings.svelte +18 -16
- package/dist/components/AuditLogDrawer.svelte +6 -3
- package/dist/components/AuditLogViewer.svelte +18 -15
- package/dist/components/Authenticated.svelte +4 -4
- package/dist/components/AutoForm.svelte +19 -16
- package/dist/components/AutoSaveIndicator.svelte +7 -5
- package/dist/components/AutoTable.svelte +185 -159
- package/dist/components/AutoTable.svelte.d.ts +1 -1
- package/dist/components/Breadcrumbs.svelte +17 -13
- package/dist/components/CancelTaskButton.svelte +5 -2
- package/dist/components/CatchAllNavigate.svelte +3 -3
- package/dist/components/ChatDialog.svelte +22 -19
- package/dist/components/ComboboxField.svelte +6 -4
- package/dist/components/CommandPalette.svelte +20 -20
- package/dist/components/ConfigErrorScreen.svelte +12 -10
- package/dist/components/ConfirmDialog.svelte +6 -4
- package/dist/components/CreatePage.svelte +4 -2
- package/dist/components/DevTools.svelte +11 -14
- package/dist/components/DrawerForm.svelte +5 -2
- package/dist/components/EditPage.svelte +8 -5
- package/dist/components/EmptyState.svelte +5 -3
- package/dist/components/ErrorBoundary.svelte +5 -3
- package/dist/components/ErrorComponent.svelte +6 -4
- package/dist/components/ErrorPage.svelte +12 -10
- package/dist/components/FieldRenderer.svelte +17 -15
- package/dist/components/ForgotPasswordPage.svelte +22 -19
- package/dist/components/Header.svelte +7 -4
- package/dist/components/InfiniteList.svelte +6 -3
- package/dist/components/IntegrationsSettings.svelte +9 -6
- package/dist/components/KeyboardShortcuts.svelte +4 -2
- package/dist/components/Layout.svelte +12 -13
- package/dist/components/LazyPage.svelte +47 -0
- package/dist/components/LazyPage.svelte.d.ts +14 -0
- package/dist/components/ListPage.svelte +8 -5
- package/dist/components/LoginPage.svelte +24 -22
- package/dist/components/MarkdownRenderer.svelte +89 -35
- package/dist/components/ModalForm.svelte +4 -2
- package/dist/components/NavigateToResource.svelte +3 -3
- package/dist/components/NotificationsSettings.svelte +26 -24
- package/dist/components/PasswordInput.svelte +4 -2
- package/dist/components/PermissionMatrix.svelte +15 -12
- package/dist/components/ProfilePage.svelte +23 -21
- package/dist/components/RegisterPage.svelte +21 -19
- package/dist/components/ResourceOperationsPage.svelte +3 -2
- package/dist/components/RetryTaskButton.svelte +5 -2
- package/dist/components/RolesSettings.svelte +10 -8
- package/dist/components/SecuritySettings.svelte +26 -23
- package/dist/components/SettingsPage.svelte +14 -11
- package/dist/components/ShowPage.svelte +9 -7
- package/dist/components/Sidebar.svelte +36 -28
- package/dist/components/SidebarItem.svelte +4 -4
- package/dist/components/SidebarItem.svelte.d.ts +1 -1
- package/dist/components/StepsForm.svelte +11 -8
- package/dist/components/TaskDetails.svelte +14 -11
- package/dist/components/TaskList.svelte +14 -11
- package/dist/components/TaskQueueDrawer.svelte +34 -32
- package/dist/components/TaskStatusBadge.svelte +5 -2
- package/dist/components/Toast.svelte +18 -4
- package/dist/components/TooltipButton.svelte +25 -3
- package/dist/components/TwoFactorAuthPage.svelte +26 -24
- package/dist/components/UndoableNotification.svelte +5 -2
- package/dist/components/UpdatePasswordPage.svelte +18 -15
- package/dist/components/VirtualTable.svelte +0 -4
- package/dist/components/account/CompanyProfilePage.svelte +13 -11
- package/dist/components/account/GetStartedPage.svelte +15 -13
- package/dist/components/account/ImportMembersPage.svelte +14 -12
- package/dist/components/account/MembersStarterPage.svelte +10 -8
- package/dist/components/account/SecurityLogPage.svelte +24 -22
- package/dist/components/account/SettingsEnterprisePage.svelte +6 -4
- package/dist/components/account/SettingsPlainPage.svelte +14 -12
- package/dist/components/account/SettingsSidebarPage.svelte +11 -9
- package/dist/components/account/TeamMembersPage.svelte +10 -8
- package/dist/components/buttons/CloneButton.svelte +4 -2
- package/dist/components/buttons/CreateButton.svelte +4 -2
- package/dist/components/buttons/DeleteButton.svelte +6 -4
- package/dist/components/buttons/EditButton.svelte +4 -2
- package/dist/components/buttons/ExportButton.svelte +4 -2
- package/dist/components/buttons/ImportButton.svelte +4 -2
- package/dist/components/buttons/RefreshButton.svelte +4 -2
- package/dist/components/buttons/SaveButton.svelte +4 -2
- package/dist/components/buttons/ShowButton.svelte +4 -2
- package/dist/components/fieldComponentMap.js +0 -3
- package/dist/components/fields/ArrayField.svelte +6 -4
- package/dist/components/fields/JsonField.svelte +5 -3
- package/dist/components/fields/RelationField.svelte +3 -3
- package/dist/components/fields/RichTextField.svelte +4 -2
- package/dist/components/network/TeamCrewTablePage.svelte +18 -16
- package/dist/components/network/UserCardsNFTPage.svelte +11 -9
- package/dist/components/profile/ActivityTimeline.svelte +10 -8
- package/dist/components/profile/ProfileCard.svelte +13 -11
- package/dist/components/profile/ProjectsGrid.svelte +7 -5
- package/dist/components/profile/PublicProfilePage.svelte +18 -16
- package/dist/components/profile/TeamsShowcase.svelte +7 -5
- package/dist/components/toast-host.svelte.d.ts +5 -0
- package/dist/components/toast-host.svelte.js +21 -0
- package/dist/components/ui/command/command-dialog.svelte +29 -13
- package/dist/components/ui/command/command-dialog.svelte.d.ts +4 -3
- package/dist/components/ui/command/command-empty.svelte +18 -0
- package/dist/components/ui/command/command-empty.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-group.svelte +41 -0
- package/dist/components/ui/command/command-group.svelte.d.ts +8 -0
- package/dist/components/ui/command/command-input.svelte +23 -0
- package/dist/components/ui/command/command-input.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-item.svelte +43 -0
- package/dist/components/ui/command/command-item.svelte.d.ts +11 -0
- package/dist/components/ui/command/command-list.svelte +18 -0
- package/dist/components/ui/command/command-list.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-loading.svelte +12 -0
- package/dist/components/ui/command/command-loading.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-separator.svelte +23 -0
- package/dist/components/ui/command/command-separator.svelte.d.ts +7 -0
- package/dist/components/ui/command/command.svelte +26 -0
- package/dist/components/ui/command/command.svelte.d.ts +4 -0
- package/dist/components/ui/command/index.d.ts +55 -2
- package/dist/components/ui/command/index.js +21 -2
- package/dist/components/ui/sheet/sheet-content.svelte +1 -4
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +1 -3
- package/dist/components/ui/tabs/tabs-content.svelte +6 -2
- package/dist/components/ui/tabs/tabs-context.svelte.d.ts +5 -0
- package/dist/components/ui/tabs/tabs-context.svelte.js +2 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +49 -4
- package/dist/components/ui/tabs/tabs.svelte +12 -1
- package/dist/components/ui/tooltip/index.d.ts +4 -1
- package/dist/components/ui/tooltip/index.js +3 -1
- package/dist/components/ui/tooltip/tooltip-content.svelte +308 -35
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +42 -3
- package/dist/components/ui/tooltip/tooltip-context.svelte.d.ts +37 -0
- package/dist/components/ui/tooltip/tooltip-context.svelte.js +220 -0
- package/dist/components/ui/tooltip/tooltip-layer-registry.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-layer-registry.svelte.js +93 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +56 -3
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +23 -2
- package/dist/components/ui/tooltip/tooltip.svelte +63 -3
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +23 -2
- package/dist/router-state.svelte.d.ts +13 -0
- package/dist/router-state.svelte.js +72 -37
- package/package.json +14 -11
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
import { getResources } from '@svadmin/core';
|
|
2
|
+
import { captureAdminContext, getResources } from '@svadmin/core';
|
|
4
3
|
import { getPath } from '../router-state.svelte.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
|
+
|
|
7
6
|
import * as Breadcrumb from './ui/breadcrumb/index.js';
|
|
8
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
10
|
+
const adminContext = captureAdminContext();
|
|
9
11
|
const resources = $derived((() => { try { return getResources(); } catch { return []; } })());
|
|
10
12
|
|
|
11
13
|
interface Crumb { label: string; href: string; }
|
|
12
14
|
|
|
13
15
|
const crumbs = $derived.by(() => {
|
|
14
|
-
const result: Crumb[] = [{ label: t('common.home') ?? 'Home', href: formatLink('/') }];
|
|
16
|
+
const result: Crumb[] = [{ label: i18n.t('common.home') ?? 'Home', href: adminContext.formatLink('/') }];
|
|
15
17
|
const path = getPath().replace(/^\//, '');
|
|
16
18
|
if (path === '') return result;
|
|
17
19
|
|
|
@@ -25,21 +27,23 @@
|
|
|
25
27
|
currentPath += `/${seg}`;
|
|
26
28
|
|
|
27
29
|
if (resourceNames.includes(seg)) {
|
|
28
|
-
const res = resources.find(r => r.name === seg)
|
|
29
|
-
|
|
30
|
+
const res = resources.find(r => r.name === seg);
|
|
31
|
+
if (res) {
|
|
32
|
+
result.push({ label: res.label, href: adminContext.formatLink(currentPath) });
|
|
33
|
+
}
|
|
30
34
|
} else if (seg === 'create') {
|
|
31
|
-
result.push({ label: t('common.create') ?? 'Create', href: formatLink(currentPath) });
|
|
35
|
+
result.push({ label: i18n.t('common.create') ?? 'Create', href: adminContext.formatLink(currentPath) });
|
|
32
36
|
} else if (['edit', 'show', 'clone'].includes(seg) && segments[i+1]) {
|
|
33
|
-
const actionLabel = seg === 'edit' ? (t('common.edit') ?? 'Edit') :
|
|
34
|
-
seg === 'show' ? (t('common.detail') ?? 'Details') :
|
|
35
|
-
(t('common.clone') ?? 'Clone');
|
|
37
|
+
const actionLabel = seg === 'edit' ? (i18n.t('common.edit') ?? 'Edit') :
|
|
38
|
+
seg === 'show' ? (i18n.t('common.detail') ?? 'Details') :
|
|
39
|
+
(i18n.t('common.clone') ?? 'Clone');
|
|
36
40
|
const id = segments[i+1];
|
|
37
41
|
currentPath += `/${id}`; // advance path by id
|
|
38
|
-
result.push({ label: `${actionLabel} #${id}`, href: formatLink(currentPath) });
|
|
42
|
+
result.push({ label: `${actionLabel} #${id}`, href: adminContext.formatLink(currentPath) });
|
|
39
43
|
i++; // skip next segment since we consumed the id
|
|
40
44
|
} else if (i > 0 && resourceNames.includes(segments[i-1])) {
|
|
41
45
|
// This is a parent ID (e.g. /teams/123/users) and we are not an action
|
|
42
|
-
result.push({ label: `#${seg}`, href: formatLink(currentPath) });
|
|
46
|
+
result.push({ label: `#${seg}`, href: adminContext.formatLink(currentPath) });
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getTaskProvider } from '@svadmin/core';
|
|
3
3
|
import { useQueryClient } from '@tanstack/svelte-query';
|
|
4
|
-
import {
|
|
4
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
|
+
|
|
5
6
|
import { Button } from './ui/button/index.js';
|
|
6
7
|
import { Loader2, Ban } from '@lucide/svelte';
|
|
7
8
|
|
|
9
|
+
const i18n = useTranslation();
|
|
10
|
+
|
|
8
11
|
let {
|
|
9
12
|
taskId,
|
|
10
13
|
taskProvider = getTaskProvider({ optional: true }),
|
|
@@ -55,6 +58,6 @@
|
|
|
55
58
|
{#if children}
|
|
56
59
|
{@render children()}
|
|
57
60
|
{:else}
|
|
58
|
-
{t('common.cancel')}
|
|
61
|
+
{i18n.t('common.cancel')}
|
|
59
62
|
{/if}
|
|
60
63
|
</Button>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useIsAuthenticated } from '@svadmin/core';
|
|
3
|
-
import { navigate } from '@svadmin/core/router';
|
|
2
|
+
import { captureAdminContext, useIsAuthenticated } from '@svadmin/core';
|
|
4
3
|
import NavigateToResource from './NavigateToResource.svelte';
|
|
5
4
|
|
|
5
|
+
const adminContext = captureAdminContext();
|
|
6
6
|
const auth = useIsAuthenticated();
|
|
7
7
|
|
|
8
8
|
$effect(() => {
|
|
9
9
|
if (!auth.isLoading && !auth.isAuthenticated) {
|
|
10
|
-
navigate('/login');
|
|
10
|
+
adminContext.navigate('/login');
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
13
|
</script>
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
/* eslint-disable no-undef, svelte/no-at-html-tags */
|
|
3
3
|
import { getChatProvider, getChatContext, setChatContext, getAgentProvider, registerApproval, resolveApproval } from '@svadmin/core';
|
|
4
4
|
import type { ChatMessage, ChatAction } from '@svadmin/core';
|
|
5
|
-
import {
|
|
5
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
6
|
+
|
|
6
7
|
import { useParsed } from '@svadmin/core';
|
|
7
8
|
import { fly, fade, scale } from 'svelte/transition';
|
|
8
9
|
import { Button } from './ui/button/index.js';
|
|
9
10
|
import TooltipButton from './TooltipButton.svelte';
|
|
10
11
|
import { MessageCircle, X, Minus, Send, Loader2, Bot, Trash2 } from '@lucide/svelte';
|
|
11
12
|
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
|
|
12
15
|
interface Props {
|
|
13
16
|
/** localStorage key for chat history persistence. Set to '' to disable. */
|
|
14
17
|
persistKey?: string;
|
|
@@ -254,18 +257,18 @@
|
|
|
254
257
|
|
|
255
258
|
collectedActions.push(
|
|
256
259
|
{
|
|
257
|
-
label: `✅ ${t('common.confirm') || 'Approve'}: ${event.description}`,
|
|
260
|
+
label: `✅ ${i18n.t('common.confirm') || 'Approve'}: ${event.description}`,
|
|
258
261
|
variant: 'default',
|
|
259
262
|
payload: { approvalId: reqId, approved: true },
|
|
260
263
|
},
|
|
261
264
|
{
|
|
262
|
-
label: `❌ ${t('common.cancel') || 'Reject'}`,
|
|
265
|
+
label: `❌ ${i18n.t('common.cancel') || 'Reject'}`,
|
|
263
266
|
variant: 'destructive',
|
|
264
267
|
payload: { approvalId: reqId, approved: false },
|
|
265
268
|
},
|
|
266
269
|
);
|
|
267
270
|
|
|
268
|
-
assistantMsg.content += `\n⚠️ **${t('chat.approvalRequired') || 'Approval required'}**: ${event.description}`;
|
|
271
|
+
assistantMsg.content += `\n⚠️ **${i18n.t('chat.approvalRequired') || 'Approval required'}**: ${event.description}`;
|
|
269
272
|
assistantMsg.actions = [...collectedActions];
|
|
270
273
|
messages = [...messages.slice(0, -1), { ...assistantMsg }];
|
|
271
274
|
scrollToBottom();
|
|
@@ -305,7 +308,7 @@
|
|
|
305
308
|
}
|
|
306
309
|
} catch (err: unknown) {
|
|
307
310
|
if (err instanceof Error && err.name === 'AbortError') return;
|
|
308
|
-
assistantMsg.content = t('chat.error') || 'Sorry, something went wrong. Please try again.';
|
|
311
|
+
assistantMsg.content = i18n.t('chat.error') || 'Sorry, something went wrong. Please try again.';
|
|
309
312
|
messages = [...messages.slice(0, -1), { ...assistantMsg }];
|
|
310
313
|
} finally {
|
|
311
314
|
isStreaming = false;
|
|
@@ -401,9 +404,9 @@
|
|
|
401
404
|
}
|
|
402
405
|
|
|
403
406
|
const suggestions = $derived([
|
|
404
|
-
t('chat.suggestion1') || 'How do I create a new resource?',
|
|
405
|
-
t('chat.suggestion2') || 'Explain the data model',
|
|
406
|
-
t('chat.suggestion3') || 'Help me write a filter query',
|
|
407
|
+
i18n.t('chat.suggestion1') || 'How do I create a new resource?',
|
|
408
|
+
i18n.t('chat.suggestion2') || 'Explain the data model',
|
|
409
|
+
i18n.t('chat.suggestion3') || 'Help me write a filter query',
|
|
407
410
|
]);
|
|
408
411
|
</script>
|
|
409
412
|
|
|
@@ -414,7 +417,7 @@
|
|
|
414
417
|
{#if !open}
|
|
415
418
|
<div transition:scale={{ duration: 200 }}>
|
|
416
419
|
<TooltipButton
|
|
417
|
-
tooltip={t('chat.title') || 'AI Assistant'}
|
|
420
|
+
tooltip={i18n.t('chat.title') || 'AI Assistant'}
|
|
418
421
|
variant="default"
|
|
419
422
|
size="icon"
|
|
420
423
|
class="fixed bottom-4 right-4 sm:bottom-6 sm:right-6 z-[9998] h-12 w-12 rounded-full shadow-xl hover:shadow-2xl hover:scale-110 transition-all bg-primary text-primary-foreground"
|
|
@@ -450,17 +453,17 @@
|
|
|
450
453
|
</div>
|
|
451
454
|
<div>
|
|
452
455
|
<h3 class="text-sm font-semibold leading-none">
|
|
453
|
-
{t('chat.title') || 'AI Assistant'}
|
|
456
|
+
{i18n.t('chat.title') || 'AI Assistant'}
|
|
454
457
|
</h3>
|
|
455
458
|
{#if isStreaming}
|
|
456
|
-
<p class="text-[10px] opacity-80 mt-0.5">{t('chat.typing') || 'Typing...'}</p>
|
|
459
|
+
<p class="text-[10px] opacity-80 mt-0.5">{i18n.t('chat.typing') || 'Typing...'}</p>
|
|
457
460
|
{/if}
|
|
458
461
|
</div>
|
|
459
462
|
</div>
|
|
460
463
|
<div class="flex items-center gap-0.5">
|
|
461
464
|
{#if messages.length > 0}
|
|
462
465
|
<TooltipButton
|
|
463
|
-
tooltip={t('chat.clear') || 'Clear'}
|
|
466
|
+
tooltip={i18n.t('chat.clear') || 'Clear'}
|
|
464
467
|
variant="ghost"
|
|
465
468
|
size="icon"
|
|
466
469
|
class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
|
|
@@ -470,7 +473,7 @@
|
|
|
470
473
|
</TooltipButton>
|
|
471
474
|
{/if}
|
|
472
475
|
<TooltipButton
|
|
473
|
-
tooltip={minimized ? (t('common.expand') || 'Expand') : (t('common.collapse') || 'Minimize')}
|
|
476
|
+
tooltip={minimized ? (i18n.t('common.expand') || 'Expand') : (i18n.t('common.collapse') || 'Minimize')}
|
|
474
477
|
variant="ghost"
|
|
475
478
|
size="icon"
|
|
476
479
|
class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
|
|
@@ -479,7 +482,7 @@
|
|
|
479
482
|
<Minus class="h-3.5 w-3.5" />
|
|
480
483
|
</TooltipButton>
|
|
481
484
|
<TooltipButton
|
|
482
|
-
tooltip={t('common.close') || 'Close'}
|
|
485
|
+
tooltip={i18n.t('common.close') || 'Close'}
|
|
483
486
|
variant="ghost"
|
|
484
487
|
size="icon"
|
|
485
488
|
class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
|
|
@@ -503,10 +506,10 @@
|
|
|
503
506
|
<Bot class="h-6 w-6 text-primary" />
|
|
504
507
|
</div>
|
|
505
508
|
<h4 class="text-sm font-semibold text-foreground mb-1">
|
|
506
|
-
{t('chat.welcome') || 'How can I help?'}
|
|
509
|
+
{i18n.t('chat.welcome') || 'How can I help?'}
|
|
507
510
|
</h4>
|
|
508
511
|
<p class="text-xs text-muted-foreground mb-4">
|
|
509
|
-
{t('chat.welcomeDesc') || 'Ask me anything about your admin panel.'}
|
|
512
|
+
{i18n.t('chat.welcomeDesc') || 'Ask me anything about your admin panel.'}
|
|
510
513
|
</p>
|
|
511
514
|
<div class="flex flex-col gap-2 w-full max-w-[240px]">
|
|
512
515
|
{#each suggestions as suggestion, _i (_i)}
|
|
@@ -551,7 +554,7 @@
|
|
|
551
554
|
{:else}
|
|
552
555
|
<div class="flex items-center gap-1.5 text-muted-foreground">
|
|
553
556
|
<Loader2 class="h-3.5 w-3.5 animate-spin" />
|
|
554
|
-
<span class="text-xs">{t('chat.thinking') || 'Thinking...'}</span>
|
|
557
|
+
<span class="text-xs">{i18n.t('chat.thinking') || 'Thinking...'}</span>
|
|
555
558
|
</div>
|
|
556
559
|
{/if}
|
|
557
560
|
{:else}
|
|
@@ -569,7 +572,7 @@
|
|
|
569
572
|
<textarea
|
|
570
573
|
bind:value={inputValue}
|
|
571
574
|
onkeydown={handleKeydown}
|
|
572
|
-
placeholder={t('chat.placeholder') || 'Type a message...'}
|
|
575
|
+
placeholder={i18n.t('chat.placeholder') || 'Type a message...'}
|
|
573
576
|
rows={1}
|
|
574
577
|
disabled={isStreaming}
|
|
575
578
|
class="flex-1 resize-none rounded-xl border border-input bg-background px-3 py-2.5 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 disabled:opacity-50 max-h-[100px] min-h-[40px]"
|
|
@@ -597,7 +600,7 @@
|
|
|
597
600
|
</div>
|
|
598
601
|
<p class="text-[10px] text-muted-foreground mt-1.5 text-center">
|
|
599
602
|
<kbd class="px-1 py-0.5 rounded border border-border bg-muted text-[9px] font-mono">Ctrl+Shift+L</kbd>
|
|
600
|
-
{t('chat.shortcutHint') || 'to toggle'}
|
|
603
|
+
{i18n.t('chat.shortcutHint') || 'to toggle'}
|
|
601
604
|
</p>
|
|
602
605
|
</div>
|
|
603
606
|
{/if}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import {
|
|
3
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
4
|
import { useSelect } from '@svadmin/core';
|
|
5
5
|
import type { Filter } from '@svadmin/core';
|
|
6
6
|
import { Button } from './ui/button/index.js';
|
|
7
7
|
import TooltipButton from './TooltipButton.svelte';
|
|
8
|
-
import { Command } from '
|
|
8
|
+
import { Command } from './ui/command/index.js';
|
|
9
9
|
import { Skeleton } from './ui/skeleton/index.js';
|
|
10
10
|
import { ChevronsUpDown, Check, X, Search } from '@lucide/svelte';
|
|
11
11
|
|
|
12
|
+
const i18n = useTranslation();
|
|
13
|
+
|
|
12
14
|
function clickOutside(node: HTMLElement) {
|
|
13
15
|
const handler = (e: MouseEvent) => {
|
|
14
16
|
if (!node.contains(e.target as Node)) open = false;
|
|
@@ -89,7 +91,7 @@
|
|
|
89
91
|
>
|
|
90
92
|
{#if selectedLabel}
|
|
91
93
|
<span class="truncate">{selectedLabel}</span>
|
|
92
|
-
<TooltipButton tooltip={t('common.clear')} size="icon-sm" class="h-5 w-5 ml-1" onclick={handleClear}>
|
|
94
|
+
<TooltipButton tooltip={i18n.t('common.clear')} size="icon-sm" class="h-5 w-5 ml-1" onclick={handleClear}>
|
|
93
95
|
<X class="h-3 w-3" />
|
|
94
96
|
</TooltipButton>
|
|
95
97
|
{:else}
|
|
@@ -125,7 +127,7 @@
|
|
|
125
127
|
<Command.Item
|
|
126
128
|
value={opt.label}
|
|
127
129
|
onSelect={() => handleSelect(opt.value)}
|
|
128
|
-
class="relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected
|
|
130
|
+
class="relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected]:bg-accent data-[selected]:text-accent-foreground"
|
|
129
131
|
>
|
|
130
132
|
<Check class="mr-2 h-3.5 w-3.5 {value === opt.value ? 'opacity-100' : 'opacity-0'}" />
|
|
131
133
|
{opt.label}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { getResources, getAgentProvider, getChatProvider } from '@svadmin/core';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { toggleTheme } from '@svadmin/core';
|
|
6
|
-
import { Command } from 'cmdk-sv';
|
|
2
|
+
import { captureAdminContext, getResources, getAgentProvider, getChatProvider, toggleTheme } from '@svadmin/core';
|
|
3
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
|
+
import { Command } from './ui/command/index.js';
|
|
7
5
|
import * as Dialog from './ui/dialog/index.js';
|
|
8
6
|
import { Search, LayoutDashboard, Plus, Sun, FileText, Sparkles } from '@lucide/svelte';
|
|
9
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
10
10
|
interface Props {
|
|
11
11
|
open?: boolean;
|
|
12
12
|
/** Callback fired when user selects "Ask AI" with a query string */
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
let { open = $bindable(false), onAskAI }: Props = $props();
|
|
17
|
+
const adminContext = captureAdminContext();
|
|
17
18
|
let searchValue = $state('');
|
|
18
19
|
|
|
19
20
|
const resources = $derived(getResources());
|
|
@@ -37,17 +38,17 @@
|
|
|
37
38
|
close();
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
const itemClass = 'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected
|
|
41
|
+
const itemClass = 'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected]:bg-accent data-[selected]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50';
|
|
41
42
|
</script>
|
|
42
43
|
|
|
43
44
|
<Dialog.Dialog bind:open>
|
|
44
45
|
<Dialog.DialogContent class="overflow-hidden p-0 sm:max-w-[560px]">
|
|
45
|
-
<Command.Root class="flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground [&_[data-
|
|
46
|
+
<Command.Root class="flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground [&_[data-command-group-heading]]:text-muted-foreground [&_[data-command-group-heading]]:px-2 [&_[data-command-group-heading]]:py-1.5 [&_[data-command-group-heading]]:text-xs [&_[data-command-group-heading]]:font-semibold [&_[data-command-group-heading]]:uppercase [&_[data-command-group-heading]]:tracking-wider">
|
|
46
47
|
<div class="flex items-center border-b px-3" data-cmdk-input-wrapper="">
|
|
47
48
|
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
48
49
|
<Command.Input
|
|
49
50
|
bind:value={searchValue}
|
|
50
|
-
placeholder={hasAI ? (t('commandPalette.searchOrAsk') || 'Search or ask AI...') : t('common.search')}
|
|
51
|
+
placeholder={hasAI ? (i18n.t('commandPalette.searchOrAsk') || 'Search or ask AI...') : i18n.t('common.search')}
|
|
51
52
|
class="flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
|
|
52
53
|
/>
|
|
53
54
|
<kbd class="ml-2 text-[10px] font-mono font-medium text-muted-foreground bg-muted px-1.5 py-0.5 rounded border border-border">ESC</kbd>
|
|
@@ -60,10 +61,10 @@
|
|
|
60
61
|
onclick={askAI}
|
|
61
62
|
>
|
|
62
63
|
<Sparkles class="h-3.5 w-3.5" />
|
|
63
|
-
{t('commandPalette.askAI') || 'Ask AI'}: "{searchValue.trim()}"
|
|
64
|
+
{i18n.t('commandPalette.askAI') || 'Ask AI'}: "{searchValue.trim()}"
|
|
64
65
|
</button>
|
|
65
66
|
{:else}
|
|
66
|
-
{t('common.noData')}
|
|
67
|
+
{i18n.t('common.noData')}
|
|
67
68
|
{/if}
|
|
68
69
|
</Command.Empty>
|
|
69
70
|
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
class={itemClass}
|
|
77
78
|
>
|
|
78
79
|
<Sparkles class="h-4 w-4 text-primary" />
|
|
79
|
-
<span class="text-primary font-medium">{t('commandPalette.askAI') || 'Ask AI'}</span>
|
|
80
|
+
<span class="text-primary font-medium">{i18n.t('commandPalette.askAI') || 'Ask AI'}</span>
|
|
80
81
|
<span class="text-muted-foreground truncate ml-1">"{searchValue.trim()}"</span>
|
|
81
82
|
</Command.Item>
|
|
82
83
|
</Command.Group>
|
|
@@ -84,19 +85,19 @@
|
|
|
84
85
|
{/if}
|
|
85
86
|
|
|
86
87
|
<!-- Navigation -->
|
|
87
|
-
<Command.Group heading={t('common.home')}>
|
|
88
|
+
<Command.Group heading={i18n.t('common.home')}>
|
|
88
89
|
<Command.Item
|
|
89
90
|
value="home"
|
|
90
|
-
onSelect={() => act(() => navigate('/'))}
|
|
91
|
+
onSelect={() => act(() => adminContext.navigate('/'))}
|
|
91
92
|
class={itemClass}
|
|
92
93
|
>
|
|
93
94
|
<LayoutDashboard class="h-4 w-4 text-muted-foreground" />
|
|
94
|
-
{t('common.home')}
|
|
95
|
+
{i18n.t('common.home')}
|
|
95
96
|
</Command.Item>
|
|
96
97
|
{#each resources as r, _i (_i)}
|
|
97
98
|
<Command.Item
|
|
98
99
|
value={r.name}
|
|
99
|
-
onSelect={() => act(() => navigate(`/${r.name}`))}
|
|
100
|
+
onSelect={() => act(() => adminContext.navigate(`/${r.name}`))}
|
|
100
101
|
class={itemClass}
|
|
101
102
|
>
|
|
102
103
|
<FileText class="h-4 w-4 text-muted-foreground" />
|
|
@@ -108,15 +109,15 @@
|
|
|
108
109
|
<Command.Separator class="mx-1 my-1 h-px bg-border" />
|
|
109
110
|
|
|
110
111
|
<!-- Actions -->
|
|
111
|
-
<Command.Group heading={t('common.actions')}>
|
|
112
|
+
<Command.Group heading={i18n.t('common.actions')}>
|
|
112
113
|
{#each resources as r, _i (_i)}
|
|
113
114
|
<Command.Item
|
|
114
115
|
value={"create-" + r.name}
|
|
115
|
-
onSelect={() => act(() => navigate(`/${r.name}/create`))}
|
|
116
|
+
onSelect={() => act(() => adminContext.navigate(`/${r.name}/create`))}
|
|
116
117
|
class={itemClass}
|
|
117
118
|
>
|
|
118
119
|
<Plus class="h-4 w-4 text-muted-foreground" />
|
|
119
|
-
{t('common.create')} {r.label}
|
|
120
|
+
{i18n.t('common.create')} {r.label}
|
|
120
121
|
</Command.Item>
|
|
121
122
|
{/each}
|
|
122
123
|
<Command.Item
|
|
@@ -125,11 +126,10 @@
|
|
|
125
126
|
class={itemClass}
|
|
126
127
|
>
|
|
127
128
|
<Sun class="h-4 w-4 text-muted-foreground" />
|
|
128
|
-
{t('common.toggleTheme')}
|
|
129
|
+
{i18n.t('common.toggleTheme')}
|
|
129
130
|
</Command.Item>
|
|
130
131
|
</Command.Group>
|
|
131
132
|
</Command.List>
|
|
132
133
|
</Command.Root>
|
|
133
134
|
</Dialog.DialogContent>
|
|
134
135
|
</Dialog.Dialog>
|
|
135
|
-
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
3
|
import { AlertTriangle, Copy, CheckCircle } from '@lucide/svelte';
|
|
4
4
|
import { Button } from './ui/button/index.js';
|
|
5
5
|
import TooltipButton from './TooltipButton.svelte';
|
|
6
6
|
import * as Card from './ui/card/index.js';
|
|
7
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
8
10
|
let { title, missingVars = [], envTemplate = '' } = $props<{
|
|
9
11
|
title?: string;
|
|
10
12
|
missingVars?: { key: string; description?: string }[];
|
|
11
13
|
envTemplate?: string;
|
|
12
14
|
}>();
|
|
13
15
|
|
|
14
|
-
const displayTitle = $derived(title ?? t('config.missingEnvTitle'));
|
|
16
|
+
const displayTitle = $derived(title ?? i18n.t('config.missingEnvTitle'));
|
|
15
17
|
|
|
16
18
|
let copied = $state<Record<string, boolean>>({});
|
|
17
19
|
let copyTimers = $state<Record<string, ReturnType<typeof setTimeout>>>({});
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
</div>
|
|
58
60
|
<Card.CardTitle class="text-xl">{displayTitle}</Card.CardTitle>
|
|
59
61
|
<p class="text-sm text-muted-foreground">
|
|
60
|
-
{t('config.missingEnvDescription')}
|
|
62
|
+
{i18n.t('config.missingEnvDescription')}
|
|
61
63
|
</p>
|
|
62
64
|
</Card.CardHeader>
|
|
63
65
|
<Card.CardContent class="space-y-4">
|
|
@@ -72,7 +74,7 @@
|
|
|
72
74
|
{/if}
|
|
73
75
|
</div>
|
|
74
76
|
<TooltipButton
|
|
75
|
-
tooltip={t('common.copy')}
|
|
77
|
+
tooltip={i18n.t('common.copy')}
|
|
76
78
|
variant="ghost"
|
|
77
79
|
size="icon"
|
|
78
80
|
class="h-7 w-7 shrink-0"
|
|
@@ -92,9 +94,9 @@
|
|
|
92
94
|
{#if envTemplate}
|
|
93
95
|
<div class="rounded-lg border overflow-hidden">
|
|
94
96
|
<div class="flex items-center justify-between px-3 py-2 bg-muted/50 border-b border-border/50">
|
|
95
|
-
<span class="text-xs font-medium text-muted-foreground">{t('config.envFilePath')}</span>
|
|
97
|
+
<span class="text-xs font-medium text-muted-foreground">{i18n.t('config.envFilePath')}</span>
|
|
96
98
|
<TooltipButton
|
|
97
|
-
tooltip={t('common.copyAll')}
|
|
99
|
+
tooltip={i18n.t('common.copyAll')}
|
|
98
100
|
variant="ghost"
|
|
99
101
|
size="sm"
|
|
100
102
|
class="h-7 gap-1"
|
|
@@ -102,10 +104,10 @@
|
|
|
102
104
|
>
|
|
103
105
|
{#if copied['__all__']}
|
|
104
106
|
<CheckCircle class="h-3.5 w-3.5 text-green-500" />
|
|
105
|
-
<span class="text-xs">{t('common.copied')}</span>
|
|
107
|
+
<span class="text-xs">{i18n.t('common.copied')}</span>
|
|
106
108
|
{:else}
|
|
107
109
|
<Copy class="h-3.5 w-3.5" />
|
|
108
|
-
<span class="text-xs">{t('common.copyAll')}</span>
|
|
110
|
+
<span class="text-xs">{i18n.t('common.copyAll')}</span>
|
|
109
111
|
{/if}
|
|
110
112
|
</TooltipButton>
|
|
111
113
|
</div>
|
|
@@ -114,11 +116,11 @@
|
|
|
114
116
|
{/if}
|
|
115
117
|
|
|
116
118
|
<p class="text-xs text-muted-foreground text-center mt-4">
|
|
117
|
-
{t('config.reload')}
|
|
119
|
+
{i18n.t('config.reload')}
|
|
118
120
|
</p>
|
|
119
121
|
|
|
120
122
|
<Button variant="outline" class="w-full" onclick={() => window.location.reload()}>
|
|
121
|
-
{t('config.reloadButton')}
|
|
123
|
+
{i18n.t('config.reloadButton')}
|
|
122
124
|
</Button>
|
|
123
125
|
</Card.CardContent>
|
|
124
126
|
</Card.Card>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import * as AlertDialog from './ui/alert-dialog/index.js';
|
|
3
3
|
import { Button } from './ui/button/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
|
+
|
|
6
|
+
const i18n = useTranslation();
|
|
5
7
|
|
|
6
8
|
let { open = $bindable(false), title, message = '',
|
|
7
9
|
confirmText, cancelText, variant = 'danger',
|
|
@@ -22,9 +24,9 @@
|
|
|
22
24
|
info: 'default' as const,
|
|
23
25
|
};
|
|
24
26
|
|
|
25
|
-
const resolvedTitle = $derived(title ?? t('common.confirmAction'));
|
|
26
|
-
const resolvedConfirmText = $derived(confirmText ?? t('common.confirm'));
|
|
27
|
-
const resolvedCancelText = $derived(cancelText ?? t('common.cancel'));
|
|
27
|
+
const resolvedTitle = $derived(title ?? i18n.t('common.confirmAction'));
|
|
28
|
+
const resolvedConfirmText = $derived(confirmText ?? i18n.t('common.confirm'));
|
|
29
|
+
const resolvedCancelText = $derived(cancelText ?? i18n.t('common.cancel'));
|
|
28
30
|
|
|
29
31
|
let confirmed = $state(false);
|
|
30
32
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getResource } from '@svadmin/core';
|
|
3
|
-
import {
|
|
3
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
4
|
import type { Snippet } from 'svelte';
|
|
5
5
|
import PageHeader from './PageHeader.svelte';
|
|
6
6
|
import AutoForm from './AutoForm.svelte';
|
|
7
7
|
import ListButton from './buttons/ListButton.svelte';
|
|
8
8
|
|
|
9
|
+
const i18n = useTranslation();
|
|
10
|
+
|
|
9
11
|
interface Props {
|
|
10
12
|
resourceName: string;
|
|
11
13
|
title?: string;
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
}: Props = $props();
|
|
22
24
|
|
|
23
25
|
const resource = $derived(getResource(resourceName));
|
|
24
|
-
const pageTitle = $derived(title ?? `${t('common.create')}${resource.label}`);
|
|
26
|
+
const pageTitle = $derived(title ?? `${i18n.t('common.create')}${resource.label}`);
|
|
25
27
|
</script>
|
|
26
28
|
|
|
27
29
|
<div class="space-y-6 {className}">
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
import { fly } from 'svelte/transition';
|
|
4
|
-
import { getResources } from '@svadmin/core';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { currentPath } from '@svadmin/core/router';
|
|
4
|
+
import { captureAdminContext, getResources, getTheme, getColorTheme } from '@svadmin/core';
|
|
5
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
6
|
+
|
|
8
7
|
import TooltipButton from './TooltipButton.svelte';
|
|
9
8
|
import * as Tabs from './ui/tabs/index.js';
|
|
10
9
|
import { Badge } from './ui/badge/index.js';
|
|
@@ -13,6 +12,9 @@
|
|
|
13
12
|
import { X, Bug, ChevronDown, ChevronUp, Wand2 } from '@lucide/svelte';
|
|
14
13
|
import InferencerPanel from './InferencerPanel.svelte';
|
|
15
14
|
|
|
15
|
+
const i18n = useTranslation();
|
|
16
|
+
|
|
17
|
+
const adminContext = captureAdminContext();
|
|
16
18
|
let visible = $state(false);
|
|
17
19
|
let collapsed = $state(false);
|
|
18
20
|
|
|
@@ -28,16 +30,11 @@
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const resources = $derived.by(() => { try { return getResources(); } catch { return []; } });
|
|
31
|
-
const path = $derived(currentPath());
|
|
33
|
+
const path = $derived(adminContext.currentPath());
|
|
32
34
|
const theme = $derived(getTheme());
|
|
33
35
|
const colorTheme = $derived(getColorTheme());
|
|
34
|
-
const locale = $derived(
|
|
36
|
+
const locale = $derived(i18n.locale);
|
|
35
37
|
|
|
36
|
-
// Auto-trace state changes in dev mode via Svelte 5 $inspect
|
|
37
|
-
if ((import.meta as any).env?.DEV) {
|
|
38
|
-
// eslint-disable-next-line svelte/no-inspect
|
|
39
|
-
$inspect({ path, theme, colorTheme, locale, resourceCount: resources.length });
|
|
40
|
-
}
|
|
41
38
|
</script>
|
|
42
39
|
|
|
43
40
|
<svelte:window onkeydown={handleKeydown} />
|
|
@@ -56,14 +53,14 @@
|
|
|
56
53
|
<span>svadmin DevTools</span>
|
|
57
54
|
</div>
|
|
58
55
|
<div class="flex gap-1">
|
|
59
|
-
<TooltipButton tooltip={collapsed ? t('common.expand') : t('common.collapse')} variant="ghost" size="icon" class="h-6 w-6" onclick={() => collapsed = !collapsed}>
|
|
56
|
+
<TooltipButton tooltip={collapsed ? i18n.t('common.expand') : i18n.t('common.collapse')} variant="ghost" size="icon" class="h-6 w-6" onclick={() => collapsed = !collapsed}>
|
|
60
57
|
{#if collapsed}
|
|
61
58
|
<ChevronUp class="h-3.5 w-3.5" />
|
|
62
59
|
{:else}
|
|
63
60
|
<ChevronDown class="h-3.5 w-3.5" />
|
|
64
61
|
{/if}
|
|
65
62
|
</TooltipButton>
|
|
66
|
-
<TooltipButton tooltip={t('common.close')} variant="ghost" size="icon" class="h-6 w-6" onclick={toggle}>
|
|
63
|
+
<TooltipButton tooltip={i18n.t('common.close')} variant="ghost" size="icon" class="h-6 w-6" onclick={toggle}>
|
|
67
64
|
<X class="h-3.5 w-3.5" />
|
|
68
65
|
</TooltipButton>
|
|
69
66
|
</div>
|
|
@@ -138,7 +135,7 @@
|
|
|
138
135
|
</div>
|
|
139
136
|
{:else}
|
|
140
137
|
<TooltipButton
|
|
141
|
-
tooltip={t('devtools.title')}
|
|
138
|
+
tooltip={i18n.t('devtools.title')}
|
|
142
139
|
variant="default"
|
|
143
140
|
size="icon"
|
|
144
141
|
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"
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getResource } from '@svadmin/core';
|
|
3
|
-
import {
|
|
3
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
|
+
|
|
4
5
|
import * as Sheet from './ui/sheet/index.js';
|
|
5
6
|
import AutoForm from './AutoForm.svelte';
|
|
6
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
7
10
|
let { resourceName, mode = 'create', id, open = $bindable(false), side = 'right', onSuccess } = $props<{
|
|
8
11
|
resourceName: string;
|
|
9
12
|
mode?: 'create' | 'edit';
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
<Sheet.Content>
|
|
26
29
|
<Sheet.Header>
|
|
27
30
|
<Sheet.Title>
|
|
28
|
-
{mode === 'create' ? `${t('common.create')}${resource.label}` : `${t('common.edit')}${resource.label}`}
|
|
31
|
+
{mode === 'create' ? `${i18n.t('common.create')}${resource.label}` : `${i18n.t('common.edit')}${resource.label}`}
|
|
29
32
|
</Sheet.Title>
|
|
30
33
|
</Sheet.Header>
|
|
31
34
|
<div class="flex-1 overflow-y-auto">
|