@bmsuisse/datagrid 0.27.0 → 0.28.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 +90 -3
- package/dist/index.js +197 -92
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2076,7 +2076,59 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
|
|
|
2076
2076
|
import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
|
|
2077
2077
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2078
2078
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
2079
|
-
import { Fragment as Fragment2, useEffect as useEffect9,
|
|
2079
|
+
import { Fragment as Fragment2, useEffect as useEffect9, useMemo as useMemo7, useRef as useRef8, useState as useState10 } from "react";
|
|
2080
|
+
|
|
2081
|
+
// src/hooks/useGroupExpansion.ts
|
|
2082
|
+
import { useCallback as useCallback2, useState as useState7 } from "react";
|
|
2083
|
+
function useGroupExpansion(defaultGroupsExpanded, controlledExpandedGroups, onExpandedGroupsChange) {
|
|
2084
|
+
const [internalExpandedGroups, setInternalExpandedGroups] = useState7({});
|
|
2085
|
+
const expandedGroups = controlledExpandedGroups ?? internalExpandedGroups;
|
|
2086
|
+
const updateExpandedGroups = useCallback2(
|
|
2087
|
+
(next) => {
|
|
2088
|
+
setInternalExpandedGroups(next);
|
|
2089
|
+
onExpandedGroupsChange?.(next);
|
|
2090
|
+
},
|
|
2091
|
+
[onExpandedGroupsChange]
|
|
2092
|
+
);
|
|
2093
|
+
const isGroupExpanded = useCallback2(
|
|
2094
|
+
(key) => expandedGroups[key] ?? defaultGroupsExpanded,
|
|
2095
|
+
[expandedGroups, defaultGroupsExpanded]
|
|
2096
|
+
);
|
|
2097
|
+
const toggleGroupExpanded = useCallback2(
|
|
2098
|
+
(key) => {
|
|
2099
|
+
updateExpandedGroups({ ...expandedGroups, [key]: !isGroupExpanded(key) });
|
|
2100
|
+
},
|
|
2101
|
+
[expandedGroups, isGroupExpanded, updateExpandedGroups]
|
|
2102
|
+
);
|
|
2103
|
+
return { expandedGroups, isGroupExpanded, toggleGroupExpanded };
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
// src/hooks/useStickyGroupHeaderTop.ts
|
|
2107
|
+
import { useLayoutEffect, useRef as useRef6, useState as useState8 } from "react";
|
|
2108
|
+
function useStickyGroupHeaderTop(enabled) {
|
|
2109
|
+
const theadRef = useRef6(null);
|
|
2110
|
+
const [groupHeaderTop, setGroupHeaderTop] = useState8(0);
|
|
2111
|
+
useLayoutEffect(() => {
|
|
2112
|
+
if (!enabled) return;
|
|
2113
|
+
const theadEl = theadRef.current;
|
|
2114
|
+
if (!theadEl) return;
|
|
2115
|
+
const updateHeight = () => setGroupHeaderTop(theadEl.getBoundingClientRect().height);
|
|
2116
|
+
updateHeight();
|
|
2117
|
+
const observer = new ResizeObserver(updateHeight);
|
|
2118
|
+
observer.observe(theadEl);
|
|
2119
|
+
return () => observer.disconnect();
|
|
2120
|
+
}, [enabled]);
|
|
2121
|
+
return { theadRef, groupHeaderTop };
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
// src/hooks/useVisibleColumns.ts
|
|
2125
|
+
import { useMemo as useMemo4 } from "react";
|
|
2126
|
+
function useVisibleColumns(columns, columnVisibility) {
|
|
2127
|
+
return useMemo4(
|
|
2128
|
+
() => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
|
|
2129
|
+
[columns, columnVisibility]
|
|
2130
|
+
);
|
|
2131
|
+
}
|
|
2080
2132
|
|
|
2081
2133
|
// src/lib/structuralColumns.ts
|
|
2082
2134
|
var SELECTION_COLUMN_WIDTH = 44;
|
|
@@ -2119,20 +2171,20 @@ function processClientData(data, state) {
|
|
|
2119
2171
|
}
|
|
2120
2172
|
|
|
2121
2173
|
// src/grid/useGridState.ts
|
|
2122
|
-
import { useCallback as
|
|
2174
|
+
import { useCallback as useCallback3, useEffect as useEffect8, useMemo as useMemo6, useState as useState9 } from "react";
|
|
2123
2175
|
|
|
2124
2176
|
// src/hooks/useDebouncedCallback.ts
|
|
2125
|
-
import { useEffect as useEffect7, useMemo as
|
|
2177
|
+
import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef7 } from "react";
|
|
2126
2178
|
function useDebouncedCallback(callback, delayMs) {
|
|
2127
|
-
const callbackRef =
|
|
2179
|
+
const callbackRef = useRef7(callback);
|
|
2128
2180
|
callbackRef.current = callback;
|
|
2129
|
-
const timeoutRef =
|
|
2181
|
+
const timeoutRef = useRef7(void 0);
|
|
2130
2182
|
useEffect7(() => {
|
|
2131
2183
|
return () => {
|
|
2132
2184
|
clearTimeout(timeoutRef.current);
|
|
2133
2185
|
};
|
|
2134
2186
|
}, []);
|
|
2135
|
-
return
|
|
2187
|
+
return useMemo5(() => {
|
|
2136
2188
|
return {
|
|
2137
2189
|
run: (...args) => {
|
|
2138
2190
|
clearTimeout(timeoutRef.current);
|
|
@@ -2157,10 +2209,10 @@ function nextSortDir(current, descFirst) {
|
|
|
2157
2209
|
return void 0;
|
|
2158
2210
|
}
|
|
2159
2211
|
function useGridState(dataSource, initialState, externalState) {
|
|
2160
|
-
const [state, setState] =
|
|
2212
|
+
const [state, setState] = useState9(
|
|
2161
2213
|
() => externalState ?? { ...DEFAULT_STATE, ...initialState }
|
|
2162
2214
|
);
|
|
2163
|
-
const notifyRaw =
|
|
2215
|
+
const notifyRaw = useCallback3(
|
|
2164
2216
|
(next) => {
|
|
2165
2217
|
if (dataSource.mode === "server") dataSource.onStateChange(next);
|
|
2166
2218
|
},
|
|
@@ -2170,7 +2222,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
2170
2222
|
notifyRaw,
|
|
2171
2223
|
FILTER_CHANGE_DEBOUNCE_MS
|
|
2172
2224
|
);
|
|
2173
|
-
const notifyNow =
|
|
2225
|
+
const notifyNow = useCallback3(
|
|
2174
2226
|
(next) => {
|
|
2175
2227
|
cancelDebouncedNotify();
|
|
2176
2228
|
notifyRaw(next);
|
|
@@ -2182,14 +2234,14 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
2182
2234
|
cancelDebouncedNotify();
|
|
2183
2235
|
setState(externalState);
|
|
2184
2236
|
}, [externalState, cancelDebouncedNotify]);
|
|
2185
|
-
const filtersByColumn =
|
|
2237
|
+
const filtersByColumn = useMemo6(() => {
|
|
2186
2238
|
const map = /* @__PURE__ */ new Map();
|
|
2187
2239
|
for (const child of state.filter?.filters ?? []) {
|
|
2188
2240
|
if ("operator" in child) map.set(fieldKey(child.field), child);
|
|
2189
2241
|
}
|
|
2190
2242
|
return map;
|
|
2191
2243
|
}, [state.filter]);
|
|
2192
|
-
const setColumnFilter =
|
|
2244
|
+
const setColumnFilter = useCallback3(
|
|
2193
2245
|
(columnId, next) => {
|
|
2194
2246
|
setState((prev) => {
|
|
2195
2247
|
const remaining = (prev.filter?.filters ?? []).filter(
|
|
@@ -2207,7 +2259,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
2207
2259
|
},
|
|
2208
2260
|
[notifyDebounced]
|
|
2209
2261
|
);
|
|
2210
|
-
const toggleSort =
|
|
2262
|
+
const toggleSort = useCallback3(
|
|
2211
2263
|
(columnId, additive, descFirst = false) => {
|
|
2212
2264
|
setState((prev) => {
|
|
2213
2265
|
const existing = prev.sort.find((s) => s.field === columnId);
|
|
@@ -2222,7 +2274,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
2222
2274
|
},
|
|
2223
2275
|
[notifyNow]
|
|
2224
2276
|
);
|
|
2225
|
-
const setPage =
|
|
2277
|
+
const setPage = useCallback3(
|
|
2226
2278
|
(page) => {
|
|
2227
2279
|
setState((prev) => {
|
|
2228
2280
|
const nextState = { ...prev, page };
|
|
@@ -2232,7 +2284,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
2232
2284
|
},
|
|
2233
2285
|
[notifyNow]
|
|
2234
2286
|
);
|
|
2235
|
-
const setPageSize =
|
|
2287
|
+
const setPageSize = useCallback3(
|
|
2236
2288
|
(pageSize) => {
|
|
2237
2289
|
setState((prev) => {
|
|
2238
2290
|
const nextState = { ...prev, pageSize, page: 0 };
|
|
@@ -2322,19 +2374,19 @@ function DataGrid({
|
|
|
2322
2374
|
initialState,
|
|
2323
2375
|
gridState
|
|
2324
2376
|
);
|
|
2325
|
-
const [internalSelectedIds, setInternalSelectedIds] =
|
|
2377
|
+
const [internalSelectedIds, setInternalSelectedIds] = useState10(/* @__PURE__ */ new Set());
|
|
2326
2378
|
const selectedIds = controlledSelectedIds ?? internalSelectedIds;
|
|
2327
2379
|
function updateSelectedIds(next) {
|
|
2328
2380
|
setInternalSelectedIds(next);
|
|
2329
2381
|
onSelectedIdsChange?.(next);
|
|
2330
2382
|
}
|
|
2331
|
-
const [internalColumnSizing, setInternalColumnSizing] =
|
|
2383
|
+
const [internalColumnSizing, setInternalColumnSizing] = useState10({});
|
|
2332
2384
|
const columnSizing = controlledColumnSizing ?? internalColumnSizing;
|
|
2333
2385
|
function updateColumnSizing(next) {
|
|
2334
2386
|
setInternalColumnSizing(next);
|
|
2335
2387
|
onColumnSizingChange?.(next);
|
|
2336
2388
|
}
|
|
2337
|
-
const [expandedIds, setExpandedIds] =
|
|
2389
|
+
const [expandedIds, setExpandedIds] = useState10(/* @__PURE__ */ new Set());
|
|
2338
2390
|
function toggleRowExpanded(id) {
|
|
2339
2391
|
setExpandedIds((prev) => {
|
|
2340
2392
|
const next = new Set(prev);
|
|
@@ -2343,32 +2395,22 @@ function DataGrid({
|
|
|
2343
2395
|
return next;
|
|
2344
2396
|
});
|
|
2345
2397
|
}
|
|
2346
|
-
const
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
}
|
|
2352
|
-
function isGroupExpanded(key) {
|
|
2353
|
-
return expandedGroupsState[key] ?? defaultGroupsExpanded;
|
|
2354
|
-
}
|
|
2355
|
-
function toggleGroupExpanded(key) {
|
|
2356
|
-
updateExpandedGroups({ ...expandedGroupsState, [key]: !isGroupExpanded(key) });
|
|
2357
|
-
}
|
|
2398
|
+
const { isGroupExpanded, toggleGroupExpanded } = useGroupExpansion(
|
|
2399
|
+
defaultGroupsExpanded,
|
|
2400
|
+
controlledExpandedGroups,
|
|
2401
|
+
onExpandedGroupsChange
|
|
2402
|
+
);
|
|
2358
2403
|
const { pendingEdits, editErrors, ctxRef: editingCtxRef, handleSaveEdits, handleDiscardEdits } = useEditingState(
|
|
2359
2404
|
editing,
|
|
2360
2405
|
getRowId
|
|
2361
2406
|
);
|
|
2362
|
-
const visibleColumns =
|
|
2363
|
-
() => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
|
|
2364
|
-
[columns, columnVisibility]
|
|
2365
|
-
);
|
|
2407
|
+
const visibleColumns = useVisibleColumns(columns, columnVisibility);
|
|
2366
2408
|
const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
|
|
2367
|
-
const { rows, rowCount } =
|
|
2409
|
+
const { rows, rowCount } = useMemo7(() => {
|
|
2368
2410
|
if (dataSource.mode === "client") return processClientData(dataSource.data, state);
|
|
2369
2411
|
return { rows: dataSource.data, rowCount: serverRowCount ?? 0 };
|
|
2370
2412
|
}, [dataSource.mode, dataSource.data, serverRowCount, state]);
|
|
2371
|
-
const selectedRows =
|
|
2413
|
+
const selectedRows = useMemo7(
|
|
2372
2414
|
() => rows.filter((row) => selectedIds.has(getRowId(row))),
|
|
2373
2415
|
[rows, selectedIds, getRowId]
|
|
2374
2416
|
);
|
|
@@ -2387,8 +2429,8 @@ function DataGrid({
|
|
|
2387
2429
|
}
|
|
2388
2430
|
updateSelectedIds(next);
|
|
2389
2431
|
}
|
|
2390
|
-
const tanstackColumns =
|
|
2391
|
-
const columnById =
|
|
2432
|
+
const tanstackColumns = useMemo7(() => toTanstackColumns(visibleColumns, editingCtxRef), [visibleColumns]);
|
|
2433
|
+
const columnById = useMemo7(() => {
|
|
2392
2434
|
const map = /* @__PURE__ */ new Map();
|
|
2393
2435
|
for (const column of visibleColumns) map.set(column.id, column);
|
|
2394
2436
|
return map;
|
|
@@ -2413,7 +2455,7 @@ function DataGrid({
|
|
|
2413
2455
|
const showDetailColumn = Boolean(renderDetail);
|
|
2414
2456
|
const totalColumnCount = visibleColumns.length + (showDetailColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0) + (showRowActionsColumn ? 1 : 0);
|
|
2415
2457
|
const hasFilterRow = visibleColumns.some((column) => isFilterable(column) && column.filterDisplay === "row");
|
|
2416
|
-
const headerRuns =
|
|
2458
|
+
const headerRuns = useMemo7(() => computeHeaderRuns(visibleColumns), [visibleColumns]);
|
|
2417
2459
|
const hasHeaderGroups = visibleColumns.some((column) => column.headerGroup);
|
|
2418
2460
|
function renderFilterWidget(column) {
|
|
2419
2461
|
const value = filtersByColumn.get(column.id);
|
|
@@ -2423,11 +2465,11 @@ function DataGrid({
|
|
|
2423
2465
|
const columnSize = (columnId) => table.getColumn(columnId)?.getSize() ?? DEFAULT_COLUMN_SIZE;
|
|
2424
2466
|
const leadingStructuralWidth = (showDetailColumn ? DETAIL_COLUMN_WIDTH : 0) + (showSelectionColumn ? SELECTION_COLUMN_WIDTH : 0);
|
|
2425
2467
|
const trailingStructuralWidth = showRowActionsColumn ? ROW_ACTIONS_COLUMN_WIDTH : 0;
|
|
2426
|
-
const leftPinnedOffsets =
|
|
2468
|
+
const leftPinnedOffsets = useMemo7(
|
|
2427
2469
|
() => pinnedOffsets(visibleColumns, "left", columnSize, leadingStructuralWidth),
|
|
2428
2470
|
[visibleColumns, columnSizing, leadingStructuralWidth]
|
|
2429
2471
|
);
|
|
2430
|
-
const rightPinnedOffsets =
|
|
2472
|
+
const rightPinnedOffsets = useMemo7(
|
|
2431
2473
|
() => pinnedOffsets(visibleColumns, "right", columnSize, trailingStructuralWidth),
|
|
2432
2474
|
[visibleColumns, columnSizing, trailingStructuralWidth]
|
|
2433
2475
|
);
|
|
@@ -2475,7 +2517,7 @@ function DataGrid({
|
|
|
2475
2517
|
style: pinnedProps?.style
|
|
2476
2518
|
};
|
|
2477
2519
|
}
|
|
2478
|
-
const bodyCellPropsByColumn =
|
|
2520
|
+
const bodyCellPropsByColumn = useMemo7(() => {
|
|
2479
2521
|
const map = /* @__PURE__ */ new Map();
|
|
2480
2522
|
for (const column of visibleColumns) map.set(column.id, bodyCellClassAndStyle(column));
|
|
2481
2523
|
return map;
|
|
@@ -2491,7 +2533,7 @@ function DataGrid({
|
|
|
2491
2533
|
);
|
|
2492
2534
|
return { className, style: pinnedProps.style };
|
|
2493
2535
|
}
|
|
2494
|
-
const leafHeaderCellPropsByColumn =
|
|
2536
|
+
const leafHeaderCellPropsByColumn = useMemo7(() => {
|
|
2495
2537
|
const map = /* @__PURE__ */ new Map();
|
|
2496
2538
|
for (const column of visibleColumns) {
|
|
2497
2539
|
map.set(
|
|
@@ -2501,7 +2543,7 @@ function DataGrid({
|
|
|
2501
2543
|
}
|
|
2502
2544
|
return map;
|
|
2503
2545
|
}, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
|
|
2504
|
-
const filterHeaderCellPropsByColumn =
|
|
2546
|
+
const filterHeaderCellPropsByColumn = useMemo7(() => {
|
|
2505
2547
|
const map = /* @__PURE__ */ new Map();
|
|
2506
2548
|
for (const column of visibleColumns) {
|
|
2507
2549
|
map.set(column.id, headerCellClassAndStyle(column, "border-b border-border p-2 align-top font-normal"));
|
|
@@ -2510,23 +2552,12 @@ function DataGrid({
|
|
|
2510
2552
|
}, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
|
|
2511
2553
|
const tableRows = table.getRowModel().rows;
|
|
2512
2554
|
const shouldVirtualize = Boolean(virtualize) && !groupBy && tableRows.length > (virtualize?.threshold ?? 100);
|
|
2513
|
-
const groupedBuckets =
|
|
2555
|
+
const groupedBuckets = useMemo7(
|
|
2514
2556
|
() => groupBy ? groupRows(tableRows, (row) => groupBy(row.original)) : void 0,
|
|
2515
2557
|
[tableRows, groupBy]
|
|
2516
2558
|
);
|
|
2517
|
-
const theadRef =
|
|
2518
|
-
const
|
|
2519
|
-
useLayoutEffect(() => {
|
|
2520
|
-
if (!groupBy) return;
|
|
2521
|
-
const theadEl = theadRef.current;
|
|
2522
|
-
if (!theadEl) return;
|
|
2523
|
-
const updateHeight = () => setGroupHeaderTop(theadEl.getBoundingClientRect().height);
|
|
2524
|
-
updateHeight();
|
|
2525
|
-
const observer = new ResizeObserver(updateHeight);
|
|
2526
|
-
observer.observe(theadEl);
|
|
2527
|
-
return () => observer.disconnect();
|
|
2528
|
-
}, [groupBy]);
|
|
2529
|
-
const scrollRef = useRef7(null);
|
|
2559
|
+
const { theadRef, groupHeaderTop } = useStickyGroupHeaderTop(Boolean(groupBy));
|
|
2560
|
+
const scrollRef = useRef8(null);
|
|
2530
2561
|
const virtualizer = useVirtualizer({
|
|
2531
2562
|
count: tableRows.length,
|
|
2532
2563
|
getScrollElement: () => scrollRef.current,
|
|
@@ -2538,7 +2569,7 @@ function DataGrid({
|
|
|
2538
2569
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
2539
2570
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
2540
2571
|
const lastVisibleIndex = virtualItems.length > 0 ? virtualItems[virtualItems.length - 1].index : -1;
|
|
2541
|
-
const notifiedForLengthRef =
|
|
2572
|
+
const notifiedForLengthRef = useRef8(-1);
|
|
2542
2573
|
useEffect9(() => {
|
|
2543
2574
|
if (!virtualize?.onEndReached) return;
|
|
2544
2575
|
if (lastVisibleIndex < 0 || lastVisibleIndex < tableRows.length - 1) return;
|
|
@@ -2931,7 +2962,7 @@ function DataGrid({
|
|
|
2931
2962
|
// src/tree/TreeDataGrid.tsx
|
|
2932
2963
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
2933
2964
|
import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
|
|
2934
|
-
import { useEffect as useEffect10, useMemo as
|
|
2965
|
+
import { Fragment as Fragment4, useEffect as useEffect10, useMemo as useMemo9, useRef as useRef9 } from "react";
|
|
2935
2966
|
|
|
2936
2967
|
// src/tree/flattenTree.ts
|
|
2937
2968
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -2976,7 +3007,7 @@ function computeSelectionStates(roots, accessors, childrenOverride, selectedIds)
|
|
|
2976
3007
|
}
|
|
2977
3008
|
|
|
2978
3009
|
// src/tree/useTreeState.ts
|
|
2979
|
-
import { useCallback as
|
|
3010
|
+
import { useCallback as useCallback4, useMemo as useMemo8, useState as useState11 } from "react";
|
|
2980
3011
|
function useTreeState({
|
|
2981
3012
|
data,
|
|
2982
3013
|
getRowId,
|
|
@@ -2988,9 +3019,9 @@ function useTreeState({
|
|
|
2988
3019
|
childrenMap: controlledChildrenMap,
|
|
2989
3020
|
onChildrenMapChange
|
|
2990
3021
|
}) {
|
|
2991
|
-
const [internalExpanded, setInternalExpanded] =
|
|
3022
|
+
const [internalExpanded, setInternalExpanded] = useState11({});
|
|
2992
3023
|
const expanded = controlledExpanded ?? internalExpanded;
|
|
2993
|
-
const setExpanded =
|
|
3024
|
+
const setExpanded = useCallback4(
|
|
2994
3025
|
(updater) => {
|
|
2995
3026
|
if (controlledExpanded) {
|
|
2996
3027
|
onExpandedChange?.(updater(controlledExpanded));
|
|
@@ -3000,9 +3031,9 @@ function useTreeState({
|
|
|
3000
3031
|
},
|
|
3001
3032
|
[controlledExpanded, onExpandedChange]
|
|
3002
3033
|
);
|
|
3003
|
-
const [internalChildrenMap, setInternalChildrenMap] =
|
|
3034
|
+
const [internalChildrenMap, setInternalChildrenMap] = useState11(/* @__PURE__ */ new Map());
|
|
3004
3035
|
const childrenMap = controlledChildrenMap ?? internalChildrenMap;
|
|
3005
|
-
const setChildrenMap =
|
|
3036
|
+
const setChildrenMap = useCallback4(
|
|
3006
3037
|
(updater) => {
|
|
3007
3038
|
if (controlledChildrenMap) {
|
|
3008
3039
|
onChildrenMapChange?.(updater(controlledChildrenMap));
|
|
@@ -3012,13 +3043,13 @@ function useTreeState({
|
|
|
3012
3043
|
},
|
|
3013
3044
|
[controlledChildrenMap, onChildrenMapChange]
|
|
3014
3045
|
);
|
|
3015
|
-
const [loadingIds, setLoadingIds] =
|
|
3016
|
-
const [errorIds, setErrorIds] =
|
|
3017
|
-
const resolveHasChildren =
|
|
3046
|
+
const [loadingIds, setLoadingIds] = useState11(/* @__PURE__ */ new Set());
|
|
3047
|
+
const [errorIds, setErrorIds] = useState11(/* @__PURE__ */ new Map());
|
|
3048
|
+
const resolveHasChildren = useMemo8(
|
|
3018
3049
|
() => hasChildren ?? ((row) => (getChildren(row)?.length ?? 0) > 0),
|
|
3019
3050
|
[hasChildren, getChildren]
|
|
3020
3051
|
);
|
|
3021
|
-
const loadChildrenFor =
|
|
3052
|
+
const loadChildrenFor = useCallback4(
|
|
3022
3053
|
async (row) => {
|
|
3023
3054
|
const id = getRowId(row);
|
|
3024
3055
|
const cached = childrenMap.get(id);
|
|
@@ -3051,7 +3082,7 @@ function useTreeState({
|
|
|
3051
3082
|
},
|
|
3052
3083
|
[childrenMap, getChildren, getRowId, onLoadChildren, setChildrenMap]
|
|
3053
3084
|
);
|
|
3054
|
-
const toggleExpand =
|
|
3085
|
+
const toggleExpand = useCallback4(
|
|
3055
3086
|
(row) => {
|
|
3056
3087
|
const id = getRowId(row);
|
|
3057
3088
|
const willExpand = !expanded[id];
|
|
@@ -3063,14 +3094,14 @@ function useTreeState({
|
|
|
3063
3094
|
},
|
|
3064
3095
|
[expanded, getRowId, loadChildrenFor, resolveHasChildren, setExpanded]
|
|
3065
3096
|
);
|
|
3066
|
-
const retry =
|
|
3097
|
+
const retry = useCallback4(
|
|
3067
3098
|
(row) => {
|
|
3068
3099
|
loadChildrenFor(row).catch(() => {
|
|
3069
3100
|
});
|
|
3070
3101
|
},
|
|
3071
3102
|
[loadChildrenFor]
|
|
3072
3103
|
);
|
|
3073
|
-
const expandToLevel =
|
|
3104
|
+
const expandToLevel = useCallback4(
|
|
3074
3105
|
async (level) => {
|
|
3075
3106
|
const nextExpanded = { ...expanded };
|
|
3076
3107
|
async function visit(row, depth) {
|
|
@@ -3093,7 +3124,7 @@ function useTreeState({
|
|
|
3093
3124
|
}
|
|
3094
3125
|
|
|
3095
3126
|
// src/tree/TreeDataGrid.tsx
|
|
3096
|
-
import { Fragment as
|
|
3127
|
+
import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3097
3128
|
var EMPTY_SELECTED_IDS = /* @__PURE__ */ new Set();
|
|
3098
3129
|
var UNCHECKED_STATE = { checked: false, indeterminate: false };
|
|
3099
3130
|
function renderCell(column, row, editingCtx) {
|
|
@@ -3137,6 +3168,7 @@ function TreeDataGrid({
|
|
|
3137
3168
|
columns,
|
|
3138
3169
|
data,
|
|
3139
3170
|
treeColumnId,
|
|
3171
|
+
columnVisibility,
|
|
3140
3172
|
getRowId,
|
|
3141
3173
|
getChildren,
|
|
3142
3174
|
hasChildren,
|
|
@@ -3157,10 +3189,15 @@ function TreeDataGrid({
|
|
|
3157
3189
|
onSelectedIdsChange,
|
|
3158
3190
|
getRowSelectionState,
|
|
3159
3191
|
isRowSelectionDisabled,
|
|
3192
|
+
groupBy,
|
|
3193
|
+
renderGroupHeader,
|
|
3194
|
+
defaultGroupsExpanded = true,
|
|
3195
|
+
expandedGroups: controlledExpandedGroups,
|
|
3196
|
+
onExpandedGroupsChange,
|
|
3160
3197
|
zebra = true,
|
|
3161
3198
|
editing
|
|
3162
3199
|
}) {
|
|
3163
|
-
const accessors =
|
|
3200
|
+
const accessors = useMemo9(
|
|
3164
3201
|
() => ({ getRowId, getChildren, hasChildren }),
|
|
3165
3202
|
[getRowId, getChildren, hasChildren]
|
|
3166
3203
|
);
|
|
@@ -3176,21 +3213,48 @@ function TreeDataGrid({
|
|
|
3176
3213
|
childrenMap: controlledChildrenMap,
|
|
3177
3214
|
onChildrenMapChange
|
|
3178
3215
|
});
|
|
3179
|
-
const didAutoExpand =
|
|
3216
|
+
const didAutoExpand = useRef9(false);
|
|
3180
3217
|
useEffect10(() => {
|
|
3181
3218
|
if (didAutoExpand.current) return;
|
|
3182
3219
|
didAutoExpand.current = true;
|
|
3183
3220
|
if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
|
|
3184
3221
|
}, []);
|
|
3185
|
-
const
|
|
3186
|
-
|
|
3187
|
-
|
|
3222
|
+
const visibleColumns = useVisibleColumns(columns, columnVisibility);
|
|
3223
|
+
const { isGroupExpanded, toggleGroupExpanded } = useGroupExpansion(
|
|
3224
|
+
defaultGroupsExpanded,
|
|
3225
|
+
controlledExpandedGroups,
|
|
3226
|
+
onExpandedGroupsChange
|
|
3227
|
+
);
|
|
3228
|
+
const flatRows = useMemo9(
|
|
3229
|
+
() => groupBy ? [] : flattenTree(data, accessors, expanded, childrenMap),
|
|
3230
|
+
[groupBy, data, accessors, expanded, childrenMap]
|
|
3231
|
+
);
|
|
3232
|
+
const groupedBuckets = useMemo9(
|
|
3233
|
+
() => groupBy ? groupRows(data, groupBy).map((bucket) => ({
|
|
3234
|
+
key: bucket.key,
|
|
3235
|
+
roots: bucket.items,
|
|
3236
|
+
flatRows: flattenTree(bucket.items, accessors, expanded, childrenMap)
|
|
3237
|
+
})) : void 0,
|
|
3238
|
+
[groupBy, data, accessors, expanded, childrenMap]
|
|
3188
3239
|
);
|
|
3240
|
+
const groupedRender = useMemo9(() => {
|
|
3241
|
+
if (!groupedBuckets) return void 0;
|
|
3242
|
+
const startIndexByBucket = /* @__PURE__ */ new Map();
|
|
3243
|
+
const rows = [];
|
|
3244
|
+
for (const bucket of groupedBuckets) {
|
|
3245
|
+
if (!isGroupExpanded(bucket.key)) continue;
|
|
3246
|
+
startIndexByBucket.set(bucket.key, rows.length);
|
|
3247
|
+
rows.push(...bucket.flatRows);
|
|
3248
|
+
}
|
|
3249
|
+
return { startIndexByBucket, rows };
|
|
3250
|
+
}, [groupedBuckets, isGroupExpanded]);
|
|
3251
|
+
const allFlatRows = groupedRender ? groupedRender.rows : flatRows;
|
|
3189
3252
|
const treeColId = treeColumnId ?? columns[0]?.id;
|
|
3190
3253
|
const showRowActionsColumn = Boolean(rowActions?.length);
|
|
3191
3254
|
const showSelectionColumn = controlledSelectedIds !== void 0;
|
|
3192
|
-
const totalColumnCount =
|
|
3193
|
-
const
|
|
3255
|
+
const totalColumnCount = visibleColumns.length + (showRowActionsColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0);
|
|
3256
|
+
const { theadRef, groupHeaderTop } = useStickyGroupHeaderTop(Boolean(groupBy));
|
|
3257
|
+
const selectionStates = useMemo9(
|
|
3194
3258
|
() => showSelectionColumn ? computeSelectionStates(data, accessors, childrenMap, controlledSelectedIds ?? EMPTY_SELECTED_IDS) : void 0,
|
|
3195
3259
|
[showSelectionColumn, data, accessors, childrenMap, controlledSelectedIds]
|
|
3196
3260
|
);
|
|
@@ -3206,9 +3270,9 @@ function TreeDataGrid({
|
|
|
3206
3270
|
else next.add(id);
|
|
3207
3271
|
onSelectedIdsChange?.(next);
|
|
3208
3272
|
}
|
|
3209
|
-
const selectableFlatRows =
|
|
3210
|
-
() =>
|
|
3211
|
-
[
|
|
3273
|
+
const selectableFlatRows = useMemo9(
|
|
3274
|
+
() => allFlatRows.filter((flatRow) => !(isRowSelectionDisabled?.(flatRow.row) ?? false)),
|
|
3275
|
+
[allFlatRows, isRowSelectionDisabled]
|
|
3212
3276
|
);
|
|
3213
3277
|
const allVisibleSelected = showSelectionColumn && selectableFlatRows.length > 0 && selectableFlatRows.every((flatRow) => controlledSelectedIds.has(flatRow.id));
|
|
3214
3278
|
function toggleAllVisibleSelected() {
|
|
@@ -3220,13 +3284,13 @@ function TreeDataGrid({
|
|
|
3220
3284
|
}
|
|
3221
3285
|
onSelectedIdsChange?.(next);
|
|
3222
3286
|
}
|
|
3223
|
-
const bodyTdClassByColumn =
|
|
3287
|
+
const bodyTdClassByColumn = useMemo9(() => {
|
|
3224
3288
|
const map = /* @__PURE__ */ new Map();
|
|
3225
|
-
for (const column of
|
|
3289
|
+
for (const column of visibleColumns) map.set(column.id, `p-2 ${alignClassName(column)}`);
|
|
3226
3290
|
return map;
|
|
3227
|
-
}, [
|
|
3228
|
-
const scrollRef =
|
|
3229
|
-
const shouldVirtualize = flatRows.length > virtualizeThreshold;
|
|
3291
|
+
}, [visibleColumns]);
|
|
3292
|
+
const scrollRef = useRef9(null);
|
|
3293
|
+
const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
|
|
3230
3294
|
const virtualizer = useVirtualizer2({
|
|
3231
3295
|
count: flatRows.length,
|
|
3232
3296
|
getScrollElement: () => scrollRef.current,
|
|
@@ -3264,7 +3328,7 @@ function TreeDataGrid({
|
|
|
3264
3328
|
}
|
|
3265
3329
|
);
|
|
3266
3330
|
})() }),
|
|
3267
|
-
|
|
3331
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx29("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx29(
|
|
3268
3332
|
TreeCell,
|
|
3269
3333
|
{
|
|
3270
3334
|
flatRow,
|
|
@@ -3312,7 +3376,7 @@ function TreeDataGrid({
|
|
|
3312
3376
|
className: shouldVirtualize ? "overflow-y-auto" : void 0,
|
|
3313
3377
|
style: shouldVirtualize ? { maxHeight: maxBodyHeight } : void 0,
|
|
3314
3378
|
children: /* @__PURE__ */ jsxs19("table", { className: "w-full border-collapse text-sm", children: [
|
|
3315
|
-
/* @__PURE__ */ jsx29("thead", { children: /* @__PURE__ */ jsxs19("tr", { className: "divide-x divide-border", children: [
|
|
3379
|
+
/* @__PURE__ */ jsx29("thead", { ref: theadRef, children: /* @__PURE__ */ jsxs19("tr", { className: "divide-x divide-border", children: [
|
|
3316
3380
|
showSelectionColumn && /* @__PURE__ */ jsx29("th", { className: "border-b border-border p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: /* @__PURE__ */ jsx29(
|
|
3317
3381
|
Checkbox,
|
|
3318
3382
|
{
|
|
@@ -3321,7 +3385,7 @@ function TreeDataGrid({
|
|
|
3321
3385
|
onCheckedChange: toggleAllVisibleSelected
|
|
3322
3386
|
}
|
|
3323
3387
|
) }),
|
|
3324
|
-
|
|
3388
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx29(
|
|
3325
3389
|
"th",
|
|
3326
3390
|
{
|
|
3327
3391
|
style: column.width ? { width: column.width } : void 0,
|
|
@@ -3332,7 +3396,45 @@ function TreeDataGrid({
|
|
|
3332
3396
|
)),
|
|
3333
3397
|
showRowActionsColumn && /* @__PURE__ */ jsx29("th", { className: "border-b border-border p-2", "aria-label": "Row actions" })
|
|
3334
3398
|
] }) }),
|
|
3335
|
-
/* @__PURE__ */ jsx29("tbody", { children:
|
|
3399
|
+
/* @__PURE__ */ jsx29("tbody", { children: data.length === 0 ? /* @__PURE__ */ jsx29("tr", { children: /* @__PURE__ */ jsx29("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: "No results." }) }) : groupedBuckets ? groupedBuckets.map((bucket) => {
|
|
3400
|
+
const groupExpanded = isGroupExpanded(bucket.key);
|
|
3401
|
+
return /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
3402
|
+
/* @__PURE__ */ jsx29("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx29(
|
|
3403
|
+
"td",
|
|
3404
|
+
{
|
|
3405
|
+
colSpan: totalColumnCount,
|
|
3406
|
+
className: cn(
|
|
3407
|
+
"sticky z-20 border-b p-2 font-medium",
|
|
3408
|
+
zebra ? "bg-muted" : "bg-background"
|
|
3409
|
+
),
|
|
3410
|
+
style: { top: groupHeaderTop },
|
|
3411
|
+
children: /* @__PURE__ */ jsxs19(
|
|
3412
|
+
"button",
|
|
3413
|
+
{
|
|
3414
|
+
type: "button",
|
|
3415
|
+
className: "flex w-full items-center gap-1 text-left",
|
|
3416
|
+
onClick: () => toggleGroupExpanded(bucket.key),
|
|
3417
|
+
"aria-expanded": groupExpanded,
|
|
3418
|
+
children: [
|
|
3419
|
+
/* @__PURE__ */ jsx29(
|
|
3420
|
+
ChevronRight2,
|
|
3421
|
+
{
|
|
3422
|
+
className: `h-4 w-4 shrink-0 transition-transform${groupExpanded ? " rotate-90" : ""}`,
|
|
3423
|
+
"aria-hidden": true
|
|
3424
|
+
}
|
|
3425
|
+
),
|
|
3426
|
+
renderGroupHeader ? renderGroupHeader(bucket.key, bucket.roots, groupExpanded) : `${bucket.key} (${bucket.roots.length})`
|
|
3427
|
+
]
|
|
3428
|
+
}
|
|
3429
|
+
)
|
|
3430
|
+
}
|
|
3431
|
+
) }),
|
|
3432
|
+
groupExpanded && (() => {
|
|
3433
|
+
const startIndex = groupedRender?.startIndexByBucket.get(bucket.key) ?? 0;
|
|
3434
|
+
return bucket.flatRows.map((flatRow, i) => renderRow(flatRow, startIndex + i));
|
|
3435
|
+
})()
|
|
3436
|
+
] }, `group-${bucket.key}`);
|
|
3437
|
+
}) : shouldVirtualize ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
|
|
3336
3438
|
paddingTop > 0 && /* @__PURE__ */ jsx29("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx29("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
|
|
3337
3439
|
virtualItems.map(
|
|
3338
3440
|
(virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
|
|
@@ -3399,6 +3501,9 @@ export {
|
|
|
3399
3501
|
useDebouncedCallback,
|
|
3400
3502
|
useEditingState,
|
|
3401
3503
|
useGridState,
|
|
3402
|
-
|
|
3504
|
+
useGroupExpansion,
|
|
3505
|
+
useStickyGroupHeaderTop,
|
|
3506
|
+
useTreeState,
|
|
3507
|
+
useVisibleColumns
|
|
3403
3508
|
};
|
|
3404
3509
|
//# sourceMappingURL=index.js.map
|