@bmsuisse/datagrid 0.31.0 → 0.31.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +28 -5
- package/dist/index.js +187 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -668,7 +668,11 @@ declare function BooleanEditor<TRow>({ column, rowId, value, onChange, error, au
|
|
|
668
668
|
declare function DateEditor<TRow>({ column, rowId, value, onChange, error, autoFocus, }: EditWidgetProps<DateColumn<TRow>>): ReactElement;
|
|
669
669
|
|
|
670
670
|
/** Default inline editor for `type: "enum"` columns: a single-value select over `column.options`. */
|
|
671
|
-
declare function EnumEditor<TRow>({ column, rowId, value, onChange, error, autoFocus, }: EditWidgetProps<EnumColumn<TRow>>
|
|
671
|
+
declare function EnumEditor<TRow>({ column, rowId, value, onChange, error, autoFocus, open, onOpenChange, }: EditWidgetProps<EnumColumn<TRow>> & {
|
|
672
|
+
/** Controls the dropdown's own open state — omit to let `<Select>` manage it itself (the default, used everywhere except `AlwaysEditCell`; see that file's own doc for why it needs control here). */
|
|
673
|
+
open?: boolean;
|
|
674
|
+
onOpenChange?: (open: boolean) => void;
|
|
675
|
+
}): ReactElement;
|
|
672
676
|
|
|
673
677
|
/**
|
|
674
678
|
* Default inline editor for a `type: "string"` column with `multiline: true`:
|
|
@@ -1420,9 +1424,18 @@ interface DataGridProps<TRow> {
|
|
|
1420
1424
|
/**
|
|
1421
1425
|
* Renders the built-in Previous/Next pagination footer. Defaults to true.
|
|
1422
1426
|
* Set to false when a caller renders its own pagination UI instead (e.g.
|
|
1423
|
-
* one with specific `data-testid`s an existing test suite depends on)
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1427
|
+
* one with specific `data-testid`s an existing test suite depends on), or
|
|
1428
|
+
* to disable pagination altogether and render every row.
|
|
1429
|
+
*
|
|
1430
|
+
* When `false` and no explicit `pageSize` is given (via `initialState` or
|
|
1431
|
+
* `gridState`), the effective page size becomes unbounded instead of
|
|
1432
|
+
* defaulting to 20 — hiding the pagination UI with no page size in mind
|
|
1433
|
+
* means "show every row," not "silently truncate to the first page." A
|
|
1434
|
+
* caller who explicitly sets `pageSize` alongside `showPagination: false`
|
|
1435
|
+
* still gets exactly that page size (deliberate fixed-size chunking with
|
|
1436
|
+
* no UI). This only affects `"client"` mode's own row slicing; in
|
|
1437
|
+
* `"server"` mode, whether every row actually comes back is up to your
|
|
1438
|
+
* `dataSource`.
|
|
1426
1439
|
*/
|
|
1427
1440
|
showPagination?: boolean;
|
|
1428
1441
|
/**
|
|
@@ -1609,8 +1622,18 @@ interface GridStateController {
|
|
|
1609
1622
|
* across the component's lifetime — start controlled and stay controlled,
|
|
1610
1623
|
* or start uncontrolled and stay uncontrolled; toggling to `undefined`
|
|
1611
1624
|
* later does not hand ownership back, it just stops resyncing.
|
|
1625
|
+
*
|
|
1626
|
+
* `showPagination`, when `false` and the caller did NOT explicitly provide
|
|
1627
|
+
* `initialState.pageSize`, seeds `pageSize` as effectively unbounded instead
|
|
1628
|
+
* of `DEFAULT_STATE`'s 20 — "hide the pagination controls" means "no
|
|
1629
|
+
* pagination" by default, matching `<DataGrid>`'s `showPagination` doc. A
|
|
1630
|
+
* caller who explicitly sets `initialState.pageSize` (deliberate fixed-size
|
|
1631
|
+
* chunking with no UI, alongside `showPagination: false`) still gets exactly
|
|
1632
|
+
* that value; this only changes what happens when they didn't ask for a
|
|
1633
|
+
* particular page size at all. Has no effect once `externalState` is in
|
|
1634
|
+
* play — a controlled `GridState` is always fully caller-specified.
|
|
1612
1635
|
*/
|
|
1613
|
-
declare function useGridState<TRow>(dataSource: DataSource<TRow>, initialState?: Partial<GridState>, externalState?: GridState): GridStateController;
|
|
1636
|
+
declare function useGridState<TRow>(dataSource: DataSource<TRow>, initialState?: Partial<GridState>, externalState?: GridState, showPagination?: boolean): GridStateController;
|
|
1614
1637
|
|
|
1615
1638
|
interface ClientProcessingResult<TRow> {
|
|
1616
1639
|
rows: TRow[];
|
package/dist/index.js
CHANGED
|
@@ -1477,25 +1477,36 @@ function EnumEditor({
|
|
|
1477
1477
|
value,
|
|
1478
1478
|
onChange,
|
|
1479
1479
|
error,
|
|
1480
|
-
autoFocus
|
|
1480
|
+
autoFocus,
|
|
1481
|
+
open,
|
|
1482
|
+
onOpenChange
|
|
1481
1483
|
}) {
|
|
1482
1484
|
const errorId = editErrorId(rowId, column.id);
|
|
1483
1485
|
return /* @__PURE__ */ jsxs11("div", { children: [
|
|
1484
|
-
/* @__PURE__ */ jsxs11(
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1486
|
+
/* @__PURE__ */ jsxs11(
|
|
1487
|
+
Select,
|
|
1488
|
+
{
|
|
1489
|
+
value: value === null || value === void 0 ? "" : String(value),
|
|
1490
|
+
onValueChange: onChange,
|
|
1491
|
+
open,
|
|
1492
|
+
onOpenChange,
|
|
1493
|
+
children: [
|
|
1494
|
+
/* @__PURE__ */ jsx18(
|
|
1495
|
+
SelectTrigger,
|
|
1496
|
+
{
|
|
1497
|
+
className: "h-8",
|
|
1498
|
+
"aria-label": `Edit ${column.header}`,
|
|
1499
|
+
"aria-invalid": error ? true : void 0,
|
|
1500
|
+
"aria-describedby": error ? errorId : void 0,
|
|
1501
|
+
"data-testid": `edit-${rowId}-${column.id}`,
|
|
1502
|
+
autoFocus,
|
|
1503
|
+
children: /* @__PURE__ */ jsx18(SelectValue, {})
|
|
1504
|
+
}
|
|
1505
|
+
),
|
|
1506
|
+
/* @__PURE__ */ jsx18(SelectContent, { children: column.options.map((option) => /* @__PURE__ */ jsx18(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1507
|
+
]
|
|
1508
|
+
}
|
|
1509
|
+
),
|
|
1499
1510
|
error && /* @__PURE__ */ jsx18(EditFieldError, { id: errorId, message: error })
|
|
1500
1511
|
] });
|
|
1501
1512
|
}
|
|
@@ -2261,7 +2272,7 @@ function renderCellModeCell(column, row, rawValue, ctx) {
|
|
|
2261
2272
|
}
|
|
2262
2273
|
|
|
2263
2274
|
// src/cell-editing/SelectionOverlay.tsx
|
|
2264
|
-
import { useLayoutEffect as useLayoutEffect2, useState as useState9 } from "react";
|
|
2275
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef9, useState as useState9 } from "react";
|
|
2265
2276
|
import { Fragment as Fragment2, jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2266
2277
|
function cellSelector(rowId, columnId) {
|
|
2267
2278
|
const escape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
@@ -2294,13 +2305,27 @@ function SelectionOverlay({
|
|
|
2294
2305
|
}) {
|
|
2295
2306
|
const [rect, setRect] = useState9(void 0);
|
|
2296
2307
|
const [previewRect, setPreviewRect] = useState9(void 0);
|
|
2297
|
-
|
|
2308
|
+
const recomputeRef = useRef9(() => {
|
|
2309
|
+
});
|
|
2310
|
+
recomputeRef.current = () => {
|
|
2298
2311
|
const container = containerRef.current;
|
|
2299
2312
|
const nextRect = range && container ? computeRangeRect(container, range) : void 0;
|
|
2300
2313
|
setRect((prev) => rectsEqual(prev, nextRect) ? prev : nextRect);
|
|
2301
2314
|
const nextPreviewRect = fillPreviewRange && container ? computeRangeRect(container, fillPreviewRange) : void 0;
|
|
2302
2315
|
setPreviewRect((prev) => rectsEqual(prev, nextPreviewRect) ? prev : nextPreviewRect);
|
|
2316
|
+
};
|
|
2317
|
+
useLayoutEffect2(() => {
|
|
2318
|
+
recomputeRef.current();
|
|
2303
2319
|
});
|
|
2320
|
+
useLayoutEffect2(() => {
|
|
2321
|
+
const container = containerRef.current;
|
|
2322
|
+
if (!container) return;
|
|
2323
|
+
function handleScroll() {
|
|
2324
|
+
recomputeRef.current();
|
|
2325
|
+
}
|
|
2326
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
2327
|
+
return () => container.removeEventListener("scroll", handleScroll);
|
|
2328
|
+
}, [containerRef.current]);
|
|
2304
2329
|
if (!rect) return null;
|
|
2305
2330
|
return /* @__PURE__ */ jsxs16(Fragment2, { children: [
|
|
2306
2331
|
/* @__PURE__ */ jsx27(
|
|
@@ -2792,16 +2817,25 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
|
|
|
2792
2817
|
import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
|
|
2793
2818
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2794
2819
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
2795
|
-
import { Fragment as Fragment3, useEffect as
|
|
2820
|
+
import { Fragment as Fragment3, useEffect as useEffect10, useMemo as useMemo8, useRef as useRef12, useState as useState14 } from "react";
|
|
2796
2821
|
|
|
2797
2822
|
// src/cell-editing/renderAlwaysEditCell.tsx
|
|
2798
|
-
import {
|
|
2823
|
+
import {
|
|
2824
|
+
useEffect as useEffect7,
|
|
2825
|
+
useState as useState10
|
|
2826
|
+
} from "react";
|
|
2799
2827
|
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
2800
2828
|
function AlwaysEditCell(props) {
|
|
2801
|
-
const { column, row, rawValue, ctx } = props;
|
|
2829
|
+
const { column, row, rawValue, ctx, atomicGesture } = props;
|
|
2802
2830
|
const rowId = ctx.getRowId(row);
|
|
2803
2831
|
const resolvedValue = ctx.resolveValue(rowId, column.id, rawValue);
|
|
2804
2832
|
const [draft, setDraft] = useState10(void 0);
|
|
2833
|
+
const [enumOpen, setEnumOpen] = useState10(false);
|
|
2834
|
+
const isBuiltinEnum = column.type === "enum" && !column.renderEditCell;
|
|
2835
|
+
const shouldOpenEnumNow = isBuiltinEnum && (atomicGesture?.shouldOpenEnum(rowId, column.id) ?? false);
|
|
2836
|
+
useEffect7(() => {
|
|
2837
|
+
if (shouldOpenEnumNow) setEnumOpen(true);
|
|
2838
|
+
}, [shouldOpenEnumNow]);
|
|
2805
2839
|
if (!isEditable(column, row)) {
|
|
2806
2840
|
return /* @__PURE__ */ jsx32("span", { "data-testid": `cell-${rowId}-${column.id}`, className: "block w-full", children: column.cell ? column.cell(resolvedValue, row) : defaultFormat(column, resolvedValue) });
|
|
2807
2841
|
}
|
|
@@ -2848,7 +2882,52 @@ function AlwaysEditCell(props) {
|
|
|
2848
2882
|
if (validate(draft.value)) setDraft(void 0);
|
|
2849
2883
|
else commit(draft.value);
|
|
2850
2884
|
}
|
|
2851
|
-
|
|
2885
|
+
function suppressNative(event) {
|
|
2886
|
+
event.stopPropagation();
|
|
2887
|
+
event.nativeEvent.stopImmediatePropagation();
|
|
2888
|
+
return true;
|
|
2889
|
+
}
|
|
2890
|
+
function handleModifierCapture(event) {
|
|
2891
|
+
if (!isAtomic || isBuiltinEnum) return false;
|
|
2892
|
+
if (!(event.shiftKey || event.ctrlKey || event.metaKey)) return false;
|
|
2893
|
+
return suppressNative(event);
|
|
2894
|
+
}
|
|
2895
|
+
function handleEnumOpenCapture(event) {
|
|
2896
|
+
if (!isBuiltinEnum || enumOpen) return false;
|
|
2897
|
+
return suppressNative(event);
|
|
2898
|
+
}
|
|
2899
|
+
function handlePointerDownCapture(event) {
|
|
2900
|
+
const suppressed = handleModifierCapture(event) || handleEnumOpenCapture(event);
|
|
2901
|
+
if (suppressed) atomicGesture?.registerSelection(rowId, column.id, event.shiftKey);
|
|
2902
|
+
}
|
|
2903
|
+
function handleClickCapture(event) {
|
|
2904
|
+
handleModifierCapture(event);
|
|
2905
|
+
handleEnumOpenCapture(event);
|
|
2906
|
+
}
|
|
2907
|
+
return /* @__PURE__ */ jsx32(
|
|
2908
|
+
"fieldset",
|
|
2909
|
+
{
|
|
2910
|
+
disabled: ctx.disabled,
|
|
2911
|
+
onKeyDown: handleKeyDown,
|
|
2912
|
+
onBlur: handleBlur,
|
|
2913
|
+
onPointerDownCapture: handlePointerDownCapture,
|
|
2914
|
+
onClickCapture: handleClickCapture,
|
|
2915
|
+
className: "contents",
|
|
2916
|
+
children: column.type === "enum" && !column.renderEditCell ? /* @__PURE__ */ jsx32(
|
|
2917
|
+
EnumEditor,
|
|
2918
|
+
{
|
|
2919
|
+
column,
|
|
2920
|
+
rowId,
|
|
2921
|
+
value: currentValue,
|
|
2922
|
+
onChange,
|
|
2923
|
+
error,
|
|
2924
|
+
autoFocus: false,
|
|
2925
|
+
open: enumOpen,
|
|
2926
|
+
onOpenChange: setEnumOpen
|
|
2927
|
+
}
|
|
2928
|
+
) : column.renderEditCell ? column.renderEditCell(currentValue, row, onChange, error, false) : renderDefaultEditWidget(column, rowId, currentValue, onChange, error, false)
|
|
2929
|
+
}
|
|
2930
|
+
);
|
|
2852
2931
|
}
|
|
2853
2932
|
|
|
2854
2933
|
// src/hooks/useGroupExpansion.ts
|
|
@@ -2877,9 +2956,9 @@ function useGroupExpansion(defaultGroupsExpanded, controlledExpandedGroups, onEx
|
|
|
2877
2956
|
}
|
|
2878
2957
|
|
|
2879
2958
|
// src/hooks/useStickyGroupHeaderTop.ts
|
|
2880
|
-
import { useLayoutEffect as useLayoutEffect3, useRef as
|
|
2959
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef10, useState as useState12 } from "react";
|
|
2881
2960
|
function useStickyGroupHeaderTop(enabled) {
|
|
2882
|
-
const theadRef =
|
|
2961
|
+
const theadRef = useRef10(null);
|
|
2883
2962
|
const [groupHeaderTop, setGroupHeaderTop] = useState12(0);
|
|
2884
2963
|
useLayoutEffect3(() => {
|
|
2885
2964
|
if (!enabled) return;
|
|
@@ -2944,15 +3023,15 @@ function processClientData(data, state) {
|
|
|
2944
3023
|
}
|
|
2945
3024
|
|
|
2946
3025
|
// src/grid/useGridState.ts
|
|
2947
|
-
import { useCallback as useCallback4, useEffect as
|
|
3026
|
+
import { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo7, useState as useState13 } from "react";
|
|
2948
3027
|
|
|
2949
3028
|
// src/hooks/useDebouncedCallback.ts
|
|
2950
|
-
import { useEffect as
|
|
3029
|
+
import { useEffect as useEffect8, useMemo as useMemo6, useRef as useRef11 } from "react";
|
|
2951
3030
|
function useDebouncedCallback(callback, delayMs) {
|
|
2952
|
-
const callbackRef =
|
|
3031
|
+
const callbackRef = useRef11(callback);
|
|
2953
3032
|
callbackRef.current = callback;
|
|
2954
|
-
const timeoutRef =
|
|
2955
|
-
|
|
3033
|
+
const timeoutRef = useRef11(void 0);
|
|
3034
|
+
useEffect8(() => {
|
|
2956
3035
|
return () => {
|
|
2957
3036
|
clearTimeout(timeoutRef.current);
|
|
2958
3037
|
};
|
|
@@ -2981,10 +3060,12 @@ function nextSortDir(current, descFirst) {
|
|
|
2981
3060
|
if (current === first) return second;
|
|
2982
3061
|
return void 0;
|
|
2983
3062
|
}
|
|
2984
|
-
function useGridState(dataSource, initialState, externalState) {
|
|
2985
|
-
const [state, setState] = useState13(
|
|
2986
|
-
()
|
|
2987
|
-
|
|
3063
|
+
function useGridState(dataSource, initialState, externalState, showPagination = true) {
|
|
3064
|
+
const [state, setState] = useState13(() => {
|
|
3065
|
+
if (externalState) return externalState;
|
|
3066
|
+
const pageSize = initialState?.pageSize ?? (showPagination ? DEFAULT_STATE.pageSize : Number.MAX_SAFE_INTEGER);
|
|
3067
|
+
return { ...DEFAULT_STATE, ...initialState, pageSize };
|
|
3068
|
+
});
|
|
2988
3069
|
const notifyRaw = useCallback4(
|
|
2989
3070
|
(next) => {
|
|
2990
3071
|
if (dataSource.mode === "server") dataSource.onStateChange(next);
|
|
@@ -3002,7 +3083,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
3002
3083
|
},
|
|
3003
3084
|
[notifyRaw, cancelDebouncedNotify]
|
|
3004
3085
|
);
|
|
3005
|
-
|
|
3086
|
+
useEffect9(() => {
|
|
3006
3087
|
if (!externalState) return;
|
|
3007
3088
|
cancelDebouncedNotify();
|
|
3008
3089
|
setState(externalState);
|
|
@@ -3107,7 +3188,7 @@ function computeHeaderRuns(columns) {
|
|
|
3107
3188
|
}
|
|
3108
3189
|
return runs;
|
|
3109
3190
|
}
|
|
3110
|
-
function toTanstackColumns(columns, editingCtxRef, cellEditingCtxRef) {
|
|
3191
|
+
function toTanstackColumns(columns, editingCtxRef, cellEditingCtxRef, atomicGestureRef) {
|
|
3111
3192
|
return columns.map((column) => ({
|
|
3112
3193
|
id: column.id,
|
|
3113
3194
|
header: column.header,
|
|
@@ -3116,7 +3197,16 @@ function toTanstackColumns(columns, editingCtxRef, cellEditingCtxRef) {
|
|
|
3116
3197
|
cell: (info) => {
|
|
3117
3198
|
const cellEditingCtx = cellEditingCtxRef.current;
|
|
3118
3199
|
if (!cellEditingCtx) return renderEditableCell(column, info.row.original, info.getValue(), editingCtxRef.current);
|
|
3119
|
-
return cellEditingCtx.alwaysEdit ? /* @__PURE__ */ jsx33(
|
|
3200
|
+
return cellEditingCtx.alwaysEdit ? /* @__PURE__ */ jsx33(
|
|
3201
|
+
AlwaysEditCell,
|
|
3202
|
+
{
|
|
3203
|
+
column,
|
|
3204
|
+
row: info.row.original,
|
|
3205
|
+
rawValue: info.getValue(),
|
|
3206
|
+
ctx: cellEditingCtx,
|
|
3207
|
+
atomicGesture: atomicGestureRef.current
|
|
3208
|
+
}
|
|
3209
|
+
) : renderCellModeCell(column, info.row.original, info.getValue(), cellEditingCtx);
|
|
3120
3210
|
}
|
|
3121
3211
|
}));
|
|
3122
3212
|
}
|
|
@@ -3156,7 +3246,8 @@ function DataGrid({
|
|
|
3156
3246
|
const { state, filtersByColumn, setColumnFilter, toggleSort, setPage } = useGridState(
|
|
3157
3247
|
dataSource,
|
|
3158
3248
|
initialState,
|
|
3159
|
-
gridState
|
|
3249
|
+
gridState,
|
|
3250
|
+
showPagination
|
|
3160
3251
|
);
|
|
3161
3252
|
const [internalSelectedIds, setInternalSelectedIds] = useState14(/* @__PURE__ */ new Set());
|
|
3162
3253
|
const selectedIds = controlledSelectedIds ?? internalSelectedIds;
|
|
@@ -3192,6 +3283,7 @@ function DataGrid({
|
|
|
3192
3283
|
hasCellEditing ? cellEditing : void 0,
|
|
3193
3284
|
getRowId
|
|
3194
3285
|
);
|
|
3286
|
+
const atomicGestureRef = useRef12(void 0);
|
|
3195
3287
|
const visibleColumns = useVisibleColumns(columns, columnVisibility);
|
|
3196
3288
|
const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
|
|
3197
3289
|
const { rows, rowCount } = useMemo8(() => {
|
|
@@ -3218,7 +3310,7 @@ function DataGrid({
|
|
|
3218
3310
|
updateSelectedIds(next);
|
|
3219
3311
|
}
|
|
3220
3312
|
const tanstackColumns = useMemo8(
|
|
3221
|
-
() => toTanstackColumns(visibleColumns, editingCtxRef, cellEditingCtxRef),
|
|
3313
|
+
() => toTanstackColumns(visibleColumns, editingCtxRef, cellEditingCtxRef, atomicGestureRef),
|
|
3222
3314
|
[visibleColumns]
|
|
3223
3315
|
);
|
|
3224
3316
|
const columnById = useMemo8(() => {
|
|
@@ -3345,6 +3437,18 @@ function DataGrid({
|
|
|
3345
3437
|
return map;
|
|
3346
3438
|
}, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
|
|
3347
3439
|
const tableRows = table.getRowModel().rows;
|
|
3440
|
+
const truncationWarnedRef = useRef12(false);
|
|
3441
|
+
useEffect10(() => {
|
|
3442
|
+
if (process.env.NODE_ENV === "production") return;
|
|
3443
|
+
if (showPagination) return;
|
|
3444
|
+
if (truncationWarnedRef.current) return;
|
|
3445
|
+
if (!gridState && initialState?.pageSize !== void 0) return;
|
|
3446
|
+
if (tableRows.length >= rowCount) return;
|
|
3447
|
+
truncationWarnedRef.current = true;
|
|
3448
|
+
console.warn(
|
|
3449
|
+
`[DataGrid] showPagination={false} but only ${tableRows.length} of ${rowCount} row(s) are rendered, with no pagination UI to reach the rest. Pass an explicit pageSize (via initialState or gridState) that covers every row you want visible, or a dataSource that returns all of them.`
|
|
3450
|
+
);
|
|
3451
|
+
}, [showPagination, gridState, initialState?.pageSize, tableRows.length, rowCount]);
|
|
3348
3452
|
const groupedBuckets = useMemo8(
|
|
3349
3453
|
() => groupBy ? groupRows(tableRows, (row) => groupBy(row.original)) : void 0,
|
|
3350
3454
|
[tableRows, groupBy]
|
|
@@ -3364,7 +3468,7 @@ function DataGrid({
|
|
|
3364
3468
|
}
|
|
3365
3469
|
return items;
|
|
3366
3470
|
}, [shouldVirtualize, groupedBuckets, tableRows, isGroupExpanded]);
|
|
3367
|
-
const scrollRef =
|
|
3471
|
+
const scrollRef = useRef12(null);
|
|
3368
3472
|
const virtualizer = useVirtualizer({
|
|
3369
3473
|
count: flatItems.length,
|
|
3370
3474
|
getScrollElement: () => scrollRef.current,
|
|
@@ -3376,8 +3480,11 @@ function DataGrid({
|
|
|
3376
3480
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
3377
3481
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
3378
3482
|
const lastVisibleIndex = virtualItems.length > 0 ? virtualItems[virtualItems.length - 1].index : -1;
|
|
3379
|
-
const notifiedForLengthRef =
|
|
3380
|
-
|
|
3483
|
+
const notifiedForLengthRef = useRef12(-1);
|
|
3484
|
+
useEffect10(() => {
|
|
3485
|
+
notifiedForLengthRef.current = -1;
|
|
3486
|
+
}, [state.filter, state.sort]);
|
|
3487
|
+
useEffect10(() => {
|
|
3381
3488
|
if (!virtualize?.onEndReached) return;
|
|
3382
3489
|
if (lastVisibleIndex < 0 || lastVisibleIndex < flatItems.length - 1) return;
|
|
3383
3490
|
if (virtualize.hasMore === false) return;
|
|
@@ -3403,8 +3510,23 @@ function DataGrid({
|
|
|
3403
3510
|
if (index !== void 0) virtualizer.scrollToIndex(index);
|
|
3404
3511
|
}
|
|
3405
3512
|
});
|
|
3406
|
-
const clickCellRef =
|
|
3407
|
-
const dragMovedRef =
|
|
3513
|
+
const clickCellRef = useRef12(null);
|
|
3514
|
+
const dragMovedRef = useRef12(false);
|
|
3515
|
+
const [pendingOpenEnumCell, setPendingOpenEnumCell] = useState14(void 0);
|
|
3516
|
+
atomicGestureRef.current = {
|
|
3517
|
+
shouldOpenEnum: (rowId, columnId) => pendingOpenEnumCell?.rowId === rowId && pendingOpenEnumCell?.columnId === columnId,
|
|
3518
|
+
// Mirrors exactly what `handleCellMouseDown` below does for every other
|
|
3519
|
+
// cell, minus the click-to-edit-only tail end (irrelevant here — always
|
|
3520
|
+
// invoked under `alwaysEdit`, same as that function's own early return
|
|
3521
|
+
// for it) — see `AtomicGestureContext.registerSelection`'s own doc for
|
|
3522
|
+
// why `AlwaysEditCell` can't just rely on that function running on its
|
|
3523
|
+
// own for a gesture it suppresses.
|
|
3524
|
+
registerSelection: (rowId, columnId, extend) => {
|
|
3525
|
+
cellSelection.startSelection({ rowId, columnId }, { extend });
|
|
3526
|
+
clickCellRef.current = { rowId, columnId, extend, wasEditing: false };
|
|
3527
|
+
dragMovedRef.current = false;
|
|
3528
|
+
}
|
|
3529
|
+
};
|
|
3408
3530
|
function beginEditFromClick(cell) {
|
|
3409
3531
|
if (!cellEditingCtx) return;
|
|
3410
3532
|
if (cellEditingCtx.editingCell?.rowId === cell.rowId && cellEditingCtx.editingCell.columnId === cell.columnId) return;
|
|
@@ -3413,9 +3535,9 @@ function DataGrid({
|
|
|
3413
3535
|
if (!column || row === void 0 || !isEditable(column, row)) return;
|
|
3414
3536
|
cellEditingCtx.onBeginEdit(cell);
|
|
3415
3537
|
}
|
|
3416
|
-
const pendingDragCellRef =
|
|
3417
|
-
const dragRafRef =
|
|
3418
|
-
|
|
3538
|
+
const pendingDragCellRef = useRef12(null);
|
|
3539
|
+
const dragRafRef = useRef12(null);
|
|
3540
|
+
useEffect10(() => {
|
|
3419
3541
|
if (!cellSelection.isDragging) return;
|
|
3420
3542
|
function handleMouseMove(event) {
|
|
3421
3543
|
const cellEl = event.target?.closest("[data-cell-row]");
|
|
@@ -3435,7 +3557,15 @@ function DataGrid({
|
|
|
3435
3557
|
cellSelection.endDrag();
|
|
3436
3558
|
const clickCell = clickCellRef.current;
|
|
3437
3559
|
clickCellRef.current = null;
|
|
3438
|
-
if (clickCell
|
|
3560
|
+
if (!clickCell || clickCell.extend || clickCell.wasEditing || dragMovedRef.current) return;
|
|
3561
|
+
if (cellEditingCtx?.alwaysEdit) {
|
|
3562
|
+
const column = columnById.get(clickCell.columnId);
|
|
3563
|
+
if (column?.type === "enum" && !column.renderEditCell) {
|
|
3564
|
+
setPendingOpenEnumCell({ rowId: clickCell.rowId, columnId: clickCell.columnId });
|
|
3565
|
+
}
|
|
3566
|
+
return;
|
|
3567
|
+
}
|
|
3568
|
+
beginEditFromClick(clickCell);
|
|
3439
3569
|
}
|
|
3440
3570
|
window.addEventListener("mousemove", handleMouseMove);
|
|
3441
3571
|
window.addEventListener("mouseup", handleMouseUp);
|
|
@@ -3446,9 +3576,9 @@ function DataGrid({
|
|
|
3446
3576
|
dragRafRef.current = null;
|
|
3447
3577
|
};
|
|
3448
3578
|
}, [cellSelection.isDragging, cellSelection.updateDrag, cellSelection.endDrag]);
|
|
3449
|
-
const pendingFillCellRef =
|
|
3450
|
-
const fillRafRef =
|
|
3451
|
-
|
|
3579
|
+
const pendingFillCellRef = useRef12(null);
|
|
3580
|
+
const fillRafRef = useRef12(null);
|
|
3581
|
+
useEffect10(() => {
|
|
3452
3582
|
if (!cellSelection.isFillDragging) return;
|
|
3453
3583
|
function handleMouseMove(event) {
|
|
3454
3584
|
const cellEl = event.target?.closest("[data-cell-row]");
|
|
@@ -3484,8 +3614,8 @@ function DataGrid({
|
|
|
3484
3614
|
fillRafRef.current = null;
|
|
3485
3615
|
};
|
|
3486
3616
|
}, [cellSelection.isFillDragging, cellSelection.updateFillDrag, cellSelection.endFillDrag]);
|
|
3487
|
-
const wasEditingCellRef =
|
|
3488
|
-
|
|
3617
|
+
const wasEditingCellRef = useRef12(void 0);
|
|
3618
|
+
useEffect10(() => {
|
|
3489
3619
|
const wasEditing = wasEditingCellRef.current !== void 0;
|
|
3490
3620
|
wasEditingCellRef.current = cellEditingCtx?.editingCell;
|
|
3491
3621
|
if (!wasEditing || cellEditingCtx?.editingCell) return;
|
|
@@ -3501,10 +3631,10 @@ function DataGrid({
|
|
|
3501
3631
|
const columnId = cellEl?.dataset.cellCol;
|
|
3502
3632
|
if (rowId === void 0 || columnId === void 0) return;
|
|
3503
3633
|
cellSelection.startSelection({ rowId, columnId }, { extend: event.shiftKey });
|
|
3504
|
-
if (cellEditingCtx?.alwaysEdit) return;
|
|
3505
3634
|
const wasEditing = cellEditingCtx?.editingCell?.rowId === rowId && cellEditingCtx.editingCell.columnId === columnId;
|
|
3506
3635
|
clickCellRef.current = { rowId, columnId, extend: event.shiftKey, wasEditing };
|
|
3507
3636
|
dragMovedRef.current = false;
|
|
3637
|
+
if (cellEditingCtx?.alwaysEdit) return;
|
|
3508
3638
|
if (wasEditing) return;
|
|
3509
3639
|
scrollRef.current?.focus();
|
|
3510
3640
|
}
|
|
@@ -4024,7 +4154,7 @@ function DataGrid({
|
|
|
4024
4154
|
// src/tree/TreeDataGrid.tsx
|
|
4025
4155
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
4026
4156
|
import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
|
|
4027
|
-
import { Fragment as Fragment5, useEffect as
|
|
4157
|
+
import { Fragment as Fragment5, useEffect as useEffect11, useMemo as useMemo10, useRef as useRef13 } from "react";
|
|
4028
4158
|
|
|
4029
4159
|
// src/tree/flattenTree.ts
|
|
4030
4160
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -4275,8 +4405,8 @@ function TreeDataGrid({
|
|
|
4275
4405
|
childrenMap: controlledChildrenMap,
|
|
4276
4406
|
onChildrenMapChange
|
|
4277
4407
|
});
|
|
4278
|
-
const didAutoExpand =
|
|
4279
|
-
|
|
4408
|
+
const didAutoExpand = useRef13(false);
|
|
4409
|
+
useEffect11(() => {
|
|
4280
4410
|
if (didAutoExpand.current) return;
|
|
4281
4411
|
didAutoExpand.current = true;
|
|
4282
4412
|
if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
|
|
@@ -4351,7 +4481,7 @@ function TreeDataGrid({
|
|
|
4351
4481
|
for (const column of visibleColumns) map.set(column.id, `p-2 ${alignClassName(column)}`);
|
|
4352
4482
|
return map;
|
|
4353
4483
|
}, [visibleColumns]);
|
|
4354
|
-
const scrollRef =
|
|
4484
|
+
const scrollRef = useRef13(null);
|
|
4355
4485
|
const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
|
|
4356
4486
|
const virtualizer = useVirtualizer2({
|
|
4357
4487
|
count: flatRows.length,
|