refactor: improve code consistency and formatting across components
CI / changes (push) Successful in 7s
CI / openapi (push) Has been skipped
CI / web (push) Successful in 29s
CI / go (push) Has been skipped
CI / docker-web (push) Successful in 1m22s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go (push) Has been skipped
CI / changes (push) Successful in 7s
CI / openapi (push) Has been skipped
CI / web (push) Successful in 29s
CI / go (push) Has been skipped
CI / docker-web (push) Successful in 1m22s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go (push) Has been skipped
- Standardized formatting in various Svelte components for better readability. - Updated README.md and .prettierrc for consistent styling and improved documentation. - Refactored class attributes in UI components to enhance clarity and maintainability. - Adjusted layout files to ensure proper alignment and spacing in the application interface.
This commit is contained in:
+1
-4
@@ -3,10 +3,7 @@
|
|||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"printWidth": 100,
|
"printWidth": 100,
|
||||||
"plugins": [
|
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
||||||
"prettier-plugin-svelte",
|
|
||||||
"prettier-plugin-tailwindcss"
|
|
||||||
],
|
|
||||||
"tailwindStylesheet": "./src/routes/layout.css",
|
"tailwindStylesheet": "./src/routes/layout.css",
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
|
|||||||
Vendored
+1
-5
@@ -1,7 +1,3 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": ["svelte.svelte-vscode", "bradlc.vscode-tailwindcss", "esbenp.prettier-vscode"]
|
||||||
"svelte.svelte-vscode",
|
|
||||||
"bradlc.vscode-tailwindcss",
|
|
||||||
"esbenp.prettier-vscode"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -6,12 +6,12 @@ SvelteKit-приложение панели управления EvoBGP. Зап
|
|||||||
|
|
||||||
## UI-архитектура
|
## UI-архитектура
|
||||||
|
|
||||||
| Путь | Назначение |
|
| Путь | Назначение |
|
||||||
|------|------------|
|
| ------------------------ | ------------------------------------------------------------------- |
|
||||||
| `src/lib/ui/core/` | shadcn-svelte (только через `npx shadcn-svelte@latest add … -y -o`) |
|
| `src/lib/ui/core/` | shadcn-svelte (только через `npx shadcn-svelte@latest add … -y -o`) |
|
||||||
| `src/lib/ui/app/` | Layout, PageHeader, toast (`notify`) |
|
| `src/lib/ui/app/` | Layout, PageHeader, toast (`notify`) |
|
||||||
| `src/lib/ui/patterns/` | FormField, AppDataTable, ConfirmDialog, EmptyState |
|
| `src/lib/ui/patterns/` | FormField, AppDataTable, ConfirmDialog, EmptyState |
|
||||||
| `src/lib/components/ui/` | Re-export на `ui/core` (совместимость) |
|
| `src/lib/components/ui/` | Re-export на `ui/core` (совместимость) |
|
||||||
|
|
||||||
Токены темы: `src/routes/layout.css`. Справочник: `src/lib/ui/app/tokens.md`.
|
Токены темы: `src/routes/layout.css`. Справочник: `src/lib/ui/app/tokens.md`.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { RevisionDiff, RevisionPrefix, RevisionRow } from '$lib/api/types.js';
|
import type { RevisionDiff, RevisionPrefix, RevisionRow } from '$lib/api/types.js';
|
||||||
import { Button } from '$lib/components/ui/button/index.js';
|
import { Button } from '$lib/components/ui/button/index.js';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle
|
||||||
|
} from '$lib/components/ui/card/index.js';
|
||||||
import { sortRevisionDiffItems } from '$lib/sort-prefixes.js';
|
import { sortRevisionDiffItems } from '$lib/sort-prefixes.js';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -79,7 +85,7 @@
|
|||||||
<select
|
<select
|
||||||
value={diffRevA}
|
value={diffRevA}
|
||||||
onchange={(e) => onDiffRevAChange((e.currentTarget as HTMLSelectElement).value)}
|
onchange={(e) => onDiffRevAChange((e.currentTarget as HTMLSelectElement).value)}
|
||||||
class="border-border bg-background h-8 min-w-0 flex-1 rounded-md border px-2 text-sm"
|
class="h-8 min-w-0 flex-1 rounded-md border border-border bg-background px-2 text-sm"
|
||||||
>
|
>
|
||||||
<option value="">Ревизия A</option>
|
<option value="">Ревизия A</option>
|
||||||
{#each revisions as rev (rev.id)}
|
{#each revisions as rev (rev.id)}
|
||||||
@@ -89,51 +95,58 @@
|
|||||||
<select
|
<select
|
||||||
value={diffRevB}
|
value={diffRevB}
|
||||||
onchange={(e) => onDiffRevBChange((e.currentTarget as HTMLSelectElement).value)}
|
onchange={(e) => onDiffRevBChange((e.currentTarget as HTMLSelectElement).value)}
|
||||||
class="border-border bg-background h-8 min-w-0 flex-1 rounded-md border px-2 text-sm"
|
class="h-8 min-w-0 flex-1 rounded-md border border-border bg-background px-2 text-sm"
|
||||||
>
|
>
|
||||||
<option value="">Ревизия B</option>
|
<option value="">Ревизия B</option>
|
||||||
{#each revisions as rev (rev.id)}
|
{#each revisions as rev (rev.id)}
|
||||||
<option value={rev.id}>{rev.id.slice(0, 8)}… ({formatDate(rev.created_at)})</option>
|
<option value={rev.id}>{rev.id.slice(0, 8)}… ({formatDate(rev.created_at)})</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
<Button size="sm" class="shrink-0 self-start sm:self-auto" onclick={onLoadDiff} disabled={diffLoading}>
|
<Button
|
||||||
|
size="sm"
|
||||||
|
class="shrink-0 self-start sm:self-auto"
|
||||||
|
onclick={onLoadDiff}
|
||||||
|
disabled={diffLoading}
|
||||||
|
>
|
||||||
{diffLoading ? 'Загрузка…' : 'Сравнить'}
|
{diffLoading ? 'Загрузка…' : 'Сравнить'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if diffData}
|
{#if diffData}
|
||||||
<div
|
<div
|
||||||
class="border-border grid min-h-0 grid-cols-1 overflow-hidden rounded-md border sm:grid-cols-2"
|
class="grid min-h-0 grid-cols-1 overflow-hidden rounded-md border border-border sm:grid-cols-2"
|
||||||
style="scrollbar-gutter: stable;"
|
style="scrollbar-gutter: stable;"
|
||||||
>
|
>
|
||||||
<!-- + Добавлено -->
|
<!-- + Добавлено -->
|
||||||
<div class="border-border flex min-h-0 min-w-0 flex-col border-b sm:border-r sm:border-b-0">
|
<div class="flex min-h-0 min-w-0 flex-col border-b border-border sm:border-r sm:border-b-0">
|
||||||
<div
|
<div
|
||||||
class="border-border bg-muted/60 flex shrink-0 items-center border-b px-3 py-2 font-mono text-xs font-semibold text-green-600 dark:text-green-400"
|
class="flex shrink-0 items-center border-b border-border bg-muted/60 px-3 py-2 font-mono text-xs font-semibold text-green-600 dark:text-green-400"
|
||||||
>
|
>
|
||||||
<span class="text-muted-foreground mr-2 w-10 shrink-0 select-none text-right">+</span>
|
<span class="mr-2 w-10 shrink-0 text-right text-muted-foreground select-none">+</span>
|
||||||
<span>Добавлено ({addedSorted.length})</span>
|
<span>Добавлено ({addedSorted.length})</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
bind:this={scrollAddedEl}
|
bind:this={scrollAddedEl}
|
||||||
class="bg-background/50 max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain"
|
class="max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain bg-background/50"
|
||||||
onscroll={syncFromAdded}
|
onscroll={syncFromAdded}
|
||||||
>
|
>
|
||||||
{#if addedSorted.length === 0}
|
{#if addedSorted.length === 0}
|
||||||
<p class="text-muted-foreground p-3 font-mono text-xs">Нет изменений</p>
|
<p class="p-3 font-mono text-xs text-muted-foreground">Нет изменений</p>
|
||||||
{:else}
|
{:else}
|
||||||
<table class="w-full border-collapse font-mono text-xs">
|
<table class="w-full border-collapse font-mono text-xs">
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each addedSorted as line, i (`a-${i}-${line}`)}
|
{#each addedSorted as line, i (`a-${i}-${line}`)}
|
||||||
<tr
|
<tr
|
||||||
class="border-border/50 hover:bg-muted/30 border-b border-l-2 border-l-green-500/80 bg-green-500/[0.08] dark:bg-green-500/15"
|
class="border-b border-l-2 border-border/50 border-l-green-500/80 bg-green-500/[0.08] hover:bg-muted/30 dark:bg-green-500/15"
|
||||||
>
|
>
|
||||||
<td
|
<td
|
||||||
class="text-muted-foreground w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] tabular-nums select-none"
|
class="w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] text-muted-foreground tabular-nums select-none"
|
||||||
>
|
>
|
||||||
{i + 1}
|
{i + 1}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-foreground max-w-0 break-all py-0.5 pr-3 pl-1 whitespace-pre-wrap">
|
<td
|
||||||
|
class="max-w-0 py-0.5 pr-3 pl-1 break-all whitespace-pre-wrap text-foreground"
|
||||||
|
>
|
||||||
{line}
|
{line}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -147,31 +160,33 @@
|
|||||||
<!-- − Удалено -->
|
<!-- − Удалено -->
|
||||||
<div class="flex min-h-0 min-w-0 flex-col">
|
<div class="flex min-h-0 min-w-0 flex-col">
|
||||||
<div
|
<div
|
||||||
class="border-border bg-muted/60 flex shrink-0 items-center border-b px-3 py-2 font-mono text-xs font-semibold text-red-600 dark:text-red-400"
|
class="flex shrink-0 items-center border-b border-border bg-muted/60 px-3 py-2 font-mono text-xs font-semibold text-red-600 dark:text-red-400"
|
||||||
>
|
>
|
||||||
<span class="text-muted-foreground mr-2 w-10 shrink-0 select-none text-right">−</span>
|
<span class="mr-2 w-10 shrink-0 text-right text-muted-foreground select-none">−</span>
|
||||||
<span>Удалено ({removedSorted.length})</span>
|
<span>Удалено ({removedSorted.length})</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
bind:this={scrollRemovedEl}
|
bind:this={scrollRemovedEl}
|
||||||
class="bg-background/50 max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain"
|
class="max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain bg-background/50"
|
||||||
onscroll={syncFromRemoved}
|
onscroll={syncFromRemoved}
|
||||||
>
|
>
|
||||||
{#if removedSorted.length === 0}
|
{#if removedSorted.length === 0}
|
||||||
<p class="text-muted-foreground p-3 font-mono text-xs">Нет изменений</p>
|
<p class="p-3 font-mono text-xs text-muted-foreground">Нет изменений</p>
|
||||||
{:else}
|
{:else}
|
||||||
<table class="w-full border-collapse font-mono text-xs">
|
<table class="w-full border-collapse font-mono text-xs">
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each removedSorted as line, i (`r-${i}-${line}`)}
|
{#each removedSorted as line, i (`r-${i}-${line}`)}
|
||||||
<tr
|
<tr
|
||||||
class="border-border/50 hover:bg-muted/30 border-b border-l-2 border-l-red-500/80 bg-red-500/[0.08] dark:bg-red-500/15"
|
class="border-b border-l-2 border-border/50 border-l-red-500/80 bg-red-500/[0.08] hover:bg-muted/30 dark:bg-red-500/15"
|
||||||
>
|
>
|
||||||
<td
|
<td
|
||||||
class="text-muted-foreground w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] tabular-nums select-none"
|
class="w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] text-muted-foreground tabular-nums select-none"
|
||||||
>
|
>
|
||||||
{i + 1}
|
{i + 1}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-foreground max-w-0 break-all py-0.5 pr-3 pl-1 whitespace-pre-wrap">
|
<td
|
||||||
|
class="max-w-0 py-0.5 pr-3 pl-1 break-all whitespace-pre-wrap text-foreground"
|
||||||
|
>
|
||||||
{line}
|
{line}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
<div class="space-y-3 rounded-lg border border-border/80 bg-muted/15 p-3">
|
<div class="space-y-3 rounded-lg border border-border/80 bg-muted/15 p-3">
|
||||||
<div class="flex flex-wrap items-center gap-2">
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
<Filter class="text-muted-foreground size-4 shrink-0" aria-hidden="true" />
|
<Filter class="size-4 shrink-0 text-muted-foreground" aria-hidden="true" />
|
||||||
<span class="text-sm font-medium">Фильтры задач</span>
|
<span class="text-sm font-medium">Фильтры задач</span>
|
||||||
<div class="ml-auto flex flex-wrap gap-1.5">
|
<div class="ml-auto flex flex-wrap gap-1.5">
|
||||||
<Button
|
<Button
|
||||||
@@ -84,7 +84,14 @@
|
|||||||
>
|
>
|
||||||
В работе
|
В работе
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="button" variant="ghost" size="sm" class="h-7 text-xs" {disabled} onclick={onResetFilters}>
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
class="h-7 text-xs"
|
||||||
|
{disabled}
|
||||||
|
onclick={onResetFilters}
|
||||||
|
>
|
||||||
<X class="size-3.5" aria-hidden="true" />
|
<X class="size-3.5" aria-hidden="true" />
|
||||||
Сброс
|
Сброс
|
||||||
</Button>
|
</Button>
|
||||||
@@ -93,7 +100,7 @@
|
|||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<Search
|
<Search
|
||||||
class="text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2"
|
class="pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
@@ -113,7 +120,7 @@
|
|||||||
<Label for="job-filter-status" class="text-xs">Статус</Label>
|
<Label for="job-filter-status" class="text-xs">Статус</Label>
|
||||||
<select
|
<select
|
||||||
id="job-filter-status"
|
id="job-filter-status"
|
||||||
class="border-border bg-background h-9 w-full rounded-md border px-2 text-sm"
|
class="h-9 w-full rounded-md border border-border bg-background px-2 text-sm"
|
||||||
value={filterStatus}
|
value={filterStatus}
|
||||||
onchange={(e) => onFilterStatusChange((e.currentTarget as HTMLSelectElement).value)}
|
onchange={(e) => onFilterStatusChange((e.currentTarget as HTMLSelectElement).value)}
|
||||||
{disabled}
|
{disabled}
|
||||||
@@ -127,7 +134,7 @@
|
|||||||
<Label for="job-filter-kind" class="text-xs">Тип задачи</Label>
|
<Label for="job-filter-kind" class="text-xs">Тип задачи</Label>
|
||||||
<select
|
<select
|
||||||
id="job-filter-kind"
|
id="job-filter-kind"
|
||||||
class="border-border bg-background h-9 w-full rounded-md border px-2 text-sm"
|
class="h-9 w-full rounded-md border border-border bg-background px-2 text-sm"
|
||||||
value={filterKind}
|
value={filterKind}
|
||||||
onchange={(e) => onFilterKindChange((e.currentTarget as HTMLSelectElement).value)}
|
onchange={(e) => onFilterKindChange((e.currentTarget as HTMLSelectElement).value)}
|
||||||
{disabled}
|
{disabled}
|
||||||
@@ -141,7 +148,7 @@
|
|||||||
<Label for="job-filter-module" class="text-xs">Модуль (локально)</Label>
|
<Label for="job-filter-module" class="text-xs">Модуль (локально)</Label>
|
||||||
<select
|
<select
|
||||||
id="job-filter-module"
|
id="job-filter-module"
|
||||||
class="border-border bg-background h-9 w-full rounded-md border px-2 text-sm"
|
class="h-9 w-full rounded-md border border-border bg-background px-2 text-sm"
|
||||||
value={filterModuleId}
|
value={filterModuleId}
|
||||||
onchange={(e) => onFilterModuleIdChange((e.currentTarget as HTMLSelectElement).value)}
|
onchange={(e) => onFilterModuleIdChange((e.currentTarget as HTMLSelectElement).value)}
|
||||||
{disabled}
|
{disabled}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
<CardDescription class="flex flex-wrap items-center gap-x-2 gap-y-1">
|
<CardDescription class="flex flex-wrap items-center gap-x-2 gap-y-1">
|
||||||
<span>Фоновые задачи (ingest, применение, обновление)</span>
|
<span>Фоновые задачи (ingest, применение, обновление)</span>
|
||||||
{#if jobsFetchedTotal !== undefined}
|
{#if jobsFetchedTotal !== undefined}
|
||||||
<span class="text-muted-foreground font-normal tabular-nums">
|
<span class="font-normal text-muted-foreground tabular-nums">
|
||||||
· Показано {jobs.length} из {jobsFetchedTotal}
|
· Показано {jobs.length} из {jobsFetchedTotal}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -163,20 +163,18 @@
|
|||||||
<div
|
<div
|
||||||
class="rounded-md border border-chart-1/25 bg-chart-1/5 px-2.5 py-2 dark:bg-chart-1/10"
|
class="rounded-md border border-chart-1/25 bg-chart-1/5 px-2.5 py-2 dark:bg-chart-1/10"
|
||||||
>
|
>
|
||||||
<p
|
<p class="flex items-center gap-1 text-[11px] font-medium text-chart-1 uppercase">
|
||||||
class="text-chart-1 flex items-center gap-1 text-[11px] font-medium uppercase"
|
|
||||||
>
|
|
||||||
<CircleDot class="size-3.5 shrink-0" aria-hidden="true" />
|
<CircleDot class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Статус
|
Статус
|
||||||
</p>
|
</p>
|
||||||
<Badge class="mt-1" variant={jobStatusVariant(job.status)}>{jobStatusRu(job.status)}</Badge>
|
<Badge class="mt-1" variant={jobStatusVariant(job.status)}
|
||||||
|
>{jobStatusRu(job.status)}</Badge
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="rounded-md border border-chart-2/25 bg-chart-2/5 px-2.5 py-2 dark:bg-chart-2/10"
|
class="rounded-md border border-chart-2/25 bg-chart-2/5 px-2.5 py-2 dark:bg-chart-2/10"
|
||||||
>
|
>
|
||||||
<p
|
<p class="flex items-center gap-1 text-[11px] font-medium text-chart-2 uppercase">
|
||||||
class="text-chart-2 flex items-center gap-1 text-[11px] font-medium uppercase"
|
|
||||||
>
|
|
||||||
<CalendarClock class="size-3.5 shrink-0" aria-hidden="true" />
|
<CalendarClock class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Создана
|
Создана
|
||||||
</p>
|
</p>
|
||||||
@@ -185,9 +183,7 @@
|
|||||||
<div
|
<div
|
||||||
class="rounded-md border border-chart-3/25 bg-chart-3/5 px-2.5 py-2 dark:bg-chart-3/10"
|
class="rounded-md border border-chart-3/25 bg-chart-3/5 px-2.5 py-2 dark:bg-chart-3/10"
|
||||||
>
|
>
|
||||||
<p
|
<p class="flex items-center gap-1 text-[11px] font-medium text-chart-3 uppercase">
|
||||||
class="text-chart-3 flex items-center gap-1 text-[11px] font-medium uppercase"
|
|
||||||
>
|
|
||||||
<PlayCircle class="size-3.5 shrink-0" aria-hidden="true" />
|
<PlayCircle class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Запущена
|
Запущена
|
||||||
</p>
|
</p>
|
||||||
@@ -196,9 +192,7 @@
|
|||||||
<div
|
<div
|
||||||
class="rounded-md border border-chart-4/25 bg-chart-4/5 px-2.5 py-2 dark:bg-chart-4/10"
|
class="rounded-md border border-chart-4/25 bg-chart-4/5 px-2.5 py-2 dark:bg-chart-4/10"
|
||||||
>
|
>
|
||||||
<p
|
<p class="flex items-center gap-1 text-[11px] font-medium text-chart-4 uppercase">
|
||||||
class="text-chart-4 flex items-center gap-1 text-[11px] font-medium uppercase"
|
|
||||||
>
|
|
||||||
<Flag class="size-3.5 shrink-0" aria-hidden="true" />
|
<Flag class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Завершена
|
Завершена
|
||||||
</p>
|
</p>
|
||||||
@@ -343,7 +337,7 @@
|
|||||||
class="min-w-0 overflow-hidden rounded-md border border-chart-1/30 bg-chart-1/5 p-2.5 dark:bg-chart-1/10"
|
class="min-w-0 overflow-hidden rounded-md border border-chart-1/30 bg-chart-1/5 p-2.5 dark:bg-chart-1/10"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="text-chart-1 flex items-center gap-1 text-[11px] font-medium uppercase"
|
class="flex items-center gap-1 text-[11px] font-medium text-chart-1 uppercase"
|
||||||
>
|
>
|
||||||
<Layers class="size-3.5 shrink-0" aria-hidden="true" />
|
<Layers class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Агрегация
|
Агрегация
|
||||||
@@ -354,7 +348,7 @@
|
|||||||
class="min-w-0 overflow-hidden rounded-md border border-chart-2/30 bg-chart-2/5 p-2.5 dark:bg-chart-2/10"
|
class="min-w-0 overflow-hidden rounded-md border border-chart-2/30 bg-chart-2/5 p-2.5 dark:bg-chart-2/10"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="text-chart-2 flex items-center gap-1 text-[11px] font-medium uppercase"
|
class="flex items-center gap-1 text-[11px] font-medium text-chart-2 uppercase"
|
||||||
>
|
>
|
||||||
<Globe class="size-3.5 shrink-0" aria-hidden="true" />
|
<Globe class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
Домены
|
Домены
|
||||||
@@ -365,7 +359,7 @@
|
|||||||
class="min-w-0 overflow-hidden rounded-md border border-chart-3/30 bg-chart-3/5 p-2.5 dark:bg-chart-3/10"
|
class="min-w-0 overflow-hidden rounded-md border border-chart-3/30 bg-chart-3/5 p-2.5 dark:bg-chart-3/10"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="text-chart-3 flex items-center gap-1 text-[11px] font-medium uppercase"
|
class="flex items-center gap-1 text-[11px] font-medium text-chart-3 uppercase"
|
||||||
>
|
>
|
||||||
<Binary class="size-3.5 shrink-0" aria-hidden="true" />
|
<Binary class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
ASN
|
ASN
|
||||||
@@ -376,7 +370,7 @@
|
|||||||
class="min-w-0 overflow-hidden rounded-md border border-chart-4/30 bg-chart-4/5 p-2.5 dark:bg-chart-4/10"
|
class="min-w-0 overflow-hidden rounded-md border border-chart-4/30 bg-chart-4/5 p-2.5 dark:bg-chart-4/10"
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
class="text-chart-4 flex items-center gap-1 text-[11px] font-medium uppercase"
|
class="flex items-center gap-1 text-[11px] font-medium text-chart-4 uppercase"
|
||||||
>
|
>
|
||||||
<Link2 class="size-3.5 shrink-0" aria-hidden="true" />
|
<Link2 class="size-3.5 shrink-0" aria-hidden="true" />
|
||||||
CDN / IP-диапазоны
|
CDN / IP-диапазоны
|
||||||
@@ -427,7 +421,9 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
||||||
<p class="text-sm font-medium">IP-диапазоны: итог по статическим диапазонам</p>
|
<p class="text-sm font-medium">
|
||||||
|
IP-диапазоны: итог по статическим диапазонам
|
||||||
|
</p>
|
||||||
<JobReportTableBlock
|
<JobReportTableBlock
|
||||||
rows={jobReport.ipRanges as RowData[]}
|
rows={jobReport.ipRanges as RowData[]}
|
||||||
columns={reportCols}
|
columns={reportCols}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
onReload: () => void;
|
onReload: () => void;
|
||||||
onRefreshBirdStatus: () => void;
|
onRefreshBirdStatus: () => void;
|
||||||
onOpenBirdProtocols: () => void;
|
onOpenBirdProtocols: () => void;
|
||||||
birdHealthyBadgeVariant: (h: boolean | null | undefined) => 'default' | 'secondary' | 'outline' | 'destructive';
|
birdHealthyBadgeVariant: (
|
||||||
|
h: boolean | null | undefined
|
||||||
|
) => 'default' | 'secondary' | 'outline' | 'destructive';
|
||||||
birdHealthyShortLabel: (h: boolean | null | undefined) => string;
|
birdHealthyShortLabel: (h: boolean | null | undefined) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,24 +40,28 @@
|
|||||||
|
|
||||||
<div class="grid grid-cols-1 items-stretch gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
<div class="grid grid-cols-1 items-stretch gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
||||||
<Card
|
<Card
|
||||||
class={cn(
|
class={cn('min-w-0 overflow-hidden border-l-4 border-l-chart-1 bg-chart-1/5 p-4 shadow-sm')}
|
||||||
'min-w-0 overflow-hidden border-l-4 border-l-chart-1 bg-chart-1/5 p-4 shadow-sm'
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div class="flex min-w-0 flex-1 gap-3">
|
<div class="flex min-w-0 flex-1 gap-3">
|
||||||
<div
|
<div
|
||||||
class="bg-chart-1/20 flex size-11 shrink-0 items-center justify-center rounded-xl"
|
class="flex size-11 shrink-0 items-center justify-center rounded-xl bg-chart-1/20"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<Play class="text-chart-1 size-5" />
|
<Play class="size-5 text-chart-1" />
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 flex-1 space-y-1">
|
<div class="min-w-0 flex-1 space-y-1">
|
||||||
<p class="font-semibold">Применить ко всем спикерам</p>
|
<p class="font-semibold">Применить ко всем спикерам</p>
|
||||||
<p class="text-muted-foreground max-w-[42ch] text-sm">Применить текущую конфигурацию на всех BIRD-спикерах</p>
|
<p class="max-w-[42ch] text-sm text-muted-foreground">
|
||||||
|
Применить текущую конфигурацию на всех BIRD-спикерах
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button class="w-full shrink-0 self-start sm:w-auto sm:self-auto" onclick={onApply} disabled={applying}>
|
<Button
|
||||||
|
class="w-full shrink-0 self-start sm:w-auto sm:self-auto"
|
||||||
|
onclick={onApply}
|
||||||
|
disabled={applying}
|
||||||
|
>
|
||||||
<Play class="size-4" aria-hidden="true" />
|
<Play class="size-4" aria-hidden="true" />
|
||||||
Применить
|
Применить
|
||||||
</Button>
|
</Button>
|
||||||
@@ -63,21 +69,21 @@
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
class={cn(
|
class={cn('min-w-0 overflow-hidden border-l-4 border-l-chart-4 bg-chart-4/5 p-4 shadow-sm')}
|
||||||
'min-w-0 overflow-hidden border-l-4 border-l-chart-4 bg-chart-4/5 p-4 shadow-sm'
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div class="flex min-w-0 flex-1 gap-3">
|
<div class="flex min-w-0 flex-1 gap-3">
|
||||||
<div
|
<div
|
||||||
class="bg-chart-4/20 flex size-11 shrink-0 items-center justify-center rounded-xl"
|
class="flex size-11 shrink-0 items-center justify-center rounded-xl bg-chart-4/20"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<RotateCcw class="text-chart-4 size-5" />
|
<RotateCcw class="size-5 text-chart-4" />
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 flex-1 space-y-1">
|
<div class="min-w-0 flex-1 space-y-1">
|
||||||
<p class="font-semibold">Перезагрузка BIRD</p>
|
<p class="font-semibold">Перезагрузка BIRD</p>
|
||||||
<p class="text-muted-foreground max-w-[42ch] text-sm">Перезагрузить конфигурацию BIRD на всех спикерах</p>
|
<p class="max-w-[42ch] text-sm text-muted-foreground">
|
||||||
|
Перезагрузить конфигурацию BIRD на всех спикерах
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -101,26 +107,32 @@
|
|||||||
<div class="min-w-0 flex-1 space-y-1">
|
<div class="min-w-0 flex-1 space-y-1">
|
||||||
<div class="flex flex-wrap items-center gap-2">
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
<div
|
<div
|
||||||
class="bg-info/15 mr-0.5 flex size-9 items-center justify-center rounded-lg"
|
class="mr-0.5 flex size-9 items-center justify-center rounded-lg bg-info/15"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<Bird class="text-info size-5 shrink-0" />
|
<Bird class="size-5 shrink-0 text-info" />
|
||||||
</div>
|
</div>
|
||||||
<p class="font-semibold">Состояние BIRD</p>
|
<p class="font-semibold">Состояние BIRD</p>
|
||||||
{#if birdStatus}
|
{#if birdStatus}
|
||||||
<Badge variant={birdHealthyBadgeVariant(birdStatus.healthy)}>{birdHealthyShortLabel(birdStatus.healthy)}</Badge>
|
<Badge variant={birdHealthyBadgeVariant(birdStatus.healthy)}
|
||||||
|
>{birdHealthyShortLabel(birdStatus.healthy)}</Badge
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<p class="text-foreground/80 max-w-[56ch] text-sm">
|
<p class="max-w-[56ch] text-sm text-foreground/80">
|
||||||
Локально на хосте API: <code class="bg-muted rounded px-1 text-xs">birdc show protocols</code>. Не заменяет мониторинг спикеров.
|
Локально на хосте API: <code class="rounded bg-muted px-1 text-xs"
|
||||||
|
>birdc show protocols</code
|
||||||
|
>. Не заменяет мониторинг спикеров.
|
||||||
</p>
|
</p>
|
||||||
{#if birdLoading}
|
{#if birdLoading}
|
||||||
<p class="text-foreground/80 text-sm">Загрузка…</p>
|
<p class="text-sm text-foreground/80">Загрузка…</p>
|
||||||
{:else if birdStatus}
|
{:else if birdStatus}
|
||||||
{#if !birdStatus.birdc_configured}
|
{#if !birdStatus.birdc_configured}
|
||||||
<p class="text-foreground/80 text-sm">{birdStatus.message ?? 'birdc не настроен на API.'}</p>
|
<p class="text-sm text-foreground/80">
|
||||||
|
{birdStatus.message ?? 'birdc не настроен на API.'}
|
||||||
|
</p>
|
||||||
{:else if birdStatus.error}
|
{:else if birdStatus.error}
|
||||||
<p class="text-destructive text-sm">{birdStatus.error}</p>
|
<p class="text-sm text-destructive">{birdStatus.error}</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="text-sm">
|
<p class="text-sm">
|
||||||
<span class="text-muted-foreground">BGP сессий:</span>
|
<span class="text-muted-foreground">BGP сессий:</span>
|
||||||
@@ -131,7 +143,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<p class="text-foreground/80 text-sm">Статус не загружен</p>
|
<p class="text-sm text-foreground/80">Статус не загружен</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { RevisionRow } from '$lib/api/types.js';
|
import type { RevisionRow } from '$lib/api/types.js';
|
||||||
import { Button } from '$lib/components/ui/button/index.js';
|
import { Button } from '$lib/components/ui/button/index.js';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle
|
||||||
|
} from '$lib/components/ui/card/index.js';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -41,60 +47,69 @@
|
|||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<CardTitle class="text-base">История ревизий</CardTitle>
|
<CardTitle class="text-base">История ревизий</CardTitle>
|
||||||
<CardDescription class="max-w-[75ch]">
|
<CardDescription class="max-w-[75ch]">
|
||||||
Создаются задачей module_refresh (CDN / IP / AS и т.д.); в превью есть полный текст BIRD с инклюдами
|
Создаются задачей module_refresh (CDN / IP / AS и т.д.); в превью есть полный текст BIRD с
|
||||||
|
инклюдами
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="outline" size="sm" class="shrink-0 self-start sm:self-auto" onclick={onReload} disabled={revLoading}>
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
class="shrink-0 self-start sm:self-auto"
|
||||||
|
onclick={onReload}
|
||||||
|
disabled={revLoading}
|
||||||
|
>
|
||||||
<RefreshCw class={revLoading ? 'animate-spin' : ''} />
|
<RefreshCw class={revLoading ? 'animate-spin' : ''} />
|
||||||
</Button>
|
</Button>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="min-w-0 p-0">
|
<CardContent class="min-w-0 p-0">
|
||||||
<div class="max-w-full overflow-x-auto overscroll-x-contain [scrollbar-gutter:stable]">
|
<div class="max-w-full overflow-x-auto overscroll-x-contain [scrollbar-gutter:stable]">
|
||||||
<Table class="min-w-[44rem]">
|
<Table class="min-w-[44rem]">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
|
||||||
<TableHead>ID</TableHead>
|
|
||||||
<TableHead>Создана</TableHead>
|
|
||||||
<TableHead>Префиксов</TableHead>
|
|
||||||
<TableHead>Хэш</TableHead>
|
|
||||||
<TableHead class="w-32"></TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{#each revisions as rev (rev.id)}
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell class="font-mono text-xs">{rev.id.slice(0, 8)}…</TableCell>
|
<TableHead>ID</TableHead>
|
||||||
<TableCell class="text-sm">{formatDate(rev.created_at)}</TableCell>
|
<TableHead>Создана</TableHead>
|
||||||
<TableCell>{rev.materialized_prefix_count}</TableCell>
|
<TableHead>Префиксов</TableHead>
|
||||||
<TableCell class="font-mono text-xs text-muted-foreground">{rev.content_hash.slice(0, 12)}…</TableCell>
|
<TableHead>Хэш</TableHead>
|
||||||
<TableCell>
|
<TableHead class="w-32"></TableHead>
|
||||||
<div class="flex gap-1">
|
|
||||||
<Button variant="ghost" size="icon-sm" onclick={() => onOpenPreview(rev)}>
|
|
||||||
<Eye class="size-3.5" />
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="icon-sm" onclick={() => onRollbackRequest(rev)}>
|
|
||||||
<Undo class="size-3.5" />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon-sm"
|
|
||||||
title="Скачать диагностический лог"
|
|
||||||
onclick={() => onDownloadDiagnosticLog(rev)}
|
|
||||||
>
|
|
||||||
<Download class="size-3.5" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{:else}
|
</TableHeader>
|
||||||
<TableRow>
|
<TableBody>
|
||||||
<TableCell colspan={5} class="text-muted-foreground py-8 text-center">
|
{#each revisions as rev (rev.id)}
|
||||||
{revLoading ? 'Загрузка…' : 'Нет ревизий'}
|
<TableRow>
|
||||||
</TableCell>
|
<TableCell class="font-mono text-xs">{rev.id.slice(0, 8)}…</TableCell>
|
||||||
</TableRow>
|
<TableCell class="text-sm">{formatDate(rev.created_at)}</TableCell>
|
||||||
{/each}
|
<TableCell>{rev.materialized_prefix_count}</TableCell>
|
||||||
</TableBody>
|
<TableCell class="font-mono text-xs text-muted-foreground"
|
||||||
</Table>
|
>{rev.content_hash.slice(0, 12)}…</TableCell
|
||||||
|
>
|
||||||
|
<TableCell>
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<Button variant="ghost" size="icon-sm" onclick={() => onOpenPreview(rev)}>
|
||||||
|
<Eye class="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
<Button variant="ghost" size="icon-sm" onclick={() => onRollbackRequest(rev)}>
|
||||||
|
<Undo class="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-sm"
|
||||||
|
title="Скачать диагностический лог"
|
||||||
|
onclick={() => onDownloadDiagnosticLog(rev)}
|
||||||
|
>
|
||||||
|
<Download class="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
{:else}
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colspan={5} class="text-muted-foreground py-8 text-center">
|
||||||
|
{revLoading ? 'Загрузка…' : 'Нет ревизий'}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
{/each}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ function parseIPv6(addrPart: string): { words: number[]; pl: number } | null {
|
|||||||
}
|
}
|
||||||
const missing = 8 - left.length - right.length;
|
const missing = 8 - left.length - right.length;
|
||||||
if (missing < 0) return null;
|
if (missing < 0) return null;
|
||||||
return { words: [...left.map(parseGroup), ...Array(missing).fill(0), ...right.map(parseGroup)], pl: 128 };
|
return {
|
||||||
|
words: [...left.map(parseGroup), ...Array(missing).fill(0), ...right.map(parseGroup)],
|
||||||
|
pl: 128
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortKey =
|
type SortKey =
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0}>
|
||||||
<div class="bg-background flex min-h-screen">
|
<div class="flex min-h-screen bg-background">
|
||||||
<AppSidebar bind:collapsed bind:theme />
|
<AppSidebar bind:collapsed bind:theme />
|
||||||
<div class="flex min-w-0 flex-1 flex-col">
|
<div class="flex min-w-0 flex-1 flex-col">
|
||||||
<div class="border-border flex items-center gap-2 border-b px-4 py-2 md:hidden">
|
<div class="flex items-center gap-2 border-b border-border px-4 py-2 md:hidden">
|
||||||
<AppMobileNav bind:open={mobileNavOpen} bind:theme />
|
<AppMobileNav bind:open={mobileNavOpen} bind:theme />
|
||||||
<span class="font-semibold tracking-tight">EvoBGP</span>
|
<span class="font-semibold tracking-tight">EvoBGP</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -28,12 +28,12 @@
|
|||||||
<Menu class="size-5" />
|
<Menu class="size-5" />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent side="left" class="bg-sidebar text-sidebar-foreground flex w-72 flex-col gap-0 p-0">
|
<SheetContent side="left" class="flex w-72 flex-col gap-0 bg-sidebar p-0 text-sidebar-foreground">
|
||||||
<SheetHeader class="border-border border-b p-4 text-left">
|
<SheetHeader class="border-b border-border p-4 text-left">
|
||||||
<SheetTitle>
|
<SheetTitle>
|
||||||
<a href={resolve('/')} class="font-semibold tracking-tight no-underline">EvoBGP</a>
|
<a href={resolve('/')} class="font-semibold tracking-tight no-underline">EvoBGP</a>
|
||||||
</SheetTitle>
|
</SheetTitle>
|
||||||
<p class="text-sidebar-foreground/50 text-xs font-normal">Панель управления</p>
|
<p class="text-xs font-normal text-sidebar-foreground/50">Панель управления</p>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<div class="flex items-center gap-2 px-4 py-2">
|
<div class="flex items-center gap-2 px-4 py-2">
|
||||||
<ThemeMenu bind:theme />
|
<ThemeMenu bind:theme />
|
||||||
|
|||||||
@@ -25,8 +25,13 @@
|
|||||||
|
|
||||||
function linkClass(active: boolean, iconOnly: boolean) {
|
function linkClass(active: boolean, iconOnly: boolean) {
|
||||||
return cn(
|
return cn(
|
||||||
buttonVariants({ variant: active ? 'secondary' : 'ghost', size: iconOnly ? 'icon-sm' : 'sm' }),
|
buttonVariants({
|
||||||
iconOnly ? 'flex w-full items-center justify-center no-underline' : 'flex w-full items-center justify-start gap-2 no-underline',
|
variant: active ? 'secondary' : 'ghost',
|
||||||
|
size: iconOnly ? 'icon-sm' : 'sm'
|
||||||
|
}),
|
||||||
|
iconOnly
|
||||||
|
? 'flex w-full items-center justify-center no-underline'
|
||||||
|
: 'flex w-full items-center justify-start gap-2 no-underline',
|
||||||
active &&
|
active &&
|
||||||
(iconOnly
|
(iconOnly
|
||||||
? 'ring-sidebar-primary/50 bg-sidebar-accent/90 text-sidebar-accent-foreground ring-1'
|
? 'ring-sidebar-primary/50 bg-sidebar-accent/90 text-sidebar-accent-foreground ring-1'
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<aside
|
<aside
|
||||||
class={cn(
|
class={cn(
|
||||||
'border-border bg-sidebar sticky top-0 hidden h-screen shrink-0 flex-col overflow-hidden border-r transition-all duration-200 md:flex',
|
'sticky top-0 hidden h-screen shrink-0 flex-col overflow-hidden border-r border-border bg-sidebar transition-all duration-200 md:flex',
|
||||||
collapsed ? 'w-14' : 'w-56'
|
collapsed ? 'w-14' : 'w-56'
|
||||||
)}
|
)}
|
||||||
aria-label="Основная навигация"
|
aria-label="Основная навигация"
|
||||||
@@ -28,10 +28,11 @@
|
|||||||
<div class={cn('flex items-center gap-2 p-3', collapsed && 'justify-center')}>
|
<div class={cn('flex items-center gap-2 p-3', collapsed && 'justify-center')}>
|
||||||
{#if !collapsed}
|
{#if !collapsed}
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<a href={resolve('/')} class="text-sidebar-foreground block truncate font-semibold tracking-tight"
|
<a
|
||||||
>EvoBGP</a
|
href={resolve('/')}
|
||||||
|
class="block truncate font-semibold tracking-tight text-sidebar-foreground">EvoBGP</a
|
||||||
>
|
>
|
||||||
<p class="text-sidebar-foreground/50 truncate text-xs">Панель управления</p>
|
<p class="truncate text-xs text-sidebar-foreground/50">Панель управления</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<ThemeMenu bind:theme />
|
<ThemeMenu bind:theme />
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
onclick={() => (collapsed = !collapsed)}
|
onclick={() => (collapsed = !collapsed)}
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({ variant: 'ghost', size: 'icon-sm' }),
|
buttonVariants({ variant: 'ghost', size: 'icon-sm' }),
|
||||||
'text-sidebar-foreground/60 hover:text-sidebar-foreground shrink-0'
|
'shrink-0 text-sidebar-foreground/60 hover:text-sidebar-foreground'
|
||||||
)}
|
)}
|
||||||
aria-label={collapsed ? 'Развернуть меню' : 'Свернуть меню'}
|
aria-label={collapsed ? 'Развернуть меню' : 'Свернуть меню'}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<header
|
<header
|
||||||
class={cn(
|
class={cn(
|
||||||
'border-border bg-background/95 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-30 flex flex-col gap-3 border-b px-4 py-3 backdrop-blur md:px-6',
|
'sticky top-0 z-30 flex flex-col gap-3 border-b border-border bg-background/95 px-4 py-3 backdrop-blur supports-[backdrop-filter]:bg-background/60 md:px-6',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<h1 class="text-lg font-semibold tracking-tight md:text-xl">{title}</h1>
|
<h1 class="text-lg font-semibold tracking-tight md:text-xl">{title}</h1>
|
||||||
{/if}
|
{/if}
|
||||||
{#if description}
|
{#if description}
|
||||||
<p class="text-muted-foreground mt-0.5 text-sm">{description}</p>
|
<p class="mt-0.5 text-sm text-muted-foreground">{description}</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if actions}
|
{#if actions}
|
||||||
|
|||||||
@@ -14,14 +14,17 @@
|
|||||||
import Moon from '@lucide/svelte/icons/moon';
|
import Moon from '@lucide/svelte/icons/moon';
|
||||||
import Monitor from '@lucide/svelte/icons/monitor';
|
import Monitor from '@lucide/svelte/icons/monitor';
|
||||||
|
|
||||||
let { theme = $bindable<ThemePreference>('system'), class: className }: { theme?: ThemePreference; class?: string } = $props();
|
let {
|
||||||
|
theme = $bindable<ThemePreference>('system'),
|
||||||
|
class: className
|
||||||
|
}: { theme?: ThemePreference; class?: string } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
class={cn(
|
class={cn(
|
||||||
buttonVariants({ variant: 'ghost', size: 'icon-sm' }),
|
buttonVariants({ variant: 'ghost', size: 'icon-sm' }),
|
||||||
'text-sidebar-foreground/60 hover:text-sidebar-foreground shrink-0',
|
'shrink-0 text-sidebar-foreground/60 hover:text-sidebar-foreground',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
aria-label="Тема оформления"
|
aria-label="Тема оформления"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<h1 class="text-2xl font-semibold tracking-tight">{title}</h1>
|
<h1 class="text-2xl font-semibold tracking-tight">{title}</h1>
|
||||||
{#if description}
|
{#if description}
|
||||||
<p class="text-muted-foreground mt-1 text-sm">{description}</p>
|
<p class="mt-1 text-sm text-muted-foreground">{description}</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
| Token | Значение | Tailwind |
|
| Token | Значение | Tailwind |
|
||||||
|-------|----------|----------|
|
| ---------------- | -------- | ---------------------------------------- |
|
||||||
| `--page-padding` | 1.5rem | `p-page` через `p-[var(--page-padding)]` |
|
| `--page-padding` | 1.5rem | `p-page` через `p-[var(--page-padding)]` |
|
||||||
| `--section-gap` | 1.5rem | `gap-section` |
|
| `--section-gap` | 1.5rem | `gap-section` |
|
||||||
|
|
||||||
## Радиусы
|
## Радиусы
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import {
|
import {
|
||||||
buttonVariants,
|
buttonVariants,
|
||||||
type ButtonVariant,
|
type ButtonVariant,
|
||||||
type ButtonSize,
|
type ButtonSize
|
||||||
} from "$lib/ui/core/button/index.js";
|
} from '$lib/ui/core/button/index.js';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
size = "default",
|
size = 'default',
|
||||||
...restProps
|
...restProps
|
||||||
}: AlertDialogPrimitive.ActionProps & {
|
}: AlertDialogPrimitive.ActionProps & {
|
||||||
variant?: ButtonVariant;
|
variant?: ButtonVariant;
|
||||||
@@ -22,6 +22,6 @@
|
|||||||
<AlertDialogPrimitive.Action
|
<AlertDialogPrimitive.Action
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="alert-dialog-action"
|
data-slot="alert-dialog-action"
|
||||||
class={cn(buttonVariants({ variant, size }), "cn-alert-dialog-action", className)}
|
class={cn(buttonVariants({ variant, size }), 'cn-alert-dialog-action', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import {
|
import {
|
||||||
buttonVariants,
|
buttonVariants,
|
||||||
type ButtonVariant,
|
type ButtonVariant,
|
||||||
type ButtonSize,
|
type ButtonSize
|
||||||
} from "$lib/ui/core/button/index.js";
|
} from '$lib/ui/core/button/index.js';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
variant = "outline",
|
variant = 'outline',
|
||||||
size = "default",
|
size = 'default',
|
||||||
...restProps
|
...restProps
|
||||||
}: AlertDialogPrimitive.CancelProps & {
|
}: AlertDialogPrimitive.CancelProps & {
|
||||||
variant?: ButtonVariant;
|
variant?: ButtonVariant;
|
||||||
@@ -22,6 +22,6 @@
|
|||||||
<AlertDialogPrimitive.Cancel
|
<AlertDialogPrimitive.Cancel
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="alert-dialog-cancel"
|
data-slot="alert-dialog-cancel"
|
||||||
class={cn(buttonVariants({ variant, size }), "cn-alert-dialog-cancel", className)}
|
class={cn(buttonVariants({ variant, size }), 'cn-alert-dialog-cancel', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import AlertDialogPortal from "./alert-dialog-portal.svelte";
|
import AlertDialogPortal from './alert-dialog-portal.svelte';
|
||||||
import AlertDialogOverlay from "./alert-dialog-overlay.svelte";
|
import AlertDialogOverlay from './alert-dialog-overlay.svelte';
|
||||||
import { cn, type WithoutChild, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChild, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import type { ComponentProps } from "svelte";
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
size = "default",
|
size = 'default',
|
||||||
portalProps,
|
portalProps,
|
||||||
...restProps
|
...restProps
|
||||||
}: WithoutChild<AlertDialogPrimitive.ContentProps> & {
|
}: WithoutChild<AlertDialogPrimitive.ContentProps> & {
|
||||||
size?: "default" | "sm";
|
size?: 'default' | 'sm';
|
||||||
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof AlertDialogPortal>>;
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof AlertDialogPortal>>;
|
||||||
} = $props();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
data-slot="alert-dialog-content"
|
data-slot="alert-dialog-content"
|
||||||
data-size={size}
|
data-size={size}
|
||||||
class={cn(
|
class={cn(
|
||||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-popover text-popover-foreground ring-foreground/10 gap-4 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",
|
'group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<AlertDialogPrimitive.Description
|
<AlertDialogPrimitive.Description
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="alert-dialog-description"
|
data-slot="alert-dialog-description"
|
||||||
class={cn("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className)}
|
class={cn(
|
||||||
|
'text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-dialog-footer"
|
data-slot="alert-dialog-footer"
|
||||||
class={cn(
|
class={cn(
|
||||||
"bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
'-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-dialog-header"
|
data-slot="alert-dialog-header"
|
||||||
class={cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className)}
|
class={cn(
|
||||||
|
'grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-dialog-media"
|
data-slot="alert-dialog-media"
|
||||||
class={cn("bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className)}
|
class={cn(
|
||||||
|
"mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<AlertDialogPrimitive.Overlay
|
<AlertDialogPrimitive.Overlay
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="alert-dialog-overlay"
|
data-slot="alert-dialog-overlay"
|
||||||
class={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50", className)}
|
class={cn(
|
||||||
|
'fixed inset-0 z-50 bg-black/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 supports-backdrop-filter:backdrop-blur-xs',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ...restProps }: AlertDialogPrimitive.PortalProps = $props();
|
let { ...restProps }: AlertDialogPrimitive.PortalProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<AlertDialogPrimitive.Title
|
<AlertDialogPrimitive.Title
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="alert-dialog-title"
|
data-slot="alert-dialog-title"
|
||||||
class={cn("text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className)}
|
class={cn(
|
||||||
|
'text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ref = $bindable(null), ...restProps }: AlertDialogPrimitive.TriggerProps = $props();
|
let { ref = $bindable(null), ...restProps }: AlertDialogPrimitive.TriggerProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { open = $bindable(false), ...restProps }: AlertDialogPrimitive.RootProps = $props();
|
let { open = $bindable(false), ...restProps }: AlertDialogPrimitive.RootProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import Root from "./alert-dialog.svelte";
|
import Root from './alert-dialog.svelte';
|
||||||
import Portal from "./alert-dialog-portal.svelte";
|
import Portal from './alert-dialog-portal.svelte';
|
||||||
import Trigger from "./alert-dialog-trigger.svelte";
|
import Trigger from './alert-dialog-trigger.svelte';
|
||||||
import Title from "./alert-dialog-title.svelte";
|
import Title from './alert-dialog-title.svelte';
|
||||||
import Action from "./alert-dialog-action.svelte";
|
import Action from './alert-dialog-action.svelte';
|
||||||
import Cancel from "./alert-dialog-cancel.svelte";
|
import Cancel from './alert-dialog-cancel.svelte';
|
||||||
import Footer from "./alert-dialog-footer.svelte";
|
import Footer from './alert-dialog-footer.svelte';
|
||||||
import Header from "./alert-dialog-header.svelte";
|
import Header from './alert-dialog-header.svelte';
|
||||||
import Overlay from "./alert-dialog-overlay.svelte";
|
import Overlay from './alert-dialog-overlay.svelte';
|
||||||
import Content from "./alert-dialog-content.svelte";
|
import Content from './alert-dialog-content.svelte';
|
||||||
import Description from "./alert-dialog-description.svelte";
|
import Description from './alert-dialog-description.svelte';
|
||||||
import Media from "./alert-dialog-media.svelte";
|
import Media from './alert-dialog-media.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -36,5 +36,5 @@ export {
|
|||||||
Overlay as AlertDialogOverlay,
|
Overlay as AlertDialogOverlay,
|
||||||
Content as AlertDialogContent,
|
Content as AlertDialogContent,
|
||||||
Description as AlertDialogDescription,
|
Description as AlertDialogDescription,
|
||||||
Media as AlertDialogMedia,
|
Media as AlertDialogMedia
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-action"
|
data-slot="alert-action"
|
||||||
class={cn("absolute top-2 right-2", className)}
|
class={cn('absolute top-2 right-2', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-description"
|
data-slot="alert-description"
|
||||||
class={cn(
|
class={cn(
|
||||||
"text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
'text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="alert-title"
|
data-slot="alert-title"
|
||||||
class={cn(
|
class={cn(
|
||||||
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
'font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,30 +1,31 @@
|
|||||||
<script lang="ts" module>
|
<script lang="ts" module>
|
||||||
import { type VariantProps, tv } from "tailwind-variants";
|
import { type VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
export const alertVariants = tv({
|
export const alertVariants = tv({
|
||||||
base: "grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 group/alert relative w-full",
|
base: "grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 group/alert relative w-full",
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-card text-card-foreground",
|
default: 'bg-card text-card-foreground',
|
||||||
destructive: "text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
destructive:
|
||||||
},
|
'text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AlertVariant = VariantProps<typeof alertVariants>["variant"];
|
export type AlertVariant = VariantProps<typeof alertVariants>['variant'];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
children,
|
children,
|
||||||
...restProps
|
...restProps
|
||||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import Root from "./alert.svelte";
|
import Root from './alert.svelte';
|
||||||
import Description from "./alert-description.svelte";
|
import Description from './alert-description.svelte';
|
||||||
import Title from "./alert-title.svelte";
|
import Title from './alert-title.svelte';
|
||||||
import Action from "./alert-action.svelte";
|
import Action from './alert-action.svelte';
|
||||||
export { alertVariants, type AlertVariant } from "./alert.svelte";
|
export { alertVariants, type AlertVariant } from './alert.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -13,5 +13,5 @@ export {
|
|||||||
Root as Alert,
|
Root as Alert,
|
||||||
Description as AlertDescription,
|
Description as AlertDescription,
|
||||||
Title as AlertTitle,
|
Title as AlertTitle,
|
||||||
Action as AlertAction,
|
Action as AlertAction
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
<script lang="ts" module>
|
<script lang="ts" module>
|
||||||
import { type VariantProps, tv } from "tailwind-variants";
|
import { type VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
export const badgeVariants = tv({
|
export const badgeVariants = tv({
|
||||||
base: "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-colors focus-visible:ring-[3px] [&>svg]:pointer-events-none",
|
base: 'h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-colors focus-visible:ring-[3px] [&>svg]:pointer-events-none',
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',
|
||||||
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
secondary: 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
|
||||||
destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
|
destructive:
|
||||||
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
'bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20',
|
||||||
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
outline: 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
ghost: 'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',
|
||||||
},
|
link: 'text-primary underline-offset-4 hover:underline'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
|
export type BadgeVariant = VariantProps<typeof badgeVariants>['variant'];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAnchorAttributes } from "svelte/elements";
|
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
href,
|
href,
|
||||||
class: className,
|
class: className,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
children,
|
children,
|
||||||
...restProps
|
...restProps
|
||||||
}: WithElementRef<HTMLAnchorAttributes> & {
|
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:element
|
<svelte:element
|
||||||
this={href ? "a" : "span"}
|
this={href ? 'a' : 'span'}
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="badge"
|
data-slot="badge"
|
||||||
{href}
|
{href}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export { default as Badge } from "./badge.svelte";
|
export { default as Badge } from './badge.svelte';
|
||||||
export { badgeVariants, type BadgeVariant } from "./badge.svelte";
|
export { badgeVariants, type BadgeVariant } from './badge.svelte';
|
||||||
|
|||||||
@@ -1,38 +1,45 @@
|
|||||||
<script lang="ts" module>
|
<script lang="ts" module>
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
|
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||||
import { type VariantProps, tv } from "tailwind-variants";
|
import { type VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
export const buttonVariants = tv({
|
export const buttonVariants = tv({
|
||||||
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',
|
||||||
outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
outline:
|
||||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground',
|
||||||
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
secondary:
|
||||||
destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
ghost:
|
||||||
|
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
|
||||||
|
destructive:
|
||||||
|
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
||||||
|
link: 'text-primary underline-offset-4 hover:underline'
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
default:
|
||||||
|
'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
|
||||||
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
||||||
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
||||||
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
|
||||||
icon: "size-8",
|
icon: 'size-8',
|
||||||
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
'icon-xs':
|
||||||
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
||||||
"icon-lg": "size-9",
|
'icon-sm':
|
||||||
},
|
'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
|
||||||
|
'icon-lg': 'size-9'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: 'default',
|
||||||
size: "default",
|
size: 'default'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
|
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
|
||||||
export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
|
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
|
||||||
|
|
||||||
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
||||||
WithElementRef<HTMLAnchorAttributes> & {
|
WithElementRef<HTMLAnchorAttributes> & {
|
||||||
@@ -44,11 +51,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
let {
|
let {
|
||||||
class: className,
|
class: className,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
size = "default",
|
size = 'default',
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
href = undefined,
|
href = undefined,
|
||||||
type = "button",
|
type = 'button',
|
||||||
disabled,
|
disabled,
|
||||||
children,
|
children,
|
||||||
...restProps
|
...restProps
|
||||||
@@ -62,7 +69,7 @@
|
|||||||
class={cn(buttonVariants({ variant, size }), className)}
|
class={cn(buttonVariants({ variant, size }), className)}
|
||||||
href={disabled ? undefined : href}
|
href={disabled ? undefined : href}
|
||||||
aria-disabled={disabled}
|
aria-disabled={disabled}
|
||||||
role={disabled ? "link" : undefined}
|
role={disabled ? 'link' : undefined}
|
||||||
tabindex={disabled ? -1 : undefined}
|
tabindex={disabled ? -1 : undefined}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import Root, {
|
|||||||
type ButtonProps,
|
type ButtonProps,
|
||||||
type ButtonSize,
|
type ButtonSize,
|
||||||
type ButtonVariant,
|
type ButtonVariant,
|
||||||
buttonVariants,
|
buttonVariants
|
||||||
} from "./button.svelte";
|
} from './button.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -13,5 +13,5 @@ export {
|
|||||||
buttonVariants,
|
buttonVariants,
|
||||||
type ButtonProps,
|
type ButtonProps,
|
||||||
type ButtonSize,
|
type ButtonSize,
|
||||||
type ButtonVariant,
|
type ButtonVariant
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-action"
|
data-slot="card-action"
|
||||||
class={cn(
|
class={cn(
|
||||||
"cn-card-action col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
'cn-card-action col-start-2 row-span-2 row-start-1 self-start justify-self-end',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-content"
|
data-slot="card-content"
|
||||||
class={cn("px-4 group-data-[size=sm]/card:px-3", className)}
|
class={cn('px-4 group-data-[size=sm]/card:px-3', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<p
|
<p
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-description"
|
data-slot="card-description"
|
||||||
class={cn("text-muted-foreground text-sm", className)}
|
class={cn('text-sm text-muted-foreground', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-footer"
|
data-slot="card-footer"
|
||||||
class={cn("bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center", className)}
|
class={cn(
|
||||||
|
'flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-header"
|
data-slot="card-header"
|
||||||
class={cn(
|
class={cn(
|
||||||
"gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
|
'group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card-title"
|
data-slot="card-title"
|
||||||
class={cn("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm", className)}
|
class={cn('text-base leading-snug font-medium group-data-[size=sm]/card:text-sm', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
children,
|
children,
|
||||||
size = "default",
|
size = 'default',
|
||||||
...restProps
|
...restProps
|
||||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { size?: "default" | "sm" } = $props();
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { size?: 'default' | 'sm' } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="card"
|
data-slot="card"
|
||||||
data-size={size}
|
data-size={size}
|
||||||
class={cn("ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
|
class={cn(
|
||||||
|
'group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import Root from "./card.svelte";
|
import Root from './card.svelte';
|
||||||
import Content from "./card-content.svelte";
|
import Content from './card-content.svelte';
|
||||||
import Description from "./card-description.svelte";
|
import Description from './card-description.svelte';
|
||||||
import Footer from "./card-footer.svelte";
|
import Footer from './card-footer.svelte';
|
||||||
import Header from "./card-header.svelte";
|
import Header from './card-header.svelte';
|
||||||
import Title from "./card-title.svelte";
|
import Title from './card-title.svelte';
|
||||||
import Action from "./card-action.svelte";
|
import Action from './card-action.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -21,5 +21,5 @@ export {
|
|||||||
Footer as CardFooter,
|
Footer as CardFooter,
|
||||||
Header as CardHeader,
|
Header as CardHeader,
|
||||||
Title as CardTitle,
|
Title as CardTitle,
|
||||||
Action as CardAction,
|
Action as CardAction
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Checkbox as CheckboxPrimitive } from "bits-ui";
|
import { Checkbox as CheckboxPrimitive } from 'bits-ui';
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import CheckIcon from '@lucide/svelte/icons/check';
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
import MinusIcon from '@lucide/svelte/icons/minus';
|
import MinusIcon from '@lucide/svelte/icons/minus';
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
bind:ref
|
bind:ref
|
||||||
data-slot="checkbox"
|
data-slot="checkbox"
|
||||||
class={cn(
|
class={cn(
|
||||||
"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50",
|
'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:data-checked:bg-primary',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
bind:checked
|
bind:checked
|
||||||
@@ -27,12 +27,12 @@
|
|||||||
{#snippet children({ checked, indeterminate })}
|
{#snippet children({ checked, indeterminate })}
|
||||||
<div
|
<div
|
||||||
data-slot="checkbox-indicator"
|
data-slot="checkbox-indicator"
|
||||||
class="[&>svg]:size-3.5 grid place-content-center text-current transition-none"
|
class="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
||||||
>
|
>
|
||||||
{#if checked}
|
{#if checked}
|
||||||
<CheckIcon />
|
<CheckIcon />
|
||||||
{:else if indeterminate}
|
{:else if indeterminate}
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Root from "./checkbox.svelte";
|
import Root from './checkbox.svelte';
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
//
|
//
|
||||||
Root as Checkbox,
|
Root as Checkbox
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import {
|
|||||||
type TableOptionsResolved,
|
type TableOptionsResolved,
|
||||||
type TableState,
|
type TableState,
|
||||||
type Updater,
|
type Updater,
|
||||||
createTable,
|
createTable
|
||||||
} from "@tanstack/table-core";
|
} from '@tanstack/table-core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a reactive TanStack table object for Svelte.
|
* Creates a reactive TanStack table object for Svelte.
|
||||||
@@ -44,7 +44,7 @@ export function createSvelteTable<TData extends RowData>(options: TableOptions<T
|
|||||||
options: Partial<TableOptions<TData>>
|
options: Partial<TableOptions<TData>>
|
||||||
) => {
|
) => {
|
||||||
return mergeObjects(defaultOptions, options);
|
return mergeObjects(defaultOptions, options);
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
@@ -62,7 +62,7 @@ export function createSvelteTable<TData extends RowData>(options: TableOptions<T
|
|||||||
else state = mergeObjects(state, updater);
|
else state = mergeObjects(state, updater);
|
||||||
|
|
||||||
options.onStateChange?.(updater);
|
options.onStateChange?.(updater);
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ export function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(
|
|||||||
...sources: Sources
|
...sources: Sources
|
||||||
): Intersection<{ [K in keyof Sources]: Sources[K] }> {
|
): Intersection<{ [K in keyof Sources]: Sources[K] }> {
|
||||||
const resolve = <T extends object>(src: MaybeThunk<T>): T | undefined =>
|
const resolve = <T extends object>(src: MaybeThunk<T>): T | undefined =>
|
||||||
typeof src === "function" ? (src() ?? undefined) : src;
|
typeof src === 'function' ? (src() ?? undefined) : src;
|
||||||
|
|
||||||
const findSourceWithKey = (key: PropertyKey) => {
|
const findSourceWithKey = (key: PropertyKey) => {
|
||||||
for (let i = sources.length - 1; i >= 0; i--) {
|
for (let i = sources.length - 1; i >= 0; i--) {
|
||||||
@@ -135,8 +135,8 @@ export function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
value: (src as any)[key],
|
value: (src as any)[key],
|
||||||
writable: true,
|
writable: true
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
}) as Intersection<{ [K in keyof Sources]: Sources[K] }>;
|
}) as Intersection<{ [K in keyof Sources]: Sources[K] }>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
lang="ts"
|
lang="ts"
|
||||||
generics="TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>"
|
generics="TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>"
|
||||||
>
|
>
|
||||||
import type { CellContext, ColumnDefTemplate, HeaderContext } from "@tanstack/table-core";
|
import type { CellContext, ColumnDefTemplate, HeaderContext } from '@tanstack/table-core';
|
||||||
import { RenderComponentConfig, RenderSnippetConfig } from "./render-helpers.js";
|
import { RenderComponentConfig, RenderSnippetConfig } from './render-helpers.js';
|
||||||
import type { Attachment } from "svelte/attachments";
|
import type { Attachment } from 'svelte/attachments';
|
||||||
type Props = {
|
type Props = {
|
||||||
/** The cell or header field of the current cell's column definition. */
|
/** The cell or header field of the current cell's column definition. */
|
||||||
content?: TContext extends HeaderContext<TData, TValue>
|
content?: TContext extends HeaderContext<TData, TValue>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
let { content, context, attach }: Props = $props();
|
let { content, context, attach }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if typeof content === "string"}
|
{#if typeof content === 'string'}
|
||||||
{content}
|
{content}
|
||||||
{:else if content instanceof Function}
|
{:else if content instanceof Function}
|
||||||
<!-- It's unlikely that a CellContext will be passed to a Header -->
|
<!-- It's unlikely that a CellContext will be passed to a Header -->
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export { default as FlexRender } from "./flex-render.svelte";
|
export { default as FlexRender } from './flex-render.svelte';
|
||||||
export { renderComponent, renderSnippet } from "./render-helpers.js";
|
export { renderComponent, renderSnippet } from './render-helpers.js';
|
||||||
export { createSvelteTable } from "./data-table.svelte.js";
|
export { createSvelteTable } from './data-table.svelte.js';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Component, ComponentProps, Snippet } from "svelte";
|
import type { Component, ComponentProps, Snippet } from 'svelte';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class to make it easy to identify Svelte components in
|
* A helper class to make it easy to identify Svelte components in
|
||||||
@@ -77,7 +77,7 @@ export class RenderSnippetConfig<TProps> {
|
|||||||
export function renderComponent<
|
export function renderComponent<
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
T extends Component<any>,
|
T extends Component<any>,
|
||||||
Props extends ComponentProps<T>,
|
Props extends ComponentProps<T>
|
||||||
>(component: T, props: Props = {} as Props) {
|
>(component: T, props: Props = {} as Props) {
|
||||||
return new RenderComponentConfig(component, props);
|
return new RenderComponentConfig(component, props);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
type = "button",
|
type = 'button',
|
||||||
...restProps
|
...restProps
|
||||||
}: DialogPrimitive.CloseProps = $props();
|
}: DialogPrimitive.CloseProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
import DialogPortal from "./dialog-portal.svelte";
|
import DialogPortal from './dialog-portal.svelte';
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from 'svelte';
|
||||||
import * as Dialog from "./index.js";
|
import * as Dialog from './index.js';
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import type { ComponentProps } from "svelte";
|
import type { ComponentProps } from 'svelte';
|
||||||
import { Button } from "$lib/ui/core/button/index.js";
|
import { Button } from '$lib/ui/core/button/index.js';
|
||||||
import XIcon from '@lucide/svelte/icons/x';
|
import XIcon from '@lucide/svelte/icons/x';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-content"
|
data-slot="dialog-content"
|
||||||
class={cn(
|
class={cn(
|
||||||
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
|
'fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 sm:max-w-sm',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<DialogPrimitive.Close data-slot="dialog-close">
|
<DialogPrimitive.Close data-slot="dialog-close">
|
||||||
{#snippet child({ props })}
|
{#snippet child({ props })}
|
||||||
<Button variant="ghost" class="absolute top-2 right-2" size="icon-sm" {...props}>
|
<Button variant="ghost" class="absolute top-2 right-2" size="icon-sm" {...props}>
|
||||||
<XIcon />
|
<XIcon />
|
||||||
<span class="sr-only">Close</span>
|
<span class="sr-only">Close</span>
|
||||||
</Button>
|
</Button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<DialogPrimitive.Description
|
<DialogPrimitive.Description
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-description"
|
data-slot="dialog-description"
|
||||||
class={cn("text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3", className)}
|
class={cn(
|
||||||
|
'text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
import { Button } from "$lib/ui/core/button/index.js";
|
import { Button } from '$lib/ui/core/button/index.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -18,7 +18,10 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="dialog-footer"
|
data-slot="dialog-footer"
|
||||||
class={cn("bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
class={cn(
|
||||||
|
'-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="dialog-header"
|
data-slot="dialog-header"
|
||||||
class={cn("gap-2 flex flex-col", className)}
|
class={cn('flex flex-col gap-2', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-overlay"
|
data-slot="dialog-overlay"
|
||||||
class={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50", className)}
|
class={cn(
|
||||||
|
'fixed inset-0 isolate z-50 bg-black/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 supports-backdrop-filter:backdrop-blur-xs',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ...restProps }: DialogPrimitive.PortalProps = $props();
|
let { ...restProps }: DialogPrimitive.PortalProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,6 @@
|
|||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-title"
|
data-slot="dialog-title"
|
||||||
class={cn("text-base leading-none font-medium", className)}
|
class={cn('text-base leading-none font-medium', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
type = "button",
|
type = 'button',
|
||||||
...restProps
|
...restProps
|
||||||
}: DialogPrimitive.TriggerProps = $props();
|
}: DialogPrimitive.TriggerProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps = $props();
|
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import Root from "./dialog.svelte";
|
import Root from './dialog.svelte';
|
||||||
import Portal from "./dialog-portal.svelte";
|
import Portal from './dialog-portal.svelte';
|
||||||
import Title from "./dialog-title.svelte";
|
import Title from './dialog-title.svelte';
|
||||||
import Footer from "./dialog-footer.svelte";
|
import Footer from './dialog-footer.svelte';
|
||||||
import Header from "./dialog-header.svelte";
|
import Header from './dialog-header.svelte';
|
||||||
import Overlay from "./dialog-overlay.svelte";
|
import Overlay from './dialog-overlay.svelte';
|
||||||
import Content from "./dialog-content.svelte";
|
import Content from './dialog-content.svelte';
|
||||||
import Description from "./dialog-description.svelte";
|
import Description from './dialog-description.svelte';
|
||||||
import Trigger from "./dialog-trigger.svelte";
|
import Trigger from './dialog-trigger.svelte';
|
||||||
import Close from "./dialog-close.svelte";
|
import Close from './dialog-close.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -30,5 +30,5 @@ export {
|
|||||||
Overlay as DialogOverlay,
|
Overlay as DialogOverlay,
|
||||||
Content as DialogContent,
|
Content as DialogContent,
|
||||||
Description as DialogDescription,
|
Description as DialogDescription,
|
||||||
Close as DialogClose,
|
Close as DialogClose
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import MinusIcon from '@lucide/svelte/icons/minus';
|
import MinusIcon from '@lucide/svelte/icons/minus';
|
||||||
import CheckIcon from '@lucide/svelte/icons/check';
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -23,20 +23,20 @@
|
|||||||
bind:indeterminate
|
bind:indeterminate
|
||||||
data-slot="dropdown-menu-checkbox-item"
|
data-slot="dropdown-menu-checkbox-item"
|
||||||
class={cn(
|
class={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{#snippet children({ checked, indeterminate })}
|
{#snippet children({ checked, indeterminate })}
|
||||||
<span
|
<span
|
||||||
class="absolute right-2 flex items-center justify-center pointer-events-none"
|
class="pointer-events-none absolute right-2 flex items-center justify-center"
|
||||||
data-slot="dropdown-menu-checkbox-item-indicator"
|
data-slot="dropdown-menu-checkbox-item-indicator"
|
||||||
>
|
>
|
||||||
{#if indeterminate}
|
{#if indeterminate}
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
{:else if checked}
|
{:else if checked}
|
||||||
<CheckIcon />
|
<CheckIcon />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
{@render childrenProp?.()}
|
{@render childrenProp?.()}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import DropdownMenuPortal from "./dropdown-menu-portal.svelte";
|
import DropdownMenuPortal from './dropdown-menu-portal.svelte';
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import type { ComponentProps } from "svelte";
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
sideOffset = 4,
|
sideOffset = 4,
|
||||||
align = "start",
|
align = 'start',
|
||||||
portalProps,
|
portalProps,
|
||||||
class: className,
|
class: className,
|
||||||
...restProps
|
...restProps
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
{sideOffset}
|
{sideOffset}
|
||||||
{align}
|
{align}
|
||||||
class={cn(
|
class={cn(
|
||||||
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 z-50 w-(--bits-dropdown-menu-anchor-width) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden",
|
'z-50 w-(--bits-dropdown-menu-anchor-width) min-w-32 overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
import type { ComponentProps } from "svelte";
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -17,6 +17,6 @@
|
|||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dropdown-menu-group-heading"
|
data-slot="dropdown-menu-group-heading"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
class={cn("px-2 py-1.5 text-sm font-semibold data-[inset]:ps-8", className)}
|
class={cn('px-2 py-1.5 text-sm font-semibold data-[inset]:ps-8', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.GroupProps = $props();
|
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.GroupProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
inset,
|
inset,
|
||||||
variant = "default",
|
variant = 'default',
|
||||||
...restProps
|
...restProps
|
||||||
}: DropdownMenuPrimitive.ItemProps & {
|
}: DropdownMenuPrimitive.ItemProps & {
|
||||||
inset?: boolean;
|
inset?: boolean;
|
||||||
variant?: "default" | "destructive";
|
variant?: 'default' | 'destructive';
|
||||||
} = $props();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
class={cn(
|
class={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -17,7 +17,10 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="dropdown-menu-label"
|
data-slot="dropdown-menu-label"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
class={cn("text-muted-foreground px-1.5 py-1 text-xs font-medium data-inset:pl-7 data-[inset]:pl-8", className)}
|
class={cn(
|
||||||
|
'px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7 data-[inset]:pl-8',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ...restProps }: DropdownMenuPrimitive.PortalProps = $props();
|
let { ...restProps }: DropdownMenuPrimitive.PortalProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import CheckIcon from '@lucide/svelte/icons/check';
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -15,18 +15,18 @@
|
|||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dropdown-menu-radio-item"
|
data-slot="dropdown-menu-radio-item"
|
||||||
class={cn(
|
class={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{#snippet children({ checked })}
|
{#snippet children({ checked })}
|
||||||
<span
|
<span
|
||||||
class="absolute right-2 flex items-center justify-center pointer-events-none"
|
class="pointer-events-none absolute right-2 flex items-center justify-center"
|
||||||
data-slot="dropdown-menu-radio-item-indicator"
|
data-slot="dropdown-menu-radio-item-indicator"
|
||||||
>
|
>
|
||||||
{#if checked}
|
{#if checked}
|
||||||
<CheckIcon />
|
<CheckIcon />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
{@render childrenProp?.({ checked })}
|
{@render childrenProp?.({ checked })}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,6 @@
|
|||||||
<DropdownMenuPrimitive.Separator
|
<DropdownMenuPrimitive.Separator
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dropdown-menu-separator"
|
data-slot="dropdown-menu-separator"
|
||||||
class={cn("bg-border -mx-1 my-1 h-px", className)}
|
class={cn('-mx-1 my-1 h-px bg-border', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,10 @@
|
|||||||
<span
|
<span
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="dropdown-menu-shortcut"
|
data-slot="dropdown-menu-shortcut"
|
||||||
class={cn("text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest", className)}
|
class={cn(
|
||||||
|
'ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dropdown-menu-sub-content"
|
data-slot="dropdown-menu-sub-content"
|
||||||
class={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-lg p-1 shadow-lg ring-1 duration-100 w-auto", className)}
|
class={cn(
|
||||||
|
'w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
|
import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
data-slot="dropdown-menu-sub-trigger"
|
data-slot="dropdown-menu-sub-trigger"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
class={cn(
|
class={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.SubProps = $props();
|
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.SubProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.TriggerProps = $props();
|
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.TriggerProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.RootProps = $props();
|
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.RootProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import Root from "./dropdown-menu.svelte";
|
import Root from './dropdown-menu.svelte';
|
||||||
import Sub from "./dropdown-menu-sub.svelte";
|
import Sub from './dropdown-menu-sub.svelte';
|
||||||
import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte";
|
import CheckboxGroup from './dropdown-menu-checkbox-group.svelte';
|
||||||
import CheckboxItem from "./dropdown-menu-checkbox-item.svelte";
|
import CheckboxItem from './dropdown-menu-checkbox-item.svelte';
|
||||||
import Content from "./dropdown-menu-content.svelte";
|
import Content from './dropdown-menu-content.svelte';
|
||||||
import Group from "./dropdown-menu-group.svelte";
|
import Group from './dropdown-menu-group.svelte';
|
||||||
import Item from "./dropdown-menu-item.svelte";
|
import Item from './dropdown-menu-item.svelte';
|
||||||
import Label from "./dropdown-menu-label.svelte";
|
import Label from './dropdown-menu-label.svelte';
|
||||||
import RadioGroup from "./dropdown-menu-radio-group.svelte";
|
import RadioGroup from './dropdown-menu-radio-group.svelte';
|
||||||
import RadioItem from "./dropdown-menu-radio-item.svelte";
|
import RadioItem from './dropdown-menu-radio-item.svelte';
|
||||||
import Separator from "./dropdown-menu-separator.svelte";
|
import Separator from './dropdown-menu-separator.svelte';
|
||||||
import Shortcut from "./dropdown-menu-shortcut.svelte";
|
import Shortcut from './dropdown-menu-shortcut.svelte';
|
||||||
import Trigger from "./dropdown-menu-trigger.svelte";
|
import Trigger from './dropdown-menu-trigger.svelte';
|
||||||
import SubContent from "./dropdown-menu-sub-content.svelte";
|
import SubContent from './dropdown-menu-sub-content.svelte';
|
||||||
import SubTrigger from "./dropdown-menu-sub-trigger.svelte";
|
import SubTrigger from './dropdown-menu-sub-trigger.svelte';
|
||||||
import GroupHeading from "./dropdown-menu-group-heading.svelte";
|
import GroupHeading from './dropdown-menu-group-heading.svelte';
|
||||||
import Portal from "./dropdown-menu-portal.svelte";
|
import Portal from './dropdown-menu-portal.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
CheckboxGroup,
|
CheckboxGroup,
|
||||||
@@ -50,5 +50,5 @@ export {
|
|||||||
Sub,
|
Sub,
|
||||||
SubContent,
|
SubContent,
|
||||||
SubTrigger,
|
SubTrigger,
|
||||||
Trigger,
|
Trigger
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Button, type ButtonProps } from "$lib/ui/core/button/index.js";
|
import { Button, type ButtonProps } from '$lib/ui/core/button/index.js';
|
||||||
|
|
||||||
let { ref = $bindable(null), ...restProps }: ButtonProps = $props();
|
let { ref = $bindable(null), ...restProps }: ButtonProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,6 +12,6 @@
|
|||||||
<FormPrimitive.Description
|
<FormPrimitive.Description
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="form-description"
|
data-slot="form-description"
|
||||||
class={cn("text-muted-foreground text-sm", className)}
|
class={cn('text-sm text-muted-foreground', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPathLeaves<T>">
|
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPathLeaves<T>">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import type { FormPathLeaves } from "sveltekit-superforms";
|
import type { FormPathLeaves } from 'sveltekit-superforms';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils.js";
|
import { cn, type WithElementRef, type WithoutChildren } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<FormPrimitive.ElementField {form} {name}>
|
<FormPrimitive.ElementField {form} {name}>
|
||||||
{#snippet children({ constraints, errors, tainted, value })}
|
{#snippet children({ constraints, errors, tainted, value })}
|
||||||
<div bind:this={ref} class={cn("space-y-2", className)} {...restProps}>
|
<div bind:this={ref} class={cn('space-y-2', className)} {...restProps}>
|
||||||
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
|
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<FormPrimitive.FieldErrors
|
<FormPrimitive.FieldErrors
|
||||||
bind:ref
|
bind:ref
|
||||||
class={cn("text-destructive text-sm font-medium", className)}
|
class={cn('text-sm font-medium text-destructive', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{#snippet children({ errors, errorProps })}
|
{#snippet children({ errors, errorProps })}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import type { FormPath } from "sveltekit-superforms";
|
import type { FormPath } from 'sveltekit-superforms';
|
||||||
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils.js";
|
import { cn, type WithElementRef, type WithoutChildren } from '$lib/utils.js';
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -17,12 +17,7 @@
|
|||||||
|
|
||||||
<FormPrimitive.Field {form} {name}>
|
<FormPrimitive.Field {form} {name}>
|
||||||
{#snippet children({ constraints, errors, tainted, value })}
|
{#snippet children({ constraints, errors, tainted, value })}
|
||||||
<div
|
<div bind:this={ref} data-slot="form-item" class={cn('space-y-2', className)} {...restProps}>
|
||||||
bind:this={ref}
|
|
||||||
data-slot="form-item"
|
|
||||||
class={cn("space-y-2", className)}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
|
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import type { FormPath } from "sveltekit-superforms";
|
import type { FormPath } from 'sveltekit-superforms';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -12,4 +12,4 @@
|
|||||||
}: WithoutChild<FormPrimitive.FieldsetProps<T, U>> = $props();
|
}: WithoutChild<FormPrimitive.FieldsetProps<T, U>> = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormPrimitive.Fieldset bind:ref {form} {name} class={cn("space-y-2", className)} {...restProps} />
|
<FormPrimitive.Fieldset bind:ref {form} {name} class={cn('space-y-2', className)} {...restProps} />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import { Label } from "$lib/ui/core/label/index.js";
|
import { Label } from '$lib/ui/core/label/index.js';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<Label
|
<Label
|
||||||
{...props}
|
{...props}
|
||||||
data-slot="form-label"
|
data-slot="form-label"
|
||||||
class={cn("data-[fs-error]:text-destructive", className)}
|
class={cn('data-[fs-error]:text-destructive', className)}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</Label>
|
</Label>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import { cn, type WithoutChild } from "$lib/utils.js";
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -11,6 +11,6 @@
|
|||||||
|
|
||||||
<FormPrimitive.Legend
|
<FormPrimitive.Legend
|
||||||
bind:ref
|
bind:ref
|
||||||
class={cn("data-[fs-error]:text-destructive text-sm leading-none font-medium", className)}
|
class={cn('text-sm leading-none font-medium data-[fs-error]:text-destructive', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import * as FormPrimitive from "formsnap";
|
import * as FormPrimitive from 'formsnap';
|
||||||
import Description from "./form-description.svelte";
|
import Description from './form-description.svelte';
|
||||||
import Label from "./form-label.svelte";
|
import Label from './form-label.svelte';
|
||||||
import FieldErrors from "./form-field-errors.svelte";
|
import FieldErrors from './form-field-errors.svelte';
|
||||||
import Field from "./form-field.svelte";
|
import Field from './form-field.svelte';
|
||||||
import Fieldset from "./form-fieldset.svelte";
|
import Fieldset from './form-fieldset.svelte';
|
||||||
import Legend from "./form-legend.svelte";
|
import Legend from './form-legend.svelte';
|
||||||
import ElementField from "./form-element-field.svelte";
|
import ElementField from './form-element-field.svelte';
|
||||||
import Button from "./form-button.svelte";
|
import Button from './form-button.svelte';
|
||||||
|
|
||||||
const Control = FormPrimitive.Control;
|
const Control = FormPrimitive.Control;
|
||||||
|
|
||||||
@@ -29,5 +29,5 @@ export {
|
|||||||
Fieldset as FormFieldset,
|
Fieldset as FormFieldset,
|
||||||
Legend as FormLegend,
|
Legend as FormLegend,
|
||||||
ElementField as FormElementField,
|
ElementField as FormElementField,
|
||||||
Button as FormButton,
|
Button as FormButton
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Root from "./input.svelte";
|
import Root from './input.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
//
|
//
|
||||||
Root as Input,
|
Root as Input
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
|
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
|
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
|
||||||
|
|
||||||
type Props = WithElementRef<
|
type Props = WithElementRef<
|
||||||
Omit<HTMLInputAttributes, "type"> &
|
Omit<HTMLInputAttributes, 'type'> &
|
||||||
({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })
|
({ type: 'file'; files?: FileList } | { type?: InputType; files?: undefined })
|
||||||
>;
|
>;
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -15,17 +15,17 @@
|
|||||||
type,
|
type,
|
||||||
files = $bindable(),
|
files = $bindable(),
|
||||||
class: className,
|
class: className,
|
||||||
"data-slot": dataSlot = "input",
|
'data-slot': dataSlot = 'input',
|
||||||
...restProps
|
...restProps
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === "file"}
|
{#if type === 'file'}
|
||||||
<input
|
<input
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot={dataSlot}
|
data-slot={dataSlot}
|
||||||
class={cn(
|
class={cn(
|
||||||
"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
type="file"
|
type="file"
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot={dataSlot}
|
data-slot={dataSlot}
|
||||||
class={cn(
|
class={cn(
|
||||||
"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{type}
|
{type}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Root from "./label.svelte";
|
import Root from './label.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
//
|
//
|
||||||
Root as Label,
|
Root as Label
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Label as LabelPrimitive } from "bits-ui";
|
import { Label as LabelPrimitive } from 'bits-ui';
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
bind:ref
|
bind:ref
|
||||||
data-slot="label"
|
data-slot="label"
|
||||||
class={cn(
|
class={cn(
|
||||||
"gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed",
|
'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import Root from "./popover.svelte";
|
import Root from './popover.svelte';
|
||||||
import Close from "./popover-close.svelte";
|
import Close from './popover-close.svelte';
|
||||||
import Content from "./popover-content.svelte";
|
import Content from './popover-content.svelte';
|
||||||
import Description from "./popover-description.svelte";
|
import Description from './popover-description.svelte';
|
||||||
import Header from "./popover-header.svelte";
|
import Header from './popover-header.svelte';
|
||||||
import Title from "./popover-title.svelte";
|
import Title from './popover-title.svelte';
|
||||||
import Trigger from "./popover-trigger.svelte";
|
import Trigger from './popover-trigger.svelte';
|
||||||
import Portal from "./popover-portal.svelte";
|
import Portal from './popover-portal.svelte';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
@@ -24,5 +24,5 @@ export {
|
|||||||
Title as PopoverTitle,
|
Title as PopoverTitle,
|
||||||
Trigger as PopoverTrigger,
|
Trigger as PopoverTrigger,
|
||||||
Close as PopoverClose,
|
Close as PopoverClose,
|
||||||
Portal as PopoverPortal,
|
Portal as PopoverPortal
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Popover as PopoverPrimitive } from "bits-ui";
|
import { Popover as PopoverPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
let { ref = $bindable(null), ...restProps }: PopoverPrimitive.CloseProps = $props();
|
let { ref = $bindable(null), ...restProps }: PopoverPrimitive.CloseProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Popover as PopoverPrimitive } from "bits-ui";
|
import { Popover as PopoverPrimitive } from 'bits-ui';
|
||||||
import PopoverPortal from "./popover-portal.svelte";
|
import PopoverPortal from './popover-portal.svelte';
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
import type { ComponentProps } from "svelte";
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
class: className,
|
class: className,
|
||||||
sideOffset = 4,
|
sideOffset = 4,
|
||||||
align = "center",
|
align = 'center',
|
||||||
portalProps,
|
portalProps,
|
||||||
...restProps
|
...restProps
|
||||||
}: PopoverPrimitive.ContentProps & {
|
}: PopoverPrimitive.ContentProps & {
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
{sideOffset}
|
{sideOffset}
|
||||||
{align}
|
{align}
|
||||||
class={cn(
|
class={cn(
|
||||||
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 z-50 w-72 origin-(--transform-origin) outline-hidden",
|
'z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="popover-description"
|
data-slot="popover-description"
|
||||||
class={cn("text-muted-foreground", className)}
|
class={cn('text-muted-foreground', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLAttributes } from "svelte/elements";
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
bind:this={ref}
|
bind:this={ref}
|
||||||
data-slot="popover-header"
|
data-slot="popover-header"
|
||||||
class={cn("flex flex-col gap-0.5 text-sm", className)}
|
class={cn('flex flex-col gap-0.5 text-sm', className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user