@classic-homes/theme-svelte 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +305 -0
  2. package/dist/lib/components/Alert.svelte +51 -0
  3. package/dist/lib/components/Alert.svelte.d.ts +9 -0
  4. package/dist/lib/components/AlertDescription.svelte +16 -0
  5. package/dist/lib/components/AlertDescription.svelte.d.ts +9 -0
  6. package/dist/lib/components/AlertDialog.svelte +136 -0
  7. package/dist/lib/components/AlertDialog.svelte.d.ts +79 -0
  8. package/dist/lib/components/AlertTitle.svelte +16 -0
  9. package/dist/lib/components/AlertTitle.svelte.d.ts +9 -0
  10. package/dist/lib/components/Avatar.svelte +56 -0
  11. package/dist/lib/components/Avatar.svelte.d.ts +26 -0
  12. package/dist/lib/components/AvatarFallback.svelte +31 -0
  13. package/dist/lib/components/AvatarFallback.svelte.d.ts +17 -0
  14. package/dist/lib/components/AvatarImage.svelte +29 -0
  15. package/dist/lib/components/AvatarImage.svelte.d.ts +12 -0
  16. package/dist/lib/components/Badge.svelte +73 -0
  17. package/dist/lib/components/Badge.svelte.d.ts +11 -0
  18. package/dist/lib/components/Button.svelte +130 -0
  19. package/dist/lib/components/Button.svelte.d.ts +17 -0
  20. package/dist/lib/components/Card.svelte +58 -0
  21. package/dist/lib/components/Card.svelte.d.ts +26 -0
  22. package/dist/lib/components/CardContent.svelte +16 -0
  23. package/dist/lib/components/CardContent.svelte.d.ts +9 -0
  24. package/dist/lib/components/CardDescription.svelte +16 -0
  25. package/dist/lib/components/CardDescription.svelte.d.ts +9 -0
  26. package/dist/lib/components/CardFooter.svelte +16 -0
  27. package/dist/lib/components/CardFooter.svelte.d.ts +9 -0
  28. package/dist/lib/components/CardHeader.svelte +16 -0
  29. package/dist/lib/components/CardHeader.svelte.d.ts +9 -0
  30. package/dist/lib/components/CardTitle.svelte +16 -0
  31. package/dist/lib/components/CardTitle.svelte.d.ts +9 -0
  32. package/dist/lib/components/Checkbox.svelte +65 -0
  33. package/dist/lib/components/Checkbox.svelte.d.ts +14 -0
  34. package/dist/lib/components/DataTable.svelte +334 -0
  35. package/dist/lib/components/DataTable.svelte.d.ts +103 -0
  36. package/dist/lib/components/Dialog.svelte +111 -0
  37. package/dist/lib/components/Dialog.svelte.d.ts +22 -0
  38. package/dist/lib/components/DropdownMenu.svelte +135 -0
  39. package/dist/lib/components/DropdownMenu.svelte.d.ts +33 -0
  40. package/dist/lib/components/FileUpload.svelte +448 -0
  41. package/dist/lib/components/FileUpload.svelte.d.ts +42 -0
  42. package/dist/lib/components/FormField.svelte +134 -0
  43. package/dist/lib/components/FormField.svelte.d.ts +37 -0
  44. package/dist/lib/components/Input.svelte +61 -0
  45. package/dist/lib/components/Input.svelte.d.ts +19 -0
  46. package/dist/lib/components/Label.svelte +33 -0
  47. package/dist/lib/components/Label.svelte.d.ts +11 -0
  48. package/dist/lib/components/LoadingLogo.svelte +124 -0
  49. package/dist/lib/components/LoadingLogo.svelte.d.ts +16 -0
  50. package/dist/lib/components/LogoMain.svelte +237 -0
  51. package/dist/lib/components/LogoMain.svelte.d.ts +20 -0
  52. package/dist/lib/components/PageHeader.svelte +90 -0
  53. package/dist/lib/components/PageHeader.svelte.d.ts +28 -0
  54. package/dist/lib/components/Section.svelte +44 -0
  55. package/dist/lib/components/Section.svelte.d.ts +28 -0
  56. package/dist/lib/components/Select.svelte +174 -0
  57. package/dist/lib/components/Select.svelte.d.ts +32 -0
  58. package/dist/lib/components/Separator.svelte +29 -0
  59. package/dist/lib/components/Separator.svelte.d.ts +9 -0
  60. package/dist/lib/components/Skeleton.svelte +35 -0
  61. package/dist/lib/components/Skeleton.svelte.d.ts +7 -0
  62. package/dist/lib/components/Spinner.svelte +50 -0
  63. package/dist/lib/components/Spinner.svelte.d.ts +8 -0
  64. package/dist/lib/components/Switch.svelte +56 -0
  65. package/dist/lib/components/Switch.svelte.d.ts +14 -0
  66. package/dist/lib/components/TabPanel.svelte +44 -0
  67. package/dist/lib/components/TabPanel.svelte.d.ts +12 -0
  68. package/dist/lib/components/Tabs.svelte +125 -0
  69. package/dist/lib/components/Tabs.svelte.d.ts +19 -0
  70. package/dist/lib/components/Textarea.svelte +54 -0
  71. package/dist/lib/components/Textarea.svelte.d.ts +16 -0
  72. package/dist/lib/components/Toast.svelte +116 -0
  73. package/dist/lib/components/Toast.svelte.d.ts +12 -0
  74. package/dist/lib/components/ToastContainer.svelte +56 -0
  75. package/dist/lib/components/ToastContainer.svelte.d.ts +8 -0
  76. package/dist/lib/components/Tooltip.svelte +55 -0
  77. package/dist/lib/components/Tooltip.svelte.d.ts +18 -0
  78. package/dist/lib/components/layout/AppShell.svelte +82 -0
  79. package/dist/lib/components/layout/AppShell.svelte.d.ts +44 -0
  80. package/dist/lib/components/layout/DashboardLayout.svelte +248 -0
  81. package/dist/lib/components/layout/DashboardLayout.svelte.d.ts +62 -0
  82. package/dist/lib/components/layout/Footer.svelte +130 -0
  83. package/dist/lib/components/layout/Footer.svelte.d.ts +32 -0
  84. package/dist/lib/components/layout/FormPageLayout.svelte +92 -0
  85. package/dist/lib/components/layout/FormPageLayout.svelte.d.ts +33 -0
  86. package/dist/lib/components/layout/Header.svelte +94 -0
  87. package/dist/lib/components/layout/Header.svelte.d.ts +30 -0
  88. package/dist/lib/components/layout/PublicLayout.svelte +180 -0
  89. package/dist/lib/components/layout/PublicLayout.svelte.d.ts +39 -0
  90. package/dist/lib/components/layout/QuickLinks.svelte +112 -0
  91. package/dist/lib/components/layout/QuickLinks.svelte.d.ts +27 -0
  92. package/dist/lib/components/layout/Sidebar.svelte +243 -0
  93. package/dist/lib/components/layout/Sidebar.svelte.d.ts +48 -0
  94. package/dist/lib/composables/index.d.ts +8 -0
  95. package/dist/lib/composables/index.js +10 -0
  96. package/dist/lib/composables/useAsync.svelte.d.ts +102 -0
  97. package/dist/lib/composables/useAsync.svelte.js +210 -0
  98. package/dist/lib/composables/useForm.svelte.d.ts +123 -0
  99. package/dist/lib/composables/useForm.svelte.js +245 -0
  100. package/dist/lib/index.d.ts +65 -0
  101. package/dist/lib/index.js +83 -0
  102. package/dist/lib/performance.d.ts +79 -0
  103. package/dist/lib/performance.js +170 -0
  104. package/dist/lib/schemas/auth.d.ts +410 -0
  105. package/dist/lib/schemas/auth.js +216 -0
  106. package/dist/lib/schemas/common.d.ts +267 -0
  107. package/dist/lib/schemas/common.js +268 -0
  108. package/dist/lib/schemas/index.d.ts +24 -0
  109. package/dist/lib/schemas/index.js +32 -0
  110. package/dist/lib/stores/sidebar.svelte.d.ts +25 -0
  111. package/dist/lib/stores/sidebar.svelte.js +38 -0
  112. package/dist/lib/stores/theme.svelte.d.ts +72 -0
  113. package/dist/lib/stores/theme.svelte.js +150 -0
  114. package/dist/lib/stores/toast.svelte.d.ts +62 -0
  115. package/dist/lib/stores/toast.svelte.js +93 -0
  116. package/dist/lib/types/components.d.ts +85 -0
  117. package/dist/lib/types/components.js +7 -0
  118. package/dist/lib/types/layout.d.ts +258 -0
  119. package/dist/lib/types/layout.js +7 -0
  120. package/dist/lib/utils.d.ts +6 -0
  121. package/dist/lib/utils.js +9 -0
  122. package/dist/lib/validation.d.ts +101 -0
  123. package/dist/lib/validation.js +170 -0
  124. package/package.json +56 -0
@@ -0,0 +1,334 @@
1
+ <script lang="ts" generics="T extends Record<string, unknown>">
2
+ /**
3
+ * DataTable - A sortable, accessible data table component
4
+ *
5
+ * @template T - The type of data objects in each row. Must be an object type.
6
+ *
7
+ * ## Features
8
+ * - Column definitions with headers and accessors
9
+ * - Client-side sorting (click column headers)
10
+ * - External sort control via onSort callback
11
+ * - Loading state with skeleton rows
12
+ * - Empty state message
13
+ * - Responsive horizontal scroll
14
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
15
+ * - Custom row rendering via snippet
16
+ * - Memoized sorting for performance
17
+ *
18
+ * ## Basic Usage
19
+ * ```svelte
20
+ * <DataTable
21
+ * data={users}
22
+ * columns={[
23
+ * { id: 'name', header: 'Name', accessor: 'name', sortable: true },
24
+ * { id: 'email', header: 'Email', accessor: 'email' },
25
+ * ]}
26
+ * />
27
+ * ```
28
+ *
29
+ * ## Custom Cell Formatting
30
+ * ```svelte
31
+ * columns={[
32
+ * {
33
+ * id: 'date',
34
+ * header: 'Created',
35
+ * accessor: 'createdAt',
36
+ * format: (value) => new Date(value).toLocaleDateString(),
37
+ * },
38
+ * ]}
39
+ * ```
40
+ *
41
+ * ## Server-Side Sorting
42
+ * ```svelte
43
+ * <DataTable
44
+ * {data}
45
+ * {columns}
46
+ * sortColumn={serverSort.column}
47
+ * sortDirection={serverSort.direction}
48
+ * onSort={(col, dir) => fetchSorted(col, dir)}
49
+ * />
50
+ * ```
51
+ *
52
+ * @see DataTableColumn for column configuration options
53
+ */
54
+ import type { DataTableColumn } from '../types/components.js';
55
+ import type { Snippet } from 'svelte';
56
+ import { cn } from '../utils.js';
57
+ import { validateNonEmptyArray } from '../validation.js';
58
+ import Skeleton from './Skeleton.svelte';
59
+
60
+ interface Props {
61
+ /** Array of data rows */
62
+ data: T[];
63
+ /** Column definitions */
64
+ columns: DataTableColumn<T>[];
65
+ /** Loading state */
66
+ loading?: boolean;
67
+ /** Number of skeleton rows to show when loading */
68
+ loadingRows?: number;
69
+ /** Message when no data */
70
+ emptyMessage?: string;
71
+ /** Current sort column ID */
72
+ sortColumn?: string;
73
+ /** Current sort direction */
74
+ sortDirection?: 'asc' | 'desc';
75
+ /** Callback when sort changes */
76
+ onSort?: (column: string, direction: 'asc' | 'desc') => void;
77
+ /** Callback when row is clicked */
78
+ onRowClick?: (row: T) => void;
79
+ /** Caption for accessibility */
80
+ caption?: string;
81
+ /** Custom row snippet for complete control */
82
+ row?: Snippet<[T, number]>;
83
+ /** Additional classes */
84
+ class?: string;
85
+ }
86
+
87
+ let {
88
+ data,
89
+ columns,
90
+ loading = false,
91
+ loadingRows = 5,
92
+ emptyMessage = 'No data available',
93
+ sortColumn = $bindable(undefined),
94
+ sortDirection = $bindable('asc'),
95
+ onSort,
96
+ onRowClick,
97
+ caption,
98
+ row: rowSnippet,
99
+ class: className,
100
+ }: Props = $props();
101
+
102
+ // Validate props in development
103
+ $effect(() => {
104
+ validateNonEmptyArray(columns, 'columns', 'DataTable');
105
+ });
106
+
107
+ // Get cell value from row
108
+ function getCellValue(row: T, column: DataTableColumn<T>): unknown {
109
+ if (typeof column.accessor === 'function') {
110
+ return column.accessor(row);
111
+ }
112
+ return row[column.accessor as keyof T];
113
+ }
114
+
115
+ // Format cell value
116
+ function formatCellValue(row: T, column: DataTableColumn<T>): string {
117
+ const value = getCellValue(row, column);
118
+ if (column.format) {
119
+ return column.format(value, row);
120
+ }
121
+ if (value === null || value === undefined) {
122
+ return '';
123
+ }
124
+ return String(value);
125
+ }
126
+
127
+ /**
128
+ * Memoization cache for sorted data
129
+ * Tracks previous inputs to avoid unnecessary re-sorts
130
+ */
131
+ let cachedData: T[] = [];
132
+ let cachedSortColumn: string | undefined;
133
+ let cachedSortDirection: 'asc' | 'desc' = 'asc';
134
+ let cachedResult: T[] = [];
135
+
136
+ /**
137
+ * Sort data internally if no onSort callback
138
+ * Uses memoization to avoid re-sorting when inputs haven't changed
139
+ *
140
+ * Future enhancement path for virtualization:
141
+ * 1. Add `virtualize?: boolean` prop
142
+ * 2. Add `rowHeight?: number` prop (default: 48)
143
+ * 3. Add `overscan?: number` prop (default: 5)
144
+ * 4. When virtualize=true, render only visible rows + overscan
145
+ * 5. Use IntersectionObserver or scroll position for windowing
146
+ */
147
+ const sortedData = $derived.by(() => {
148
+ // If external sort handler or no sort column, return data as-is
149
+ if (!sortColumn || onSort) {
150
+ return data;
151
+ }
152
+
153
+ // Check if we can use cached result (same inputs)
154
+ const inputsUnchanged =
155
+ data === cachedData &&
156
+ sortColumn === cachedSortColumn &&
157
+ sortDirection === cachedSortDirection;
158
+
159
+ if (inputsUnchanged && cachedResult.length > 0) {
160
+ return cachedResult;
161
+ }
162
+
163
+ // Find the column definition
164
+ const column = columns.find((c) => c.id === sortColumn);
165
+ if (!column) {
166
+ return data;
167
+ }
168
+
169
+ // Perform sort with improved comparison
170
+ const sorted = [...data].sort((a, b) => {
171
+ const aVal = getCellValue(a, column);
172
+ const bVal = getCellValue(b, column);
173
+
174
+ // Handle null/undefined - nulls sort to end
175
+ if (aVal == null && bVal == null) return 0;
176
+ if (aVal == null) return sortDirection === 'asc' ? 1 : -1;
177
+ if (bVal == null) return sortDirection === 'asc' ? -1 : 1;
178
+
179
+ // String comparison with locale support and numeric sorting
180
+ if (typeof aVal === 'string' && typeof bVal === 'string') {
181
+ const result = aVal.localeCompare(bVal, undefined, {
182
+ numeric: true,
183
+ sensitivity: 'base',
184
+ });
185
+ return sortDirection === 'asc' ? result : -result;
186
+ }
187
+
188
+ // Date comparison
189
+ if (aVal instanceof Date && bVal instanceof Date) {
190
+ const diff = aVal.getTime() - bVal.getTime();
191
+ return sortDirection === 'asc' ? diff : -diff;
192
+ }
193
+
194
+ // Numeric/generic comparison
195
+ if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
196
+ if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
197
+ return 0;
198
+ });
199
+
200
+ // Update cache
201
+ cachedData = data;
202
+ cachedSortColumn = sortColumn;
203
+ cachedSortDirection = sortDirection;
204
+ cachedResult = sorted;
205
+
206
+ return sorted;
207
+ });
208
+
209
+ // Handle column header click for sorting
210
+ function handleSort(column: DataTableColumn<T>) {
211
+ if (!column.sortable) return;
212
+
213
+ const newDirection = sortColumn === column.id && sortDirection === 'asc' ? 'desc' : 'asc';
214
+ sortColumn = column.id;
215
+ sortDirection = newDirection;
216
+
217
+ if (onSort) {
218
+ onSort(column.id, newDirection);
219
+ }
220
+ }
221
+
222
+ // Handle row click
223
+ function handleRowClick(row: T) {
224
+ if (onRowClick) {
225
+ onRowClick(row);
226
+ }
227
+ }
228
+
229
+ // Get alignment class
230
+ function getAlignClass(align?: 'left' | 'center' | 'right'): string {
231
+ switch (align) {
232
+ case 'center':
233
+ return 'text-center';
234
+ case 'right':
235
+ return 'text-right';
236
+ default:
237
+ return 'text-left';
238
+ }
239
+ }
240
+ </script>
241
+
242
+ <div class={cn('overflow-x-auto rounded-lg border', className)}>
243
+ <table class="w-full text-sm">
244
+ {#if caption}
245
+ <caption class="sr-only">{caption}</caption>
246
+ {/if}
247
+
248
+ <thead class="border-b bg-muted/50">
249
+ <tr>
250
+ {#each columns as column (column.id)}
251
+ <th
252
+ scope="col"
253
+ class={cn(
254
+ 'px-4 py-3 font-medium text-muted-foreground',
255
+ getAlignClass(column.align),
256
+ column.sortable && 'cursor-pointer select-none hover:bg-muted/80'
257
+ )}
258
+ style={column.width ? `width: ${column.width}` : undefined}
259
+ aria-sort={sortColumn === column.id
260
+ ? sortDirection === 'asc'
261
+ ? 'ascending'
262
+ : 'descending'
263
+ : undefined}
264
+ >
265
+ {#if column.sortable}
266
+ <button
267
+ type="button"
268
+ class="inline-flex w-full items-center justify-between gap-2"
269
+ onclick={() => handleSort(column)}
270
+ >
271
+ <span>{column.header}</span>
272
+ <svg
273
+ class={cn(
274
+ 'h-4 w-4 transition-transform',
275
+ sortColumn !== column.id && 'opacity-0',
276
+ sortColumn === column.id && sortDirection === 'desc' && 'rotate-180'
277
+ )}
278
+ fill="none"
279
+ viewBox="0 0 24 24"
280
+ stroke="currentColor"
281
+ stroke-width="2"
282
+ >
283
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5 15l7-7 7 7" />
284
+ </svg>
285
+ </button>
286
+ {:else}
287
+ {column.header}
288
+ {/if}
289
+ </th>
290
+ {/each}
291
+ </tr>
292
+ </thead>
293
+
294
+ <tbody class="divide-y">
295
+ {#if loading}
296
+ {#each Array(loadingRows) as _, i}
297
+ <tr>
298
+ {#each columns as column (column.id)}
299
+ <td class="px-4 py-3">
300
+ <Skeleton class="h-4 w-3/4" />
301
+ </td>
302
+ {/each}
303
+ </tr>
304
+ {/each}
305
+ {:else if sortedData.length === 0}
306
+ <tr>
307
+ <td colspan={columns.length} class="px-4 py-8 text-center text-muted-foreground">
308
+ {emptyMessage}
309
+ </td>
310
+ </tr>
311
+ {:else}
312
+ {#each sortedData as row, index (index)}
313
+ {#if rowSnippet}
314
+ {@render rowSnippet(row, index)}
315
+ {:else}
316
+ <tr
317
+ class={cn(
318
+ 'bg-card transition-colors',
319
+ onRowClick && 'cursor-pointer hover:bg-muted/50'
320
+ )}
321
+ onclick={() => handleRowClick(row)}
322
+ >
323
+ {#each columns as column (column.id)}
324
+ <td class={cn('px-4 py-3', getAlignClass(column.align))}>
325
+ {formatCellValue(row, column)}
326
+ </td>
327
+ {/each}
328
+ </tr>
329
+ {/if}
330
+ {/each}
331
+ {/if}
332
+ </tbody>
333
+ </table>
334
+ </div>
@@ -0,0 +1,103 @@
1
+ /**
2
+ * DataTable - A sortable, accessible data table component
3
+ *
4
+ * @template T - The type of data objects in each row. Must be an object type.
5
+ *
6
+ * ## Features
7
+ * - Column definitions with headers and accessors
8
+ * - Client-side sorting (click column headers)
9
+ * - External sort control via onSort callback
10
+ * - Loading state with skeleton rows
11
+ * - Empty state message
12
+ * - Responsive horizontal scroll
13
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
14
+ * - Custom row rendering via snippet
15
+ * - Memoized sorting for performance
16
+ *
17
+ * ## Basic Usage
18
+ * ```svelte
19
+ * <DataTable
20
+ * data={users}
21
+ * columns={[
22
+ * { id: 'name', header: 'Name', accessor: 'name', sortable: true },
23
+ * { id: 'email', header: 'Email', accessor: 'email' },
24
+ * ]}
25
+ * />
26
+ * ```
27
+ *
28
+ * ## Custom Cell Formatting
29
+ * ```svelte
30
+ * columns={[
31
+ * {
32
+ * id: 'date',
33
+ * header: 'Created',
34
+ * accessor: 'createdAt',
35
+ * format: (value) => new Date(value).toLocaleDateString(),
36
+ * },
37
+ * ]}
38
+ * ```
39
+ *
40
+ * ## Server-Side Sorting
41
+ * ```svelte
42
+ * <DataTable
43
+ * {data}
44
+ * {columns}
45
+ * sortColumn={serverSort.column}
46
+ * sortDirection={serverSort.direction}
47
+ * onSort={(col, dir) => fetchSorted(col, dir)}
48
+ * />
49
+ * ```
50
+ *
51
+ * @see DataTableColumn for column configuration options
52
+ */
53
+ import type { DataTableColumn } from '../types/components.js';
54
+ import type { Snippet } from 'svelte';
55
+ declare function $$render<T extends Record<string, unknown>>(): {
56
+ props: {
57
+ /** Array of data rows */
58
+ data: T[];
59
+ /** Column definitions */
60
+ columns: DataTableColumn<T>[];
61
+ /** Loading state */
62
+ loading?: boolean;
63
+ /** Number of skeleton rows to show when loading */
64
+ loadingRows?: number;
65
+ /** Message when no data */
66
+ emptyMessage?: string;
67
+ /** Current sort column ID */
68
+ sortColumn?: string;
69
+ /** Current sort direction */
70
+ sortDirection?: "asc" | "desc";
71
+ /** Callback when sort changes */
72
+ onSort?: (column: string, direction: "asc" | "desc") => void;
73
+ /** Callback when row is clicked */
74
+ onRowClick?: (row: T) => void;
75
+ /** Caption for accessibility */
76
+ caption?: string;
77
+ /** Custom row snippet for complete control */
78
+ row?: Snippet<[T, number]>;
79
+ /** Additional classes */
80
+ class?: string;
81
+ };
82
+ exports: {};
83
+ bindings: "sortColumn" | "sortDirection";
84
+ slots: {};
85
+ events: {};
86
+ };
87
+ declare class __sveltets_Render<T extends Record<string, unknown>> {
88
+ props(): ReturnType<typeof $$render<T>>['props'];
89
+ events(): ReturnType<typeof $$render<T>>['events'];
90
+ slots(): ReturnType<typeof $$render<T>>['slots'];
91
+ bindings(): "sortColumn" | "sortDirection";
92
+ exports(): {};
93
+ }
94
+ interface $$IsomorphicComponent {
95
+ new <T extends Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
96
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
97
+ } & ReturnType<__sveltets_Render<T>['exports']>;
98
+ <T extends Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
99
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
100
+ }
101
+ declare const DataTable: $$IsomorphicComponent;
102
+ type DataTable<T extends Record<string, unknown>> = InstanceType<typeof DataTable<T>>;
103
+ export default DataTable;
@@ -0,0 +1,111 @@
1
+ <script lang="ts">
2
+ import { Dialog as DialogPrimitive } from 'bits-ui';
3
+ import { cn } from '../utils.js';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ interface Props {
7
+ /** Whether the dialog is open */
8
+ open?: boolean;
9
+ /** Callback when open state changes */
10
+ onOpenChange?: (open: boolean) => void;
11
+ /** Dialog title */
12
+ title?: string;
13
+ /** Dialog description */
14
+ description?: string;
15
+ /** Additional class for dialog content */
16
+ class?: string;
17
+ /** Content inside the dialog */
18
+ children: Snippet;
19
+ /** Optional trigger element */
20
+ trigger?: Snippet;
21
+ /** Optional footer element */
22
+ footer?: Snippet;
23
+ }
24
+
25
+ let {
26
+ open = $bindable(false),
27
+ onOpenChange,
28
+ title,
29
+ description,
30
+ class: className,
31
+ children,
32
+ trigger,
33
+ footer,
34
+ }: Props = $props();
35
+
36
+ function handleOpenChange(newOpen: boolean) {
37
+ open = newOpen;
38
+ onOpenChange?.(newOpen);
39
+ }
40
+ </script>
41
+
42
+ <DialogPrimitive.Root bind:open onOpenChange={handleOpenChange}>
43
+ {#if trigger}
44
+ <DialogPrimitive.Trigger asChild>
45
+ {#snippet child({ props })}
46
+ <span {...props}>
47
+ {@render trigger()}
48
+ </span>
49
+ {/snippet}
50
+ </DialogPrimitive.Trigger>
51
+ {/if}
52
+
53
+ <DialogPrimitive.Portal>
54
+ <DialogPrimitive.Overlay
55
+ class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
56
+ />
57
+ <DialogPrimitive.Content
58
+ class={cn(
59
+ 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
60
+ className
61
+ )}
62
+ >
63
+ {#if title || description}
64
+ <div class="flex flex-col space-y-1.5 text-center sm:text-left">
65
+ {#if title}
66
+ <DialogPrimitive.Title class="text-lg font-semibold leading-none tracking-tight">
67
+ {title}
68
+ </DialogPrimitive.Title>
69
+ {/if}
70
+ {#if description}
71
+ <DialogPrimitive.Description class="text-sm text-muted-foreground">
72
+ {description}
73
+ </DialogPrimitive.Description>
74
+ {/if}
75
+ </div>
76
+ {/if}
77
+
78
+ <div class="dialog-content">
79
+ {@render children()}
80
+ </div>
81
+
82
+ {#if footer}
83
+ <div class="flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2">
84
+ {@render footer()}
85
+ </div>
86
+ {/if}
87
+
88
+ <DialogPrimitive.Close
89
+ class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
90
+ aria-label="Close dialog"
91
+ >
92
+ <svg
93
+ xmlns="http://www.w3.org/2000/svg"
94
+ width="24"
95
+ height="24"
96
+ viewBox="0 0 24 24"
97
+ fill="none"
98
+ stroke="currentColor"
99
+ stroke-width="2"
100
+ stroke-linecap="round"
101
+ stroke-linejoin="round"
102
+ class="h-4 w-4"
103
+ >
104
+ <path d="M18 6 6 18" />
105
+ <path d="m6 6 12 12" />
106
+ </svg>
107
+ <span class="sr-only">Close</span>
108
+ </DialogPrimitive.Close>
109
+ </DialogPrimitive.Content>
110
+ </DialogPrimitive.Portal>
111
+ </DialogPrimitive.Root>
@@ -0,0 +1,22 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ /** Whether the dialog is open */
4
+ open?: boolean;
5
+ /** Callback when open state changes */
6
+ onOpenChange?: (open: boolean) => void;
7
+ /** Dialog title */
8
+ title?: string;
9
+ /** Dialog description */
10
+ description?: string;
11
+ /** Additional class for dialog content */
12
+ class?: string;
13
+ /** Content inside the dialog */
14
+ children: Snippet;
15
+ /** Optional trigger element */
16
+ trigger?: Snippet;
17
+ /** Optional footer element */
18
+ footer?: Snippet;
19
+ }
20
+ declare const Dialog: import("svelte").Component<Props, {}, "open">;
21
+ type Dialog = ReturnType<typeof Dialog>;
22
+ export default Dialog;