@eifi1/ui-kit 0.48.0 → 0.48.2
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 +4 -3
- package/dist/components/data-table-fit.d.ts +8 -1
- package/dist/components/data-table-fit.js +7 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-groups.d.ts +3 -1
- package/dist/components/data-table-groups.js +11 -5
- package/dist/components/data-table-groups.js.map +1 -1
- package/dist/components/data-table-head.d.ts +8 -1
- package/dist/components/data-table-head.js +11 -3
- package/dist/components/data-table-head.js.map +1 -1
- package/dist/components/data-table-leading-row.d.ts +3 -1
- package/dist/components/data-table-leading-row.js +2 -1
- package/dist/components/data-table-leading-row.js.map +1 -1
- package/dist/components/data-table-row-actions.js +2 -2
- package/dist/components/data-table-row-actions.js.map +1 -1
- package/dist/components/data-table-row.d.ts +84 -0
- package/dist/components/data-table-row.js +261 -0
- package/dist/components/data-table-row.js.map +1 -0
- package/dist/components/data-table-selection.d.ts +3 -0
- package/dist/components/data-table-selection.js +12 -1
- package/dist/components/data-table-selection.js.map +1 -1
- package/dist/components/data-table-virtual.d.ts +98 -0
- package/dist/components/data-table-virtual.js +369 -0
- package/dist/components/data-table-virtual.js.map +1 -0
- package/dist/components/data-table.d.ts +58 -2
- package/dist/components/data-table.js +227 -230
- package/dist/components/data-table.js.map +1 -1
- package/dist/data-table.d.ts +1 -0
- package/dist/data-table.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/hooks/use-anchored-panel.js +2 -1
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/shell/app-shell.js +7 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-table-fit.ts +17 -2
- package/src/components/data-table-groups.tsx +15 -4
- package/src/components/data-table-head.tsx +25 -2
- package/src/components/data-table-leading-row.tsx +4 -1
- package/src/components/data-table-row-actions.tsx +3 -2
- package/src/components/data-table-row.tsx +483 -0
- package/src/components/data-table-selection.ts +17 -1
- package/src/components/data-table-virtual.ts +547 -0
- package/src/components/data-table.tsx +326 -327
- package/src/data-table.ts +2 -0
- package/src/hooks/use-anchored-panel.ts +9 -1
- package/src/shell/app-shell.tsx +7 -1
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { createElement } from "react";
|
|
4
3
|
import { Fragment as Fragment2, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
4
|
import { Card } from "./card.js";
|
|
6
5
|
import { Spinner } from "./spinner.js";
|
|
7
6
|
import { isTableOwnColumn, useRowActionColumn } from "./data-table-row-actions.js";
|
|
8
7
|
import { useColumnResize } from "./data-table-resize.js";
|
|
9
8
|
import { useRangeSelection } from "./data-table-selection.js";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
columnLabel,
|
|
14
|
-
fromOutside,
|
|
15
|
-
fromOwnControl,
|
|
16
|
-
logicalAlign,
|
|
17
|
-
resolveDataTableLabels,
|
|
18
|
-
splitCellProps
|
|
19
|
-
} from "./data-table-shared.js";
|
|
20
|
-
import { MobileFilters, MobileRow, MobileSelectBar, MobileSort, StackedFields } from "./data-table-mobile.js";
|
|
9
|
+
import { columnLabel, logicalAlign, resolveDataTableLabels } from "./data-table-shared.js";
|
|
10
|
+
import { MobileFilters, MobileSelectBar, MobileSort, StackedFields } from "./data-table-mobile.js";
|
|
11
|
+
import { DataTableMobileRow, DataTableRow } from "./data-table-row.js";
|
|
21
12
|
import { DataTableHead } from "./data-table-head.js";
|
|
22
13
|
import { DataTableLeadingRow } from "./data-table-leading-row.js";
|
|
23
14
|
import {
|
|
@@ -27,6 +18,7 @@ import {
|
|
|
27
18
|
groupRows,
|
|
28
19
|
useGroupBandTops
|
|
29
20
|
} from "./data-table-groups.js";
|
|
21
|
+
import { VIRTUAL_SELECT_COL, rowNavTarget, useRowWindow } from "./data-table-virtual.js";
|
|
30
22
|
import { ColumnSettingsPanel } from "./data-table-column-settings.js";
|
|
31
23
|
import { useLargeText } from "../hooks/use-large-text.js";
|
|
32
24
|
import { cn } from "../lib/cn.js";
|
|
@@ -48,21 +40,11 @@ const DEFAULT_DATA_TABLE_SORT_LABELS = {
|
|
|
48
40
|
sortDescending: DEFAULT_DATA_TABLE_LABELS.sortDescending
|
|
49
41
|
};
|
|
50
42
|
const flipDir = (d) => d === "asc" ? "desc" : "asc";
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
(body) => Array.from(body.children).filter(
|
|
57
|
-
(el) => el instanceof HTMLElement && el.hasAttribute("data-row-nav")
|
|
58
|
-
)
|
|
59
|
-
);
|
|
60
|
-
const i = rows.indexOf(from);
|
|
61
|
-
const target = key === "ArrowDown" ? rows[i + 1] : key === "ArrowUp" ? rows[i - 1] : key === "Home" ? rows[0] : key === "End" ? rows[rows.length - 1] : void 0;
|
|
62
|
-
target?.focus();
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
const ROW_NAV_KEYS = { ArrowDown: 1, ArrowUp: 1, Home: 1, End: 1 };
|
|
43
|
+
const NO_BANDS = [];
|
|
44
|
+
const BAND_1 = [1];
|
|
45
|
+
const BAND_2 = [2];
|
|
46
|
+
const BAND_1_2 = [1, 2];
|
|
47
|
+
const NO_VIRTUAL_OPTIONS = {};
|
|
66
48
|
import { DEFAULT_PERSIST_PREFIX, useTableState } from "./use-table-state.js";
|
|
67
49
|
import { useMobileReveal } from "./use-mobile-reveal.js";
|
|
68
50
|
import { GROW_CELL_CLASS, GROW_PEER_CELL_CLASS, useColumnFit } from "./data-table-fit.js";
|
|
@@ -84,6 +66,7 @@ function DataTable({
|
|
|
84
66
|
fillHeight = false,
|
|
85
67
|
maxBodyHeight = "calc(100dvh - 12rem)",
|
|
86
68
|
serverPagination,
|
|
69
|
+
serverRows: serverRowsProp,
|
|
87
70
|
filters: filtersProp,
|
|
88
71
|
onFiltersChange,
|
|
89
72
|
sorts: sortsProp,
|
|
@@ -108,6 +91,7 @@ function DataTable({
|
|
|
108
91
|
leadingRowSticky = false,
|
|
109
92
|
groupBy,
|
|
110
93
|
loadMore,
|
|
94
|
+
virtualize = false,
|
|
111
95
|
density = "comfortable",
|
|
112
96
|
sortCycle = "tri",
|
|
113
97
|
chrome = "full",
|
|
@@ -129,6 +113,7 @@ function DataTable({
|
|
|
129
113
|
const resizable = resizableProp ?? !minimal;
|
|
130
114
|
const multiSort = multiSortProp ?? !minimal;
|
|
131
115
|
const isServer = !!serverPagination;
|
|
116
|
+
const serverRows = isServer || (serverRowsProp ?? !!loadMore);
|
|
132
117
|
const isLoading = !!serverPagination?.isLoading;
|
|
133
118
|
const labelOverrides = useKitLabelOverrides("dataTable");
|
|
134
119
|
const providerStorageKeyPrefix = useKitTableStorageKeyPrefix();
|
|
@@ -210,7 +195,7 @@ function DataTable({
|
|
|
210
195
|
return map;
|
|
211
196
|
}, [columnSig, selectOptionsSig, rows]);
|
|
212
197
|
const filtered = useMemo(() => {
|
|
213
|
-
if (
|
|
198
|
+
if (serverRows) return rows;
|
|
214
199
|
let result = rows;
|
|
215
200
|
for (const col of columns) {
|
|
216
201
|
const state = filters[col.key];
|
|
@@ -218,9 +203,9 @@ function DataTable({
|
|
|
218
203
|
result = result.filter((row) => rowMatches(col, row, state, locale));
|
|
219
204
|
}
|
|
220
205
|
return result;
|
|
221
|
-
}, [rows, columnSig, filters,
|
|
206
|
+
}, [rows, columnSig, filters, serverRows, locale]);
|
|
222
207
|
const sorted = useMemo(() => {
|
|
223
|
-
if (
|
|
208
|
+
if (serverRows) return filtered;
|
|
224
209
|
const chain = sorts.map((s) => {
|
|
225
210
|
const col = columns.find((c) => c.key === s.key);
|
|
226
211
|
return col?.sortBy ? { sortBy: col.sortBy, dir: s.dir } : null;
|
|
@@ -240,8 +225,8 @@ function DataTable({
|
|
|
240
225
|
return 0;
|
|
241
226
|
});
|
|
242
227
|
return copy;
|
|
243
|
-
}, [filtered, sorts, columnSig,
|
|
244
|
-
const unpaged = !isServer && (!paginated || !!loadMore);
|
|
228
|
+
}, [filtered, sorts, columnSig, serverRows]);
|
|
229
|
+
const unpaged = !isServer && (!paginated || !!loadMore || serverRows);
|
|
245
230
|
const effectivePageSize = isServer ? serverPagination.pageSize : unpaged || pageSize === Infinity ? sorted.length || 1 : pageSize;
|
|
246
231
|
const paginationTotal = isServer ? serverPagination.total : sorted.length;
|
|
247
232
|
const paginationPageSize = isServer ? serverPagination.pageSize : pageSize;
|
|
@@ -289,7 +274,7 @@ function DataTable({
|
|
|
289
274
|
setPage(0);
|
|
290
275
|
};
|
|
291
276
|
const clearAllFilters = () => {
|
|
292
|
-
const keys = columns.filter((col) => !
|
|
277
|
+
const keys = columns.filter((col) => !serverRows || onFiltersChange ? resolveFilter(col) : null).map((col) => col.key);
|
|
293
278
|
if (!keys.length) return;
|
|
294
279
|
if (onFiltersChange) {
|
|
295
280
|
const rest = { ...filters };
|
|
@@ -309,20 +294,23 @@ function DataTable({
|
|
|
309
294
|
useEffect(() => {
|
|
310
295
|
if (announcedFilterKey.current === filterKey) return;
|
|
311
296
|
announcedFilterKey.current = filterKey;
|
|
312
|
-
if (
|
|
297
|
+
if (serverRows) return;
|
|
313
298
|
announce(labels.filterResults(filtered.length, rows.length));
|
|
314
|
-
}, [filterKey, filtered.length, rows.length,
|
|
299
|
+
}, [filterKey, filtered.length, rows.length, serverRows, announce, labels]);
|
|
315
300
|
const goToPage = (p) => {
|
|
316
301
|
if (isServer) serverPagination.onPageChange(p);
|
|
317
302
|
else setPage(p);
|
|
318
303
|
announce(labels.pageChanged(p + 1, totalPages));
|
|
319
304
|
};
|
|
305
|
+
const large = useLargeText();
|
|
320
306
|
const { autoHidden, keep: keepColumn } = useColumnFit({
|
|
321
307
|
columns,
|
|
322
308
|
hiddenCols,
|
|
323
309
|
headRefs,
|
|
324
310
|
scroller: () => desktopScroller.current,
|
|
325
|
-
enabled: !usePhoneLayout()
|
|
311
|
+
enabled: !usePhoneLayout(),
|
|
312
|
+
// Measured only when one of these changed (0.48.2): not on a ticked box.
|
|
313
|
+
content: [slice, columns, hiddenCols, widths, density, large]
|
|
326
314
|
});
|
|
327
315
|
const visibleColumns = useMemo(
|
|
328
316
|
() => columns.filter((c) => !hiddenCols.has(c.key) && !autoHidden.has(c.key)),
|
|
@@ -362,11 +350,13 @@ function DataTable({
|
|
|
362
350
|
return () => ro.disconnect();
|
|
363
351
|
}, [measuresVisibleWidth]);
|
|
364
352
|
const edgeFadeProps = useEdgeFade(desktopScroller, edgeFade && isMdUp);
|
|
365
|
-
const mobileColumns = visibleColumns.filter((c) => !c.mobileHidden);
|
|
353
|
+
const mobileColumns = useMemo(() => visibleColumns.filter((c) => !c.mobileHidden), [visibleColumns]);
|
|
366
354
|
const mobilePrimaryCol = mobileColumns.find((c) => c.mobilePrimary) ?? mobileColumns[0] ?? null;
|
|
367
|
-
const mobileSecondaryColumns =
|
|
355
|
+
const mobileSecondaryColumns = useMemo(
|
|
356
|
+
() => mobileColumns.filter((c) => c !== mobilePrimaryCol),
|
|
357
|
+
[mobileColumns, mobilePrimaryCol]
|
|
358
|
+
);
|
|
368
359
|
const mobileDetailColumns = mobileDetailsInRow ? visibleColumns.filter((c) => c.mobileHidden) : [];
|
|
369
|
-
const large = useLargeText();
|
|
370
360
|
const opensRow = !!expandedRow || mobileDetailColumns.length > 0;
|
|
371
361
|
const openedRowContent = (row) => {
|
|
372
362
|
const detail = expandedRow?.(row) ?? null;
|
|
@@ -415,7 +405,7 @@ function DataTable({
|
|
|
415
405
|
if (!anySelected) setPhoneSelectMode(false);
|
|
416
406
|
}
|
|
417
407
|
const phoneSelecting = !!selection && !isMdUp && (phoneSelectMode || anySelected);
|
|
418
|
-
const {
|
|
408
|
+
const { canSelect, selectRange, setAnchor, markRangeClick, takeRangeClick } = useRangeSelection({
|
|
419
409
|
selection,
|
|
420
410
|
slice,
|
|
421
411
|
rowKey
|
|
@@ -423,49 +413,73 @@ function DataTable({
|
|
|
423
413
|
const rowsFocusable = !!onRowClick;
|
|
424
414
|
const [focusRowKey, setFocusRowKey] = useState(null);
|
|
425
415
|
const tabRowKey = focusRowKey !== null && slice.some((r) => rowKey(r) === focusRowKey) ? focusRowKey : slice.length ? rowKey(slice[0]) : null;
|
|
416
|
+
const virtualOn = !!virtualize && isMdUp && slice.length > 0;
|
|
417
|
+
const focusRowRef = useRef(void 0);
|
|
418
|
+
const latestRowCtx = {
|
|
419
|
+
moveFocus: virtualOn ? (from, key) => {
|
|
420
|
+
const target = rowNavTarget(from, key, slice.length);
|
|
421
|
+
if (target === null) return false;
|
|
422
|
+
focusRowRef.current?.(target);
|
|
423
|
+
return true;
|
|
424
|
+
} : void 0,
|
|
425
|
+
onRowClick,
|
|
426
|
+
onToggle: selection?.onToggle,
|
|
427
|
+
isSelected: (row) => !!selection?.isSelected(row),
|
|
428
|
+
canSelect,
|
|
429
|
+
selectRange,
|
|
430
|
+
setAnchor,
|
|
431
|
+
markRangeClick,
|
|
432
|
+
takeRangeClick,
|
|
433
|
+
setFocusRowKey,
|
|
434
|
+
onLongPress: (row) => {
|
|
435
|
+
setPhoneSelectMode(true);
|
|
436
|
+
setAnchor(rowKey(row));
|
|
437
|
+
if (selection && !selection.isSelected(row)) selection.onToggle(row, true);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
const rowCtx = useRef(latestRowCtx);
|
|
441
|
+
useLayoutEffect(() => {
|
|
442
|
+
rowCtx.current = latestRowCtx;
|
|
443
|
+
});
|
|
426
444
|
const mobileDialogRow = mobileExpandAsDialog && !isMdUp ? mobileSlice.find((r) => isExpanded?.(r)) : void 0;
|
|
427
445
|
const mobileDialogContent = mobileDialogRow ? openedRowContent(mobileDialogRow) : null;
|
|
428
446
|
const dialogOpen = !!(mobileDialogRow && mobileDialogContent);
|
|
429
447
|
const closeDialog = () => {
|
|
430
448
|
if (mobileDialogRow) onRowClick?.(mobileDialogRow);
|
|
431
449
|
};
|
|
432
|
-
const renderMobileRow = (row) =>
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
450
|
+
const renderMobileRow = (row) => {
|
|
451
|
+
const key = rowKey(row);
|
|
452
|
+
const expanded = isExpanded?.(row) ?? false;
|
|
453
|
+
return /* @__PURE__ */ jsx(
|
|
454
|
+
DataTableMobileRow,
|
|
455
|
+
{
|
|
456
|
+
ctx: rowCtx,
|
|
457
|
+
rowKey: key,
|
|
458
|
+
row,
|
|
459
|
+
expanded,
|
|
460
|
+
expansion: expanded ? openedRowContent(row) : null,
|
|
461
|
+
opensRow,
|
|
462
|
+
className: rowClassName?.(row),
|
|
463
|
+
attrs: rowAttributes?.(row),
|
|
464
|
+
interactive: !!onRowClick,
|
|
465
|
+
href: mobileCardLinkable ? rowHref?.(row) : void 0,
|
|
466
|
+
swipeActionsFor,
|
|
467
|
+
mobileDir,
|
|
468
|
+
mobileCardLinkable,
|
|
469
|
+
mobileCard,
|
|
470
|
+
mobilePrimaryCol,
|
|
471
|
+
mobileSecondaryColumns,
|
|
472
|
+
mobileExpandAsDialog,
|
|
473
|
+
compact,
|
|
474
|
+
large,
|
|
475
|
+
selectionOn: !!selection,
|
|
476
|
+
selectActive: phoneSelecting,
|
|
454
477
|
selectable: canSelect(row),
|
|
455
|
-
selected: selection.isSelected(row)
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
onLongPress: () => {
|
|
461
|
-
setPhoneSelectMode(true);
|
|
462
|
-
selectionAnchor.current = rowKey(row);
|
|
463
|
-
if (!selection.isSelected(row)) selection.onToggle(row, true);
|
|
464
|
-
}
|
|
465
|
-
} : null
|
|
466
|
-
},
|
|
467
|
-
rowKey(row)
|
|
468
|
-
);
|
|
478
|
+
selected: !!selection && selection.isSelected(row)
|
|
479
|
+
},
|
|
480
|
+
key
|
|
481
|
+
);
|
|
482
|
+
};
|
|
469
483
|
const tableRef = useRef(null);
|
|
470
484
|
const desktopGroups = isMdUp && levels.length > 0 ? groupRows(slice, levels) : null;
|
|
471
485
|
const bandTops = useGroupBandTops(
|
|
@@ -473,6 +487,51 @@ function DataTable({
|
|
|
473
487
|
!!desktopGroups,
|
|
474
488
|
`${levels.length}:${leadingRowSticky && !!leadingRow}:${desktopGroups?.[0]?.key ?? ""}`
|
|
475
489
|
);
|
|
490
|
+
const virtualGroups = [];
|
|
491
|
+
const virtualBands = [];
|
|
492
|
+
if (virtualOn) {
|
|
493
|
+
if (!desktopGroups) virtualGroups.push({ start: 0, end: slice.length, bands: NO_BANDS, first: 0 });
|
|
494
|
+
else
|
|
495
|
+
for (const g1 of desktopGroups) {
|
|
496
|
+
const first = virtualGroups.length;
|
|
497
|
+
if (!g1.children) {
|
|
498
|
+
virtualGroups.push({ start: g1.start, end: g1.start + g1.rows.length, bands: BAND_1, first });
|
|
499
|
+
virtualBands.push({ g1, g2: null });
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
g1.children.forEach((g2, j) => {
|
|
503
|
+
virtualGroups.push({ start: g2.start, end: g2.start + g2.rows.length, bands: j === 0 ? BAND_1_2 : BAND_2, first });
|
|
504
|
+
virtualBands.push({ g1, g2 });
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const expandedIndices = [];
|
|
509
|
+
if (virtualOn && isExpanded && expandedRow) slice.forEach((r, i) => isExpanded(r) && expandedIndices.push(i));
|
|
510
|
+
const virtualColKeys = [...selection ? [VIRTUAL_SELECT_COL] : [], ...visibleColumns.map((c) => c.key)];
|
|
511
|
+
const virtualLockable = new Set(
|
|
512
|
+
virtualColKeys.filter((k) => !widths[k] && !visibleColumns.some((c) => c.key === k && c.grow))
|
|
513
|
+
);
|
|
514
|
+
const rowWindow = useRowWindow({
|
|
515
|
+
enabled: virtualOn,
|
|
516
|
+
rows: slice,
|
|
517
|
+
rowKey,
|
|
518
|
+
groups: virtualGroups,
|
|
519
|
+
expanded: expandedIndices,
|
|
520
|
+
pinnedKeys: [tabRowKey],
|
|
521
|
+
scrollerRef: desktopScroller,
|
|
522
|
+
tableRef,
|
|
523
|
+
options: typeof virtualize === "object" ? virtualize : NO_VIRTUAL_OPTIONS,
|
|
524
|
+
compact,
|
|
525
|
+
rowsBefore: 1 + (leadingRow ? 1 : 0),
|
|
526
|
+
rowsAfter: showFooter ? 1 : 0,
|
|
527
|
+
colKeys: virtualColKeys,
|
|
528
|
+
lockable: virtualLockable,
|
|
529
|
+
resetKey: `${Object.entries(widths).join(";")}|${density}|${large}|${slice.length}:${slice.length ? `${rowKey(slice[0])}:${rowKey(slice[slice.length - 1])}` : ""}`
|
|
530
|
+
});
|
|
531
|
+
const focusRowAt = rowWindow?.focusRow;
|
|
532
|
+
useLayoutEffect(() => {
|
|
533
|
+
focusRowRef.current = focusRowAt;
|
|
534
|
+
}, [focusRowAt]);
|
|
476
535
|
const mobileLevel = typeof mobileGroupBy === "function" ? null : mobileGroupBy ?? null;
|
|
477
536
|
const mobileKey = typeof mobileGroupBy === "function" ? mobileGroupBy : mobileGroupBy?.key;
|
|
478
537
|
const mobileGroups = mobileKey ? mobileSlice.reduce((acc, row) => {
|
|
@@ -515,13 +574,13 @@ function DataTable({
|
|
|
515
574
|
}
|
|
516
575
|
),
|
|
517
576
|
!isMdUp && /* @__PURE__ */ jsxs("div", { ref: mobileRootRef, className: cn(fillHeight && "flex min-h-0 flex-1 flex-col"), children: [
|
|
518
|
-
(!
|
|
577
|
+
(!serverRows || onFiltersChange) && /* @__PURE__ */ jsx(
|
|
519
578
|
MobileFilters,
|
|
520
579
|
{
|
|
521
580
|
columns,
|
|
522
581
|
filters,
|
|
523
582
|
selectOptionsByKey,
|
|
524
|
-
isServer,
|
|
583
|
+
isServer: serverRows,
|
|
525
584
|
hasFilterCallback: !!onFiltersChange,
|
|
526
585
|
onSetFilter: setFilterValue,
|
|
527
586
|
onClearFilter: clearFilter,
|
|
@@ -533,7 +592,7 @@ function DataTable({
|
|
|
533
592
|
mobileSort && /* @__PURE__ */ jsx(
|
|
534
593
|
MobileSort,
|
|
535
594
|
{
|
|
536
|
-
columns: visibleColumns.filter((c) => (!
|
|
595
|
+
columns: visibleColumns.filter((c) => (!serverRows || !!onSortsChange) && !!c.sortBy),
|
|
537
596
|
sorts,
|
|
538
597
|
sortCycle,
|
|
539
598
|
compact,
|
|
@@ -702,7 +761,13 @@ function DataTable({
|
|
|
702
761
|
"data-fit-grow": growDrawn ? "" : void 0,
|
|
703
762
|
"aria-label": labels.table,
|
|
704
763
|
"aria-busy": isLoading || void 0,
|
|
764
|
+
"aria-rowcount": rowWindow?.rowCount,
|
|
765
|
+
"data-virtualized": rowWindow ? "" : void 0,
|
|
705
766
|
children: [
|
|
767
|
+
rowWindow && /* @__PURE__ */ jsx("colgroup", { children: virtualColKeys.map((key) => {
|
|
768
|
+
const w = rowWindow.colWidths?.[key];
|
|
769
|
+
return /* @__PURE__ */ jsx("col", { style: w !== void 0 ? { width: w } : void 0 }, key);
|
|
770
|
+
}) }),
|
|
706
771
|
/* @__PURE__ */ jsx(
|
|
707
772
|
DataTableHead,
|
|
708
773
|
{
|
|
@@ -711,7 +776,7 @@ function DataTable({
|
|
|
711
776
|
compact,
|
|
712
777
|
labels,
|
|
713
778
|
locale,
|
|
714
|
-
isServer,
|
|
779
|
+
isServer: serverRows,
|
|
715
780
|
hasSortCallback: !!onSortsChange,
|
|
716
781
|
hasFilterCallback: !!onFiltersChange,
|
|
717
782
|
sorts,
|
|
@@ -727,154 +792,58 @@ function DataTable({
|
|
|
727
792
|
clearFilter,
|
|
728
793
|
startResize,
|
|
729
794
|
moveResize,
|
|
730
|
-
finishResize
|
|
795
|
+
finishResize,
|
|
796
|
+
ariaRowIndex: rowWindow ? 1 : void 0,
|
|
797
|
+
lockedWidths: rowWindow?.colWidths,
|
|
798
|
+
selectionLockKey: VIRTUAL_SELECT_COL
|
|
731
799
|
}
|
|
732
800
|
),
|
|
733
801
|
(() => {
|
|
734
802
|
const bodyClass = cn(isLoading && slice.length > 0 && "opacity-60 transition-opacity");
|
|
735
|
-
const leading = leadingRow ? /* @__PURE__ */ jsx(
|
|
803
|
+
const leading = leadingRow ? /* @__PURE__ */ jsx(
|
|
804
|
+
DataTableLeadingRow,
|
|
805
|
+
{
|
|
806
|
+
colSpan: totalColSpan,
|
|
807
|
+
sticky: leadingRowSticky,
|
|
808
|
+
ariaRowIndex: rowWindow ? 2 : void 0,
|
|
809
|
+
children: leadingRow
|
|
810
|
+
}
|
|
811
|
+
) : null;
|
|
736
812
|
const renderRow = (row, rowIndex) => {
|
|
737
813
|
const expanded = isExpanded?.(row) ?? false;
|
|
738
|
-
const expansion = expanded ? expandedRow?.(row) : null;
|
|
739
|
-
const rowInteractive = !!onRowClick || !!selection;
|
|
740
|
-
const href = rowHref?.(row);
|
|
741
814
|
const key = rowKey(row);
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
"button",
|
|
815
|
+
return /* @__PURE__ */ jsx(
|
|
816
|
+
DataTableRow,
|
|
745
817
|
{
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
} : void 0,
|
|
776
|
-
className: cn(
|
|
777
|
-
"border-t border-subtle",
|
|
778
|
-
rowInteractive && "cursor-pointer hover:bg-hover",
|
|
779
|
-
// The kit's focus frame width (§5, `--focus-ring-width`), drawn as an
|
|
780
|
-
// OUTLINE rather than FOCUS_RING's box-shadow: a shadow on a `<tr>`
|
|
781
|
-
// is not painted by every engine, an outline is.
|
|
782
|
-
rowsFocusable && "focus-visible:bg-hover focus-visible:outline-focus focus-visible:-outline-offset-2 focus-visible:outline-brand",
|
|
783
|
-
rowClassName?.(row)
|
|
784
|
-
),
|
|
785
|
-
onClick: rowInteractive ? (e) => {
|
|
786
|
-
if (fromOwnControl(e.target, e.currentTarget)) return;
|
|
787
|
-
if (fromOutside(e.target, e.currentTarget)) return;
|
|
788
|
-
if (selection && canSelect(row)) {
|
|
789
|
-
if (e.shiftKey) {
|
|
790
|
-
window.getSelection?.()?.removeAllRanges();
|
|
791
|
-
if (selectRange(rowIndex)) return;
|
|
792
|
-
selectionAnchor.current = rowKey(row);
|
|
793
|
-
selection.onToggle(row, !selection.isSelected(row));
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
if (e.metaKey || e.ctrlKey) {
|
|
797
|
-
selectionAnchor.current = rowKey(row);
|
|
798
|
-
selection.onToggle(row, !selection.isSelected(row));
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
onRowClick?.(row);
|
|
803
|
-
} : void 0,
|
|
804
|
-
children: [
|
|
805
|
-
selection && /* @__PURE__ */ jsx(
|
|
806
|
-
"td",
|
|
807
|
-
{
|
|
808
|
-
className: cn("align-top", compact ? "w-8 px-2 py-1" : "w-10 px-3 py-2"),
|
|
809
|
-
onClick: (e) => e.stopPropagation(),
|
|
810
|
-
children: canSelect(row) && /* @__PURE__ */ jsx(
|
|
811
|
-
"input",
|
|
812
|
-
{
|
|
813
|
-
type: "checkbox",
|
|
814
|
-
className: cn("accent-indigo-600", compact ? "size-3.5" : "size-4"),
|
|
815
|
-
checked: selection.isSelected(row),
|
|
816
|
-
onClick: (e) => {
|
|
817
|
-
if (e.shiftKey && selectRange(rowIndex)) {
|
|
818
|
-
e.preventDefault();
|
|
819
|
-
rangeClick.current = e.nativeEvent;
|
|
820
|
-
}
|
|
821
|
-
},
|
|
822
|
-
onChange: (e) => {
|
|
823
|
-
if (rangeClick.current && e.nativeEvent === rangeClick.current) {
|
|
824
|
-
rangeClick.current = null;
|
|
825
|
-
return;
|
|
826
|
-
}
|
|
827
|
-
selectionAnchor.current = rowKey(row);
|
|
828
|
-
selection.onToggle(row, e.target.checked);
|
|
829
|
-
},
|
|
830
|
-
"aria-label": labels.selectRow
|
|
831
|
-
}
|
|
832
|
-
)
|
|
833
|
-
}
|
|
834
|
-
),
|
|
835
|
-
visibleColumns.map((col, colIndex) => {
|
|
836
|
-
const width = widths[col.key];
|
|
837
|
-
const own = splitCellProps(col.cellProps?.(row));
|
|
838
|
-
const pinned = width ? { width, minWidth: width, maxWidth: width } : void 0;
|
|
839
|
-
return /* @__PURE__ */ createElement(
|
|
840
|
-
"td",
|
|
841
|
-
{
|
|
842
|
-
...own.attrs,
|
|
843
|
-
key: col.key,
|
|
844
|
-
"data-col": col.key,
|
|
845
|
-
style: own.style || pinned ? { ...own.style, ...pinned } : void 0,
|
|
846
|
-
className: cn(
|
|
847
|
-
"align-top",
|
|
848
|
-
compact ? "px-2 py-1" : "px-3 py-2",
|
|
849
|
-
width && "overflow-hidden text-ellipsis",
|
|
850
|
-
col.grow ? GROW_CELL_CLASS : growDrawn && GROW_PEER_CELL_CLASS,
|
|
851
|
-
logicalAlign(own.className),
|
|
852
|
-
logicalAlign(col.className)
|
|
853
|
-
)
|
|
854
|
-
},
|
|
855
|
-
colIndex === 0 && disclosure,
|
|
856
|
-
col === linkColumn && href ? (
|
|
857
|
-
// No `onActivate`: the click is left to bubble to the
|
|
858
|
-
// <tr> handler above, which already owns expand-vs-select.
|
|
859
|
-
// Calling it here as well would toggle the row twice.
|
|
860
|
-
/* @__PURE__ */ jsx(RowLink, { href, className: "block", "data-row-link": "", children: col.cell(row) })
|
|
861
|
-
) : col.cell(row)
|
|
862
|
-
);
|
|
863
|
-
})
|
|
864
|
-
]
|
|
865
|
-
}
|
|
866
|
-
),
|
|
867
|
-
expansion && /* @__PURE__ */ jsx("tr", { id: disclosure ? detailId : void 0, className: "bg-surface-2 border-t border-subtle", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0", children: /* @__PURE__ */ jsx("div", { className: "w-0 min-w-full", children: /* @__PURE__ */ jsx(
|
|
868
|
-
"div",
|
|
869
|
-
{
|
|
870
|
-
className: cn(
|
|
871
|
-
"sticky start-0 w-[var(--dt-visible-w,100%)] max-w-full",
|
|
872
|
-
compact ? "px-2 py-2" : "px-3 py-3"
|
|
873
|
-
),
|
|
874
|
-
children: expansion
|
|
875
|
-
}
|
|
876
|
-
) }) }) })
|
|
877
|
-
] }, key);
|
|
818
|
+
row,
|
|
819
|
+
rowIndex,
|
|
820
|
+
rowKey: key,
|
|
821
|
+
ctx: rowCtx,
|
|
822
|
+
columns: visibleColumns,
|
|
823
|
+
widths,
|
|
824
|
+
growDrawn,
|
|
825
|
+
linkColumn,
|
|
826
|
+
href: rowHref?.(row),
|
|
827
|
+
selectionColumn: !!selection,
|
|
828
|
+
selectable: canSelect(row),
|
|
829
|
+
selected: !!selection && selection.isSelected(row),
|
|
830
|
+
expanded,
|
|
831
|
+
expansion: expanded ? expandedRow?.(row) : null,
|
|
832
|
+
disclosure: rowsFocusable && !!expandedRow,
|
|
833
|
+
detailId: `${detailIdBase}-${rowIndex}`,
|
|
834
|
+
rowsFocusable,
|
|
835
|
+
rowInteractive: !!onRowClick || !!selection,
|
|
836
|
+
tabbable: key === tabRowKey,
|
|
837
|
+
className: rowClassName?.(row),
|
|
838
|
+
attrs: rowAttributes?.(row),
|
|
839
|
+
compact,
|
|
840
|
+
totalColSpan,
|
|
841
|
+
rowDetailsLabel: labels.rowDetails,
|
|
842
|
+
selectRowLabel: labels.selectRow,
|
|
843
|
+
ariaRowIndex: rowWindow?.ariaRow(rowIndex)
|
|
844
|
+
},
|
|
845
|
+
key
|
|
846
|
+
);
|
|
878
847
|
};
|
|
879
848
|
const emptyRow = slice.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
880
849
|
"td",
|
|
@@ -884,14 +853,7 @@ function DataTable({
|
|
|
884
853
|
children: isLoading ? /* @__PURE__ */ jsx(LoadingText, { label: labels.loading }) : empty ?? labels.empty
|
|
885
854
|
}
|
|
886
855
|
) }) : null;
|
|
887
|
-
|
|
888
|
-
return /* @__PURE__ */ jsxs("tbody", { className: bodyClass, children: [
|
|
889
|
-
leading,
|
|
890
|
-
slice.map(renderRow),
|
|
891
|
-
emptyRow
|
|
892
|
-
] });
|
|
893
|
-
}
|
|
894
|
-
const band = (level, def, g) => /* @__PURE__ */ jsx(
|
|
856
|
+
const band = (level, def, g, ariaRowIndex) => /* @__PURE__ */ jsx(
|
|
895
857
|
DataTableGroupBand,
|
|
896
858
|
{
|
|
897
859
|
level,
|
|
@@ -899,9 +861,44 @@ function DataTable({
|
|
|
899
861
|
top: level === 1 ? bandTops[0] : bandTops[1],
|
|
900
862
|
compact,
|
|
901
863
|
label: def.label ? def.label(g.key, g.rows) : g.key,
|
|
902
|
-
end: def.end?.(g.key, g.rows)
|
|
864
|
+
end: def.end?.(g.key, g.rows),
|
|
865
|
+
ariaRowIndex
|
|
903
866
|
}
|
|
904
867
|
);
|
|
868
|
+
if (rowWindow) {
|
|
869
|
+
const spacer = (key, height) => /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", "data-vt-spacer": "", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, style: { height, padding: 0, border: 0 } }) }, key);
|
|
870
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
871
|
+
leading && /* @__PURE__ */ jsx("tbody", { className: bodyClass, children: leading }),
|
|
872
|
+
rowWindow.bodies.map((b) => {
|
|
873
|
+
if (b.kind === "spacer")
|
|
874
|
+
return /* @__PURE__ */ jsx("tbody", { "data-vt-body": "", "aria-hidden": "true", children: spacer("s", b.height) }, b.key);
|
|
875
|
+
const g = virtualGroups[b.group];
|
|
876
|
+
const vb = virtualBands[b.group];
|
|
877
|
+
return /* @__PURE__ */ jsxs(
|
|
878
|
+
"tbody",
|
|
879
|
+
{
|
|
880
|
+
"data-vt-body": "",
|
|
881
|
+
className: bodyClass,
|
|
882
|
+
children: [
|
|
883
|
+
vb && g.bands.includes(1) && band(1, levels[0], vb.g1, rowWindow.ariaBand(b.group, 1)),
|
|
884
|
+
vb?.g2 && band(2, levels[1], vb.g2, rowWindow.ariaBand(b.group, 2)),
|
|
885
|
+
b.items.map(
|
|
886
|
+
(it) => it.kind === "gap" ? spacer(it.key, it.height) : renderRow(slice[it.index], it.index)
|
|
887
|
+
)
|
|
888
|
+
]
|
|
889
|
+
},
|
|
890
|
+
vb ? `vg:${vb.g1.key}:${vb.g2?.key ?? ""}:${g.start}` : "vg"
|
|
891
|
+
);
|
|
892
|
+
})
|
|
893
|
+
] });
|
|
894
|
+
}
|
|
895
|
+
if (!desktopGroups) {
|
|
896
|
+
return /* @__PURE__ */ jsxs("tbody", { className: bodyClass, children: [
|
|
897
|
+
leading,
|
|
898
|
+
slice.map(renderRow),
|
|
899
|
+
emptyRow
|
|
900
|
+
] });
|
|
901
|
+
}
|
|
905
902
|
const rowsOf = (g) => g.rows.map((r, i) => renderRow(r, g.start + i));
|
|
906
903
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
907
904
|
(leading || emptyRow) && /* @__PURE__ */ jsxs("tbody", { className: bodyClass, children: [
|
|
@@ -933,7 +930,7 @@ function DataTable({
|
|
|
933
930
|
"font-semibold text-primary",
|
|
934
931
|
isLoading && "opacity-60 transition-opacity"
|
|
935
932
|
),
|
|
936
|
-
children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
933
|
+
children: /* @__PURE__ */ jsxs("tr", { "aria-rowindex": rowWindow?.rowCount, children: [
|
|
937
934
|
selection && /* @__PURE__ */ jsx(
|
|
938
935
|
"td",
|
|
939
936
|
{
|