@makolabs/ripple 2.5.8 → 3.0.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.
- package/README.md +403 -497
- package/dist/adapters/storage/S3Adapter.d.ts +49 -1
- package/dist/adapters/storage/S3Adapter.js +38 -1
- package/dist/adapters/storage/types.d.ts +20 -0
- package/dist/ai/AIChatInterface.svelte +2 -1
- package/dist/ai/AIChatInterface.svelte.d.ts +2 -1
- package/dist/ai/CodeRenderer.svelte +7 -2
- package/dist/ai/CodeRenderer.svelte.d.ts +2 -1
- package/dist/ai/ComposeDropdown.svelte +1 -1
- package/dist/ai/MessageBox.svelte +3 -3
- package/dist/ai/MessageBox.svelte.d.ts +3 -2
- package/dist/ai/ThinkingDisplay.svelte +4 -3
- package/dist/ai/ThinkingDisplay.svelte.d.ts +2 -1
- package/dist/ai/ai-types.d.ts +55 -1
- package/dist/button/Button.svelte +5 -5
- package/dist/button/button-types.d.ts +49 -4
- package/dist/button/button.d.ts +9 -9
- package/dist/button/button.js +6 -6
- package/dist/charts/Chart.svelte +8 -16
- package/dist/charts/chart-types.d.ts +78 -1
- package/dist/drawer/Drawer.svelte +6 -26
- package/dist/drawer/drawer-types.d.ts +33 -12
- package/dist/drawer/drawer.d.ts +3 -3
- package/dist/drawer/drawer.js +1 -1
- package/dist/elements/accordion/Accordion.svelte +6 -17
- package/dist/elements/accordion/accordion-types.d.ts +53 -6
- package/dist/elements/alert/Alert.svelte +3 -0
- package/dist/elements/badge/Badge.svelte +1 -1
- package/dist/elements/badge/badge-types.d.ts +22 -0
- package/dist/elements/badge/badge.d.ts +3 -3
- package/dist/elements/badge/badge.js +1 -1
- package/dist/elements/combobox/ComboBox.svelte +247 -0
- package/dist/elements/combobox/ComboBox.svelte.d.ts +4 -0
- package/dist/elements/combobox/combobox-types.d.ts +41 -0
- package/dist/elements/combobox/combobox-types.js +1 -0
- package/dist/elements/context-menu/ContextMenu.svelte +137 -0
- package/dist/elements/context-menu/ContextMenu.svelte.d.ts +4 -0
- package/dist/elements/context-menu/context-menu-types.d.ts +40 -0
- package/dist/elements/context-menu/context-menu-types.js +1 -0
- package/dist/elements/dropdown/Dropdown.svelte +1 -1
- package/dist/elements/dropdown/Select.svelte +4 -1
- package/dist/elements/dropdown/dropdown-types.d.ts +114 -0
- package/dist/elements/dropdown/dropdown.d.ts +3 -3
- package/dist/elements/dropdown/dropdown.js +2 -2
- package/dist/elements/dropdown/select.d.ts +3 -3
- package/dist/elements/dropdown/select.js +2 -2
- package/dist/elements/empty-state/EmptyState.svelte +1 -1
- package/dist/elements/empty-state/empty-state-types.d.ts +32 -1
- package/dist/elements/empty-state/empty-state.d.ts +3 -3
- package/dist/elements/empty-state/empty-state.js +2 -2
- package/dist/elements/file-upload/FileUpload.svelte +5 -0
- package/dist/elements/file-upload/file-upload-types.d.ts +59 -0
- package/dist/elements/pagination/Pagination.svelte +53 -21
- package/dist/elements/pagination/Pagination.svelte.d.ts +33 -5
- package/dist/elements/popover/Popover.svelte +234 -0
- package/dist/elements/popover/Popover.svelte.d.ts +4 -0
- package/dist/elements/popover/index.d.ts +2 -0
- package/dist/elements/popover/index.js +1 -0
- package/dist/elements/popover/popover-types.d.ts +60 -0
- package/dist/elements/popover/popover-types.js +1 -0
- package/dist/elements/progress/Progress.svelte +32 -7
- package/dist/elements/progress/progress-types.d.ts +48 -1
- package/dist/elements/skeleton/Skeleton.svelte +56 -0
- package/dist/elements/skeleton/Skeleton.svelte.d.ts +4 -0
- package/dist/elements/skeleton/index.d.ts +2 -0
- package/dist/elements/skeleton/index.js +1 -0
- package/dist/elements/skeleton/skeleton-types.d.ts +50 -0
- package/dist/elements/skeleton/skeleton-types.js +1 -0
- package/dist/elements/spinner/Spinner.svelte +1 -1
- package/dist/elements/spinner/spinner-types.d.ts +20 -0
- package/dist/elements/spinner/spinner.d.ts +3 -3
- package/dist/elements/spinner/spinner.js +2 -2
- package/dist/elements/tooltip/Tooltip.svelte +108 -11
- package/dist/elements/tooltip/tooltip-types.d.ts +49 -1
- package/dist/file-browser/FileBrowser.svelte +21 -12
- package/dist/filters/CompactFilters.svelte +221 -33
- package/dist/filters/CompactFilters.svelte.d.ts +1 -1
- package/dist/filters/FilterBar.svelte +184 -0
- package/dist/filters/FilterBar.svelte.d.ts +4 -0
- package/dist/filters/FilterPopover.svelte +346 -0
- package/dist/filters/FilterPopover.svelte.d.ts +4 -0
- package/dist/filters/date-presets.d.ts +15 -0
- package/dist/filters/date-presets.js +107 -0
- package/dist/filters/filter-types.d.ts +69 -3
- package/dist/filters/index.d.ts +5 -0
- package/dist/filters/index.js +4 -0
- package/dist/filters/sync-filters-to-url.svelte.d.ts +37 -0
- package/dist/filters/sync-filters-to-url.svelte.js +114 -0
- package/dist/forms/DateRange.svelte +4 -2
- package/dist/forms/Input.svelte +2 -2
- package/dist/forms/MarketSelector.svelte +8 -3
- package/dist/forms/NumberInput.svelte +4 -4
- package/dist/forms/RadioGroup.svelte +123 -0
- package/dist/forms/RadioGroup.svelte.d.ts +4 -0
- package/dist/forms/SegmentedControl.svelte +11 -4
- package/dist/forms/Slider.svelte +72 -3
- package/dist/forms/Tags.svelte +14 -5
- package/dist/forms/Textarea.svelte +126 -0
- package/dist/forms/Textarea.svelte.d.ts +4 -0
- package/dist/forms/Toggle.svelte +8 -8
- package/dist/forms/calendar/Calendar.svelte +218 -0
- package/dist/forms/calendar/Calendar.svelte.d.ts +4 -0
- package/dist/forms/calendar/calendar-types.d.ts +46 -0
- package/dist/forms/calendar/calendar-types.js +1 -0
- package/dist/forms/calendar/index.d.ts +2 -0
- package/dist/forms/calendar/index.js +1 -0
- package/dist/forms/date-picker/DatePicker.svelte +144 -0
- package/dist/forms/date-picker/DatePicker.svelte.d.ts +4 -0
- package/dist/forms/date-picker/date-picker-types.d.ts +29 -0
- package/dist/forms/date-picker/date-picker-types.js +1 -0
- package/dist/forms/form-types.d.ts +425 -6
- package/dist/forms/market/market-selector-types.d.ts +52 -1
- package/dist/forms/segmented-control.d.ts +5 -2
- package/dist/forms/segmented-control.js +16 -5
- package/dist/forms/slider.d.ts +3 -3
- package/dist/forms/slider.js +2 -2
- package/dist/funcs/user-management.remote.d.ts +1 -1
- package/dist/funcs/user-management.remote.js +2 -2
- package/dist/header/Breadcrumbs.svelte +4 -20
- package/dist/header/PageHeader.svelte +6 -14
- package/dist/header/breadcrumbs.d.ts +3 -11
- package/dist/header/breadcrumbs.js +10 -5
- package/dist/header/header-types.d.ts +62 -11
- package/dist/index.d.ts +35 -9
- package/dist/index.js +24 -4
- package/dist/layout/activity-list/ActivityList.svelte +13 -7
- package/dist/layout/activity-list/activity-list-types.d.ts +46 -7
- package/dist/layout/card/Card.svelte +12 -15
- package/dist/layout/card/MetricCard.svelte +50 -32
- package/dist/layout/card/card-types.d.ts +114 -4
- package/dist/layout/navbar/navbar-types.d.ts +48 -0
- package/dist/layout/navbar/navbar.d.ts +3 -3
- package/dist/layout/navbar/navbar.js +2 -2
- package/dist/layout/sidebar/Sidebar.svelte +87 -11
- package/dist/layout/sidebar/sidebar-types.d.ts +60 -1
- package/dist/layout/stepper/Stepper.svelte +288 -0
- package/dist/layout/stepper/Stepper.svelte.d.ts +4 -0
- package/dist/layout/stepper/stepper-types.d.ts +80 -0
- package/dist/layout/stepper/stepper-types.js +1 -0
- package/dist/layout/table/Table.svelte +91 -85
- package/dist/layout/table/table-types.d.ts +148 -24
- package/dist/layout/table/table.d.ts +3 -3
- package/dist/layout/table/table.js +2 -2
- package/dist/layout/tabs/Tab.svelte +6 -2
- package/dist/layout/tabs/Tab.svelte.d.ts +4 -1
- package/dist/layout/tabs/TabGroup.svelte +9 -2
- package/dist/layout/tabs/tabs-types.d.ts +63 -0
- package/dist/layout/tabs/tabs.d.ts +3 -3
- package/dist/layout/tabs/tabs.js +12 -6
- package/dist/modal/ConfirmDialog.svelte +65 -0
- package/dist/modal/ConfirmDialog.svelte.d.ts +4 -0
- package/dist/modal/Modal.svelte +6 -26
- package/dist/modal/confirm-dialog-types.d.ts +39 -0
- package/dist/modal/confirm-dialog-types.js +1 -0
- package/dist/modal/modal-types.d.ts +51 -12
- package/dist/modal/modal.d.ts +3 -3
- package/dist/modal/modal.js +3 -3
- package/dist/pipeline/Pipeline.svelte +8 -3
- package/dist/pipeline/pipeline-types.d.ts +55 -3
- package/dist/pipeline/pipeline.d.ts +18 -3
- package/dist/pipeline/pipeline.js +7 -2
- package/dist/server/s3.d.ts +35 -3
- package/dist/sonner/Toaster.svelte +29 -0
- package/dist/sonner/Toaster.svelte.d.ts +4 -0
- package/dist/sonner/index.d.ts +21 -0
- package/dist/sonner/index.js +20 -0
- package/dist/user-management/UserManagement.svelte +22 -16
- package/dist/user-management/UserModal.svelte +10 -7
- package/dist/user-management/UserTable.svelte +16 -17
- package/dist/user-management/UserViewModal.svelte +11 -11
- package/dist/user-management/user-management-types.d.ts +118 -31
- package/dist/variants.d.ts +1 -1
- package/dist/variants.js +1 -1
- package/package.json +7 -4
- package/dist/config/ai.d.ts +0 -13
- package/dist/config/ai.js +0 -44
- package/dist/elements/empty-state/EmptyStateTestWrapper.svelte +0 -25
- package/dist/elements/empty-state/EmptyStateTestWrapper.svelte.d.ts +0 -8
- package/dist/elements/tooltip/TooltipTestWrapper.svelte +0 -14
- package/dist/elements/tooltip/TooltipTestWrapper.svelte.d.ts +0 -7
- package/dist/helper/deprecation.d.ts +0 -14
- package/dist/helper/deprecation.js +0 -24
- package/dist/modal/ModalFooterTestWrapper.svelte +0 -17
- package/dist/modal/ModalFooterTestWrapper.svelte.d.ts +0 -8
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
3
|
import { table } from './table.js';
|
|
4
4
|
import { buildTestId } from '../../helper/testid.js';
|
|
5
|
-
import { warnDeprecatedProps } from '../../helper/deprecation.js';
|
|
6
5
|
import type { TableProps, SortDirection, SortState, DataRow } from '../../index.js';
|
|
7
6
|
import Pagination from '../../elements/pagination/Pagination.svelte';
|
|
8
7
|
import Card from '../../layout/card/Card.svelte';
|
|
8
|
+
import Skeleton from '../../elements/skeleton/Skeleton.svelte';
|
|
9
9
|
import { SvelteSet } from 'svelte/reactivity';
|
|
10
|
+
import { slide } from 'svelte/transition';
|
|
11
|
+
import { quintOut } from 'svelte/easing';
|
|
10
12
|
|
|
11
13
|
let {
|
|
12
14
|
data = [],
|
|
@@ -24,30 +26,19 @@
|
|
|
24
26
|
onpagechange,
|
|
25
27
|
onpagesizechange,
|
|
26
28
|
class: classname = '',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
thclass,
|
|
38
|
-
thClass = thclass ?? '',
|
|
39
|
-
tdclass,
|
|
40
|
-
tdClass = tdclass ?? '',
|
|
41
|
-
footerclass,
|
|
42
|
-
footerClass = footerclass ?? '',
|
|
43
|
-
paginationclass,
|
|
44
|
-
paginationClass = paginationclass ?? '',
|
|
45
|
-
rowclass,
|
|
46
|
-
rowClass = rowclass ?? (() => ''),
|
|
29
|
+
wrapperClass = '',
|
|
30
|
+
tableClass = '',
|
|
31
|
+
theadClass = '',
|
|
32
|
+
tbodyClass = '',
|
|
33
|
+
trClass = 'bg-white',
|
|
34
|
+
thClass = '',
|
|
35
|
+
tdClass = '',
|
|
36
|
+
footerClass = '',
|
|
37
|
+
paginationClass = '',
|
|
38
|
+
rowClass = () => '',
|
|
47
39
|
loading = false,
|
|
48
40
|
expandedContent,
|
|
49
41
|
pagination = true,
|
|
50
|
-
showPagination = true,
|
|
51
42
|
showPageSize = false,
|
|
52
43
|
pageSizeOptions = [5, 10, 25, 50, 100],
|
|
53
44
|
paginationPosition = 'bottom',
|
|
@@ -62,34 +53,6 @@
|
|
|
62
53
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
54
|
}: TableProps<any> = $props();
|
|
64
55
|
|
|
65
|
-
warnDeprecatedProps(
|
|
66
|
-
'Table',
|
|
67
|
-
{
|
|
68
|
-
wrapperclass,
|
|
69
|
-
tableclass,
|
|
70
|
-
theadclass,
|
|
71
|
-
tbodyclass,
|
|
72
|
-
trclass,
|
|
73
|
-
thclass,
|
|
74
|
-
tdclass,
|
|
75
|
-
footerclass,
|
|
76
|
-
paginationclass,
|
|
77
|
-
rowclass
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
wrapperclass: 'wrapperClass',
|
|
81
|
-
tableclass: 'tableClass',
|
|
82
|
-
theadclass: 'theadClass',
|
|
83
|
-
tbodyclass: 'tbodyClass',
|
|
84
|
-
trclass: 'trClass',
|
|
85
|
-
thclass: 'thClass',
|
|
86
|
-
tdclass: 'tdClass',
|
|
87
|
-
footerclass: 'footerClass',
|
|
88
|
-
paginationclass: 'paginationClass',
|
|
89
|
-
rowclass: 'rowClass'
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
|
|
93
56
|
// Determine if we should use Card wrapper
|
|
94
57
|
const hasHeader = $derived(title !== undefined || subtitle !== undefined);
|
|
95
58
|
|
|
@@ -115,9 +78,7 @@
|
|
|
115
78
|
|
|
116
79
|
// Pagination is automatically determined by pageSize and pagination prop
|
|
117
80
|
const showPaginationControls = $derived(
|
|
118
|
-
pagination &&
|
|
119
|
-
showPagination &&
|
|
120
|
-
(data.length > internalPageSize || (totalItems ?? 0) > internalPageSize)
|
|
81
|
+
pagination && (data.length > internalPageSize || (totalItems ?? 0) > internalPageSize)
|
|
121
82
|
);
|
|
122
83
|
|
|
123
84
|
// Calculate total items and pages
|
|
@@ -156,6 +117,21 @@
|
|
|
156
117
|
const paginationClasses = $derived(cn(paginationBaseClass(), paginationClass));
|
|
157
118
|
const emptyStateClasses = $derived(emptyStateBaseClass());
|
|
158
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Map `column.hideBelow` to Tailwind classes that hide the column
|
|
122
|
+
* below that breakpoint. Applied to both `<th>` and `<td>` so the
|
|
123
|
+
* column disappears as a unit on narrow viewports.
|
|
124
|
+
*/
|
|
125
|
+
function hideBelowClass(hideBelow: 'sm' | 'md' | 'lg' | 'xl' | undefined): string {
|
|
126
|
+
if (!hideBelow) return '';
|
|
127
|
+
return {
|
|
128
|
+
sm: 'hidden sm:table-cell',
|
|
129
|
+
md: 'hidden md:table-cell',
|
|
130
|
+
lg: 'hidden lg:table-cell',
|
|
131
|
+
xl: 'hidden xl:table-cell'
|
|
132
|
+
}[hideBelow];
|
|
133
|
+
}
|
|
134
|
+
|
|
159
135
|
// Apply client-side sorting when no onsort handler is provided
|
|
160
136
|
const sortedData = $derived.by<DataRow[]>(() => {
|
|
161
137
|
if (onsort || !sortColumn || !sortDirection) {
|
|
@@ -228,30 +204,60 @@
|
|
|
228
204
|
onsort?.(newSortState);
|
|
229
205
|
}
|
|
230
206
|
|
|
207
|
+
// Synthetic per-row id used when `rowKey` isn't provided. WeakMap keys are
|
|
208
|
+
// identity-stable across Svelte 5 $state proxies, so this avoids the
|
|
209
|
+
// `state_proxy_equality_mismatch` warning that `selected.includes(row)` causes.
|
|
210
|
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
211
|
+
const rowIdMap = new WeakMap<DataRow, number>();
|
|
212
|
+
let rowIdCounter = 0;
|
|
213
|
+
function rowIdentity(row: DataRow): string | number {
|
|
214
|
+
if (rowKey) {
|
|
215
|
+
const v = row[rowKey];
|
|
216
|
+
// Only trust `rowKey` if it yields a primitive id. Falling back
|
|
217
|
+
// to the WeakMap below means a misconfigured `rowKey` (missing
|
|
218
|
+
// field, object value) still produces stable per-row identity
|
|
219
|
+
// instead of returning the same unusable value for every row.
|
|
220
|
+
if (typeof v === 'string' || typeof v === 'number') return v;
|
|
221
|
+
}
|
|
222
|
+
let id = rowIdMap.get(row);
|
|
223
|
+
if (id === undefined) {
|
|
224
|
+
id = ++rowIdCounter;
|
|
225
|
+
rowIdMap.set(row, id);
|
|
226
|
+
}
|
|
227
|
+
// Prefix synthetic IDs so they can never collide with a real
|
|
228
|
+
// numeric `rowKey` value (e.g. `id: 1`) when a dataset mixes rows
|
|
229
|
+
// that resolve `rowKey` with rows that fall back to this counter.
|
|
230
|
+
return `__table_row_fallback__${id}`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function sameRow(a: DataRow, b: DataRow): boolean {
|
|
234
|
+
return rowIdentity(a) === rowIdentity(b);
|
|
235
|
+
}
|
|
236
|
+
|
|
231
237
|
function toggleRowSelection(row: DataRow) {
|
|
232
238
|
if (!selectable) return;
|
|
233
239
|
|
|
234
|
-
const index =
|
|
235
|
-
? selected.findIndex((r) => r[rowKey] === row[rowKey])
|
|
236
|
-
: selected.findIndex((r) => r === row);
|
|
240
|
+
const index = selected.findIndex((r) => sameRow(r, row));
|
|
237
241
|
if (index === -1) {
|
|
238
242
|
selected = [...selected, row];
|
|
239
243
|
} else {
|
|
240
|
-
selected =
|
|
241
|
-
? selected.filter((r) => r[rowKey] !== row[rowKey])
|
|
242
|
-
: selected.filter((r) => r !== row);
|
|
244
|
+
selected = selected.filter((r) => !sameRow(r, row));
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
onselect(selected);
|
|
246
248
|
}
|
|
247
249
|
|
|
248
250
|
function isRowSelected(row: DataRow) {
|
|
249
|
-
|
|
250
|
-
return selected.includes(row);
|
|
251
|
+
return selected.some((r) => sameRow(r, row));
|
|
251
252
|
}
|
|
252
253
|
|
|
253
|
-
function getRowExpandKey(row: DataRow,
|
|
254
|
-
|
|
254
|
+
function getRowExpandKey(row: DataRow, _index: number): string | number {
|
|
255
|
+
// Share identity with selection so expanding row 0 on page 1 doesn't
|
|
256
|
+
// also expand row 0 after paging or resorting. `_index` is kept in
|
|
257
|
+
// the signature for call-site symmetry (callers have the index
|
|
258
|
+
// handy) but is deliberately unused now.
|
|
259
|
+
void _index;
|
|
260
|
+
return rowIdentity(row);
|
|
255
261
|
}
|
|
256
262
|
|
|
257
263
|
function toggleRowExpanded(row: DataRow, index: number) {
|
|
@@ -280,9 +286,7 @@
|
|
|
280
286
|
if (selectAllScope === 'all') {
|
|
281
287
|
selected = [];
|
|
282
288
|
} else {
|
|
283
|
-
selected = selected.filter(
|
|
284
|
-
(r) => !pageData.some((pr) => (rowKey ? pr[rowKey] === r[rowKey] : pr === r))
|
|
285
|
-
);
|
|
289
|
+
selected = selected.filter((r) => !pageData.some((pr) => sameRow(pr, r)));
|
|
286
290
|
}
|
|
287
291
|
} else {
|
|
288
292
|
if (selectAllScope === 'all') {
|
|
@@ -336,8 +340,8 @@
|
|
|
336
340
|
currentPage={internalCurrentPage}
|
|
337
341
|
totalItems={effectiveTotalItems}
|
|
338
342
|
pageSize={internalPageSize}
|
|
339
|
-
|
|
340
|
-
|
|
343
|
+
onpagechange={handlePageChange}
|
|
344
|
+
onpagesizechange={handlePageSizeChange}
|
|
341
345
|
{showPageSize}
|
|
342
346
|
{pageSizeOptions}
|
|
343
347
|
template={paginationTemplate === 'full' ? 'full' : 'compact'}
|
|
@@ -372,6 +376,7 @@
|
|
|
372
376
|
thClasses,
|
|
373
377
|
column.align === 'center' && 'text-center',
|
|
374
378
|
column.align === 'right' && 'text-right',
|
|
379
|
+
hideBelowClass(column.hideBelow),
|
|
375
380
|
column.class
|
|
376
381
|
)}
|
|
377
382
|
style={column.width ? `width: ${column.width}` : undefined}
|
|
@@ -442,37 +447,35 @@
|
|
|
442
447
|
<tr class={cn(trClasses, rowIdx % 2 === 1 && striped ? 'bg-default-50' : '')}>
|
|
443
448
|
{#if expandable && expandedContent}
|
|
444
449
|
<td class={cn(tdClasses, 'w-10')}>
|
|
445
|
-
<
|
|
450
|
+
<Skeleton class="mx-auto h-4 w-4" />
|
|
446
451
|
</td>
|
|
447
452
|
{/if}
|
|
448
453
|
{#if selectable}
|
|
449
454
|
<td class={cn(tdClasses, 'text-center')}>
|
|
450
|
-
<
|
|
455
|
+
<Skeleton class="mx-auto h-4 w-4" />
|
|
451
456
|
</td>
|
|
452
457
|
{/if}
|
|
453
458
|
{#each columns as column, colIdx (column.key)}
|
|
454
|
-
<td class={cn(tdClasses, column.class)}>
|
|
459
|
+
<td class={cn(tdClasses, hideBelowClass(column.hideBelow), column.class)}>
|
|
455
460
|
{#if colIdx === 0}
|
|
456
461
|
<div class="flex items-center gap-3">
|
|
457
|
-
<
|
|
458
|
-
class="bg-default-200 h-8 w-8 shrink-0 animate-pulse rounded-full"
|
|
459
|
-
></div>
|
|
462
|
+
<Skeleton class="size-8 shrink-0" rounded="rounded-full" />
|
|
460
463
|
<div class="flex-1 space-y-2">
|
|
461
|
-
<
|
|
462
|
-
<
|
|
464
|
+
<Skeleton class="h-3.5 w-28" />
|
|
465
|
+
<Skeleton class="h-3 w-20" />
|
|
463
466
|
</div>
|
|
464
467
|
</div>
|
|
465
468
|
{:else if colIdx === columns.length - 1}
|
|
466
469
|
<div class="flex items-center justify-end gap-2">
|
|
467
|
-
<
|
|
468
|
-
<
|
|
469
|
-
<
|
|
470
|
+
<Skeleton class="h-5 w-5" />
|
|
471
|
+
<Skeleton class="h-5 w-5" />
|
|
472
|
+
<Skeleton class="h-5 w-5" />
|
|
470
473
|
</div>
|
|
471
474
|
{:else}
|
|
472
|
-
<
|
|
473
|
-
class="
|
|
475
|
+
<Skeleton
|
|
476
|
+
class="h-3.5"
|
|
474
477
|
style="width: {60 + ((rowIdx * 17 + colIdx * 31) % 40)}%"
|
|
475
|
-
|
|
478
|
+
/>
|
|
476
479
|
{/if}
|
|
477
480
|
</td>
|
|
478
481
|
{/each}
|
|
@@ -543,6 +546,7 @@
|
|
|
543
546
|
tdClasses,
|
|
544
547
|
column.align === 'center' && 'text-center',
|
|
545
548
|
column.align === 'right' && 'text-right',
|
|
549
|
+
hideBelowClass(column.hideBelow),
|
|
546
550
|
column.class
|
|
547
551
|
)}
|
|
548
552
|
>
|
|
@@ -559,7 +563,9 @@
|
|
|
559
563
|
{#if expandedContent && (!expandable || isRowExpanded(row, rowIndex))}
|
|
560
564
|
<tr class="expandedContent-row">
|
|
561
565
|
<td colspan={totalColumnCount} class="border-0 p-0">
|
|
562
|
-
{
|
|
566
|
+
<div transition:slide={{ duration: 350, easing: quintOut }}>
|
|
567
|
+
{@render expandedContent(row)}
|
|
568
|
+
</div>
|
|
563
569
|
</td>
|
|
564
570
|
</tr>
|
|
565
571
|
{/if}
|
|
@@ -575,8 +581,8 @@
|
|
|
575
581
|
currentPage={internalCurrentPage}
|
|
576
582
|
totalItems={effectiveTotalItems}
|
|
577
583
|
pageSize={internalPageSize}
|
|
578
|
-
|
|
579
|
-
|
|
584
|
+
onpagechange={handlePageChange}
|
|
585
|
+
onpagesizechange={handlePageSizeChange}
|
|
580
586
|
{showPageSize}
|
|
581
587
|
{pageSizeOptions}
|
|
582
588
|
template={paginationTemplate === 'full' ? 'full' : 'compact'}
|
|
@@ -1,82 +1,206 @@
|
|
|
1
1
|
import type { ClassValue } from 'tailwind-variants';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Default shape for a table row — any record. Consumers typically
|
|
5
|
+
* supply a stricter type via Table's generic parameter
|
|
6
|
+
* (`<Table<User> …>`).
|
|
7
|
+
*/
|
|
8
|
+
export type DataRow = Record<string, unknown>;
|
|
9
|
+
/** Key type derived from `DataRow`. Used for column `key` references. */
|
|
4
10
|
export type KeyType = keyof DataRow;
|
|
11
|
+
/** Semantic status tokens recognised by the `Cells.Status` built-in renderer. */
|
|
5
12
|
export type StatusType = 'active' | 'inactive' | 'pending' | 'error' | 'default';
|
|
6
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Column definition for `<Table>`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const columns: TableColumn<User>[] = [
|
|
19
|
+
* { key: 'name', header: 'Name', sortable: true },
|
|
20
|
+
* { key: 'email', header: 'Email', cell: Cells.Email },
|
|
21
|
+
* { key: 'lastSeen', header: 'Last seen', cell: Cells.DateCell, align: 'right' }
|
|
22
|
+
* ];
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export type TableColumn<T = DataRow> = {
|
|
26
|
+
/** Field name in the row object — used for default rendering and sort keys. */
|
|
7
27
|
key: KeyType;
|
|
28
|
+
/** Column header text. */
|
|
8
29
|
header: string;
|
|
30
|
+
/**
|
|
31
|
+
* Custom cell renderer. Receives `(row, key, index)`. For common cases
|
|
32
|
+
* use pre-built snippets from `Cells` (Currency, DateCell, Email, Status, etc.).
|
|
33
|
+
*/
|
|
9
34
|
cell?: Snippet<[row: T, key: KeyType, index?: number]>;
|
|
35
|
+
/** Enable click-to-sort on the column header. @default false */
|
|
10
36
|
sortable?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Override the sort identifier if it should differ from `key` (e.g.
|
|
39
|
+
* when multiple columns share a derived sort field).
|
|
40
|
+
*/
|
|
11
41
|
sortKey?: string;
|
|
42
|
+
/** Text alignment for the cells in this column. @default 'left' */
|
|
12
43
|
align?: 'left' | 'center' | 'right';
|
|
44
|
+
/** CSS width value. Supports `'200px'`, `'20%'`, etc. */
|
|
13
45
|
width?: string;
|
|
46
|
+
/** Classes applied to both header and cells in this column. */
|
|
14
47
|
class?: ClassValue;
|
|
48
|
+
/**
|
|
49
|
+
* Hide this column below a Tailwind breakpoint. Lets you keep the
|
|
50
|
+
* most important columns visible on narrow viewports without writing
|
|
51
|
+
* responsive class strings yourself. Maps to `hidden sm:table-cell`
|
|
52
|
+
* (and equivalents for md / lg / xl). When unset, the column is
|
|
53
|
+
* always visible — the table's wrapper still allows horizontal
|
|
54
|
+
* scrolling as a fallback.
|
|
55
|
+
*/
|
|
56
|
+
hideBelow?: 'sm' | 'md' | 'lg' | 'xl';
|
|
15
57
|
};
|
|
58
|
+
/** Sort direction. `null` = unsorted. */
|
|
16
59
|
export type SortDirection = 'asc' | 'desc' | null;
|
|
60
|
+
/** Current sort state — emitted by `onsort`. */
|
|
17
61
|
export type SortState = {
|
|
18
62
|
column: string | null;
|
|
19
63
|
direction: SortDirection;
|
|
20
64
|
};
|
|
21
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Props for `<Table>` — a data table with sorting, selection, pagination,
|
|
67
|
+
* row expansion, and skeleton loading. Generic over the row type `T`.
|
|
68
|
+
*
|
|
69
|
+
* Use `<Cells.Currency>`, `<Cells.Email>`, `<Cells.DateCell>` etc. from
|
|
70
|
+
* `Cells` for common cell formatting without writing snippets yourself.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```svelte
|
|
74
|
+
* <script lang="ts">
|
|
75
|
+
* import { Table, Cells } from '@makolabs/ripple';
|
|
76
|
+
* import type { TableColumn } from '@makolabs/ripple';
|
|
77
|
+
*
|
|
78
|
+
* const columns: TableColumn<User>[] = [
|
|
79
|
+
* { key: 'name', header: 'Name', sortable: true },
|
|
80
|
+
* { key: 'email', header: 'Email', cell: Cells.Email },
|
|
81
|
+
* { key: 'createdAt', header: 'Joined', cell: Cells.DateCell }
|
|
82
|
+
* ];
|
|
83
|
+
* </script>
|
|
84
|
+
*
|
|
85
|
+
* <Table
|
|
86
|
+
* {columns}
|
|
87
|
+
* data={users}
|
|
88
|
+
* {loading}
|
|
89
|
+
* pageSize={25}
|
|
90
|
+
* title="Users"
|
|
91
|
+
* onrowclick={(user) => goto(`/users/${user.id}`)}
|
|
92
|
+
* />
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```svelte
|
|
97
|
+
* <!-- Selectable with expandable rows -->
|
|
98
|
+
* <Table
|
|
99
|
+
* {columns}
|
|
100
|
+
* data={orders}
|
|
101
|
+
* selectable
|
|
102
|
+
* bind:selected
|
|
103
|
+
* expandable
|
|
104
|
+
* rowKey="id"
|
|
105
|
+
* >
|
|
106
|
+
* {#snippet expandedContent(row)}
|
|
107
|
+
* <OrderLineItems orderId={row.id} />
|
|
108
|
+
* {/snippet}
|
|
109
|
+
* </Table>
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export type TableProps<T = DataRow> = {
|
|
113
|
+
/** Array of rows to render. */
|
|
22
114
|
data: T[];
|
|
115
|
+
/** Column definitions — see `TableColumn`. */
|
|
23
116
|
columns: TableColumn<T>[];
|
|
117
|
+
/** Show horizontal/vertical borders. @default true (unless a title/subtitle is set) */
|
|
24
118
|
bordered?: boolean;
|
|
119
|
+
/** Alternate row backgrounds. @default false */
|
|
25
120
|
striped?: boolean;
|
|
121
|
+
/** Rows per page. @default 10 */
|
|
26
122
|
pageSize?: number;
|
|
123
|
+
/** Bindable current page (1-indexed). */
|
|
27
124
|
currentPage?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Total item count — needed when doing server-side pagination where
|
|
127
|
+
* `data` only contains the current page.
|
|
128
|
+
*/
|
|
28
129
|
totalItems?: number;
|
|
130
|
+
/** Add a checkbox column and enable row selection. @default false */
|
|
29
131
|
selectable?: boolean;
|
|
132
|
+
/** Bindable selected rows. */
|
|
30
133
|
selected?: T[];
|
|
31
134
|
class?: ClassValue;
|
|
32
|
-
/**
|
|
33
|
-
wrapperclass?: ClassValue;
|
|
135
|
+
/** Classes on the outer scroll container (default has `overflow-x-auto`). */
|
|
34
136
|
wrapperClass?: ClassValue;
|
|
35
|
-
/**
|
|
36
|
-
tableclass?: ClassValue;
|
|
137
|
+
/** Classes on the `<table>` element. */
|
|
37
138
|
tableClass?: ClassValue;
|
|
38
|
-
/**
|
|
39
|
-
theadclass?: ClassValue;
|
|
139
|
+
/** Classes on `<thead>`. */
|
|
40
140
|
theadClass?: ClassValue;
|
|
41
|
-
/**
|
|
42
|
-
tbodyclass?: ClassValue;
|
|
141
|
+
/** Classes on `<tbody>`. */
|
|
43
142
|
tbodyClass?: ClassValue;
|
|
44
|
-
/**
|
|
45
|
-
trclass?: ClassValue;
|
|
143
|
+
/** Static classes on every `<tr>`. Use `rowClass` for per-row dynamic classes. */
|
|
46
144
|
trClass?: ClassValue;
|
|
47
|
-
/**
|
|
48
|
-
thclass?: ClassValue;
|
|
145
|
+
/** Classes on every `<th>`. */
|
|
49
146
|
thClass?: ClassValue;
|
|
50
|
-
/**
|
|
51
|
-
tdclass?: ClassValue;
|
|
147
|
+
/** Classes on every `<td>`. */
|
|
52
148
|
tdClass?: ClassValue;
|
|
53
|
-
/**
|
|
54
|
-
footerclass?: ClassValue;
|
|
149
|
+
/** Classes on the footer area (pagination row). */
|
|
55
150
|
footerClass?: ClassValue;
|
|
56
|
-
/**
|
|
57
|
-
paginationclass?: ClassValue;
|
|
151
|
+
/** Classes on the pagination control itself. */
|
|
58
152
|
paginationClass?: ClassValue;
|
|
153
|
+
/** Fires when a row is clicked (ignored on checkbox cells). */
|
|
59
154
|
onrowclick?: (row: T, index: number) => void;
|
|
155
|
+
/** Fires when the user changes the sort column/direction. */
|
|
60
156
|
onsort?: (sortState: SortState) => void;
|
|
157
|
+
/** Fires when row selection changes (selectable mode). */
|
|
61
158
|
onselect?: (selected: T[]) => void;
|
|
159
|
+
/** Fires on page change. */
|
|
62
160
|
onpagechange?: (page: number) => void;
|
|
63
|
-
/**
|
|
64
|
-
rowclass?: (row: T, index: number) => ClassValue;
|
|
161
|
+
/** Per-row dynamic classes (e.g. tint by status). */
|
|
65
162
|
rowClass?: (row: T, index: number) => ClassValue;
|
|
163
|
+
/** Show a skeleton placeholder instead of rows while loading. @default false */
|
|
66
164
|
loading?: boolean;
|
|
165
|
+
/** Expanded-row content snippet. Only used when `expandable` is true. */
|
|
67
166
|
expandedContent?: Snippet<[T]>;
|
|
167
|
+
/**
|
|
168
|
+
* Show pagination controls below (or above) the table when the data
|
|
169
|
+
* set exceeds `pageSize`. @default true
|
|
170
|
+
*/
|
|
68
171
|
pagination?: boolean;
|
|
69
|
-
|
|
172
|
+
/** Show a "rows per page" selector in the pagination footer. @default false */
|
|
70
173
|
showPageSize?: boolean;
|
|
174
|
+
/** Options for the page-size selector. @default [5, 10, 25, 50, 100] */
|
|
71
175
|
pageSizeOptions?: number[];
|
|
176
|
+
/** Fires when the user changes the page size. */
|
|
72
177
|
onpagesizechange?: (pageSize: number) => void;
|
|
178
|
+
/** Where to render pagination controls. @default 'bottom' */
|
|
73
179
|
paginationPosition?: 'top' | 'bottom' | 'both';
|
|
180
|
+
/**
|
|
181
|
+
* Pagination layout:
|
|
182
|
+
* - `'simple'` — prev/next + "Page 3 of 7"
|
|
183
|
+
* - `'full'` (default) — full page-number buttons + first/last/prev/next
|
|
184
|
+
*/
|
|
74
185
|
paginationTemplate?: 'simple' | 'full';
|
|
186
|
+
/** Optional card title shown above the table. Auto-wraps the table in a `<Card>`. */
|
|
75
187
|
title?: string;
|
|
188
|
+
/** Subtitle shown under the title. */
|
|
76
189
|
subtitle?: string;
|
|
190
|
+
/** Content rendered on the right side of the header (e.g. Export button). */
|
|
77
191
|
headerActions?: Snippet;
|
|
192
|
+
/**
|
|
193
|
+
* Whether "select all" picks the current page or the entire data set.
|
|
194
|
+
* `'all'` only makes sense for client-side pagination. @default 'page'
|
|
195
|
+
*/
|
|
78
196
|
selectAllScope?: 'page' | 'all';
|
|
197
|
+
/**
|
|
198
|
+
* Key used to deduplicate selections and track expanded rows. Required
|
|
199
|
+
* when `expandable` or `selectable` is used with an async/paged data
|
|
200
|
+
* source where array references aren't stable.
|
|
201
|
+
*/
|
|
79
202
|
rowKey?: string;
|
|
203
|
+
/** Allow rows to expand/collapse showing `expandedContent`. @default false */
|
|
80
204
|
expandable?: boolean;
|
|
81
205
|
testId?: string;
|
|
82
206
|
};
|
|
@@ -8,7 +8,7 @@ export declare const table: import("tailwind-variants").TVReturnType<{
|
|
|
8
8
|
th: string;
|
|
9
9
|
td: string;
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
md: {
|
|
12
12
|
th: string;
|
|
13
13
|
td: string;
|
|
14
14
|
};
|
|
@@ -93,7 +93,7 @@ export declare const table: import("tailwind-variants").TVReturnType<{
|
|
|
93
93
|
th: string;
|
|
94
94
|
td: string;
|
|
95
95
|
};
|
|
96
|
-
|
|
96
|
+
md: {
|
|
97
97
|
th: string;
|
|
98
98
|
td: string;
|
|
99
99
|
};
|
|
@@ -178,7 +178,7 @@ export declare const table: import("tailwind-variants").TVReturnType<{
|
|
|
178
178
|
th: string;
|
|
179
179
|
td: string;
|
|
180
180
|
};
|
|
181
|
-
|
|
181
|
+
md: {
|
|
182
182
|
th: string;
|
|
183
183
|
td: string;
|
|
184
184
|
};
|
|
@@ -26,7 +26,7 @@ export const table = tv({
|
|
|
26
26
|
th: 'px-3 py-2 text-xs',
|
|
27
27
|
td: 'px-3 py-2 text-sm'
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
md: {
|
|
30
30
|
th: 'px-4 py-3 text-sm',
|
|
31
31
|
td: 'px-4 py-3 text-sm'
|
|
32
32
|
},
|
|
@@ -134,7 +134,7 @@ export const table = tv({
|
|
|
134
134
|
}
|
|
135
135
|
],
|
|
136
136
|
defaultVariants: {
|
|
137
|
-
size: '
|
|
137
|
+
size: 'md',
|
|
138
138
|
color: 'default',
|
|
139
139
|
bordered: false,
|
|
140
140
|
striped: false
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
3
|
import { tabs } from './tabs.js';
|
|
4
4
|
import { Color, Size } from '../../index.js';
|
|
5
|
+
import { fly } from 'svelte/transition';
|
|
6
|
+
import { quintOut } from 'svelte/easing';
|
|
5
7
|
import type { TabProps } from '../../index.js';
|
|
6
8
|
let {
|
|
7
9
|
value = '',
|
|
@@ -10,11 +12,12 @@
|
|
|
10
12
|
selected = false,
|
|
11
13
|
disabled = false,
|
|
12
14
|
color = Color.PRIMARY,
|
|
13
|
-
size = Size.
|
|
15
|
+
size = Size.MD,
|
|
14
16
|
onclick = () => {},
|
|
15
17
|
variant = 'line',
|
|
18
|
+
index = 0,
|
|
16
19
|
testId
|
|
17
|
-
}: TabProps = $props();
|
|
20
|
+
}: TabProps & { index?: number } = $props();
|
|
18
21
|
|
|
19
22
|
function handleClick(event: Event & { currentTarget: EventTarget & HTMLButtonElement }) {
|
|
20
23
|
event.preventDefault();
|
|
@@ -45,6 +48,7 @@
|
|
|
45
48
|
aria-controls={`panel-${value}`}
|
|
46
49
|
aria-selected={selected ? 'true' : 'false'}
|
|
47
50
|
data-testid={testId}
|
|
51
|
+
in:fly|global={{ y: -12, duration: 400, delay: index * 60, easing: quintOut }}
|
|
48
52
|
onclick={handleClick}
|
|
49
53
|
onkeydown={(e) => {
|
|
50
54
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { TabProps } from '../../index.js';
|
|
2
|
-
|
|
2
|
+
type $$ComponentProps = TabProps & {
|
|
3
|
+
index?: number;
|
|
4
|
+
};
|
|
5
|
+
declare const Tab: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
3
6
|
type Tab = ReturnType<typeof Tab>;
|
|
4
7
|
export default Tab;
|
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
import { tabs } from './tabs.js';
|
|
6
6
|
import type { TabsGroupProps } from '../../index.js';
|
|
7
7
|
import { setContext } from 'svelte';
|
|
8
|
+
import { fade } from 'svelte/transition';
|
|
9
|
+
import { quintOut } from 'svelte/easing';
|
|
8
10
|
import type { VariantColors, VariantSizes } from '../../index.js';
|
|
9
11
|
|
|
10
12
|
let {
|
|
11
13
|
tabs: tabItems = [],
|
|
12
14
|
selected = $bindable(''),
|
|
13
15
|
color = 'primary' as VariantColors,
|
|
14
|
-
size = '
|
|
16
|
+
size = 'md' as VariantSizes,
|
|
15
17
|
variant = 'line',
|
|
16
18
|
class: className = '',
|
|
17
19
|
listClass = '',
|
|
@@ -53,6 +55,7 @@
|
|
|
53
55
|
{color}
|
|
54
56
|
{size}
|
|
55
57
|
{variant}
|
|
58
|
+
{index}
|
|
56
59
|
testId={buildTestId('tabgroup', 'tab', testId, index)}
|
|
57
60
|
onclick={() => handleTabClick(tab.value)}
|
|
58
61
|
/>
|
|
@@ -60,6 +63,10 @@
|
|
|
60
63
|
</div>
|
|
61
64
|
|
|
62
65
|
<div class={panelClass_} data-testid={buildTestId('tabgroup', 'panel', testId)}>
|
|
63
|
-
{
|
|
66
|
+
{#key selected}
|
|
67
|
+
<div in:fade={{ duration: 500, easing: quintOut }}>
|
|
68
|
+
{@render children?.(selected)}
|
|
69
|
+
</div>
|
|
70
|
+
{/key}
|
|
64
71
|
</div>
|
|
65
72
|
</div>
|