@joewinke/jatui 0.1.33 → 0.2.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 (209) hide show
  1. package/CLAUDE.md +22 -0
  2. package/dist/actions/attention.d.ts +24 -0
  3. package/dist/actions/attention.js +94 -0
  4. package/dist/actions/floating.d.ts +53 -0
  5. package/dist/actions/floating.js +158 -0
  6. package/dist/actions/staggerEntrance.d.ts +28 -0
  7. package/dist/actions/staggerEntrance.js +71 -0
  8. package/dist/actions/tooltip.d.ts +28 -0
  9. package/dist/actions/tooltip.js +186 -0
  10. package/dist/assets/sounds/README.md +47 -0
  11. package/dist/assets/sounds/error.d.ts +1 -0
  12. package/dist/assets/sounds/error.js +4 -0
  13. package/dist/assets/sounds/notify.d.ts +1 -0
  14. package/dist/assets/sounds/notify.js +4 -0
  15. package/dist/assets/sounds/pop.d.ts +1 -0
  16. package/dist/assets/sounds/pop.js +4 -0
  17. package/dist/assets/sounds/send.d.ts +1 -0
  18. package/dist/assets/sounds/send.js +4 -0
  19. package/dist/assets/sounds/success.d.ts +1 -0
  20. package/dist/assets/sounds/success.js +4 -0
  21. package/dist/assets/sounds/toggle.d.ts +1 -0
  22. package/dist/assets/sounds/toggle.js +4 -0
  23. package/dist/components/AnimatedNumber.svelte +112 -0
  24. package/dist/components/AnimatedNumber.svelte.d.ts +8 -0
  25. package/dist/components/Badge.svelte +75 -4
  26. package/dist/components/Badge.svelte.d.ts +6 -1
  27. package/dist/components/Button.svelte +196 -21
  28. package/dist/components/Button.svelte.d.ts +10 -1
  29. package/dist/components/Carousel.svelte +265 -0
  30. package/dist/components/Carousel.svelte.d.ts +21 -0
  31. package/dist/components/ChipInput.svelte +63 -3
  32. package/dist/components/Collapse.svelte +70 -14
  33. package/dist/components/Collapse.svelte.d.ts +11 -0
  34. package/dist/components/ColorSelector.svelte +21 -24
  35. package/dist/components/CommandPalette.svelte +475 -0
  36. package/dist/components/CommandPalette.svelte.d.ts +3 -0
  37. package/dist/components/ContextMenu.svelte +9 -73
  38. package/dist/components/CopyButton.svelte +156 -0
  39. package/dist/components/CopyButton.svelte.d.ts +12 -0
  40. package/dist/components/HoldToConfirm.svelte +183 -0
  41. package/dist/components/HoldToConfirm.svelte.d.ts +11 -0
  42. package/dist/components/KeyboardShortcutsOverlay.svelte +54 -8
  43. package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +3 -0
  44. package/dist/components/PasswordMeter.svelte +87 -0
  45. package/dist/components/PasswordMeter.svelte.d.ts +8 -0
  46. package/dist/components/PinInput.svelte +186 -0
  47. package/dist/components/PinInput.svelte.d.ts +13 -0
  48. package/dist/components/QuantityStepper.svelte +185 -0
  49. package/dist/components/QuantityStepper.svelte.d.ts +12 -0
  50. package/dist/components/Skeleton.svelte +123 -0
  51. package/dist/components/Skeleton.svelte.d.ts +12 -0
  52. package/dist/components/SpeechForm.svelte +37 -0
  53. package/dist/components/StatusBadge.svelte +31 -3
  54. package/dist/components/StatusBadge.svelte.d.ts +0 -5
  55. package/dist/components/Tabs.svelte +270 -0
  56. package/dist/components/Tabs.svelte.d.ts +15 -0
  57. package/dist/components/TextInput.svelte +138 -38
  58. package/dist/components/TextInput.svelte.d.ts +9 -1
  59. package/dist/components/VoicePlayer.svelte +51 -0
  60. package/dist/components/basic/Alert.svelte +36 -0
  61. package/dist/components/basic/Alert.svelte.d.ts +9 -0
  62. package/dist/components/basic/Breadcrumb.svelte +27 -0
  63. package/dist/components/basic/Breadcrumb.svelte.d.ts +11 -0
  64. package/dist/components/basic/ButtonGroup.svelte +15 -0
  65. package/dist/components/basic/ButtonGroup.svelte.d.ts +8 -0
  66. package/dist/components/basic/Checkbox.svelte +85 -0
  67. package/dist/components/basic/Checkbox.svelte.d.ts +15 -0
  68. package/dist/components/basic/Empty.svelte +17 -0
  69. package/dist/components/basic/Empty.svelte.d.ts +8 -0
  70. package/dist/components/basic/Kbd.svelte +16 -0
  71. package/dist/components/basic/Kbd.svelte.d.ts +8 -0
  72. package/dist/components/basic/Pagination.svelte +104 -0
  73. package/dist/components/basic/Pagination.svelte.d.ts +12 -0
  74. package/dist/components/basic/RadioGroup.svelte +71 -0
  75. package/dist/components/basic/RadioGroup.svelte.d.ts +18 -0
  76. package/dist/components/basic/Separator.svelte +19 -0
  77. package/dist/components/basic/Separator.svelte.d.ts +8 -0
  78. package/dist/components/basic/Slider.svelte +72 -0
  79. package/dist/components/basic/Slider.svelte.d.ts +17 -0
  80. package/dist/components/basic/Switch.svelte +88 -0
  81. package/dist/components/basic/Switch.svelte.d.ts +14 -0
  82. package/dist/components/basic/Toggle.svelte +43 -0
  83. package/dist/components/basic/Toggle.svelte.d.ts +14 -0
  84. package/dist/components/graph/GraphCanvas.svelte +103 -0
  85. package/dist/components/graph/GraphCanvas.svelte.d.ts +22 -0
  86. package/dist/components/graph/JatuiNode.svelte +128 -0
  87. package/dist/components/graph/JatuiNode.svelte.d.ts +14 -0
  88. package/dist/components/graph/theme.d.ts +27 -0
  89. package/dist/components/graph/theme.js +136 -0
  90. package/dist/components/messaging/MessageItem.svelte +92 -0
  91. package/dist/components/messaging/MessageItem.svelte.d.ts +5 -0
  92. package/dist/components/messaging/TypingIndicator.svelte +63 -0
  93. package/dist/components/messaging/TypingIndicator.svelte.d.ts +7 -0
  94. package/dist/components/pipeline/PipelineColumn.svelte +44 -3
  95. package/dist/components/progress/ProgressBar.svelte +189 -0
  96. package/dist/components/progress/ProgressBar.svelte.d.ts +17 -0
  97. package/dist/components/progress/ProgressRing.svelte +138 -0
  98. package/dist/components/progress/ProgressRing.svelte.d.ts +12 -0
  99. package/dist/components/progress/Steps.svelte +195 -0
  100. package/dist/components/progress/Steps.svelte.d.ts +14 -0
  101. package/dist/components/shell/NavigationMenu.svelte +422 -0
  102. package/dist/components/shell/NavigationMenu.svelte.d.ts +43 -0
  103. package/dist/components/shell/Sidebar.svelte +276 -0
  104. package/dist/components/shell/Sidebar.svelte.d.ts +32 -0
  105. package/dist/components/shell/SidebarGroup.svelte +180 -0
  106. package/dist/components/shell/SidebarGroup.svelte.d.ts +19 -0
  107. package/dist/components/shell/SidebarItem.svelte +170 -0
  108. package/dist/components/shell/SidebarItem.svelte.d.ts +24 -0
  109. package/dist/components/shell/shell.d.ts +30 -0
  110. package/dist/components/shell/shell.js +65 -0
  111. package/dist/components/table/DataTable.svelte +364 -0
  112. package/dist/components/table/DataTable.svelte.d.ts +4 -0
  113. package/dist/components/table/flexRender.d.ts +31 -0
  114. package/dist/components/table/flexRender.js +32 -0
  115. package/dist/components/table/types.d.ts +28 -0
  116. package/dist/components/table/types.js +1 -0
  117. package/dist/components/toast/ToastHost.svelte +21 -0
  118. package/dist/components/toast/ToastHost.svelte.d.ts +3 -0
  119. package/dist/components/toast/ToastItem.svelte +287 -0
  120. package/dist/components/toast/ToastItem.svelte.d.ts +9 -0
  121. package/dist/index.d.ts +59 -0
  122. package/dist/index.js +67 -0
  123. package/dist/showcase/AnimatedBeam.svelte +183 -0
  124. package/dist/showcase/AnimatedBeam.svelte.d.ts +26 -0
  125. package/dist/showcase/AuroraDrift.svelte +74 -0
  126. package/dist/showcase/AuroraDrift.svelte.d.ts +9 -0
  127. package/dist/showcase/BentoCard.svelte +50 -0
  128. package/dist/showcase/BentoCard.svelte.d.ts +14 -0
  129. package/dist/showcase/BentoGrid.svelte +43 -0
  130. package/dist/showcase/BentoGrid.svelte.d.ts +12 -0
  131. package/dist/showcase/BorderBeam.svelte +79 -0
  132. package/dist/showcase/BorderBeam.svelte.d.ts +12 -0
  133. package/dist/showcase/ClipWipe.svelte +82 -0
  134. package/dist/showcase/ClipWipe.svelte.d.ts +12 -0
  135. package/dist/showcase/Confetti.svelte +71 -0
  136. package/dist/showcase/Confetti.svelte.d.ts +10 -0
  137. package/dist/showcase/CursorSpotlight.svelte +85 -0
  138. package/dist/showcase/CursorSpotlight.svelte.d.ts +9 -0
  139. package/dist/showcase/DeviceMock.svelte +186 -0
  140. package/dist/showcase/DeviceMock.svelte.d.ts +11 -0
  141. package/dist/showcase/Dock.svelte +123 -0
  142. package/dist/showcase/Dock.svelte.d.ts +17 -0
  143. package/dist/showcase/FlipCard.svelte +103 -0
  144. package/dist/showcase/FlipCard.svelte.d.ts +10 -0
  145. package/dist/showcase/FocusReveal.svelte +83 -0
  146. package/dist/showcase/FocusReveal.svelte.d.ts +11 -0
  147. package/dist/showcase/Globe.svelte +202 -0
  148. package/dist/showcase/Globe.svelte.d.ts +16 -0
  149. package/dist/showcase/KenBurns.svelte +105 -0
  150. package/dist/showcase/KenBurns.svelte.d.ts +13 -0
  151. package/dist/showcase/Marquee.svelte +89 -0
  152. package/dist/showcase/Marquee.svelte.d.ts +9 -0
  153. package/dist/showcase/ParallaxTilt.svelte +98 -0
  154. package/dist/showcase/ParallaxTilt.svelte.d.ts +10 -0
  155. package/dist/showcase/ScrambleText.svelte +98 -0
  156. package/dist/showcase/ScrambleText.svelte.d.ts +11 -0
  157. package/dist/showcase/ShineSweep.svelte +81 -0
  158. package/dist/showcase/ShineSweep.svelte.d.ts +9 -0
  159. package/dist/showcase/Terminal.svelte +230 -0
  160. package/dist/showcase/Terminal.svelte.d.ts +18 -0
  161. package/dist/showcase/TextSplitReveal.svelte +146 -0
  162. package/dist/showcase/TextSplitReveal.svelte.d.ts +13 -0
  163. package/dist/showcase/TextWave.svelte +55 -0
  164. package/dist/showcase/TextWave.svelte.d.ts +8 -0
  165. package/dist/showcase/TypewriterText.svelte +130 -0
  166. package/dist/showcase/TypewriterText.svelte.d.ts +9 -0
  167. package/dist/showcase/backdrop/GrainGradient.svelte +126 -0
  168. package/dist/showcase/backdrop/GrainGradient.svelte.d.ts +23 -0
  169. package/dist/showcase/backdrop/MeshGradient.svelte +104 -0
  170. package/dist/showcase/backdrop/MeshGradient.svelte.d.ts +20 -0
  171. package/dist/showcase/backdrop/Metaballs.svelte +116 -0
  172. package/dist/showcase/backdrop/Metaballs.svelte.d.ts +18 -0
  173. package/dist/showcase/backdrop/NeuroNoise.svelte +115 -0
  174. package/dist/showcase/backdrop/NeuroNoise.svelte.d.ts +20 -0
  175. package/dist/showcase/backdrop/ShowcaseBackdrop.svelte +48 -0
  176. package/dist/showcase/backdrop/ShowcaseBackdrop.svelte.d.ts +12 -0
  177. package/dist/showcase/generative/GenerativeBackdrop.svelte +234 -0
  178. package/dist/showcase/generative/GenerativeBackdrop.svelte.d.ts +9 -0
  179. package/dist/showcase/generative/intent.d.ts +7 -0
  180. package/dist/showcase/generative/intent.js +67 -0
  181. package/dist/showcase/generative/manifest.d.ts +9 -0
  182. package/dist/showcase/generative/manifest.js +97 -0
  183. package/dist/showcase/generative/types.d.ts +48 -0
  184. package/dist/showcase/generative/types.js +8 -0
  185. package/dist/showcase/index.d.ts +36 -0
  186. package/dist/showcase/index.js +46 -0
  187. package/dist/showcase/scroll/SmoothScroll.svelte +49 -0
  188. package/dist/showcase/scroll/SmoothScroll.svelte.d.ts +12 -0
  189. package/dist/showcase/scroll/scrollProgress.d.ts +24 -0
  190. package/dist/showcase/scroll/scrollProgress.js +65 -0
  191. package/dist/showcase/scroll/scrollReveal.d.ts +30 -0
  192. package/dist/showcase/scroll/scrollReveal.js +70 -0
  193. package/dist/stores/commandPalette.svelte.d.ts +24 -0
  194. package/dist/stores/commandPalette.svelte.js +82 -0
  195. package/dist/stores/toast.svelte.d.ts +28 -0
  196. package/dist/stores/toast.svelte.js +33 -0
  197. package/dist/styles/motion.css +46 -0
  198. package/dist/styles/tokens.css +31 -0
  199. package/dist/transitions/glide.d.ts +31 -0
  200. package/dist/transitions/glide.js +58 -0
  201. package/dist/utils/sound.d.ts +6 -0
  202. package/dist/utils/sound.js +113 -0
  203. package/dist/utils/splitText.d.ts +25 -0
  204. package/dist/utils/splitText.js +94 -0
  205. package/dist/utils/themeWipe.d.ts +21 -0
  206. package/dist/utils/themeWipe.js +94 -0
  207. package/dist/utils/viewTransition.d.ts +23 -0
  208. package/dist/utils/viewTransition.js +75 -0
  209. package/package.json +50 -3
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Sidebar context state — createSidebarState returns a reactive object
3
+ * driven by Svelte 5 runes. Pass it into Sidebar via setContext/getContext
4
+ * or prop drilling.
5
+ *
6
+ * Persistence: localStorage (fallback to cookie via document.cookie) keyed
7
+ * on `storageKey`. Set storageKey = '' to disable persistence.
8
+ */
9
+ export type SidebarMode = 'expanded' | 'collapsed' | 'icon';
10
+ export interface SidebarState {
11
+ /** Current sidebar display mode */
12
+ mode: SidebarMode;
13
+ /** ID of the currently active nav item */
14
+ activeId: string;
15
+ /** Whether the mobile drawer overlay is open */
16
+ mobileOpen: boolean;
17
+ /** Set the display mode (persisted) */
18
+ setMode(mode: SidebarMode): void;
19
+ /** Toggle between expanded and icon-collapse */
20
+ toggleCollapse(): void;
21
+ /** Set the active item ID */
22
+ setActive(id: string): void;
23
+ /** Open/close the mobile drawer */
24
+ setMobileOpen(open: boolean): void;
25
+ }
26
+ export declare function createSidebarState(options?: {
27
+ storageKey?: string;
28
+ defaultMode?: SidebarMode;
29
+ defaultActiveId?: string;
30
+ }): SidebarState;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Sidebar context state — createSidebarState returns a reactive object
3
+ * driven by Svelte 5 runes. Pass it into Sidebar via setContext/getContext
4
+ * or prop drilling.
5
+ *
6
+ * Persistence: localStorage (fallback to cookie via document.cookie) keyed
7
+ * on `storageKey`. Set storageKey = '' to disable persistence.
8
+ */
9
+ function readStorage(key) {
10
+ if (!key || typeof window === 'undefined')
11
+ return null;
12
+ try {
13
+ return localStorage.getItem(key);
14
+ }
15
+ catch (_a) {
16
+ return null;
17
+ }
18
+ }
19
+ function writeStorage(key, value) {
20
+ if (!key || typeof window === 'undefined')
21
+ return;
22
+ try {
23
+ localStorage.setItem(key, value);
24
+ }
25
+ catch (_a) {
26
+ // silently fail if storage unavailable
27
+ }
28
+ }
29
+ export function createSidebarState(options) {
30
+ var _a, _b, _c;
31
+ var storageKey = (_a = options === null || options === void 0 ? void 0 : options.storageKey) !== null && _a !== void 0 ? _a : 'jatui-sidebar';
32
+ var defaultMode = (_b = options === null || options === void 0 ? void 0 : options.defaultMode) !== null && _b !== void 0 ? _b : 'expanded';
33
+ var storedMode = readStorage(storageKey);
34
+ var validModes = ['expanded', 'collapsed', 'icon'];
35
+ var initialMode = storedMode && validModes.includes(storedMode) ? storedMode : defaultMode;
36
+ var mode = $state(initialMode);
37
+ var activeId = $state((_c = options === null || options === void 0 ? void 0 : options.defaultActiveId) !== null && _c !== void 0 ? _c : '');
38
+ var mobileOpen = $state(false);
39
+ return {
40
+ get mode() {
41
+ return mode;
42
+ },
43
+ get activeId() {
44
+ return activeId;
45
+ },
46
+ get mobileOpen() {
47
+ return mobileOpen;
48
+ },
49
+ setMode: function (m) {
50
+ mode = m;
51
+ writeStorage(storageKey, m);
52
+ },
53
+ toggleCollapse: function () {
54
+ var next = mode === 'expanded' ? 'icon' : 'expanded';
55
+ mode = next;
56
+ writeStorage(storageKey, next);
57
+ },
58
+ setActive: function (id) {
59
+ activeId = id;
60
+ },
61
+ setMobileOpen: function (open) {
62
+ mobileOpen = open;
63
+ }
64
+ };
65
+ }
@@ -0,0 +1,364 @@
1
+ <script lang="ts">
2
+ import {
3
+ createTable,
4
+ getCoreRowModel,
5
+ getSortedRowModel,
6
+ getPaginationRowModel,
7
+ type ColumnDef,
8
+ type SortingState,
9
+ type RowSelectionState,
10
+ type PaginationState,
11
+ type TableOptionsResolved,
12
+ } from '@tanstack/table-core';
13
+ import { flexRender } from './flexRender.js';
14
+ import type { DataTableProps } from './types.js';
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ type AnyData = any;
18
+
19
+ let {
20
+ data,
21
+ columns,
22
+ selectable = false,
23
+ paginated = false,
24
+ pageSize = 10,
25
+ sortable = false,
26
+ loading = false,
27
+ loadingRows = 5,
28
+ onSelectionChange,
29
+ class: className = '',
30
+ }: DataTableProps = $props();
31
+
32
+ // ── State ──────────────────────────────────────────────────────────────
33
+ let sorting = $state<SortingState>([]);
34
+ let rowSelection = $state<RowSelectionState>({});
35
+ let pagination = $state<PaginationState>({ pageIndex: 0, pageSize });
36
+
37
+ $effect(() => {
38
+ void data;
39
+ pagination = { pageIndex: 0, pageSize: pagination.pageSize };
40
+ });
41
+
42
+ const checkboxCol: ColumnDef<AnyData, unknown> = {
43
+ id: '__select',
44
+ header: () => null,
45
+ cell: () => null,
46
+ enableSorting: false,
47
+ size: 40,
48
+ };
49
+
50
+ const allColumns = $derived<ColumnDef<AnyData, unknown>[]>(
51
+ selectable ? [checkboxCol, ...(columns as ColumnDef<AnyData, unknown>[])] : (columns as ColumnDef<AnyData, unknown>[])
52
+ );
53
+
54
+ // ── Table instance ─────────────────────────────────────────────────────
55
+ const table = $derived.by(() => {
56
+ const opts: TableOptionsResolved<AnyData> = {
57
+ data,
58
+ columns: allColumns,
59
+ state: {
60
+ sorting,
61
+ rowSelection,
62
+ ...(paginated ? { pagination } : {}),
63
+ },
64
+ enableRowSelection: selectable,
65
+ enableSorting: sortable,
66
+ onSortingChange: (updater) => {
67
+ sorting = typeof updater === 'function' ? updater(sorting) : updater;
68
+ },
69
+ onRowSelectionChange: (updater) => {
70
+ rowSelection = typeof updater === 'function' ? updater(rowSelection) : updater;
71
+ },
72
+ onPaginationChange: paginated
73
+ ? (updater) => {
74
+ pagination = typeof updater === 'function' ? updater(pagination) : updater;
75
+ }
76
+ : () => {},
77
+ onStateChange: () => {},
78
+ getCoreRowModel: getCoreRowModel(),
79
+ getSortedRowModel: sortable ? getSortedRowModel() : undefined,
80
+ getPaginationRowModel: paginated ? getPaginationRowModel() : undefined,
81
+ renderFallbackValue: '',
82
+ };
83
+ return createTable(opts);
84
+ });
85
+
86
+ const headerGroups = $derived(table.getHeaderGroups());
87
+ const rows = $derived(table.getRowModel().rows);
88
+ const pageCount = $derived(table.getPageCount());
89
+ const canPrevPage = $derived(table.getCanPreviousPage());
90
+ const canNextPage = $derived(table.getCanNextPage());
91
+
92
+ $effect(() => {
93
+ if (!selectable || !onSelectionChange) return;
94
+ const selected = table.getSelectedRowModel().rows.map((r: AnyData) => r.original);
95
+ onSelectionChange(selected);
96
+ });
97
+
98
+ function sortDir(headerId: string): 'asc' | 'desc' | false {
99
+ const s = sorting.find((item) => item.id === headerId);
100
+ return s ? (s.desc ? 'desc' : 'asc') : false;
101
+ }
102
+
103
+ function renderHeader(header: ReturnType<typeof table.getHeaderGroups>[0]['headers'][0]) {
104
+ return flexRender(header.column.columnDef.header, header.getContext());
105
+ }
106
+
107
+ function renderCell(cell: ReturnType<ReturnType<typeof table.getRowModel>['rows'][0]['getVisibleCells']>[0]) {
108
+ return flexRender(cell.column.columnDef.cell, cell.getContext());
109
+ }
110
+ </script>
111
+
112
+ <div class="datatable-root {className}">
113
+ {#if loading}
114
+ <div class="overflow-x-auto">
115
+ <table class="table table-zebra w-full">
116
+ <thead>
117
+ <tr>
118
+ {#each allColumns as _}
119
+ <th><div class="skel-cell"></div></th>
120
+ {/each}
121
+ </tr>
122
+ </thead>
123
+ <tbody>
124
+ {#each { length: loadingRows } as _}
125
+ <tr>
126
+ {#each allColumns as _, ci}
127
+ <td>
128
+ <div class="skel-cell" style:width={ci === 0 && selectable ? '1.25rem' : '80%'}></div>
129
+ </td>
130
+ {/each}
131
+ </tr>
132
+ {/each}
133
+ </tbody>
134
+ </table>
135
+ </div>
136
+ {:else}
137
+ <div class="overflow-x-auto">
138
+ <table class="table table-zebra w-full">
139
+ <thead>
140
+ {#each headerGroups as headerGroup}
141
+ <tr>
142
+ {#each headerGroup.headers as header}
143
+ {#if header.column.id === '__select'}
144
+ <th class="dt-select-cell">
145
+ <input
146
+ type="checkbox"
147
+ class="checkbox checkbox-sm"
148
+ checked={table.getIsAllRowsSelected()}
149
+ indeterminate={table.getIsSomeRowsSelected()}
150
+ aria-label="Select all rows"
151
+ onchange={() => table.toggleAllRowsSelected()}
152
+ />
153
+ </th>
154
+ {:else}
155
+ {@const isSortable = sortable && header.column.getCanSort()}
156
+ {@const dir = sortDir(header.column.id)}
157
+ {@const rendered = renderHeader(header)}
158
+ <th
159
+ style:width={header.getSize() !== 150 ? `${header.getSize()}px` : undefined}
160
+ class:dt-th-sortable={isSortable}
161
+ onclick={isSortable ? () => header.column.toggleSorting() : undefined}
162
+ aria-sort={dir === 'asc' ? 'ascending' : dir === 'desc' ? 'descending' : undefined}
163
+ >
164
+ <span class="dt-th-label">
165
+ {#if rendered.type === 'snippet'}
166
+ {@render rendered.snippet(rendered.props)}
167
+ {:else}
168
+ {rendered.value}
169
+ {/if}
170
+ </span>
171
+ {#if isSortable}
172
+ <span class="dt-sort-icon" class:dt-sort-active={dir !== false} aria-hidden="true">
173
+ {#if dir === 'asc'}
174
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M6 2L10 8H2L6 2Z" fill="currentColor"/></svg>
175
+ {:else if dir === 'desc'}
176
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M6 10L2 4H10L6 10Z" fill="currentColor"/></svg>
177
+ {:else}
178
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
179
+ <path d="M6 2L9 6H3L6 2Z" fill="currentColor" opacity="0.35"/>
180
+ <path d="M6 10L3 6H9L6 10Z" fill="currentColor" opacity="0.35"/>
181
+ </svg>
182
+ {/if}
183
+ </span>
184
+ {/if}
185
+ </th>
186
+ {/if}
187
+ {/each}
188
+ </tr>
189
+ {/each}
190
+ </thead>
191
+
192
+ <tbody>
193
+ {#if rows.length === 0}
194
+ <tr>
195
+ <td colspan={allColumns.length} class="dt-empty">No data</td>
196
+ </tr>
197
+ {:else}
198
+ {#each rows as row}
199
+ <tr class:dt-row-selected={row.getIsSelected()}>
200
+ {#each row.getVisibleCells() as cell}
201
+ {#if cell.column.id === '__select'}
202
+ <td class="dt-select-cell">
203
+ <input
204
+ type="checkbox"
205
+ class="checkbox checkbox-sm"
206
+ checked={row.getIsSelected()}
207
+ disabled={!row.getCanSelect()}
208
+ aria-label="Select row"
209
+ onchange={() => row.toggleSelected()}
210
+ />
211
+ </td>
212
+ {:else}
213
+ {@const rendered = renderCell(cell)}
214
+ <td>
215
+ {#if rendered.type === 'snippet'}
216
+ {@render rendered.snippet(rendered.props)}
217
+ {:else}
218
+ {rendered.value}
219
+ {/if}
220
+ </td>
221
+ {/if}
222
+ {/each}
223
+ </tr>
224
+ {/each}
225
+ {/if}
226
+ </tbody>
227
+ </table>
228
+ </div>
229
+
230
+ {#if paginated && pageCount > 1}
231
+ <div class="dt-pagination">
232
+ <span class="dt-page-info">
233
+ Page {pagination.pageIndex + 1} of {pageCount}
234
+ </span>
235
+ <div class="dt-page-btns">
236
+ <button
237
+ type="button"
238
+ class="btn btn-sm btn-ghost"
239
+ disabled={!canPrevPage}
240
+ onclick={() => table.setPageIndex(0)}
241
+ aria-label="First page"
242
+ >«</button>
243
+ <button
244
+ type="button"
245
+ class="btn btn-sm btn-ghost"
246
+ disabled={!canPrevPage}
247
+ onclick={() => table.previousPage()}
248
+ aria-label="Previous page"
249
+ >‹</button>
250
+ <button
251
+ type="button"
252
+ class="btn btn-sm btn-ghost"
253
+ disabled={!canNextPage}
254
+ onclick={() => table.nextPage()}
255
+ aria-label="Next page"
256
+ >›</button>
257
+ <button
258
+ type="button"
259
+ class="btn btn-sm btn-ghost"
260
+ disabled={!canNextPage}
261
+ onclick={() => table.setPageIndex(pageCount - 1)}
262
+ aria-label="Last page"
263
+ >»</button>
264
+ </div>
265
+ </div>
266
+ {/if}
267
+ {/if}
268
+ </div>
269
+
270
+ <style>
271
+ .datatable-root {
272
+ width: 100%;
273
+ }
274
+
275
+ .dt-th-sortable {
276
+ cursor: pointer;
277
+ user-select: none;
278
+ }
279
+ .dt-th-sortable:hover {
280
+ background-color: oklch(var(--b2) / 0.6);
281
+ }
282
+
283
+ .dt-th-label {
284
+ display: inline-flex;
285
+ align-items: center;
286
+ gap: var(--jatui-space-sm);
287
+ }
288
+
289
+ .dt-sort-icon {
290
+ display: inline-flex;
291
+ align-items: center;
292
+ margin-left: var(--jatui-space-xs);
293
+ color: oklch(var(--bc) / 0.35);
294
+ transition: color var(--motion-fast) var(--motion-glide),
295
+ transform var(--motion-fast) var(--motion-glide);
296
+ }
297
+
298
+ .dt-sort-active {
299
+ color: oklch(var(--p) / 0.9);
300
+ }
301
+
302
+ @media (prefers-reduced-motion: reduce) {
303
+ .dt-sort-icon { transition: none; }
304
+ }
305
+
306
+ .dt-row-selected {
307
+ background-color: oklch(var(--p) / 0.06) !important;
308
+ }
309
+
310
+ .dt-select-cell {
311
+ width: 2.5rem;
312
+ text-align: center;
313
+ vertical-align: middle;
314
+ }
315
+
316
+ .dt-empty {
317
+ text-align: center;
318
+ color: oklch(var(--bc) / 0.35);
319
+ padding: 2rem 1rem;
320
+ font-size: 0.875rem;
321
+ }
322
+
323
+ .dt-pagination {
324
+ display: flex;
325
+ align-items: center;
326
+ justify-content: space-between;
327
+ padding: var(--jatui-space-base) var(--jatui-space-xs);
328
+ border-top: var(--jatui-border-w) solid oklch(var(--b3) / 1);
329
+ margin-top: var(--jatui-space-base);
330
+ }
331
+
332
+ .dt-page-info {
333
+ font-size: 0.8125rem;
334
+ color: oklch(var(--bc) / 0.5);
335
+ }
336
+
337
+ .dt-page-btns {
338
+ display: flex;
339
+ gap: var(--jatui-space-xs);
340
+ }
341
+
342
+ .skel-cell {
343
+ height: 0.875rem;
344
+ width: 80%;
345
+ border-radius: var(--jatui-radius-selector);
346
+ background: linear-gradient(
347
+ 90deg,
348
+ oklch(var(--b2) / 1) 0%,
349
+ oklch(var(--b3) / 1) 25%,
350
+ oklch(var(--b2) / 1) 50%
351
+ );
352
+ background-size: 280% 100%;
353
+ animation: skel-shimmer 1.5s linear infinite;
354
+ }
355
+
356
+ @keyframes skel-shimmer {
357
+ 0% { background-position: 140% 0; }
358
+ 100% { background-position: -140% 0; }
359
+ }
360
+
361
+ @media (prefers-reduced-motion: reduce) {
362
+ .skel-cell { animation: none; }
363
+ }
364
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { DataTableProps } from './types.js';
2
+ declare const DataTable: import("svelte").Component<DataTableProps<any>, {}, "">;
3
+ type DataTable = ReturnType<typeof DataTable>;
4
+ export default DataTable;
@@ -0,0 +1,31 @@
1
+ import type { Snippet } from 'svelte';
2
+ /**
3
+ * Determines if a value is a Svelte snippet (function with _isSnippet marker
4
+ * or just a callable function — Svelte 5 snippets are tagged functions).
5
+ */
6
+ export declare function isSnippet(value: unknown): value is Snippet;
7
+ /**
8
+ * Cell render descriptor — returned from accessorFn / header / cell column
9
+ * definition fields. Can be a plain value, a Svelte snippet, or null/undefined.
10
+ */
11
+ export type FlexRenderResult = {
12
+ type: 'snippet';
13
+ snippet: Snippet<[unknown]>;
14
+ props: unknown;
15
+ } | {
16
+ type: 'value';
17
+ value: unknown;
18
+ };
19
+ /**
20
+ * Resolve a TanStack column `cell` or `header` definition to a renderable
21
+ * descriptor for use in Svelte templates.
22
+ *
23
+ * Usage in a .svelte template:
24
+ * {@const cell = flexRender(column.columnDef.cell, cellCtx)}
25
+ * {#if cell.type === 'snippet'}
26
+ * {@render cell.snippet(cell.props)}
27
+ * {:else}
28
+ * {cell.value}
29
+ * {/if}
30
+ */
31
+ export declare function flexRender<TProps>(component: ((ctx: TProps) => unknown) | string | null | undefined, props: TProps): FlexRenderResult;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Determines if a value is a Svelte snippet (function with _isSnippet marker
3
+ * or just a callable function — Svelte 5 snippets are tagged functions).
4
+ */
5
+ export function isSnippet(value) {
6
+ return typeof value === 'function';
7
+ }
8
+ /**
9
+ * Resolve a TanStack column `cell` or `header` definition to a renderable
10
+ * descriptor for use in Svelte templates.
11
+ *
12
+ * Usage in a .svelte template:
13
+ * {@const cell = flexRender(column.columnDef.cell, cellCtx)}
14
+ * {#if cell.type === 'snippet'}
15
+ * {@render cell.snippet(cell.props)}
16
+ * {:else}
17
+ * {cell.value}
18
+ * {/if}
19
+ */
20
+ export function flexRender(component, props) {
21
+ if (component == null) {
22
+ return { type: 'value', value: '' };
23
+ }
24
+ if (typeof component === 'string') {
25
+ return { type: 'value', value: component };
26
+ }
27
+ var result = component(props);
28
+ if (isSnippet(result)) {
29
+ return { type: 'snippet', snippet: result, props: props };
30
+ }
31
+ return { type: 'value', value: result };
32
+ }
@@ -0,0 +1,28 @@
1
+ import type { ColumnDef, Row } from '@tanstack/table-core';
2
+ export type { ColumnDef, Row };
3
+ export interface DataTableProps<TData = any> {
4
+ /** Row data array */
5
+ data: TData[];
6
+ /** TanStack column definitions */
7
+ columns: ColumnDef<TData, unknown>[];
8
+ /** Show a checkbox column for row selection */
9
+ selectable?: boolean;
10
+ /** Enable client-side pagination */
11
+ paginated?: boolean;
12
+ /** Rows per page (default 10) */
13
+ pageSize?: number;
14
+ /** Enable column sorting */
15
+ sortable?: boolean;
16
+ /** Show shimmer skeleton rows while loading */
17
+ loading?: boolean;
18
+ /** Number of skeleton rows to show while loading (default 5) */
19
+ loadingRows?: number;
20
+ /** Emitted when the selection set changes */
21
+ onSelectionChange?: (rows: TData[]) => void;
22
+ /** Additional table class */
23
+ class?: string;
24
+ }
25
+ export interface SelectionEvent<TData> {
26
+ rows: TData[];
27
+ ids: string[];
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import { getToasts } from '../../stores/toast.svelte.js';
3
+ import ToastItem from './ToastItem.svelte';
4
+
5
+ const toasts = $derived(getToasts());
6
+ </script>
7
+
8
+ <!--
9
+ Mount once in your app root (e.g. +layout.svelte).
10
+ Fixed bottom-right, pointer-events only on the toast list.
11
+ -->
12
+ <div
13
+ aria-label="Notifications"
14
+ class="toast-host pointer-events-none fixed right-4 bottom-4 z-[9999] flex flex-col-reverse items-end gap-2 w-80 max-w-[calc(100vw-2rem)]"
15
+ >
16
+ <ul class="contents">
17
+ {#each toasts as toast, i (toast.id)}
18
+ <ToastItem {toast} index={i} total={toasts.length} />
19
+ {/each}
20
+ </ul>
21
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const ToastHost: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type ToastHost = ReturnType<typeof ToastHost>;
3
+ export default ToastHost;