@bmsuisse/datagrid 0.39.0 → 0.41.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/dist/index.d.ts +33 -2
- package/dist/index.js +275 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3267,7 +3267,7 @@ function GridInlineError({
|
|
|
3267
3267
|
}
|
|
3268
3268
|
|
|
3269
3269
|
// src/grid/DataGrid.tsx
|
|
3270
|
-
import { Fragment as Fragment3, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef13, useState as useState16 } from "react";
|
|
3270
|
+
import { Fragment as Fragment3, useEffect as useEffect12, useId as useId4, useMemo as useMemo9, useRef as useRef13, useState as useState16 } from "react";
|
|
3271
3271
|
|
|
3272
3272
|
// src/cell-editing/renderAlwaysEditCell.tsx
|
|
3273
3273
|
import {
|
|
@@ -3689,6 +3689,8 @@ function DataGrid({
|
|
|
3689
3689
|
onGridStateChange,
|
|
3690
3690
|
selectedIds: controlledSelectedIds,
|
|
3691
3691
|
onSelectedIdsChange,
|
|
3692
|
+
selectionMode = "multiple",
|
|
3693
|
+
maxHeight,
|
|
3692
3694
|
testId,
|
|
3693
3695
|
loading: loadingProp = false,
|
|
3694
3696
|
error,
|
|
@@ -3715,11 +3717,18 @@ function DataGrid({
|
|
|
3715
3717
|
onGridStateChange
|
|
3716
3718
|
);
|
|
3717
3719
|
const [internalSelectedIds, setInternalSelectedIds] = useState16(/* @__PURE__ */ new Set());
|
|
3718
|
-
const
|
|
3720
|
+
const rawSelectedIds = controlledSelectedIds ?? internalSelectedIds;
|
|
3721
|
+
const selectedIds = useMemo9(
|
|
3722
|
+
() => selectionMode === "single" && rawSelectedIds.size > 1 ? new Set([...rawSelectedIds].slice(0, 1)) : rawSelectedIds,
|
|
3723
|
+
[selectionMode, rawSelectedIds]
|
|
3724
|
+
);
|
|
3719
3725
|
function updateSelectedIds(next) {
|
|
3720
3726
|
setInternalSelectedIds(next);
|
|
3721
3727
|
onSelectedIdsChange?.(next);
|
|
3722
3728
|
}
|
|
3729
|
+
useEffect12(() => {
|
|
3730
|
+
if (selectedIds !== rawSelectedIds) updateSelectedIds(selectedIds);
|
|
3731
|
+
}, [selectedIds, rawSelectedIds]);
|
|
3723
3732
|
const [internalColumnSizing, setInternalColumnSizing] = useState16({});
|
|
3724
3733
|
const columnSizing = controlledColumnSizing ?? internalColumnSizing;
|
|
3725
3734
|
function updateColumnSizing(next) {
|
|
@@ -3760,7 +3769,13 @@ function DataGrid({
|
|
|
3760
3769
|
[rows, selectedIds, getRowId]
|
|
3761
3770
|
);
|
|
3762
3771
|
const allOnPageSelected = rows.length > 0 && rows.every((row) => selectedIds.has(getRowId(row)));
|
|
3772
|
+
const singleSelect = selectionMode === "single";
|
|
3773
|
+
const selectionGroupName = useId4();
|
|
3763
3774
|
function toggleRowSelected(id) {
|
|
3775
|
+
if (singleSelect) {
|
|
3776
|
+
updateSelectedIds(/* @__PURE__ */ new Set([id]));
|
|
3777
|
+
return;
|
|
3778
|
+
}
|
|
3764
3779
|
const next = new Set(selectedIds);
|
|
3765
3780
|
if (next.has(id)) next.delete(id);
|
|
3766
3781
|
else next.add(id);
|
|
@@ -3803,7 +3818,7 @@ function DataGrid({
|
|
|
3803
3818
|
const labels = resolveStatusLabels(statusLabels);
|
|
3804
3819
|
const hasError = toErrorInfo(error) !== void 0;
|
|
3805
3820
|
const loading = loadingProp || (dataSource.mode === "server" ? Boolean(dataSource.loading) : false);
|
|
3806
|
-
const showSelectionColumn = Boolean(headerActions?.length) || controlledSelectedIds !== void 0;
|
|
3821
|
+
const showSelectionColumn = Boolean(headerActions?.length) || controlledSelectedIds !== void 0 || selectionMode === "single";
|
|
3807
3822
|
const showRowActionsColumn = Boolean(rowActions?.length);
|
|
3808
3823
|
const showDetailColumn = Boolean(renderDetail);
|
|
3809
3824
|
const totalColumnCount = visibleColumns.length + (showDetailColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0) + (showRowActionsColumn ? 1 : 0);
|
|
@@ -4124,6 +4139,8 @@ function DataGrid({
|
|
|
4124
4139
|
}
|
|
4125
4140
|
function handleCellKeyDown(event) {
|
|
4126
4141
|
if (!hasCellEditing || !cellEditingCtx) return;
|
|
4142
|
+
if (event.target instanceof HTMLInputElement && (event.target.type === "radio" || event.target.type === "checkbox") && !event.target.closest("[data-cell-row]"))
|
|
4143
|
+
return;
|
|
4127
4144
|
if (cellEditingCtx.alwaysEdit) return;
|
|
4128
4145
|
if (cellEditingCtx.editingCell && !cellEditingCtx.consumeJustCommitted()) return;
|
|
4129
4146
|
const direction = CELL_NAV_KEYS[event.key];
|
|
@@ -4253,7 +4270,8 @@ function DataGrid({
|
|
|
4253
4270
|
children: /* @__PURE__ */ jsx35(
|
|
4254
4271
|
"input",
|
|
4255
4272
|
{
|
|
4256
|
-
type: "checkbox",
|
|
4273
|
+
type: singleSelect ? "radio" : "checkbox",
|
|
4274
|
+
name: singleSelect ? selectionGroupName : void 0,
|
|
4257
4275
|
"aria-label": `Select row ${row.id}`,
|
|
4258
4276
|
checked: selectedIds.has(row.id),
|
|
4259
4277
|
onClick: stopRowClick,
|
|
@@ -4432,7 +4450,7 @@ function DataGrid({
|
|
|
4432
4450
|
"h-full overflow-auto rounded-md border",
|
|
4433
4451
|
hasCellEditing && "relative"
|
|
4434
4452
|
),
|
|
4435
|
-
style: shouldVirtualize ? { maxHeight: virtualize?.maxBodyHeight ?? 480 } : void 0,
|
|
4453
|
+
style: shouldVirtualize ? { maxHeight: virtualize?.maxBodyHeight ?? 480 } : maxHeight !== void 0 ? { maxHeight } : void 0,
|
|
4436
4454
|
tabIndex: hasCellEditing ? 0 : void 0,
|
|
4437
4455
|
onMouseDown: hasCellEditing ? handleCellMouseDown : void 0,
|
|
4438
4456
|
onDoubleClick: hasCellEditing ? handleCellDoubleClick : void 0,
|
|
@@ -4550,7 +4568,7 @@ function DataGrid({
|
|
|
4550
4568
|
rowSpan: 2,
|
|
4551
4569
|
className: selectionHeaderCellProps.className,
|
|
4552
4570
|
style: selectionHeaderCellProps.style,
|
|
4553
|
-
children: /* @__PURE__ */ jsx35(
|
|
4571
|
+
children: !singleSelect && /* @__PURE__ */ jsx35(
|
|
4554
4572
|
"input",
|
|
4555
4573
|
{
|
|
4556
4574
|
type: "checkbox",
|
|
@@ -4596,7 +4614,7 @@ function DataGrid({
|
|
|
4596
4614
|
{
|
|
4597
4615
|
className: selectionHeaderCellProps.className,
|
|
4598
4616
|
style: selectionHeaderCellProps.style,
|
|
4599
|
-
children: /* @__PURE__ */ jsx35(
|
|
4617
|
+
children: !singleSelect && /* @__PURE__ */ jsx35(
|
|
4600
4618
|
"input",
|
|
4601
4619
|
{
|
|
4602
4620
|
type: "checkbox",
|
|
@@ -4718,7 +4736,73 @@ import {
|
|
|
4718
4736
|
ChevronDownIcon as ChevronDownIcon3,
|
|
4719
4737
|
ChevronRightIcon as ChevronRightIcon3
|
|
4720
4738
|
} from "@heroicons/react/24/outline";
|
|
4721
|
-
import { Fragment as Fragment5, useEffect as useEffect13, useMemo as useMemo11, useRef as
|
|
4739
|
+
import { Fragment as Fragment5, useEffect as useEffect13, useMemo as useMemo11, useRef as useRef15 } from "react";
|
|
4740
|
+
|
|
4741
|
+
// src/hooks/useColumnSizing.ts
|
|
4742
|
+
import { useCallback as useCallback5, useState as useState17 } from "react";
|
|
4743
|
+
var MIN_COLUMN_SIZE2 = 40;
|
|
4744
|
+
var KEYBOARD_RESIZE_STEP = 10;
|
|
4745
|
+
function useColumnSizing(controlled, onChange) {
|
|
4746
|
+
const [internal, setInternal] = useState17({});
|
|
4747
|
+
const columnSizing = controlled ?? internal;
|
|
4748
|
+
const setColumnSize = useCallback5(
|
|
4749
|
+
(columnId, width) => {
|
|
4750
|
+
const next = { ...columnSizing, [columnId]: Math.max(MIN_COLUMN_SIZE2, Math.round(width)) };
|
|
4751
|
+
setInternal(next);
|
|
4752
|
+
onChange?.(next);
|
|
4753
|
+
},
|
|
4754
|
+
[columnSizing, onChange]
|
|
4755
|
+
);
|
|
4756
|
+
return { columnSizing, setColumnSize };
|
|
4757
|
+
}
|
|
4758
|
+
|
|
4759
|
+
// src/tree/ColumnResizeHandle.tsx
|
|
4760
|
+
import { useRef as useRef14 } from "react";
|
|
4761
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
4762
|
+
function ColumnResizeHandle({ columnId, label, width, onResize }) {
|
|
4763
|
+
const drag = useRef14(null);
|
|
4764
|
+
const cellWidth = (handle) => handle.parentElement?.getBoundingClientRect().width ?? 0;
|
|
4765
|
+
const onPointerDown = (event) => {
|
|
4766
|
+
event.preventDefault();
|
|
4767
|
+
event.stopPropagation();
|
|
4768
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
4769
|
+
drag.current = { startX: event.clientX, startWidth: cellWidth(event.currentTarget) };
|
|
4770
|
+
};
|
|
4771
|
+
const onPointerMove = (event) => {
|
|
4772
|
+
if (!drag.current) return;
|
|
4773
|
+
onResize(columnId, drag.current.startWidth + event.clientX - drag.current.startX);
|
|
4774
|
+
};
|
|
4775
|
+
const endDrag = (event) => {
|
|
4776
|
+
if (!drag.current) return;
|
|
4777
|
+
drag.current = null;
|
|
4778
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
4779
|
+
};
|
|
4780
|
+
const onKeyDown = (event) => {
|
|
4781
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
4782
|
+
event.preventDefault();
|
|
4783
|
+
const delta = event.key === "ArrowRight" ? KEYBOARD_RESIZE_STEP : -KEYBOARD_RESIZE_STEP;
|
|
4784
|
+
onResize(columnId, cellWidth(event.currentTarget) + delta);
|
|
4785
|
+
};
|
|
4786
|
+
return /* @__PURE__ */ jsx36(
|
|
4787
|
+
"div",
|
|
4788
|
+
{
|
|
4789
|
+
"data-testid": `resize-handle-${columnId}`,
|
|
4790
|
+
role: "separator",
|
|
4791
|
+
"aria-orientation": "vertical",
|
|
4792
|
+
"aria-label": `Resize ${label} column`,
|
|
4793
|
+
"aria-valuenow": width,
|
|
4794
|
+
"aria-valuemin": MIN_COLUMN_SIZE2,
|
|
4795
|
+
"aria-valuetext": width === void 0 ? void 0 : `${width} pixels`,
|
|
4796
|
+
tabIndex: 0,
|
|
4797
|
+
onPointerDown,
|
|
4798
|
+
onPointerMove,
|
|
4799
|
+
onPointerUp: endDrag,
|
|
4800
|
+
onPointerCancel: endDrag,
|
|
4801
|
+
onKeyDown,
|
|
4802
|
+
className: "absolute right-0 top-0 h-full w-1 cursor-col-resize touch-none select-none hover:bg-accent focus-visible:bg-accent focus-visible:outline-none"
|
|
4803
|
+
}
|
|
4804
|
+
);
|
|
4805
|
+
}
|
|
4722
4806
|
|
|
4723
4807
|
// src/tree/flattenTree.ts
|
|
4724
4808
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -4763,7 +4847,7 @@ function computeSelectionStates(roots, accessors, childrenOverride, selectedIds)
|
|
|
4763
4847
|
}
|
|
4764
4848
|
|
|
4765
4849
|
// src/tree/useTreeState.ts
|
|
4766
|
-
import { useCallback as
|
|
4850
|
+
import { useCallback as useCallback6, useMemo as useMemo10, useState as useState18 } from "react";
|
|
4767
4851
|
function useTreeState({
|
|
4768
4852
|
data,
|
|
4769
4853
|
getRowId,
|
|
@@ -4775,9 +4859,9 @@ function useTreeState({
|
|
|
4775
4859
|
childrenMap: controlledChildrenMap,
|
|
4776
4860
|
onChildrenMapChange
|
|
4777
4861
|
}) {
|
|
4778
|
-
const [internalExpanded, setInternalExpanded] =
|
|
4862
|
+
const [internalExpanded, setInternalExpanded] = useState18({});
|
|
4779
4863
|
const expanded = controlledExpanded ?? internalExpanded;
|
|
4780
|
-
const setExpanded =
|
|
4864
|
+
const setExpanded = useCallback6(
|
|
4781
4865
|
(updater) => {
|
|
4782
4866
|
if (controlledExpanded) {
|
|
4783
4867
|
onExpandedChange?.(updater(controlledExpanded));
|
|
@@ -4787,9 +4871,9 @@ function useTreeState({
|
|
|
4787
4871
|
},
|
|
4788
4872
|
[controlledExpanded, onExpandedChange]
|
|
4789
4873
|
);
|
|
4790
|
-
const [internalChildrenMap, setInternalChildrenMap] =
|
|
4874
|
+
const [internalChildrenMap, setInternalChildrenMap] = useState18(/* @__PURE__ */ new Map());
|
|
4791
4875
|
const childrenMap = controlledChildrenMap ?? internalChildrenMap;
|
|
4792
|
-
const setChildrenMap =
|
|
4876
|
+
const setChildrenMap = useCallback6(
|
|
4793
4877
|
(updater) => {
|
|
4794
4878
|
if (controlledChildrenMap) {
|
|
4795
4879
|
onChildrenMapChange?.(updater(controlledChildrenMap));
|
|
@@ -4799,13 +4883,13 @@ function useTreeState({
|
|
|
4799
4883
|
},
|
|
4800
4884
|
[controlledChildrenMap, onChildrenMapChange]
|
|
4801
4885
|
);
|
|
4802
|
-
const [loadingIds, setLoadingIds] =
|
|
4803
|
-
const [errorIds, setErrorIds] =
|
|
4886
|
+
const [loadingIds, setLoadingIds] = useState18(/* @__PURE__ */ new Set());
|
|
4887
|
+
const [errorIds, setErrorIds] = useState18(/* @__PURE__ */ new Map());
|
|
4804
4888
|
const resolveHasChildren = useMemo10(
|
|
4805
4889
|
() => hasChildren ?? ((row) => (getChildren(row)?.length ?? 0) > 0),
|
|
4806
4890
|
[hasChildren, getChildren]
|
|
4807
4891
|
);
|
|
4808
|
-
const loadChildrenFor =
|
|
4892
|
+
const loadChildrenFor = useCallback6(
|
|
4809
4893
|
async (row) => {
|
|
4810
4894
|
const id = getRowId(row);
|
|
4811
4895
|
const cached = childrenMap.get(id);
|
|
@@ -4838,7 +4922,7 @@ function useTreeState({
|
|
|
4838
4922
|
},
|
|
4839
4923
|
[childrenMap, getChildren, getRowId, onLoadChildren, setChildrenMap]
|
|
4840
4924
|
);
|
|
4841
|
-
const toggleExpand =
|
|
4925
|
+
const toggleExpand = useCallback6(
|
|
4842
4926
|
(row) => {
|
|
4843
4927
|
const id = getRowId(row);
|
|
4844
4928
|
const willExpand = !expanded[id];
|
|
@@ -4850,14 +4934,14 @@ function useTreeState({
|
|
|
4850
4934
|
},
|
|
4851
4935
|
[expanded, getRowId, loadChildrenFor, resolveHasChildren, setExpanded]
|
|
4852
4936
|
);
|
|
4853
|
-
const retry =
|
|
4937
|
+
const retry = useCallback6(
|
|
4854
4938
|
(row) => {
|
|
4855
4939
|
loadChildrenFor(row).catch(() => {
|
|
4856
4940
|
});
|
|
4857
4941
|
},
|
|
4858
4942
|
[loadChildrenFor]
|
|
4859
4943
|
);
|
|
4860
|
-
const expandToLevel =
|
|
4944
|
+
const expandToLevel = useCallback6(
|
|
4861
4945
|
async (level) => {
|
|
4862
4946
|
const nextExpanded = { ...expanded };
|
|
4863
4947
|
async function visit(row, depth) {
|
|
@@ -4880,7 +4964,7 @@ function useTreeState({
|
|
|
4880
4964
|
}
|
|
4881
4965
|
|
|
4882
4966
|
// src/tree/TreeDataGrid.tsx
|
|
4883
|
-
import { Fragment as Fragment6, jsx as
|
|
4967
|
+
import { Fragment as Fragment6, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4884
4968
|
var EMPTY_SELECTED_IDS = /* @__PURE__ */ new Set();
|
|
4885
4969
|
var UNCHECKED_STATE = { checked: false, indeterminate: false };
|
|
4886
4970
|
function renderCell(column, row, editingCtx) {
|
|
@@ -4898,7 +4982,7 @@ function TreeCell({
|
|
|
4898
4982
|
editingCtx
|
|
4899
4983
|
}) {
|
|
4900
4984
|
return /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1", style: { paddingLeft: flatRow.depth * indentSize }, children: [
|
|
4901
|
-
flatRow.hasChildren ? /* @__PURE__ */
|
|
4985
|
+
flatRow.hasChildren ? /* @__PURE__ */ jsx37(
|
|
4902
4986
|
"button",
|
|
4903
4987
|
{
|
|
4904
4988
|
type: "button",
|
|
@@ -4910,11 +4994,11 @@ function TreeCell({
|
|
|
4910
4994
|
"aria-label": flatRow.isExpanded ? "Collapse" : "Expand",
|
|
4911
4995
|
"aria-expanded": flatRow.isExpanded,
|
|
4912
4996
|
className: "flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-50",
|
|
4913
|
-
children: isLoading ? /* @__PURE__ */
|
|
4997
|
+
children: isLoading ? /* @__PURE__ */ jsx37(ArrowPathIcon2, { className: "h-3.5 w-3.5 animate-spin", "aria-hidden": "true" }) : flatRow.isExpanded ? /* @__PURE__ */ jsx37(ChevronDownIcon3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx37(ChevronRightIcon3, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
4914
4998
|
}
|
|
4915
|
-
) : /* @__PURE__ */
|
|
4916
|
-
/* @__PURE__ */
|
|
4917
|
-
flatRow.isExpanded && error ? /* @__PURE__ */
|
|
4999
|
+
) : /* @__PURE__ */ jsx37("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
5000
|
+
/* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 truncate", children: renderCell(column, flatRow.row, editingCtx) }),
|
|
5001
|
+
flatRow.isExpanded && error ? /* @__PURE__ */ jsx37(
|
|
4918
5002
|
GridInlineError,
|
|
4919
5003
|
{
|
|
4920
5004
|
error: { message: labels.nodeLoadFailed, details: error },
|
|
@@ -4962,7 +5046,10 @@ function TreeDataGrid({
|
|
|
4962
5046
|
onExpandedGroupsChange,
|
|
4963
5047
|
zebra = true,
|
|
4964
5048
|
showTotals = false,
|
|
4965
|
-
editing
|
|
5049
|
+
editing,
|
|
5050
|
+
enableColumnResizing = false,
|
|
5051
|
+
columnSizing: controlledColumnSizing,
|
|
5052
|
+
onColumnSizingChange
|
|
4966
5053
|
}) {
|
|
4967
5054
|
const labels = resolveStatusLabels(statusLabels);
|
|
4968
5055
|
const hasError = toErrorInfo(error) !== void 0;
|
|
@@ -4982,7 +5069,7 @@ function TreeDataGrid({
|
|
|
4982
5069
|
childrenMap: controlledChildrenMap,
|
|
4983
5070
|
onChildrenMapChange
|
|
4984
5071
|
});
|
|
4985
|
-
const didAutoExpand =
|
|
5072
|
+
const didAutoExpand = useRef15(false);
|
|
4986
5073
|
useEffect13(() => {
|
|
4987
5074
|
if (didAutoExpand.current) return;
|
|
4988
5075
|
didAutoExpand.current = true;
|
|
@@ -5022,6 +5109,12 @@ function TreeDataGrid({
|
|
|
5022
5109
|
const showRowActionsColumn = Boolean(rowActions?.length);
|
|
5023
5110
|
const showSelectionColumn = controlledSelectedIds !== void 0;
|
|
5024
5111
|
const totalColumnCount = visibleColumns.length + (showRowActionsColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0);
|
|
5112
|
+
const { columnSizing, setColumnSize } = useColumnSizing(controlledColumnSizing, onColumnSizingChange);
|
|
5113
|
+
const columnWidthStyle = (column) => {
|
|
5114
|
+
const width = enableColumnResizing ? columnSizing[column.id] ?? column.width : column.width;
|
|
5115
|
+
return width ? { width } : void 0;
|
|
5116
|
+
};
|
|
5117
|
+
const fixedTableWidth = enableColumnResizing && !showRowActionsColumn && visibleColumns.every((c) => columnWidthStyle(c)) ? visibleColumns.reduce((sum, c) => sum + Number(columnWidthStyle(c)?.width), showSelectionColumn ? SELECTION_COLUMN_WIDTH : 0) : void 0;
|
|
5025
5118
|
const { theadRef, groupHeaderTop } = useStickyGroupHeaderTop(Boolean(groupBy));
|
|
5026
5119
|
const selectionStates = useMemo11(
|
|
5027
5120
|
() => showSelectionColumn ? computeSelectionStates(data, accessors, childrenMap, controlledSelectedIds ?? EMPTY_SELECTED_IDS) : void 0,
|
|
@@ -5055,14 +5148,15 @@ function TreeDataGrid({
|
|
|
5055
5148
|
}
|
|
5056
5149
|
const bodyTdClassByColumn = useMemo11(() => {
|
|
5057
5150
|
const map = /* @__PURE__ */ new Map();
|
|
5058
|
-
|
|
5151
|
+
const clip = enableColumnResizing ? "overflow-hidden " : "";
|
|
5152
|
+
for (const column of visibleColumns) map.set(column.id, `${clip}p-2 ${alignClassName(column)}`);
|
|
5059
5153
|
return map;
|
|
5060
|
-
}, [visibleColumns]);
|
|
5154
|
+
}, [visibleColumns, enableColumnResizing]);
|
|
5061
5155
|
const hasColumnSummary = visibleColumns.some((column) => column.summary);
|
|
5062
5156
|
function renderGroupSummaryCells(rows) {
|
|
5063
|
-
return visibleColumns.map((column) => /* @__PURE__ */
|
|
5157
|
+
return visibleColumns.map((column) => /* @__PURE__ */ jsx37("td", { className: cn(bodyTdClassByColumn.get(column.id), "font-medium"), children: column.summary?.(rows) }, column.id));
|
|
5064
5158
|
}
|
|
5065
|
-
const scrollRef =
|
|
5159
|
+
const scrollRef = useRef15(null);
|
|
5066
5160
|
const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
|
|
5067
5161
|
const virtualizer = useVirtualizer2({
|
|
5068
5162
|
count: flatRows.length,
|
|
@@ -5088,9 +5182,9 @@ function TreeDataGrid({
|
|
|
5088
5182
|
isOddRow && "bg-foreground/5"
|
|
5089
5183
|
) : `border-b border-border divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
|
|
5090
5184
|
children: [
|
|
5091
|
-
showSelectionColumn && /* @__PURE__ */
|
|
5185
|
+
showSelectionColumn && /* @__PURE__ */ jsx37("td", { className: "p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: (() => {
|
|
5092
5186
|
const state = resolveSelectionState(flatRow.row, flatRow.id);
|
|
5093
|
-
return /* @__PURE__ */
|
|
5187
|
+
return /* @__PURE__ */ jsx37(
|
|
5094
5188
|
Checkbox,
|
|
5095
5189
|
{
|
|
5096
5190
|
"aria-label": `Select row ${flatRow.id}`,
|
|
@@ -5101,7 +5195,7 @@ function TreeDataGrid({
|
|
|
5101
5195
|
}
|
|
5102
5196
|
);
|
|
5103
5197
|
})() }),
|
|
5104
|
-
visibleColumns.map((column) => /* @__PURE__ */
|
|
5198
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx37("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx37(
|
|
5105
5199
|
TreeCell,
|
|
5106
5200
|
{
|
|
5107
5201
|
flatRow,
|
|
@@ -5115,7 +5209,7 @@ function TreeDataGrid({
|
|
|
5115
5209
|
editingCtx: editingState.ctx
|
|
5116
5210
|
}
|
|
5117
5211
|
) : renderCell(column, flatRow.row, editingState.ctx) }, column.id)),
|
|
5118
|
-
showRowActionsColumn && rowActions && /* @__PURE__ */
|
|
5212
|
+
showRowActionsColumn && rowActions && /* @__PURE__ */ jsx37("td", { className: "p-2", children: /* @__PURE__ */ jsx37(
|
|
5119
5213
|
ActionsMenu,
|
|
5120
5214
|
{
|
|
5121
5215
|
items: rowActions,
|
|
@@ -5132,8 +5226,8 @@ function TreeDataGrid({
|
|
|
5132
5226
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
5133
5227
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
5134
5228
|
return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", "data-testid": "tree-datagrid", children: [
|
|
5135
|
-
hasError && data.length > 0 && /* @__PURE__ */
|
|
5136
|
-
editing && editingState.pendingEdits.size > 0 && /* @__PURE__ */
|
|
5229
|
+
hasError && data.length > 0 && /* @__PURE__ */ jsx37("div", { className: "flex shrink-0 items-center rounded-md border border-destructive/40 bg-destructive/10 px-2 py-1", children: /* @__PURE__ */ jsx37(GridInlineError, { error, onRetry, labels }) }),
|
|
5230
|
+
editing && editingState.pendingEdits.size > 0 && /* @__PURE__ */ jsx37(
|
|
5137
5231
|
EditingBar,
|
|
5138
5232
|
{
|
|
5139
5233
|
editing,
|
|
@@ -5144,143 +5238,167 @@ function TreeDataGrid({
|
|
|
5144
5238
|
testIdPrefix: "tree-datagrid"
|
|
5145
5239
|
}
|
|
5146
5240
|
),
|
|
5147
|
-
/* @__PURE__ */
|
|
5241
|
+
/* @__PURE__ */ jsx37(
|
|
5148
5242
|
"div",
|
|
5149
5243
|
{
|
|
5150
5244
|
ref: scrollRef,
|
|
5151
5245
|
"data-testid": testId,
|
|
5152
5246
|
className: "overflow-y-auto",
|
|
5153
5247
|
style: { maxHeight: maxBodyHeight },
|
|
5154
|
-
children: /* @__PURE__ */ jsxs22(
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5248
|
+
children: /* @__PURE__ */ jsxs22(
|
|
5249
|
+
"table",
|
|
5250
|
+
{
|
|
5251
|
+
className: cn(
|
|
5252
|
+
"border-collapse text-sm",
|
|
5253
|
+
fixedTableWidth === void 0 && "w-full",
|
|
5254
|
+
enableColumnResizing && "table-fixed"
|
|
5255
|
+
),
|
|
5256
|
+
style: fixedTableWidth === void 0 ? void 0 : { width: fixedTableWidth },
|
|
5257
|
+
children: [
|
|
5258
|
+
/* @__PURE__ */ jsx37("thead", { ref: theadRef, children: /* @__PURE__ */ jsxs22("tr", { className: "divide-x divide-border", children: [
|
|
5259
|
+
showSelectionColumn && /* @__PURE__ */ jsx37(
|
|
5260
|
+
"th",
|
|
5163
5261
|
{
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5262
|
+
className: "sticky top-0 z-20 border-b border-border bg-muted p-1",
|
|
5263
|
+
style: { width: SELECTION_COLUMN_WIDTH },
|
|
5264
|
+
children: /* @__PURE__ */ jsx37(
|
|
5265
|
+
Checkbox,
|
|
5266
|
+
{
|
|
5267
|
+
"aria-label": "Select all visible rows",
|
|
5268
|
+
checked: allVisibleSelected,
|
|
5269
|
+
onCheckedChange: toggleAllVisibleSelected
|
|
5270
|
+
}
|
|
5271
|
+
)
|
|
5167
5272
|
}
|
|
5168
|
-
)
|
|
5169
|
-
}
|
|
5170
|
-
),
|
|
5171
|
-
visibleColumns.map((column) => /* @__PURE__ */ jsx36(
|
|
5172
|
-
"th",
|
|
5173
|
-
{
|
|
5174
|
-
style: column.width ? { width: column.width } : void 0,
|
|
5175
|
-
className: cn(
|
|
5176
|
-
"sticky top-0 z-20 border-b border-border bg-muted p-2 font-medium",
|
|
5177
|
-
alignClassName(column)
|
|
5178
5273
|
),
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5274
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsxs22(
|
|
5275
|
+
"th",
|
|
5276
|
+
{
|
|
5277
|
+
style: columnWidthStyle(column),
|
|
5278
|
+
className: cn(
|
|
5279
|
+
"sticky top-0 z-20 border-b border-border bg-muted p-2 font-medium",
|
|
5280
|
+
enableColumnResizing && "overflow-hidden",
|
|
5281
|
+
alignClassName(column)
|
|
5282
|
+
),
|
|
5283
|
+
children: [
|
|
5284
|
+
column.header,
|
|
5285
|
+
enableColumnResizing && /* @__PURE__ */ jsx37(
|
|
5286
|
+
ColumnResizeHandle,
|
|
5287
|
+
{
|
|
5288
|
+
columnId: column.id,
|
|
5289
|
+
label: String(column.header),
|
|
5290
|
+
width: columnSizing[column.id] ?? column.width,
|
|
5291
|
+
onResize: setColumnSize
|
|
5292
|
+
}
|
|
5293
|
+
)
|
|
5294
|
+
]
|
|
5295
|
+
},
|
|
5296
|
+
column.id
|
|
5297
|
+
)),
|
|
5298
|
+
showRowActionsColumn && /* @__PURE__ */ jsx37("th", { className: "sticky top-0 z-20 border-b border-border bg-muted p-2", "aria-label": "Row actions" })
|
|
5299
|
+
] }) }),
|
|
5300
|
+
/* @__PURE__ */ jsx37("tbody", { children: data.length === 0 ? /* @__PURE__ */ jsx37("tr", { children: /* @__PURE__ */ jsx37("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? /* @__PURE__ */ jsx37(LoadingRows, { label: labels.loading }) : hasError ? /* @__PURE__ */ jsx37(GridErrorState, { error, onRetry, labels }) : labels.noResults }) }) : groupedBuckets ? groupedBuckets.map((bucket) => {
|
|
5301
|
+
const groupExpanded = isGroupExpanded(bucket.key);
|
|
5302
|
+
return /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
5303
|
+
/* @__PURE__ */ jsx37("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx37(
|
|
5304
|
+
"td",
|
|
5199
5305
|
{
|
|
5200
|
-
|
|
5201
|
-
className:
|
|
5202
|
-
|
|
5203
|
-
|
|
5306
|
+
colSpan: totalColumnCount,
|
|
5307
|
+
className: cn(
|
|
5308
|
+
"sticky z-20 border-b p-2 font-medium",
|
|
5309
|
+
zebra ? "bg-muted" : "bg-background"
|
|
5310
|
+
),
|
|
5311
|
+
style: { top: groupHeaderTop },
|
|
5312
|
+
children: /* @__PURE__ */ jsxs22(
|
|
5313
|
+
"button",
|
|
5314
|
+
{
|
|
5315
|
+
type: "button",
|
|
5316
|
+
className: "flex w-full items-center gap-1 text-left",
|
|
5317
|
+
onClick: () => toggleGroupExpanded(bucket.key),
|
|
5318
|
+
"aria-expanded": groupExpanded,
|
|
5319
|
+
children: [
|
|
5320
|
+
/* @__PURE__ */ jsx37(
|
|
5321
|
+
ChevronRightIcon3,
|
|
5322
|
+
{
|
|
5323
|
+
className: `h-4 w-4 shrink-0 transition-transform${groupExpanded ? " rotate-90" : ""}`,
|
|
5324
|
+
"aria-hidden": true
|
|
5325
|
+
}
|
|
5326
|
+
),
|
|
5327
|
+
renderGroupHeader ? renderGroupHeader(bucket.key, bucket.roots, groupExpanded) : `${bucket.key} (${bucket.roots.length})`
|
|
5328
|
+
]
|
|
5329
|
+
}
|
|
5330
|
+
)
|
|
5331
|
+
}
|
|
5332
|
+
) }),
|
|
5333
|
+
hasColumnSummary && /* @__PURE__ */ jsxs22(
|
|
5334
|
+
"tr",
|
|
5335
|
+
{
|
|
5336
|
+
"data-testid": `group-summary-${bucket.key}`,
|
|
5337
|
+
className: "border-b border-border divide-x divide-border",
|
|
5204
5338
|
children: [
|
|
5205
|
-
/* @__PURE__ */
|
|
5206
|
-
|
|
5339
|
+
showSelectionColumn && /* @__PURE__ */ jsx37(
|
|
5340
|
+
"td",
|
|
5207
5341
|
{
|
|
5208
|
-
className:
|
|
5209
|
-
|
|
5342
|
+
className: cn("p-2", zebra ? "bg-muted" : "bg-background"),
|
|
5343
|
+
style: { width: SELECTION_COLUMN_WIDTH }
|
|
5210
5344
|
}
|
|
5211
5345
|
),
|
|
5212
|
-
|
|
5346
|
+
renderGroupSummaryCells(bucket.roots),
|
|
5347
|
+
showRowActionsColumn && /* @__PURE__ */ jsx37("td", { className: cn("p-2", zebra ? "bg-muted" : "bg-background"), "aria-hidden": true })
|
|
5213
5348
|
]
|
|
5214
5349
|
}
|
|
5215
|
-
)
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
{
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
"td",
|
|
5226
|
-
{
|
|
5227
|
-
className: cn("p-2", zebra ? "bg-muted" : "bg-background"),
|
|
5228
|
-
style: { width: SELECTION_COLUMN_WIDTH }
|
|
5229
|
-
}
|
|
5230
|
-
),
|
|
5231
|
-
renderGroupSummaryCells(bucket.roots),
|
|
5232
|
-
showRowActionsColumn && /* @__PURE__ */ jsx36("td", { className: cn("p-2", zebra ? "bg-muted" : "bg-background"), "aria-hidden": true })
|
|
5233
|
-
]
|
|
5234
|
-
}
|
|
5235
|
-
),
|
|
5236
|
-
groupExpanded && (() => {
|
|
5237
|
-
const startIndex = groupedRender?.startIndexByBucket.get(bucket.key) ?? 0;
|
|
5238
|
-
return bucket.flatRows.map((flatRow, i) => renderRow(flatRow, startIndex + i));
|
|
5239
|
-
})()
|
|
5240
|
-
] }, `group-${bucket.key}`);
|
|
5241
|
-
}) : shouldVirtualize ? /* @__PURE__ */ jsxs22(Fragment6, { children: [
|
|
5242
|
-
paddingTop > 0 && /* @__PURE__ */ jsx36("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx36("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
|
|
5243
|
-
virtualItems.map(
|
|
5244
|
-
(virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
|
|
5245
|
-
),
|
|
5246
|
-
paddingBottom > 0 && /* @__PURE__ */ jsx36("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx36(
|
|
5247
|
-
"td",
|
|
5248
|
-
{
|
|
5249
|
-
colSpan: totalColumnCount,
|
|
5250
|
-
style: { padding: 0, border: "none", height: paddingBottom }
|
|
5251
|
-
}
|
|
5252
|
-
) })
|
|
5253
|
-
] }) : flatRows.map((flatRow, index) => renderRow(flatRow, index)) }),
|
|
5254
|
-
showTotals && hasColumnSummary && // Sticky to the BOTTOM of the scroll container, mirroring the
|
|
5255
|
-
// `<thead>`'s own `top-0` stickiness — see `<DataGrid>`'s own
|
|
5256
|
-
// `renderTotalsFooter` for the full reasoning. Summarizes `data`
|
|
5257
|
-
// (the root-level rows), not `flatRows`/`allFlatRows` — same
|
|
5258
|
-
// "roots only" scope `groupBy` itself uses, and for the same
|
|
5259
|
-
// reason (a child's value is usually already folded into its
|
|
5260
|
-
// parent's).
|
|
5261
|
-
/* @__PURE__ */ jsx36("tfoot", { children: /* @__PURE__ */ jsxs22("tr", { "data-testid": "totals-row", className: "divide-x divide-border", children: [
|
|
5262
|
-
showSelectionColumn && /* @__PURE__ */ jsx36(
|
|
5263
|
-
"td",
|
|
5264
|
-
{
|
|
5265
|
-
className: "sticky bottom-0 z-20 border-t border-border bg-muted p-2",
|
|
5266
|
-
style: { width: SELECTION_COLUMN_WIDTH }
|
|
5267
|
-
}
|
|
5268
|
-
),
|
|
5269
|
-
visibleColumns.map((column) => /* @__PURE__ */ jsx36(
|
|
5270
|
-
"td",
|
|
5271
|
-
{
|
|
5272
|
-
style: column.width ? { width: column.width } : void 0,
|
|
5273
|
-
className: cn(
|
|
5274
|
-
"sticky bottom-0 z-20 border-t border-border bg-muted p-2 font-medium",
|
|
5275
|
-
alignClassName(column)
|
|
5350
|
+
),
|
|
5351
|
+
groupExpanded && (() => {
|
|
5352
|
+
const startIndex = groupedRender?.startIndexByBucket.get(bucket.key) ?? 0;
|
|
5353
|
+
return bucket.flatRows.map((flatRow, i) => renderRow(flatRow, startIndex + i));
|
|
5354
|
+
})()
|
|
5355
|
+
] }, `group-${bucket.key}`);
|
|
5356
|
+
}) : shouldVirtualize ? /* @__PURE__ */ jsxs22(Fragment6, { children: [
|
|
5357
|
+
paddingTop > 0 && /* @__PURE__ */ jsx37("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx37("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
|
|
5358
|
+
virtualItems.map(
|
|
5359
|
+
(virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
|
|
5276
5360
|
),
|
|
5277
|
-
children:
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5361
|
+
paddingBottom > 0 && /* @__PURE__ */ jsx37("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx37(
|
|
5362
|
+
"td",
|
|
5363
|
+
{
|
|
5364
|
+
colSpan: totalColumnCount,
|
|
5365
|
+
style: { padding: 0, border: "none", height: paddingBottom }
|
|
5366
|
+
}
|
|
5367
|
+
) })
|
|
5368
|
+
] }) : flatRows.map((flatRow, index) => renderRow(flatRow, index)) }),
|
|
5369
|
+
showTotals && hasColumnSummary && // Sticky to the BOTTOM of the scroll container, mirroring the
|
|
5370
|
+
// `<thead>`'s own `top-0` stickiness — see `<DataGrid>`'s own
|
|
5371
|
+
// `renderTotalsFooter` for the full reasoning. Summarizes `data`
|
|
5372
|
+
// (the root-level rows), not `flatRows`/`allFlatRows` — same
|
|
5373
|
+
// "roots only" scope `groupBy` itself uses, and for the same
|
|
5374
|
+
// reason (a child's value is usually already folded into its
|
|
5375
|
+
// parent's).
|
|
5376
|
+
/* @__PURE__ */ jsx37("tfoot", { children: /* @__PURE__ */ jsxs22("tr", { "data-testid": "totals-row", className: "divide-x divide-border", children: [
|
|
5377
|
+
showSelectionColumn && /* @__PURE__ */ jsx37(
|
|
5378
|
+
"td",
|
|
5379
|
+
{
|
|
5380
|
+
className: "sticky bottom-0 z-20 border-t border-border bg-muted p-2",
|
|
5381
|
+
style: { width: SELECTION_COLUMN_WIDTH }
|
|
5382
|
+
}
|
|
5383
|
+
),
|
|
5384
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx37(
|
|
5385
|
+
"td",
|
|
5386
|
+
{
|
|
5387
|
+
style: columnWidthStyle(column),
|
|
5388
|
+
className: cn(
|
|
5389
|
+
"sticky bottom-0 z-20 border-t border-border bg-muted p-2 font-medium",
|
|
5390
|
+
enableColumnResizing && "overflow-hidden",
|
|
5391
|
+
alignClassName(column)
|
|
5392
|
+
),
|
|
5393
|
+
children: column.summary?.(data)
|
|
5394
|
+
},
|
|
5395
|
+
column.id
|
|
5396
|
+
)),
|
|
5397
|
+
showRowActionsColumn && /* @__PURE__ */ jsx37("td", { className: "sticky bottom-0 z-20 border-t border-border bg-muted p-2", "aria-hidden": true })
|
|
5398
|
+
] }) })
|
|
5399
|
+
]
|
|
5400
|
+
}
|
|
5401
|
+
)
|
|
5284
5402
|
}
|
|
5285
5403
|
)
|
|
5286
5404
|
] });
|