@bmsuisse/datagrid 0.36.0 → 0.37.1

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.js CHANGED
@@ -204,12 +204,13 @@ import { forwardRef as forwardRef2 } from "react";
204
204
  import { jsx as jsx2 } from "react/jsx-runtime";
205
205
  var Popover = PopoverPrimitive.Root;
206
206
  var PopoverTrigger = PopoverPrimitive.Trigger;
207
- var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx2(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx2(
207
+ var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, collisionPadding = 8, ...props }, ref) => /* @__PURE__ */ jsx2(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx2(
208
208
  PopoverPrimitive.Content,
209
209
  {
210
210
  ref,
211
211
  align,
212
212
  sideOffset,
213
+ collisionPadding,
213
214
  className: cn(
214
215
  "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
215
216
  className
@@ -358,10 +359,91 @@ import { CalendarDaysIcon } from "@heroicons/react/24/outline";
358
359
  import { endOfDay, endOfMonth, format, parseISO as parseISO2, startOfDay, startOfMonth, subDays } from "date-fns";
359
360
 
360
361
  // src/components/ui/calendar.tsx
361
- import { DayPicker } from "react-day-picker";
362
+ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from "lucide-react";
363
+ import { useEffect, useRef } from "react";
364
+ import { DayPicker, getDefaultClassNames } from "react-day-picker";
362
365
  import { jsx as jsx5 } from "react/jsx-runtime";
363
- function Calendar({ className, ...props }) {
364
- return /* @__PURE__ */ jsx5(DayPicker, { className: cn("p-3", className), ...props });
366
+ function Calendar({ className, classNames, ...props }) {
367
+ const defaultClassNames = getDefaultClassNames();
368
+ return /* @__PURE__ */ jsx5(
369
+ DayPicker,
370
+ {
371
+ className: cn("w-fit", className),
372
+ classNames: {
373
+ root: cn("relative", defaultClassNames.root),
374
+ months: cn(
375
+ "flex flex-col gap-4 sm:flex-row sm:divide-x sm:divide-border",
376
+ defaultClassNames.months
377
+ ),
378
+ month: cn("flex flex-col gap-3", defaultClassNames.month),
379
+ month_caption: cn("flex items-center justify-center px-8 h-8", defaultClassNames.month_caption),
380
+ caption_label: cn("text-sm font-medium", defaultClassNames.caption_label),
381
+ nav: cn("flex items-center justify-between absolute inset-x-0 top-0 px-1", defaultClassNames.nav),
382
+ button_previous: cn(
383
+ buttonVariants({ variant: "outline", size: "icon" }),
384
+ "h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground",
385
+ defaultClassNames.button_previous
386
+ ),
387
+ button_next: cn(
388
+ buttonVariants({ variant: "outline", size: "icon" }),
389
+ "h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground",
390
+ defaultClassNames.button_next
391
+ ),
392
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
393
+ weekdays: cn("flex", defaultClassNames.weekdays),
394
+ weekday: cn(
395
+ "w-8 text-center text-[0.7rem] font-normal text-muted-foreground",
396
+ defaultClassNames.weekday
397
+ ),
398
+ week: cn("flex w-full mt-1", defaultClassNames.week),
399
+ day: cn(
400
+ "relative w-8 h-8 p-0 text-center text-sm focus-within:relative focus-within:z-20",
401
+ "[&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
402
+ defaultClassNames.day
403
+ ),
404
+ range_start: cn("rounded-l-md bg-accent", defaultClassNames.range_start),
405
+ range_middle: cn("rounded-none bg-accent/60", defaultClassNames.range_middle),
406
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
407
+ today: cn(
408
+ "[&:not([data-selected])]:text-primary [&:not([data-selected])]:font-semibold",
409
+ defaultClassNames.today
410
+ ),
411
+ outside: cn("text-muted-foreground/50", defaultClassNames.outside),
412
+ disabled: cn("text-muted-foreground/30 line-through", defaultClassNames.disabled),
413
+ hidden: cn("invisible", defaultClassNames.hidden),
414
+ ...classNames
415
+ },
416
+ components: {
417
+ Chevron: ({ className: chevronClassName, orientation }) => {
418
+ const Icon2 = orientation === "up" ? ChevronUpIcon : orientation === "down" ? ChevronDownIcon : orientation === "right" ? ChevronRightIcon : ChevronLeftIcon;
419
+ return /* @__PURE__ */ jsx5(Icon2, { className: cn("h-4 w-4", chevronClassName), "aria-hidden": true });
420
+ },
421
+ DayButton: ({ className: dayClassName, day: _day, modifiers, ...dayProps }) => {
422
+ const ref = useRef(null);
423
+ useEffect(() => {
424
+ if (modifiers.focused) ref.current?.focus();
425
+ }, [modifiers.focused]);
426
+ return /* @__PURE__ */ jsx5(
427
+ "button",
428
+ {
429
+ ref,
430
+ type: "button",
431
+ className: cn(
432
+ "h-8 w-8 rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground",
433
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
434
+ "data-[selected=true]:bg-primary data-[selected=true]:text-primary-foreground data-[selected=true]:hover:bg-primary data-[selected=true]:hover:text-primary-foreground",
435
+ modifiers.range_middle && "data-[selected=true]:bg-transparent data-[selected=true]:text-foreground data-[selected=true]:hover:bg-accent",
436
+ dayClassName
437
+ ),
438
+ "data-selected": modifiers.selected || void 0,
439
+ ...dayProps
440
+ }
441
+ );
442
+ }
443
+ },
444
+ ...props
445
+ }
446
+ );
365
447
  }
366
448
 
367
449
  // src/filter/DateRangeFilter.tsx
@@ -436,7 +518,7 @@ function DateRangeFilter({
436
518
  )),
437
519
  /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", size: "sm", onClick: () => emit(void 0), children: "Custom" })
438
520
  ] }),
439
- /* @__PURE__ */ jsx6(Calendar, { mode: "range", selected: range, onSelect: emit, numberOfMonths: 1 })
521
+ /* @__PURE__ */ jsx6(Calendar, { mode: "range", selected: range, onSelect: emit, numberOfMonths: 2 })
440
522
  ] });
441
523
  if (bare) {
442
524
  return /* @__PURE__ */ jsx6("div", { "data-testid": `filter-${column.id}`, children: panel });
@@ -678,7 +760,7 @@ function EnumFilter({
678
760
 
679
761
  // src/filter/NumberComparisonFilter.tsx
680
762
  import { FunnelIcon as FunnelIcon3 } from "@heroicons/react/24/outline";
681
- import { useEffect, useId, useRef, useState as useState2 } from "react";
763
+ import { useEffect as useEffect2, useId, useRef as useRef2, useState as useState2 } from "react";
682
764
 
683
765
  // src/column/format.ts
684
766
  import { parseISO as parseISO3 } from "date-fns";
@@ -865,8 +947,8 @@ function NumberComparisonFilter({
865
947
  const [text2, setText2] = useState2(initial.text2);
866
948
  const operatorId = useId();
867
949
  const valueId = useId();
868
- const lastEmittedRef = useRef(value);
869
- useEffect(() => {
950
+ const lastEmittedRef = useRef2(value);
951
+ useEffect2(() => {
870
952
  if (value === lastEmittedRef.current) return;
871
953
  lastEmittedRef.current = value;
872
954
  const next = stateFromValue(value);
@@ -982,7 +1064,7 @@ function NumberComparisonFilter({
982
1064
 
983
1065
  // src/filter/NumberRangeFilter.tsx
984
1066
  import { FunnelIcon as FunnelIcon4 } from "@heroicons/react/24/outline";
985
- import { useEffect as useEffect2, useId as useId2, useRef as useRef2, useState as useState3 } from "react";
1067
+ import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
986
1068
  import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
987
1069
  function parseNumber2(raw) {
988
1070
  if (raw.trim() === "") return void 0;
@@ -1000,8 +1082,8 @@ function NumberRangeFilter({
1000
1082
  const [maxText, setMaxText] = useState3(initial.max?.toString() ?? "");
1001
1083
  const minId = useId2();
1002
1084
  const maxId = useId2();
1003
- const lastEmittedRef = useRef2(value);
1004
- useEffect2(() => {
1085
+ const lastEmittedRef = useRef3(value);
1086
+ useEffect3(() => {
1005
1087
  if (value === lastEmittedRef.current) return;
1006
1088
  lastEmittedRef.current = value;
1007
1089
  const next = rangeOf2(value);
@@ -1082,7 +1164,7 @@ function NumberRangeFilter({
1082
1164
 
1083
1165
  // src/filter/NumberHistogramFilter.tsx
1084
1166
  import { FunnelIcon as FunnelIcon5 } from "@heroicons/react/24/outline";
1085
- import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState4 } from "react";
1167
+ import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
1086
1168
  import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1087
1169
  var BAR_HEIGHT_PX = 56;
1088
1170
  var DEFAULT_BUCKETS = 24;
@@ -1104,12 +1186,12 @@ function NumberHistogramFilter({
1104
1186
  }) {
1105
1187
  const [openState, setOpen] = useState4(false);
1106
1188
  const open = bare || openState;
1107
- const trackRef = useRef3(null);
1189
+ const trackRef = useRef4(null);
1108
1190
  const [minOnTop, setMinOnTop] = useState4(false);
1109
1191
  const [loadedValues, setLoadedValues] = useState4([]);
1110
1192
  const [loading, setLoading] = useState4(false);
1111
1193
  const { min, max } = rangeOf2(value);
1112
- useEffect3(() => {
1194
+ useEffect4(() => {
1113
1195
  if (!open || !loadValues) return;
1114
1196
  let cancelled = false;
1115
1197
  setLoading(true);
@@ -1133,7 +1215,7 @@ function NumberHistogramFilter({
1133
1215
  const activeMax = max ?? dataMax;
1134
1216
  const [minText, setMinText] = useState4("");
1135
1217
  const [maxText, setMaxText] = useState4("");
1136
- useEffect3(() => {
1218
+ useEffect4(() => {
1137
1219
  if (!open) return;
1138
1220
  setMinText(Number.isFinite(activeMin) ? String(Math.round(activeMin)) : "");
1139
1221
  setMaxText(Number.isFinite(activeMax) ? String(Math.round(activeMax)) : "");
@@ -1346,7 +1428,7 @@ function facetedNumberValues(data, column, filter) {
1346
1428
 
1347
1429
  // src/filter/StringFilter.tsx
1348
1430
  import { FunnelIcon as FunnelIcon6 } from "@heroicons/react/24/outline";
1349
- import { useEffect as useEffect4, useId as useId3, useState as useState5 } from "react";
1431
+ import { useEffect as useEffect5, useId as useId3, useState as useState5 } from "react";
1350
1432
  import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1351
1433
  var STRING_OPERATORS = [
1352
1434
  { value: "contains", label: "Contains" },
@@ -1365,7 +1447,7 @@ function StringFilter({
1365
1447
  const text = typeof value?.value === "string" ? value.value : "";
1366
1448
  const inputId = useId3();
1367
1449
  const isFiltered = text !== "";
1368
- useEffect4(() => {
1450
+ useEffect5(() => {
1369
1451
  setOperator(value?.operator ?? DEFAULT_OPERATOR2);
1370
1452
  }, [value?.operator]);
1371
1453
  function emit(nextOperator, nextText) {
@@ -1580,7 +1662,7 @@ function EnumEditor({
1580
1662
  }
1581
1663
 
1582
1664
  // src/edit/MultilineStringEditor.tsx
1583
- import { useLayoutEffect, useRef as useRef4 } from "react";
1665
+ import { useLayoutEffect, useRef as useRef5 } from "react";
1584
1666
 
1585
1667
  // src/components/ui/textarea.tsx
1586
1668
  import { forwardRef as forwardRef6 } from "react";
@@ -1611,8 +1693,8 @@ function MultilineStringEditor({
1611
1693
  autoFocus
1612
1694
  }) {
1613
1695
  const errorId = editErrorId(rowId, column.id);
1614
- const textareaRef = useRef4(null);
1615
- const selectionRef = useRef4(null);
1696
+ const textareaRef = useRef5(null);
1697
+ const selectionRef = useRef5(null);
1616
1698
  const text = value === null || value === void 0 ? "" : String(value);
1617
1699
  useLayoutEffect(() => {
1618
1700
  const el = textareaRef.current;
@@ -1647,7 +1729,7 @@ function MultilineStringEditor({
1647
1729
  }
1648
1730
 
1649
1731
  // src/edit/NumberEditor.tsx
1650
- import { useEffect as useEffect5, useRef as useRef5, useState as useState6 } from "react";
1732
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
1651
1733
  import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1652
1734
  function textFromValue(value) {
1653
1735
  return value === null || value === void 0 ? "" : String(value);
@@ -1662,8 +1744,8 @@ function NumberEditor({
1662
1744
  }) {
1663
1745
  const errorId = editErrorId(rowId, column.id);
1664
1746
  const [text, setText] = useState6(() => textFromValue(value));
1665
- const lastEmittedRef = useRef5(value);
1666
- useEffect5(() => {
1747
+ const lastEmittedRef = useRef6(value);
1748
+ useEffect6(() => {
1667
1749
  if (value === lastEmittedRef.current) return;
1668
1750
  lastEmittedRef.current = value;
1669
1751
  setText(textFromValue(value));
@@ -1741,7 +1823,7 @@ function renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocu
1741
1823
  }
1742
1824
 
1743
1825
  // src/edit/editingState.ts
1744
- import { useEffect as useEffect6, useRef as useRef6, useState as useState7 } from "react";
1826
+ import { useEffect as useEffect7, useRef as useRef7, useState as useState7 } from "react";
1745
1827
  function editValuesEqual(a, b) {
1746
1828
  if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
1747
1829
  return a === b;
@@ -1756,7 +1838,7 @@ function useEditingState(editing, getRowId) {
1756
1838
  setActiveRowId(rowId);
1757
1839
  setAutoFocusTarget({ rowId, columnId });
1758
1840
  }
1759
- useEffect6(() => {
1841
+ useEffect7(() => {
1760
1842
  if (autoFocusTarget) setAutoFocusTarget(null);
1761
1843
  }, [autoFocusTarget]);
1762
1844
  function commitEdit(column, row, value) {
@@ -1843,7 +1925,7 @@ function useEditingState(editing, getRowId) {
1843
1925
  editing?.onDiscard?.();
1844
1926
  }
1845
1927
  const ctx = editing ? { pendingEdits, editErrors, activeRowId, autoFocusTarget, getRowId, onEdit: commitEdit, onActivateRow: activateRow } : void 0;
1846
- const ctxRef = useRef6(void 0);
1928
+ const ctxRef = useRef7(void 0);
1847
1929
  ctxRef.current = ctx;
1848
1930
  return { pendingEdits, editErrors, hasEditErrors, ctx, ctxRef, handleSaveEdits, handleDiscardEdits };
1849
1931
  }
@@ -2049,13 +2131,13 @@ function extendRangeForFillToCellRange(base, target, rowIds, columnIds, rowIndex
2049
2131
  }
2050
2132
 
2051
2133
  // src/cell-editing/useCellSelection.ts
2052
- import { useCallback as useCallback2, useMemo as useMemo3, useRef as useRef7, useState as useState8 } from "react";
2134
+ import { useCallback as useCallback2, useMemo as useMemo3, useRef as useRef8, useState as useState8 } from "react";
2053
2135
  function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
2054
2136
  const [selection, setSelectionState] = useState8(void 0);
2055
2137
  const [isDragging, setIsDragging] = useState8(false);
2056
2138
  const [dragFocus, setDragFocus] = useState8(void 0);
2057
- const draggingRef = useRef7(false);
2058
- const dragFocusRef = useRef7(void 0);
2139
+ const draggingRef = useRef8(false);
2140
+ const dragFocusRef = useRef8(void 0);
2059
2141
  const rowIndex = useMemo3(() => buildIndexMap(rowIds), [rowIds]);
2060
2142
  const columnIndex = useMemo3(() => buildIndexMap(columnIds), [columnIds]);
2061
2143
  const startSelection = useCallback2((cell, options) => {
@@ -2118,9 +2200,9 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
2118
2200
  }, [selection, isDragging, dragFocus]);
2119
2201
  const [isFillDragging, setIsFillDragging] = useState8(false);
2120
2202
  const [fillTarget, setFillTarget] = useState8(void 0);
2121
- const fillDraggingRef = useRef7(false);
2122
- const fillTargetRef = useRef7(void 0);
2123
- const fillBaseRef = useRef7(void 0);
2203
+ const fillDraggingRef = useRef8(false);
2204
+ const fillTargetRef = useRef8(void 0);
2205
+ const fillBaseRef = useRef8(void 0);
2124
2206
  const startFillDrag = useCallback2(() => {
2125
2207
  if (!selection) return;
2126
2208
  fillBaseRef.current = selection;
@@ -2170,7 +2252,7 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
2170
2252
  }
2171
2253
 
2172
2254
  // src/cell-editing/useCellEditingState.ts
2173
- import { useRef as useRef8, useState as useState9 } from "react";
2255
+ import { useRef as useRef9, useState as useState9 } from "react";
2174
2256
  function cellKey(rowId, columnId) {
2175
2257
  return `${rowId}:${columnId}`;
2176
2258
  }
@@ -2181,7 +2263,7 @@ function useCellEditingState(cellEditing, getRowId) {
2181
2263
  const [draftValue, setDraftValue] = useState9(void 0);
2182
2264
  const [overrides, setOverrides] = useState9(/* @__PURE__ */ new Map());
2183
2265
  const [errors, setErrors] = useState9(/* @__PURE__ */ new Map());
2184
- const justCommittedRef = useRef8(false);
2266
+ const justCommittedRef = useRef9(false);
2185
2267
  function closeEditor() {
2186
2268
  setEditingCell(void 0);
2187
2269
  setInitialText(void 0);
@@ -2279,7 +2361,7 @@ function useCellEditingState(cellEditing, getRowId) {
2279
2361
  applyChange: (change) => applyChanges([change]),
2280
2362
  consumeJustCommitted
2281
2363
  } : void 0;
2282
- const ctxRef = useRef8(void 0);
2364
+ const ctxRef = useRef9(void 0);
2283
2365
  ctxRef.current = ctx;
2284
2366
  return { ctx, ctxRef, applyChanges };
2285
2367
  }
@@ -2340,7 +2422,7 @@ function renderCellModeCell(column, row, rawValue, ctx) {
2340
2422
  }
2341
2423
 
2342
2424
  // src/cell-editing/SelectionOverlay.tsx
2343
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef9, useState as useState10 } from "react";
2425
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef10, useState as useState10 } from "react";
2344
2426
  import { Fragment as Fragment2, jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
2345
2427
  function cellSelector(rowId, columnId) {
2346
2428
  const escape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
@@ -2373,7 +2455,7 @@ function SelectionOverlay({
2373
2455
  }) {
2374
2456
  const [rect, setRect] = useState10(void 0);
2375
2457
  const [previewRect, setPreviewRect] = useState10(void 0);
2376
- const recomputeRef = useRef9(() => {
2458
+ const recomputeRef = useRef10(() => {
2377
2459
  });
2378
2460
  recomputeRef.current = () => {
2379
2461
  const container = containerRef.current;
@@ -2620,7 +2702,7 @@ function computeFillChanges(sourceRange, finalRange, rowIds, columnIds, columns,
2620
2702
 
2621
2703
  // src/column-selector/ColumnSelector.tsx
2622
2704
  import { Columns3, GripVertical } from "lucide-react";
2623
- import { useEffect as useEffect7, useState as useState11 } from "react";
2705
+ import { useEffect as useEffect8, useState as useState11 } from "react";
2624
2706
 
2625
2707
  // src/components/ui/dialog.tsx
2626
2708
  import * as DialogPrimitive from "@radix-ui/react-dialog";
@@ -2787,12 +2869,12 @@ function ColumnSelector({
2787
2869
  columnOrder,
2788
2870
  onColumnOrderChange
2789
2871
  }) {
2790
- useEffect7(() => {
2872
+ useEffect8(() => {
2791
2873
  if (!persistKey) return;
2792
2874
  const restored = readPersistedVisibility(persistKey);
2793
2875
  if (restored) onVisibilityChange({ ...visibility, ...restored });
2794
2876
  }, [persistKey]);
2795
- useEffect7(() => {
2877
+ useEffect8(() => {
2796
2878
  if (!persistKey || !onColumnOrderChange) return;
2797
2879
  const restored = readPersistedColumnOrder(persistKey);
2798
2880
  if (restored) onColumnOrderChange(restored);
@@ -2975,11 +3057,11 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
2975
3057
  import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
2976
3058
  import { useVirtualizer } from "@tanstack/react-virtual";
2977
3059
  import { ChevronRight, Loader2 } from "lucide-react";
2978
- import { Fragment as Fragment3, useEffect as useEffect11, useMemo as useMemo8, useRef as useRef12, useState as useState16 } from "react";
3060
+ import { Fragment as Fragment3, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef13, useState as useState16 } from "react";
2979
3061
 
2980
3062
  // src/cell-editing/renderAlwaysEditCell.tsx
2981
3063
  import {
2982
- useEffect as useEffect8,
3064
+ useEffect as useEffect9,
2983
3065
  useState as useState12
2984
3066
  } from "react";
2985
3067
  import { jsx as jsx32 } from "react/jsx-runtime";
@@ -2991,7 +3073,7 @@ function AlwaysEditCell(props) {
2991
3073
  const [enumOpen, setEnumOpen] = useState12(false);
2992
3074
  const isBuiltinEnum = column.type === "enum" && !column.renderEditCell;
2993
3075
  const shouldOpenEnumNow = isBuiltinEnum && (atomicGesture?.shouldOpenEnum(rowId, column.id) ?? false);
2994
- useEffect8(() => {
3076
+ useEffect9(() => {
2995
3077
  if (shouldOpenEnumNow) setEnumOpen(true);
2996
3078
  }, [shouldOpenEnumNow]);
2997
3079
  if (!isEditable(column, row)) {
@@ -3114,9 +3196,9 @@ function useGroupExpansion(defaultGroupsExpanded, controlledExpandedGroups, onEx
3114
3196
  }
3115
3197
 
3116
3198
  // src/hooks/useStickyGroupHeaderTop.ts
3117
- import { useLayoutEffect as useLayoutEffect3, useRef as useRef10, useState as useState14 } from "react";
3199
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef11, useState as useState14 } from "react";
3118
3200
  function useStickyGroupHeaderTop(enabled) {
3119
- const theadRef = useRef10(null);
3201
+ const theadRef = useRef11(null);
3120
3202
  const [groupHeaderTop, setGroupHeaderTop] = useState14(0);
3121
3203
  useLayoutEffect3(() => {
3122
3204
  if (!enabled) return;
@@ -3181,15 +3263,15 @@ function processClientData(data, state) {
3181
3263
  }
3182
3264
 
3183
3265
  // src/grid/useGridState.ts
3184
- import { useCallback as useCallback4, useEffect as useEffect10, useMemo as useMemo7, useState as useState15 } from "react";
3266
+ import { useCallback as useCallback4, useEffect as useEffect11, useMemo as useMemo7, useState as useState15 } from "react";
3185
3267
 
3186
3268
  // src/hooks/useDebouncedCallback.ts
3187
- import { useEffect as useEffect9, useMemo as useMemo6, useRef as useRef11 } from "react";
3269
+ import { useEffect as useEffect10, useMemo as useMemo6, useRef as useRef12 } from "react";
3188
3270
  function useDebouncedCallback(callback, delayMs) {
3189
- const callbackRef = useRef11(callback);
3271
+ const callbackRef = useRef12(callback);
3190
3272
  callbackRef.current = callback;
3191
- const timeoutRef = useRef11(void 0);
3192
- useEffect9(() => {
3273
+ const timeoutRef = useRef12(void 0);
3274
+ useEffect10(() => {
3193
3275
  return () => {
3194
3276
  clearTimeout(timeoutRef.current);
3195
3277
  };
@@ -3242,7 +3324,7 @@ function useGridState(dataSource, initialState, externalState, showPagination =
3242
3324
  },
3243
3325
  [notifyRaw, cancelDebouncedNotify]
3244
3326
  );
3245
- useEffect10(() => {
3327
+ useEffect11(() => {
3246
3328
  if (!externalState) return;
3247
3329
  cancelDebouncedNotify();
3248
3330
  setState(externalState);
@@ -3451,7 +3533,7 @@ function DataGrid({
3451
3533
  hasCellEditing ? cellEditing : void 0,
3452
3534
  getRowId
3453
3535
  );
3454
- const atomicGestureRef = useRef12(void 0);
3536
+ const atomicGestureRef = useRef13(void 0);
3455
3537
  const visibleColumns = useVisibleColumns(columns, columnVisibility);
3456
3538
  const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
3457
3539
  const { rows, rowCount } = useMemo8(() => {
@@ -3530,11 +3612,12 @@ function DataGrid({
3530
3612
  );
3531
3613
  function pinnedCellProps(column, area = "body") {
3532
3614
  const bg = area === "header" ? "bg-muted" : "bg-background";
3615
+ const bgOdd = area === "header" ? "bg-muted" : STRUCTURAL_ZEBRA_BG_CLASS;
3533
3616
  if (column.pinned === "left") {
3534
- return { className: `sticky z-10 ${bg}`, style: { left: leftPinnedOffsets.get(column.id), width: columnSize(column.id), minWidth: columnSize(column.id) } };
3617
+ return { className: `sticky z-10 ${bg}`, classNameOdd: `sticky z-10 ${bgOdd}`, style: { left: leftPinnedOffsets.get(column.id), width: columnSize(column.id), minWidth: columnSize(column.id) } };
3535
3618
  }
3536
3619
  if (column.pinned === "right") {
3537
- return { className: `sticky z-10 ${bg}`, style: { right: rightPinnedOffsets.get(column.id), width: columnSize(column.id), minWidth: columnSize(column.id) } };
3620
+ return { className: `sticky z-10 ${bg}`, classNameOdd: `sticky z-10 ${bgOdd}`, style: { right: rightPinnedOffsets.get(column.id), width: columnSize(column.id), minWidth: columnSize(column.id) } };
3538
3621
  }
3539
3622
  if (enableColumnResizing) return { style: { width: columnSize(column.id) } };
3540
3623
  return { style: column.width ? { width: column.width } : void 0 };
@@ -3569,6 +3652,7 @@ function DataGrid({
3569
3652
  const pinnedProps = column.pinned || enableColumnResizing ? pinnedCellProps(column) : void 0;
3570
3653
  return {
3571
3654
  className: pinnedProps?.className ? `${BODY_TD_BASE_CLASS} ${pinnedProps.className}` : BODY_TD_BASE_CLASS,
3655
+ classNameOdd: pinnedProps?.classNameOdd ? `${BODY_TD_BASE_CLASS} ${pinnedProps.classNameOdd}` : BODY_TD_BASE_CLASS,
3572
3656
  style: pinnedProps?.style
3573
3657
  };
3574
3658
  }
@@ -3606,8 +3690,8 @@ function DataGrid({
3606
3690
  return map;
3607
3691
  }, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
3608
3692
  const tableRows = table.getRowModel().rows;
3609
- const truncationWarnedRef = useRef12(false);
3610
- useEffect11(() => {
3693
+ const truncationWarnedRef = useRef13(false);
3694
+ useEffect12(() => {
3611
3695
  if (process.env.NODE_ENV === "production") return;
3612
3696
  if (showPagination) return;
3613
3697
  if (truncationWarnedRef.current) return;
@@ -3637,7 +3721,7 @@ function DataGrid({
3637
3721
  }
3638
3722
  return items;
3639
3723
  }, [shouldVirtualize, groupedBuckets, tableRows, isGroupExpanded]);
3640
- const scrollRef = useRef12(null);
3724
+ const scrollRef = useRef13(null);
3641
3725
  const virtualizer = useVirtualizer({
3642
3726
  count: flatItems.length,
3643
3727
  getScrollElement: () => scrollRef.current,
@@ -3649,11 +3733,11 @@ function DataGrid({
3649
3733
  const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
3650
3734
  const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
3651
3735
  const lastVisibleIndex = virtualItems.length > 0 ? virtualItems[virtualItems.length - 1].index : -1;
3652
- const notifiedForLengthRef = useRef12(-1);
3653
- useEffect11(() => {
3736
+ const notifiedForLengthRef = useRef13(-1);
3737
+ useEffect12(() => {
3654
3738
  notifiedForLengthRef.current = -1;
3655
3739
  }, [state.filter, state.sort]);
3656
- useEffect11(() => {
3740
+ useEffect12(() => {
3657
3741
  if (!virtualize?.onEndReached) return;
3658
3742
  if (lastVisibleIndex < 0 || lastVisibleIndex < flatItems.length - 1) return;
3659
3743
  if (virtualize.hasMore === false) return;
@@ -3679,8 +3763,8 @@ function DataGrid({
3679
3763
  if (index !== void 0) virtualizer.scrollToIndex(index);
3680
3764
  }
3681
3765
  });
3682
- const clickCellRef = useRef12(null);
3683
- const dragMovedRef = useRef12(false);
3766
+ const clickCellRef = useRef13(null);
3767
+ const dragMovedRef = useRef13(false);
3684
3768
  const [pendingOpenEnumCell, setPendingOpenEnumCell] = useState16(void 0);
3685
3769
  atomicGestureRef.current = {
3686
3770
  shouldOpenEnum: (rowId, columnId) => pendingOpenEnumCell?.rowId === rowId && pendingOpenEnumCell?.columnId === columnId,
@@ -3704,9 +3788,9 @@ function DataGrid({
3704
3788
  if (!column || row === void 0 || !isEditable(column, row)) return;
3705
3789
  cellEditingCtx.onBeginEdit(cell);
3706
3790
  }
3707
- const pendingDragCellRef = useRef12(null);
3708
- const dragRafRef = useRef12(null);
3709
- useEffect11(() => {
3791
+ const pendingDragCellRef = useRef13(null);
3792
+ const dragRafRef = useRef13(null);
3793
+ useEffect12(() => {
3710
3794
  if (!cellSelection.isDragging) return;
3711
3795
  function handleMouseMove(event) {
3712
3796
  const cellEl = event.target?.closest("[data-cell-row]");
@@ -3745,9 +3829,9 @@ function DataGrid({
3745
3829
  dragRafRef.current = null;
3746
3830
  };
3747
3831
  }, [cellSelection.isDragging, cellSelection.updateDrag, cellSelection.endDrag]);
3748
- const pendingFillCellRef = useRef12(null);
3749
- const fillRafRef = useRef12(null);
3750
- useEffect11(() => {
3832
+ const pendingFillCellRef = useRef13(null);
3833
+ const fillRafRef = useRef13(null);
3834
+ useEffect12(() => {
3751
3835
  if (!cellSelection.isFillDragging) return;
3752
3836
  function handleMouseMove(event) {
3753
3837
  const cellEl = event.target?.closest("[data-cell-row]");
@@ -3783,8 +3867,8 @@ function DataGrid({
3783
3867
  fillRafRef.current = null;
3784
3868
  };
3785
3869
  }, [cellSelection.isFillDragging, cellSelection.updateFillDrag, cellSelection.endFillDrag]);
3786
- const wasEditingCellRef = useRef12(void 0);
3787
- useEffect11(() => {
3870
+ const wasEditingCellRef = useRef13(void 0);
3871
+ useEffect12(() => {
3788
3872
  const wasEditing = wasEditingCellRef.current !== void 0;
3789
3873
  wasEditingCellRef.current = cellEditingCtx?.editingCell;
3790
3874
  if (!wasEditing || cellEditingCtx?.editingCell) return;
@@ -3967,7 +4051,7 @@ function DataGrid({
3967
4051
  "td",
3968
4052
  {
3969
4053
  style: cellProps?.style,
3970
- className: cellProps?.className ?? BODY_TD_BASE_CLASS,
4054
+ className: (isOddRow ? cellProps?.classNameOdd : cellProps?.className) ?? BODY_TD_BASE_CLASS,
3971
4055
  "data-cell-row": hasCellEditing ? row.id : void 0,
3972
4056
  "data-cell-col": hasCellEditing ? cell.column.id : void 0,
3973
4057
  children: flexRender(cell.column.columnDef.cell, cell.getContext())
@@ -4207,7 +4291,7 @@ function DataGrid({
4207
4291
  )
4208
4292
  }
4209
4293
  ) }),
4210
- /* @__PURE__ */ jsx33(PopoverContent, { children: renderFilterWidget(column) })
4294
+ /* @__PURE__ */ jsx33(PopoverContent, { className: "w-auto", children: renderFilterWidget(column) })
4211
4295
  ] })
4212
4296
  ] }),
4213
4297
  enableColumnResizing && /* @__PURE__ */ jsx33(
@@ -4415,7 +4499,7 @@ function DataGrid({
4415
4499
  // src/tree/TreeDataGrid.tsx
4416
4500
  import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
4417
4501
  import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
4418
- import { Fragment as Fragment5, useEffect as useEffect12, useMemo as useMemo10, useRef as useRef13 } from "react";
4502
+ import { Fragment as Fragment5, useEffect as useEffect13, useMemo as useMemo10, useRef as useRef14 } from "react";
4419
4503
 
4420
4504
  // src/tree/flattenTree.ts
4421
4505
  function flattenTree(roots, accessors, expanded, childrenOverride) {
@@ -4669,8 +4753,8 @@ function TreeDataGrid({
4669
4753
  childrenMap: controlledChildrenMap,
4670
4754
  onChildrenMapChange
4671
4755
  });
4672
- const didAutoExpand = useRef13(false);
4673
- useEffect12(() => {
4756
+ const didAutoExpand = useRef14(false);
4757
+ useEffect13(() => {
4674
4758
  if (didAutoExpand.current) return;
4675
4759
  didAutoExpand.current = true;
4676
4760
  if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
@@ -4749,7 +4833,7 @@ function TreeDataGrid({
4749
4833
  function renderGroupSummaryCells(rows) {
4750
4834
  return visibleColumns.map((column) => /* @__PURE__ */ jsx34("td", { className: cn(bodyTdClassByColumn.get(column.id), "font-medium"), children: column.summary?.(rows) }, column.id));
4751
4835
  }
4752
- const scrollRef = useRef13(null);
4836
+ const scrollRef = useRef14(null);
4753
4837
  const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
4754
4838
  const virtualizer = useVirtualizer2({
4755
4839
  count: flatRows.length,