@bmsuisse/datagrid 0.25.3 → 0.27.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.d.ts +352 -3
- package/dist/index.js +674 -186
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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,18 +1369,458 @@ 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 { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
|
|
1492
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1493
|
+
function textFromValue(value) {
|
|
1494
|
+
return value === null || value === void 0 ? "" : String(value);
|
|
1495
|
+
}
|
|
1496
|
+
function NumberEditor({
|
|
1497
|
+
column,
|
|
1498
|
+
rowId,
|
|
1499
|
+
value,
|
|
1500
|
+
onChange,
|
|
1501
|
+
error,
|
|
1502
|
+
autoFocus
|
|
1503
|
+
}) {
|
|
1504
|
+
const errorId = editErrorId(rowId, column.id);
|
|
1505
|
+
const [text, setText] = useState5(() => textFromValue(value));
|
|
1506
|
+
const lastEmittedRef = useRef4(value);
|
|
1507
|
+
useEffect4(() => {
|
|
1508
|
+
if (value === lastEmittedRef.current) return;
|
|
1509
|
+
lastEmittedRef.current = value;
|
|
1510
|
+
setText(textFromValue(value));
|
|
1511
|
+
}, [value]);
|
|
1512
|
+
return /* @__PURE__ */ jsxs12("div", { children: [
|
|
1513
|
+
/* @__PURE__ */ jsx19(
|
|
1514
|
+
Input,
|
|
1515
|
+
{
|
|
1516
|
+
type: "number",
|
|
1517
|
+
className: "h-8",
|
|
1518
|
+
"aria-label": `Edit ${column.header}`,
|
|
1519
|
+
"aria-invalid": error ? true : void 0,
|
|
1520
|
+
"aria-describedby": error ? errorId : void 0,
|
|
1521
|
+
"data-testid": `edit-${rowId}-${column.id}`,
|
|
1522
|
+
autoFocus,
|
|
1523
|
+
value: text,
|
|
1524
|
+
onChange: (event) => {
|
|
1525
|
+
setText(event.target.value);
|
|
1526
|
+
const next = event.target.value === "" ? null : Number(event.target.value);
|
|
1527
|
+
lastEmittedRef.current = next;
|
|
1528
|
+
onChange(next);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
error && /* @__PURE__ */ jsx19(EditFieldError, { id: errorId, message: error })
|
|
1533
|
+
] });
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// src/edit/StringEditor.tsx
|
|
1537
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1538
|
+
function StringEditor({
|
|
1539
|
+
column,
|
|
1540
|
+
rowId,
|
|
1541
|
+
value,
|
|
1542
|
+
onChange,
|
|
1543
|
+
error,
|
|
1544
|
+
autoFocus
|
|
1545
|
+
}) {
|
|
1546
|
+
const errorId = editErrorId(rowId, column.id);
|
|
1547
|
+
return /* @__PURE__ */ jsxs13("div", { children: [
|
|
1548
|
+
/* @__PURE__ */ jsx20(
|
|
1549
|
+
Input,
|
|
1550
|
+
{
|
|
1551
|
+
className: "h-8",
|
|
1552
|
+
"aria-label": `Edit ${column.header}`,
|
|
1553
|
+
"aria-invalid": error ? true : void 0,
|
|
1554
|
+
"aria-describedby": error ? errorId : void 0,
|
|
1555
|
+
"data-testid": `edit-${rowId}-${column.id}`,
|
|
1556
|
+
autoFocus,
|
|
1557
|
+
value: value === null || value === void 0 ? "" : String(value),
|
|
1558
|
+
onChange: (event) => onChange(event.target.value)
|
|
1559
|
+
}
|
|
1560
|
+
),
|
|
1561
|
+
error && /* @__PURE__ */ jsx20(EditFieldError, { id: errorId, message: error })
|
|
1562
|
+
] });
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
// src/edit/registry.tsx
|
|
1566
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
1567
|
+
function renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus) {
|
|
1568
|
+
switch (column.type) {
|
|
1569
|
+
case "string":
|
|
1570
|
+
return /* @__PURE__ */ jsx21(StringEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1571
|
+
case "enum":
|
|
1572
|
+
return /* @__PURE__ */ jsx21(EnumEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1573
|
+
case "boolean":
|
|
1574
|
+
return /* @__PURE__ */ jsx21(BooleanEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1575
|
+
case "number":
|
|
1576
|
+
case "currency":
|
|
1577
|
+
return /* @__PURE__ */ jsx21(NumberEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1578
|
+
case "date":
|
|
1579
|
+
case "datetime":
|
|
1580
|
+
return /* @__PURE__ */ jsx21(DateEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
// src/edit/editingState.ts
|
|
1585
|
+
import { useEffect as useEffect5, useRef as useRef5, useState as useState6 } from "react";
|
|
1586
|
+
function editValuesEqual(a, b) {
|
|
1587
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
1588
|
+
return a === b;
|
|
1589
|
+
}
|
|
1590
|
+
function useEditingState(editing, getRowId) {
|
|
1591
|
+
const [pendingEdits, setPendingEdits] = useState6(/* @__PURE__ */ new Map());
|
|
1592
|
+
const [editErrors, setEditErrors] = useState6(/* @__PURE__ */ new Map());
|
|
1593
|
+
const hasEditErrors = editErrors.size > 0;
|
|
1594
|
+
const [activeRowId, setActiveRowId] = useState6(null);
|
|
1595
|
+
const [autoFocusTarget, setAutoFocusTarget] = useState6(null);
|
|
1596
|
+
function activateRow(rowId, columnId) {
|
|
1597
|
+
setActiveRowId(rowId);
|
|
1598
|
+
setAutoFocusTarget({ rowId, columnId });
|
|
1599
|
+
}
|
|
1600
|
+
useEffect5(() => {
|
|
1601
|
+
if (autoFocusTarget) setAutoFocusTarget(null);
|
|
1602
|
+
}, [autoFocusTarget]);
|
|
1603
|
+
function commitEdit(column, row, value) {
|
|
1604
|
+
const rowId = getRowId(row);
|
|
1605
|
+
const baseline = getColumnValue(column, row);
|
|
1606
|
+
setPendingEdits((prev) => {
|
|
1607
|
+
const next = new Map(prev);
|
|
1608
|
+
const values = new Map(next.get(rowId)?.values);
|
|
1609
|
+
if (editValuesEqual(value, baseline)) values.delete(column.id);
|
|
1610
|
+
else values.set(column.id, value);
|
|
1611
|
+
if (values.size === 0) next.delete(rowId);
|
|
1612
|
+
else next.set(rowId, { row, values });
|
|
1613
|
+
return next;
|
|
1614
|
+
});
|
|
1615
|
+
const message = column.validateEdit?.(value, row);
|
|
1616
|
+
setEditErrors((prev) => {
|
|
1617
|
+
const next = new Map(prev);
|
|
1618
|
+
const rowErrors = new Map(next.get(rowId));
|
|
1619
|
+
if (message) rowErrors.set(column.id, message);
|
|
1620
|
+
else rowErrors.delete(column.id);
|
|
1621
|
+
if (rowErrors.size === 0) next.delete(rowId);
|
|
1622
|
+
else next.set(rowId, rowErrors);
|
|
1623
|
+
return next;
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
async function handleSaveEdits() {
|
|
1627
|
+
if (!editing || pendingEdits.size === 0) return;
|
|
1628
|
+
const snapshot = pendingEdits;
|
|
1629
|
+
const edited = [...snapshot.entries()].map(([rowId, entry]) => ({
|
|
1630
|
+
rowId,
|
|
1631
|
+
row: entry.row,
|
|
1632
|
+
values: Object.fromEntries(entry.values)
|
|
1633
|
+
}));
|
|
1634
|
+
try {
|
|
1635
|
+
await editing.onSave(edited);
|
|
1636
|
+
} catch {
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
const snapshotRowIds = new Set(snapshot.keys());
|
|
1640
|
+
const survivedRowIds = /* @__PURE__ */ new Set();
|
|
1641
|
+
const clearedErrorKeys = [];
|
|
1642
|
+
setPendingEdits((prev) => {
|
|
1643
|
+
const next = new Map(prev);
|
|
1644
|
+
for (const [rowId, snapshotEntry] of snapshot) {
|
|
1645
|
+
const current = next.get(rowId);
|
|
1646
|
+
if (!current) continue;
|
|
1647
|
+
const values = new Map(current.values);
|
|
1648
|
+
for (const [columnId, snapshotValue] of snapshotEntry.values) {
|
|
1649
|
+
if (values.has(columnId) && editValuesEqual(values.get(columnId), snapshotValue)) {
|
|
1650
|
+
values.delete(columnId);
|
|
1651
|
+
clearedErrorKeys.push({ rowId, columnId });
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
if (values.size === 0) {
|
|
1655
|
+
next.delete(rowId);
|
|
1656
|
+
} else {
|
|
1657
|
+
next.set(rowId, { row: current.row, values });
|
|
1658
|
+
survivedRowIds.add(rowId);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
return next;
|
|
1662
|
+
});
|
|
1663
|
+
setEditErrors((prev) => {
|
|
1664
|
+
if (clearedErrorKeys.length === 0) return prev;
|
|
1665
|
+
const next = new Map(prev);
|
|
1666
|
+
for (const { rowId, columnId } of clearedErrorKeys) {
|
|
1667
|
+
const rowErrors = next.get(rowId);
|
|
1668
|
+
if (!rowErrors) continue;
|
|
1669
|
+
const nextRowErrors = new Map(rowErrors);
|
|
1670
|
+
nextRowErrors.delete(columnId);
|
|
1671
|
+
if (nextRowErrors.size === 0) next.delete(rowId);
|
|
1672
|
+
else next.set(rowId, nextRowErrors);
|
|
1673
|
+
}
|
|
1674
|
+
return next;
|
|
1675
|
+
});
|
|
1676
|
+
setActiveRowId(
|
|
1677
|
+
(prev) => prev !== null && snapshotRowIds.has(prev) && !survivedRowIds.has(prev) ? null : prev
|
|
1678
|
+
);
|
|
1679
|
+
}
|
|
1680
|
+
function handleDiscardEdits() {
|
|
1681
|
+
setPendingEdits(/* @__PURE__ */ new Map());
|
|
1682
|
+
setEditErrors(/* @__PURE__ */ new Map());
|
|
1683
|
+
setActiveRowId(null);
|
|
1684
|
+
editing?.onDiscard?.();
|
|
1685
|
+
}
|
|
1686
|
+
const ctx = editing ? { pendingEdits, editErrors, activeRowId, autoFocusTarget, getRowId, onEdit: commitEdit, onActivateRow: activateRow } : void 0;
|
|
1687
|
+
const ctxRef = useRef5(void 0);
|
|
1688
|
+
ctxRef.current = ctx;
|
|
1689
|
+
return { pendingEdits, editErrors, hasEditErrors, ctx, ctxRef, handleSaveEdits, handleDiscardEdits };
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
// src/edit/renderEditableCell.tsx
|
|
1693
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1694
|
+
function renderEditableCell(column, row, rawValue, ctx) {
|
|
1695
|
+
const staticContent = (value2) => column.cell ? column.cell(value2, row) : defaultFormat(column, value2);
|
|
1696
|
+
if (!ctx || !isEditable(column, row)) return staticContent(rawValue);
|
|
1697
|
+
const rowId = ctx.getRowId(row);
|
|
1698
|
+
const pendingRow = ctx.pendingEdits.get(rowId);
|
|
1699
|
+
const value = pendingRow?.values.has(column.id) ? pendingRow.values.get(column.id) : rawValue;
|
|
1700
|
+
if (ctx.activeRowId === rowId) {
|
|
1701
|
+
const error = ctx.editErrors.get(rowId)?.get(column.id);
|
|
1702
|
+
const autoFocus = ctx.autoFocusTarget?.rowId === rowId && ctx.autoFocusTarget.columnId === column.id;
|
|
1703
|
+
const onChange = (next) => ctx.onEdit(column, row, next);
|
|
1704
|
+
const editor = column.renderEditCell ? column.renderEditCell(value, row, onChange, error, autoFocus) : renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus);
|
|
1705
|
+
return /* @__PURE__ */ jsx22(
|
|
1706
|
+
"div",
|
|
1707
|
+
{
|
|
1708
|
+
onKeyDown: (event) => {
|
|
1709
|
+
if (event.key !== "Escape") return;
|
|
1710
|
+
if (!event.currentTarget.contains(event.target)) return;
|
|
1711
|
+
event.stopPropagation();
|
|
1712
|
+
ctx.onEdit(column, row, getColumnValue(column, row));
|
|
1713
|
+
},
|
|
1714
|
+
children: editor
|
|
1715
|
+
}
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1718
|
+
return /* @__PURE__ */ jsx22(
|
|
1719
|
+
"span",
|
|
1720
|
+
{
|
|
1721
|
+
role: "button",
|
|
1722
|
+
tabIndex: 0,
|
|
1723
|
+
"data-testid": `cell-${rowId}-${column.id}`,
|
|
1724
|
+
className: "block w-full cursor-text",
|
|
1725
|
+
onClick: (event) => {
|
|
1726
|
+
stopRowClick(event);
|
|
1727
|
+
ctx.onActivateRow(rowId, column.id);
|
|
1728
|
+
},
|
|
1729
|
+
onKeyDown: (event) => {
|
|
1730
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1731
|
+
event.preventDefault();
|
|
1732
|
+
stopRowClick(event);
|
|
1733
|
+
ctx.onActivateRow(rowId, column.id);
|
|
1734
|
+
},
|
|
1735
|
+
children: staticContent(value)
|
|
1736
|
+
}
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// src/edit/EditingBar.tsx
|
|
1741
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1742
|
+
function resolveEditLabel(label, changedRowCount, fallback) {
|
|
1743
|
+
if (label === void 0) return fallback(changedRowCount);
|
|
1744
|
+
return typeof label === "function" ? label(changedRowCount) : label;
|
|
1745
|
+
}
|
|
1746
|
+
function describeErrorRows(editErrors) {
|
|
1747
|
+
const rowIds = [...editErrors.keys()];
|
|
1748
|
+
const shown = rowIds.slice(0, 3);
|
|
1749
|
+
const suffix = rowIds.length > shown.length ? `, and ${rowIds.length - shown.length} more` : "";
|
|
1750
|
+
return `row${rowIds.length === 1 ? "" : "s"} ${shown.join(", ")}${suffix}`;
|
|
1751
|
+
}
|
|
1752
|
+
function EditingBar({
|
|
1753
|
+
editing,
|
|
1754
|
+
pendingRowCount,
|
|
1755
|
+
editErrors,
|
|
1756
|
+
onSave,
|
|
1757
|
+
onDiscard,
|
|
1758
|
+
testIdPrefix = "datagrid"
|
|
1759
|
+
}) {
|
|
1760
|
+
const hasEditErrors = editErrors.size > 0;
|
|
1761
|
+
return /* @__PURE__ */ jsxs14(
|
|
1762
|
+
"div",
|
|
1763
|
+
{
|
|
1764
|
+
"data-testid": `${testIdPrefix}-edit-bar`,
|
|
1765
|
+
className: "flex shrink-0 flex-wrap items-center justify-between gap-2 rounded-md border bg-muted/50 px-3 py-2 text-sm",
|
|
1766
|
+
children: [
|
|
1767
|
+
/* @__PURE__ */ jsxs14("span", { "aria-live": "polite", children: [
|
|
1768
|
+
pendingRowCount,
|
|
1769
|
+
" row",
|
|
1770
|
+
pendingRowCount === 1 ? "" : "s",
|
|
1771
|
+
" changed",
|
|
1772
|
+
hasEditErrors && /* @__PURE__ */ jsxs14("span", { className: "ml-2 text-destructive", children: [
|
|
1773
|
+
"Fix the highlighted errors before saving (",
|
|
1774
|
+
describeErrorRows(editErrors),
|
|
1775
|
+
")."
|
|
1776
|
+
] })
|
|
1777
|
+
] }),
|
|
1778
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
|
|
1779
|
+
/* @__PURE__ */ jsx23(
|
|
1780
|
+
Button,
|
|
1781
|
+
{
|
|
1782
|
+
type: "button",
|
|
1783
|
+
variant: "outline",
|
|
1784
|
+
size: "sm",
|
|
1785
|
+
"data-testid": `${testIdPrefix}-discard-edits`,
|
|
1786
|
+
disabled: editing.saving,
|
|
1787
|
+
onClick: onDiscard,
|
|
1788
|
+
children: resolveEditLabel(editing.discardLabel, pendingRowCount, () => "Discard")
|
|
1789
|
+
}
|
|
1790
|
+
),
|
|
1791
|
+
/* @__PURE__ */ jsx23(
|
|
1792
|
+
Button,
|
|
1793
|
+
{
|
|
1794
|
+
type: "button",
|
|
1795
|
+
size: "sm",
|
|
1796
|
+
"data-testid": `${testIdPrefix}-save-edits`,
|
|
1797
|
+
disabled: editing.saving || hasEditErrors,
|
|
1798
|
+
onClick: onSave,
|
|
1799
|
+
children: resolveEditLabel(
|
|
1800
|
+
editing.saveLabel,
|
|
1801
|
+
pendingRowCount,
|
|
1802
|
+
(count) => `Save ${count} change${count === 1 ? "" : "s"}`
|
|
1803
|
+
)
|
|
1804
|
+
}
|
|
1805
|
+
)
|
|
1806
|
+
] })
|
|
1807
|
+
]
|
|
1808
|
+
}
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1368
1812
|
// src/column-selector/ColumnSelector.tsx
|
|
1369
1813
|
import { Columns3 } from "lucide-react";
|
|
1370
|
-
import { useEffect as
|
|
1814
|
+
import { useEffect as useEffect6 } from "react";
|
|
1371
1815
|
|
|
1372
1816
|
// src/components/ui/dialog.tsx
|
|
1373
1817
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1374
1818
|
import { X } from "lucide-react";
|
|
1375
1819
|
import { forwardRef as forwardRef6 } from "react";
|
|
1376
|
-
import { jsx as
|
|
1820
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1377
1821
|
var Dialog = DialogPrimitive.Root;
|
|
1378
1822
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
1379
|
-
var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */
|
|
1823
|
+
var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
1380
1824
|
DialogPrimitive.Overlay,
|
|
1381
1825
|
{
|
|
1382
1826
|
ref,
|
|
@@ -1385,9 +1829,9 @@ var DialogOverlay = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
1385
1829
|
}
|
|
1386
1830
|
));
|
|
1387
1831
|
DialogOverlay.displayName = "DialogOverlay";
|
|
1388
|
-
var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1832
|
+
var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs15(DialogPrimitive.Portal, { children: [
|
|
1833
|
+
/* @__PURE__ */ jsx24(DialogOverlay, {}),
|
|
1834
|
+
/* @__PURE__ */ jsxs15(
|
|
1391
1835
|
DialogPrimitive.Content,
|
|
1392
1836
|
{
|
|
1393
1837
|
ref,
|
|
@@ -1398,9 +1842,9 @@ var DialogContent = forwardRef6(({ className, children, ...props }, ref) => /* @
|
|
|
1398
1842
|
...props,
|
|
1399
1843
|
children: [
|
|
1400
1844
|
children,
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
/* @__PURE__ */
|
|
1845
|
+
/* @__PURE__ */ jsxs15(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100", children: [
|
|
1846
|
+
/* @__PURE__ */ jsx24(X, { className: "h-4 w-4" }),
|
|
1847
|
+
/* @__PURE__ */ jsx24("span", { className: "sr-only", children: "Close" })
|
|
1404
1848
|
] })
|
|
1405
1849
|
]
|
|
1406
1850
|
}
|
|
@@ -1410,10 +1854,10 @@ DialogContent.displayName = "DialogContent";
|
|
|
1410
1854
|
var DialogHeader = ({
|
|
1411
1855
|
className,
|
|
1412
1856
|
...props
|
|
1413
|
-
}) => /* @__PURE__ */
|
|
1414
|
-
var DialogTitle = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */
|
|
1857
|
+
}) => /* @__PURE__ */ jsx24("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
1858
|
+
var DialogTitle = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
|
|
1415
1859
|
DialogTitle.displayName = "DialogTitle";
|
|
1416
|
-
var DialogDescription = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */
|
|
1860
|
+
var DialogDescription = forwardRef6(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
1417
1861
|
DialogPrimitive.Description,
|
|
1418
1862
|
{
|
|
1419
1863
|
ref,
|
|
@@ -1481,7 +1925,7 @@ function canHideGroup(columns, visibility, groupColumnIds) {
|
|
|
1481
1925
|
}
|
|
1482
1926
|
|
|
1483
1927
|
// src/column-selector/ColumnSelector.tsx
|
|
1484
|
-
import { jsx as
|
|
1928
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1485
1929
|
function ColumnSelector({
|
|
1486
1930
|
columns,
|
|
1487
1931
|
visibility,
|
|
@@ -1491,7 +1935,7 @@ function ColumnSelector({
|
|
|
1491
1935
|
open,
|
|
1492
1936
|
onOpenChange
|
|
1493
1937
|
}) {
|
|
1494
|
-
|
|
1938
|
+
useEffect6(() => {
|
|
1495
1939
|
if (!persistKey) return;
|
|
1496
1940
|
const restored = readPersistedVisibility(persistKey);
|
|
1497
1941
|
if (restored) onVisibilityChange({ ...visibility, ...restored });
|
|
@@ -1506,20 +1950,20 @@ function ColumnSelector({
|
|
|
1506
1950
|
}
|
|
1507
1951
|
const totalVisible = countVisible(columns, visibility);
|
|
1508
1952
|
const groups = groupColumns(columns);
|
|
1509
|
-
return /* @__PURE__ */
|
|
1510
|
-
/* @__PURE__ */
|
|
1511
|
-
/* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1514
|
-
group && /* @__PURE__ */
|
|
1953
|
+
return /* @__PURE__ */ jsxs16(Dialog, { open, onOpenChange, children: [
|
|
1954
|
+
/* @__PURE__ */ jsx25(DialogTrigger, { asChild: true, children: trigger ?? /* @__PURE__ */ jsx25(Button, { variant: "outline", size: "icon", "aria-label": "Choose columns", children: /* @__PURE__ */ jsx25(Columns3, { className: "h-4 w-4", "aria-hidden": true }) }) }),
|
|
1955
|
+
/* @__PURE__ */ jsxs16(DialogContent, { className: "w-fit max-w-[calc(100vw-2rem)] sm:max-w-2xl", children: [
|
|
1956
|
+
/* @__PURE__ */ jsx25(DialogHeader, { children: /* @__PURE__ */ jsx25(DialogTitle, { children: "Columns" }) }),
|
|
1957
|
+
/* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-x-8 gap-y-5", children: groups.map(({ group, columns: groupCols }) => /* @__PURE__ */ jsxs16("div", { className: "flex min-w-32 flex-col gap-1.5", children: [
|
|
1958
|
+
group && /* @__PURE__ */ jsx25("span", { className: "border-b pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: group }),
|
|
1515
1959
|
groupCols.map((column) => {
|
|
1516
1960
|
const visible = isColumnVisible(visibility, column.id);
|
|
1517
|
-
return /* @__PURE__ */
|
|
1961
|
+
return /* @__PURE__ */ jsxs16(
|
|
1518
1962
|
"label",
|
|
1519
1963
|
{
|
|
1520
1964
|
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
1965
|
children: [
|
|
1522
|
-
/* @__PURE__ */
|
|
1966
|
+
/* @__PURE__ */ jsx25(
|
|
1523
1967
|
Checkbox,
|
|
1524
1968
|
{
|
|
1525
1969
|
checked: visible,
|
|
@@ -1556,10 +2000,10 @@ import { useMemo as useMemo3 } from "react";
|
|
|
1556
2000
|
// src/components/ui/dropdown-menu.tsx
|
|
1557
2001
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
1558
2002
|
import { forwardRef as forwardRef7 } from "react";
|
|
1559
|
-
import { jsx as
|
|
2003
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
1560
2004
|
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
1561
2005
|
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
1562
|
-
var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */
|
|
2006
|
+
var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx26(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx26(
|
|
1563
2007
|
DropdownMenuPrimitive.Content,
|
|
1564
2008
|
{
|
|
1565
2009
|
ref,
|
|
@@ -1572,7 +2016,7 @@ var DropdownMenuContent = forwardRef7(({ className, sideOffset = 4, ...props },
|
|
|
1572
2016
|
}
|
|
1573
2017
|
) }));
|
|
1574
2018
|
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
1575
|
-
var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /* @__PURE__ */
|
|
2019
|
+
var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1576
2020
|
DropdownMenuPrimitive.Item,
|
|
1577
2021
|
{
|
|
1578
2022
|
ref,
|
|
@@ -1585,7 +2029,7 @@ var DropdownMenuItem = forwardRef7(({ className, danger, ...props }, ref) => /*
|
|
|
1585
2029
|
}
|
|
1586
2030
|
));
|
|
1587
2031
|
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
1588
|
-
var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */
|
|
2032
|
+
var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1589
2033
|
DropdownMenuPrimitive.Separator,
|
|
1590
2034
|
{
|
|
1591
2035
|
ref,
|
|
@@ -1594,7 +2038,7 @@ var DropdownMenuSeparator = forwardRef7(({ className, ...props }, ref) => /* @__
|
|
|
1594
2038
|
}
|
|
1595
2039
|
));
|
|
1596
2040
|
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
1597
|
-
var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */
|
|
2041
|
+
var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
|
|
1598
2042
|
DropdownMenuPrimitive.Label,
|
|
1599
2043
|
{
|
|
1600
2044
|
ref,
|
|
@@ -1605,16 +2049,16 @@ var DropdownMenuLabel = forwardRef7(({ className, ...props }, ref) => /* @__PURE
|
|
|
1605
2049
|
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
|
1606
2050
|
|
|
1607
2051
|
// src/menu/ActionsMenu.tsx
|
|
1608
|
-
import { jsx as
|
|
2052
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1609
2053
|
function ActionsMenu({ items, ctx, triggerLabel }) {
|
|
1610
2054
|
const resolved = useMemo3(
|
|
1611
2055
|
() => resolveMenuItems(items, ctx),
|
|
1612
2056
|
[items, ctx.row, ctx.selectedRows]
|
|
1613
2057
|
);
|
|
1614
2058
|
if (resolved.length === 0) return null;
|
|
1615
|
-
return /* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
2059
|
+
return /* @__PURE__ */ jsxs17(DropdownMenu, { children: [
|
|
2060
|
+
/* @__PURE__ */ jsx27(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx27(Button, { variant: "ghost", size: "icon", "aria-label": triggerLabel, onClick: stopRowClick, children: /* @__PURE__ */ jsx27(MoreVertical, { className: "h-4 w-4", "aria-hidden": true }) }) }),
|
|
2061
|
+
/* @__PURE__ */ jsx27(DropdownMenuContent, { align: "end", children: resolved.map((item) => /* @__PURE__ */ jsx27(
|
|
1618
2062
|
DropdownMenuItem,
|
|
1619
2063
|
{
|
|
1620
2064
|
danger: item.danger,
|
|
@@ -1632,7 +2076,7 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
|
|
|
1632
2076
|
import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
|
|
1633
2077
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
1634
2078
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
1635
|
-
import { Fragment as Fragment2, useEffect as
|
|
2079
|
+
import { Fragment as Fragment2, useEffect as useEffect9, useLayoutEffect, useMemo as useMemo6, useRef as useRef7, useState as useState8 } from "react";
|
|
1636
2080
|
|
|
1637
2081
|
// src/lib/structuralColumns.ts
|
|
1638
2082
|
var SELECTION_COLUMN_WIDTH = 44;
|
|
@@ -1675,15 +2119,15 @@ function processClientData(data, state) {
|
|
|
1675
2119
|
}
|
|
1676
2120
|
|
|
1677
2121
|
// src/grid/useGridState.ts
|
|
1678
|
-
import { useCallback as useCallback2, useEffect as
|
|
2122
|
+
import { useCallback as useCallback2, useEffect as useEffect8, useMemo as useMemo5, useState as useState7 } from "react";
|
|
1679
2123
|
|
|
1680
2124
|
// src/hooks/useDebouncedCallback.ts
|
|
1681
|
-
import { useEffect as
|
|
2125
|
+
import { useEffect as useEffect7, useMemo as useMemo4, useRef as useRef6 } from "react";
|
|
1682
2126
|
function useDebouncedCallback(callback, delayMs) {
|
|
1683
|
-
const callbackRef =
|
|
2127
|
+
const callbackRef = useRef6(callback);
|
|
1684
2128
|
callbackRef.current = callback;
|
|
1685
|
-
const timeoutRef =
|
|
1686
|
-
|
|
2129
|
+
const timeoutRef = useRef6(void 0);
|
|
2130
|
+
useEffect7(() => {
|
|
1687
2131
|
return () => {
|
|
1688
2132
|
clearTimeout(timeoutRef.current);
|
|
1689
2133
|
};
|
|
@@ -1713,7 +2157,7 @@ function nextSortDir(current, descFirst) {
|
|
|
1713
2157
|
return void 0;
|
|
1714
2158
|
}
|
|
1715
2159
|
function useGridState(dataSource, initialState, externalState) {
|
|
1716
|
-
const [state, setState] =
|
|
2160
|
+
const [state, setState] = useState7(
|
|
1717
2161
|
() => externalState ?? { ...DEFAULT_STATE, ...initialState }
|
|
1718
2162
|
);
|
|
1719
2163
|
const notifyRaw = useCallback2(
|
|
@@ -1733,7 +2177,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
1733
2177
|
},
|
|
1734
2178
|
[notifyRaw, cancelDebouncedNotify]
|
|
1735
2179
|
);
|
|
1736
|
-
|
|
2180
|
+
useEffect8(() => {
|
|
1737
2181
|
if (!externalState) return;
|
|
1738
2182
|
cancelDebouncedNotify();
|
|
1739
2183
|
setState(externalState);
|
|
@@ -1802,7 +2246,7 @@ function useGridState(dataSource, initialState, externalState) {
|
|
|
1802
2246
|
}
|
|
1803
2247
|
|
|
1804
2248
|
// src/grid/DataGrid.tsx
|
|
1805
|
-
import { Fragment as Fragment3, jsx as
|
|
2249
|
+
import { Fragment as Fragment3, jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1806
2250
|
var gridTableFeatures = tableFeatures({ columnSizingFeature, columnResizingFeature });
|
|
1807
2251
|
var DEFAULT_COLUMN_SIZE = 150;
|
|
1808
2252
|
var DETAIL_COLUMN_WIDTH = 44;
|
|
@@ -1833,13 +2277,13 @@ function computeHeaderRuns(columns) {
|
|
|
1833
2277
|
}
|
|
1834
2278
|
return runs;
|
|
1835
2279
|
}
|
|
1836
|
-
function toTanstackColumns(columns) {
|
|
2280
|
+
function toTanstackColumns(columns, editingCtxRef) {
|
|
1837
2281
|
return columns.map((column) => ({
|
|
1838
2282
|
id: column.id,
|
|
1839
2283
|
header: column.header,
|
|
1840
2284
|
size: column.width,
|
|
1841
2285
|
accessorFn: (row) => getColumnValue(column, row),
|
|
1842
|
-
cell: (info) => column
|
|
2286
|
+
cell: (info) => renderEditableCell(column, info.row.original, info.getValue(), editingCtxRef.current)
|
|
1843
2287
|
}));
|
|
1844
2288
|
}
|
|
1845
2289
|
function DataGrid({
|
|
@@ -1870,26 +2314,27 @@ function DataGrid({
|
|
|
1870
2314
|
defaultGroupsExpanded = true,
|
|
1871
2315
|
expandedGroups: controlledExpandedGroups,
|
|
1872
2316
|
onExpandedGroupsChange,
|
|
1873
|
-
zebra = true
|
|
2317
|
+
zebra = true,
|
|
2318
|
+
editing
|
|
1874
2319
|
}) {
|
|
1875
2320
|
const { state, filtersByColumn, setColumnFilter, toggleSort, setPage } = useGridState(
|
|
1876
2321
|
dataSource,
|
|
1877
2322
|
initialState,
|
|
1878
2323
|
gridState
|
|
1879
2324
|
);
|
|
1880
|
-
const [internalSelectedIds, setInternalSelectedIds] =
|
|
2325
|
+
const [internalSelectedIds, setInternalSelectedIds] = useState8(/* @__PURE__ */ new Set());
|
|
1881
2326
|
const selectedIds = controlledSelectedIds ?? internalSelectedIds;
|
|
1882
2327
|
function updateSelectedIds(next) {
|
|
1883
2328
|
setInternalSelectedIds(next);
|
|
1884
2329
|
onSelectedIdsChange?.(next);
|
|
1885
2330
|
}
|
|
1886
|
-
const [internalColumnSizing, setInternalColumnSizing] =
|
|
2331
|
+
const [internalColumnSizing, setInternalColumnSizing] = useState8({});
|
|
1887
2332
|
const columnSizing = controlledColumnSizing ?? internalColumnSizing;
|
|
1888
2333
|
function updateColumnSizing(next) {
|
|
1889
2334
|
setInternalColumnSizing(next);
|
|
1890
2335
|
onColumnSizingChange?.(next);
|
|
1891
2336
|
}
|
|
1892
|
-
const [expandedIds, setExpandedIds] =
|
|
2337
|
+
const [expandedIds, setExpandedIds] = useState8(/* @__PURE__ */ new Set());
|
|
1893
2338
|
function toggleRowExpanded(id) {
|
|
1894
2339
|
setExpandedIds((prev) => {
|
|
1895
2340
|
const next = new Set(prev);
|
|
@@ -1898,7 +2343,7 @@ function DataGrid({
|
|
|
1898
2343
|
return next;
|
|
1899
2344
|
});
|
|
1900
2345
|
}
|
|
1901
|
-
const [internalExpandedGroups, setInternalExpandedGroups] =
|
|
2346
|
+
const [internalExpandedGroups, setInternalExpandedGroups] = useState8({});
|
|
1902
2347
|
const expandedGroupsState = controlledExpandedGroups ?? internalExpandedGroups;
|
|
1903
2348
|
function updateExpandedGroups(next) {
|
|
1904
2349
|
setInternalExpandedGroups(next);
|
|
@@ -1910,6 +2355,10 @@ function DataGrid({
|
|
|
1910
2355
|
function toggleGroupExpanded(key) {
|
|
1911
2356
|
updateExpandedGroups({ ...expandedGroupsState, [key]: !isGroupExpanded(key) });
|
|
1912
2357
|
}
|
|
2358
|
+
const { pendingEdits, editErrors, ctxRef: editingCtxRef, handleSaveEdits, handleDiscardEdits } = useEditingState(
|
|
2359
|
+
editing,
|
|
2360
|
+
getRowId
|
|
2361
|
+
);
|
|
1913
2362
|
const visibleColumns = useMemo6(
|
|
1914
2363
|
() => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
|
|
1915
2364
|
[columns, columnVisibility]
|
|
@@ -1938,7 +2387,7 @@ function DataGrid({
|
|
|
1938
2387
|
}
|
|
1939
2388
|
updateSelectedIds(next);
|
|
1940
2389
|
}
|
|
1941
|
-
const tanstackColumns = useMemo6(() => toTanstackColumns(visibleColumns), [visibleColumns]);
|
|
2390
|
+
const tanstackColumns = useMemo6(() => toTanstackColumns(visibleColumns, editingCtxRef), [visibleColumns]);
|
|
1942
2391
|
const columnById = useMemo6(() => {
|
|
1943
2392
|
const map = /* @__PURE__ */ new Map();
|
|
1944
2393
|
for (const column of visibleColumns) map.set(column.id, column);
|
|
@@ -2065,8 +2514,8 @@ function DataGrid({
|
|
|
2065
2514
|
() => groupBy ? groupRows(tableRows, (row) => groupBy(row.original)) : void 0,
|
|
2066
2515
|
[tableRows, groupBy]
|
|
2067
2516
|
);
|
|
2068
|
-
const theadRef =
|
|
2069
|
-
const [groupHeaderTop, setGroupHeaderTop] =
|
|
2517
|
+
const theadRef = useRef7(null);
|
|
2518
|
+
const [groupHeaderTop, setGroupHeaderTop] = useState8(0);
|
|
2070
2519
|
useLayoutEffect(() => {
|
|
2071
2520
|
if (!groupBy) return;
|
|
2072
2521
|
const theadEl = theadRef.current;
|
|
@@ -2077,7 +2526,7 @@ function DataGrid({
|
|
|
2077
2526
|
observer.observe(theadEl);
|
|
2078
2527
|
return () => observer.disconnect();
|
|
2079
2528
|
}, [groupBy]);
|
|
2080
|
-
const scrollRef =
|
|
2529
|
+
const scrollRef = useRef7(null);
|
|
2081
2530
|
const virtualizer = useVirtualizer({
|
|
2082
2531
|
count: tableRows.length,
|
|
2083
2532
|
getScrollElement: () => scrollRef.current,
|
|
@@ -2089,8 +2538,8 @@ function DataGrid({
|
|
|
2089
2538
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
2090
2539
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
2091
2540
|
const lastVisibleIndex = virtualItems.length > 0 ? virtualItems[virtualItems.length - 1].index : -1;
|
|
2092
|
-
const notifiedForLengthRef =
|
|
2093
|
-
|
|
2541
|
+
const notifiedForLengthRef = useRef7(-1);
|
|
2542
|
+
useEffect9(() => {
|
|
2094
2543
|
if (!virtualize?.onEndReached) return;
|
|
2095
2544
|
if (lastVisibleIndex < 0 || lastVisibleIndex < tableRows.length - 1) return;
|
|
2096
2545
|
if (virtualize.hasMore === false) return;
|
|
@@ -2103,20 +2552,20 @@ function DataGrid({
|
|
|
2103
2552
|
const rowProps = getRowProps?.(row.original);
|
|
2104
2553
|
const rowTestId = getRowTestId?.(row.original) ?? `row-${row.id}`;
|
|
2105
2554
|
const isOddRow = zebra && row.index % 2 === 1;
|
|
2106
|
-
return /* @__PURE__ */
|
|
2107
|
-
/* @__PURE__ */
|
|
2555
|
+
return /* @__PURE__ */ jsxs18("tbody", { ref: measureRef, "data-index": row.index, children: [
|
|
2556
|
+
/* @__PURE__ */ jsxs18(
|
|
2108
2557
|
"tr",
|
|
2109
2558
|
{
|
|
2110
2559
|
...rowProps,
|
|
2111
2560
|
"data-testid": rowTestId,
|
|
2112
2561
|
className: rowProps?.className ? cn("divide-x divide-border", rowProps.className, isOddRow && "bg-foreground/5") : `divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
|
|
2113
2562
|
children: [
|
|
2114
|
-
showDetailColumn && /* @__PURE__ */
|
|
2563
|
+
showDetailColumn && /* @__PURE__ */ jsx28(
|
|
2115
2564
|
"td",
|
|
2116
2565
|
{
|
|
2117
2566
|
className: isOddRow ? detailCellProps.classNameOdd : detailCellProps.className,
|
|
2118
2567
|
style: detailCellProps.style,
|
|
2119
|
-
children: /* @__PURE__ */
|
|
2568
|
+
children: /* @__PURE__ */ jsx28(
|
|
2120
2569
|
Button,
|
|
2121
2570
|
{
|
|
2122
2571
|
type: "button",
|
|
@@ -2128,7 +2577,7 @@ function DataGrid({
|
|
|
2128
2577
|
stopRowClick(event);
|
|
2129
2578
|
toggleRowExpanded(row.id);
|
|
2130
2579
|
},
|
|
2131
|
-
children: /* @__PURE__ */
|
|
2580
|
+
children: /* @__PURE__ */ jsx28(
|
|
2132
2581
|
ChevronRight,
|
|
2133
2582
|
{
|
|
2134
2583
|
className: `h-4 w-4 transition-transform${isExpanded ? " rotate-90" : ""}`,
|
|
@@ -2139,12 +2588,12 @@ function DataGrid({
|
|
|
2139
2588
|
)
|
|
2140
2589
|
}
|
|
2141
2590
|
),
|
|
2142
|
-
showSelectionColumn && /* @__PURE__ */
|
|
2591
|
+
showSelectionColumn && /* @__PURE__ */ jsx28(
|
|
2143
2592
|
"td",
|
|
2144
2593
|
{
|
|
2145
2594
|
className: isOddRow ? selectionCellProps.classNameOdd : selectionCellProps.className,
|
|
2146
2595
|
style: selectionCellProps.style,
|
|
2147
|
-
children: /* @__PURE__ */
|
|
2596
|
+
children: /* @__PURE__ */ jsx28(
|
|
2148
2597
|
"input",
|
|
2149
2598
|
{
|
|
2150
2599
|
type: "checkbox",
|
|
@@ -2158,27 +2607,27 @@ function DataGrid({
|
|
|
2158
2607
|
),
|
|
2159
2608
|
row.getAllCells().map((cell) => {
|
|
2160
2609
|
const cellProps = bodyCellPropsByColumn.get(cell.column.id);
|
|
2161
|
-
return /* @__PURE__ */
|
|
2610
|
+
return /* @__PURE__ */ jsx28("td", { style: cellProps?.style, className: cellProps?.className ?? BODY_TD_BASE_CLASS, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id);
|
|
2162
2611
|
}),
|
|
2163
|
-
showRowActionsColumn && rowActions && /* @__PURE__ */
|
|
2612
|
+
showRowActionsColumn && rowActions && /* @__PURE__ */ jsx28(
|
|
2164
2613
|
"td",
|
|
2165
2614
|
{
|
|
2166
2615
|
className: isOddRow ? rowActionsCellProps.classNameOdd : rowActionsCellProps.className,
|
|
2167
2616
|
style: rowActionsCellProps.style,
|
|
2168
|
-
children: /* @__PURE__ */
|
|
2617
|
+
children: /* @__PURE__ */ jsx28(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` })
|
|
2169
2618
|
}
|
|
2170
2619
|
)
|
|
2171
2620
|
]
|
|
2172
2621
|
}
|
|
2173
2622
|
),
|
|
2174
|
-
showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */
|
|
2623
|
+
showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */ jsx28("tr", { "data-testid": `${rowTestId}-detail`, children: /* @__PURE__ */ jsx28("td", { colSpan: totalColumnCount, className: "border-b border-border p-2", children: renderDetail(row.original) }) })
|
|
2175
2624
|
] }, row.id);
|
|
2176
2625
|
}
|
|
2177
2626
|
function renderGroupedBucket(bucket) {
|
|
2178
2627
|
const expanded = isGroupExpanded(bucket.key);
|
|
2179
2628
|
const originalRows = bucket.items.map((row) => row.original);
|
|
2180
|
-
return /* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2629
|
+
return /* @__PURE__ */ jsxs18(Fragment2, { children: [
|
|
2630
|
+
/* @__PURE__ */ jsx28("tbody", { children: /* @__PURE__ */ jsx28("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx28(
|
|
2182
2631
|
"td",
|
|
2183
2632
|
{
|
|
2184
2633
|
colSpan: totalColumnCount,
|
|
@@ -2187,7 +2636,7 @@ function DataGrid({
|
|
|
2187
2636
|
zebra ? "bg-muted" : "bg-background"
|
|
2188
2637
|
),
|
|
2189
2638
|
style: { top: groupHeaderTop },
|
|
2190
|
-
children: /* @__PURE__ */
|
|
2639
|
+
children: /* @__PURE__ */ jsxs18(
|
|
2191
2640
|
"button",
|
|
2192
2641
|
{
|
|
2193
2642
|
type: "button",
|
|
@@ -2195,7 +2644,7 @@ function DataGrid({
|
|
|
2195
2644
|
onClick: () => toggleGroupExpanded(bucket.key),
|
|
2196
2645
|
"aria-expanded": expanded,
|
|
2197
2646
|
children: [
|
|
2198
|
-
/* @__PURE__ */
|
|
2647
|
+
/* @__PURE__ */ jsx28(
|
|
2199
2648
|
ChevronRight,
|
|
2200
2649
|
{
|
|
2201
2650
|
className: `h-4 w-4 shrink-0 transition-transform${expanded ? " rotate-90" : ""}`,
|
|
@@ -2224,32 +2673,42 @@ function DataGrid({
|
|
|
2224
2673
|
// containers (that one scrolling vertically, this component's own
|
|
2225
2674
|
// `overflow-x-auto` div scrolling horizontally) fighting over which one
|
|
2226
2675
|
// a sticky header/pinned column is actually stuck relative to.
|
|
2227
|
-
/* @__PURE__ */
|
|
2228
|
-
|
|
2229
|
-
|
|
2676
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex h-full min-h-0 flex-col gap-2", "data-testid": "datagrid", children: [
|
|
2677
|
+
editing && pendingEdits.size > 0 && /* @__PURE__ */ jsx28(
|
|
2678
|
+
EditingBar,
|
|
2679
|
+
{
|
|
2680
|
+
editing,
|
|
2681
|
+
pendingRowCount: pendingEdits.size,
|
|
2682
|
+
editErrors,
|
|
2683
|
+
onSave: () => void handleSaveEdits(),
|
|
2684
|
+
onDiscard: handleDiscardEdits
|
|
2685
|
+
}
|
|
2686
|
+
),
|
|
2687
|
+
showSelectionColumn && headerActions && /* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
|
|
2688
|
+
/* @__PURE__ */ jsxs18("span", { children: [
|
|
2230
2689
|
selectedRows.length,
|
|
2231
2690
|
" selected"
|
|
2232
2691
|
] }),
|
|
2233
|
-
/* @__PURE__ */
|
|
2692
|
+
/* @__PURE__ */ jsx28(ActionsMenu, { items: headerActions, ctx: { selectedRows }, triggerLabel: "Bulk actions" })
|
|
2234
2693
|
] }),
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
loading && /* @__PURE__ */
|
|
2694
|
+
/* @__PURE__ */ jsxs18("div", { className: "relative min-h-0 flex-1", children: [
|
|
2695
|
+
loading && /* @__PURE__ */ jsx28(
|
|
2237
2696
|
"div",
|
|
2238
2697
|
{
|
|
2239
2698
|
"data-testid": "datagrid-loading-overlay",
|
|
2240
2699
|
className: "absolute inset-0 z-30 flex items-center justify-center bg-background/60",
|
|
2241
|
-
children: /* @__PURE__ */
|
|
2700
|
+
children: /* @__PURE__ */ jsx28(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground", "aria-hidden": true })
|
|
2242
2701
|
}
|
|
2243
2702
|
),
|
|
2244
|
-
/* @__PURE__ */
|
|
2703
|
+
/* @__PURE__ */ jsx28(
|
|
2245
2704
|
"div",
|
|
2246
2705
|
{
|
|
2247
2706
|
ref: scrollRef,
|
|
2248
2707
|
"data-testid": testId,
|
|
2249
2708
|
className: "h-full overflow-auto rounded-md border",
|
|
2250
2709
|
style: shouldVirtualize ? { maxHeight: virtualize?.maxBodyHeight ?? 480 } : void 0,
|
|
2251
|
-
children: /* @__PURE__ */
|
|
2252
|
-
/* @__PURE__ */
|
|
2710
|
+
children: /* @__PURE__ */ jsxs18("table", { className: cn("w-full border-collapse text-sm", enableColumnResizing && "table-fixed"), children: [
|
|
2711
|
+
/* @__PURE__ */ jsxs18("thead", { ref: theadRef, className: "bg-muted", children: [
|
|
2253
2712
|
table.getHeaderGroups().map((headerGroup) => {
|
|
2254
2713
|
const headerById = new Map(headerGroup.headers.map((header) => [header.id, header]));
|
|
2255
2714
|
function renderLeafHeaderCell(column, rowSpan) {
|
|
@@ -2260,9 +2719,9 @@ function DataGrid({
|
|
|
2260
2719
|
const filterable = isFilterable(column) && column.filterDisplay !== "row";
|
|
2261
2720
|
const cellProps = leafHeaderCellPropsByColumn.get(column.id);
|
|
2262
2721
|
const headerContent = column.renderHeader ? column.renderHeader(column) : column.header;
|
|
2263
|
-
return /* @__PURE__ */
|
|
2264
|
-
/* @__PURE__ */
|
|
2265
|
-
sortable ? /* @__PURE__ */
|
|
2722
|
+
return /* @__PURE__ */ jsxs18("th", { rowSpan, style: cellProps?.style, className: cellProps?.className, children: [
|
|
2723
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", children: [
|
|
2724
|
+
sortable ? /* @__PURE__ */ jsxs18(
|
|
2266
2725
|
"button",
|
|
2267
2726
|
{
|
|
2268
2727
|
type: "button",
|
|
@@ -2270,8 +2729,8 @@ function DataGrid({
|
|
|
2270
2729
|
onClick: (event) => toggleSort(column.id, enableMultiSort && event.shiftKey, column.sortDescFirst === true),
|
|
2271
2730
|
children: [
|
|
2272
2731
|
headerContent,
|
|
2273
|
-
sortEntry?.dir === "asc" && /* @__PURE__ */
|
|
2274
|
-
sortEntry?.dir === "desc" && /* @__PURE__ */
|
|
2732
|
+
sortEntry?.dir === "asc" && /* @__PURE__ */ jsx28(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
|
|
2733
|
+
sortEntry?.dir === "desc" && /* @__PURE__ */ jsx28(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
|
|
2275
2734
|
]
|
|
2276
2735
|
}
|
|
2277
2736
|
) : (
|
|
@@ -2280,10 +2739,10 @@ function DataGrid({
|
|
|
2280
2739
|
// silently breaking any interactive content a column's own `renderHeader`
|
|
2281
2740
|
// embeds directly (bare filter inputs, "select/reject all" buttons) —
|
|
2282
2741
|
// clicks never reach them at all, even though nothing looks wrong visually.
|
|
2283
|
-
/* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ jsx28("div", { className: "flex items-center gap-1 px-1", children: headerContent })
|
|
2284
2743
|
),
|
|
2285
|
-
filterable && /* @__PURE__ */
|
|
2286
|
-
/* @__PURE__ */
|
|
2744
|
+
filterable && /* @__PURE__ */ jsxs18(Popover, { children: [
|
|
2745
|
+
/* @__PURE__ */ jsx28(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(Button, { variant: "ghost", size: "icon", "aria-label": `Filter ${column.header}`, children: /* @__PURE__ */ jsx28(
|
|
2287
2746
|
FunnelIcon7,
|
|
2288
2747
|
{
|
|
2289
2748
|
className: cn(
|
|
@@ -2293,10 +2752,10 @@ function DataGrid({
|
|
|
2293
2752
|
"aria-hidden": true
|
|
2294
2753
|
}
|
|
2295
2754
|
) }) }),
|
|
2296
|
-
/* @__PURE__ */
|
|
2755
|
+
/* @__PURE__ */ jsx28(PopoverContent, { children: renderFilterWidget(column) })
|
|
2297
2756
|
] })
|
|
2298
2757
|
] }),
|
|
2299
|
-
enableColumnResizing && /* @__PURE__ */
|
|
2758
|
+
enableColumnResizing && /* @__PURE__ */ jsx28(
|
|
2300
2759
|
"div",
|
|
2301
2760
|
{
|
|
2302
2761
|
"data-testid": `resize-handle-${column.id}`,
|
|
@@ -2307,9 +2766,9 @@ function DataGrid({
|
|
|
2307
2766
|
)
|
|
2308
2767
|
] }, header.id);
|
|
2309
2768
|
}
|
|
2310
|
-
return /* @__PURE__ */
|
|
2311
|
-
hasHeaderGroups && /* @__PURE__ */
|
|
2312
|
-
showDetailColumn && /* @__PURE__ */
|
|
2769
|
+
return /* @__PURE__ */ jsxs18(Fragment2, { children: [
|
|
2770
|
+
hasHeaderGroups && /* @__PURE__ */ jsxs18("tr", { "data-testid": "header-group-row", className: "divide-x divide-border", children: [
|
|
2771
|
+
showDetailColumn && /* @__PURE__ */ jsx28(
|
|
2313
2772
|
"th",
|
|
2314
2773
|
{
|
|
2315
2774
|
rowSpan: 2,
|
|
@@ -2318,13 +2777,13 @@ function DataGrid({
|
|
|
2318
2777
|
"aria-hidden": true
|
|
2319
2778
|
}
|
|
2320
2779
|
),
|
|
2321
|
-
showSelectionColumn && /* @__PURE__ */
|
|
2780
|
+
showSelectionColumn && /* @__PURE__ */ jsx28(
|
|
2322
2781
|
"th",
|
|
2323
2782
|
{
|
|
2324
2783
|
rowSpan: 2,
|
|
2325
2784
|
className: selectionHeaderCellProps.className,
|
|
2326
2785
|
style: selectionHeaderCellProps.style,
|
|
2327
|
-
children: /* @__PURE__ */
|
|
2786
|
+
children: /* @__PURE__ */ jsx28(
|
|
2328
2787
|
"input",
|
|
2329
2788
|
{
|
|
2330
2789
|
type: "checkbox",
|
|
@@ -2336,7 +2795,7 @@ function DataGrid({
|
|
|
2336
2795
|
}
|
|
2337
2796
|
),
|
|
2338
2797
|
headerRuns.map(
|
|
2339
|
-
(run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */
|
|
2798
|
+
(run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */ jsx28(
|
|
2340
2799
|
"th",
|
|
2341
2800
|
{
|
|
2342
2801
|
colSpan: run.columns.length,
|
|
@@ -2346,7 +2805,7 @@ function DataGrid({
|
|
|
2346
2805
|
`group-${run.label}-${run.columns[0].id}`
|
|
2347
2806
|
)
|
|
2348
2807
|
),
|
|
2349
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
2808
|
+
showRowActionsColumn && /* @__PURE__ */ jsx28(
|
|
2350
2809
|
"th",
|
|
2351
2810
|
{
|
|
2352
2811
|
rowSpan: 2,
|
|
@@ -2356,8 +2815,8 @@ function DataGrid({
|
|
|
2356
2815
|
}
|
|
2357
2816
|
)
|
|
2358
2817
|
] }, `${headerGroup.id}-groups`),
|
|
2359
|
-
/* @__PURE__ */
|
|
2360
|
-
!hasHeaderGroups && showDetailColumn && /* @__PURE__ */
|
|
2818
|
+
/* @__PURE__ */ jsxs18("tr", { className: "divide-x divide-border", children: [
|
|
2819
|
+
!hasHeaderGroups && showDetailColumn && /* @__PURE__ */ jsx28(
|
|
2361
2820
|
"th",
|
|
2362
2821
|
{
|
|
2363
2822
|
className: detailHeaderCellProps.className,
|
|
@@ -2365,12 +2824,12 @@ function DataGrid({
|
|
|
2365
2824
|
"aria-hidden": true
|
|
2366
2825
|
}
|
|
2367
2826
|
),
|
|
2368
|
-
!hasHeaderGroups && showSelectionColumn && /* @__PURE__ */
|
|
2827
|
+
!hasHeaderGroups && showSelectionColumn && /* @__PURE__ */ jsx28(
|
|
2369
2828
|
"th",
|
|
2370
2829
|
{
|
|
2371
2830
|
className: selectionHeaderCellProps.className,
|
|
2372
2831
|
style: selectionHeaderCellProps.style,
|
|
2373
|
-
children: /* @__PURE__ */
|
|
2832
|
+
children: /* @__PURE__ */ jsx28(
|
|
2374
2833
|
"input",
|
|
2375
2834
|
{
|
|
2376
2835
|
type: "checkbox",
|
|
@@ -2386,7 +2845,7 @@ function DataGrid({
|
|
|
2386
2845
|
if (!column || hasHeaderGroups && !column.headerGroup) return null;
|
|
2387
2846
|
return renderLeafHeaderCell(column);
|
|
2388
2847
|
}),
|
|
2389
|
-
!hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */
|
|
2848
|
+
!hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */ jsx28(
|
|
2390
2849
|
"th",
|
|
2391
2850
|
{
|
|
2392
2851
|
className: rowActionsHeaderCellProps.className,
|
|
@@ -2397,9 +2856,9 @@ function DataGrid({
|
|
|
2397
2856
|
] }, headerGroup.id)
|
|
2398
2857
|
] }, headerGroup.id);
|
|
2399
2858
|
}),
|
|
2400
|
-
hasFilterRow && /* @__PURE__ */
|
|
2401
|
-
showDetailColumn && /* @__PURE__ */
|
|
2402
|
-
showSelectionColumn && /* @__PURE__ */
|
|
2859
|
+
hasFilterRow && /* @__PURE__ */ jsxs18("tr", { "data-testid": "filter-row", className: "divide-x divide-border", children: [
|
|
2860
|
+
showDetailColumn && /* @__PURE__ */ jsx28("th", { className: detailHeaderCellProps.className, style: detailHeaderCellProps.style }),
|
|
2861
|
+
showSelectionColumn && /* @__PURE__ */ jsx28(
|
|
2403
2862
|
"th",
|
|
2404
2863
|
{
|
|
2405
2864
|
className: selectionHeaderCellProps.className,
|
|
@@ -2408,9 +2867,9 @@ function DataGrid({
|
|
|
2408
2867
|
),
|
|
2409
2868
|
visibleColumns.map((column) => {
|
|
2410
2869
|
const cellProps = filterHeaderCellPropsByColumn.get(column.id);
|
|
2411
|
-
return /* @__PURE__ */
|
|
2870
|
+
return /* @__PURE__ */ jsx28("th", { style: cellProps?.style, className: cellProps?.className, children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null }, column.id);
|
|
2412
2871
|
}),
|
|
2413
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
2872
|
+
showRowActionsColumn && /* @__PURE__ */ jsx28(
|
|
2414
2873
|
"th",
|
|
2415
2874
|
{
|
|
2416
2875
|
className: rowActionsHeaderCellProps.className,
|
|
@@ -2419,19 +2878,19 @@ function DataGrid({
|
|
|
2419
2878
|
)
|
|
2420
2879
|
] })
|
|
2421
2880
|
] }),
|
|
2422
|
-
rows.length === 0 ? /* @__PURE__ */
|
|
2423
|
-
paddingTop > 0 && /* @__PURE__ */
|
|
2881
|
+
rows.length === 0 ? /* @__PURE__ */ jsx28("tbody", { children: /* @__PURE__ */ jsx28("tr", { children: /* @__PURE__ */ jsx28("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? "Loading..." : "No results." }) }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs18(Fragment3, { children: [
|
|
2882
|
+
paddingTop > 0 && /* @__PURE__ */ jsx28("tbody", { children: /* @__PURE__ */ jsx28("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx28("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }) }),
|
|
2424
2883
|
virtualItems.map(
|
|
2425
2884
|
(virtualItem) => renderRow(tableRows[virtualItem.index], (el) => virtualizer.measureElement(el))
|
|
2426
2885
|
),
|
|
2427
|
-
paddingBottom > 0 && /* @__PURE__ */
|
|
2886
|
+
paddingBottom > 0 && /* @__PURE__ */ jsx28("tbody", { children: /* @__PURE__ */ jsx28("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx28("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingBottom } }) }) })
|
|
2428
2887
|
] }) : groupedBuckets ? groupedBuckets.map((bucket) => renderGroupedBucket(bucket)) : tableRows.map((row) => renderRow(row))
|
|
2429
2888
|
] })
|
|
2430
2889
|
}
|
|
2431
2890
|
)
|
|
2432
2891
|
] }),
|
|
2433
|
-
showPagination && /* @__PURE__ */
|
|
2434
|
-
/* @__PURE__ */
|
|
2892
|
+
showPagination && /* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center justify-between text-sm", children: [
|
|
2893
|
+
/* @__PURE__ */ jsxs18("span", { children: [
|
|
2435
2894
|
"Page ",
|
|
2436
2895
|
state.page + 1,
|
|
2437
2896
|
" of ",
|
|
@@ -2442,8 +2901,8 @@ function DataGrid({
|
|
|
2442
2901
|
rowCount === 1 ? "" : "s",
|
|
2443
2902
|
")"
|
|
2444
2903
|
] }),
|
|
2445
|
-
/* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
2904
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex gap-2", children: [
|
|
2905
|
+
/* @__PURE__ */ jsx28(
|
|
2447
2906
|
Button,
|
|
2448
2907
|
{
|
|
2449
2908
|
variant: "outline",
|
|
@@ -2453,7 +2912,7 @@ function DataGrid({
|
|
|
2453
2912
|
children: "Previous"
|
|
2454
2913
|
}
|
|
2455
2914
|
),
|
|
2456
|
-
/* @__PURE__ */
|
|
2915
|
+
/* @__PURE__ */ jsx28(
|
|
2457
2916
|
Button,
|
|
2458
2917
|
{
|
|
2459
2918
|
variant: "outline",
|
|
@@ -2472,7 +2931,7 @@ function DataGrid({
|
|
|
2472
2931
|
// src/tree/TreeDataGrid.tsx
|
|
2473
2932
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
2474
2933
|
import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
|
|
2475
|
-
import { useEffect as
|
|
2934
|
+
import { useEffect as useEffect10, useMemo as useMemo8, useRef as useRef8 } from "react";
|
|
2476
2935
|
|
|
2477
2936
|
// src/tree/flattenTree.ts
|
|
2478
2937
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -2517,7 +2976,7 @@ function computeSelectionStates(roots, accessors, childrenOverride, selectedIds)
|
|
|
2517
2976
|
}
|
|
2518
2977
|
|
|
2519
2978
|
// src/tree/useTreeState.ts
|
|
2520
|
-
import { useCallback as useCallback3, useMemo as useMemo7, useState as
|
|
2979
|
+
import { useCallback as useCallback3, useMemo as useMemo7, useState as useState9 } from "react";
|
|
2521
2980
|
function useTreeState({
|
|
2522
2981
|
data,
|
|
2523
2982
|
getRowId,
|
|
@@ -2529,7 +2988,7 @@ function useTreeState({
|
|
|
2529
2988
|
childrenMap: controlledChildrenMap,
|
|
2530
2989
|
onChildrenMapChange
|
|
2531
2990
|
}) {
|
|
2532
|
-
const [internalExpanded, setInternalExpanded] =
|
|
2991
|
+
const [internalExpanded, setInternalExpanded] = useState9({});
|
|
2533
2992
|
const expanded = controlledExpanded ?? internalExpanded;
|
|
2534
2993
|
const setExpanded = useCallback3(
|
|
2535
2994
|
(updater) => {
|
|
@@ -2541,7 +3000,7 @@ function useTreeState({
|
|
|
2541
3000
|
},
|
|
2542
3001
|
[controlledExpanded, onExpandedChange]
|
|
2543
3002
|
);
|
|
2544
|
-
const [internalChildrenMap, setInternalChildrenMap] =
|
|
3003
|
+
const [internalChildrenMap, setInternalChildrenMap] = useState9(/* @__PURE__ */ new Map());
|
|
2545
3004
|
const childrenMap = controlledChildrenMap ?? internalChildrenMap;
|
|
2546
3005
|
const setChildrenMap = useCallback3(
|
|
2547
3006
|
(updater) => {
|
|
@@ -2553,8 +3012,8 @@ function useTreeState({
|
|
|
2553
3012
|
},
|
|
2554
3013
|
[controlledChildrenMap, onChildrenMapChange]
|
|
2555
3014
|
);
|
|
2556
|
-
const [loadingIds, setLoadingIds] =
|
|
2557
|
-
const [errorIds, setErrorIds] =
|
|
3015
|
+
const [loadingIds, setLoadingIds] = useState9(/* @__PURE__ */ new Set());
|
|
3016
|
+
const [errorIds, setErrorIds] = useState9(/* @__PURE__ */ new Map());
|
|
2558
3017
|
const resolveHasChildren = useMemo7(
|
|
2559
3018
|
() => hasChildren ?? ((row) => (getChildren(row)?.length ?? 0) > 0),
|
|
2560
3019
|
[hasChildren, getChildren]
|
|
@@ -2634,12 +3093,11 @@ function useTreeState({
|
|
|
2634
3093
|
}
|
|
2635
3094
|
|
|
2636
3095
|
// src/tree/TreeDataGrid.tsx
|
|
2637
|
-
import { Fragment as Fragment4, jsx as
|
|
3096
|
+
import { Fragment as Fragment4, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2638
3097
|
var EMPTY_SELECTED_IDS = /* @__PURE__ */ new Set();
|
|
2639
3098
|
var UNCHECKED_STATE = { checked: false, indeterminate: false };
|
|
2640
|
-
function renderCell(column, row) {
|
|
2641
|
-
|
|
2642
|
-
return column.cell ? column.cell(value, row) : defaultFormat(column, value);
|
|
3099
|
+
function renderCell(column, row, editingCtx) {
|
|
3100
|
+
return renderEditableCell(column, row, getColumnValue(column, row), editingCtx);
|
|
2643
3101
|
}
|
|
2644
3102
|
function TreeCell({
|
|
2645
3103
|
flatRow,
|
|
@@ -2648,10 +3106,11 @@ function TreeCell({
|
|
|
2648
3106
|
isLoading,
|
|
2649
3107
|
error,
|
|
2650
3108
|
onToggle,
|
|
2651
|
-
onRetry
|
|
3109
|
+
onRetry,
|
|
3110
|
+
editingCtx
|
|
2652
3111
|
}) {
|
|
2653
|
-
return /* @__PURE__ */
|
|
2654
|
-
flatRow.hasChildren ? /* @__PURE__ */
|
|
3112
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1", style: { paddingLeft: flatRow.depth * indentSize }, children: [
|
|
3113
|
+
flatRow.hasChildren ? /* @__PURE__ */ jsx29(
|
|
2655
3114
|
"button",
|
|
2656
3115
|
{
|
|
2657
3116
|
type: "button",
|
|
@@ -2663,14 +3122,14 @@ function TreeCell({
|
|
|
2663
3122
|
"aria-label": flatRow.isExpanded ? "Collapse" : "Expand",
|
|
2664
3123
|
"aria-expanded": flatRow.isExpanded,
|
|
2665
3124
|
className: "flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-50",
|
|
2666
|
-
children: isLoading ? /* @__PURE__ */
|
|
3125
|
+
children: isLoading ? /* @__PURE__ */ jsx29(Loader22, { className: "h-3.5 w-3.5 animate-spin", "aria-hidden": "true" }) : flatRow.isExpanded ? /* @__PURE__ */ jsx29(ChevronDown2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx29(ChevronRight2, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2667
3126
|
}
|
|
2668
|
-
) : /* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
2670
|
-
flatRow.isExpanded && error ? /* @__PURE__ */
|
|
2671
|
-
/* @__PURE__ */
|
|
3127
|
+
) : /* @__PURE__ */ jsx29("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
3128
|
+
/* @__PURE__ */ jsx29("span", { className: "min-w-0 flex-1 truncate", children: renderCell(column, flatRow.row, editingCtx) }),
|
|
3129
|
+
flatRow.isExpanded && error ? /* @__PURE__ */ jsxs19("span", { className: "ml-1 flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
|
|
3130
|
+
/* @__PURE__ */ jsx29(AlertCircle, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
2672
3131
|
"Failed to load.",
|
|
2673
|
-
/* @__PURE__ */
|
|
3132
|
+
/* @__PURE__ */ jsx29("button", { type: "button", className: "underline underline-offset-2", onClick: onRetry, children: "Retry" })
|
|
2674
3133
|
] }) : null
|
|
2675
3134
|
] });
|
|
2676
3135
|
}
|
|
@@ -2698,12 +3157,14 @@ function TreeDataGrid({
|
|
|
2698
3157
|
onSelectedIdsChange,
|
|
2699
3158
|
getRowSelectionState,
|
|
2700
3159
|
isRowSelectionDisabled,
|
|
2701
|
-
zebra = true
|
|
3160
|
+
zebra = true,
|
|
3161
|
+
editing
|
|
2702
3162
|
}) {
|
|
2703
3163
|
const accessors = useMemo8(
|
|
2704
3164
|
() => ({ getRowId, getChildren, hasChildren }),
|
|
2705
3165
|
[getRowId, getChildren, hasChildren]
|
|
2706
3166
|
);
|
|
3167
|
+
const editingState = useEditingState(editing, getRowId);
|
|
2707
3168
|
const { expanded, childrenMap, loadingIds, errorIds, toggleExpand, retry, expandToLevel } = useTreeState({
|
|
2708
3169
|
data,
|
|
2709
3170
|
getRowId,
|
|
@@ -2715,8 +3176,8 @@ function TreeDataGrid({
|
|
|
2715
3176
|
childrenMap: controlledChildrenMap,
|
|
2716
3177
|
onChildrenMapChange
|
|
2717
3178
|
});
|
|
2718
|
-
const didAutoExpand =
|
|
2719
|
-
|
|
3179
|
+
const didAutoExpand = useRef8(false);
|
|
3180
|
+
useEffect10(() => {
|
|
2720
3181
|
if (didAutoExpand.current) return;
|
|
2721
3182
|
didAutoExpand.current = true;
|
|
2722
3183
|
if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
|
|
@@ -2764,7 +3225,7 @@ function TreeDataGrid({
|
|
|
2764
3225
|
for (const column of columns) map.set(column.id, `p-2 ${alignClassName(column)}`);
|
|
2765
3226
|
return map;
|
|
2766
3227
|
}, [columns]);
|
|
2767
|
-
const scrollRef =
|
|
3228
|
+
const scrollRef = useRef8(null);
|
|
2768
3229
|
const shouldVirtualize = flatRows.length > virtualizeThreshold;
|
|
2769
3230
|
const virtualizer = useVirtualizer2({
|
|
2770
3231
|
count: flatRows.length,
|
|
@@ -2777,7 +3238,7 @@ function TreeDataGrid({
|
|
|
2777
3238
|
const rowProps = getRowProps?.(flatRow.row, flatRow.depth, index);
|
|
2778
3239
|
const rowTestId = getRowTestId?.(flatRow.row) ?? `tree-row-${flatRow.id}`;
|
|
2779
3240
|
const isOddRow = zebra && index % 2 === 1;
|
|
2780
|
-
return /* @__PURE__ */
|
|
3241
|
+
return /* @__PURE__ */ jsxs19(
|
|
2781
3242
|
"tr",
|
|
2782
3243
|
{
|
|
2783
3244
|
ref: measureRef,
|
|
@@ -2790,9 +3251,9 @@ function TreeDataGrid({
|
|
|
2790
3251
|
isOddRow && "bg-foreground/5"
|
|
2791
3252
|
) : `border-b border-border divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
|
|
2792
3253
|
children: [
|
|
2793
|
-
showSelectionColumn && /* @__PURE__ */
|
|
3254
|
+
showSelectionColumn && /* @__PURE__ */ jsx29("td", { className: "p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: (() => {
|
|
2794
3255
|
const state = resolveSelectionState(flatRow.row, flatRow.id);
|
|
2795
|
-
return /* @__PURE__ */
|
|
3256
|
+
return /* @__PURE__ */ jsx29(
|
|
2796
3257
|
Checkbox,
|
|
2797
3258
|
{
|
|
2798
3259
|
"aria-label": `Select row ${flatRow.id}`,
|
|
@@ -2803,7 +3264,7 @@ function TreeDataGrid({
|
|
|
2803
3264
|
}
|
|
2804
3265
|
);
|
|
2805
3266
|
})() }),
|
|
2806
|
-
columns.map((column) => /* @__PURE__ */
|
|
3267
|
+
columns.map((column) => /* @__PURE__ */ jsx29("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx29(
|
|
2807
3268
|
TreeCell,
|
|
2808
3269
|
{
|
|
2809
3270
|
flatRow,
|
|
@@ -2812,10 +3273,11 @@ function TreeDataGrid({
|
|
|
2812
3273
|
isLoading: loadingIds.has(flatRow.id),
|
|
2813
3274
|
error: errorIds.get(flatRow.id),
|
|
2814
3275
|
onToggle: () => toggleExpand(flatRow.row),
|
|
2815
|
-
onRetry: () => retry(flatRow.row)
|
|
3276
|
+
onRetry: () => retry(flatRow.row),
|
|
3277
|
+
editingCtx: editingState.ctx
|
|
2816
3278
|
}
|
|
2817
|
-
) : renderCell(column, flatRow.row) }, column.id)),
|
|
2818
|
-
showRowActionsColumn && rowActions && /* @__PURE__ */
|
|
3279
|
+
) : renderCell(column, flatRow.row, editingState.ctx) }, column.id)),
|
|
3280
|
+
showRowActionsColumn && rowActions && /* @__PURE__ */ jsx29("td", { className: "p-2", children: /* @__PURE__ */ jsx29(
|
|
2819
3281
|
ActionsMenu,
|
|
2820
3282
|
{
|
|
2821
3283
|
items: rowActions,
|
|
@@ -2831,60 +3293,80 @@ function TreeDataGrid({
|
|
|
2831
3293
|
const virtualItems = shouldVirtualize ? virtualizer.getVirtualItems() : [];
|
|
2832
3294
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
2833
3295
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
2834
|
-
return /* @__PURE__ */
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
}
|
|
2872
|
-
) })
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
3296
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", "data-testid": "tree-datagrid", children: [
|
|
3297
|
+
editing && editingState.pendingEdits.size > 0 && /* @__PURE__ */ jsx29(
|
|
3298
|
+
EditingBar,
|
|
3299
|
+
{
|
|
3300
|
+
editing,
|
|
3301
|
+
pendingRowCount: editingState.pendingEdits.size,
|
|
3302
|
+
editErrors: editingState.editErrors,
|
|
3303
|
+
onSave: () => void editingState.handleSaveEdits(),
|
|
3304
|
+
onDiscard: editingState.handleDiscardEdits,
|
|
3305
|
+
testIdPrefix: "tree-datagrid"
|
|
3306
|
+
}
|
|
3307
|
+
),
|
|
3308
|
+
/* @__PURE__ */ jsx29(
|
|
3309
|
+
"div",
|
|
3310
|
+
{
|
|
3311
|
+
ref: scrollRef,
|
|
3312
|
+
className: shouldVirtualize ? "overflow-y-auto" : void 0,
|
|
3313
|
+
style: shouldVirtualize ? { maxHeight: maxBodyHeight } : void 0,
|
|
3314
|
+
children: /* @__PURE__ */ jsxs19("table", { className: "w-full border-collapse text-sm", children: [
|
|
3315
|
+
/* @__PURE__ */ jsx29("thead", { children: /* @__PURE__ */ jsxs19("tr", { className: "divide-x divide-border", children: [
|
|
3316
|
+
showSelectionColumn && /* @__PURE__ */ jsx29("th", { className: "border-b border-border p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: /* @__PURE__ */ jsx29(
|
|
3317
|
+
Checkbox,
|
|
3318
|
+
{
|
|
3319
|
+
"aria-label": "Select all visible rows",
|
|
3320
|
+
checked: allVisibleSelected,
|
|
3321
|
+
onCheckedChange: toggleAllVisibleSelected
|
|
3322
|
+
}
|
|
3323
|
+
) }),
|
|
3324
|
+
columns.map((column) => /* @__PURE__ */ jsx29(
|
|
3325
|
+
"th",
|
|
3326
|
+
{
|
|
3327
|
+
style: column.width ? { width: column.width } : void 0,
|
|
3328
|
+
className: `border-b border-border p-2 font-medium ${alignClassName(column)}`,
|
|
3329
|
+
children: column.header
|
|
3330
|
+
},
|
|
3331
|
+
column.id
|
|
3332
|
+
)),
|
|
3333
|
+
showRowActionsColumn && /* @__PURE__ */ jsx29("th", { className: "border-b border-border p-2", "aria-label": "Row actions" })
|
|
3334
|
+
] }) }),
|
|
3335
|
+
/* @__PURE__ */ jsx29("tbody", { children: flatRows.length === 0 ? /* @__PURE__ */ jsx29("tr", { children: /* @__PURE__ */ jsx29("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: "No results." }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
3336
|
+
paddingTop > 0 && /* @__PURE__ */ jsx29("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx29("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
|
|
3337
|
+
virtualItems.map(
|
|
3338
|
+
(virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
|
|
3339
|
+
),
|
|
3340
|
+
paddingBottom > 0 && /* @__PURE__ */ jsx29("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx29(
|
|
3341
|
+
"td",
|
|
3342
|
+
{
|
|
3343
|
+
colSpan: totalColumnCount,
|
|
3344
|
+
style: { padding: 0, border: "none", height: paddingBottom }
|
|
3345
|
+
}
|
|
3346
|
+
) })
|
|
3347
|
+
] }) : flatRows.map((flatRow, index) => renderRow(flatRow, index)) })
|
|
3348
|
+
] })
|
|
3349
|
+
}
|
|
3350
|
+
)
|
|
3351
|
+
] });
|
|
2877
3352
|
}
|
|
2878
3353
|
export {
|
|
2879
3354
|
ActionsMenu,
|
|
3355
|
+
BooleanEditor,
|
|
2880
3356
|
BooleanFilter,
|
|
2881
3357
|
ColumnSelector,
|
|
2882
3358
|
DataGrid,
|
|
3359
|
+
DateEditor,
|
|
2883
3360
|
DateRangeFilter,
|
|
3361
|
+
EditFieldError,
|
|
3362
|
+
EditingBar,
|
|
3363
|
+
EnumEditor,
|
|
2884
3364
|
EnumFilter,
|
|
2885
3365
|
NumberComparisonFilter,
|
|
3366
|
+
NumberEditor,
|
|
2886
3367
|
NumberHistogramFilter,
|
|
2887
3368
|
NumberRangeFilter,
|
|
3369
|
+
StringEditor,
|
|
2888
3370
|
StringFilter,
|
|
2889
3371
|
TreeDataGrid,
|
|
2890
3372
|
UNARY_OPERATORS,
|
|
@@ -2894,6 +3376,7 @@ export {
|
|
|
2894
3376
|
countVisible,
|
|
2895
3377
|
defaultAlign,
|
|
2896
3378
|
defaultFormat,
|
|
3379
|
+
editErrorId,
|
|
2897
3380
|
evaluateFilter,
|
|
2898
3381
|
facetedNumberValues,
|
|
2899
3382
|
fieldKey,
|
|
@@ -2902,14 +3385,19 @@ export {
|
|
|
2902
3385
|
groupColumns,
|
|
2903
3386
|
isColumnVisible,
|
|
2904
3387
|
isCompositeFilterDescriptor,
|
|
3388
|
+
isEditable,
|
|
2905
3389
|
isFilterDescriptor,
|
|
2906
3390
|
isFilterable,
|
|
2907
3391
|
isSortable,
|
|
2908
3392
|
processClientData,
|
|
3393
|
+
renderDefaultEditWidget,
|
|
2909
3394
|
renderDefaultFilterWidget,
|
|
3395
|
+
renderEditableCell,
|
|
2910
3396
|
resolveMenuItems,
|
|
2911
3397
|
storageKeyFor,
|
|
3398
|
+
toDate,
|
|
2912
3399
|
useDebouncedCallback,
|
|
3400
|
+
useEditingState,
|
|
2913
3401
|
useGridState,
|
|
2914
3402
|
useTreeState
|
|
2915
3403
|
};
|