@happyvertical/smrt-ui 0.42.2 → 0.42.4

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.
@@ -16,12 +16,20 @@ import { M } from '../../i18n/strings.js';
16
16
  import Trans from '../../i18n/Trans.svelte';
17
17
  import { useI18n } from '../../i18n/use-i18n.js';
18
18
  import Pagination from '../ui/Pagination.svelte';
19
- import type {
20
- DataTableColumn,
21
- DataTableProps,
22
- SortDirection,
23
- SortState,
24
- } from './types.js';
19
+ import {
20
+ compareDataTableRowIds,
21
+ createDataTableController,
22
+ type DataTableCommand,
23
+ type DataTableController,
24
+ type DataTableFilter,
25
+ type DataTableModes,
26
+ type DataTableRowId,
27
+ type DataTableSnapshot,
28
+ type DataTableViewState,
29
+ type DataTableViewStateInput,
30
+ } from './DataTableController.js';
31
+ import { resolveDataTableRows } from './DataTableIdentity.js';
32
+ import type { DataTableColumn, DataTableProps, SortState } from './types.js';
25
33
  import { defaultSort, getNestedValue } from './types.js';
26
34
 
27
35
  const { t } = useI18n();
@@ -37,6 +45,7 @@ let {
37
45
  data = [],
38
46
  columns = [],
39
47
  rowKey,
48
+ agentAddressable = false,
40
49
  selectable = false,
41
50
  selected = $bindable(new Set<string | number>()),
42
51
  onSelectionChange,
@@ -68,85 +77,227 @@ let {
68
77
  caption,
69
78
  dense = false,
70
79
  cell,
80
+ controller,
81
+ state: controlledState,
82
+ initialState,
83
+ onStateChange,
84
+ modes,
71
85
  }: ExtendedProps<T> = $props();
72
86
 
73
- // Get row key value
74
- function getRowKey(row: T, index: number): string | number {
75
- if (!rowKey) return index;
76
- if (typeof rowKey === 'function') return rowKey(row);
77
- return row[rowKey] as string | number;
87
+ function legacyModes(): DataTableModes {
88
+ return {
89
+ filtering: modes?.filtering ?? 'local',
90
+ sorting: modes?.sorting ?? (manualSorting ? 'manual' : 'local'),
91
+ pagination: modes?.pagination ?? (manualPagination ? 'manual' : 'local'),
92
+ };
78
93
  }
79
94
 
80
- function getDisplayRowKey(row: T, index: number): string | number {
81
- return getRowKey(row, displayIndexOffset + index);
95
+ function legacyViewState(): Partial<DataTableViewState> {
96
+ return {
97
+ sorting:
98
+ sort.columnId && sort.direction
99
+ ? [{ columnId: sort.columnId, direction: sort.direction }]
100
+ : [],
101
+ page,
102
+ pageSize: pageSize ?? null,
103
+ columnOrder: columns.map((column) => column.id),
104
+ columnVisibility: columns.map((column) => ({
105
+ columnId: column.id,
106
+ visible: !visibleColumnIds || visibleColumnIds.has(column.id),
107
+ })),
108
+ selectedRowIds: [...selected],
109
+ expandedRowIds: [...expanded],
110
+ };
82
111
  }
83
112
 
84
- // Handle sort click
85
- function handleSort(column: DataTableColumn<T>) {
86
- if (!sortable || !column.sortable) return;
113
+ function mergedLegacyState(): Omit<DataTableViewState, 'selection'> {
114
+ const { selection: _selection, ...current } = localController.getState();
115
+ return { ...current, ...legacyViewState() };
116
+ }
87
117
 
88
- const newSort: SortState = {
89
- columnId: column.id,
90
- direction:
91
- sort.columnId === column.id
92
- ? sort.direction === 'asc'
93
- ? 'desc'
94
- : sort.direction === 'desc'
95
- ? null
96
- : 'asc'
97
- : 'asc',
98
- };
118
+ const localController = createDataTableController({
119
+ modes: legacyModes(),
120
+ onStateChange: (next, command) => onStateChange?.(next, command),
121
+ });
99
122
 
100
- if (newSort.direction === null) {
101
- newSort.columnId = null;
102
- }
123
+ let controllerSnapshot = $state<DataTableSnapshot>(localController.snapshot());
124
+ let publishedLegacySignature: string | undefined;
125
+ let localControllerInitialized = false;
103
126
 
104
- sort = newSort;
105
- onSortChange?.(newSort);
127
+ function activeController(): DataTableController {
128
+ return controller ?? localController;
106
129
  }
107
130
 
108
- // Handle row selection
109
- function handleRowSelect(key: string | number, event: Event) {
110
- event.stopPropagation();
111
- const newSelected = new Set(selected);
131
+ function legacySignature(): string {
132
+ const legacy = legacyViewState();
133
+ return JSON.stringify({
134
+ sorting: legacy.sorting,
135
+ page: legacy.page,
136
+ pageSize: legacy.pageSize,
137
+ columnVisibility: legacy.columnVisibility,
138
+ selectedRowIds: [...(legacy.selectedRowIds ?? [])].sort(),
139
+ expandedRowIds: [...(legacy.expandedRowIds ?? [])].sort(),
140
+ });
141
+ }
112
142
 
113
- if (newSelected.has(key)) {
114
- newSelected.delete(key);
115
- } else {
116
- newSelected.add(key);
143
+ function legacySort(next: DataTableViewState): SortState {
144
+ const rule = next.sorting[0];
145
+ return rule
146
+ ? { columnId: rule.columnId, direction: rule.direction }
147
+ : { columnId: null, direction: null };
148
+ }
149
+
150
+ function publishLegacyState(
151
+ next: DataTableViewState,
152
+ command: DataTableCommand,
153
+ previous: DataTableViewState,
154
+ ) {
155
+ const nextSort = legacySort(next);
156
+ const previousSort = legacySort(previous);
157
+ sort = nextSort;
158
+ page = next.page;
159
+ selected = new Set(next.selectedRowIds);
160
+ expanded = new Set(next.expandedRowIds);
161
+ publishedLegacySignature = legacySignature();
162
+
163
+ if (
164
+ nextSort.columnId !== previousSort.columnId ||
165
+ nextSort.direction !== previousSort.direction
166
+ ) {
167
+ onSortChange?.(nextSort);
168
+ }
169
+ if (
170
+ JSON.stringify(next.selectedRowIds) !==
171
+ JSON.stringify(previous.selectedRowIds)
172
+ ) {
173
+ onSelectionChange?.(new Set(next.selectedRowIds));
174
+ }
175
+ if (
176
+ JSON.stringify(next.expandedRowIds) !==
177
+ JSON.stringify(previous.expandedRowIds)
178
+ ) {
179
+ onExpandedChange?.(new Set(next.expandedRowIds));
180
+ }
181
+ if (next.page !== previous.page) onPageChange?.(next.page);
182
+ void command;
183
+ }
184
+
185
+ $effect(() => {
186
+ if (controller) return;
187
+
188
+ localController.setControlled(controlledState !== undefined);
189
+ localController.setModes(legacyModes());
190
+ localController.setColumnIds(columns.map((column) => column.id));
191
+
192
+ if (!localControllerInitialized) {
193
+ localControllerInitialized = true;
194
+ const nextState: DataTableViewStateInput = controlledState ?? {
195
+ ...mergedLegacyState(),
196
+ ...initialState,
197
+ };
198
+ localController.replaceState(nextState);
199
+ return;
200
+ }
201
+
202
+ if (controlledState !== undefined) {
203
+ localController.replaceState(controlledState);
204
+ return;
205
+ }
206
+
207
+ const signature = legacySignature();
208
+ if (signature === publishedLegacySignature) {
209
+ publishedLegacySignature = undefined;
210
+ return;
117
211
  }
212
+ localController.replaceState(mergedLegacyState());
213
+ });
214
+
215
+ $effect(() => {
216
+ const current = activeController();
217
+ current.setColumnIds(columns.map((column) => column.id));
218
+ controllerSnapshot = current.snapshot();
219
+ return current.subscribe((transition) => {
220
+ controllerSnapshot = transition.next;
221
+ if (
222
+ current === localController &&
223
+ controlledState === undefined &&
224
+ transition.command
225
+ ) {
226
+ publishLegacyState(
227
+ transition.next.state,
228
+ transition.command,
229
+ transition.previous.state,
230
+ );
231
+ }
232
+ });
233
+ });
118
234
 
119
- selected = newSelected;
120
- onSelectionChange?.(newSelected);
235
+ const tableState = $derived(controllerSnapshot.state);
236
+ const tableModes = $derived(controllerSnapshot.modes);
237
+ const requiresStableRowIdentity = $derived(
238
+ selectable ||
239
+ Boolean(expandedContent) ||
240
+ agentAddressable ||
241
+ tableModes.filtering === 'manual' ||
242
+ tableModes.sorting === 'manual' ||
243
+ tableModes.pagination === 'manual',
244
+ );
245
+ const sourceRows = $derived.by(() =>
246
+ resolveDataTableRows(data, rowKey, {
247
+ requireStableIdentity: requiresStableRowIdentity,
248
+ }),
249
+ );
250
+
251
+ function dispatch(command: DataTableCommand) {
252
+ activeController().dispatch(command);
253
+ }
254
+
255
+ function handleSort(column: DataTableColumn<T>, event: MouseEvent) {
256
+ if (!sortable || !column.sortable) return;
257
+ dispatch({
258
+ type: 'toggleSorting',
259
+ columnId: column.id,
260
+ multi: event.shiftKey,
261
+ });
262
+ }
263
+
264
+ function handleRowSelect(key: DataTableRowId, event: Event) {
265
+ event.stopPropagation();
266
+ dispatch({ type: 'toggleRowSelection', rowId: key });
121
267
  }
122
268
 
123
- // Handle select all
124
269
  function handleSelectAll() {
270
+ if (tableState.selection.scope === 'allMatching') {
271
+ dispatch({
272
+ type: 'setSelection',
273
+ selection: { scope: 'explicit', rowIds: [] },
274
+ });
275
+ return;
276
+ }
277
+ const selectedIds = new Set(tableState.selectedRowIds);
278
+ const visibleIds = displayRows.map(({ rowId }) => rowId);
279
+ if (tableState.selection.scope === 'page') {
280
+ dispatch({
281
+ type: 'setPageSelection',
282
+ rowIds: allSelected ? [] : visibleIds,
283
+ });
284
+ return;
285
+ }
125
286
  if (allSelected) {
126
- const visibleKeys = new Set(
127
- displayData.map((row, i) => getDisplayRowKey(row, i)),
128
- );
129
- selected = new Set([...selected].filter((key) => !visibleKeys.has(key)));
287
+ for (const key of visibleIds) selectedIds.delete(key);
130
288
  } else {
131
- selected = new Set([
132
- ...selected,
133
- ...displayData.map((row, i) => getDisplayRowKey(row, i)),
134
- ]);
289
+ for (const key of visibleIds) selectedIds.add(key);
135
290
  }
136
- onSelectionChange?.(selected);
291
+ dispatch({ type: 'setSelectedRows', rowIds: [...selectedIds] });
137
292
  }
138
293
 
139
- function handleExpanded(key: string | number, event: Event) {
294
+ function handleExpanded(key: DataTableRowId, event: Event) {
140
295
  event.stopPropagation();
141
- const next = new Set(expanded);
142
- next.has(key) ? next.delete(key) : next.add(key);
143
- expanded = next;
144
- onExpandedChange?.(next);
296
+ dispatch({ type: 'toggleRowExpansion', rowId: key });
145
297
  }
146
298
 
147
299
  function handlePageChange(next: number) {
148
- page = Math.min(Math.max(1, next), totalPages);
149
- onPageChange?.(page);
300
+ dispatch({ type: 'setPage', page: next });
150
301
  }
151
302
 
152
303
  // Handle row click
@@ -164,55 +315,190 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
164
315
  };
165
316
  }
166
317
 
167
- // Get visible columns
168
- const visibleColumns = $derived(
169
- columns.filter(
170
- (col) => !col.hidden && (!visibleColumnIds || visibleColumnIds.has(col.id)),
171
- ),
172
- );
318
+ const visibleColumns = $derived.by(() => {
319
+ const configuredOrder = new Map(
320
+ tableState.columnOrder.map((id, index) => [id, index]),
321
+ );
322
+ const visibility = new Map(
323
+ tableState.columnVisibility.map((entry) => [entry.columnId, entry.visible]),
324
+ );
325
+ return columns
326
+ .filter((column) => !column.hidden && visibility.get(column.id) !== false)
327
+ .slice()
328
+ .sort((left, right) => {
329
+ const leftOrder = configuredOrder.get(left.id) ?? Number.MAX_SAFE_INTEGER;
330
+ const rightOrder =
331
+ configuredOrder.get(right.id) ?? Number.MAX_SAFE_INTEGER;
332
+ return leftOrder - rightOrder;
333
+ });
334
+ });
335
+
336
+ function sameFilterValue(value: unknown, expected: unknown): boolean {
337
+ return Object.is(value, expected);
338
+ }
173
339
 
174
- const filteredData = $derived(filterFn ? data.filter(filterFn) : data);
340
+ function textValue(value: unknown): string {
341
+ return String(value ?? '').toLowerCase();
342
+ }
175
343
 
176
- // Sort data
177
- const sortedData = $derived.by(() => {
178
- if (manualSorting || !sort.columnId || !sort.direction) return filteredData;
344
+ function compareFilterValues(left: unknown, right: unknown): number {
345
+ const leftValue = left instanceof Date ? left.getTime() : left;
346
+ const rightValue = right instanceof Date ? right.getTime() : right;
347
+ if (typeof leftValue === 'number' && typeof rightValue === 'number')
348
+ return leftValue - rightValue;
349
+ const a = String(leftValue ?? '');
350
+ const b = String(rightValue ?? '');
351
+ return a < b ? -1 : a > b ? 1 : 0;
352
+ }
179
353
 
180
- const column = columns.find((c) => c.id === sort.columnId);
181
- if (!column) return filteredData;
354
+ function matchesFilter(
355
+ row: T,
356
+ column: DataTableColumn<T>,
357
+ filter: DataTableFilter,
358
+ ): boolean {
359
+ if (column.filterable === false) return true;
360
+ const value = getCellValue(row, column);
361
+ if (column.filterFn) return column.filterFn(row, value, filter);
362
+ const expected = filter.value;
363
+ const valueText = textValue(value);
364
+ const expectedText = textValue(expected);
365
+ switch (filter.operator) {
366
+ case 'equals':
367
+ return sameFilterValue(value, expected);
368
+ case 'notEquals':
369
+ return !sameFilterValue(value, expected);
370
+ case 'contains':
371
+ return valueText.includes(expectedText);
372
+ case 'notContains':
373
+ return !valueText.includes(expectedText);
374
+ case 'startsWith':
375
+ return valueText.startsWith(expectedText);
376
+ case 'endsWith':
377
+ return valueText.endsWith(expectedText);
378
+ case 'in':
379
+ return (
380
+ Array.isArray(expected) &&
381
+ expected.some((entry) => sameFilterValue(value, entry))
382
+ );
383
+ case 'notIn':
384
+ return (
385
+ Array.isArray(expected) &&
386
+ !expected.some((entry) => sameFilterValue(value, entry))
387
+ );
388
+ case 'gt':
389
+ return compareFilterValues(value, expected) > 0;
390
+ case 'gte':
391
+ return compareFilterValues(value, expected) >= 0;
392
+ case 'lt':
393
+ return compareFilterValues(value, expected) < 0;
394
+ case 'lte':
395
+ return compareFilterValues(value, expected) <= 0;
396
+ case 'isNull':
397
+ return value == null;
398
+ case 'isNotNull':
399
+ return value != null;
400
+ }
401
+ }
182
402
 
183
- const accessor = column.accessor ?? column.id;
184
- const direction = sort.direction;
403
+ const filteredRows = $derived.by(() => {
404
+ if (tableModes.filtering === 'manual') return sourceRows;
405
+ const search = tableState.search.toLowerCase();
406
+ return sourceRows.filter(({ row, sourceIndex }) => {
407
+ if (filterFn && !filterFn(row, sourceIndex)) return false;
408
+ if (
409
+ search &&
410
+ !columns.some(
411
+ (column) =>
412
+ column.searchable !== false &&
413
+ textValue(getCellValue(row, column)).includes(search),
414
+ )
415
+ ) {
416
+ return false;
417
+ }
418
+ return tableState.filters.every((filter) => {
419
+ const column = columns.find(
420
+ (candidate) => candidate.id === filter.columnId,
421
+ );
422
+ return Boolean(column && matchesFilter(row, column, filter));
423
+ });
424
+ });
425
+ });
185
426
 
186
- return [...filteredData].sort((a, b) => {
187
- if (column.sortFn) {
188
- return column.sortFn(a, b, direction);
427
+ const sortedRows = $derived.by(() => {
428
+ if (tableModes.sorting === 'manual' || tableState.sorting.length === 0)
429
+ return filteredRows;
430
+ return filteredRows.slice().sort((left, right) => {
431
+ for (const rule of tableState.sorting) {
432
+ const column = columns.find(
433
+ (candidate) => candidate.id === rule.columnId,
434
+ );
435
+ if (!column) continue;
436
+ const result = column.sortFn
437
+ ? column.sortFn(left.row, right.row, rule.direction)
438
+ : defaultSort(
439
+ left.row,
440
+ right.row,
441
+ String(column.accessor ?? column.id),
442
+ rule.direction,
443
+ );
444
+ if (result !== 0) return result;
189
445
  }
190
- return defaultSort(a, b, String(accessor), direction);
446
+ return rowKey
447
+ ? compareDataTableRowIds(left.rowId, right.rowId)
448
+ : left.sourceIndex - right.sourceIndex;
191
449
  });
192
450
  });
193
451
 
194
- const totalRowCount = $derived(totalRows ?? sortedData.length);
452
+ const totalRowCount = $derived(
453
+ tableModes.pagination === 'manual' ? totalRows : sortedRows.length,
454
+ );
195
455
  const totalPages = $derived(
196
- pageSize ? Math.max(1, Math.ceil(totalRowCount / pageSize)) : 1,
456
+ tableState.pageSize
457
+ ? totalRowCount === undefined
458
+ ? null
459
+ : Math.max(1, Math.ceil(totalRowCount / tableState.pageSize))
460
+ : 1,
197
461
  );
198
- const displayData = $derived.by(() => {
199
- if (!pageSize || manualPagination) return sortedData;
200
- const start = (page - 1) * pageSize;
201
- return sortedData.slice(start, start + pageSize);
462
+ const displayRows = $derived.by(() => {
463
+ if (!tableState.pageSize || tableModes.pagination === 'manual')
464
+ return sortedRows;
465
+ const start = (tableState.page - 1) * tableState.pageSize;
466
+ return sortedRows.slice(start, start + tableState.pageSize);
202
467
  });
203
- const displayIndexOffset = $derived(pageSize ? (page - 1) * pageSize : 0);
204
468
 
205
469
  $effect(() => {
206
- if (page > totalPages) handlePageChange(totalPages);
470
+ const total = totalRows;
471
+ if (total === undefined) return;
472
+ if (tableModes.pagination !== 'manual') {
473
+ throw new TypeError(
474
+ 'DataTable totalRows is only valid when pagination mode is manual',
475
+ );
476
+ }
477
+ if (!Number.isFinite(total) || !Number.isInteger(total) || total < 0) {
478
+ throw new TypeError(
479
+ 'DataTable totalRows must be a non-negative integer when supplied',
480
+ );
481
+ }
207
482
  });
208
483
 
209
- // Selection state
484
+ $effect(() => {
485
+ void tableState.page;
486
+ void tableState.pageSize;
487
+ activeController().clampPage(totalRowCount);
488
+ });
489
+
490
+ const selectedIds = $derived(new Set(tableState.selectedRowIds));
491
+ const expandedIds = $derived(new Set(tableState.expandedRowIds));
492
+ const currentSort = $derived(legacySort(tableState));
493
+
210
494
  const allSelected = $derived(
211
- displayData.length > 0 &&
212
- displayData.every((row, i) => selected.has(getDisplayRowKey(row, i))),
495
+ tableState.selection.scope === 'allMatching' ||
496
+ (displayRows.length > 0 &&
497
+ displayRows.every(({ rowId }) => selectedIds.has(rowId))),
213
498
  );
214
499
  const someSelected = $derived(
215
- displayData.some((row, i) => selected.has(getDisplayRowKey(row, i))) &&
500
+ tableState.selection.scope !== 'allMatching' &&
501
+ displayRows.some(({ rowId }) => selectedIds.has(rowId)) &&
216
502
  !allSelected,
217
503
  );
218
504
 
@@ -220,13 +506,11 @@ const columnCount = $derived(
220
506
  visibleColumns.length + (selectable ? 1 : 0) + (expandedContent ? 1 : 0),
221
507
  );
222
508
 
223
- // Get cell value
224
509
  function getCellValue(row: T, column: DataTableColumn<T>): unknown {
225
510
  const accessor = column.accessor ?? column.id;
226
511
  return getNestedValue(row, String(accessor));
227
512
  }
228
513
 
229
- // Size classes
230
514
  const sizeClasses = {
231
515
  sm: 'data-table--sm',
232
516
  md: 'data-table--md',
@@ -257,7 +541,7 @@ const sizeClasses = {
257
541
  checked={allSelected}
258
542
  use:setIndeterminate={someSelected}
259
543
  onchange={handleSelectAll}
260
- aria-label={t(M['ui.data_table.select_all'])}
544
+ aria-label={t(M['ui.data_table.select_current_page'])}
261
545
  class="data-table__checkbox"
262
546
  />
263
547
  </th>
@@ -267,14 +551,14 @@ const sizeClasses = {
267
551
  <th
268
552
  class="data-table__cell data-table__cell--header"
269
553
  class:data-table__cell--sortable={sortable && column.sortable}
270
- class:data-table__cell--sorted={sort.columnId === column.id}
554
+ class:data-table__cell--sorted={currentSort.columnId === column.id}
271
555
  style:width={column.width}
272
556
  style:min-width={column.minWidth}
273
557
  style:max-width={column.maxWidth}
274
558
  style:text-align={column.align}
275
559
  scope="col"
276
- aria-sort={sort.columnId === column.id
277
- ? sort.direction === 'asc'
560
+ aria-sort={currentSort.columnId === column.id
561
+ ? currentSort.direction === 'asc'
278
562
  ? 'ascending'
279
563
  : 'descending'
280
564
  : undefined}
@@ -285,12 +569,12 @@ const sizeClasses = {
285
569
  <button
286
570
  type="button"
287
571
  class="data-table__sort-button"
288
- onclick={() => handleSort(column)}
572
+ onclick={(event) => handleSort(column, event)}
289
573
  >
290
574
  <span>{column.label}</span>
291
575
  <span class="data-table__sort-icon" aria-hidden="true">
292
- {#if sort.columnId === column.id}
293
- {sort.direction === 'asc' ? '↑' : '↓'}
576
+ {#if currentSort.columnId === column.id}
577
+ {currentSort.direction === 'asc' ? '↑' : '↓'}
294
578
  {:else}
295
579
 
296
580
  {/if}
@@ -317,7 +601,7 @@ const sizeClasses = {
317
601
  </div>
318
602
  </td>
319
603
  </tr>
320
- {:else if displayData.length === 0}
604
+ {:else if displayRows.length === 0}
321
605
  <tr class="data-table__row data-table__row--empty">
322
606
  <td
323
607
  class="data-table__cell data-table__cell--empty"
@@ -333,10 +617,11 @@ const sizeClasses = {
333
617
  </td>
334
618
  </tr>
335
619
  {:else}
336
- {#each displayData as row, index (getDisplayRowKey(row, index))}
337
- {@const key = getDisplayRowKey(row, index)}
338
- {@const isSelected = selected.has(key)}
339
- {@const isExpanded = expanded.has(key)}
620
+ {#each displayRows as entry, index (entry.rowId)}
621
+ {@const row = entry.row}
622
+ {@const key = entry.rowId}
623
+ {@const isSelected = tableState.selection.scope === 'allMatching' || selectedIds.has(key)}
624
+ {@const isExpanded = expandedIds.has(key)}
340
625
  {@const rowCanExpand = canExpand?.(row, index) ?? true}
341
626
  <tr
342
627
  class="data-table__row {rowClass?.(row, index) ?? ''}"
@@ -361,6 +646,7 @@ const sizeClasses = {
361
646
  <input
362
647
  type="checkbox"
363
648
  checked={isSelected}
649
+ disabled={tableState.selection.scope === 'allMatching'}
364
650
  onchange={(e) => handleRowSelect(key, e)}
365
651
  aria-label={t(M['ui.data_table.select_row'])}
366
652
  class="data-table__checkbox"
@@ -393,11 +679,11 @@ const sizeClasses = {
393
679
  {/if}
394
680
  </tbody>
395
681
  {#if footer}
396
- <tfoot><tr><td class="data-table__cell data-table__footer" colspan={columnCount}>{@render footer({ rows: displayData })}</td></tr></tfoot>
682
+ <tfoot><tr><td class="data-table__cell data-table__footer" colspan={columnCount}>{@render footer({ rows: displayRows.map(({ row }) => row) })}</td></tr></tfoot>
397
683
  {/if}
398
684
  </table>
399
685
  </div>
400
- {#if pageSize && totalPages > 1}<Pagination currentPage={page} {totalPages} onPageChange={handlePageChange} aria-label="Table pages" />{/if}
686
+ {#if tableState.pageSize && totalPages && totalPages > 1}<Pagination currentPage={tableState.page} {totalPages} onPageChange={handlePageChange} aria-label="Table pages" />{/if}
401
687
 
402
688
  <style>
403
689
  .data-table-container {
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAGf,MAAM,YAAY,CAAC;AAIpB,UAAU,aAAa,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClD,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CACZ;QAAC;YAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;YAAC,GAAG,EAAE,CAAC,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE;KAAC,CACxE,CAAC;CACH;AAAC,iBAAS,QAAQ,CAAC,CAAC;WA6UQ,aAAa,CAAC,CAAC,CAAC;;;;;EAAgH;AAC7J,cAAM,iBAAiB,CAAC,CAAC;IACrB,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5X,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3H,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,SAAS,EAAE,qBAAmC,CAAC;AACnC,KAAK,SAAS,CAAC,CAAC,IAAI,YAAY,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"DataTable.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAkBtC,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAa,MAAM,YAAY,CAAC;AAI7E,UAAU,aAAa,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClD,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CACZ;QAAC;YAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;YAAC,GAAG,EAAE,CAAC,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE;KAAC,CACxE,CAAC;CACH;AAAC,iBAAS,QAAQ,CAAC,CAAC;WAomBQ,aAAa,CAAC,CAAC,CAAC;;;;;EAAgH;AAC7J,cAAM,iBAAiB,CAAC,CAAC;IACrB,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5X,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3H,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,SAAS,EAAE,qBAAmC,CAAC;AACnC,KAAK,SAAS,CAAC,CAAC,IAAI,YAAY,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,eAAe,SAAS,CAAC"}