@bmsuisse/datagrid 0.23.2 → 0.23.4

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
@@ -192,7 +192,8 @@ var buttonVariants = cva(
192
192
  var Button = forwardRef(
193
193
  ({ className, variant, size, asChild = false, ...props }, ref) => {
194
194
  const Comp = asChild ? Slot : "button";
195
- return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
195
+ const variantClass = buttonVariants({ variant, size });
196
+ return /* @__PURE__ */ jsx(Comp, { className: className ? cn(variantClass, className) : variantClass, ref, ...props });
196
197
  }
197
198
  );
198
199
  Button.displayName = "Button";
@@ -648,6 +649,15 @@ function toNumber(value) {
648
649
  }
649
650
  return null;
650
651
  }
652
+ var currencyFormatters = /* @__PURE__ */ new Map();
653
+ function currencyFormatter(currency) {
654
+ let formatter = currencyFormatters.get(currency);
655
+ if (!formatter) {
656
+ formatter = new Intl.NumberFormat(void 0, { style: "currency", currency });
657
+ currencyFormatters.set(currency, formatter);
658
+ }
659
+ return formatter;
660
+ }
651
661
  function defaultFormat(column, value) {
652
662
  if (value === null || value === void 0) return "";
653
663
  switch (column.type) {
@@ -660,10 +670,7 @@ function defaultFormat(column, value) {
660
670
  case "currency": {
661
671
  const num = toNumber(value);
662
672
  if (num === null) return String(value);
663
- return new Intl.NumberFormat(void 0, {
664
- style: "currency",
665
- currency: column.currency ?? "USD"
666
- }).format(num);
673
+ return currencyFormatter(column.currency ?? "USD").format(num);
667
674
  }
668
675
  case "date": {
669
676
  const date = toDate(value);
@@ -1508,6 +1515,7 @@ function resolveMenuItems(items, ctx) {
1508
1515
 
1509
1516
  // src/menu/ActionsMenu.tsx
1510
1517
  import { MoreVertical } from "lucide-react";
1518
+ import { useMemo as useMemo3 } from "react";
1511
1519
 
1512
1520
  // src/components/ui/dropdown-menu.tsx
1513
1521
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
@@ -1563,7 +1571,10 @@ DropdownMenuLabel.displayName = "DropdownMenuLabel";
1563
1571
  // src/menu/ActionsMenu.tsx
1564
1572
  import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1565
1573
  function ActionsMenu({ items, ctx, triggerLabel }) {
1566
- const resolved = resolveMenuItems(items, ctx);
1574
+ const resolved = useMemo3(
1575
+ () => resolveMenuItems(items, ctx),
1576
+ [items, ctx.row, ctx.selectedRows]
1577
+ );
1567
1578
  if (resolved.length === 0) return null;
1568
1579
  return /* @__PURE__ */ jsxs11(DropdownMenu, { children: [
1569
1580
  /* @__PURE__ */ jsx18(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx18(Button, { variant: "ghost", size: "icon", "aria-label": triggerLabel, onClick: stopRowClick, children: /* @__PURE__ */ jsx18(MoreVertical, { className: "h-4 w-4", "aria-hidden": true }) }) }),
@@ -1585,7 +1596,7 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
1585
1596
  import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
1586
1597
  import { useVirtualizer } from "@tanstack/react-virtual";
1587
1598
  import { ChevronRight, Loader2 } from "lucide-react";
1588
- import { Fragment as Fragment2, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState6 } from "react";
1599
+ import { Fragment as Fragment2, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef5, useState as useState6 } from "react";
1589
1600
 
1590
1601
  // src/grid/processClientData.ts
1591
1602
  function makeComparator(sort) {
@@ -1613,10 +1624,10 @@ function processClientData(data, state) {
1613
1624
  }
1614
1625
 
1615
1626
  // src/grid/useGridState.ts
1616
- import { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo4, useState as useState5 } from "react";
1627
+ import { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo5, useState as useState5 } from "react";
1617
1628
 
1618
1629
  // src/hooks/useDebouncedCallback.ts
1619
- import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef4 } from "react";
1630
+ import { useEffect as useEffect5, useMemo as useMemo4, useRef as useRef4 } from "react";
1620
1631
  function useDebouncedCallback(callback, delayMs) {
1621
1632
  const callbackRef = useRef4(callback);
1622
1633
  callbackRef.current = callback;
@@ -1626,7 +1637,7 @@ function useDebouncedCallback(callback, delayMs) {
1626
1637
  clearTimeout(timeoutRef.current);
1627
1638
  };
1628
1639
  }, []);
1629
- return useMemo3(() => {
1640
+ return useMemo4(() => {
1630
1641
  return {
1631
1642
  run: (...args) => {
1632
1643
  clearTimeout(timeoutRef.current);
@@ -1676,7 +1687,7 @@ function useGridState(dataSource, initialState, externalState) {
1676
1687
  cancelDebouncedNotify();
1677
1688
  setState(externalState);
1678
1689
  }, [externalState, cancelDebouncedNotify]);
1679
- const filtersByColumn = useMemo4(() => {
1690
+ const filtersByColumn = useMemo5(() => {
1680
1691
  const map = /* @__PURE__ */ new Map();
1681
1692
  for (const child of state.filter?.filters ?? []) {
1682
1693
  if ("operator" in child) map.set(fieldKey(child.field), child);
@@ -1830,16 +1841,16 @@ function DataGrid({
1830
1841
  return next;
1831
1842
  });
1832
1843
  }
1833
- const visibleColumns = useMemo5(
1844
+ const visibleColumns = useMemo6(
1834
1845
  () => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
1835
1846
  [columns, columnVisibility]
1836
1847
  );
1837
1848
  const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
1838
- const { rows, rowCount } = useMemo5(() => {
1849
+ const { rows, rowCount } = useMemo6(() => {
1839
1850
  if (dataSource.mode === "client") return processClientData(dataSource.data, state);
1840
1851
  return { rows: dataSource.data, rowCount: serverRowCount ?? 0 };
1841
1852
  }, [dataSource.mode, dataSource.data, serverRowCount, state]);
1842
- const selectedRows = useMemo5(
1853
+ const selectedRows = useMemo6(
1843
1854
  () => rows.filter((row) => selectedIds.has(getRowId(row))),
1844
1855
  [rows, selectedIds, getRowId]
1845
1856
  );
@@ -1858,8 +1869,8 @@ function DataGrid({
1858
1869
  }
1859
1870
  updateSelectedIds(next);
1860
1871
  }
1861
- const tanstackColumns = useMemo5(() => toTanstackColumns(visibleColumns), [visibleColumns]);
1862
- const columnById = useMemo5(() => {
1872
+ const tanstackColumns = useMemo6(() => toTanstackColumns(visibleColumns), [visibleColumns]);
1873
+ const columnById = useMemo6(() => {
1863
1874
  const map = /* @__PURE__ */ new Map();
1864
1875
  for (const column of visibleColumns) map.set(column.id, column);
1865
1876
  return map;
@@ -1884,7 +1895,7 @@ function DataGrid({
1884
1895
  const showDetailColumn = Boolean(renderDetail);
1885
1896
  const totalColumnCount = visibleColumns.length + (showDetailColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0) + (showRowActionsColumn ? 1 : 0);
1886
1897
  const hasFilterRow = visibleColumns.some((column) => isFilterable(column) && column.filterDisplay === "row");
1887
- const headerRuns = useMemo5(() => computeHeaderRuns(visibleColumns), [visibleColumns]);
1898
+ const headerRuns = useMemo6(() => computeHeaderRuns(visibleColumns), [visibleColumns]);
1888
1899
  const hasHeaderGroups = visibleColumns.some((column) => column.headerGroup);
1889
1900
  function renderFilterWidget(column) {
1890
1901
  const value = filtersByColumn.get(column.id);
@@ -1894,22 +1905,28 @@ function DataGrid({
1894
1905
  const columnSize = (columnId) => table.getColumn(columnId)?.getSize() ?? DEFAULT_COLUMN_SIZE;
1895
1906
  const leadingStructuralWidth = (showDetailColumn ? DETAIL_COLUMN_WIDTH : 0) + (showSelectionColumn ? SELECTION_COLUMN_WIDTH : 0);
1896
1907
  const trailingStructuralWidth = showRowActionsColumn ? ROW_ACTIONS_COLUMN_WIDTH : 0;
1897
- const leftPinnedOffsets = pinnedOffsets(visibleColumns, "left", columnSize, leadingStructuralWidth);
1898
- const rightPinnedOffsets = pinnedOffsets(visibleColumns, "right", columnSize, trailingStructuralWidth);
1908
+ const leftPinnedOffsets = useMemo6(
1909
+ () => pinnedOffsets(visibleColumns, "left", columnSize, leadingStructuralWidth),
1910
+ [visibleColumns, columnSizing, leadingStructuralWidth]
1911
+ );
1912
+ const rightPinnedOffsets = useMemo6(
1913
+ () => pinnedOffsets(visibleColumns, "right", columnSize, trailingStructuralWidth),
1914
+ [visibleColumns, columnSizing, trailingStructuralWidth]
1915
+ );
1899
1916
  function pinnedCellProps(column, area = "body") {
1900
1917
  const bg = area === "header" ? "bg-muted" : "bg-background";
1901
1918
  if (column.pinned === "left") {
1902
- return { className: cn("sticky z-10", bg), style: { left: leftPinnedOffsets.get(column.id), width: columnSize(column.id) } };
1919
+ return { className: `sticky z-10 ${bg}`, style: { left: leftPinnedOffsets.get(column.id), width: columnSize(column.id) } };
1903
1920
  }
1904
1921
  if (column.pinned === "right") {
1905
- return { className: cn("sticky z-10", bg), style: { right: rightPinnedOffsets.get(column.id), width: columnSize(column.id) } };
1922
+ return { className: `sticky z-10 ${bg}`, style: { right: rightPinnedOffsets.get(column.id), width: columnSize(column.id) } };
1906
1923
  }
1907
1924
  if (enableColumnResizing) return { style: { width: columnSize(column.id) } };
1908
1925
  return { style: column.width ? { width: column.width } : void 0 };
1909
1926
  }
1910
1927
  function structuralCellProps(side, offset, width, area = "body") {
1911
1928
  const bg = area === "header" ? "bg-muted" : "bg-background";
1912
- return { className: cn("sticky z-10", bg), style: { [side]: offset, width } };
1929
+ return { className: `border-b p-1 sticky z-10 ${bg}`, style: { [side]: offset, width } };
1913
1930
  }
1914
1931
  const detailCellProps = structuralCellProps("left", 0, DETAIL_COLUMN_WIDTH);
1915
1932
  const selectionCellProps = structuralCellProps(
@@ -1926,6 +1943,39 @@ function DataGrid({
1926
1943
  "header"
1927
1944
  );
1928
1945
  const rowActionsHeaderCellProps = structuralCellProps("right", 0, ROW_ACTIONS_COLUMN_WIDTH, "header");
1946
+ const BODY_TD_BASE_CLASS = "border-b p-2";
1947
+ function bodyCellClassAndStyle(column) {
1948
+ const pinnedProps = column.pinned || enableColumnResizing ? pinnedCellProps(column) : void 0;
1949
+ return {
1950
+ className: pinnedProps?.className ? `${BODY_TD_BASE_CLASS} ${pinnedProps.className}` : BODY_TD_BASE_CLASS,
1951
+ style: pinnedProps?.style
1952
+ };
1953
+ }
1954
+ const bodyCellPropsByColumn = useMemo6(() => {
1955
+ const map = /* @__PURE__ */ new Map();
1956
+ for (const column of visibleColumns) map.set(column.id, bodyCellClassAndStyle(column));
1957
+ return map;
1958
+ }, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
1959
+ function headerCellClassAndStyle(column, base) {
1960
+ const pinnedProps = pinnedCellProps(column, "header");
1961
+ const align = alignClassName(column);
1962
+ const className = pinnedProps.className ? `${base} ${align} ${pinnedProps.className}` : `${base} ${align}`;
1963
+ return { className, style: pinnedProps.style };
1964
+ }
1965
+ const leafHeaderCellPropsByColumn = useMemo6(() => {
1966
+ const map = /* @__PURE__ */ new Map();
1967
+ for (const column of visibleColumns) {
1968
+ map.set(column.id, headerCellClassAndStyle(column, "relative border-b p-2 font-medium"));
1969
+ }
1970
+ return map;
1971
+ }, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
1972
+ const filterHeaderCellPropsByColumn = useMemo6(() => {
1973
+ const map = /* @__PURE__ */ new Map();
1974
+ for (const column of visibleColumns) {
1975
+ map.set(column.id, headerCellClassAndStyle(column, "border-b p-2 align-top font-normal"));
1976
+ }
1977
+ return map;
1978
+ }, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
1929
1979
  const tableRows = table.getRowModel().rows;
1930
1980
  const shouldVirtualize = Boolean(virtualize) && tableRows.length > (virtualize?.threshold ?? 100);
1931
1981
  const scrollRef = useRef5(null);
@@ -1959,9 +2009,9 @@ function DataGrid({
1959
2009
  {
1960
2010
  ...rowProps,
1961
2011
  "data-testid": rowTestId,
1962
- className: cn(rowProps?.className, row.index % 2 === 1 && "bg-foreground/5"),
2012
+ className: rowProps?.className ? cn(rowProps.className, row.index % 2 === 1 && "bg-foreground/5") : row.index % 2 === 1 ? "bg-foreground/5" : void 0,
1963
2013
  children: [
1964
- showDetailColumn && /* @__PURE__ */ jsx19("td", { className: cn("border-b p-1", detailCellProps.className), style: detailCellProps.style, children: /* @__PURE__ */ jsx19(
2014
+ showDetailColumn && /* @__PURE__ */ jsx19("td", { className: detailCellProps.className, style: detailCellProps.style, children: /* @__PURE__ */ jsx19(
1965
2015
  Button,
1966
2016
  {
1967
2017
  type: "button",
@@ -1973,10 +2023,16 @@ function DataGrid({
1973
2023
  stopRowClick(event);
1974
2024
  toggleRowExpanded(row.id);
1975
2025
  },
1976
- children: /* @__PURE__ */ jsx19(ChevronRight, { className: cn("h-4 w-4 transition-transform", isExpanded && "rotate-90"), "aria-hidden": true })
2026
+ children: /* @__PURE__ */ jsx19(
2027
+ ChevronRight,
2028
+ {
2029
+ className: `h-4 w-4 transition-transform${isExpanded ? " rotate-90" : ""}`,
2030
+ "aria-hidden": true
2031
+ }
2032
+ )
1977
2033
  }
1978
2034
  ) }),
1979
- showSelectionColumn && /* @__PURE__ */ jsx19("td", { className: cn("border-b p-1", selectionCellProps.className), style: selectionCellProps.style, children: /* @__PURE__ */ jsx19(
2035
+ showSelectionColumn && /* @__PURE__ */ jsx19("td", { className: selectionCellProps.className, style: selectionCellProps.style, children: /* @__PURE__ */ jsx19(
1980
2036
  "input",
1981
2037
  {
1982
2038
  type: "checkbox",
@@ -1987,11 +2043,10 @@ function DataGrid({
1987
2043
  }
1988
2044
  ) }),
1989
2045
  row.getAllCells().map((cell) => {
1990
- const cellColumn = columnById.get(cell.column.id);
1991
- const pinnedProps = cellColumn && (cellColumn.pinned || enableColumnResizing) ? pinnedCellProps(cellColumn) : void 0;
1992
- return /* @__PURE__ */ jsx19("td", { style: pinnedProps?.style, className: cn("border-b p-2", pinnedProps?.className), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
2046
+ const cellProps = bodyCellPropsByColumn.get(cell.column.id);
2047
+ return /* @__PURE__ */ jsx19("td", { style: cellProps?.style, className: cellProps?.className ?? BODY_TD_BASE_CLASS, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
1993
2048
  }),
1994
- showRowActionsColumn && rowActions && /* @__PURE__ */ jsx19("td", { className: cn("border-b p-1", rowActionsCellProps.className), style: rowActionsCellProps.style, children: /* @__PURE__ */ jsx19(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` }) })
2049
+ showRowActionsColumn && rowActions && /* @__PURE__ */ jsx19("td", { className: rowActionsCellProps.className, style: rowActionsCellProps.style, children: /* @__PURE__ */ jsx19(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` }) })
1995
2050
  ]
1996
2051
  }
1997
2052
  ),
@@ -2032,50 +2087,41 @@ function DataGrid({
2032
2087
  const sortEntry = state.sort.find((s) => s.field === column.id);
2033
2088
  const sortable = isSortable(column);
2034
2089
  const filterable = isFilterable(column) && column.filterDisplay !== "row";
2035
- const pinnedProps = pinnedCellProps(column, "header");
2036
- return /* @__PURE__ */ jsxs12(
2037
- "th",
2038
- {
2039
- rowSpan,
2040
- style: pinnedProps.style,
2041
- className: cn("relative border-b p-2 font-medium", alignClassName(column), pinnedProps.className),
2042
- children: [
2043
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
2044
- /* @__PURE__ */ jsxs12(
2045
- "button",
2046
- {
2047
- type: "button",
2048
- className: cn(
2049
- "flex items-center gap-1 rounded-sm px-1",
2050
- sortable && "hover:bg-accent hover:text-accent-foreground"
2051
- ),
2052
- disabled: !sortable,
2053
- onClick: (event) => sortable && toggleSort(column.id, enableMultiSort && event.shiftKey, column.sortDescFirst === true),
2054
- children: [
2055
- column.renderHeader ? column.renderHeader(column) : column.header,
2056
- sortable && sortEntry?.dir === "asc" && /* @__PURE__ */ jsx19(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
2057
- sortable && sortEntry?.dir === "desc" && /* @__PURE__ */ jsx19(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
2058
- ]
2059
- }
2090
+ const cellProps = leafHeaderCellPropsByColumn.get(column.id);
2091
+ return /* @__PURE__ */ jsxs12("th", { rowSpan, style: cellProps?.style, className: cellProps?.className, children: [
2092
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
2093
+ /* @__PURE__ */ jsxs12(
2094
+ "button",
2095
+ {
2096
+ type: "button",
2097
+ className: cn(
2098
+ "flex items-center gap-1 rounded-sm px-1",
2099
+ sortable && "hover:bg-accent hover:text-accent-foreground"
2060
2100
  ),
2061
- filterable && /* @__PURE__ */ jsxs12(Popover, { children: [
2062
- /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(Button, { variant: "ghost", size: "icon", "aria-label": `Filter ${column.header}`, children: /* @__PURE__ */ jsx19(FunnelIcon7, { className: "h-3 w-3", "aria-hidden": true }) }) }),
2063
- /* @__PURE__ */ jsx19(PopoverContent, { children: renderFilterWidget(column) })
2064
- ] })
2065
- ] }),
2066
- enableColumnResizing && /* @__PURE__ */ jsx19(
2067
- "div",
2068
- {
2069
- "data-testid": `resize-handle-${column.id}`,
2070
- onMouseDown: header.getResizeHandler(),
2071
- onTouchStart: header.getResizeHandler(),
2072
- className: "absolute right-0 top-0 h-full w-1 cursor-col-resize touch-none select-none hover:bg-accent"
2073
- }
2074
- )
2075
- ]
2076
- },
2077
- header.id
2078
- );
2101
+ disabled: !sortable,
2102
+ onClick: (event) => sortable && toggleSort(column.id, enableMultiSort && event.shiftKey, column.sortDescFirst === true),
2103
+ children: [
2104
+ column.renderHeader ? column.renderHeader(column) : column.header,
2105
+ sortable && sortEntry?.dir === "asc" && /* @__PURE__ */ jsx19(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
2106
+ sortable && sortEntry?.dir === "desc" && /* @__PURE__ */ jsx19(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
2107
+ ]
2108
+ }
2109
+ ),
2110
+ filterable && /* @__PURE__ */ jsxs12(Popover, { children: [
2111
+ /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(Button, { variant: "ghost", size: "icon", "aria-label": `Filter ${column.header}`, children: /* @__PURE__ */ jsx19(FunnelIcon7, { className: "h-3 w-3", "aria-hidden": true }) }) }),
2112
+ /* @__PURE__ */ jsx19(PopoverContent, { children: renderFilterWidget(column) })
2113
+ ] })
2114
+ ] }),
2115
+ enableColumnResizing && /* @__PURE__ */ jsx19(
2116
+ "div",
2117
+ {
2118
+ "data-testid": `resize-handle-${column.id}`,
2119
+ onMouseDown: header.getResizeHandler(),
2120
+ onTouchStart: header.getResizeHandler(),
2121
+ className: "absolute right-0 top-0 h-full w-1 cursor-col-resize touch-none select-none hover:bg-accent"
2122
+ }
2123
+ )
2124
+ ] }, header.id);
2079
2125
  }
2080
2126
  return /* @__PURE__ */ jsxs12(Fragment2, { children: [
2081
2127
  hasHeaderGroups && /* @__PURE__ */ jsxs12("tr", { "data-testid": "header-group-row", children: [
@@ -2083,7 +2129,7 @@ function DataGrid({
2083
2129
  "th",
2084
2130
  {
2085
2131
  rowSpan: 2,
2086
- className: cn("border-b p-1", detailHeaderCellProps.className),
2132
+ className: detailHeaderCellProps.className,
2087
2133
  style: detailHeaderCellProps.style,
2088
2134
  "aria-hidden": true
2089
2135
  }
@@ -2092,7 +2138,7 @@ function DataGrid({
2092
2138
  "th",
2093
2139
  {
2094
2140
  rowSpan: 2,
2095
- className: cn("border-b p-1", selectionHeaderCellProps.className),
2141
+ className: selectionHeaderCellProps.className,
2096
2142
  style: selectionHeaderCellProps.style,
2097
2143
  children: /* @__PURE__ */ jsx19(
2098
2144
  "input",
@@ -2120,7 +2166,7 @@ function DataGrid({
2120
2166
  "th",
2121
2167
  {
2122
2168
  rowSpan: 2,
2123
- className: cn("border-b p-1", rowActionsHeaderCellProps.className),
2169
+ className: rowActionsHeaderCellProps.className,
2124
2170
  style: rowActionsHeaderCellProps.style,
2125
2171
  "aria-label": "Row actions"
2126
2172
  }
@@ -2130,7 +2176,7 @@ function DataGrid({
2130
2176
  !hasHeaderGroups && showDetailColumn && /* @__PURE__ */ jsx19(
2131
2177
  "th",
2132
2178
  {
2133
- className: cn("border-b p-1", detailHeaderCellProps.className),
2179
+ className: detailHeaderCellProps.className,
2134
2180
  style: detailHeaderCellProps.style,
2135
2181
  "aria-hidden": true
2136
2182
  }
@@ -2138,7 +2184,7 @@ function DataGrid({
2138
2184
  !hasHeaderGroups && showSelectionColumn && /* @__PURE__ */ jsx19(
2139
2185
  "th",
2140
2186
  {
2141
- className: cn("border-b p-1", selectionHeaderCellProps.className),
2187
+ className: selectionHeaderCellProps.className,
2142
2188
  style: selectionHeaderCellProps.style,
2143
2189
  children: /* @__PURE__ */ jsx19(
2144
2190
  "input",
@@ -2159,7 +2205,7 @@ function DataGrid({
2159
2205
  !hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */ jsx19(
2160
2206
  "th",
2161
2207
  {
2162
- className: cn("border-b p-1", rowActionsHeaderCellProps.className),
2208
+ className: rowActionsHeaderCellProps.className,
2163
2209
  style: rowActionsHeaderCellProps.style,
2164
2210
  "aria-label": "Row actions"
2165
2211
  }
@@ -2168,30 +2214,22 @@ function DataGrid({
2168
2214
  ] }, headerGroup.id);
2169
2215
  }),
2170
2216
  hasFilterRow && /* @__PURE__ */ jsxs12("tr", { "data-testid": "filter-row", children: [
2171
- showDetailColumn && /* @__PURE__ */ jsx19("th", { className: cn("border-b p-1", detailHeaderCellProps.className), style: detailHeaderCellProps.style }),
2217
+ showDetailColumn && /* @__PURE__ */ jsx19("th", { className: detailHeaderCellProps.className, style: detailHeaderCellProps.style }),
2172
2218
  showSelectionColumn && /* @__PURE__ */ jsx19(
2173
2219
  "th",
2174
2220
  {
2175
- className: cn("border-b p-1", selectionHeaderCellProps.className),
2221
+ className: selectionHeaderCellProps.className,
2176
2222
  style: selectionHeaderCellProps.style
2177
2223
  }
2178
2224
  ),
2179
2225
  visibleColumns.map((column) => {
2180
- const pinnedProps = pinnedCellProps(column, "header");
2181
- return /* @__PURE__ */ jsx19(
2182
- "th",
2183
- {
2184
- style: pinnedProps.style,
2185
- className: cn("border-b p-2 align-top font-normal", alignClassName(column), pinnedProps.className),
2186
- children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null
2187
- },
2188
- column.id
2189
- );
2226
+ const cellProps = filterHeaderCellPropsByColumn.get(column.id);
2227
+ return /* @__PURE__ */ jsx19("th", { style: cellProps?.style, className: cellProps?.className, children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null }, column.id);
2190
2228
  }),
2191
2229
  showRowActionsColumn && /* @__PURE__ */ jsx19(
2192
2230
  "th",
2193
2231
  {
2194
- className: cn("border-b p-1", rowActionsHeaderCellProps.className),
2232
+ className: rowActionsHeaderCellProps.className,
2195
2233
  style: rowActionsHeaderCellProps.style
2196
2234
  }
2197
2235
  )
@@ -2249,7 +2287,7 @@ function DataGrid({
2249
2287
  // src/tree/TreeDataGrid.tsx
2250
2288
  import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
2251
2289
  import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
2252
- import { useEffect as useEffect8, useMemo as useMemo7, useRef as useRef6 } from "react";
2290
+ import { useEffect as useEffect8, useMemo as useMemo8, useRef as useRef6 } from "react";
2253
2291
 
2254
2292
  // src/tree/flattenTree.ts
2255
2293
  function flattenTree(roots, accessors, expanded, childrenOverride) {
@@ -2269,7 +2307,7 @@ function flattenTree(roots, accessors, expanded, childrenOverride) {
2269
2307
  }
2270
2308
 
2271
2309
  // src/tree/useTreeState.ts
2272
- import { useCallback as useCallback3, useMemo as useMemo6, useState as useState7 } from "react";
2310
+ import { useCallback as useCallback3, useMemo as useMemo7, useState as useState7 } from "react";
2273
2311
  function useTreeState({
2274
2312
  data,
2275
2313
  getRowId,
@@ -2294,7 +2332,7 @@ function useTreeState({
2294
2332
  const [childrenMap, setChildrenMap] = useState7(/* @__PURE__ */ new Map());
2295
2333
  const [loadingIds, setLoadingIds] = useState7(/* @__PURE__ */ new Set());
2296
2334
  const [errorIds, setErrorIds] = useState7(/* @__PURE__ */ new Map());
2297
- const resolveHasChildren = useMemo6(
2335
+ const resolveHasChildren = useMemo7(
2298
2336
  () => hasChildren ?? ((row) => (getChildren(row)?.length ?? 0) > 0),
2299
2337
  [hasChildren, getChildren]
2300
2338
  );
@@ -2430,7 +2468,7 @@ function TreeDataGrid({
2430
2468
  estimatedRowHeight = 40,
2431
2469
  maxBodyHeight = 480
2432
2470
  }) {
2433
- const accessors = useMemo7(
2471
+ const accessors = useMemo8(
2434
2472
  () => ({ getRowId, getChildren, hasChildren }),
2435
2473
  [getRowId, getChildren, hasChildren]
2436
2474
  );
@@ -2449,13 +2487,18 @@ function TreeDataGrid({
2449
2487
  didAutoExpand.current = true;
2450
2488
  if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
2451
2489
  }, []);
2452
- const flatRows = useMemo7(
2490
+ const flatRows = useMemo8(
2453
2491
  () => flattenTree(data, accessors, expanded, childrenMap),
2454
2492
  [data, accessors, expanded, childrenMap]
2455
2493
  );
2456
2494
  const treeColId = treeColumnId ?? columns[0]?.id;
2457
2495
  const showRowActionsColumn = Boolean(rowActions?.length);
2458
2496
  const totalColumnCount = columns.length + (showRowActionsColumn ? 1 : 0);
2497
+ const bodyTdClassByColumn = useMemo8(() => {
2498
+ const map = /* @__PURE__ */ new Map();
2499
+ for (const column of columns) map.set(column.id, `p-2 ${alignClassName(column)}`);
2500
+ return map;
2501
+ }, [columns]);
2459
2502
  const scrollRef = useRef6(null);
2460
2503
  const shouldVirtualize = flatRows.length > virtualizeThreshold;
2461
2504
  const virtualizer = useVirtualizer2({
@@ -2474,9 +2517,9 @@ function TreeDataGrid({
2474
2517
  ref: measureRef,
2475
2518
  ...rowProps,
2476
2519
  "data-testid": rowTestId,
2477
- className: cn("border-b", rowProps?.className, index % 2 === 1 && "bg-foreground/5"),
2520
+ className: rowProps?.className ? cn("border-b", rowProps.className, index % 2 === 1 && "bg-foreground/5") : `border-b${index % 2 === 1 ? " bg-foreground/5" : ""}`,
2478
2521
  children: [
2479
- columns.map((column) => /* @__PURE__ */ jsx20("td", { className: cn("p-2", alignClassName(column)), children: column.id === treeColId ? /* @__PURE__ */ jsx20(
2522
+ columns.map((column) => /* @__PURE__ */ jsx20("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx20(
2480
2523
  TreeCell,
2481
2524
  {
2482
2525
  flatRow,
@@ -2516,7 +2559,7 @@ function TreeDataGrid({
2516
2559
  "th",
2517
2560
  {
2518
2561
  style: column.width ? { width: column.width } : void 0,
2519
- className: cn("border-b p-2 font-medium", alignClassName(column)),
2562
+ className: `border-b p-2 font-medium ${alignClassName(column)}`,
2520
2563
  children: column.header
2521
2564
  },
2522
2565
  column.id