@eifi1/ui-kit 0.48.1 → 0.49.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 +28 -13
- package/dist/admin/admin-action-confirm.js +1 -1
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/invitations-panel.js +5 -1
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/user-roster.d.ts +11 -5
- package/dist/admin/user-roster.js +15 -4
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/accept-invitation.js +2 -2
- package/dist/auth/accept-invitation.js.map +1 -1
- package/dist/auth/not-found-page.js +1 -1
- package/dist/auth/not-found-page.js.map +1 -1
- package/dist/auth/reset-password-form.js +2 -2
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/verify-email.js +2 -2
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/billing/plan-card.js +2 -2
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/components/breadcrumbs.d.ts +19 -1
- package/dist/components/breadcrumbs.js +11 -4
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/button-look.d.ts +37 -7
- package/dist/components/button-look.js +33 -6
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/button.d.ts +4 -1
- package/dist/components/button.js +2 -2
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +2 -1
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/chart-edge.d.ts +10 -0
- package/dist/components/chart-edge.js +57 -0
- package/dist/components/chart-edge.js.map +1 -0
- package/dist/components/chart.js +2 -1
- package/dist/components/chart.js.map +1 -1
- package/dist/components/chip.d.ts +8 -1
- package/dist/components/chip.js +4 -1
- package/dist/components/chip.js.map +1 -1
- package/dist/components/confirm-context.d.ts +5 -0
- package/dist/components/confirm-context.js +7 -0
- package/dist/components/confirm-context.js.map +1 -0
- package/dist/components/confirm-dialog.js +3 -3
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +2 -2
- package/dist/components/danger-confirm.js +1 -1
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-fit.d.ts +8 -1
- package/dist/components/data-table-fit.js +28 -4
- 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-mobile.d.ts +48 -2
- package/dist/components/data-table-mobile.js +87 -10
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table-row-actions.d.ts +2 -1
- package/dist/components/data-table-row-actions.js +9 -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 +74 -2
- package/dist/components/data-table.js +241 -221
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/error-boundary.js +2 -2
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/floating-panel.d.ts +36 -13
- package/dist/components/floating-panel.js +27 -7
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +1 -1
- package/dist/components/form-actions.js +1 -1
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/icon-button.d.ts +11 -0
- package/dist/components/icon-button.js +7 -5
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/nav-pills.d.ts +8 -1
- package/dist/components/nav-pills.js +61 -38
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/page-header-context.d.ts +8 -0
- package/dist/components/page-header-context.js +7 -0
- package/dist/components/page-header-context.js.map +1 -0
- package/dist/components/page-header.d.ts +14 -2
- package/dist/components/page-header.js +10 -1
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/pie-chart.js +2 -1
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/progress-bar.js +5 -4
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/reauth-dialog.js +1 -1
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/row-actions-labels.js +3 -1
- package/dist/components/row-actions-labels.js.map +1 -1
- package/dist/components/row-actions.d.ts +43 -9
- package/dist/components/row-actions.js +78 -15
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/section-nav.d.ts +37 -0
- package/dist/components/section-nav.js +33 -0
- package/dist/components/section-nav.js.map +1 -0
- package/dist/components/series-chart.js +8 -3
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/share-card.js +1 -1
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/signature-pad.js +1 -1
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/sparkline.js +2 -1
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.js +14 -7
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/status-dot.d.ts +5 -1
- package/dist/components/status-dot.js +4 -1
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/translation-review-editor.js +2 -2
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review.js +2 -2
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/treemap.d.ts +5 -2
- package/dist/components/treemap.js +26 -6
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/use-table-state.js +37 -6
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/data-table.d.ts +1 -0
- package/dist/data-table.js.map +1 -1
- package/dist/demo/demo-banner.js +1 -1
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/demo/demo-ended.js +1 -1
- package/dist/demo/demo-ended.js.map +1 -1
- package/dist/demo/demo-start.js +1 -1
- package/dist/demo/demo-start.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-inbox.js +1 -1
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/hooks/use-anchored-panel.js +2 -1
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-dismiss.d.ts +9 -1
- package/dist/hooks/use-dismiss.js +25 -5
- package/dist/hooks/use-dismiss.js.map +1 -1
- package/dist/hooks/use-document-title.d.ts +14 -0
- package/dist/hooks/use-document-title.js +22 -0
- package/dist/hooks/use-document-title.js.map +1 -0
- package/dist/i18n/german.js +6 -2
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +31 -1
- package/dist/i18n/kit-labels.js +43 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +6 -2
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +6 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +6 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +6 -2
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +6 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +6 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +2 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js +1 -0
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.js +2 -2
- package/dist/landing/landing-actions.js.map +1 -1
- package/dist/landing/public-header.js +2 -2
- package/dist/landing/public-header.js.map +1 -1
- package/dist/lib/clipboard-minus.d.ts +27 -0
- package/dist/lib/clipboard-minus.js +63 -0
- package/dist/lib/clipboard-minus.js.map +1 -0
- package/dist/lib/document-title.d.ts +17 -0
- package/dist/lib/document-title.js +29 -0
- package/dist/lib/document-title.js.map +1 -0
- package/dist/lib/float-clearance.js +8 -2
- package/dist/lib/float-clearance.js.map +1 -1
- package/dist/lib/format.d.ts +35 -10
- package/dist/lib/format.js +55 -11
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/minus.d.ts +22 -0
- package/dist/lib/minus.js +14 -0
- package/dist/lib/minus.js.map +1 -0
- package/dist/lib/status-tone.d.ts +30 -0
- package/dist/lib/status-tone.js +17 -0
- package/dist/lib/status-tone.js.map +1 -0
- package/dist/settings/settings-layout.js +3 -2
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/shell/account-menu-language.d.ts +1 -1
- package/dist/shell/account-menu-language.js +9 -1
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/app-shell-labels.js +2 -1
- package/dist/shell/app-shell-labels.js.map +1 -1
- package/dist/shell/app-shell.d.ts +58 -16
- package/dist/shell/app-shell.js +158 -44
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/language-code.d.ts +3 -0
- package/dist/shell/language-code.js +8 -0
- package/dist/shell/language-code.js.map +1 -0
- package/dist/shell/topbar-controls.d.ts +14 -6
- package/dist/shell/topbar-controls.js +14 -17
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/testing/css-variables.generated.d.ts +1 -1
- package/dist/testing/css-variables.generated.js +1 -1
- package/dist/testing/css-variables.generated.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +82 -15
- package/dist/theme/chart-palette.js +51 -24
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/palette-presets.d.ts +9 -0
- package/dist/theme/palette-presets.js +77 -62
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/tour/tour.js +1 -1
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +1 -1
- package/dist/wizard/stepper-nav.js +3 -3
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/admin-action-confirm.tsx +1 -1
- package/src/admin/invitations-panel.tsx +7 -3
- package/src/admin/user-roster.tsx +23 -6
- package/src/auth/accept-invitation.tsx +3 -3
- package/src/auth/not-found-page.tsx +1 -1
- package/src/auth/reset-password-form.tsx +3 -3
- package/src/auth/verify-email.tsx +3 -3
- package/src/billing/plan-card.tsx +2 -2
- package/src/components/breadcrumbs.tsx +32 -4
- package/src/components/button-look.ts +86 -15
- package/src/components/button.tsx +6 -3
- package/src/components/calendar-heatmap.tsx +2 -1
- package/src/components/chart-edge.ts +73 -0
- package/src/components/chart.tsx +3 -1
- package/src/components/chip.tsx +10 -1
- package/src/components/confirm-context.ts +7 -0
- package/src/components/confirm-dialog.tsx +3 -3
- package/src/components/danger-confirm.tsx +3 -3
- package/src/components/data-table-fit.ts +58 -8
- 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-mobile.tsx +162 -11
- package/src/components/data-table-row-actions.tsx +12 -3
- package/src/components/data-table-row.tsx +485 -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 +367 -326
- package/src/components/error-boundary.tsx +2 -2
- package/src/components/floating-panel.tsx +67 -16
- package/src/components/form-actions.tsx +2 -2
- package/src/components/icon-button.tsx +21 -8
- package/src/components/nav-pills.tsx +29 -2
- package/src/components/page-header-context.ts +8 -0
- package/src/components/page-header.tsx +34 -2
- package/src/components/pie-chart.tsx +2 -1
- package/src/components/progress-bar.tsx +6 -3
- package/src/components/reauth-dialog.tsx +1 -1
- package/src/components/row-actions-labels.ts +2 -0
- package/src/components/row-actions.tsx +154 -33
- package/src/components/section-nav.tsx +65 -0
- package/src/components/series-chart.tsx +12 -3
- package/src/components/share-card.tsx +1 -1
- package/src/components/signature-pad.tsx +1 -1
- package/src/components/sparkline.tsx +2 -1
- package/src/components/stat-tile.tsx +19 -7
- package/src/components/status-dot.tsx +7 -1
- package/src/components/tooltip.tsx +3 -1
- package/src/components/translation-review-editor.tsx +2 -2
- package/src/components/translation-review.tsx +2 -2
- package/src/components/treemap.tsx +34 -8
- package/src/components/use-table-state.ts +63 -8
- package/src/data-table.ts +5 -3
- package/src/demo/demo-banner.tsx +1 -1
- package/src/demo/demo-ended.tsx +1 -1
- package/src/demo/demo-start.tsx +1 -1
- package/src/feedback/feedback-inbox.tsx +1 -1
- package/src/hooks/use-anchored-panel.ts +9 -1
- package/src/hooks/use-dismiss.ts +43 -4
- package/src/hooks/use-document-title.ts +31 -0
- package/src/i18n/german.ts +4 -0
- package/src/i18n/kit-labels.tsx +76 -1
- package/src/i18n/locales/es.ts +4 -0
- package/src/i18n/locales/fr.ts +4 -0
- package/src/i18n/locales/hu.ts +4 -0
- package/src/i18n/locales/it.ts +4 -0
- package/src/i18n/locales/zh.ts +4 -0
- package/src/i18n/review.ts +2 -0
- package/src/i18n/shared-labels.ts +1 -0
- package/src/index.ts +13 -0
- package/src/landing/landing-actions.tsx +2 -2
- package/src/landing/public-header.tsx +2 -2
- package/src/lib/clipboard-minus.ts +94 -0
- package/src/lib/document-title.ts +41 -0
- package/src/lib/float-clearance.ts +19 -3
- package/src/lib/format.ts +115 -30
- package/src/lib/minus.ts +40 -0
- package/src/lib/status-tone.ts +43 -0
- package/src/settings/settings-layout.tsx +3 -2
- package/src/shell/account-menu-language.tsx +14 -2
- package/src/shell/app-shell-labels.ts +1 -0
- package/src/shell/app-shell.tsx +298 -69
- package/src/shell/language-code.ts +5 -0
- package/src/shell/topbar-controls.tsx +35 -15
- package/src/testing/css-variables.generated.ts +6 -6
- package/src/theme/chart-palette.ts +102 -20
- package/src/theme/palette-presets.ts +121 -84
- package/src/tour/tour.tsx +1 -1
- package/src/wizard/stepper-nav.tsx +4 -4
- package/tokens.css +28 -18
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
const SELECT_KEY = "\0select";
|
|
4
|
+
const VIRTUAL_SELECT_COL = SELECT_KEY;
|
|
5
|
+
function firstBelow(m, y) {
|
|
6
|
+
let lo = 0;
|
|
7
|
+
let hi = m.n;
|
|
8
|
+
while (lo < hi) {
|
|
9
|
+
const mid = lo + hi >> 1;
|
|
10
|
+
if (m.tops[mid] + m.h[mid] > y) hi = mid;
|
|
11
|
+
else lo = mid + 1;
|
|
12
|
+
}
|
|
13
|
+
return lo;
|
|
14
|
+
}
|
|
15
|
+
function lastAbove(m, y) {
|
|
16
|
+
let lo = 0;
|
|
17
|
+
let hi = m.n;
|
|
18
|
+
while (lo < hi) {
|
|
19
|
+
const mid = lo + hi >> 1;
|
|
20
|
+
if (m.tops[mid] < y) lo = mid + 1;
|
|
21
|
+
else hi = mid;
|
|
22
|
+
}
|
|
23
|
+
return lo;
|
|
24
|
+
}
|
|
25
|
+
function planBodies(m, groups, start, end, pinned) {
|
|
26
|
+
const rendered = /* @__PURE__ */ new Set();
|
|
27
|
+
for (let i = Math.max(0, start); i < Math.min(m.n, end); i++) rendered.add(i);
|
|
28
|
+
for (const p of pinned) if (p >= 0 && p < m.n) rendered.add(p);
|
|
29
|
+
const sorted = [...rendered].sort((a, b) => a - b);
|
|
30
|
+
let anchor = -1;
|
|
31
|
+
if (sorted.length > 0 && start < m.n) {
|
|
32
|
+
const s = Math.max(0, start);
|
|
33
|
+
const g = groups.findIndex((gr) => s >= gr.start && s < gr.end);
|
|
34
|
+
if (g >= 0) anchor = groups[g].first;
|
|
35
|
+
}
|
|
36
|
+
const bottom = (i) => m.tops[i] + m.h[i];
|
|
37
|
+
const out = [];
|
|
38
|
+
let k = 0;
|
|
39
|
+
let skippedFrom = -1;
|
|
40
|
+
const flushSkipped = (upTo) => {
|
|
41
|
+
if (skippedFrom < 0) return;
|
|
42
|
+
out.push({ kind: "spacer", key: `vs:${skippedFrom}`, height: m.gTop[upTo] - m.gTop[skippedFrom] });
|
|
43
|
+
skippedFrom = -1;
|
|
44
|
+
};
|
|
45
|
+
groups.forEach((g, gi) => {
|
|
46
|
+
while (k < sorted.length && sorted[k] < g.start) k++;
|
|
47
|
+
const items = [];
|
|
48
|
+
let prevBottom = m.tops[g.start] ?? m.gTop[gi + 1];
|
|
49
|
+
let any = false;
|
|
50
|
+
while (k < sorted.length && sorted[k] < g.end) {
|
|
51
|
+
const i = sorted[k++];
|
|
52
|
+
const gap = m.tops[i] - prevBottom;
|
|
53
|
+
if (gap > 0.01) items.push({ kind: "gap", key: `gap:${i}`, height: gap });
|
|
54
|
+
items.push({ kind: "row", index: i });
|
|
55
|
+
prevBottom = bottom(i);
|
|
56
|
+
any = true;
|
|
57
|
+
}
|
|
58
|
+
if (!any && gi !== anchor) {
|
|
59
|
+
if (skippedFrom < 0) skippedFrom = gi;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
flushSkipped(gi);
|
|
63
|
+
const rest = m.gTop[gi + 1] - prevBottom;
|
|
64
|
+
if (rest > 0.01) items.push({ kind: "gap", key: `gap:end:${gi}`, height: rest });
|
|
65
|
+
out.push({ kind: "group", group: gi, items });
|
|
66
|
+
});
|
|
67
|
+
flushSkipped(groups.length);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function useRowWindow({
|
|
71
|
+
enabled,
|
|
72
|
+
rows,
|
|
73
|
+
rowKey,
|
|
74
|
+
groups,
|
|
75
|
+
expanded,
|
|
76
|
+
pinnedKeys,
|
|
77
|
+
scrollerRef,
|
|
78
|
+
tableRef,
|
|
79
|
+
options,
|
|
80
|
+
compact,
|
|
81
|
+
rowsBefore,
|
|
82
|
+
rowsAfter,
|
|
83
|
+
colKeys,
|
|
84
|
+
lockable,
|
|
85
|
+
resetKey
|
|
86
|
+
}) {
|
|
87
|
+
const overscan = Math.max(1, options.overscan ?? 12);
|
|
88
|
+
const estimate = options.estimateRowHeight ?? (compact ? 29 : 37);
|
|
89
|
+
const n = rows.length;
|
|
90
|
+
const [measured, setMeasured] = useState(() => ({
|
|
91
|
+
heights: /* @__PURE__ */ new Map(),
|
|
92
|
+
details: /* @__PURE__ */ new Map(),
|
|
93
|
+
sum: 0,
|
|
94
|
+
count: 0,
|
|
95
|
+
band: [estimate, estimate * 0.8]
|
|
96
|
+
}));
|
|
97
|
+
const initialEnd = () => Math.min(n, Math.ceil((typeof window === "undefined" ? 800 : Math.min(window.innerHeight || 800, 1600)) / estimate) + overscan);
|
|
98
|
+
const [range, setRange] = useState(() => ({ start: 0, end: initialEnd() }));
|
|
99
|
+
const [focusTarget, setFocusTarget] = useState(null);
|
|
100
|
+
const [focusKey, setFocusKey] = useState(null);
|
|
101
|
+
const [scrollerWidth, setScrollerWidth] = useState(0);
|
|
102
|
+
const [lock, setLock] = useState(null);
|
|
103
|
+
const naturalOverflow = useRef(false);
|
|
104
|
+
const expandedSig = expanded.join(",");
|
|
105
|
+
const model = useMemo(() => {
|
|
106
|
+
if (!enabled) return null;
|
|
107
|
+
const keys = rows.map(rowKey);
|
|
108
|
+
const avg = measured.count > 0 ? measured.sum / measured.count : estimate;
|
|
109
|
+
const open = new Set(expanded);
|
|
110
|
+
const h = new Float64Array(n);
|
|
111
|
+
for (let i = 0; i < n; i++) {
|
|
112
|
+
h[i] = (measured.heights.get(keys[i]) ?? avg) + (open.has(i) ? measured.details.get(keys[i]) ?? 0 : 0);
|
|
113
|
+
}
|
|
114
|
+
const tops = new Float64Array(n + 1);
|
|
115
|
+
const gTop = new Float64Array(groups.length + 1);
|
|
116
|
+
const ariaRows = new Int32Array(n);
|
|
117
|
+
const ariaBands = new Int32Array(groups.length * 2);
|
|
118
|
+
let y = 0;
|
|
119
|
+
let aria = rowsBefore + 1;
|
|
120
|
+
groups.forEach((g, gi) => {
|
|
121
|
+
gTop[gi] = y;
|
|
122
|
+
for (const level of g.bands) {
|
|
123
|
+
y += measured.band[level - 1];
|
|
124
|
+
ariaBands[gi * 2 + level - 1] = aria++;
|
|
125
|
+
}
|
|
126
|
+
for (let i = g.start; i < g.end; i++) {
|
|
127
|
+
tops[i] = y;
|
|
128
|
+
y += h[i];
|
|
129
|
+
ariaRows[i] = aria++;
|
|
130
|
+
if (open.has(i)) aria++;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
gTop[groups.length] = y;
|
|
134
|
+
tops[n] = y;
|
|
135
|
+
return { n, keys, tops, h, gTop, total: y, ariaRows, ariaBands, rowCount: aria - 1 + rowsAfter };
|
|
136
|
+
}, [enabled, rows, rowKey, groups, expandedSig, measured, estimate, n, rowsBefore, rowsAfter]);
|
|
137
|
+
const pinned = useMemo(() => {
|
|
138
|
+
if (!model) return [];
|
|
139
|
+
const out = [...expanded];
|
|
140
|
+
for (const key of [...pinnedKeys, focusKey]) {
|
|
141
|
+
if (key === null) continue;
|
|
142
|
+
const i = model.keys.indexOf(key);
|
|
143
|
+
if (i >= 0) out.push(i);
|
|
144
|
+
}
|
|
145
|
+
if (focusTarget !== null) out.push(focusTarget);
|
|
146
|
+
return out;
|
|
147
|
+
}, [model, expanded, pinnedKeys, focusKey, focusTarget]);
|
|
148
|
+
const pinnedSig = pinned.join(",");
|
|
149
|
+
const start = Math.min(range.start, n);
|
|
150
|
+
const end = Math.min(range.end, n);
|
|
151
|
+
const bodies = useMemo(
|
|
152
|
+
() => model ? planBodies(model, groups, start, end, pinned) : [],
|
|
153
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
154
|
+
[model, groups, start, end, pinnedSig]
|
|
155
|
+
);
|
|
156
|
+
const lockSig = `${resetKey}|${scrollerWidth}|${colKeys.join(",")}`;
|
|
157
|
+
const colWidths = lock && lock.sig === lockSig ? lock.widths : null;
|
|
158
|
+
const latest = useRef({ model, colWidths, lockSig, colKeys, lockable, overscan });
|
|
159
|
+
useLayoutEffect(() => {
|
|
160
|
+
latest.current = { model, colWidths, lockSig, colKeys, lockable, overscan };
|
|
161
|
+
});
|
|
162
|
+
const update = useCallback(() => {
|
|
163
|
+
const { model: m, overscan: over } = latest.current;
|
|
164
|
+
const sc = scrollerRef.current;
|
|
165
|
+
const table = tableRef.current;
|
|
166
|
+
if (!m || !sc || !table) return;
|
|
167
|
+
const origin = table.querySelector("tbody[data-vt-body]");
|
|
168
|
+
if (!origin) return;
|
|
169
|
+
const sr = sc.getBoundingClientRect();
|
|
170
|
+
const top = Math.max(sr.top, 0);
|
|
171
|
+
const bottom = Math.min(sr.bottom, window.innerHeight || sr.bottom);
|
|
172
|
+
if (!(bottom > top)) return;
|
|
173
|
+
const o = origin.getBoundingClientRect().top;
|
|
174
|
+
const a = Math.min(firstBelow(m, top - o), m.n);
|
|
175
|
+
const b = Math.max(a, Math.min(lastAbove(m, bottom - o), m.n));
|
|
176
|
+
setRange(
|
|
177
|
+
(prev) => prev.start <= a && prev.end >= b && prev.end <= m.n && prev.end - prev.start <= b - a + 4 * over ? prev : { start: Math.max(0, a - over), end: Math.min(m.n, b + over) }
|
|
178
|
+
);
|
|
179
|
+
}, [scrollerRef, tableRef]);
|
|
180
|
+
const measure = useCallback(() => {
|
|
181
|
+
const { model: m, colWidths: locked, lockSig: sig, colKeys: cols, lockable: lockKeys } = latest.current;
|
|
182
|
+
const table = tableRef.current;
|
|
183
|
+
const sc = scrollerRef.current;
|
|
184
|
+
if (!m || !table || !sc) return;
|
|
185
|
+
const trs = table.rows;
|
|
186
|
+
const rects = Array.from(trs, (tr) => tr.getBoundingClientRect());
|
|
187
|
+
const rowSamples = [];
|
|
188
|
+
const detailSamples = [];
|
|
189
|
+
const bandSamples = [];
|
|
190
|
+
for (let k = 0; k < trs.length; k++) {
|
|
191
|
+
const own = rects[k];
|
|
192
|
+
const next = rects[k + 1];
|
|
193
|
+
const h = next && next.top > own.top ? next.top - own.top : own.height;
|
|
194
|
+
if (!(h > 0)) continue;
|
|
195
|
+
const ds = trs[k].dataset;
|
|
196
|
+
if (ds.rowIndex !== void 0) {
|
|
197
|
+
const key = m.keys[Number(ds.rowIndex)];
|
|
198
|
+
if (key !== void 0) rowSamples.push([key, h]);
|
|
199
|
+
} else if (ds.rowDetail !== void 0) {
|
|
200
|
+
const key = m.keys[Number(ds.rowDetail)];
|
|
201
|
+
if (key !== void 0) detailSamples.push([key, h]);
|
|
202
|
+
} else if (ds.groupRow === "1" || ds.groupRow === "2") {
|
|
203
|
+
bandSamples.push([ds.groupRow === "1" ? 0 : 1, h]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (rowSamples.length + detailSamples.length + bandSamples.length > 0) {
|
|
207
|
+
setMeasured((prev) => {
|
|
208
|
+
let { heights, details, sum, count } = prev;
|
|
209
|
+
let band = prev.band;
|
|
210
|
+
for (const [key, h] of rowSamples) {
|
|
211
|
+
const old = heights.get(key);
|
|
212
|
+
if (old !== void 0 && Math.abs(old - h) <= 0.5) continue;
|
|
213
|
+
if (heights === prev.heights) heights = new Map(heights);
|
|
214
|
+
heights.set(key, h);
|
|
215
|
+
sum += h - (old ?? 0);
|
|
216
|
+
if (old === void 0) count++;
|
|
217
|
+
}
|
|
218
|
+
for (const [key, h] of detailSamples) {
|
|
219
|
+
const old = details.get(key);
|
|
220
|
+
if (old !== void 0 && Math.abs(old - h) <= 0.5) continue;
|
|
221
|
+
if (details === prev.details) details = new Map(details);
|
|
222
|
+
details.set(key, h);
|
|
223
|
+
}
|
|
224
|
+
for (const [level, h] of bandSamples) {
|
|
225
|
+
if (Math.abs(band[level] - h) <= 0.5) continue;
|
|
226
|
+
band = level === 0 ? [h, band[1]] : [band[0], h];
|
|
227
|
+
}
|
|
228
|
+
return heights === prev.heights && details === prev.details && band === prev.band ? prev : { heights, details, sum, count, band };
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const cells = table.tHead?.rows[0]?.cells;
|
|
232
|
+
if (!cells || cells.length !== cols.length) return;
|
|
233
|
+
const widths = {};
|
|
234
|
+
let anyWidth = false;
|
|
235
|
+
for (let c = 0; c < cells.length; c++) {
|
|
236
|
+
if (!lockKeys.has(cols[c])) continue;
|
|
237
|
+
const w = cells[c].getBoundingClientRect().width;
|
|
238
|
+
if (w > 0) {
|
|
239
|
+
widths[cols[c]] = w;
|
|
240
|
+
anyWidth = true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!anyWidth) return;
|
|
244
|
+
const over = table.getBoundingClientRect().width > sc.clientWidth + 1;
|
|
245
|
+
if (!locked) {
|
|
246
|
+
naturalOverflow.current = over;
|
|
247
|
+
setLock({ sig, widths });
|
|
248
|
+
} else if (over && !naturalOverflow.current) {
|
|
249
|
+
setLock(null);
|
|
250
|
+
} else {
|
|
251
|
+
let grew = false;
|
|
252
|
+
const merged = { ...locked };
|
|
253
|
+
for (const [key, w] of Object.entries(widths)) {
|
|
254
|
+
if (w > (merged[key] ?? 0) + 0.5) {
|
|
255
|
+
merged[key] = w;
|
|
256
|
+
grew = true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (grew) setLock({ sig, widths: merged });
|
|
260
|
+
}
|
|
261
|
+
}, [scrollerRef, tableRef]);
|
|
262
|
+
const frame = useRef(0);
|
|
263
|
+
const schedule = useCallback(() => {
|
|
264
|
+
if (frame.current) return;
|
|
265
|
+
const run = () => {
|
|
266
|
+
frame.current = 0;
|
|
267
|
+
measure();
|
|
268
|
+
update();
|
|
269
|
+
};
|
|
270
|
+
frame.current = typeof requestAnimationFrame === "undefined" ? -setTimeout(run, 16) : requestAnimationFrame(run);
|
|
271
|
+
}, [measure, update]);
|
|
272
|
+
useEffect(
|
|
273
|
+
() => () => {
|
|
274
|
+
if (frame.current > 0) cancelAnimationFrame(frame.current);
|
|
275
|
+
else if (frame.current < 0) clearTimeout(-frame.current);
|
|
276
|
+
frame.current = 0;
|
|
277
|
+
},
|
|
278
|
+
[]
|
|
279
|
+
);
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
if (!enabled) return;
|
|
282
|
+
const onScroll = () => update();
|
|
283
|
+
window.addEventListener("scroll", onScroll, { capture: true, passive: true });
|
|
284
|
+
window.addEventListener("resize", onScroll, { passive: true });
|
|
285
|
+
const sc = scrollerRef.current;
|
|
286
|
+
let ro;
|
|
287
|
+
if (sc && typeof ResizeObserver !== "undefined") {
|
|
288
|
+
ro = new ResizeObserver(() => {
|
|
289
|
+
setScrollerWidth(Math.round(sc.clientWidth));
|
|
290
|
+
update();
|
|
291
|
+
});
|
|
292
|
+
ro.observe(sc);
|
|
293
|
+
}
|
|
294
|
+
return () => {
|
|
295
|
+
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
296
|
+
window.removeEventListener("resize", onScroll);
|
|
297
|
+
ro?.disconnect();
|
|
298
|
+
};
|
|
299
|
+
}, [enabled, update, scrollerRef]);
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
const table = tableRef.current;
|
|
302
|
+
if (!enabled || !table) return;
|
|
303
|
+
const onIn = (e) => {
|
|
304
|
+
const tr = e.target?.closest?.("tr[data-row-index], tr[data-row-detail]");
|
|
305
|
+
const index = tr ? Number(tr.dataset.rowIndex ?? tr.dataset.rowDetail) : NaN;
|
|
306
|
+
const key = Number.isNaN(index) ? void 0 : latest.current.model?.keys[index];
|
|
307
|
+
setFocusKey(key ?? null);
|
|
308
|
+
setFocusTarget(null);
|
|
309
|
+
};
|
|
310
|
+
const onOut = (e) => {
|
|
311
|
+
const to = e.relatedTarget;
|
|
312
|
+
if (!to || !table.contains(to)) setFocusKey(null);
|
|
313
|
+
};
|
|
314
|
+
table.addEventListener("focusin", onIn);
|
|
315
|
+
table.addEventListener("focusout", onOut);
|
|
316
|
+
return () => {
|
|
317
|
+
table.removeEventListener("focusin", onIn);
|
|
318
|
+
table.removeEventListener("focusout", onOut);
|
|
319
|
+
};
|
|
320
|
+
}, [enabled, tableRef]);
|
|
321
|
+
const dataSig = n > 0 && model ? `${n}:${String(model.keys[0])}:${String(model.keys[n - 1])}` : "0";
|
|
322
|
+
const renderSig = `${start}:${end}:${dataSig}:${expandedSig}:${pinnedSig}:${lockSig}:${colWidths ? 1 : 0}`;
|
|
323
|
+
const lastRender = useRef("");
|
|
324
|
+
useLayoutEffect(() => {
|
|
325
|
+
if (!enabled || lastRender.current === renderSig) return;
|
|
326
|
+
lastRender.current = renderSig;
|
|
327
|
+
schedule();
|
|
328
|
+
});
|
|
329
|
+
const total = model?.total ?? 0;
|
|
330
|
+
useLayoutEffect(() => {
|
|
331
|
+
if (enabled) schedule();
|
|
332
|
+
}, [enabled, schedule, total, n]);
|
|
333
|
+
useLayoutEffect(() => {
|
|
334
|
+
if (focusTarget === null) return;
|
|
335
|
+
tableRef.current?.querySelector(`tr[data-row-index="${focusTarget}"]`)?.focus();
|
|
336
|
+
}, [focusTarget, bodies, tableRef]);
|
|
337
|
+
const focusRow = useCallback(
|
|
338
|
+
(i) => {
|
|
339
|
+
const el = tableRef.current?.querySelector(`tr[data-row-index="${i}"]`);
|
|
340
|
+
if (el) el.focus();
|
|
341
|
+
else setFocusTarget(i);
|
|
342
|
+
},
|
|
343
|
+
[tableRef]
|
|
344
|
+
);
|
|
345
|
+
if (!enabled || !model) return null;
|
|
346
|
+
return {
|
|
347
|
+
bodies,
|
|
348
|
+
rowCount: model.rowCount,
|
|
349
|
+
ariaRow: (i) => model.ariaRows[i],
|
|
350
|
+
ariaBand: (g, level) => model.ariaBands[g * 2 + level - 1],
|
|
351
|
+
colWidths,
|
|
352
|
+
focusRow
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function rowNavTarget(from, key, n) {
|
|
356
|
+
if (n === 0) return null;
|
|
357
|
+
if (key === "ArrowDown") return Math.min(n - 1, from + 1);
|
|
358
|
+
if (key === "ArrowUp") return Math.max(0, from - 1);
|
|
359
|
+
if (key === "Home") return 0;
|
|
360
|
+
if (key === "End") return n - 1;
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
export {
|
|
364
|
+
VIRTUAL_SELECT_COL,
|
|
365
|
+
planBodies,
|
|
366
|
+
rowNavTarget,
|
|
367
|
+
useRowWindow
|
|
368
|
+
};
|
|
369
|
+
//# sourceMappingURL=data-table-virtual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/data-table-virtual.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { RefObject } from \"react\";\n\n// DataTable's row windowing (0.48.2, keksdose dev #632 — Marcel: \"The table is extremely\n// slow. Is it virtualised or is everytime the whole table rendered?\"). Opt-in through\n// `virtualize`: the desktop table renders the rows near the visible part of its scroller\n// (plus `overscan`) and stands spacer rows in for the rest, inside each group's own\n// `<tbody>`, so the sticky group bands keep working as they do on a full table — a band\n// cell's sticky containing block is the TABLE, and the latest band of each level that has\n// scrolled past is the one drawn (Chromium, checked with a probe at the group's middle,\n// its end and the next group's start).\n//\n// What it keeps rendered whatever the scroll: the header, the leading row, the band rows\n// of every group that has a rendered row (and the first day of the period the window\n// starts in, whose band is the period's), every OPEN row (`isExpanded`, so an inline\n// editor keeps its state), the roving tab stop, a row holding the focus, and the row the\n// keyboard is moving to.\n//\n// Heights: each rendered row is measured after render (the distance to the next row's\n// top, which is exact under collapsed borders where a row's own box is half a border\n// short) and remembered by its key; a row never rendered counts as the average of the\n// measured ones, or `estimateRowHeight` before any. The spacers are the sums, so the\n// scroll height settles as rows are seen. Scroll anchoring (the browser's) keeps the rows\n// in view still while a spacer above them is corrected.\n//\n// Column widths: in an auto table layout a column is as wide as its widest RENDERED\n// cell, so rows coming and going would move the columns. The header cells' widths are\n// read after the first render and locked into a `<colgroup>`, only ever growing while the\n// rows scroll (a wider cell arriving widens its column once; one leaving narrows\n// nothing). Re-measured from scratch when the data, the columns, a user width, the text\n// size or the scroller's width change — and when a grown column would push the table\n// past its scroller, which it fit before. A `grow` column and a user-resized one are not\n// locked (the first takes the rest, the second is pinned already).\n\n/** {@link DataTableProps.virtualize}'s options. */\nexport interface DataTableVirtualize {\n /** Rows rendered beyond each edge of the visible part. Default 12. */\n overscan?: number;\n /** A row's height in px before it has been measured. Default: 37 (`comfortable`) /\n * 29 (`compact`) — the kit's one-line rows. */\n estimateRowHeight?: number;\n}\n\n/** One innermost group's run of rows, `[start, end)` in the rows on screen, with the\n * band levels its `<tbody>` opens with. `first` is the index of the innermost group that\n * opens its level-1 group (itself with one level). Ungrouped: one run with no bands. */\nexport interface VirtualGroup {\n start: number;\n end: number;\n bands: readonly (1 | 2)[];\n first: number;\n}\n\n/** A row, or a spacer standing in for the rows between two rendered ones. */\nexport type VirtualItem = { kind: \"row\"; index: number } | { kind: \"gap\"; key: string; height: number };\n\n/** A group's `<tbody>` with its rendered rows, or one spacer `<tbody>` for a run of\n * groups of which nothing is rendered. */\nexport type VirtualBody =\n | { kind: \"spacer\"; key: string; height: number }\n | { kind: \"group\"; group: number; items: VirtualItem[] };\n\nexport interface RowWindow {\n bodies: VirtualBody[];\n /** `aria-rowcount`: every row of the table, header, bands, details and footer included. */\n rowCount: number;\n /** `aria-rowindex` of data row `i`; its detail row (open) is the next one. */\n ariaRow: (i: number) => number;\n /** `aria-rowindex` of group `g`'s band of `level`. */\n ariaBand: (g: number, level: 1 | 2) => number;\n /** The locked widths for the `<colgroup>`, by column key; null while measuring. */\n colWidths: Record<string, number> | null;\n /** Move the focus to row `i`, rendering it first when it is not. */\n focusRow: (i: number) => void;\n}\n\n/** The heights measured so far, by row key; the bands' by level. */\ninterface Measured {\n heights: Map<string | number, number>;\n details: Map<string | number, number>;\n sum: number;\n count: number;\n band: [number, number];\n}\n\nconst SELECT_KEY = \"\\u0000select\";\n/** The `<colgroup>` key of the selection column. */\nexport const VIRTUAL_SELECT_COL = SELECT_KEY;\n\ninterface Model {\n n: number;\n keys: (string | number)[];\n /** Top of row i, from the top of the first group's `<tbody>`. */\n tops: Float64Array;\n /** Full height of row i (its detail row included while open). */\n h: Float64Array;\n /** Top of group g's `<tbody>`; [groups.length] is the total. */\n gTop: Float64Array;\n total: number;\n ariaRows: Int32Array;\n ariaBands: Int32Array;\n rowCount: number;\n}\n\n/** First index whose bottom is below `y` (n when none). */\nfunction firstBelow(m: Model, y: number): number {\n let lo = 0;\n let hi = m.n;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (m.tops[mid] + m.h[mid] > y) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n}\n\n/** One past the last index whose top is above `y`. */\nfunction lastAbove(m: Model, y: number): number {\n let lo = 0;\n let hi = m.n;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (m.tops[mid] < y) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/** The `<tbody>`s to render: the groups holding a rendered row (or the period's first\n * day, for its band), and one spacer for each run of groups in between. Pure. */\nexport function planBodies(\n m: Pick<Model, \"n\" | \"tops\" | \"h\" | \"gTop\">,\n groups: readonly VirtualGroup[],\n start: number,\n end: number,\n pinned: readonly number[],\n): VirtualBody[] {\n const rendered = new Set<number>();\n for (let i = Math.max(0, start); i < Math.min(m.n, end); i++) rendered.add(i);\n for (const p of pinned) if (p >= 0 && p < m.n) rendered.add(p);\n const sorted = [...rendered].sort((a, b) => a - b);\n // The group the window starts in, and the first day of its period.\n let anchor = -1;\n if (sorted.length > 0 && start < m.n) {\n const s = Math.max(0, start);\n const g = groups.findIndex((gr) => s >= gr.start && s < gr.end);\n if (g >= 0) anchor = groups[g].first;\n }\n const bottom = (i: number) => m.tops[i] + m.h[i];\n const out: VirtualBody[] = [];\n let k = 0;\n let skippedFrom = -1;\n const flushSkipped = (upTo: number) => {\n if (skippedFrom < 0) return;\n out.push({ kind: \"spacer\", key: `vs:${skippedFrom}`, height: m.gTop[upTo] - m.gTop[skippedFrom] });\n skippedFrom = -1;\n };\n groups.forEach((g, gi) => {\n while (k < sorted.length && sorted[k] < g.start) k++;\n const items: VirtualItem[] = [];\n let prevBottom = m.tops[g.start] ?? m.gTop[gi + 1];\n let any = false;\n while (k < sorted.length && sorted[k] < g.end) {\n const i = sorted[k++];\n const gap = m.tops[i] - prevBottom;\n if (gap > 0.01) items.push({ kind: \"gap\", key: `gap:${i}`, height: gap });\n items.push({ kind: \"row\", index: i });\n prevBottom = bottom(i);\n any = true;\n }\n if (!any && gi !== anchor) {\n if (skippedFrom < 0) skippedFrom = gi;\n return;\n }\n flushSkipped(gi);\n const rest = m.gTop[gi + 1] - prevBottom;\n if (rest > 0.01) items.push({ kind: \"gap\", key: `gap:end:${gi}`, height: rest });\n out.push({ kind: \"group\", group: gi, items });\n });\n flushSkipped(groups.length);\n return out;\n}\n\nexport function useRowWindow<T>({\n enabled,\n rows,\n rowKey,\n groups,\n expanded,\n pinnedKeys,\n scrollerRef,\n tableRef,\n options,\n compact,\n rowsBefore,\n rowsAfter,\n colKeys,\n lockable,\n resetKey,\n}: {\n enabled: boolean;\n /** The rows on screen, in order. */\n rows: T[];\n rowKey: (row: T) => string | number;\n groups: readonly VirtualGroup[];\n /** Indices of the open rows: always rendered, their detail rows counted. */\n expanded: readonly number[];\n /** Keys always rendered (the roving tab stop). */\n pinnedKeys: readonly (string | number | null)[];\n scrollerRef: RefObject<HTMLElement | null>;\n tableRef: RefObject<HTMLTableElement | null>;\n options: DataTableVirtualize;\n compact: boolean;\n /** Rows above the first group: the header, the leading row. */\n rowsBefore: number;\n /** Rows after the last: the totals row. */\n rowsAfter: number;\n /** The header cells' keys, in order (the selection column as {@link VIRTUAL_SELECT_COL}). */\n colKeys: readonly string[];\n /** The keys whose width is locked (not a `grow` column, not a user-resized one). */\n lockable: ReadonlySet<string>;\n /** Anything that re-measures the column widths from scratch when it changes. */\n resetKey: string;\n}): RowWindow | null {\n const overscan = Math.max(1, options.overscan ?? 12);\n const estimate = options.estimateRowHeight ?? (compact ? 29 : 37);\n const n = rows.length;\n\n const [measured, setMeasured] = useState<Measured>(() => ({\n heights: new Map(),\n details: new Map(),\n sum: 0,\n count: 0,\n band: [estimate, estimate * 0.8],\n }));\n const initialEnd = () =>\n Math.min(n, Math.ceil((typeof window === \"undefined\" ? 800 : Math.min(window.innerHeight || 800, 1600)) / estimate) + overscan);\n const [range, setRange] = useState(() => ({ start: 0, end: initialEnd() }));\n const [focusTarget, setFocusTarget] = useState<number | null>(null);\n const [focusKey, setFocusKey] = useState<string | number | null>(null);\n const [scrollerWidth, setScrollerWidth] = useState(0);\n const [lock, setLock] = useState<{ sig: string; widths: Record<string, number> } | null>(null);\n const naturalOverflow = useRef(false);\n\n const expandedSig = expanded.join(\",\");\n const model = useMemo<Model | null>(() => {\n if (!enabled) return null;\n const keys = rows.map(rowKey);\n const avg = measured.count > 0 ? measured.sum / measured.count : estimate;\n const open = new Set(expanded);\n const h = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n h[i] = (measured.heights.get(keys[i]) ?? avg) + (open.has(i) ? (measured.details.get(keys[i]) ?? 0) : 0);\n }\n const tops = new Float64Array(n + 1);\n const gTop = new Float64Array(groups.length + 1);\n const ariaRows = new Int32Array(n);\n const ariaBands = new Int32Array(groups.length * 2);\n let y = 0;\n let aria = rowsBefore + 1;\n groups.forEach((g, gi) => {\n gTop[gi] = y;\n for (const level of g.bands) {\n y += measured.band[level - 1];\n ariaBands[gi * 2 + level - 1] = aria++;\n }\n for (let i = g.start; i < g.end; i++) {\n tops[i] = y;\n y += h[i];\n ariaRows[i] = aria++;\n if (open.has(i)) aria++;\n }\n });\n gTop[groups.length] = y;\n tops[n] = y;\n return { n, keys, tops, h, gTop, total: y, ariaRows, ariaBands, rowCount: aria - 1 + rowsAfter };\n // `expanded` by its signature.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, rows, rowKey, groups, expandedSig, measured, estimate, n, rowsBefore, rowsAfter]);\n\n // The rows outside the range that stay: open rows, the tab stop, the focused row and\n // the keyboard's target.\n const pinned = useMemo(() => {\n if (!model) return [];\n const out = [...expanded];\n for (const key of [...pinnedKeys, focusKey]) {\n if (key === null) continue;\n const i = model.keys.indexOf(key);\n if (i >= 0) out.push(i);\n }\n if (focusTarget !== null) out.push(focusTarget);\n return out;\n }, [model, expanded, pinnedKeys, focusKey, focusTarget]);\n const pinnedSig = pinned.join(\",\");\n\n const start = Math.min(range.start, n);\n const end = Math.min(range.end, n);\n const bodies = useMemo(\n () => (model ? planBodies(model, groups, start, end, pinned) : []),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [model, groups, start, end, pinnedSig],\n );\n\n const lockSig = `${resetKey}|${scrollerWidth}|${colKeys.join(\",\")}`;\n const colWidths = lock && lock.sig === lockSig ? lock.widths : null;\n\n // What the scroll handler and the frame's measure read: this render's model and lock.\n const latest = useRef({ model, colWidths, lockSig, colKeys, lockable, overscan });\n useLayoutEffect(() => {\n latest.current = { model, colWidths, lockSig, colKeys, lockable, overscan };\n });\n\n // Which rows the visible part of the scroller (and of the window, for a table in a page\n // that scrolls) shows, and a new range around them when the rendered one no longer\n // covers them. Read from the client rects, which a scroll leaves laid out.\n const update = useCallback(() => {\n const { model: m, overscan: over } = latest.current;\n const sc = scrollerRef.current;\n const table = tableRef.current;\n if (!m || !sc || !table) return;\n const origin = table.querySelector<HTMLElement>(\"tbody[data-vt-body]\");\n if (!origin) return;\n const sr = sc.getBoundingClientRect();\n const top = Math.max(sr.top, 0);\n const bottom = Math.min(sr.bottom, window.innerHeight || sr.bottom);\n if (!(bottom > top)) return;\n const o = origin.getBoundingClientRect().top;\n const a = Math.min(firstBelow(m, top - o), m.n);\n const b = Math.max(a, Math.min(lastAbove(m, bottom - o), m.n));\n setRange((prev) =>\n prev.start <= a && prev.end >= b && prev.end <= m.n && prev.end - prev.start <= b - a + 4 * over\n ? prev\n : { start: Math.max(0, a - over), end: Math.min(m.n, b + over) },\n );\n }, [scrollerRef, tableRef]);\n\n // After a render that changed what is drawn: measure the rendered rows and bands, and\n // the header cells for the lock. Not after a render that only ticked a box. In the next\n // animation frame rather than in the commit: there the browser lays the table out once\n // for the frame anyway, where a read in the commit forced a layout of its own, and the\n // re-render the heights cause forced another (Chromium, 3000 rows: 35–130 ms of forced\n // layout per scrolled step, against one layout per frame now).\n const measure = useCallback(() => {\n const { model: m, colWidths: locked, lockSig: sig, colKeys: cols, lockable: lockKeys } = latest.current;\n const table = tableRef.current;\n const sc = scrollerRef.current;\n if (!m || !table || !sc) return;\n const trs = table.rows;\n const rects = Array.from(trs, (tr) => tr.getBoundingClientRect());\n const rowSamples: [string | number, number][] = [];\n const detailSamples: [string | number, number][] = [];\n const bandSamples: [0 | 1, number][] = [];\n for (let k = 0; k < trs.length; k++) {\n const own = rects[k];\n const next = rects[k + 1];\n // The distance to the next row's top: exact under collapsed borders.\n const h = next && next.top > own.top ? next.top - own.top : own.height;\n if (!(h > 0)) continue;\n const ds = trs[k].dataset;\n if (ds.rowIndex !== undefined) {\n const key = m.keys[Number(ds.rowIndex)];\n if (key !== undefined) rowSamples.push([key, h]);\n } else if (ds.rowDetail !== undefined) {\n const key = m.keys[Number(ds.rowDetail)];\n if (key !== undefined) detailSamples.push([key, h]);\n } else if (ds.groupRow === \"1\" || ds.groupRow === \"2\") {\n bandSamples.push([ds.groupRow === \"1\" ? 0 : 1, h]);\n }\n }\n if (rowSamples.length + detailSamples.length + bandSamples.length > 0) {\n setMeasured((prev) => {\n let { heights, details, sum, count } = prev;\n let band = prev.band;\n for (const [key, h] of rowSamples) {\n const old = heights.get(key);\n if (old !== undefined && Math.abs(old - h) <= 0.5) continue;\n if (heights === prev.heights) heights = new Map(heights);\n heights.set(key, h);\n sum += h - (old ?? 0);\n if (old === undefined) count++;\n }\n for (const [key, h] of detailSamples) {\n const old = details.get(key);\n if (old !== undefined && Math.abs(old - h) <= 0.5) continue;\n if (details === prev.details) details = new Map(details);\n details.set(key, h);\n }\n for (const [level, h] of bandSamples) {\n if (Math.abs(band[level] - h) <= 0.5) continue;\n band = level === 0 ? [h, band[1]] : [band[0], h];\n }\n return heights === prev.heights && details === prev.details && band === prev.band\n ? prev\n : { heights, details, sum, count, band };\n });\n }\n // The column lock.\n const cells = table.tHead?.rows[0]?.cells;\n if (!cells || cells.length !== cols.length) return;\n const widths: Record<string, number> = {};\n let anyWidth = false;\n for (let c = 0; c < cells.length; c++) {\n if (!lockKeys.has(cols[c])) continue;\n const w = cells[c].getBoundingClientRect().width;\n if (w > 0) {\n widths[cols[c]] = w;\n anyWidth = true;\n }\n }\n if (!anyWidth) return;\n const over = table.getBoundingClientRect().width > sc.clientWidth + 1;\n if (!locked) {\n naturalOverflow.current = over;\n setLock({ sig, widths });\n } else if (over && !naturalOverflow.current) {\n // A grown column pushed the table past a scroller it fit: measure afresh.\n setLock(null);\n } else {\n let grew = false;\n const merged = { ...locked };\n for (const [key, w] of Object.entries(widths)) {\n if (w > (merged[key] ?? 0) + 0.5) {\n merged[key] = w;\n grew = true;\n }\n }\n if (grew) setLock({ sig, widths: merged });\n }\n }, [scrollerRef, tableRef]);\n\n const frame = useRef(0);\n const schedule = useCallback(() => {\n if (frame.current) return;\n const run = () => {\n frame.current = 0;\n measure();\n update();\n };\n frame.current =\n typeof requestAnimationFrame === \"undefined\" ? -(setTimeout(run, 16) as unknown as number) : requestAnimationFrame(run);\n }, [measure, update]);\n useEffect(\n () => () => {\n if (frame.current > 0) cancelAnimationFrame(frame.current);\n else if (frame.current < 0) clearTimeout(-frame.current);\n frame.current = 0;\n },\n [],\n );\n\n useEffect(() => {\n if (!enabled) return;\n const onScroll = () => update();\n window.addEventListener(\"scroll\", onScroll, { capture: true, passive: true });\n window.addEventListener(\"resize\", onScroll, { passive: true });\n const sc = scrollerRef.current;\n let ro: ResizeObserver | undefined;\n if (sc && typeof ResizeObserver !== \"undefined\") {\n ro = new ResizeObserver(() => {\n setScrollerWidth(Math.round(sc.clientWidth));\n update();\n });\n ro.observe(sc);\n }\n return () => {\n window.removeEventListener(\"scroll\", onScroll, { capture: true });\n window.removeEventListener(\"resize\", onScroll);\n ro?.disconnect();\n };\n }, [enabled, update, scrollerRef]);\n\n // The row holding the focus (a row, or a control in it or in its open detail) stays.\n useEffect(() => {\n const table = tableRef.current;\n if (!enabled || !table) return;\n const onIn = (e: FocusEvent) => {\n const tr = (e.target as Element | null)?.closest?.<HTMLElement>(\"tr[data-row-index], tr[data-row-detail]\");\n const index = tr ? Number(tr.dataset.rowIndex ?? tr.dataset.rowDetail) : NaN;\n const key = Number.isNaN(index) ? undefined : latest.current.model?.keys[index];\n setFocusKey(key ?? null);\n setFocusTarget(null);\n };\n const onOut = (e: FocusEvent) => {\n const to = e.relatedTarget as Node | null;\n if (!to || !table.contains(to)) setFocusKey(null);\n };\n table.addEventListener(\"focusin\", onIn);\n table.addEventListener(\"focusout\", onOut);\n return () => {\n table.removeEventListener(\"focusin\", onIn);\n table.removeEventListener(\"focusout\", onOut);\n };\n }, [enabled, tableRef]);\n\n const dataSig = n > 0 && model ? `${n}:${String(model.keys[0])}:${String(model.keys[n - 1])}` : \"0\";\n const renderSig = `${start}:${end}:${dataSig}:${expandedSig}:${pinnedSig}:${lockSig}:${colWidths ? 1 : 0}`;\n const lastRender = useRef(\"\");\n useLayoutEffect(() => {\n if (!enabled || lastRender.current === renderSig) return;\n lastRender.current = renderSig;\n schedule();\n });\n\n // A new layout (heights measured, rows added): the range may no longer cover the view.\n const total = model?.total ?? 0;\n useLayoutEffect(() => {\n if (enabled) schedule();\n }, [enabled, schedule, total, n]);\n\n // The keyboard's target: rendered (pinned), then focused — its focus scrolls it into\n // view, and the scroll renders the rows around it.\n useLayoutEffect(() => {\n if (focusTarget === null) return;\n // Released by the focus it receives (the `focusin` above), which pins it as the\n // focused row from then on.\n tableRef.current?.querySelector<HTMLElement>(`tr[data-row-index=\"${focusTarget}\"]`)?.focus();\n }, [focusTarget, bodies, tableRef]);\n\n const focusRow = useCallback(\n (i: number) => {\n const el = tableRef.current?.querySelector<HTMLElement>(`tr[data-row-index=\"${i}\"]`);\n if (el) el.focus();\n else setFocusTarget(i);\n },\n [tableRef],\n );\n\n if (!enabled || !model) return null;\n return {\n bodies,\n rowCount: model.rowCount,\n ariaRow: (i) => model.ariaRows[i],\n ariaBand: (g, level) => model.ariaBands[g * 2 + level - 1],\n colWidths,\n focusRow,\n };\n}\n\n/** The roving rows' Arrow/Home/End target over ALL the rows, rendered or not. */\nexport function rowNavTarget(from: number, key: string, n: number): number | null {\n if (n === 0) return null;\n if (key === \"ArrowDown\") return Math.min(n - 1, from + 1);\n if (key === \"ArrowUp\") return Math.max(0, from - 1);\n if (key === \"Home\") return 0;\n if (key === \"End\") return n - 1;\n return null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ReactNode, TdHTMLAttributes, ThHTMLAttributes } from "react";
|
|
2
2
|
import { type DataTableGroupBy, type DataTableLoadMore } from "./data-table-groups.js";
|
|
3
3
|
export type { DataTableGroupBy, DataTableLoadMore } from "./data-table-groups.js";
|
|
4
|
+
import { type DataTableVirtualize } from "./data-table-virtual.js";
|
|
5
|
+
export type { DataTableVirtualize } from "./data-table-virtual.js";
|
|
4
6
|
import type { ColumnFilter, FilterValue } from "./data-table-filters.js";
|
|
5
7
|
import type { SortCycle, SortDir, SortState } from "./data-table-sort.js";
|
|
6
8
|
import type { SwipeAction } from "./swipeable-row.js";
|
|
@@ -19,6 +21,36 @@ export interface DataTableColumn<T> {
|
|
|
19
21
|
headClassName?: string;
|
|
20
22
|
mobilePrimary?: boolean;
|
|
21
23
|
mobileHidden?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* This column on the phone's default card (0.49 KIT-7; ignored with `mobileCard`):
|
|
26
|
+
* `"primary"` — the card's title, as `mobilePrimary`; `"secondary"` — one of its
|
|
27
|
+
* fields; `"hidden"` — not on the card, as `mobileHidden`. The card shows at most
|
|
28
|
+
* three fields: the columns marked `"secondary"` when any
|
|
29
|
+
* is, else the first three visible columns after the title. A field whose value is
|
|
30
|
+
* empty — the cell returns `null`, `undefined`, `""` or the formatters' empty "—" —
|
|
31
|
+
* is left out of that card. The columns the card does not show go into the opened
|
|
32
|
+
* row with `mobileDetailsInRow`. A `noRowLink` column (the cell's own buttons or link)
|
|
33
|
+
* counts as a field: past the third it leaves the card with its action, and a
|
|
34
|
+
* development build says so once per table and column key. Give a column of row
|
|
35
|
+
* actions `role: "actions"` instead: it is then no field, and the card draws it after
|
|
36
|
+
* them.
|
|
37
|
+
*/
|
|
38
|
+
mobile?: "primary" | "secondary" | "hidden";
|
|
39
|
+
/**
|
|
40
|
+
* What the column is (0.49 KIT-7), for the phone's default card; the desktop table is
|
|
41
|
+
* unchanged.
|
|
42
|
+
*
|
|
43
|
+
* - `"status"`: its value sits as a chip beside the title instead of as a label/value
|
|
44
|
+
* line, and takes none of the card's three fields. A cell that returns text is drawn
|
|
45
|
+
* in a neutral `Chip`; one that returns an element (a `Chip` with its own tone, a
|
|
46
|
+
* `StatusDot`) is drawn as it is.
|
|
47
|
+
* - `"actions"`: the row's buttons (`rowActionsColumn` sets it). Never the card's title
|
|
48
|
+
* and never one of its three fields: the card draws it after them, at its end,
|
|
49
|
+
* whether or not other columns are marked `mobile: "secondary"`; only `mobileHidden`
|
|
50
|
+
* / `mobile: "hidden"` take it off. Its cell keeps its own clicks, as `noRowLink`:
|
|
51
|
+
* no row link wraps it, and a card that draws it is not a link.
|
|
52
|
+
*/
|
|
53
|
+
role?: "status" | "actions";
|
|
22
54
|
/**
|
|
23
55
|
* Set on a column whose cell renders its own `<a>` (or anything else that must
|
|
24
56
|
* keep its own click): the row anchor of `rowHref` then skips it and lands on
|
|
@@ -230,7 +262,10 @@ export interface DataTableProps<T> {
|
|
|
230
262
|
* When true, mirror filter/sort/page state into URL search params so views are
|
|
231
263
|
* shareable and bookmarkable. URL params used: `f.<column>`, `sort`, `p`, `ps`.
|
|
232
264
|
* URL state takes precedence over localStorage on initial load. Requires the
|
|
233
|
-
* consuming app to render inside a react-router Router.
|
|
265
|
+
* consuming app to render inside a react-router Router (0.49: only with `urlSync` — a
|
|
266
|
+
* table without it needs none). With `urlSync` and no Router, a development build
|
|
267
|
+
* throws "DataTable urlSync requires a Router"; a production build keeps the view in
|
|
268
|
+
* local state instead.
|
|
234
269
|
*
|
|
235
270
|
* `{ prefix }` namespaces them, for two URL-synced tables on one page:
|
|
236
271
|
* `urlSync={{ prefix: "inv." }}` uses `inv.f.<column>`, `inv.sort`, `inv.p`, `inv.ps`.
|
|
@@ -557,6 +592,43 @@ export interface DataTableProps<T> {
|
|
|
557
592
|
* {@link DataTableLoadMore}.
|
|
558
593
|
*/
|
|
559
594
|
loadMore?: DataTableLoadMore;
|
|
595
|
+
/**
|
|
596
|
+
* 0.48.2 (keksdose dev #632, Marcel: "The table is extremely slow. Is it virtualised…?"):
|
|
597
|
+
* render only the desktop rows near the visible part of the scroller, plus `overscan`
|
|
598
|
+
* rows each side ({@link DataTableVirtualize}), with spacer rows standing in for the
|
|
599
|
+
* rest. For long lists — keksdose's register under `loadMore` holds 1000+ rows. Opt-in;
|
|
600
|
+
* without it every row renders, as before.
|
|
601
|
+
*
|
|
602
|
+
* - **Scroller:** the bounded body (`fillHeight` or `maxBodyHeight`), or the page when the
|
|
603
|
+
* body is unbounded (`maxBodyHeight="none"`): the window is what of the table both the
|
|
604
|
+
* scroller and the browser window show.
|
|
605
|
+
* - **Kept rendered:** the header, the `leadingRow`, the group bands (sticky and stacked
|
|
606
|
+
* as before; a period's band while any of its rows is in view), every OPEN row (so an
|
|
607
|
+
* inline editor in `expandedRow` keeps its state), the roving tab stop and a row
|
|
608
|
+
* holding the focus. The `loadMore` footer follows the last spacer and loads once.
|
|
609
|
+
* - **Heights:** each rendered row is measured and remembered by its key; a row not yet
|
|
610
|
+
* seen counts as the measured average (`estimateRowHeight` before any). The scroll
|
|
611
|
+
* height settles as the rows are seen; the browser's scroll anchoring holds the rows in
|
|
612
|
+
* view while a spacer above is corrected (Safari has none: a jump of the difference
|
|
613
|
+
* is possible there on the first pass).
|
|
614
|
+
* - **Columns:** the header widths are measured once and locked in a `<colgroup>`, so the
|
|
615
|
+
* columns do not move as rows come and go; a wider cell scrolling in widens its column
|
|
616
|
+
* (once). Re-measured when the rows, the columns, a width or the scroller's width
|
|
617
|
+
* change. A `grow` column and a resized one are not locked.
|
|
618
|
+
* - **Keyboard and screen reader:** Arrow/Home/End move over every row — the target is
|
|
619
|
+
* rendered, then focused (End reaches the last row); Shift+click ranges and select-all
|
|
620
|
+
* work on the data, not the DOM. The table has `aria-rowcount`, every rendered row its
|
|
621
|
+
* `aria-rowindex` (bands, details and the totals row counted); spacers are
|
|
622
|
+
* `aria-hidden`.
|
|
623
|
+
* - **Trade-offs:** the browser's find-in-page sees only the rendered rows, and so does
|
|
624
|
+
* print; an `id` from `rowAttributes` (an anchor, an `aria-controls` target, a
|
|
625
|
+
* `scrollIntoView` on a fresh row) exists only while its row is rendered. Memoise
|
|
626
|
+
* `columns` (and `mobileCard`): the rows bail out of a render only then, and a scroll
|
|
627
|
+
* renders the rows that come in, not the whole window.
|
|
628
|
+
* - **Phone:** desktop only. The card list renders every row it holds (`loadMore`,
|
|
629
|
+
* `paginated={false}`) or reveals them in chunks as it is scrolled (client paging).
|
|
630
|
+
*/
|
|
631
|
+
virtualize?: boolean | DataTableVirtualize;
|
|
560
632
|
/**
|
|
561
633
|
* Row height. `"compact"` is lenkbank's in-card tables: five `text-xs` tables with
|
|
562
634
|
* `px-2 py-1` cells sitting inside cards, which at the default padding came out at
|
|
@@ -786,4 +858,4 @@ export interface DataTableSortLabels {
|
|
|
786
858
|
* (DataTableLabels extends DataTableSortLabels; one source for the English). */
|
|
787
859
|
export declare const DEFAULT_DATA_TABLE_SORT_LABELS: DataTableSortLabels;
|
|
788
860
|
import { type TableUrlSync } from "./use-table-state.js";
|
|
789
|
-
export declare function DataTable<T>({ rows, columns: columnsProp, rowKey, defaultPageSize, onRowClick, rowHref, expandedRow, isExpanded, rowClassName, rowAttributes, paginated, empty, storageKey, urlSync, fillHeight, maxBodyHeight, serverPagination, serverRows: serverRowsProp, filters: filtersProp, onFiltersChange, sorts: sortsProp, onSortsChange, pageSize: pageSizeProp, onPageSizeChange, selection, labels: labelsProp, locale: localeProp, storageKeyPrefix: storageKeyPrefixProp, mobileExpandAsDialog, mobileDetailsInRow, rowName, mobileDialogBackCloses, mobileGroupBy, mobileGroupLabel, mobileCard, mobileSort, mobileSwipeActions, desktopSwipeActions, leadingRow, leadingRowSticky, groupBy, loadMore, density, sortCycle, chrome, columnSettings: columnSettingsProp, resizable: resizableProp, multiSort: multiSortProp, frame, edgeFade, className, rowActions, rowActionsHeader, toolbar, footerLabel, footer: footerProp, }: DataTableProps<T>): import("react").JSX.Element;
|
|
861
|
+
export declare function DataTable<T>({ rows, columns: columnsProp, rowKey, defaultPageSize, onRowClick, rowHref, expandedRow, isExpanded, rowClassName, rowAttributes, paginated, empty, storageKey, urlSync, fillHeight, maxBodyHeight, serverPagination, serverRows: serverRowsProp, filters: filtersProp, onFiltersChange, sorts: sortsProp, onSortsChange, pageSize: pageSizeProp, onPageSizeChange, selection, labels: labelsProp, locale: localeProp, storageKeyPrefix: storageKeyPrefixProp, mobileExpandAsDialog, mobileDetailsInRow, rowName, mobileDialogBackCloses, mobileGroupBy, mobileGroupLabel, mobileCard, mobileSort, mobileSwipeActions, desktopSwipeActions, leadingRow, leadingRowSticky, groupBy, loadMore, virtualize, density, sortCycle, chrome, columnSettings: columnSettingsProp, resizable: resizableProp, multiSort: multiSortProp, frame, edgeFade, className, rowActions, rowActionsHeader, toolbar, footerLabel, footer: footerProp, }: DataTableProps<T>): import("react").JSX.Element;
|