@svadmin/ui 0.0.6 → 0.4.1
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/package.json +8 -3
- package/src/actions.ts +110 -0
- package/src/components/AdminApp.svelte +8 -4
- package/src/components/Authenticated.svelte +38 -13
- package/src/components/AutoForm.svelte +163 -74
- package/src/components/AutoSaveIndicator.svelte +35 -0
- package/src/components/AutoTable.svelte +476 -183
- package/src/components/Breadcrumbs.svelte +22 -17
- package/src/components/CatchAllNavigate.svelte +21 -0
- package/src/components/ComboboxField.svelte +122 -0
- package/src/components/CommandPalette.svelte +93 -0
- package/src/components/ConfigErrorScreen.svelte +53 -151
- package/src/components/ConfirmDialog.svelte +25 -17
- package/src/components/CreatePage.svelte +43 -0
- package/src/components/DevTools.svelte +99 -230
- package/src/components/DrawerForm.svelte +19 -10
- package/src/components/EditPage.svelte +71 -0
- package/src/components/EmptyState.svelte +21 -31
- package/src/components/ErrorBoundary.svelte +38 -40
- package/src/components/ErrorComponent.svelte +36 -0
- package/src/components/FieldRenderer.svelte +240 -75
- package/src/components/ForgotPasswordPage.svelte +20 -111
- package/src/components/Header.svelte +46 -57
- package/src/components/InferencerPanel.svelte +136 -110
- package/src/components/InfiniteList.svelte +93 -0
- package/src/components/Layout.svelte +85 -22
- package/src/components/ListPage.svelte +71 -0
- package/src/components/LiveIndicator.svelte +58 -0
- package/src/components/LoginPage.svelte +33 -154
- package/src/components/ModalForm.svelte +6 -2
- package/src/components/NavigateToResource.svelte +20 -0
- package/src/components/PageSkeleton.svelte +71 -0
- package/src/components/PasswordInput.svelte +95 -0
- package/src/components/RegisterPage.svelte +35 -164
- package/src/components/ShowPage.svelte +35 -36
- package/src/components/Sidebar.svelte +212 -81
- package/src/components/StatsCard.svelte +12 -3
- package/src/components/StepsForm.svelte +139 -0
- package/src/components/ThemedTitle.svelte +32 -0
- package/src/components/Toast.svelte +15 -44
- package/src/components/TooltipButton.svelte +52 -0
- package/src/components/UndoableNotification.svelte +28 -96
- package/src/components/UpdatePasswordPage.svelte +32 -160
- package/src/components/buttons/CloneButton.svelte +1 -1
- package/src/components/buttons/CreateButton.svelte +1 -1
- package/src/components/buttons/DeleteButton.svelte +3 -4
- package/src/components/buttons/EditButton.svelte +1 -1
- package/src/components/buttons/ImportButton.svelte +29 -7
- package/src/components/buttons/RefreshButton.svelte +11 -5
- package/src/components/fieldComponentMap.ts +79 -0
- package/src/components/fields/BooleanField.svelte +13 -0
- package/src/components/fields/DateField.svelte +6 -0
- package/src/components/fields/EmailField.svelte +9 -0
- package/src/components/fields/FileField.svelte +14 -0
- package/src/components/fields/ImageField.svelte +9 -0
- package/src/components/fields/JsonField.svelte +72 -0
- package/src/components/fields/MarkdownField.svelte +9 -0
- package/src/components/fields/MultiSelectField.svelte +20 -0
- package/src/components/fields/NumberField.svelte +6 -0
- package/src/components/fields/RelationField.svelte +24 -0
- package/src/components/fields/RichTextField.svelte +35 -0
- package/src/components/fields/SelectField.svelte +14 -0
- package/src/components/fields/TagField.svelte +12 -0
- package/src/components/fields/TextField.svelte +11 -0
- package/src/components/fields/UrlField.svelte +14 -0
- package/src/components/ui/alert-dialog/alert-dialog-content.svelte +25 -0
- package/src/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
- package/src/components/ui/alert-dialog/alert-dialog-footer.svelte +8 -0
- package/src/components/ui/alert-dialog/alert-dialog-header.svelte +8 -0
- package/src/components/ui/alert-dialog/alert-dialog-overlay.svelte +16 -0
- package/src/components/ui/alert-dialog/alert-dialog-portal.svelte +6 -0
- package/src/components/ui/alert-dialog/alert-dialog-title.svelte +16 -0
- package/src/components/ui/alert-dialog/index.ts +20 -0
- package/src/components/ui/avatar/avatar.svelte +2 -1
- package/src/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +18 -0
- package/src/components/ui/breadcrumb/breadcrumb-item.svelte +15 -0
- package/src/components/ui/breadcrumb/breadcrumb-link.svelte +15 -0
- package/src/components/ui/breadcrumb/breadcrumb-list.svelte +15 -0
- package/src/components/ui/breadcrumb/breadcrumb-page.svelte +18 -0
- package/src/components/ui/breadcrumb/breadcrumb-separator.svelte +22 -0
- package/src/components/ui/breadcrumb/breadcrumb.svelte +11 -0
- package/src/components/ui/breadcrumb/index.ts +7 -0
- package/src/components/ui/collapsible/index.ts +7 -0
- package/src/components/ui/command/command-dialog.svelte +31 -0
- package/src/components/ui/command/index.ts +2 -0
- package/src/components/ui/context-menu/index.ts +11 -0
- package/src/components/ui/drawer/drawer-content.svelte +21 -0
- package/src/components/ui/drawer/drawer-description.svelte +11 -0
- package/src/components/ui/drawer/drawer-footer.svelte +11 -0
- package/src/components/ui/drawer/drawer-header.svelte +11 -0
- package/src/components/ui/drawer/drawer-title.svelte +11 -0
- package/src/components/ui/drawer/drawer.svelte +18 -0
- package/src/components/ui/drawer/index.ts +6 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +27 -0
- package/src/components/ui/dropdown-menu/index.ts +6 -0
- package/src/components/ui/label/index.ts +1 -0
- package/src/components/ui/label/label.svelte +18 -0
- package/src/components/ui/pagination/index.ts +7 -0
- package/src/components/ui/pagination/pagination-content.svelte +11 -0
- package/src/components/ui/pagination/pagination-ellipsis.svelte +12 -0
- package/src/components/ui/pagination/pagination-item.svelte +11 -0
- package/src/components/ui/pagination/pagination-link.svelte +26 -0
- package/src/components/ui/pagination/pagination-next.svelte +22 -0
- package/src/components/ui/pagination/pagination-previous.svelte +22 -0
- package/src/components/ui/pagination/pagination.svelte +11 -0
- package/src/components/ui/popover/index.ts +12 -0
- package/src/components/ui/popover/popover-content.svelte +25 -0
- package/src/components/ui/progress/index.ts +1 -0
- package/src/components/ui/progress/progress.svelte +22 -0
- package/src/components/ui/scroll-area/index.ts +1 -0
- package/src/components/ui/scroll-area/scroll-area.svelte +20 -0
- package/src/components/ui/sheet/index.ts +15 -1
- package/src/components/ui/sheet/sheet-content.svelte +28 -0
- package/src/components/ui/sheet/sheet-description.svelte +22 -0
- package/src/components/ui/sheet/sheet-footer.svelte +22 -0
- package/src/components/ui/sheet/sheet-header.svelte +22 -0
- package/src/components/ui/sheet/sheet-title.svelte +22 -0
- package/src/index.ts +52 -1
- package/src/router-state.svelte.ts +16 -9
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: string | number | Date | null | undefined; locale?: string; options?: Intl.DateTimeFormatOptions }
|
|
3
|
+
let { value, locale = 'en-US', options = { dateStyle: 'medium' } }: Props = $props();
|
|
4
|
+
const formatted = $derived(value != null ? new Intl.DateTimeFormat(locale, options).format(new Date(value as string | number | Date)) : '—');
|
|
5
|
+
</script>
|
|
6
|
+
<span class="field-date">{formatted}</span>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: string | null | undefined }
|
|
3
|
+
let { value }: Props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
{#if value}
|
|
6
|
+
<a href="mailto:{value}" class="text-primary hover:underline no-underline">{value}</a>
|
|
7
|
+
{:else}
|
|
8
|
+
<span class="text-muted-foreground">—</span>
|
|
9
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Download } from 'lucide-svelte';
|
|
3
|
+
interface Props { value: string | null | undefined; title?: string }
|
|
4
|
+
let { value, title }: Props = $props();
|
|
5
|
+
const fileName = $derived(value ? value.split('/').pop() ?? value : null);
|
|
6
|
+
</script>
|
|
7
|
+
{#if value}
|
|
8
|
+
<a href={value} download class="text-primary hover:underline no-underline inline-flex items-center gap-1" title={title ?? fileName ?? ''}>
|
|
9
|
+
<Download class="h-3.5 w-3.5 opacity-60" />
|
|
10
|
+
{fileName}
|
|
11
|
+
</a>
|
|
12
|
+
{:else}
|
|
13
|
+
<span class="text-muted-foreground">—</span>
|
|
14
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: string | null | undefined; alt?: string; width?: number; height?: number }
|
|
3
|
+
let { value, alt = '', width = 80, height = 80 }: Props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
{#if value}
|
|
6
|
+
<img src={value} {alt} {width} {height} class="rounded-lg object-cover border border-border" />
|
|
7
|
+
{:else}
|
|
8
|
+
<span class="inline-flex items-center justify-center w-20 h-20 bg-muted rounded-lg text-muted-foreground">—</span>
|
|
9
|
+
{/if}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { t } from '@svadmin/core/i18n';
|
|
3
|
+
import { Button } from '../ui/button/index.js';
|
|
4
|
+
import { Copy, Check, ChevronDown, ChevronRight } from 'lucide-svelte';
|
|
5
|
+
|
|
6
|
+
let { value } = $props<{
|
|
7
|
+
value: unknown;
|
|
8
|
+
}>();
|
|
9
|
+
|
|
10
|
+
let expanded = $state(false);
|
|
11
|
+
let copied = $state(false);
|
|
12
|
+
let copyTimer: ReturnType<typeof setTimeout> | undefined;
|
|
13
|
+
|
|
14
|
+
$effect(() => {
|
|
15
|
+
return () => { if (copyTimer) clearTimeout(copyTimer); };
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const formatted = $derived(
|
|
19
|
+
value != null ? JSON.stringify(value, null, 2) : '—'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const preview = $derived(
|
|
23
|
+
value != null ? JSON.stringify(value).slice(0, 80) + (JSON.stringify(value).length > 80 ? '...' : '') : '—'
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
function copyJson() {
|
|
27
|
+
navigator.clipboard.writeText(formatted);
|
|
28
|
+
copied = true;
|
|
29
|
+
if (copyTimer) clearTimeout(copyTimer);
|
|
30
|
+
copyTimer = setTimeout(() => { copied = false; }, 2000);
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
{#if value == null}
|
|
35
|
+
<span class="text-muted-foreground">—</span>
|
|
36
|
+
{:else}
|
|
37
|
+
<div class="space-y-1">
|
|
38
|
+
<div class="flex items-center gap-2">
|
|
39
|
+
<Button
|
|
40
|
+
variant="ghost"
|
|
41
|
+
size="sm"
|
|
42
|
+
class="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground h-auto py-0.5 px-1"
|
|
43
|
+
onclick={() => { expanded = !expanded; }}
|
|
44
|
+
>
|
|
45
|
+
{#if expanded}
|
|
46
|
+
<ChevronDown class="h-3 w-3" />
|
|
47
|
+
{:else}
|
|
48
|
+
<ChevronRight class="h-3 w-3" />
|
|
49
|
+
{/if}
|
|
50
|
+
{expanded ? t('common.collapse') : t('common.expand')}
|
|
51
|
+
</Button>
|
|
52
|
+
<Button
|
|
53
|
+
variant="ghost"
|
|
54
|
+
size="sm"
|
|
55
|
+
class="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground h-auto py-0.5 px-1"
|
|
56
|
+
onclick={copyJson}
|
|
57
|
+
aria-label={t('common.copy')}
|
|
58
|
+
>
|
|
59
|
+
{#if copied}
|
|
60
|
+
<Check class="h-3 w-3 text-emerald-500" />
|
|
61
|
+
{:else}
|
|
62
|
+
<Copy class="h-3 w-3" />
|
|
63
|
+
{/if}
|
|
64
|
+
</Button>
|
|
65
|
+
</div>
|
|
66
|
+
{#if expanded}
|
|
67
|
+
<pre class="rounded-lg bg-muted p-3 text-xs overflow-auto max-h-64 font-mono">{formatted}</pre>
|
|
68
|
+
{:else}
|
|
69
|
+
<code class="text-xs font-mono bg-muted px-1.5 py-0.5 rounded">{preview}</code>
|
|
70
|
+
{/if}
|
|
71
|
+
</div>
|
|
72
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: string | null | undefined }
|
|
3
|
+
let { value }: Props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
{#if value}
|
|
6
|
+
<div class="prose prose-sm dark:prose-invert max-w-none leading-relaxed [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[0.875em] [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:rounded-lg [&_pre]:overflow-x-auto [&_a]:text-primary">{@html value}</div>
|
|
7
|
+
{:else}
|
|
8
|
+
<span class="text-muted-foreground">—</span>
|
|
9
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge } from '../ui/badge/index.js';
|
|
3
|
+
|
|
4
|
+
let { value } = $props<{
|
|
5
|
+
value: (string | number)[] | null | undefined;
|
|
6
|
+
options?: { label: string; value: string | number }[];
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const items = $derived(Array.isArray(value) ? value : []);
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if items.length > 0}
|
|
13
|
+
<div class="flex flex-wrap gap-1">
|
|
14
|
+
{#each items as item}
|
|
15
|
+
<Badge variant="secondary">{String(item)}</Badge>
|
|
16
|
+
{/each}
|
|
17
|
+
</div>
|
|
18
|
+
{:else}
|
|
19
|
+
<span class="text-muted-foreground">—</span>
|
|
20
|
+
{/if}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: number | string | null | undefined; locale?: string; options?: Intl.NumberFormatOptions }
|
|
3
|
+
let { value, locale = 'en-US', options = {} }: Props = $props();
|
|
4
|
+
const formatted = $derived(value != null ? new Intl.NumberFormat(locale, options).format(Number(value)) : '—');
|
|
5
|
+
</script>
|
|
6
|
+
<span class="field-number">{formatted}</span>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ExternalLink } from 'lucide-svelte';
|
|
3
|
+
|
|
4
|
+
let { value, resourceName, displayValue } = $props<{
|
|
5
|
+
value: string | number | null | undefined;
|
|
6
|
+
resourceName?: string;
|
|
7
|
+
displayValue?: string;
|
|
8
|
+
}>();
|
|
9
|
+
|
|
10
|
+
const display = $derived(displayValue ?? (value != null ? `#${value}` : '—'));
|
|
11
|
+
const href = $derived(resourceName && value != null ? `#/${resourceName}/show/${value}` : undefined);
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if href}
|
|
15
|
+
<a
|
|
16
|
+
{href}
|
|
17
|
+
class="inline-flex items-center gap-1 text-primary hover:underline text-sm"
|
|
18
|
+
>
|
|
19
|
+
{display}
|
|
20
|
+
<ExternalLink class="h-3 w-3" />
|
|
21
|
+
</a>
|
|
22
|
+
{:else}
|
|
23
|
+
<span class="text-muted-foreground">{display}</span>
|
|
24
|
+
{/if}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { t } from '@svadmin/core/i18n';
|
|
3
|
+
import { Button } from '../ui/button/index.js';
|
|
4
|
+
|
|
5
|
+
let { value, maxLength = 200 } = $props<{
|
|
6
|
+
value: string | null | undefined;
|
|
7
|
+
maxLength?: number;
|
|
8
|
+
}>();
|
|
9
|
+
|
|
10
|
+
const text = $derived(value ?? '');
|
|
11
|
+
const truncated = $derived(text.length > maxLength);
|
|
12
|
+
const display = $derived(truncated ? text.slice(0, maxLength) + '...' : text);
|
|
13
|
+
|
|
14
|
+
let showFull = $state(false);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if !text}
|
|
18
|
+
<span class="text-muted-foreground">—</span>
|
|
19
|
+
{:else}
|
|
20
|
+
<div class="prose prose-sm dark:prose-invert max-w-none">
|
|
21
|
+
<p class="whitespace-pre-wrap text-sm leading-relaxed">
|
|
22
|
+
{showFull ? text : display}
|
|
23
|
+
</p>
|
|
24
|
+
{#if truncated}
|
|
25
|
+
<Button
|
|
26
|
+
variant="link"
|
|
27
|
+
size="sm"
|
|
28
|
+
class="text-xs text-primary h-auto p-0"
|
|
29
|
+
onclick={() => { showFull = !showFull; }}
|
|
30
|
+
>
|
|
31
|
+
{showFull ? t('common.showLess') : t('common.showMore')}
|
|
32
|
+
</Button>
|
|
33
|
+
{/if}
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge } from '../ui/badge/index.js';
|
|
3
|
+
|
|
4
|
+
let { value, options } = $props<{
|
|
5
|
+
value: string | number | null | undefined;
|
|
6
|
+
options?: { label: string; value: string | number }[];
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const label = $derived(
|
|
10
|
+
options?.find(o => o.value === value)?.label ?? (value != null ? String(value) : '—')
|
|
11
|
+
);
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Badge variant="outline">{label}</Badge>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge } from '../ui/badge/index.js';
|
|
3
|
+
interface Props { value: string | string[] | null | undefined }
|
|
4
|
+
let { value }: Props = $props();
|
|
5
|
+
const tags = $derived(Array.isArray(value) ? value : value ? [value] : []);
|
|
6
|
+
</script>
|
|
7
|
+
<span class="inline-flex flex-wrap gap-1">
|
|
8
|
+
{#each tags as tag}
|
|
9
|
+
<Badge variant="secondary">{tag}</Badge>
|
|
10
|
+
{/each}
|
|
11
|
+
{#if tags.length === 0}<span class="text-muted-foreground">—</span>{/if}
|
|
12
|
+
</span>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props { value: string | null | undefined; maxLength?: number }
|
|
3
|
+
let { value, maxLength }: Props = $props();
|
|
4
|
+
const display = $derived(value && maxLength && value.length > maxLength ? value.slice(0, maxLength) + '…' : value);
|
|
5
|
+
const needsTooltip = $derived(value && maxLength && value.length > maxLength);
|
|
6
|
+
</script>
|
|
7
|
+
{#if value}
|
|
8
|
+
<span class="inline-block" title={needsTooltip ? value : undefined}>{display}</span>
|
|
9
|
+
{:else}
|
|
10
|
+
<span class="text-muted-foreground">—</span>
|
|
11
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ExternalLink } from 'lucide-svelte';
|
|
3
|
+
interface Props { value: string | null | undefined; label?: string }
|
|
4
|
+
let { value, label }: Props = $props();
|
|
5
|
+
const display = $derived(label ?? value ?? '');
|
|
6
|
+
</script>
|
|
7
|
+
{#if value}
|
|
8
|
+
<a href={value} target="_blank" rel="noopener noreferrer" class="text-primary hover:underline no-underline inline-flex items-center gap-1">
|
|
9
|
+
{display}
|
|
10
|
+
<ExternalLink class="h-3 w-3 opacity-60" />
|
|
11
|
+
</a>
|
|
12
|
+
{:else}
|
|
13
|
+
<span class="text-muted-foreground">—</span>
|
|
14
|
+
{/if}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
|
3
|
+
import type { WithoutChildrenOrChild } from "bits-ui";
|
|
4
|
+
import { cn } from "../../../utils.js";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithoutChildrenOrChild<AlertDialogPrimitive.ContentProps> & { class?: string } = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<AlertDialogPrimitive.Portal>
|
|
14
|
+
<AlertDialogPrimitive.Overlay
|
|
15
|
+
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
16
|
+
/>
|
|
17
|
+
<AlertDialogPrimitive.Content
|
|
18
|
+
bind:ref
|
|
19
|
+
class={cn(
|
|
20
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
21
|
+
className,
|
|
22
|
+
)}
|
|
23
|
+
{...restProps}
|
|
24
|
+
/>
|
|
25
|
+
</AlertDialogPrimitive.Portal>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: AlertDialogPrimitive.DescriptionProps & { class?: string } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<AlertDialogPrimitive.Description
|
|
13
|
+
bind:ref
|
|
14
|
+
class={cn("text-sm text-muted-foreground", className)}
|
|
15
|
+
{...restProps}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
|
|
5
|
+
let { class: className, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...restProps}></div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
|
|
5
|
+
let { class: className, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...restProps}></div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: AlertDialogPrimitive.OverlayProps & { class?: string } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<AlertDialogPrimitive.Overlay
|
|
13
|
+
bind:ref
|
|
14
|
+
class={cn("fixed inset-0 z-50 bg-black/80", className)}
|
|
15
|
+
{...restProps}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
...restProps
|
|
9
|
+
}: AlertDialogPrimitive.TitleProps & { class?: string } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<AlertDialogPrimitive.Title
|
|
13
|
+
bind:ref
|
|
14
|
+
class={cn("text-lg font-semibold", className)}
|
|
15
|
+
{...restProps}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
|
2
|
+
|
|
3
|
+
const Root = AlertDialogPrimitive.Root;
|
|
4
|
+
const Trigger = AlertDialogPrimitive.Trigger;
|
|
5
|
+
const Action = AlertDialogPrimitive.Action;
|
|
6
|
+
const Cancel = AlertDialogPrimitive.Cancel;
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
Root,
|
|
10
|
+
Trigger,
|
|
11
|
+
Action,
|
|
12
|
+
Cancel,
|
|
13
|
+
};
|
|
14
|
+
export { default as Content } from "./alert-dialog-content.svelte";
|
|
15
|
+
export { default as Description } from "./alert-dialog-description.svelte";
|
|
16
|
+
export { default as Footer } from "./alert-dialog-footer.svelte";
|
|
17
|
+
export { default as Header } from "./alert-dialog-header.svelte";
|
|
18
|
+
export { default as Overlay } from "./alert-dialog-overlay.svelte";
|
|
19
|
+
export { default as Portal } from "./alert-dialog-portal.svelte";
|
|
20
|
+
export { default as Title } from "./alert-dialog-title.svelte";
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
defaultVariants: { size: "default" },
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// AvatarSize type is exported from the package index.ts
|
|
20
|
+
type AvatarSize = VariantProps<typeof avatarVariants>["size"];
|
|
20
21
|
|
|
21
22
|
type Props = WithElementRef<HTMLImgAttributes> & {
|
|
22
23
|
size?: AvatarSize;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { Ellipsis } from 'lucide-svelte';
|
|
5
|
+
|
|
6
|
+
let { class: className, ...restProps }: HTMLAttributes<HTMLSpanElement> = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<span
|
|
10
|
+
role="presentation"
|
|
11
|
+
aria-hidden="true"
|
|
12
|
+
data-slot="breadcrumb-ellipsis"
|
|
13
|
+
class={cn("flex size-9 items-center justify-center", className)}
|
|
14
|
+
{...restProps}
|
|
15
|
+
>
|
|
16
|
+
<Ellipsis class="size-4" />
|
|
17
|
+
<span class="sr-only">More</span>
|
|
18
|
+
</span>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLLiAttributes } from 'svelte/elements';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: HTMLLiAttributes & { children?: Snippet } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<li
|
|
10
|
+
data-slot="breadcrumb-item"
|
|
11
|
+
class={cn("inline-flex items-center gap-1.5", className)}
|
|
12
|
+
{...restProps}
|
|
13
|
+
>
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</li>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: HTMLAnchorAttributes & { children?: Snippet } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<a
|
|
10
|
+
data-slot="breadcrumb-link"
|
|
11
|
+
class={cn("hover:text-foreground transition-colors", className)}
|
|
12
|
+
{...restProps}
|
|
13
|
+
>
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</a>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLOlAttributes } from 'svelte/elements';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: HTMLOlAttributes & { children?: Snippet } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<ol
|
|
10
|
+
data-slot="breadcrumb-list"
|
|
11
|
+
class={cn("text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5", className)}
|
|
12
|
+
{...restProps}
|
|
13
|
+
>
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</ol>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLSpanElement> & { children?: Snippet } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<span
|
|
10
|
+
role="link"
|
|
11
|
+
aria-disabled="true"
|
|
12
|
+
aria-current="page"
|
|
13
|
+
data-slot="breadcrumb-page"
|
|
14
|
+
class={cn("text-foreground font-normal", className)}
|
|
15
|
+
{...restProps}
|
|
16
|
+
>
|
|
17
|
+
{@render children?.()}
|
|
18
|
+
</span>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLLiAttributes } from 'svelte/elements';
|
|
5
|
+
import { ChevronRight } from 'lucide-svelte';
|
|
6
|
+
|
|
7
|
+
let { class: className, children, ...restProps }: HTMLLiAttributes & { children?: Snippet } = $props();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<li
|
|
11
|
+
role="presentation"
|
|
12
|
+
aria-hidden="true"
|
|
13
|
+
data-slot="breadcrumb-separator"
|
|
14
|
+
class={cn("[&>svg]:size-3.5", className)}
|
|
15
|
+
{...restProps}
|
|
16
|
+
>
|
|
17
|
+
{#if children}
|
|
18
|
+
{@render children()}
|
|
19
|
+
{:else}
|
|
20
|
+
<ChevronRight />
|
|
21
|
+
{/if}
|
|
22
|
+
</li>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../../utils.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLElement> & { children?: Snippet } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<nav aria-label="breadcrumb" data-slot="breadcrumb" class={cn("", className)} {...restProps}>
|
|
10
|
+
{@render children?.()}
|
|
11
|
+
</nav>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as Root } from './breadcrumb.svelte';
|
|
2
|
+
export { default as Item } from './breadcrumb-item.svelte';
|
|
3
|
+
export { default as Link } from './breadcrumb-link.svelte';
|
|
4
|
+
export { default as Page } from './breadcrumb-page.svelte';
|
|
5
|
+
export { default as Separator } from './breadcrumb-separator.svelte';
|
|
6
|
+
export { default as Ellipsis } from './breadcrumb-ellipsis.svelte';
|
|
7
|
+
export { default as List } from './breadcrumb-list.svelte';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Command } from 'cmdk-sv';
|
|
3
|
+
import * as Dialog from '../dialog/index.js';
|
|
4
|
+
import { cn } from '../../../utils.js';
|
|
5
|
+
import type { Snippet } from 'svelte';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
open = $bindable(false),
|
|
9
|
+
class: className,
|
|
10
|
+
children,
|
|
11
|
+
...restProps
|
|
12
|
+
}: {
|
|
13
|
+
open?: boolean;
|
|
14
|
+
class?: string;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
} = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Dialog.Dialog bind:open {...restProps}>
|
|
21
|
+
<Dialog.DialogContent class="overflow-hidden p-0">
|
|
22
|
+
<Command.Root
|
|
23
|
+
class={cn(
|
|
24
|
+
"[&_[data-cmdk-group-heading]]:text-muted-foreground flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground [&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:font-medium [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 [&_[data-cmdk-input]]:h-12 [&_[data-cmdk-item]]:px-2 [&_[data-cmdk-item]]:py-3",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
{@render children?.()}
|
|
29
|
+
</Command.Root>
|
|
30
|
+
</Dialog.DialogContent>
|
|
31
|
+
</Dialog.Dialog>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
|
2
|
+
|
|
3
|
+
const Root = ContextMenuPrimitive.Root;
|
|
4
|
+
const Trigger = ContextMenuPrimitive.Trigger;
|
|
5
|
+
const Content = ContextMenuPrimitive.Content;
|
|
6
|
+
const Item = ContextMenuPrimitive.Item;
|
|
7
|
+
const Separator = ContextMenuPrimitive.Separator;
|
|
8
|
+
const Group = ContextMenuPrimitive.Group;
|
|
9
|
+
const GroupHeading = ContextMenuPrimitive.GroupHeading;
|
|
10
|
+
|
|
11
|
+
export { Root, Trigger, Content, Item, Separator, Group, GroupHeading };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Drawer as DrawerPrimitive } from 'vaul-svelte';
|
|
3
|
+
import { cn } from '../../../utils.js';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: { class?: string; children?: Snippet; [key: string]: unknown } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<DrawerPrimitive.Portal>
|
|
10
|
+
<DrawerPrimitive.Overlay class="fixed inset-0 z-50 bg-black/80" />
|
|
11
|
+
<DrawerPrimitive.Content
|
|
12
|
+
class={cn(
|
|
13
|
+
"bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border",
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
{...restProps}
|
|
17
|
+
>
|
|
18
|
+
<div class="bg-muted mx-auto mt-4 h-2 w-[100px] rounded-full"></div>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</DrawerPrimitive.Content>
|
|
21
|
+
</DrawerPrimitive.Portal>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Drawer as DrawerPrimitive } from 'vaul-svelte';
|
|
3
|
+
import { cn } from '../../../utils.js';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
|
|
6
|
+
let { class: className, children, ...restProps }: { class?: string; children?: Snippet; [key: string]: unknown } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<DrawerPrimitive.Description class={cn("text-muted-foreground text-sm", className)} {...restProps}>
|
|
10
|
+
{@render children?.()}
|
|
11
|
+
</DrawerPrimitive.Description>
|