@bmsuisse/datagrid 0.25.2 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1235,6 +1235,10 @@ function isSortable(column) {
1235
1235
  function isFilterable(column) {
1236
1236
  return column.filterable === true;
1237
1237
  }
1238
+ function isEditable(column, row) {
1239
+ if (!column.editable) return false;
1240
+ return typeof column.editable === "function" ? column.editable(row) : true;
1241
+ }
1238
1242
 
1239
1243
  // src/filter/facetedValues.ts
1240
1244
  function withoutColumn(filter, columnId) {
@@ -1365,6 +1369,202 @@ function renderDefaultFilterWidget(column, value, onChange) {
1365
1369
  }
1366
1370
  }
1367
1371
 
1372
+ // src/edit/widget-types.ts
1373
+ function editErrorId(rowId, columnId) {
1374
+ return `edit-error-${rowId}-${columnId}`;
1375
+ }
1376
+
1377
+ // src/edit/EditFieldError.tsx
1378
+ import { jsx as jsx15 } from "react/jsx-runtime";
1379
+ function EditFieldError({ id, message }) {
1380
+ return /* @__PURE__ */ jsx15("span", { id, className: "mt-0.5 block text-xs text-destructive", children: message });
1381
+ }
1382
+
1383
+ // src/edit/BooleanEditor.tsx
1384
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
1385
+ function toBoolean(value) {
1386
+ if (typeof value === "boolean") return value;
1387
+ if (typeof value === "string") return value.trim().toLowerCase() === "true";
1388
+ if (typeof value === "number") return value !== 0;
1389
+ return false;
1390
+ }
1391
+ function BooleanEditor({
1392
+ column,
1393
+ rowId,
1394
+ value,
1395
+ onChange,
1396
+ error,
1397
+ autoFocus
1398
+ }) {
1399
+ const errorId = editErrorId(rowId, column.id);
1400
+ return (
1401
+ // No `gap-*` here (unlike a plain flex stack) — `EditFieldError`'s own
1402
+ // `mt-0.5` already provides the same spacing every other editor gets;
1403
+ // adding both would double it for this one editor only.
1404
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center", children: [
1405
+ /* @__PURE__ */ jsx16(
1406
+ Checkbox,
1407
+ {
1408
+ "aria-label": `Edit ${column.header}`,
1409
+ "aria-invalid": error ? true : void 0,
1410
+ "aria-describedby": error ? errorId : void 0,
1411
+ "data-testid": `edit-${rowId}-${column.id}`,
1412
+ autoFocus,
1413
+ checked: toBoolean(value),
1414
+ onCheckedChange: (next) => onChange(next === true)
1415
+ }
1416
+ ),
1417
+ error && /* @__PURE__ */ jsx16(EditFieldError, { id: errorId, message: error })
1418
+ ] })
1419
+ );
1420
+ }
1421
+
1422
+ // src/edit/DateEditor.tsx
1423
+ import { format as formatDate, parseISO as parseISO4 } from "date-fns";
1424
+ import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
1425
+ function inputValueOf(value, columnType) {
1426
+ const date = toDate(value);
1427
+ if (!date) return "";
1428
+ return columnType === "datetime" ? formatDate(date, "yyyy-MM-dd'T'HH:mm:ss") : formatDate(date, "yyyy-MM-dd");
1429
+ }
1430
+ function DateEditor({
1431
+ column,
1432
+ rowId,
1433
+ value,
1434
+ onChange,
1435
+ error,
1436
+ autoFocus
1437
+ }) {
1438
+ const errorId = editErrorId(rowId, column.id);
1439
+ return /* @__PURE__ */ jsxs10("div", { children: [
1440
+ /* @__PURE__ */ jsx17(
1441
+ Input,
1442
+ {
1443
+ type: column.type === "datetime" ? "datetime-local" : "date",
1444
+ step: column.type === "datetime" ? 1 : void 0,
1445
+ className: "h-8",
1446
+ "aria-label": `Edit ${column.header}`,
1447
+ "aria-invalid": error ? true : void 0,
1448
+ "aria-describedby": error ? errorId : void 0,
1449
+ "data-testid": `edit-${rowId}-${column.id}`,
1450
+ autoFocus,
1451
+ value: inputValueOf(value, column.type),
1452
+ onChange: (event) => onChange(event.target.value === "" ? null : parseISO4(event.target.value))
1453
+ }
1454
+ ),
1455
+ error && /* @__PURE__ */ jsx17(EditFieldError, { id: errorId, message: error })
1456
+ ] });
1457
+ }
1458
+
1459
+ // src/edit/EnumEditor.tsx
1460
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1461
+ function EnumEditor({
1462
+ column,
1463
+ rowId,
1464
+ value,
1465
+ onChange,
1466
+ error,
1467
+ autoFocus
1468
+ }) {
1469
+ const errorId = editErrorId(rowId, column.id);
1470
+ return /* @__PURE__ */ jsxs11("div", { children: [
1471
+ /* @__PURE__ */ jsxs11(Select, { value: value === null || value === void 0 ? "" : String(value), onValueChange: onChange, children: [
1472
+ /* @__PURE__ */ jsx18(
1473
+ SelectTrigger,
1474
+ {
1475
+ className: "h-8",
1476
+ "aria-label": `Edit ${column.header}`,
1477
+ "aria-invalid": error ? true : void 0,
1478
+ "aria-describedby": error ? errorId : void 0,
1479
+ "data-testid": `edit-${rowId}-${column.id}`,
1480
+ autoFocus,
1481
+ children: /* @__PURE__ */ jsx18(SelectValue, {})
1482
+ }
1483
+ ),
1484
+ /* @__PURE__ */ jsx18(SelectContent, { children: column.options.map((option) => /* @__PURE__ */ jsx18(SelectItem, { value: option.value, children: option.label }, option.value)) })
1485
+ ] }),
1486
+ error && /* @__PURE__ */ jsx18(EditFieldError, { id: errorId, message: error })
1487
+ ] });
1488
+ }
1489
+
1490
+ // src/edit/NumberEditor.tsx
1491
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1492
+ function NumberEditor({
1493
+ column,
1494
+ rowId,
1495
+ value,
1496
+ onChange,
1497
+ error,
1498
+ autoFocus
1499
+ }) {
1500
+ const errorId = editErrorId(rowId, column.id);
1501
+ return /* @__PURE__ */ jsxs12("div", { children: [
1502
+ /* @__PURE__ */ jsx19(
1503
+ Input,
1504
+ {
1505
+ type: "number",
1506
+ className: "h-8",
1507
+ "aria-label": `Edit ${column.header}`,
1508
+ "aria-invalid": error ? true : void 0,
1509
+ "aria-describedby": error ? errorId : void 0,
1510
+ "data-testid": `edit-${rowId}-${column.id}`,
1511
+ autoFocus,
1512
+ value: value === null || value === void 0 ? "" : String(value),
1513
+ onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value))
1514
+ }
1515
+ ),
1516
+ error && /* @__PURE__ */ jsx19(EditFieldError, { id: errorId, message: error })
1517
+ ] });
1518
+ }
1519
+
1520
+ // src/edit/StringEditor.tsx
1521
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1522
+ function StringEditor({
1523
+ column,
1524
+ rowId,
1525
+ value,
1526
+ onChange,
1527
+ error,
1528
+ autoFocus
1529
+ }) {
1530
+ const errorId = editErrorId(rowId, column.id);
1531
+ return /* @__PURE__ */ jsxs13("div", { children: [
1532
+ /* @__PURE__ */ jsx20(
1533
+ Input,
1534
+ {
1535
+ className: "h-8",
1536
+ "aria-label": `Edit ${column.header}`,
1537
+ "aria-invalid": error ? true : void 0,
1538
+ "aria-describedby": error ? errorId : void 0,
1539
+ "data-testid": `edit-${rowId}-${column.id}`,
1540
+ autoFocus,
1541
+ value: value === null || value === void 0 ? "" : String(value),
1542
+ onChange: (event) => onChange(event.target.value)
1543
+ }
1544
+ ),
1545
+ error && /* @__PURE__ */ jsx20(EditFieldError, { id: errorId, message: error })
1546
+ ] });
1547
+ }
1548
+
1549
+ // src/edit/registry.tsx
1550
+ import { jsx as jsx21 } from "react/jsx-runtime";
1551
+ function renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus) {
1552
+ switch (column.type) {
1553
+ case "string":
1554
+ return /* @__PURE__ */ jsx21(StringEditor, { column, rowId, value, onChange, error, autoFocus });
1555
+ case "enum":
1556
+ return /* @__PURE__ */ jsx21(EnumEditor, { column, rowId, value, onChange, error, autoFocus });
1557
+ case "boolean":
1558
+ return /* @__PURE__ */ jsx21(BooleanEditor, { column, rowId, value, onChange, error, autoFocus });
1559
+ case "number":
1560
+ case "currency":
1561
+ return /* @__PURE__ */ jsx21(NumberEditor, { column, rowId, value, onChange, error, autoFocus });
1562
+ case "date":
1563
+ case "datetime":
1564
+ return /* @__PURE__ */ jsx21(DateEditor, { column, rowId, value, onChange, error, autoFocus });
1565
+ }
1566
+ }
1567
+
1368
1568
  // src/column-selector/ColumnSelector.tsx
1369
1569
  import { Columns3 } from "lucide-react";
1370
1570
  import { useEffect as useEffect4 } from "react";
@@ -1373,10 +1573,10 @@ import { useEffect as useEffect4 } from "react";
1373
1573
  import * as DialogPrimitive from "@radix-ui/react-dialog";
1374
1574
  import { X } from "lucide-react";
1375
1575
  import { forwardRef as forwardRef6 } from "react";
1376
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1576
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1377
1577
  var Dialog = DialogPrimitive.Root;
1378
1578
  var DialogTrigger = DialogPrimitive.Trigger;
1379
- var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(
1579
+ var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
1380
1580
  DialogPrimitive.Overlay,
1381
1581
  {
1382
1582
  ref,
@@ -1385,9 +1585,9 @@ var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ *
1385
1585
  }
1386
1586
  ));
1387
1587
  DialogOverlay.displayName = "DialogOverlay";
1388
- var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs9(DialogPrimitive.Portal, { children: [
1389
- /* @__PURE__ */ jsx15(DialogOverlay, {}),
1390
- /* @__PURE__ */ jsxs9(
1588
+ var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs14(DialogPrimitive.Portal, { children: [
1589
+ /* @__PURE__ */ jsx22(DialogOverlay, {}),
1590
+ /* @__PURE__ */ jsxs14(
1391
1591
  DialogPrimitive.Content,
1392
1592
  {
1393
1593
  ref,
@@ -1398,9 +1598,9 @@ var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @
1398
1598
  ...props,
1399
1599
  children: [
1400
1600
  children,
1401
- /* @__PURE__ */ jsxs9(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100", children: [
1402
- /* @__PURE__ */ jsx15(X, { className: "h-4 w-4" }),
1403
- /* @__PURE__ */ jsx15("span", { className: "sr-only", children: "Close" })
1601
+ /* @__PURE__ */ jsxs14(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100", children: [
1602
+ /* @__PURE__ */ jsx22(X, { className: "h-4 w-4" }),
1603
+ /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Close" })
1404
1604
  ] })
1405
1605
  ]
1406
1606
  }
@@ -1410,10 +1610,10 @@ DialogContent.displayName = "DialogContent";
1410
1610
  var DialogHeader = ({
1411
1611
  className,
1412
1612
  ...props
1413
- }) => /* @__PURE__ */ jsx15("div", { className: cn("flex flex-col gap-1.5", className), ...props });
1414
- var DialogTitle = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
1613
+ }) => /* @__PURE__ */ jsx22("div", { className: cn("flex flex-col gap-1.5", className), ...props });
1614
+ var DialogTitle = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
1415
1615
  DialogTitle.displayName = "DialogTitle";
1416
- var DialogDescription = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(
1616
+ var DialogDescription = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
1417
1617
  DialogPrimitive.Description,
1418
1618
  {
1419
1619
  ref,
@@ -1481,7 +1681,7 @@ function canHideGroup(columns, visibility, groupColumnIds) {
1481
1681
  }
1482
1682
 
1483
1683
  // src/column-selector/ColumnSelector.tsx
1484
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1684
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
1485
1685
  function ColumnSelector({
1486
1686
  columns,
1487
1687
  visibility,
@@ -1506,20 +1706,20 @@ function ColumnSelector({
1506
1706
  }
1507
1707
  const totalVisible = countVisible(columns, visibility);
1508
1708
  const groups = groupColumns(columns);
1509
- return /* @__PURE__ */ jsxs10(Dialog, { open, onOpenChange, children: [
1510
- /* @__PURE__ */ jsx16(DialogTrigger, { asChild: true, children: trigger ?? /* @__PURE__ */ jsx16(Button, { variant: "outline", size: "icon", "aria-label": "Choose columns", children: /* @__PURE__ */ jsx16(Columns3, { className: "h-4 w-4", "aria-hidden": true }) }) }),
1511
- /* @__PURE__ */ jsxs10(DialogContent, { className: "w-fit max-w-[calc(100vw-2rem)] sm:max-w-2xl", children: [
1512
- /* @__PURE__ */ jsx16(DialogHeader, { children: /* @__PURE__ */ jsx16(DialogTitle, { children: "Columns" }) }),
1513
- /* @__PURE__ */ jsx16("div", { className: "flex flex-wrap gap-x-8 gap-y-5", children: groups.map(({ group, columns: groupCols }) => /* @__PURE__ */ jsxs10("div", { className: "flex min-w-32 flex-col gap-1.5", children: [
1514
- group && /* @__PURE__ */ jsx16("span", { className: "border-b pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: group }),
1709
+ return /* @__PURE__ */ jsxs15(Dialog, { open, onOpenChange, children: [
1710
+ /* @__PURE__ */ jsx23(DialogTrigger, { asChild: true, children: trigger ?? /* @__PURE__ */ jsx23(Button, { variant: "outline", size: "icon", "aria-label": "Choose columns", children: /* @__PURE__ */ jsx23(Columns3, { className: "h-4 w-4", "aria-hidden": true }) }) }),
1711
+ /* @__PURE__ */ jsxs15(DialogContent, { className: "w-fit max-w-[calc(100vw-2rem)] sm:max-w-2xl", children: [
1712
+ /* @__PURE__ */ jsx23(DialogHeader, { children: /* @__PURE__ */ jsx23(DialogTitle, { children: "Columns" }) }),
1713
+ /* @__PURE__ */ jsx23("div", { className: "flex flex-wrap gap-x-8 gap-y-5", children: groups.map(({ group, columns: groupCols }) => /* @__PURE__ */ jsxs15("div", { className: "flex min-w-32 flex-col gap-1.5", children: [
1714
+ group && /* @__PURE__ */ jsx23("span", { className: "border-b pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: group }),
1515
1715
  groupCols.map((column) => {
1516
1716
  const visible = isColumnVisible(visibility, column.id);
1517
- return /* @__PURE__ */ jsxs10(
1717
+ return /* @__PURE__ */ jsxs15(
1518
1718
  "label",
1519
1719
  {
1520
1720
  className: "flex items-center gap-2 rounded-md px-1.5 py-1 text-sm hover:bg-accent/50 focus-within:bg-accent/50",
1521
1721
  children: [
1522
- /* @__PURE__ */ jsx16(
1722
+ /* @__PURE__ */ jsx23(
1523
1723
  Checkbox,
1524
1724
  {
1525
1725
  checked: visible,
@@ -1556,10 +1756,10 @@ import { useMemo as useMemo3 } from "react";
1556
1756
  // src/components/ui/dropdown-menu.tsx
1557
1757
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
1558
1758
  import { forwardRef as forwardRef7 } from "react";
1559
- import { jsx as jsx17 } from "react/jsx-runtime";
1759
+ import { jsx as jsx24 } from "react/jsx-runtime";
1560
1760
  var DropdownMenu = DropdownMenuPrimitive.Root;
1561
1761
  var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1562
- var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx17(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx17(
1762
+ var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
1563
1763
  DropdownMenuPrimitive.Content,
1564
1764
  {
1565
1765
  ref,
@@ -1572,7 +1772,7 @@ var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props },
1572
1772
  }
1573
1773
  ) }));
1574
1774
  DropdownMenuContent.displayName = "DropdownMenuContent";
1575
- var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /* @__PURE__ */ jsx17(
1775
+ var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /* @__PURE__ */ jsx24(
1576
1776
  DropdownMenuPrimitive.Item,
1577
1777
  {
1578
1778
  ref,
@@ -1585,7 +1785,7 @@ var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /*
1585
1785
  }
1586
1786
  ));
1587
1787
  DropdownMenuItem.displayName = "DropdownMenuItem";
1588
- var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(
1788
+ var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
1589
1789
  DropdownMenuPrimitive.Separator,
1590
1790
  {
1591
1791
  ref,
@@ -1594,7 +1794,7 @@ var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__
1594
1794
  }
1595
1795
  ));
1596
1796
  DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
1597
- var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(
1797
+ var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
1598
1798
  DropdownMenuPrimitive.Label,
1599
1799
  {
1600
1800
  ref,
@@ -1605,16 +1805,16 @@ var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE
1605
1805
  DropdownMenuLabel.displayName = "DropdownMenuLabel";
1606
1806
 
1607
1807
  // src/menu/ActionsMenu.tsx
1608
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1808
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
1609
1809
  function ActionsMenu({ items, ctx, triggerLabel }) {
1610
1810
  const resolved = useMemo3(
1611
1811
  () => resolveMenuItems(items, ctx),
1612
1812
  [items, ctx.row, ctx.selectedRows]
1613
1813
  );
1614
1814
  if (resolved.length === 0) return null;
1615
- return /* @__PURE__ */ jsxs11(DropdownMenu, { children: [
1616
- /* @__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 }) }) }),
1617
- /* @__PURE__ */ jsx18(DropdownMenuContent, { align: "end", children: resolved.map((item) => /* @__PURE__ */ jsx18(
1815
+ return /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
1816
+ /* @__PURE__ */ jsx25(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { variant: "ghost", size: "icon", "aria-label": triggerLabel, onClick: stopRowClick, children: /* @__PURE__ */ jsx25(MoreVertical, { className: "h-4 w-4", "aria-hidden": true }) }) }),
1817
+ /* @__PURE__ */ jsx25(DropdownMenuContent, { align: "end", children: resolved.map((item) => /* @__PURE__ */ jsx25(
1618
1818
  DropdownMenuItem,
1619
1819
  {
1620
1820
  danger: item.danger,
@@ -1632,7 +1832,7 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
1632
1832
  import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
1633
1833
  import { useVirtualizer } from "@tanstack/react-virtual";
1634
1834
  import { ChevronRight, Loader2 } from "lucide-react";
1635
- import { Fragment as Fragment2, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef5, useState as useState6 } from "react";
1835
+ import { Fragment as Fragment2, useEffect as useEffect7, useLayoutEffect, useMemo as useMemo6, useRef as useRef5, useState as useState6 } from "react";
1636
1836
 
1637
1837
  // src/lib/structuralColumns.ts
1638
1838
  var SELECTION_COLUMN_WIDTH = 44;
@@ -1802,7 +2002,7 @@ function useGridState(dataSource, initialState, externalState) {
1802
2002
  }
1803
2003
 
1804
2004
  // src/grid/DataGrid.tsx
1805
- import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2005
+ import { Fragment as Fragment3, jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
1806
2006
  var gridTableFeatures = tableFeatures({ columnSizingFeature, columnResizingFeature });
1807
2007
  var DEFAULT_COLUMN_SIZE = 150;
1808
2008
  var DETAIL_COLUMN_WIDTH = 44;
@@ -1833,15 +2033,77 @@ function computeHeaderRuns(columns) {
1833
2033
  }
1834
2034
  return runs;
1835
2035
  }
1836
- function toTanstackColumns(columns) {
2036
+ function toTanstackColumns(columns, editingCtxRef) {
1837
2037
  return columns.map((column) => ({
1838
2038
  id: column.id,
1839
2039
  header: column.header,
1840
2040
  size: column.width,
1841
2041
  accessorFn: (row) => getColumnValue(column, row),
1842
- cell: (info) => column.cell ? column.cell(info.getValue(), info.row.original) : defaultFormat(column, info.getValue())
2042
+ cell: (info) => {
2043
+ const row = info.row.original;
2044
+ const editingCtx = editingCtxRef.current;
2045
+ const staticContent = (value) => column.cell ? column.cell(value, row) : defaultFormat(column, value);
2046
+ if (editingCtx && isEditable(column, row)) {
2047
+ const rowId = editingCtx.getRowId(row);
2048
+ const pendingRow = editingCtx.pendingEdits.get(rowId);
2049
+ const value = pendingRow?.values.has(column.id) ? pendingRow.values.get(column.id) : info.getValue();
2050
+ if (editingCtx.activeRowId === rowId) {
2051
+ const error = editingCtx.editErrors.get(rowId)?.get(column.id);
2052
+ const autoFocus = editingCtx.autoFocusTarget?.rowId === rowId && editingCtx.autoFocusTarget.columnId === column.id;
2053
+ const onChange = (next) => editingCtx.onEdit(column, row, next);
2054
+ const editor = column.renderEditCell ? column.renderEditCell(value, row, onChange, error, autoFocus) : renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus);
2055
+ return /* @__PURE__ */ jsx26(
2056
+ "div",
2057
+ {
2058
+ onKeyDown: (event) => {
2059
+ if (event.key !== "Escape") return;
2060
+ if (!event.currentTarget.contains(event.target)) return;
2061
+ event.stopPropagation();
2062
+ editingCtx.onEdit(column, row, getColumnValue(column, row));
2063
+ },
2064
+ children: editor
2065
+ }
2066
+ );
2067
+ }
2068
+ return /* @__PURE__ */ jsx26(
2069
+ "span",
2070
+ {
2071
+ role: "button",
2072
+ tabIndex: 0,
2073
+ "data-testid": `cell-${rowId}-${column.id}`,
2074
+ className: "block w-full cursor-text",
2075
+ onClick: (event) => {
2076
+ stopRowClick(event);
2077
+ editingCtx.onActivateRow(rowId, column.id);
2078
+ },
2079
+ onKeyDown: (event) => {
2080
+ if (event.key !== "Enter" && event.key !== " ") return;
2081
+ event.preventDefault();
2082
+ stopRowClick(event);
2083
+ editingCtx.onActivateRow(rowId, column.id);
2084
+ },
2085
+ children: staticContent(value)
2086
+ }
2087
+ );
2088
+ }
2089
+ return staticContent(info.getValue());
2090
+ }
1843
2091
  }));
1844
2092
  }
2093
+ function editValuesEqual(a, b) {
2094
+ if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
2095
+ return a === b;
2096
+ }
2097
+ function resolveEditLabel(label, changedRowCount, fallback) {
2098
+ if (label === void 0) return fallback(changedRowCount);
2099
+ return typeof label === "function" ? label(changedRowCount) : label;
2100
+ }
2101
+ function describeErrorRows(editErrors) {
2102
+ const rowIds = [...editErrors.keys()];
2103
+ const shown = rowIds.slice(0, 3);
2104
+ const suffix = rowIds.length > shown.length ? `, and ${rowIds.length - shown.length} more` : "";
2105
+ return `row${rowIds.length === 1 ? "" : "s"} ${shown.join(", ")}${suffix}`;
2106
+ }
1845
2107
  function DataGrid({
1846
2108
  columns,
1847
2109
  dataSource,
@@ -1870,7 +2132,8 @@ function DataGrid({
1870
2132
  defaultGroupsExpanded = true,
1871
2133
  expandedGroups: controlledExpandedGroups,
1872
2134
  onExpandedGroupsChange,
1873
- zebra = true
2135
+ zebra = true,
2136
+ editing
1874
2137
  }) {
1875
2138
  const { state, filtersByColumn, setColumnFilter, toggleSort, setPage } = useGridState(
1876
2139
  dataSource,
@@ -1910,6 +2173,102 @@ function DataGrid({
1910
2173
  function toggleGroupExpanded(key) {
1911
2174
  updateExpandedGroups({ ...expandedGroupsState, [key]: !isGroupExpanded(key) });
1912
2175
  }
2176
+ const [pendingEdits, setPendingEdits] = useState6(/* @__PURE__ */ new Map());
2177
+ const [editErrors, setEditErrors] = useState6(/* @__PURE__ */ new Map());
2178
+ const hasEditErrors = editErrors.size > 0;
2179
+ const [activeRowId, setActiveRowId] = useState6(null);
2180
+ const [autoFocusTarget, setAutoFocusTarget] = useState6(null);
2181
+ function activateRow(rowId, columnId) {
2182
+ setActiveRowId(rowId);
2183
+ setAutoFocusTarget({ rowId, columnId });
2184
+ }
2185
+ useEffect7(() => {
2186
+ if (autoFocusTarget) setAutoFocusTarget(null);
2187
+ }, [autoFocusTarget]);
2188
+ function commitEdit(column, row, value) {
2189
+ const rowId = getRowId(row);
2190
+ const baseline = getColumnValue(column, row);
2191
+ setPendingEdits((prev) => {
2192
+ const next = new Map(prev);
2193
+ const values = new Map(next.get(rowId)?.values);
2194
+ if (editValuesEqual(value, baseline)) values.delete(column.id);
2195
+ else values.set(column.id, value);
2196
+ if (values.size === 0) next.delete(rowId);
2197
+ else next.set(rowId, { row, values });
2198
+ return next;
2199
+ });
2200
+ const message = column.validateEdit?.(value, row);
2201
+ setEditErrors((prev) => {
2202
+ const next = new Map(prev);
2203
+ const rowErrors = new Map(next.get(rowId));
2204
+ if (message) rowErrors.set(column.id, message);
2205
+ else rowErrors.delete(column.id);
2206
+ if (rowErrors.size === 0) next.delete(rowId);
2207
+ else next.set(rowId, rowErrors);
2208
+ return next;
2209
+ });
2210
+ }
2211
+ async function handleSaveEdits() {
2212
+ if (!editing || pendingEdits.size === 0) return;
2213
+ const snapshot = pendingEdits;
2214
+ const edited = [...snapshot.entries()].map(([rowId, entry]) => ({
2215
+ rowId,
2216
+ row: entry.row,
2217
+ values: Object.fromEntries(entry.values)
2218
+ }));
2219
+ try {
2220
+ await editing.onSave(edited);
2221
+ } catch {
2222
+ return;
2223
+ }
2224
+ const snapshotRowIds = new Set(snapshot.keys());
2225
+ const survivedRowIds = /* @__PURE__ */ new Set();
2226
+ const clearedErrorKeys = [];
2227
+ setPendingEdits((prev) => {
2228
+ const next = new Map(prev);
2229
+ for (const [rowId, snapshotEntry] of snapshot) {
2230
+ const current = next.get(rowId);
2231
+ if (!current) continue;
2232
+ const values = new Map(current.values);
2233
+ for (const [columnId, snapshotValue] of snapshotEntry.values) {
2234
+ if (values.has(columnId) && editValuesEqual(values.get(columnId), snapshotValue)) {
2235
+ values.delete(columnId);
2236
+ clearedErrorKeys.push({ rowId, columnId });
2237
+ }
2238
+ }
2239
+ if (values.size === 0) next.delete(rowId);
2240
+ else {
2241
+ next.set(rowId, { row: current.row, values });
2242
+ survivedRowIds.add(rowId);
2243
+ }
2244
+ }
2245
+ return next;
2246
+ });
2247
+ setEditErrors((prev) => {
2248
+ if (clearedErrorKeys.length === 0) return prev;
2249
+ const next = new Map(prev);
2250
+ for (const { rowId, columnId } of clearedErrorKeys) {
2251
+ const rowErrors = next.get(rowId);
2252
+ if (!rowErrors) continue;
2253
+ const nextRowErrors = new Map(rowErrors);
2254
+ nextRowErrors.delete(columnId);
2255
+ if (nextRowErrors.size === 0) next.delete(rowId);
2256
+ else next.set(rowId, nextRowErrors);
2257
+ }
2258
+ return next;
2259
+ });
2260
+ setActiveRowId(
2261
+ (prev) => prev !== null && snapshotRowIds.has(prev) && !survivedRowIds.has(prev) ? null : prev
2262
+ );
2263
+ }
2264
+ function handleDiscardEdits() {
2265
+ setPendingEdits(/* @__PURE__ */ new Map());
2266
+ setEditErrors(/* @__PURE__ */ new Map());
2267
+ setActiveRowId(null);
2268
+ editing?.onDiscard?.();
2269
+ }
2270
+ const editingCtxRef = useRef5(void 0);
2271
+ editingCtxRef.current = editing ? { pendingEdits, editErrors, activeRowId, autoFocusTarget, getRowId, onEdit: commitEdit, onActivateRow: activateRow } : void 0;
1913
2272
  const visibleColumns = useMemo6(
1914
2273
  () => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
1915
2274
  [columns, columnVisibility]
@@ -1938,7 +2297,7 @@ function DataGrid({
1938
2297
  }
1939
2298
  updateSelectedIds(next);
1940
2299
  }
1941
- const tanstackColumns = useMemo6(() => toTanstackColumns(visibleColumns), [visibleColumns]);
2300
+ const tanstackColumns = useMemo6(() => toTanstackColumns(visibleColumns, editingCtxRef), [visibleColumns]);
1942
2301
  const columnById = useMemo6(() => {
1943
2302
  const map = /* @__PURE__ */ new Map();
1944
2303
  for (const column of visibleColumns) map.set(column.id, column);
@@ -2065,6 +2424,18 @@ function DataGrid({
2065
2424
  () => groupBy ? groupRows(tableRows, (row) => groupBy(row.original)) : void 0,
2066
2425
  [tableRows, groupBy]
2067
2426
  );
2427
+ const theadRef = useRef5(null);
2428
+ const [groupHeaderTop, setGroupHeaderTop] = useState6(0);
2429
+ useLayoutEffect(() => {
2430
+ if (!groupBy) return;
2431
+ const theadEl = theadRef.current;
2432
+ if (!theadEl) return;
2433
+ const updateHeight = () => setGroupHeaderTop(theadEl.getBoundingClientRect().height);
2434
+ updateHeight();
2435
+ const observer = new ResizeObserver(updateHeight);
2436
+ observer.observe(theadEl);
2437
+ return () => observer.disconnect();
2438
+ }, [groupBy]);
2068
2439
  const scrollRef = useRef5(null);
2069
2440
  const virtualizer = useVirtualizer({
2070
2441
  count: tableRows.length,
@@ -2091,20 +2462,20 @@ function DataGrid({
2091
2462
  const rowProps = getRowProps?.(row.original);
2092
2463
  const rowTestId = getRowTestId?.(row.original) ?? `row-${row.id}`;
2093
2464
  const isOddRow = zebra && row.index % 2 === 1;
2094
- return /* @__PURE__ */ jsxs12("tbody", { ref: measureRef, "data-index": row.index, children: [
2095
- /* @__PURE__ */ jsxs12(
2465
+ return /* @__PURE__ */ jsxs17("tbody", { ref: measureRef, "data-index": row.index, children: [
2466
+ /* @__PURE__ */ jsxs17(
2096
2467
  "tr",
2097
2468
  {
2098
2469
  ...rowProps,
2099
2470
  "data-testid": rowTestId,
2100
2471
  className: rowProps?.className ? cn("divide-x divide-border", rowProps.className, isOddRow && "bg-foreground/5") : `divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
2101
2472
  children: [
2102
- showDetailColumn && /* @__PURE__ */ jsx19(
2473
+ showDetailColumn && /* @__PURE__ */ jsx26(
2103
2474
  "td",
2104
2475
  {
2105
2476
  className: isOddRow ? detailCellProps.classNameOdd : detailCellProps.className,
2106
2477
  style: detailCellProps.style,
2107
- children: /* @__PURE__ */ jsx19(
2478
+ children: /* @__PURE__ */ jsx26(
2108
2479
  Button,
2109
2480
  {
2110
2481
  type: "button",
@@ -2116,7 +2487,7 @@ function DataGrid({
2116
2487
  stopRowClick(event);
2117
2488
  toggleRowExpanded(row.id);
2118
2489
  },
2119
- children: /* @__PURE__ */ jsx19(
2490
+ children: /* @__PURE__ */ jsx26(
2120
2491
  ChevronRight,
2121
2492
  {
2122
2493
  className: `h-4 w-4 transition-transform${isExpanded ? " rotate-90" : ""}`,
@@ -2127,12 +2498,12 @@ function DataGrid({
2127
2498
  )
2128
2499
  }
2129
2500
  ),
2130
- showSelectionColumn && /* @__PURE__ */ jsx19(
2501
+ showSelectionColumn && /* @__PURE__ */ jsx26(
2131
2502
  "td",
2132
2503
  {
2133
2504
  className: isOddRow ? selectionCellProps.classNameOdd : selectionCellProps.className,
2134
2505
  style: selectionCellProps.style,
2135
- children: /* @__PURE__ */ jsx19(
2506
+ children: /* @__PURE__ */ jsx26(
2136
2507
  "input",
2137
2508
  {
2138
2509
  type: "checkbox",
@@ -2146,45 +2517,56 @@ function DataGrid({
2146
2517
  ),
2147
2518
  row.getAllCells().map((cell) => {
2148
2519
  const cellProps = bodyCellPropsByColumn.get(cell.column.id);
2149
- return /* @__PURE__ */ jsx19("td", { style: cellProps?.style, className: cellProps?.className ?? BODY_TD_BASE_CLASS, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
2520
+ return /* @__PURE__ */ jsx26("td", { style: cellProps?.style, className: cellProps?.className ?? BODY_TD_BASE_CLASS, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
2150
2521
  }),
2151
- showRowActionsColumn && rowActions && /* @__PURE__ */ jsx19(
2522
+ showRowActionsColumn && rowActions && /* @__PURE__ */ jsx26(
2152
2523
  "td",
2153
2524
  {
2154
2525
  className: isOddRow ? rowActionsCellProps.classNameOdd : rowActionsCellProps.className,
2155
2526
  style: rowActionsCellProps.style,
2156
- children: /* @__PURE__ */ jsx19(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` })
2527
+ children: /* @__PURE__ */ jsx26(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` })
2157
2528
  }
2158
2529
  )
2159
2530
  ]
2160
2531
  }
2161
2532
  ),
2162
- showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */ jsx19("tr", { "data-testid": `${rowTestId}-detail`, children: /* @__PURE__ */ jsx19("td", { colSpan: totalColumnCount, className: "border-b border-border p-2", children: renderDetail(row.original) }) })
2533
+ showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */ jsx26("tr", { "data-testid": `${rowTestId}-detail`, children: /* @__PURE__ */ jsx26("td", { colSpan: totalColumnCount, className: "border-b border-border p-2", children: renderDetail(row.original) }) })
2163
2534
  ] }, row.id);
2164
2535
  }
2165
2536
  function renderGroupedBucket(bucket) {
2166
2537
  const expanded = isGroupExpanded(bucket.key);
2167
2538
  const originalRows = bucket.items.map((row) => row.original);
2168
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
2169
- /* @__PURE__ */ jsx19("tbody", { children: /* @__PURE__ */ jsx19("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx19("td", { colSpan: totalColumnCount, className: "border-b bg-muted/50 p-2 font-medium", children: /* @__PURE__ */ jsxs12(
2170
- "button",
2539
+ return /* @__PURE__ */ jsxs17(Fragment2, { children: [
2540
+ /* @__PURE__ */ jsx26("tbody", { children: /* @__PURE__ */ jsx26("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx26(
2541
+ "td",
2171
2542
  {
2172
- type: "button",
2173
- className: "flex w-full items-center gap-1 text-left",
2174
- onClick: () => toggleGroupExpanded(bucket.key),
2175
- "aria-expanded": expanded,
2176
- children: [
2177
- /* @__PURE__ */ jsx19(
2178
- ChevronRight,
2179
- {
2180
- className: `h-4 w-4 shrink-0 transition-transform${expanded ? " rotate-90" : ""}`,
2181
- "aria-hidden": true
2182
- }
2183
- ),
2184
- renderGroupHeader ? renderGroupHeader(bucket.key, originalRows, expanded) : `${bucket.key} (${originalRows.length})`
2185
- ]
2543
+ colSpan: totalColumnCount,
2544
+ className: cn(
2545
+ "sticky z-20 border-b p-2 font-medium",
2546
+ zebra ? "bg-muted" : "bg-background"
2547
+ ),
2548
+ style: { top: groupHeaderTop },
2549
+ children: /* @__PURE__ */ jsxs17(
2550
+ "button",
2551
+ {
2552
+ type: "button",
2553
+ className: "flex w-full items-center gap-1 text-left",
2554
+ onClick: () => toggleGroupExpanded(bucket.key),
2555
+ "aria-expanded": expanded,
2556
+ children: [
2557
+ /* @__PURE__ */ jsx26(
2558
+ ChevronRight,
2559
+ {
2560
+ className: `h-4 w-4 shrink-0 transition-transform${expanded ? " rotate-90" : ""}`,
2561
+ "aria-hidden": true
2562
+ }
2563
+ ),
2564
+ renderGroupHeader ? renderGroupHeader(bucket.key, originalRows, expanded) : `${bucket.key} (${originalRows.length})`
2565
+ ]
2566
+ }
2567
+ )
2186
2568
  }
2187
- ) }) }) }),
2569
+ ) }) }),
2188
2570
  expanded && bucket.items.map((row) => renderRow(row))
2189
2571
  ] }, `group-${bucket.key}`);
2190
2572
  }
@@ -2201,32 +2583,81 @@ function DataGrid({
2201
2583
  // containers (that one scrolling vertically, this component's own
2202
2584
  // `overflow-x-auto` div scrolling horizontally) fighting over which one
2203
2585
  // a sticky header/pinned column is actually stuck relative to.
2204
- /* @__PURE__ */ jsxs12("div", { className: "flex h-full min-h-0 flex-col gap-2", "data-testid": "datagrid", children: [
2205
- showSelectionColumn && headerActions && /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
2206
- /* @__PURE__ */ jsxs12("span", { children: [
2586
+ /* @__PURE__ */ jsxs17("div", { className: "flex h-full min-h-0 flex-col gap-2", "data-testid": "datagrid", children: [
2587
+ editing && pendingEdits.size > 0 && /* @__PURE__ */ jsxs17(
2588
+ "div",
2589
+ {
2590
+ "data-testid": "datagrid-edit-bar",
2591
+ className: "flex shrink-0 flex-wrap items-center justify-between gap-2 rounded-md border bg-muted/50 px-3 py-2 text-sm",
2592
+ children: [
2593
+ /* @__PURE__ */ jsxs17("span", { "aria-live": "polite", children: [
2594
+ pendingEdits.size,
2595
+ " row",
2596
+ pendingEdits.size === 1 ? "" : "s",
2597
+ " changed",
2598
+ hasEditErrors && /* @__PURE__ */ jsxs17("span", { className: "ml-2 text-destructive", children: [
2599
+ "Fix the highlighted errors before saving (",
2600
+ describeErrorRows(editErrors),
2601
+ ")."
2602
+ ] })
2603
+ ] }),
2604
+ /* @__PURE__ */ jsxs17("div", { className: "flex gap-2", children: [
2605
+ /* @__PURE__ */ jsx26(
2606
+ Button,
2607
+ {
2608
+ type: "button",
2609
+ variant: "outline",
2610
+ size: "sm",
2611
+ "data-testid": "datagrid-discard-edits",
2612
+ disabled: editing.saving,
2613
+ onClick: handleDiscardEdits,
2614
+ children: resolveEditLabel(editing.discardLabel, pendingEdits.size, () => "Discard")
2615
+ }
2616
+ ),
2617
+ /* @__PURE__ */ jsx26(
2618
+ Button,
2619
+ {
2620
+ type: "button",
2621
+ size: "sm",
2622
+ "data-testid": "datagrid-save-edits",
2623
+ disabled: editing.saving || hasEditErrors,
2624
+ onClick: () => void handleSaveEdits(),
2625
+ children: resolveEditLabel(
2626
+ editing.saveLabel,
2627
+ pendingEdits.size,
2628
+ (count) => `Save ${count} change${count === 1 ? "" : "s"}`
2629
+ )
2630
+ }
2631
+ )
2632
+ ] })
2633
+ ]
2634
+ }
2635
+ ),
2636
+ showSelectionColumn && headerActions && /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
2637
+ /* @__PURE__ */ jsxs17("span", { children: [
2207
2638
  selectedRows.length,
2208
2639
  " selected"
2209
2640
  ] }),
2210
- /* @__PURE__ */ jsx19(ActionsMenu, { items: headerActions, ctx: { selectedRows }, triggerLabel: "Bulk actions" })
2641
+ /* @__PURE__ */ jsx26(ActionsMenu, { items: headerActions, ctx: { selectedRows }, triggerLabel: "Bulk actions" })
2211
2642
  ] }),
2212
- /* @__PURE__ */ jsxs12("div", { className: "relative min-h-0 flex-1", children: [
2213
- loading && /* @__PURE__ */ jsx19(
2643
+ /* @__PURE__ */ jsxs17("div", { className: "relative min-h-0 flex-1", children: [
2644
+ loading && /* @__PURE__ */ jsx26(
2214
2645
  "div",
2215
2646
  {
2216
2647
  "data-testid": "datagrid-loading-overlay",
2217
2648
  className: "absolute inset-0 z-30 flex items-center justify-center bg-background/60",
2218
- children: /* @__PURE__ */ jsx19(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground", "aria-hidden": true })
2649
+ children: /* @__PURE__ */ jsx26(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground", "aria-hidden": true })
2219
2650
  }
2220
2651
  ),
2221
- /* @__PURE__ */ jsx19(
2652
+ /* @__PURE__ */ jsx26(
2222
2653
  "div",
2223
2654
  {
2224
2655
  ref: scrollRef,
2225
2656
  "data-testid": testId,
2226
2657
  className: "h-full overflow-auto rounded-md border",
2227
2658
  style: shouldVirtualize ? { maxHeight: virtualize?.maxBodyHeight ?? 480 } : void 0,
2228
- children: /* @__PURE__ */ jsxs12("table", { className: cn("w-full border-collapse text-sm", enableColumnResizing && "table-fixed"), children: [
2229
- /* @__PURE__ */ jsxs12("thead", { className: "bg-muted", children: [
2659
+ children: /* @__PURE__ */ jsxs17("table", { className: cn("w-full border-collapse text-sm", enableColumnResizing && "table-fixed"), children: [
2660
+ /* @__PURE__ */ jsxs17("thead", { ref: theadRef, className: "bg-muted", children: [
2230
2661
  table.getHeaderGroups().map((headerGroup) => {
2231
2662
  const headerById = new Map(headerGroup.headers.map((header) => [header.id, header]));
2232
2663
  function renderLeafHeaderCell(column, rowSpan) {
@@ -2237,9 +2668,9 @@ function DataGrid({
2237
2668
  const filterable = isFilterable(column) && column.filterDisplay !== "row";
2238
2669
  const cellProps = leafHeaderCellPropsByColumn.get(column.id);
2239
2670
  const headerContent = column.renderHeader ? column.renderHeader(column) : column.header;
2240
- return /* @__PURE__ */ jsxs12("th", { rowSpan, style: cellProps?.style, className: cellProps?.className, children: [
2241
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
2242
- sortable ? /* @__PURE__ */ jsxs12(
2671
+ return /* @__PURE__ */ jsxs17("th", { rowSpan, style: cellProps?.style, className: cellProps?.className, children: [
2672
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
2673
+ sortable ? /* @__PURE__ */ jsxs17(
2243
2674
  "button",
2244
2675
  {
2245
2676
  type: "button",
@@ -2247,8 +2678,8 @@ function DataGrid({
2247
2678
  onClick: (event) => toggleSort(column.id, enableMultiSort && event.shiftKey, column.sortDescFirst === true),
2248
2679
  children: [
2249
2680
  headerContent,
2250
- sortEntry?.dir === "asc" && /* @__PURE__ */ jsx19(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
2251
- sortEntry?.dir === "desc" && /* @__PURE__ */ jsx19(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
2681
+ sortEntry?.dir === "asc" && /* @__PURE__ */ jsx26(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
2682
+ sortEntry?.dir === "desc" && /* @__PURE__ */ jsx26(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
2252
2683
  ]
2253
2684
  }
2254
2685
  ) : (
@@ -2257,10 +2688,10 @@ function DataGrid({
2257
2688
  // silently breaking any interactive content a column's own `renderHeader`
2258
2689
  // embeds directly (bare filter inputs, "select/reject all" buttons) —
2259
2690
  // clicks never reach them at all, even though nothing looks wrong visually.
2260
- /* @__PURE__ */ jsx19("div", { className: "flex items-center gap-1 px-1", children: headerContent })
2691
+ /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-1 px-1", children: headerContent })
2261
2692
  ),
2262
- filterable && /* @__PURE__ */ jsxs12(Popover, { children: [
2263
- /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(Button, { variant: "ghost", size: "icon", "aria-label": `Filter ${column.header}`, children: /* @__PURE__ */ jsx19(
2693
+ filterable && /* @__PURE__ */ jsxs17(Popover, { children: [
2694
+ /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "icon", "aria-label": `Filter ${column.header}`, children: /* @__PURE__ */ jsx26(
2264
2695
  FunnelIcon7,
2265
2696
  {
2266
2697
  className: cn(
@@ -2270,10 +2701,10 @@ function DataGrid({
2270
2701
  "aria-hidden": true
2271
2702
  }
2272
2703
  ) }) }),
2273
- /* @__PURE__ */ jsx19(PopoverContent, { children: renderFilterWidget(column) })
2704
+ /* @__PURE__ */ jsx26(PopoverContent, { children: renderFilterWidget(column) })
2274
2705
  ] })
2275
2706
  ] }),
2276
- enableColumnResizing && /* @__PURE__ */ jsx19(
2707
+ enableColumnResizing && /* @__PURE__ */ jsx26(
2277
2708
  "div",
2278
2709
  {
2279
2710
  "data-testid": `resize-handle-${column.id}`,
@@ -2284,9 +2715,9 @@ function DataGrid({
2284
2715
  )
2285
2716
  ] }, header.id);
2286
2717
  }
2287
- return /* @__PURE__ */ jsxs12(Fragment2, { children: [
2288
- hasHeaderGroups && /* @__PURE__ */ jsxs12("tr", { "data-testid": "header-group-row", className: "divide-x divide-border", children: [
2289
- showDetailColumn && /* @__PURE__ */ jsx19(
2718
+ return /* @__PURE__ */ jsxs17(Fragment2, { children: [
2719
+ hasHeaderGroups && /* @__PURE__ */ jsxs17("tr", { "data-testid": "header-group-row", className: "divide-x divide-border", children: [
2720
+ showDetailColumn && /* @__PURE__ */ jsx26(
2290
2721
  "th",
2291
2722
  {
2292
2723
  rowSpan: 2,
@@ -2295,13 +2726,13 @@ function DataGrid({
2295
2726
  "aria-hidden": true
2296
2727
  }
2297
2728
  ),
2298
- showSelectionColumn && /* @__PURE__ */ jsx19(
2729
+ showSelectionColumn && /* @__PURE__ */ jsx26(
2299
2730
  "th",
2300
2731
  {
2301
2732
  rowSpan: 2,
2302
2733
  className: selectionHeaderCellProps.className,
2303
2734
  style: selectionHeaderCellProps.style,
2304
- children: /* @__PURE__ */ jsx19(
2735
+ children: /* @__PURE__ */ jsx26(
2305
2736
  "input",
2306
2737
  {
2307
2738
  type: "checkbox",
@@ -2313,7 +2744,7 @@ function DataGrid({
2313
2744
  }
2314
2745
  ),
2315
2746
  headerRuns.map(
2316
- (run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */ jsx19(
2747
+ (run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */ jsx26(
2317
2748
  "th",
2318
2749
  {
2319
2750
  colSpan: run.columns.length,
@@ -2323,7 +2754,7 @@ function DataGrid({
2323
2754
  `group-${run.label}-${run.columns[0].id}`
2324
2755
  )
2325
2756
  ),
2326
- showRowActionsColumn && /* @__PURE__ */ jsx19(
2757
+ showRowActionsColumn && /* @__PURE__ */ jsx26(
2327
2758
  "th",
2328
2759
  {
2329
2760
  rowSpan: 2,
@@ -2333,8 +2764,8 @@ function DataGrid({
2333
2764
  }
2334
2765
  )
2335
2766
  ] }, `${headerGroup.id}-groups`),
2336
- /* @__PURE__ */ jsxs12("tr", { className: "divide-x divide-border", children: [
2337
- !hasHeaderGroups && showDetailColumn && /* @__PURE__ */ jsx19(
2767
+ /* @__PURE__ */ jsxs17("tr", { className: "divide-x divide-border", children: [
2768
+ !hasHeaderGroups && showDetailColumn && /* @__PURE__ */ jsx26(
2338
2769
  "th",
2339
2770
  {
2340
2771
  className: detailHeaderCellProps.className,
@@ -2342,12 +2773,12 @@ function DataGrid({
2342
2773
  "aria-hidden": true
2343
2774
  }
2344
2775
  ),
2345
- !hasHeaderGroups && showSelectionColumn && /* @__PURE__ */ jsx19(
2776
+ !hasHeaderGroups && showSelectionColumn && /* @__PURE__ */ jsx26(
2346
2777
  "th",
2347
2778
  {
2348
2779
  className: selectionHeaderCellProps.className,
2349
2780
  style: selectionHeaderCellProps.style,
2350
- children: /* @__PURE__ */ jsx19(
2781
+ children: /* @__PURE__ */ jsx26(
2351
2782
  "input",
2352
2783
  {
2353
2784
  type: "checkbox",
@@ -2363,7 +2794,7 @@ function DataGrid({
2363
2794
  if (!column || hasHeaderGroups && !column.headerGroup) return null;
2364
2795
  return renderLeafHeaderCell(column);
2365
2796
  }),
2366
- !hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */ jsx19(
2797
+ !hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */ jsx26(
2367
2798
  "th",
2368
2799
  {
2369
2800
  className: rowActionsHeaderCellProps.className,
@@ -2374,9 +2805,9 @@ function DataGrid({
2374
2805
  ] }, headerGroup.id)
2375
2806
  ] }, headerGroup.id);
2376
2807
  }),
2377
- hasFilterRow && /* @__PURE__ */ jsxs12("tr", { "data-testid": "filter-row", className: "divide-x divide-border", children: [
2378
- showDetailColumn && /* @__PURE__ */ jsx19("th", { className: detailHeaderCellProps.className, style: detailHeaderCellProps.style }),
2379
- showSelectionColumn && /* @__PURE__ */ jsx19(
2808
+ hasFilterRow && /* @__PURE__ */ jsxs17("tr", { "data-testid": "filter-row", className: "divide-x divide-border", children: [
2809
+ showDetailColumn && /* @__PURE__ */ jsx26("th", { className: detailHeaderCellProps.className, style: detailHeaderCellProps.style }),
2810
+ showSelectionColumn && /* @__PURE__ */ jsx26(
2380
2811
  "th",
2381
2812
  {
2382
2813
  className: selectionHeaderCellProps.className,
@@ -2385,9 +2816,9 @@ function DataGrid({
2385
2816
  ),
2386
2817
  visibleColumns.map((column) => {
2387
2818
  const cellProps = filterHeaderCellPropsByColumn.get(column.id);
2388
- return /* @__PURE__ */ jsx19("th", { style: cellProps?.style, className: cellProps?.className, children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null }, column.id);
2819
+ return /* @__PURE__ */ jsx26("th", { style: cellProps?.style, className: cellProps?.className, children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null }, column.id);
2389
2820
  }),
2390
- showRowActionsColumn && /* @__PURE__ */ jsx19(
2821
+ showRowActionsColumn && /* @__PURE__ */ jsx26(
2391
2822
  "th",
2392
2823
  {
2393
2824
  className: rowActionsHeaderCellProps.className,
@@ -2396,19 +2827,19 @@ function DataGrid({
2396
2827
  )
2397
2828
  ] })
2398
2829
  ] }),
2399
- rows.length === 0 ? /* @__PURE__ */ jsx19("tbody", { children: /* @__PURE__ */ jsx19("tr", { children: /* @__PURE__ */ jsx19("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? "Loading..." : "No results." }) }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
2400
- paddingTop > 0 && /* @__PURE__ */ jsx19("tbody", { children: /* @__PURE__ */ jsx19("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx19("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }) }),
2830
+ rows.length === 0 ? /* @__PURE__ */ jsx26("tbody", { children: /* @__PURE__ */ jsx26("tr", { children: /* @__PURE__ */ jsx26("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? "Loading..." : "No results." }) }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs17(Fragment3, { children: [
2831
+ paddingTop > 0 && /* @__PURE__ */ jsx26("tbody", { children: /* @__PURE__ */ jsx26("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx26("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }) }),
2401
2832
  virtualItems.map(
2402
2833
  (virtualItem) => renderRow(tableRows[virtualItem.index], (el) => virtualizer.measureElement(el))
2403
2834
  ),
2404
- paddingBottom > 0 && /* @__PURE__ */ jsx19("tbody", { children: /* @__PURE__ */ jsx19("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx19("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingBottom } }) }) })
2835
+ paddingBottom > 0 && /* @__PURE__ */ jsx26("tbody", { children: /* @__PURE__ */ jsx26("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx26("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingBottom } }) }) })
2405
2836
  ] }) : groupedBuckets ? groupedBuckets.map((bucket) => renderGroupedBucket(bucket)) : tableRows.map((row) => renderRow(row))
2406
2837
  ] })
2407
2838
  }
2408
2839
  )
2409
2840
  ] }),
2410
- showPagination && /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
2411
- /* @__PURE__ */ jsxs12("span", { children: [
2841
+ showPagination && /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
2842
+ /* @__PURE__ */ jsxs17("span", { children: [
2412
2843
  "Page ",
2413
2844
  state.page + 1,
2414
2845
  " of ",
@@ -2419,8 +2850,8 @@ function DataGrid({
2419
2850
  rowCount === 1 ? "" : "s",
2420
2851
  ")"
2421
2852
  ] }),
2422
- /* @__PURE__ */ jsxs12("div", { className: "flex gap-2", children: [
2423
- /* @__PURE__ */ jsx19(
2853
+ /* @__PURE__ */ jsxs17("div", { className: "flex gap-2", children: [
2854
+ /* @__PURE__ */ jsx26(
2424
2855
  Button,
2425
2856
  {
2426
2857
  variant: "outline",
@@ -2430,7 +2861,7 @@ function DataGrid({
2430
2861
  children: "Previous"
2431
2862
  }
2432
2863
  ),
2433
- /* @__PURE__ */ jsx19(
2864
+ /* @__PURE__ */ jsx26(
2434
2865
  Button,
2435
2866
  {
2436
2867
  variant: "outline",
@@ -2611,7 +3042,7 @@ function useTreeState({
2611
3042
  }
2612
3043
 
2613
3044
  // src/tree/TreeDataGrid.tsx
2614
- import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
3045
+ import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
2615
3046
  var EMPTY_SELECTED_IDS = /* @__PURE__ */ new Set();
2616
3047
  var UNCHECKED_STATE = { checked: false, indeterminate: false };
2617
3048
  function renderCell(column, row) {
@@ -2627,8 +3058,8 @@ function TreeCell({
2627
3058
  onToggle,
2628
3059
  onRetry
2629
3060
  }) {
2630
- return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1", style: { paddingLeft: flatRow.depth * indentSize }, children: [
2631
- flatRow.hasChildren ? /* @__PURE__ */ jsx20(
3061
+ return /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", style: { paddingLeft: flatRow.depth * indentSize }, children: [
3062
+ flatRow.hasChildren ? /* @__PURE__ */ jsx27(
2632
3063
  "button",
2633
3064
  {
2634
3065
  type: "button",
@@ -2640,14 +3071,14 @@ function TreeCell({
2640
3071
  "aria-label": flatRow.isExpanded ? "Collapse" : "Expand",
2641
3072
  "aria-expanded": flatRow.isExpanded,
2642
3073
  className: "flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-50",
2643
- children: isLoading ? /* @__PURE__ */ jsx20(Loader22, { className: "h-3.5 w-3.5 animate-spin", "aria-hidden": "true" }) : flatRow.isExpanded ? /* @__PURE__ */ jsx20(ChevronDown2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx20(ChevronRight2, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
3074
+ children: isLoading ? /* @__PURE__ */ jsx27(Loader22, { className: "h-3.5 w-3.5 animate-spin", "aria-hidden": "true" }) : flatRow.isExpanded ? /* @__PURE__ */ jsx27(ChevronDown2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx27(ChevronRight2, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
2644
3075
  }
2645
- ) : /* @__PURE__ */ jsx20("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
2646
- /* @__PURE__ */ jsx20("span", { className: "truncate", children: renderCell(column, flatRow.row) }),
2647
- flatRow.isExpanded && error ? /* @__PURE__ */ jsxs13("span", { className: "ml-1 flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
2648
- /* @__PURE__ */ jsx20(AlertCircle, { className: "h-3 w-3", "aria-hidden": "true" }),
3076
+ ) : /* @__PURE__ */ jsx27("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
3077
+ /* @__PURE__ */ jsx27("span", { className: "truncate", children: renderCell(column, flatRow.row) }),
3078
+ flatRow.isExpanded && error ? /* @__PURE__ */ jsxs18("span", { className: "ml-1 flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
3079
+ /* @__PURE__ */ jsx27(AlertCircle, { className: "h-3 w-3", "aria-hidden": "true" }),
2649
3080
  "Failed to load.",
2650
- /* @__PURE__ */ jsx20("button", { type: "button", className: "underline underline-offset-2", onClick: onRetry, children: "Retry" })
3081
+ /* @__PURE__ */ jsx27("button", { type: "button", className: "underline underline-offset-2", onClick: onRetry, children: "Retry" })
2651
3082
  ] }) : null
2652
3083
  ] });
2653
3084
  }
@@ -2754,7 +3185,7 @@ function TreeDataGrid({
2754
3185
  const rowProps = getRowProps?.(flatRow.row, flatRow.depth, index);
2755
3186
  const rowTestId = getRowTestId?.(flatRow.row) ?? `tree-row-${flatRow.id}`;
2756
3187
  const isOddRow = zebra && index % 2 === 1;
2757
- return /* @__PURE__ */ jsxs13(
3188
+ return /* @__PURE__ */ jsxs18(
2758
3189
  "tr",
2759
3190
  {
2760
3191
  ref: measureRef,
@@ -2767,9 +3198,9 @@ function TreeDataGrid({
2767
3198
  isOddRow && "bg-foreground/5"
2768
3199
  ) : `border-b border-border divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
2769
3200
  children: [
2770
- showSelectionColumn && /* @__PURE__ */ jsx20("td", { className: "p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: (() => {
3201
+ showSelectionColumn && /* @__PURE__ */ jsx27("td", { className: "p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: (() => {
2771
3202
  const state = resolveSelectionState(flatRow.row, flatRow.id);
2772
- return /* @__PURE__ */ jsx20(
3203
+ return /* @__PURE__ */ jsx27(
2773
3204
  Checkbox,
2774
3205
  {
2775
3206
  "aria-label": `Select row ${flatRow.id}`,
@@ -2780,7 +3211,7 @@ function TreeDataGrid({
2780
3211
  }
2781
3212
  );
2782
3213
  })() }),
2783
- columns.map((column) => /* @__PURE__ */ jsx20("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx20(
3214
+ columns.map((column) => /* @__PURE__ */ jsx27("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx27(
2784
3215
  TreeCell,
2785
3216
  {
2786
3217
  flatRow,
@@ -2792,7 +3223,7 @@ function TreeDataGrid({
2792
3223
  onRetry: () => retry(flatRow.row)
2793
3224
  }
2794
3225
  ) : renderCell(column, flatRow.row) }, column.id)),
2795
- showRowActionsColumn && rowActions && /* @__PURE__ */ jsx20("td", { className: "p-2", children: /* @__PURE__ */ jsx20(
3226
+ showRowActionsColumn && rowActions && /* @__PURE__ */ jsx27("td", { className: "p-2", children: /* @__PURE__ */ jsx27(
2796
3227
  ActionsMenu,
2797
3228
  {
2798
3229
  items: rowActions,
@@ -2808,15 +3239,15 @@ function TreeDataGrid({
2808
3239
  const virtualItems = shouldVirtualize ? virtualizer.getVirtualItems() : [];
2809
3240
  const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
2810
3241
  const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
2811
- return /* @__PURE__ */ jsx20("div", { className: "flex flex-col gap-2", "data-testid": "tree-datagrid", children: /* @__PURE__ */ jsx20(
3242
+ return /* @__PURE__ */ jsx27("div", { className: "flex flex-col gap-2", "data-testid": "tree-datagrid", children: /* @__PURE__ */ jsx27(
2812
3243
  "div",
2813
3244
  {
2814
3245
  ref: scrollRef,
2815
3246
  className: shouldVirtualize ? "overflow-y-auto" : void 0,
2816
3247
  style: shouldVirtualize ? { maxHeight: maxBodyHeight } : void 0,
2817
- children: /* @__PURE__ */ jsxs13("table", { className: "w-full border-collapse text-sm", children: [
2818
- /* @__PURE__ */ jsx20("thead", { children: /* @__PURE__ */ jsxs13("tr", { className: "divide-x divide-border", children: [
2819
- showSelectionColumn && /* @__PURE__ */ jsx20("th", { className: "border-b border-border p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: /* @__PURE__ */ jsx20(
3248
+ children: /* @__PURE__ */ jsxs18("table", { className: "w-full border-collapse text-sm", children: [
3249
+ /* @__PURE__ */ jsx27("thead", { children: /* @__PURE__ */ jsxs18("tr", { className: "divide-x divide-border", children: [
3250
+ showSelectionColumn && /* @__PURE__ */ jsx27("th", { className: "border-b border-border p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: /* @__PURE__ */ jsx27(
2820
3251
  Checkbox,
2821
3252
  {
2822
3253
  "aria-label": "Select all visible rows",
@@ -2824,7 +3255,7 @@ function TreeDataGrid({
2824
3255
  onCheckedChange: toggleAllVisibleSelected
2825
3256
  }
2826
3257
  ) }),
2827
- columns.map((column) => /* @__PURE__ */ jsx20(
3258
+ columns.map((column) => /* @__PURE__ */ jsx27(
2828
3259
  "th",
2829
3260
  {
2830
3261
  style: column.width ? { width: column.width } : void 0,
@@ -2833,14 +3264,14 @@ function TreeDataGrid({
2833
3264
  },
2834
3265
  column.id
2835
3266
  )),
2836
- showRowActionsColumn && /* @__PURE__ */ jsx20("th", { className: "border-b border-border p-2", "aria-label": "Row actions" })
3267
+ showRowActionsColumn && /* @__PURE__ */ jsx27("th", { className: "border-b border-border p-2", "aria-label": "Row actions" })
2837
3268
  ] }) }),
2838
- /* @__PURE__ */ jsx20("tbody", { children: flatRows.length === 0 ? /* @__PURE__ */ jsx20("tr", { children: /* @__PURE__ */ jsx20("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: "No results." }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs13(Fragment4, { children: [
2839
- paddingTop > 0 && /* @__PURE__ */ jsx20("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx20("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
3269
+ /* @__PURE__ */ jsx27("tbody", { children: flatRows.length === 0 ? /* @__PURE__ */ jsx27("tr", { children: /* @__PURE__ */ jsx27("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: "No results." }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs18(Fragment4, { children: [
3270
+ paddingTop > 0 && /* @__PURE__ */ jsx27("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx27("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
2840
3271
  virtualItems.map(
2841
3272
  (virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
2842
3273
  ),
2843
- paddingBottom > 0 && /* @__PURE__ */ jsx20("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx20(
3274
+ paddingBottom > 0 && /* @__PURE__ */ jsx27("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx27(
2844
3275
  "td",
2845
3276
  {
2846
3277
  colSpan: totalColumnCount,
@@ -2854,14 +3285,20 @@ function TreeDataGrid({
2854
3285
  }
2855
3286
  export {
2856
3287
  ActionsMenu,
3288
+ BooleanEditor,
2857
3289
  BooleanFilter,
2858
3290
  ColumnSelector,
2859
3291
  DataGrid,
3292
+ DateEditor,
2860
3293
  DateRangeFilter,
3294
+ EditFieldError,
3295
+ EnumEditor,
2861
3296
  EnumFilter,
2862
3297
  NumberComparisonFilter,
3298
+ NumberEditor,
2863
3299
  NumberHistogramFilter,
2864
3300
  NumberRangeFilter,
3301
+ StringEditor,
2865
3302
  StringFilter,
2866
3303
  TreeDataGrid,
2867
3304
  UNARY_OPERATORS,
@@ -2871,6 +3308,7 @@ export {
2871
3308
  countVisible,
2872
3309
  defaultAlign,
2873
3310
  defaultFormat,
3311
+ editErrorId,
2874
3312
  evaluateFilter,
2875
3313
  facetedNumberValues,
2876
3314
  fieldKey,
@@ -2879,13 +3317,16 @@ export {
2879
3317
  groupColumns,
2880
3318
  isColumnVisible,
2881
3319
  isCompositeFilterDescriptor,
3320
+ isEditable,
2882
3321
  isFilterDescriptor,
2883
3322
  isFilterable,
2884
3323
  isSortable,
2885
3324
  processClientData,
3325
+ renderDefaultEditWidget,
2886
3326
  renderDefaultFilterWidget,
2887
3327
  resolveMenuItems,
2888
3328
  storageKeyFor,
3329
+ toDate,
2889
3330
  useDebouncedCallback,
2890
3331
  useGridState,
2891
3332
  useTreeState