@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.
Files changed (184) hide show
  1. package/README.md +403 -497
  2. package/dist/adapters/storage/S3Adapter.d.ts +49 -1
  3. package/dist/adapters/storage/S3Adapter.js +38 -1
  4. package/dist/adapters/storage/types.d.ts +20 -0
  5. package/dist/ai/AIChatInterface.svelte +2 -1
  6. package/dist/ai/AIChatInterface.svelte.d.ts +2 -1
  7. package/dist/ai/CodeRenderer.svelte +7 -2
  8. package/dist/ai/CodeRenderer.svelte.d.ts +2 -1
  9. package/dist/ai/ComposeDropdown.svelte +1 -1
  10. package/dist/ai/MessageBox.svelte +3 -3
  11. package/dist/ai/MessageBox.svelte.d.ts +3 -2
  12. package/dist/ai/ThinkingDisplay.svelte +4 -3
  13. package/dist/ai/ThinkingDisplay.svelte.d.ts +2 -1
  14. package/dist/ai/ai-types.d.ts +55 -1
  15. package/dist/button/Button.svelte +5 -5
  16. package/dist/button/button-types.d.ts +49 -4
  17. package/dist/button/button.d.ts +9 -9
  18. package/dist/button/button.js +6 -6
  19. package/dist/charts/Chart.svelte +8 -16
  20. package/dist/charts/chart-types.d.ts +78 -1
  21. package/dist/drawer/Drawer.svelte +6 -26
  22. package/dist/drawer/drawer-types.d.ts +33 -12
  23. package/dist/drawer/drawer.d.ts +3 -3
  24. package/dist/drawer/drawer.js +1 -1
  25. package/dist/elements/accordion/Accordion.svelte +6 -17
  26. package/dist/elements/accordion/accordion-types.d.ts +53 -6
  27. package/dist/elements/alert/Alert.svelte +3 -0
  28. package/dist/elements/badge/Badge.svelte +1 -1
  29. package/dist/elements/badge/badge-types.d.ts +22 -0
  30. package/dist/elements/badge/badge.d.ts +3 -3
  31. package/dist/elements/badge/badge.js +1 -1
  32. package/dist/elements/combobox/ComboBox.svelte +247 -0
  33. package/dist/elements/combobox/ComboBox.svelte.d.ts +4 -0
  34. package/dist/elements/combobox/combobox-types.d.ts +41 -0
  35. package/dist/elements/combobox/combobox-types.js +1 -0
  36. package/dist/elements/context-menu/ContextMenu.svelte +137 -0
  37. package/dist/elements/context-menu/ContextMenu.svelte.d.ts +4 -0
  38. package/dist/elements/context-menu/context-menu-types.d.ts +40 -0
  39. package/dist/elements/context-menu/context-menu-types.js +1 -0
  40. package/dist/elements/dropdown/Dropdown.svelte +1 -1
  41. package/dist/elements/dropdown/Select.svelte +4 -1
  42. package/dist/elements/dropdown/dropdown-types.d.ts +114 -0
  43. package/dist/elements/dropdown/dropdown.d.ts +3 -3
  44. package/dist/elements/dropdown/dropdown.js +2 -2
  45. package/dist/elements/dropdown/select.d.ts +3 -3
  46. package/dist/elements/dropdown/select.js +2 -2
  47. package/dist/elements/empty-state/EmptyState.svelte +1 -1
  48. package/dist/elements/empty-state/empty-state-types.d.ts +32 -1
  49. package/dist/elements/empty-state/empty-state.d.ts +3 -3
  50. package/dist/elements/empty-state/empty-state.js +2 -2
  51. package/dist/elements/file-upload/FileUpload.svelte +5 -0
  52. package/dist/elements/file-upload/file-upload-types.d.ts +59 -0
  53. package/dist/elements/pagination/Pagination.svelte +53 -21
  54. package/dist/elements/pagination/Pagination.svelte.d.ts +33 -5
  55. package/dist/elements/popover/Popover.svelte +234 -0
  56. package/dist/elements/popover/Popover.svelte.d.ts +4 -0
  57. package/dist/elements/popover/index.d.ts +2 -0
  58. package/dist/elements/popover/index.js +1 -0
  59. package/dist/elements/popover/popover-types.d.ts +60 -0
  60. package/dist/elements/popover/popover-types.js +1 -0
  61. package/dist/elements/progress/Progress.svelte +32 -7
  62. package/dist/elements/progress/progress-types.d.ts +48 -1
  63. package/dist/elements/skeleton/Skeleton.svelte +56 -0
  64. package/dist/elements/skeleton/Skeleton.svelte.d.ts +4 -0
  65. package/dist/elements/skeleton/index.d.ts +2 -0
  66. package/dist/elements/skeleton/index.js +1 -0
  67. package/dist/elements/skeleton/skeleton-types.d.ts +50 -0
  68. package/dist/elements/skeleton/skeleton-types.js +1 -0
  69. package/dist/elements/spinner/Spinner.svelte +1 -1
  70. package/dist/elements/spinner/spinner-types.d.ts +20 -0
  71. package/dist/elements/spinner/spinner.d.ts +3 -3
  72. package/dist/elements/spinner/spinner.js +2 -2
  73. package/dist/elements/tooltip/Tooltip.svelte +108 -11
  74. package/dist/elements/tooltip/tooltip-types.d.ts +49 -1
  75. package/dist/file-browser/FileBrowser.svelte +21 -12
  76. package/dist/filters/CompactFilters.svelte +221 -33
  77. package/dist/filters/CompactFilters.svelte.d.ts +1 -1
  78. package/dist/filters/FilterBar.svelte +184 -0
  79. package/dist/filters/FilterBar.svelte.d.ts +4 -0
  80. package/dist/filters/FilterPopover.svelte +346 -0
  81. package/dist/filters/FilterPopover.svelte.d.ts +4 -0
  82. package/dist/filters/date-presets.d.ts +15 -0
  83. package/dist/filters/date-presets.js +107 -0
  84. package/dist/filters/filter-types.d.ts +69 -3
  85. package/dist/filters/index.d.ts +5 -0
  86. package/dist/filters/index.js +4 -0
  87. package/dist/filters/sync-filters-to-url.svelte.d.ts +37 -0
  88. package/dist/filters/sync-filters-to-url.svelte.js +114 -0
  89. package/dist/forms/DateRange.svelte +4 -2
  90. package/dist/forms/Input.svelte +2 -2
  91. package/dist/forms/MarketSelector.svelte +8 -3
  92. package/dist/forms/NumberInput.svelte +4 -4
  93. package/dist/forms/RadioGroup.svelte +123 -0
  94. package/dist/forms/RadioGroup.svelte.d.ts +4 -0
  95. package/dist/forms/SegmentedControl.svelte +11 -4
  96. package/dist/forms/Slider.svelte +72 -3
  97. package/dist/forms/Tags.svelte +14 -5
  98. package/dist/forms/Textarea.svelte +126 -0
  99. package/dist/forms/Textarea.svelte.d.ts +4 -0
  100. package/dist/forms/Toggle.svelte +8 -8
  101. package/dist/forms/calendar/Calendar.svelte +218 -0
  102. package/dist/forms/calendar/Calendar.svelte.d.ts +4 -0
  103. package/dist/forms/calendar/calendar-types.d.ts +46 -0
  104. package/dist/forms/calendar/calendar-types.js +1 -0
  105. package/dist/forms/calendar/index.d.ts +2 -0
  106. package/dist/forms/calendar/index.js +1 -0
  107. package/dist/forms/date-picker/DatePicker.svelte +144 -0
  108. package/dist/forms/date-picker/DatePicker.svelte.d.ts +4 -0
  109. package/dist/forms/date-picker/date-picker-types.d.ts +29 -0
  110. package/dist/forms/date-picker/date-picker-types.js +1 -0
  111. package/dist/forms/form-types.d.ts +425 -6
  112. package/dist/forms/market/market-selector-types.d.ts +52 -1
  113. package/dist/forms/segmented-control.d.ts +5 -2
  114. package/dist/forms/segmented-control.js +16 -5
  115. package/dist/forms/slider.d.ts +3 -3
  116. package/dist/forms/slider.js +2 -2
  117. package/dist/funcs/user-management.remote.d.ts +1 -1
  118. package/dist/funcs/user-management.remote.js +2 -2
  119. package/dist/header/Breadcrumbs.svelte +4 -20
  120. package/dist/header/PageHeader.svelte +6 -14
  121. package/dist/header/breadcrumbs.d.ts +3 -11
  122. package/dist/header/breadcrumbs.js +10 -5
  123. package/dist/header/header-types.d.ts +62 -11
  124. package/dist/index.d.ts +35 -9
  125. package/dist/index.js +24 -4
  126. package/dist/layout/activity-list/ActivityList.svelte +13 -7
  127. package/dist/layout/activity-list/activity-list-types.d.ts +46 -7
  128. package/dist/layout/card/Card.svelte +12 -15
  129. package/dist/layout/card/MetricCard.svelte +50 -32
  130. package/dist/layout/card/card-types.d.ts +114 -4
  131. package/dist/layout/navbar/navbar-types.d.ts +48 -0
  132. package/dist/layout/navbar/navbar.d.ts +3 -3
  133. package/dist/layout/navbar/navbar.js +2 -2
  134. package/dist/layout/sidebar/Sidebar.svelte +87 -11
  135. package/dist/layout/sidebar/sidebar-types.d.ts +60 -1
  136. package/dist/layout/stepper/Stepper.svelte +288 -0
  137. package/dist/layout/stepper/Stepper.svelte.d.ts +4 -0
  138. package/dist/layout/stepper/stepper-types.d.ts +80 -0
  139. package/dist/layout/stepper/stepper-types.js +1 -0
  140. package/dist/layout/table/Table.svelte +91 -85
  141. package/dist/layout/table/table-types.d.ts +148 -24
  142. package/dist/layout/table/table.d.ts +3 -3
  143. package/dist/layout/table/table.js +2 -2
  144. package/dist/layout/tabs/Tab.svelte +6 -2
  145. package/dist/layout/tabs/Tab.svelte.d.ts +4 -1
  146. package/dist/layout/tabs/TabGroup.svelte +9 -2
  147. package/dist/layout/tabs/tabs-types.d.ts +63 -0
  148. package/dist/layout/tabs/tabs.d.ts +3 -3
  149. package/dist/layout/tabs/tabs.js +12 -6
  150. package/dist/modal/ConfirmDialog.svelte +65 -0
  151. package/dist/modal/ConfirmDialog.svelte.d.ts +4 -0
  152. package/dist/modal/Modal.svelte +6 -26
  153. package/dist/modal/confirm-dialog-types.d.ts +39 -0
  154. package/dist/modal/confirm-dialog-types.js +1 -0
  155. package/dist/modal/modal-types.d.ts +51 -12
  156. package/dist/modal/modal.d.ts +3 -3
  157. package/dist/modal/modal.js +3 -3
  158. package/dist/pipeline/Pipeline.svelte +8 -3
  159. package/dist/pipeline/pipeline-types.d.ts +55 -3
  160. package/dist/pipeline/pipeline.d.ts +18 -3
  161. package/dist/pipeline/pipeline.js +7 -2
  162. package/dist/server/s3.d.ts +35 -3
  163. package/dist/sonner/Toaster.svelte +29 -0
  164. package/dist/sonner/Toaster.svelte.d.ts +4 -0
  165. package/dist/sonner/index.d.ts +21 -0
  166. package/dist/sonner/index.js +20 -0
  167. package/dist/user-management/UserManagement.svelte +22 -16
  168. package/dist/user-management/UserModal.svelte +10 -7
  169. package/dist/user-management/UserTable.svelte +16 -17
  170. package/dist/user-management/UserViewModal.svelte +11 -11
  171. package/dist/user-management/user-management-types.d.ts +118 -31
  172. package/dist/variants.d.ts +1 -1
  173. package/dist/variants.js +1 -1
  174. package/package.json +7 -4
  175. package/dist/config/ai.d.ts +0 -13
  176. package/dist/config/ai.js +0 -44
  177. package/dist/elements/empty-state/EmptyStateTestWrapper.svelte +0 -25
  178. package/dist/elements/empty-state/EmptyStateTestWrapper.svelte.d.ts +0 -8
  179. package/dist/elements/tooltip/TooltipTestWrapper.svelte +0 -14
  180. package/dist/elements/tooltip/TooltipTestWrapper.svelte.d.ts +0 -7
  181. package/dist/helper/deprecation.d.ts +0 -14
  182. package/dist/helper/deprecation.js +0 -24
  183. package/dist/modal/ModalFooterTestWrapper.svelte +0 -17
  184. 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
- wrapperclass,
28
- wrapperClass = wrapperclass ?? '',
29
- tableclass,
30
- tableClass = tableclass ?? '',
31
- theadclass,
32
- theadClass = theadclass ?? '',
33
- tbodyclass,
34
- tbodyClass = tbodyclass ?? '',
35
- trclass,
36
- trClass = trclass ?? 'bg-white',
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 = rowKey
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 = rowKey
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
- if (rowKey) return selected.some((r) => r[rowKey] === row[rowKey]);
250
- return selected.includes(row);
251
+ return selected.some((r) => sameRow(r, row));
251
252
  }
252
253
 
253
- function getRowExpandKey(row: DataRow, index: number): string | number {
254
- return rowKey ? row[rowKey] : index;
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
- onPageChange={handlePageChange}
340
- onPageSizeChange={handlePageSizeChange}
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
- <div class="bg-default-200 mx-auto h-4 w-4 animate-pulse rounded"></div>
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
- <div class="bg-default-200 mx-auto h-4 w-4 animate-pulse rounded"></div>
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
- <div
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
- <div class="bg-default-200 h-3.5 w-28 animate-pulse rounded"></div>
462
- <div class="bg-default-100 h-3 w-20 animate-pulse rounded"></div>
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
- <div class="bg-default-200 h-5 w-5 animate-pulse rounded"></div>
468
- <div class="bg-default-200 h-5 w-5 animate-pulse rounded"></div>
469
- <div class="bg-default-200 h-5 w-5 animate-pulse rounded"></div>
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
- <div
473
- class="bg-default-200 h-3.5 animate-pulse rounded"
475
+ <Skeleton
476
+ class="h-3.5"
474
477
  style="width: {60 + ((rowIdx * 17 + colIdx * 31) % 40)}%"
475
- ></div>
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
- {@render expandedContent(row)}
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
- onPageChange={handlePageChange}
579
- onPageSizeChange={handlePageSizeChange}
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
- export type DataRow = Record<string, any>;
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
- export type TableColumn<T extends DataRow = any> = {
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
- export type TableProps<T extends DataRow = any> = {
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
- /** @deprecated Use wrapperClass instead */
33
- wrapperclass?: ClassValue;
135
+ /** Classes on the outer scroll container (default has `overflow-x-auto`). */
34
136
  wrapperClass?: ClassValue;
35
- /** @deprecated Use tableClass instead */
36
- tableclass?: ClassValue;
137
+ /** Classes on the `<table>` element. */
37
138
  tableClass?: ClassValue;
38
- /** @deprecated Use theadClass instead */
39
- theadclass?: ClassValue;
139
+ /** Classes on `<thead>`. */
40
140
  theadClass?: ClassValue;
41
- /** @deprecated Use tbodyClass instead */
42
- tbodyclass?: ClassValue;
141
+ /** Classes on `<tbody>`. */
43
142
  tbodyClass?: ClassValue;
44
- /** @deprecated Use trClass instead */
45
- trclass?: ClassValue;
143
+ /** Static classes on every `<tr>`. Use `rowClass` for per-row dynamic classes. */
46
144
  trClass?: ClassValue;
47
- /** @deprecated Use thClass instead */
48
- thclass?: ClassValue;
145
+ /** Classes on every `<th>`. */
49
146
  thClass?: ClassValue;
50
- /** @deprecated Use tdClass instead */
51
- tdclass?: ClassValue;
147
+ /** Classes on every `<td>`. */
52
148
  tdClass?: ClassValue;
53
- /** @deprecated Use footerClass instead */
54
- footerclass?: ClassValue;
149
+ /** Classes on the footer area (pagination row). */
55
150
  footerClass?: ClassValue;
56
- /** @deprecated Use paginationClass instead */
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
- /** @deprecated Use rowClass instead */
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
- showPagination?: boolean;
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
- base: {
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
- base: {
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
- base: {
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
- base: {
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: 'base',
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.BASE,
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
- declare const Tab: import("svelte").Component<TabProps, {}, "">;
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 = 'base' as VariantSizes,
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
- {@render children?.(selected)}
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>