@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 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>>): ReactElement;
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
- * `<DataGrid>` itself never conditions any other behavior on this, it just
1425
- * stops rendering that one footer.
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(Select, { value: value === null || value === void 0 ? "" : String(value), onValueChange: onChange, children: [
1485
- /* @__PURE__ */ jsx18(
1486
- SelectTrigger,
1487
- {
1488
- className: "h-8",
1489
- "aria-label": `Edit ${column.header}`,
1490
- "aria-invalid": error ? true : void 0,
1491
- "aria-describedby": error ? errorId : void 0,
1492
- "data-testid": `edit-${rowId}-${column.id}`,
1493
- autoFocus,
1494
- children: /* @__PURE__ */ jsx18(SelectValue, {})
1495
- }
1496
- ),
1497
- /* @__PURE__ */ jsx18(SelectContent, { children: column.options.map((option) => /* @__PURE__ */ jsx18(SelectItem, { value: option.value, children: option.label }, option.value)) })
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
- useLayoutEffect2(() => {
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 useEffect9, useMemo as useMemo8, useRef as useRef11, useState as useState14 } from "react";
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 { useState as useState10 } from "react";
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
- return /* @__PURE__ */ jsx32("fieldset", { disabled: ctx.disabled, onKeyDown: handleKeyDown, onBlur: handleBlur, className: "contents", children: column.renderEditCell ? column.renderEditCell(currentValue, row, onChange, error, false) : renderDefaultEditWidget(column, rowId, currentValue, onChange, error, false) });
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 useRef9, useState as useState12 } from "react";
2959
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef10, useState as useState12 } from "react";
2881
2960
  function useStickyGroupHeaderTop(enabled) {
2882
- const theadRef = useRef9(null);
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 useEffect8, useMemo as useMemo7, useState as useState13 } from "react";
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 useEffect7, useMemo as useMemo6, useRef as useRef10 } from "react";
3029
+ import { useEffect as useEffect8, useMemo as useMemo6, useRef as useRef11 } from "react";
2951
3030
  function useDebouncedCallback(callback, delayMs) {
2952
- const callbackRef = useRef10(callback);
3031
+ const callbackRef = useRef11(callback);
2953
3032
  callbackRef.current = callback;
2954
- const timeoutRef = useRef10(void 0);
2955
- useEffect7(() => {
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
- () => externalState ?? { ...DEFAULT_STATE, ...initialState }
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
- useEffect8(() => {
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(AlwaysEditCell, { column, row: info.row.original, rawValue: info.getValue(), ctx: cellEditingCtx }) : renderCellModeCell(column, info.row.original, info.getValue(), cellEditingCtx);
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 = useRef11(null);
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 = useRef11(-1);
3380
- useEffect9(() => {
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 = useRef11(null);
3407
- const dragMovedRef = useRef11(false);
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 = useRef11(null);
3417
- const dragRafRef = useRef11(null);
3418
- useEffect9(() => {
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 && !clickCell.extend && !clickCell.wasEditing && !dragMovedRef.current) beginEditFromClick(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 = useRef11(null);
3450
- const fillRafRef = useRef11(null);
3451
- useEffect9(() => {
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 = useRef11(void 0);
3488
- useEffect9(() => {
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 useEffect10, useMemo as useMemo10, useRef as useRef12 } from "react";
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 = useRef12(false);
4279
- useEffect10(() => {
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 = useRef12(null);
4484
+ const scrollRef = useRef13(null);
4355
4485
  const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
4356
4486
  const virtualizer = useVirtualizer2({
4357
4487
  count: flatRows.length,