@eifi1/ui-kit 0.6.0 → 0.7.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 +69 -33
- package/dist/chart.d.ts +1 -0
- package/dist/components/account-settings.js +3 -2
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +3 -0
- package/dist/components/amount-input.js +6 -4
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +36 -7
- package/dist/components/autocomplete.js +68 -22
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/calculator.d.ts +3 -0
- package/dist/components/calculator.js +2 -1
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/chart-zoom.js +2 -1
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/chart.d.ts +33 -2
- package/dist/components/chart.js +20 -8
- package/dist/components/chart.js.map +1 -1
- package/dist/components/checkbox.d.ts +9 -0
- package/dist/components/checkbox.js +7 -2
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +34 -14
- package/dist/components/chip.js +63 -28
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +18 -1
- package/dist/components/choice-card.js +21 -8
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/combobox-core.d.ts +61 -2
- package/dist/components/combobox-core.js +68 -17
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +11 -7
- package/dist/components/combobox.js +51 -28
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/currency-select.js +3 -3
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +30 -6
- package/dist/components/danger-confirm.js +51 -32
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +6 -3
- package/dist/components/data-table-pagination.js +6 -5
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +332 -248
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +17 -7
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +28 -3
- package/dist/components/dialog-frame.js +47 -11
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.d.ts +22 -2
- package/dist/components/disclosure.js +41 -8
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/dropdown.d.ts +7 -3
- package/dist/components/dropdown.js +6 -2
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +17 -8
- package/dist/components/entity-combobox.js +7 -5
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/file-button.d.ts +36 -5
- package/dist/components/file-button.js +42 -3
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +9 -5
- package/dist/components/file-dropzone.js +14 -19
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/grouped-picker.js +2 -2
- package/dist/components/grouped-picker.js.map +1 -1
- package/dist/components/hover-menu.d.ts +8 -3
- package/dist/components/hover-menu.js +88 -4
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-picker.d.ts +10 -1
- package/dist/components/icon-picker.js +5 -1
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/measured-grid.d.ts +165 -0
- package/dist/components/measured-grid.js +559 -0
- package/dist/components/measured-grid.js.map +1 -0
- package/dist/components/mini-calendar.js +7 -8
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/month-picker.js +13 -9
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.js +2 -2
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.d.ts +9 -1
- package/dist/components/multi-select.js +22 -8
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +3 -0
- package/dist/components/number-input.d.ts +3 -0
- package/dist/components/number-input.js +3 -3
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +3 -0
- package/dist/components/numpad-sheet.js +3 -3
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/picker-sheet.js +1 -1
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/popover.js +11 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/series-chart-ticks.d.ts +13 -0
- package/dist/components/series-chart-ticks.js +29 -0
- package/dist/components/series-chart-ticks.js.map +1 -0
- package/dist/components/series-chart.js +33 -27
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/swatch-picker.d.ts +10 -1
- package/dist/components/swatch-picker.js +2 -0
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/swipeable-row.d.ts +11 -2
- package/dist/components/swipeable-row.js +5 -3
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +9 -0
- package/dist/components/switch.js +7 -2
- package/dist/components/switch.js.map +1 -1
- package/dist/components/tile-radio.js +5 -7
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/toggle-group.d.ts +13 -3
- package/dist/components/toggle-group.js +21 -1
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.js +1 -2
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/treemap.d.ts +6 -1
- package/dist/components/treemap.js +16 -6
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +31 -7
- package/dist/components/ui.js +26 -18
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-anchor-dir.d.ts +15 -0
- package/dist/components/use-anchor-dir.js +14 -0
- package/dist/components/use-anchor-dir.js.map +1 -0
- package/dist/components/use-mobile-reveal.d.ts +8 -1
- package/dist/components/use-mobile-reveal.js +3 -2
- package/dist/components/use-mobile-reveal.js.map +1 -1
- package/dist/components/use-table-state.d.ts +4 -4
- package/dist/components/use-table-state.js +12 -5
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/{data-table-filters-DM1auUfH.d.ts → data-table-filters-noy0Abvi.d.ts} +40 -7
- package/dist/data-table.d.ts +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +22 -3
- package/dist/feedback/feedback-attachment.js +15 -7
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +3 -2
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback.d.ts +1 -1
- package/dist/hooks/use-windowed-rows.d.ts +29 -0
- package/dist/hooks/use-windowed-rows.js +31 -0
- package/dist/hooks/use-windowed-rows.js.map +1 -0
- package/dist/i18n/defaults.d.ts +3 -0
- package/dist/i18n/defaults.js +5 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +5 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/de-CH.d.ts +43 -0
- package/dist/i18n/locales/de-CH.js +21 -0
- package/dist/i18n/locales/de-CH.js.map +1 -0
- package/dist/i18n/locales/de.d.ts +43 -0
- package/dist/i18n/locales/de.js +344 -0
- package/dist/i18n/locales/de.js.map +1 -0
- package/dist/i18n/locales/es.d.ts +43 -0
- package/dist/i18n/locales/es.js +339 -0
- package/dist/i18n/locales/es.js.map +1 -0
- package/dist/i18n/locales/fr.d.ts +43 -0
- package/dist/i18n/locales/fr.js +344 -0
- package/dist/i18n/locales/fr.js.map +1 -0
- package/dist/i18n/locales/hu.d.ts +43 -0
- package/dist/i18n/locales/hu.js +343 -0
- package/dist/i18n/locales/hu.js.map +1 -0
- package/dist/i18n/locales/it.d.ts +43 -0
- package/dist/i18n/locales/it.js +342 -0
- package/dist/i18n/locales/it.js.map +1 -0
- package/dist/i18n/locales/zh.d.ts +43 -0
- package/dist/i18n/locales/zh.js +338 -0
- package/dist/i18n/locales/zh.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/direction.d.ts +24 -0
- package/dist/lib/direction.js +19 -0
- package/dist/lib/direction.js.map +1 -0
- package/dist/rhf/form.js.map +1 -1
- package/dist/search/command-palette.d.ts +5 -0
- package/dist/search/command-palette.js +80 -50
- package/dist/search/command-palette.js.map +1 -1
- package/dist/shell/app-shell.d.ts +13 -1
- package/dist/shell/app-shell.js +133 -84
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/topbar-action-menu.js +1 -1
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.d.ts +7 -3
- package/dist/shell/topbar-controls.js +38 -31
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +7 -1
- package/dist/theme/chart-palette.js +2 -1
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/tour/tour.d.ts +11 -5
- package/dist/tour/tour.js +124 -58
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/use-wizard.js +30 -13
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/wizard-summary.js +1 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/package.json +12 -2
- package/src/components/account-settings.tsx +6 -2
- package/src/components/amount-input.tsx +10 -8
- package/src/components/autocomplete.tsx +123 -33
- package/src/components/calculator.tsx +5 -1
- package/src/components/chart-zoom.tsx +8 -1
- package/src/components/chart.tsx +68 -7
- package/src/components/checkbox.tsx +16 -0
- package/src/components/chip.tsx +131 -49
- package/src/components/choice-card.tsx +77 -36
- package/src/components/combobox-core.tsx +147 -20
- package/src/components/combobox.tsx +100 -44
- package/src/components/currency-select.tsx +6 -6
- package/src/components/danger-confirm.tsx +90 -36
- package/src/components/data-table-pagination.tsx +32 -19
- package/src/components/data-table.tsx +198 -36
- package/src/components/date-picker.tsx +24 -7
- package/src/components/dialog-frame.tsx +97 -22
- package/src/components/disclosure.tsx +75 -13
- package/src/components/dropdown.tsx +17 -5
- package/src/components/entity-combobox.tsx +26 -13
- package/src/components/file-button.tsx +102 -6
- package/src/components/file-dropzone.tsx +44 -35
- package/src/components/grouped-picker.tsx +2 -2
- package/src/components/hover-menu.tsx +139 -10
- package/src/components/icon-picker.tsx +14 -1
- package/src/components/measured-grid.tsx +852 -0
- package/src/components/mini-calendar.tsx +11 -8
- package/src/components/month-picker.tsx +18 -11
- package/src/components/multi-entity-combobox.tsx +2 -2
- package/src/components/multi-select.tsx +34 -7
- package/src/components/number-input.tsx +4 -4
- package/src/components/numpad-sheet.tsx +5 -3
- package/src/components/picker-sheet.tsx +1 -1
- package/src/components/popover.tsx +18 -3
- package/src/components/series-chart-ticks.ts +52 -0
- package/src/components/series-chart.tsx +39 -31
- package/src/components/swatch-picker.tsx +11 -0
- package/src/components/swipeable-row.tsx +21 -6
- package/src/components/switch.tsx +16 -0
- package/src/components/tile-radio.tsx +5 -7
- package/src/components/toggle-group.tsx +39 -3
- package/src/components/toggle-legend.tsx +5 -2
- package/src/components/treemap.tsx +28 -5
- package/src/components/ui.tsx +74 -30
- package/src/components/use-anchor-dir.ts +20 -0
- package/src/components/use-mobile-reveal.ts +10 -2
- package/src/components/use-table-state.ts +44 -7
- package/src/data-table.ts +1 -0
- package/src/feedback/feedback-attachment.tsx +36 -9
- package/src/feedback/feedback-dialog.tsx +3 -2
- package/src/hooks/use-windowed-rows.ts +69 -0
- package/src/i18n/defaults.ts +4 -0
- package/src/i18n/kit-labels.tsx +4 -0
- package/src/i18n/locales/de-CH.ts +30 -0
- package/src/i18n/locales/de.ts +365 -0
- package/src/i18n/locales/es.ts +358 -0
- package/src/i18n/locales/fr.ts +371 -0
- package/src/i18n/locales/hu.ts +359 -0
- package/src/i18n/locales/it.ts +360 -0
- package/src/i18n/locales/zh.ts +348 -0
- package/src/index.ts +10 -1
- package/src/lib/direction.ts +37 -0
- package/src/rhf/form.tsx +21 -0
- package/src/search/command-palette.tsx +77 -19
- package/src/shell/app-shell.tsx +200 -129
- package/src/shell/topbar-action-menu.tsx +1 -1
- package/src/shell/topbar-controls.tsx +19 -8
- package/src/theme/chart-palette.ts +9 -2
- package/src/tour/tour.tsx +119 -18
- package/src/wizard/use-wizard.ts +55 -17
- package/src/wizard/wizard-summary.tsx +1 -1
|
@@ -11,8 +11,7 @@ import {
|
|
|
11
11
|
Filter,
|
|
12
12
|
X
|
|
13
13
|
} from "lucide-react";
|
|
14
|
-
import {
|
|
15
|
-
import { Card } from "./ui.js";
|
|
14
|
+
import { Card, Spinner } from "./ui.js";
|
|
16
15
|
import { cn } from "../lib/cn.js";
|
|
17
16
|
import {
|
|
18
17
|
defaultFilterState,
|
|
@@ -34,6 +33,25 @@ import { useAnnounce } from "../hooks/use-announce.js";
|
|
|
34
33
|
import { resolveDataTableLabels } from "./data-table-labels.js";
|
|
35
34
|
import { useKitLabelOverrides, useKitLocale } from "../i18n/kit-labels.js";
|
|
36
35
|
import { Tooltip } from "./tooltip.js";
|
|
36
|
+
import { dirOf, isRtl } from "../lib/direction.js";
|
|
37
|
+
function physicalSwipe(actions, dir) {
|
|
38
|
+
const rtl = dir === "rtl";
|
|
39
|
+
return {
|
|
40
|
+
left: (rtl ? actions.end : actions.start) ?? actions.left,
|
|
41
|
+
right: (rtl ? actions.start : actions.end) ?? actions.right
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const PHYSICAL_ALIGN = /(^|\s)((?:[\w-]+:)*)text-(left|right)(?=\s|$)/g;
|
|
45
|
+
function logicalAlign(className) {
|
|
46
|
+
return className?.replace(
|
|
47
|
+
PHYSICAL_ALIGN,
|
|
48
|
+
(token, lead, variants, side) => (
|
|
49
|
+
// Already scoped to one direction: that is a caller choosing the physical side.
|
|
50
|
+
/(^|:)(ltr|rtl):/.test(variants) ? token : `${lead}${variants}text-${side === "right" ? "end" : "start"}`
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const END_ALIGN = /(^|\s)text-end(?=\s|$)/;
|
|
37
55
|
function cleanAttrs(attrs) {
|
|
38
56
|
if (!attrs) return void 0;
|
|
39
57
|
const out = {};
|
|
@@ -108,6 +126,7 @@ function DataTable({
|
|
|
108
126
|
leadingRow
|
|
109
127
|
}) {
|
|
110
128
|
const isServer = !!serverPagination;
|
|
129
|
+
const isLoading = !!serverPagination?.isLoading;
|
|
111
130
|
const labelOverrides = useKitLabelOverrides("dataTable");
|
|
112
131
|
const labels = useMemo(
|
|
113
132
|
() => resolveDataTableLabels(
|
|
@@ -120,7 +139,6 @@ function DataTable({
|
|
|
120
139
|
[labelOverrides, labelsProp]
|
|
121
140
|
);
|
|
122
141
|
const locale = useKitLocale(localeProp);
|
|
123
|
-
const [, setSearchParams] = useSearchParams();
|
|
124
142
|
const { announce, regionProps } = useAnnounce();
|
|
125
143
|
const {
|
|
126
144
|
sorts,
|
|
@@ -143,7 +161,6 @@ function DataTable({
|
|
|
143
161
|
storageKey,
|
|
144
162
|
storageKeyPrefix,
|
|
145
163
|
urlSync,
|
|
146
|
-
setSearchParams,
|
|
147
164
|
defaultPageSize,
|
|
148
165
|
sortsProp,
|
|
149
166
|
filtersProp
|
|
@@ -315,6 +332,7 @@ function DataTable({
|
|
|
315
332
|
pointerId: e.pointerId,
|
|
316
333
|
startX: e.clientX,
|
|
317
334
|
startWidth,
|
|
335
|
+
sign: isRtl(e.currentTarget) ? -1 : 1,
|
|
318
336
|
hadWidth: widths[key],
|
|
319
337
|
cells: columnCells(key),
|
|
320
338
|
width: startWidth,
|
|
@@ -327,7 +345,7 @@ function DataTable({
|
|
|
327
345
|
const moveResize = (e) => {
|
|
328
346
|
const drag = resizing.current;
|
|
329
347
|
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
330
|
-
drag.width = Math.max(40, Math.round(drag.startWidth + (e.clientX - drag.startX)));
|
|
348
|
+
drag.width = Math.max(40, Math.round(drag.startWidth + drag.sign * (e.clientX - drag.startX)));
|
|
331
349
|
drag.moved = true;
|
|
332
350
|
applyLiveWidth(drag.cells, drag.width);
|
|
333
351
|
};
|
|
@@ -373,14 +391,22 @@ function DataTable({
|
|
|
373
391
|
const mobilePrimaryCol = mobileColumns.find((c) => c.mobilePrimary) ?? mobileColumns[0] ?? null;
|
|
374
392
|
const mobileSecondaryColumns = mobileColumns.filter((c) => c !== mobilePrimaryCol);
|
|
375
393
|
const mobileCardLinkable = mobileColumns.every((c) => !c.noRowLink);
|
|
394
|
+
const [mobileDir, setMobileDir] = useState("ltr");
|
|
395
|
+
const mobileRootRef = (el) => {
|
|
396
|
+
if (!el) return;
|
|
397
|
+
const d = dirOf(el);
|
|
398
|
+
if (d !== mobileDir) setMobileDir(d);
|
|
399
|
+
};
|
|
376
400
|
const { mobileSlice, canRevealMoreMobile, loadMoreRef } = useMobileReveal({
|
|
377
401
|
rows: sorted,
|
|
378
402
|
slice,
|
|
379
403
|
isServer,
|
|
380
404
|
isMdUp,
|
|
405
|
+
unpaged,
|
|
381
406
|
defaultPageSize
|
|
382
407
|
});
|
|
383
408
|
const selectionAnchor = useRef(null);
|
|
409
|
+
const rangeClick = useRef(null);
|
|
384
410
|
const canSelect = (row) => !!selection && (selection.isSelectable?.(row) ?? true);
|
|
385
411
|
const selectRange = (toIndex) => {
|
|
386
412
|
if (!selection || selectionAnchor.current === null) return false;
|
|
@@ -408,11 +434,12 @@ function DataTable({
|
|
|
408
434
|
const tint = rowClassName?.(row);
|
|
409
435
|
const interactive = !!onRowClick;
|
|
410
436
|
const opensDetail = interactive && !!expandedRow;
|
|
411
|
-
const
|
|
437
|
+
const swipeActions = mobileSwipeActions?.(row);
|
|
438
|
+
const swipe = swipeActions ? physicalSwipe(swipeActions, mobileDir) : null;
|
|
412
439
|
const swipeEnabled = !!swipe && !expanded;
|
|
413
440
|
const href = mobileCardLinkable ? rowHref?.(row) : void 0;
|
|
414
441
|
const cardClass = cn(
|
|
415
|
-
"w-full px-4 py-3 text-
|
|
442
|
+
"w-full px-4 py-3 text-start flex items-center gap-3",
|
|
416
443
|
// Live #320's other half: the card acknowledges the touch before the sheet
|
|
417
444
|
// arrives. On a cold route the data can take a beat, and an unacknowledged tap
|
|
418
445
|
// reads as "did that register?" — which is most of what "abrupt" means here.
|
|
@@ -432,7 +459,16 @@ function DataTable({
|
|
|
432
459
|
] }) }),
|
|
433
460
|
opensDetail && // `aria-hidden`: the row already announces itself as a button with
|
|
434
461
|
// `aria-expanded`, so the icon would only add a second, wordless stop.
|
|
435
|
-
(mobileExpandAsDialog ?
|
|
462
|
+
(mobileExpandAsDialog ? (
|
|
463
|
+
// Points INTO the sheet, which is the reading-forward direction.
|
|
464
|
+
/* @__PURE__ */ jsx(
|
|
465
|
+
ChevronRight,
|
|
466
|
+
{
|
|
467
|
+
"aria-hidden": true,
|
|
468
|
+
className: "size-4 shrink-0 text-[var(--text-placeholder)] rtl:-scale-x-100"
|
|
469
|
+
}
|
|
470
|
+
)
|
|
471
|
+
) : /* @__PURE__ */ jsx(
|
|
436
472
|
ChevronDown,
|
|
437
473
|
{
|
|
438
474
|
"aria-hidden": true,
|
|
@@ -493,7 +529,7 @@ function DataTable({
|
|
|
493
529
|
}, []) : null;
|
|
494
530
|
return /* @__PURE__ */ jsxs(Card, { flush: true, className: cn("overflow-clip", fillHeight && "md:flex md:flex-1 md:flex-col md:min-h-0"), children: [
|
|
495
531
|
/* @__PURE__ */ jsx("span", { ...regionProps }),
|
|
496
|
-
!isMdUp && /* @__PURE__ */ jsxs("div", { children: [
|
|
532
|
+
!isMdUp && /* @__PURE__ */ jsxs("div", { ref: mobileRootRef, children: [
|
|
497
533
|
(!isServer || onFiltersChange) && /* @__PURE__ */ jsx(
|
|
498
534
|
MobileFilters,
|
|
499
535
|
{
|
|
@@ -509,21 +545,32 @@ function DataTable({
|
|
|
509
545
|
locale
|
|
510
546
|
}
|
|
511
547
|
),
|
|
512
|
-
/* @__PURE__ */ jsxs(
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
548
|
+
/* @__PURE__ */ jsxs(
|
|
549
|
+
"ul",
|
|
550
|
+
{
|
|
551
|
+
className: cn(
|
|
552
|
+
"divide-y divide-[var(--border)]",
|
|
553
|
+
// Same busy treatment as the desktop body; see `isLoading` below.
|
|
554
|
+
isLoading && mobileSlice.length > 0 && "opacity-60 transition-opacity"
|
|
555
|
+
),
|
|
556
|
+
"aria-busy": isLoading || void 0,
|
|
557
|
+
children: [
|
|
558
|
+
mobileGroups ? mobileGroups.map((g) => /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
559
|
+
/* @__PURE__ */ jsx("li", { className: "sticky top-0 z-10 bg-[var(--bg-surface-2)] px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-[var(--text-muted)] backdrop-blur", children: mobileGroupLabel ? mobileGroupLabel(g.key) : g.key }),
|
|
560
|
+
g.rows.map(renderMobileRow)
|
|
561
|
+
] }, `hb-group:${g.key}`)) : mobileSlice.map(renderMobileRow),
|
|
562
|
+
mobileSlice.length === 0 && /* @__PURE__ */ jsx("li", { className: "px-4 py-6 text-center text-sm text-[var(--text-muted)]", children: isLoading ? /* @__PURE__ */ jsx(LoadingText, { label: labels.loading }) : empty ?? "\u2014" }),
|
|
563
|
+
canRevealMoreMobile && /* @__PURE__ */ jsx(
|
|
564
|
+
"li",
|
|
565
|
+
{
|
|
566
|
+
ref: loadMoreRef,
|
|
567
|
+
className: "px-4 py-4 text-center text-xs text-[var(--text-placeholder)]",
|
|
568
|
+
children: labels.loading
|
|
569
|
+
}
|
|
570
|
+
)
|
|
571
|
+
]
|
|
572
|
+
}
|
|
573
|
+
),
|
|
527
574
|
isServer && /* @__PURE__ */ jsx(
|
|
528
575
|
Pagination,
|
|
529
576
|
{
|
|
@@ -532,7 +579,7 @@ function DataTable({
|
|
|
532
579
|
pageSize: paginationPageSize,
|
|
533
580
|
total: paginationTotal,
|
|
534
581
|
onPage: goToPage,
|
|
535
|
-
onPageSize:
|
|
582
|
+
onPageSize: serverPagination.onPageSizeChange,
|
|
536
583
|
labels,
|
|
537
584
|
locale
|
|
538
585
|
}
|
|
@@ -555,236 +602,262 @@ function DataTable({
|
|
|
555
602
|
{
|
|
556
603
|
className: cn("overflow-auto [scrollbar-gutter:stable]", fillHeight && "flex-1 min-h-0"),
|
|
557
604
|
style: fillHeight ? void 0 : { maxHeight: maxBodyHeight },
|
|
558
|
-
children: /* @__PURE__ */ jsxs(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
605
|
+
children: /* @__PURE__ */ jsxs(
|
|
606
|
+
"table",
|
|
607
|
+
{
|
|
608
|
+
className: "w-full text-sm",
|
|
609
|
+
"aria-label": labels.table,
|
|
610
|
+
"aria-busy": isLoading || void 0,
|
|
611
|
+
children: [
|
|
612
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-[var(--bg-surface-2)] text-[var(--text-secondary)]", children: /* @__PURE__ */ jsxs("tr", { className: "text-start", children: [
|
|
613
|
+
selection && /* @__PURE__ */ jsx(
|
|
614
|
+
"th",
|
|
567
615
|
{
|
|
568
|
-
|
|
569
|
-
className: "
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
if (el) el.indeterminate = selection.someSelected && !selection.allSelected;
|
|
573
|
-
},
|
|
574
|
-
onChange: (e) => selection.onToggleAll(e.target.checked),
|
|
575
|
-
"aria-label": labels.selectAllRows
|
|
576
|
-
}
|
|
577
|
-
)
|
|
578
|
-
}
|
|
579
|
-
),
|
|
580
|
-
visibleColumns.map((col) => {
|
|
581
|
-
const sortable = (!isServer || !!onSortsChange) && !!col.sortBy;
|
|
582
|
-
const filter = !isServer || onFiltersChange ? resolveFilter(col) : null;
|
|
583
|
-
const filterState = filters[col.key] ?? (filter ? defaultFilterState(filter) : void 0);
|
|
584
|
-
const sortIdx = sorts.findIndex((s) => s.key === col.key);
|
|
585
|
-
const active = sortIdx !== -1;
|
|
586
|
-
const Icon = active ? sorts[sortIdx].dir === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
|
|
587
|
-
const filterActive = filterState && isFilterActive(filterState);
|
|
588
|
-
const isRightAligned = col.headClassName?.includes("text-right");
|
|
589
|
-
const width = widths[col.key];
|
|
590
|
-
return /* @__PURE__ */ jsxs(
|
|
591
|
-
"th",
|
|
592
|
-
{
|
|
593
|
-
ref: (el) => {
|
|
594
|
-
if (el) headRefs.set(col.key, el);
|
|
595
|
-
else headRefs.delete(col.key);
|
|
596
|
-
},
|
|
597
|
-
scope: "col",
|
|
598
|
-
"aria-sort": sortable ? sortIdx === 0 ? sorts[0].dir === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
599
|
-
style: width ? { width, minWidth: width, maxWidth: width } : void 0,
|
|
600
|
-
className: cn(
|
|
601
|
-
"relative px-3 py-2 font-medium align-middle whitespace-nowrap",
|
|
602
|
-
// Keep the header visible while the user scrolls the page.
|
|
603
|
-
// Each <th> carries its own bg so the row doesn't render
|
|
604
|
-
// transparent over the data rows underneath.
|
|
605
|
-
"sticky top-0 z-10 bg-[var(--bg-surface-2)] backdrop-blur-sm",
|
|
606
|
-
col.headClassName
|
|
607
|
-
),
|
|
608
|
-
children: [
|
|
609
|
-
/* @__PURE__ */ jsxs(
|
|
610
|
-
"div",
|
|
616
|
+
scope: "col",
|
|
617
|
+
className: "sticky top-0 z-10 w-10 bg-[var(--bg-surface-2)] px-3 py-2 align-middle backdrop-blur-sm",
|
|
618
|
+
children: /* @__PURE__ */ jsx(
|
|
619
|
+
"input",
|
|
611
620
|
{
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
)
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
621
|
+
type: "checkbox",
|
|
622
|
+
className: "size-4 align-middle accent-indigo-600",
|
|
623
|
+
checked: selection.allSelected,
|
|
624
|
+
ref: (el) => {
|
|
625
|
+
if (el) el.indeterminate = selection.someSelected && !selection.allSelected;
|
|
626
|
+
},
|
|
627
|
+
onChange: (e) => selection.onToggleAll(e.target.checked),
|
|
628
|
+
"aria-label": labels.selectAllRows
|
|
629
|
+
}
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
),
|
|
633
|
+
visibleColumns.map((col) => {
|
|
634
|
+
const sortable = (!isServer || !!onSortsChange) && !!col.sortBy;
|
|
635
|
+
const filter = !isServer || onFiltersChange ? resolveFilter(col) : null;
|
|
636
|
+
const filterState = filters[col.key] ?? (filter ? defaultFilterState(filter) : void 0);
|
|
637
|
+
const sortIdx = sorts.findIndex((s) => s.key === col.key);
|
|
638
|
+
const active = sortIdx !== -1;
|
|
639
|
+
const Icon = active ? sorts[sortIdx].dir === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
|
|
640
|
+
const filterActive = filterState && isFilterActive(filterState);
|
|
641
|
+
const headClass = logicalAlign(col.headClassName);
|
|
642
|
+
const isEndAligned = !!headClass && END_ALIGN.test(headClass);
|
|
643
|
+
const width = widths[col.key];
|
|
644
|
+
return /* @__PURE__ */ jsxs(
|
|
645
|
+
"th",
|
|
646
|
+
{
|
|
647
|
+
ref: (el) => {
|
|
648
|
+
if (el) headRefs.set(col.key, el);
|
|
649
|
+
else headRefs.delete(col.key);
|
|
650
|
+
},
|
|
651
|
+
scope: "col",
|
|
652
|
+
"aria-sort": sortable ? sortIdx === 0 ? sorts[0].dir === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
653
|
+
style: width ? { width, minWidth: width, maxWidth: width } : void 0,
|
|
654
|
+
className: cn(
|
|
655
|
+
"relative px-3 py-2 font-medium align-middle whitespace-nowrap",
|
|
656
|
+
// Keep the header visible while the user scrolls the page.
|
|
657
|
+
// Each <th> carries its own bg so the row doesn't render
|
|
658
|
+
// transparent over the data rows underneath.
|
|
659
|
+
"sticky top-0 z-10 bg-[var(--bg-surface-2)] backdrop-blur-sm",
|
|
660
|
+
headClass
|
|
661
|
+
),
|
|
662
|
+
children: [
|
|
663
|
+
/* @__PURE__ */ jsxs(
|
|
664
|
+
"div",
|
|
665
|
+
{
|
|
666
|
+
className: cn(
|
|
667
|
+
"flex items-center gap-1",
|
|
668
|
+
isEndAligned && "flex-row-reverse"
|
|
669
|
+
),
|
|
670
|
+
children: [
|
|
671
|
+
/* @__PURE__ */ jsx(Tooltip, { label: sortable ? labels.sortHint : void 0, portal: true, children: /* @__PURE__ */ jsxs(
|
|
640
672
|
"button",
|
|
641
673
|
{
|
|
642
674
|
type: "button",
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
"aria-label": labels.filter,
|
|
675
|
+
onClick: (e) => sortable && toggleSort(col.key, e.shiftKey),
|
|
676
|
+
disabled: !sortable,
|
|
646
677
|
className: cn(
|
|
647
|
-
"
|
|
648
|
-
|
|
678
|
+
"flex items-center gap-1 text-start",
|
|
679
|
+
sortable && "hover:text-[var(--text-primary)]"
|
|
649
680
|
),
|
|
650
|
-
children:
|
|
681
|
+
children: [
|
|
682
|
+
/* @__PURE__ */ jsx("span", { children: col.header }),
|
|
683
|
+
sortable && /* @__PURE__ */ jsx(Icon, { className: cn("size-3", active ? "opacity-100" : "opacity-40") }),
|
|
684
|
+
active && sorts.length > 1 && /* @__PURE__ */ jsx("span", { className: "text-[9px] font-semibold leading-none text-brand", children: sortIdx + 1 })
|
|
685
|
+
]
|
|
651
686
|
}
|
|
652
|
-
),
|
|
653
|
-
|
|
654
|
-
|
|
687
|
+
) }),
|
|
688
|
+
filter && /* @__PURE__ */ jsx(
|
|
689
|
+
Popover,
|
|
655
690
|
{
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
691
|
+
width: filter.type === "date" ? 420 : void 0,
|
|
692
|
+
labels: { panel: labels.filter },
|
|
693
|
+
trigger: ({ toggle, ref }) => /* @__PURE__ */ jsx(
|
|
694
|
+
"button",
|
|
695
|
+
{
|
|
696
|
+
type: "button",
|
|
697
|
+
ref,
|
|
698
|
+
onClick: toggle,
|
|
699
|
+
"aria-label": labels.filter,
|
|
700
|
+
className: cn(
|
|
701
|
+
"rounded p-1 transition-colors",
|
|
702
|
+
filterActive ? "bg-[var(--brand-bg)] text-[var(--brand-muted)]" : "text-[var(--text-placeholder)] hover:text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]"
|
|
703
|
+
),
|
|
704
|
+
children: /* @__PURE__ */ jsx(Filter, { className: "size-3" })
|
|
705
|
+
}
|
|
706
|
+
),
|
|
707
|
+
children: () => /* @__PURE__ */ jsx(
|
|
708
|
+
FilterPopover,
|
|
709
|
+
{
|
|
710
|
+
column: col,
|
|
711
|
+
state: filterState ?? defaultFilterState(filter),
|
|
712
|
+
onChange: (next) => setFilterValue(col.key, next),
|
|
713
|
+
onClear: () => clearFilter(col.key),
|
|
714
|
+
selectOptions: selectOptionsByKey[col.key] ?? [],
|
|
715
|
+
labels,
|
|
716
|
+
locale
|
|
717
|
+
}
|
|
718
|
+
)
|
|
663
719
|
}
|
|
664
720
|
)
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
),
|
|
724
|
+
/* @__PURE__ */ jsx(
|
|
725
|
+
"span",
|
|
726
|
+
{
|
|
727
|
+
role: "separator",
|
|
728
|
+
"aria-orientation": "vertical",
|
|
729
|
+
onPointerDown: (e) => startResize(e, col.key),
|
|
730
|
+
onPointerMove: moveResize,
|
|
731
|
+
onPointerUp: (e) => finishResize(e, true),
|
|
732
|
+
onPointerCancel: (e) => finishResize(e, false),
|
|
733
|
+
onDoubleClick: (e) => {
|
|
734
|
+
e.preventDefault();
|
|
735
|
+
setWidths((w) => {
|
|
736
|
+
const next = { ...w };
|
|
737
|
+
delete next[col.key];
|
|
738
|
+
return next;
|
|
739
|
+
});
|
|
740
|
+
},
|
|
741
|
+
className: "absolute end-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 rtl:translate-x-1/2 cursor-col-resize select-none touch-none hover:bg-[var(--brand-bg-hover)]"
|
|
742
|
+
}
|
|
743
|
+
)
|
|
744
|
+
]
|
|
745
|
+
},
|
|
746
|
+
col.key
|
|
747
|
+
);
|
|
748
|
+
})
|
|
749
|
+
] }) }),
|
|
750
|
+
/* @__PURE__ */ jsxs(
|
|
751
|
+
"tbody",
|
|
752
|
+
{
|
|
753
|
+
className: cn(isLoading && slice.length > 0 && "opacity-60 transition-opacity"),
|
|
754
|
+
children: [
|
|
755
|
+
leadingRow && /* @__PURE__ */ jsx("tr", { className: "border-t border-[var(--border)]", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0", children: leadingRow }) }),
|
|
756
|
+
slice.map((row, rowIndex) => {
|
|
757
|
+
const expanded = isExpanded?.(row) ?? false;
|
|
758
|
+
const expansion = expanded ? expandedRow?.(row) : null;
|
|
759
|
+
const rowInteractive = !!onRowClick || !!selection;
|
|
760
|
+
const href = rowHref?.(row);
|
|
761
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
762
|
+
/* @__PURE__ */ jsxs(
|
|
763
|
+
"tr",
|
|
764
|
+
{
|
|
765
|
+
...cleanAttrs(rowAttributes?.(row)),
|
|
766
|
+
className: cn(
|
|
767
|
+
"border-t border-[var(--border)]",
|
|
768
|
+
rowInteractive && "cursor-pointer hover:bg-[var(--bg-hover)]",
|
|
769
|
+
rowClassName?.(row)
|
|
770
|
+
),
|
|
771
|
+
onClick: rowInteractive ? (e) => {
|
|
772
|
+
if (selection && canSelect(row)) {
|
|
773
|
+
if (e.shiftKey) {
|
|
774
|
+
window.getSelection?.()?.removeAllRanges();
|
|
775
|
+
if (selectRange(rowIndex)) return;
|
|
776
|
+
selectionAnchor.current = rowKey(row);
|
|
777
|
+
selection.onToggle(row, !selection.isSelected(row));
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
if (e.metaKey || e.ctrlKey) {
|
|
781
|
+
selectionAnchor.current = rowKey(row);
|
|
782
|
+
selection.onToggle(row, !selection.isSelected(row));
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
onRowClick?.(row);
|
|
787
|
+
} : void 0,
|
|
788
|
+
children: [
|
|
789
|
+
selection && /* @__PURE__ */ jsx(
|
|
790
|
+
"td",
|
|
791
|
+
{
|
|
792
|
+
className: "w-10 px-3 py-2 align-top",
|
|
793
|
+
onClick: (e) => e.stopPropagation(),
|
|
794
|
+
children: canSelect(row) && /* @__PURE__ */ jsx(
|
|
795
|
+
"input",
|
|
796
|
+
{
|
|
797
|
+
type: "checkbox",
|
|
798
|
+
className: "size-4 accent-indigo-600",
|
|
799
|
+
checked: selection.isSelected(row),
|
|
800
|
+
onClick: (e) => {
|
|
801
|
+
if (e.shiftKey && selectRange(rowIndex)) {
|
|
802
|
+
e.preventDefault();
|
|
803
|
+
rangeClick.current = e.nativeEvent;
|
|
804
|
+
}
|
|
805
|
+
},
|
|
806
|
+
onChange: (e) => {
|
|
807
|
+
if (rangeClick.current && e.nativeEvent === rangeClick.current) {
|
|
808
|
+
rangeClick.current = null;
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
selectionAnchor.current = rowKey(row);
|
|
812
|
+
selection.onToggle(row, e.target.checked);
|
|
813
|
+
},
|
|
814
|
+
"aria-label": labels.selectRow
|
|
815
|
+
}
|
|
816
|
+
)
|
|
817
|
+
}
|
|
818
|
+
),
|
|
819
|
+
visibleColumns.map((col) => {
|
|
820
|
+
const width = widths[col.key];
|
|
821
|
+
return /* @__PURE__ */ jsx(
|
|
822
|
+
"td",
|
|
823
|
+
{
|
|
824
|
+
"data-col": col.key,
|
|
825
|
+
style: width ? { width, minWidth: width, maxWidth: width } : void 0,
|
|
826
|
+
className: cn(
|
|
827
|
+
"px-3 py-2 align-top",
|
|
828
|
+
width && "overflow-hidden text-ellipsis",
|
|
829
|
+
logicalAlign(col.className)
|
|
830
|
+
),
|
|
831
|
+
children: col === linkColumn && href ? (
|
|
832
|
+
// No `onActivate`: the click is left to bubble to the
|
|
833
|
+
// <tr> handler above, which already owns expand-vs-select.
|
|
834
|
+
// Calling it here as well would toggle the row twice.
|
|
835
|
+
/* @__PURE__ */ jsx(RowLink, { href, className: "block", children: col.cell(row) })
|
|
836
|
+
) : col.cell(row)
|
|
837
|
+
},
|
|
838
|
+
col.key
|
|
839
|
+
);
|
|
840
|
+
})
|
|
841
|
+
]
|
|
842
|
+
}
|
|
843
|
+
),
|
|
844
|
+
expansion && /* @__PURE__ */ jsx("tr", { className: "bg-[var(--bg-surface-2)] border-t border-[var(--border)]", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0", children: /* @__PURE__ */ jsx("div", { className: "w-0 min-w-full px-3 py-3", children: expansion }) }) })
|
|
845
|
+
] }, rowKey(row));
|
|
846
|
+
}),
|
|
847
|
+
slice.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
848
|
+
"td",
|
|
672
849
|
{
|
|
673
|
-
|
|
674
|
-
"
|
|
675
|
-
|
|
676
|
-
onPointerMove: moveResize,
|
|
677
|
-
onPointerUp: (e) => finishResize(e, true),
|
|
678
|
-
onPointerCancel: (e) => finishResize(e, false),
|
|
679
|
-
onDoubleClick: (e) => {
|
|
680
|
-
e.preventDefault();
|
|
681
|
-
setWidths((w) => {
|
|
682
|
-
const next = { ...w };
|
|
683
|
-
delete next[col.key];
|
|
684
|
-
return next;
|
|
685
|
-
});
|
|
686
|
-
},
|
|
687
|
-
className: "absolute right-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize select-none touch-none hover:bg-[var(--brand-bg-hover)]"
|
|
850
|
+
colSpan: totalColSpan,
|
|
851
|
+
className: "px-3 py-4 text-center text-[var(--text-muted)]",
|
|
852
|
+
children: isLoading ? /* @__PURE__ */ jsx(LoadingText, { label: labels.loading }) : empty ?? "\u2014"
|
|
688
853
|
}
|
|
689
|
-
)
|
|
854
|
+
) })
|
|
690
855
|
]
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
/* @__PURE__ */ jsxs("tbody", { children: [
|
|
697
|
-
leadingRow && /* @__PURE__ */ jsx("tr", { className: "border-t border-[var(--border)]", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0", children: leadingRow }) }),
|
|
698
|
-
slice.map((row, rowIndex) => {
|
|
699
|
-
const expanded = isExpanded?.(row) ?? false;
|
|
700
|
-
const expansion = expanded ? expandedRow?.(row) : null;
|
|
701
|
-
const rowInteractive = !!onRowClick || !!selection;
|
|
702
|
-
const href = rowHref?.(row);
|
|
703
|
-
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
704
|
-
/* @__PURE__ */ jsxs(
|
|
705
|
-
"tr",
|
|
706
|
-
{
|
|
707
|
-
...cleanAttrs(rowAttributes?.(row)),
|
|
708
|
-
className: cn(
|
|
709
|
-
"border-t border-[var(--border)]",
|
|
710
|
-
rowInteractive && "cursor-pointer hover:bg-[var(--bg-hover)]",
|
|
711
|
-
rowClassName?.(row)
|
|
712
|
-
),
|
|
713
|
-
onClick: rowInteractive ? (e) => {
|
|
714
|
-
if (selection && canSelect(row)) {
|
|
715
|
-
if (e.shiftKey) {
|
|
716
|
-
window.getSelection?.()?.removeAllRanges();
|
|
717
|
-
if (selectRange(rowIndex)) return;
|
|
718
|
-
selectionAnchor.current = rowKey(row);
|
|
719
|
-
selection.onToggle(row, !selection.isSelected(row));
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
if (e.metaKey || e.ctrlKey) {
|
|
723
|
-
selectionAnchor.current = rowKey(row);
|
|
724
|
-
selection.onToggle(row, !selection.isSelected(row));
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
onRowClick?.(row);
|
|
729
|
-
} : void 0,
|
|
730
|
-
children: [
|
|
731
|
-
selection && /* @__PURE__ */ jsx(
|
|
732
|
-
"td",
|
|
733
|
-
{
|
|
734
|
-
className: "w-10 px-3 py-2 align-top",
|
|
735
|
-
onClick: (e) => e.stopPropagation(),
|
|
736
|
-
children: canSelect(row) && /* @__PURE__ */ jsx(
|
|
737
|
-
"input",
|
|
738
|
-
{
|
|
739
|
-
type: "checkbox",
|
|
740
|
-
className: "size-4 accent-indigo-600",
|
|
741
|
-
checked: selection.isSelected(row),
|
|
742
|
-
onClick: (e) => {
|
|
743
|
-
if (e.shiftKey && selectRange(rowIndex)) e.preventDefault();
|
|
744
|
-
},
|
|
745
|
-
onChange: (e) => {
|
|
746
|
-
selectionAnchor.current = rowKey(row);
|
|
747
|
-
selection.onToggle(row, e.target.checked);
|
|
748
|
-
},
|
|
749
|
-
"aria-label": labels.selectRow
|
|
750
|
-
}
|
|
751
|
-
)
|
|
752
|
-
}
|
|
753
|
-
),
|
|
754
|
-
visibleColumns.map((col) => {
|
|
755
|
-
const width = widths[col.key];
|
|
756
|
-
return /* @__PURE__ */ jsx(
|
|
757
|
-
"td",
|
|
758
|
-
{
|
|
759
|
-
"data-col": col.key,
|
|
760
|
-
style: width ? { width, minWidth: width, maxWidth: width } : void 0,
|
|
761
|
-
className: cn("px-3 py-2 align-top", width && "overflow-hidden text-ellipsis", col.className),
|
|
762
|
-
children: col === linkColumn && href ? (
|
|
763
|
-
// No `onActivate`: the click is left to bubble to the
|
|
764
|
-
// <tr> handler above, which already owns expand-vs-select.
|
|
765
|
-
// Calling it here as well would toggle the row twice.
|
|
766
|
-
/* @__PURE__ */ jsx(RowLink, { href, className: "block", children: col.cell(row) })
|
|
767
|
-
) : col.cell(row)
|
|
768
|
-
},
|
|
769
|
-
col.key
|
|
770
|
-
);
|
|
771
|
-
})
|
|
772
|
-
]
|
|
773
|
-
}
|
|
774
|
-
),
|
|
775
|
-
expansion && /* @__PURE__ */ jsx("tr", { className: "bg-[var(--bg-surface-2)] border-t border-[var(--border)]", children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0", children: /* @__PURE__ */ jsx("div", { className: "w-0 min-w-full px-3 py-3", children: expansion }) }) })
|
|
776
|
-
] }, rowKey(row));
|
|
777
|
-
}),
|
|
778
|
-
slice.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
779
|
-
"td",
|
|
780
|
-
{
|
|
781
|
-
colSpan: totalColSpan,
|
|
782
|
-
className: "px-3 py-4 text-center text-[var(--text-muted)]",
|
|
783
|
-
children: empty ?? "\u2014"
|
|
784
|
-
}
|
|
785
|
-
) })
|
|
786
|
-
] })
|
|
787
|
-
] })
|
|
856
|
+
}
|
|
857
|
+
)
|
|
858
|
+
]
|
|
859
|
+
}
|
|
860
|
+
)
|
|
788
861
|
}
|
|
789
862
|
),
|
|
790
863
|
!unpaged && /* @__PURE__ */ jsx(
|
|
@@ -795,7 +868,7 @@ function DataTable({
|
|
|
795
868
|
pageSize: paginationPageSize,
|
|
796
869
|
total: paginationTotal,
|
|
797
870
|
onPage: goToPage,
|
|
798
|
-
onPageSize: isServer ?
|
|
871
|
+
onPageSize: isServer ? serverPagination.onPageSizeChange : (n) => {
|
|
799
872
|
setPageSize(n);
|
|
800
873
|
setPage(0);
|
|
801
874
|
},
|
|
@@ -814,9 +887,9 @@ function DataTable({
|
|
|
814
887
|
tabIndex: showSettings ? -1 : 0,
|
|
815
888
|
className: cn(
|
|
816
889
|
"group flex shrink-0 items-start justify-center overflow-hidden pt-3 transition-[width] duration-200 ease-out",
|
|
817
|
-
"border-
|
|
890
|
+
"border-s border-[var(--border)]",
|
|
818
891
|
"hover:bg-[var(--bg-hover)]",
|
|
819
|
-
showSettings ? "w-0 border-
|
|
892
|
+
showSettings ? "w-0 border-s-0" : "w-8 cursor-pointer"
|
|
820
893
|
),
|
|
821
894
|
children: /* @__PURE__ */ jsx(
|
|
822
895
|
"span",
|
|
@@ -835,7 +908,7 @@ function DataTable({
|
|
|
835
908
|
"shrink-0 overflow-hidden transition-[width] duration-200 ease-out",
|
|
836
909
|
showSettings ? "w-56" : "w-0"
|
|
837
910
|
),
|
|
838
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex w-56 flex-col border-
|
|
911
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex w-56 flex-col border-s border-[var(--border)] p-2", children: [
|
|
839
912
|
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-1", children: [
|
|
840
913
|
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase tracking-wide text-[var(--text-muted)]", children: columnsCountLabel }),
|
|
841
914
|
/* @__PURE__ */ jsx(Tooltip, { label: labels.close, portal: true, children: /* @__PURE__ */ jsx(
|
|
@@ -894,6 +967,12 @@ function DataTable({
|
|
|
894
967
|
] })
|
|
895
968
|
] });
|
|
896
969
|
}
|
|
970
|
+
function LoadingText({ label }) {
|
|
971
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
972
|
+
/* @__PURE__ */ jsx(Spinner, { label: null, className: "size-4" }),
|
|
973
|
+
label
|
|
974
|
+
] });
|
|
975
|
+
}
|
|
897
976
|
function MobileFilters({
|
|
898
977
|
columns,
|
|
899
978
|
filters,
|
|
@@ -907,6 +986,7 @@ function MobileFilters({
|
|
|
907
986
|
locale
|
|
908
987
|
}) {
|
|
909
988
|
const [open, setOpen] = useState(false);
|
|
989
|
+
const [dir, setDir] = useState("ltr");
|
|
910
990
|
const [expanded, setExpanded] = useState(null);
|
|
911
991
|
const backdropClose = useBackdropClose(() => setOpen(false));
|
|
912
992
|
useBodyScrollLock(open);
|
|
@@ -925,7 +1005,10 @@ function MobileFilters({
|
|
|
925
1005
|
"button",
|
|
926
1006
|
{
|
|
927
1007
|
type: "button",
|
|
928
|
-
onClick: () =>
|
|
1008
|
+
onClick: (e) => {
|
|
1009
|
+
setDir(dirOf(e.currentTarget));
|
|
1010
|
+
setOpen(true);
|
|
1011
|
+
},
|
|
929
1012
|
className: "inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]",
|
|
930
1013
|
children: [
|
|
931
1014
|
/* @__PURE__ */ jsx(Filter, { className: "size-4" }),
|
|
@@ -950,6 +1033,7 @@ function MobileFilters({
|
|
|
950
1033
|
className: "fixed inset-0 z-50 flex items-end justify-center bg-black/40",
|
|
951
1034
|
role: "dialog",
|
|
952
1035
|
"aria-modal": "true",
|
|
1036
|
+
dir,
|
|
953
1037
|
...backdropClose,
|
|
954
1038
|
children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[85vh] w-full flex-col overflow-hidden rounded-t-2xl bg-[var(--bg-surface)] shadow-xl", children: [
|
|
955
1039
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-b border-[var(--border)] px-4 py-3", children: [
|
|
@@ -960,7 +1044,7 @@ function MobileFilters({
|
|
|
960
1044
|
type: "button",
|
|
961
1045
|
onClick: () => setOpen(false),
|
|
962
1046
|
"aria-label": labels.close,
|
|
963
|
-
className: "-
|
|
1047
|
+
className: "-me-1 rounded p-1.5 text-[var(--text-muted)] hover:bg-[var(--bg-hover)] hover:text-[var(--text-secondary)]",
|
|
964
1048
|
children: /* @__PURE__ */ jsx(X, { className: "size-5" })
|
|
965
1049
|
}
|
|
966
1050
|
)
|
|
@@ -976,7 +1060,7 @@ function MobileFilters({
|
|
|
976
1060
|
type: "button",
|
|
977
1061
|
onClick: () => setExpanded(isItemOpen ? null : col.key),
|
|
978
1062
|
"aria-expanded": isItemOpen,
|
|
979
|
-
className: "flex w-full items-center justify-between gap-2 px-4 py-3 text-
|
|
1063
|
+
className: "flex w-full items-center justify-between gap-2 px-4 py-3 text-start",
|
|
980
1064
|
children: [
|
|
981
1065
|
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-[var(--text-secondary)]", children: [
|
|
982
1066
|
col.header,
|