@crisp-ui-kit/crisp 0.54.11 → 0.55.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/cjs/components/datatable/datatable.js +130 -38
- package/dist/cjs/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/cjs/components/table/table.js +8 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +110 -27
- package/dist/cjs/index.js +0 -2
- package/dist/cjs/product/recordpage/index.js +6 -1
- package/dist/cjs/product/recordpage/recordpage.js +20 -4
- package/dist/esm/components/datatable/datatable.js +131 -39
- package/dist/esm/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/esm/components/table/table.js +8 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +111 -28
- package/dist/esm/index.js +0 -2
- package/dist/esm/product/recordpage/index.js +2 -0
- package/dist/esm/product/recordpage/recordpage.js +20 -4
- package/dist/styles.css +0 -272
- package/dist/styles.layered.css +0 -272
- package/dist/types/components/table/table.d.ts +14 -0
- package/dist/types/index.d.ts +0 -2
- package/dist/types/product/recordpage/index.d.ts +2 -0
- package/package.json +2 -12
- package/dist/cjs/product/recordstable/company-logos.js +0 -29
- package/dist/cjs/product/recordstable/index.js +0 -13
- package/dist/cjs/product/recordstable/recordstable.js +0 -1362
- package/dist/cjs/product/recordstable/recordstable.recipe.js +0 -175
- package/dist/cjs/product/recordstable/recordstable.tag.js +0 -26
- package/dist/cjs/product/taskstable/index.js +0 -7
- package/dist/cjs/product/taskstable/taskstable.js +0 -32
- package/dist/cjs/product/taskstable/taskstable.recipe.js +0 -56
- package/dist/esm/product/recordstable/company-logos.js +0 -26
- package/dist/esm/product/recordstable/index.js +0 -3
- package/dist/esm/product/recordstable/recordstable.js +0 -1322
- package/dist/esm/product/recordstable/recordstable.recipe.js +0 -172
- package/dist/esm/product/recordstable/recordstable.tag.js +0 -23
- package/dist/esm/product/taskstable/index.js +0 -2
- package/dist/esm/product/taskstable/taskstable.js +0 -29
- package/dist/esm/product/taskstable/taskstable.recipe.js +0 -53
- package/dist/recordstable.css +0 -240
- package/dist/recordstable.d.ts +0 -7
- package/dist/recordstable.layered.css +0 -242
- package/dist/taskstable.css +0 -30
- package/dist/taskstable.d.ts +0 -7
- package/dist/taskstable.layered.css +0 -32
- package/dist/types/product/recordstable/company-logos.d.ts +0 -1
- package/dist/types/product/recordstable/index.d.ts +0 -3
- package/dist/types/product/recordstable/recordstable.d.ts +0 -294
- package/dist/types/product/recordstable/recordstable.recipe.d.ts +0 -5
- package/dist/types/product/recordstable/recordstable.tag.d.ts +0 -15
- package/dist/types/product/taskstable/index.d.ts +0 -2
- package/dist/types/product/taskstable/taskstable.d.ts +0 -59
- package/dist/types/product/taskstable/taskstable.recipe.d.ts +0 -3
|
@@ -1071,14 +1071,48 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1071
1071
|
const colAriaIndex = (i) => ariaColIndexBase + i + 1;
|
|
1072
1072
|
const allSelected = rows.length > 0 && rows.every((r) => selected.has(r.id));
|
|
1073
1073
|
const someSelected = selected.size > 0 && !allSelected;
|
|
1074
|
+
// crisp/#782, ported from RecordsTable's own already-shipped logic: the
|
|
1075
|
+
// header checkbox speaks for the rows you can SEE. Rebuilding the whole
|
|
1076
|
+
// set from `rows` (the filtered/visible set) would silently drop any
|
|
1077
|
+
// selection an active filter is hiding -- add/remove only the visible
|
|
1078
|
+
// rows and leave the rest of `selected` alone.
|
|
1074
1079
|
function toggleAll() {
|
|
1075
|
-
|
|
1080
|
+
const next = new Set(selected);
|
|
1081
|
+
for (const r of rows) {
|
|
1082
|
+
if (allSelected)
|
|
1083
|
+
next.delete(r.id);
|
|
1084
|
+
else
|
|
1085
|
+
next.add(r.id);
|
|
1086
|
+
}
|
|
1087
|
+
setSelected(next);
|
|
1076
1088
|
}
|
|
1077
1089
|
function toggleRow(id) {
|
|
1078
1090
|
const next = new Set(selected);
|
|
1079
1091
|
next.has(id) ? next.delete(id) : next.add(id);
|
|
1080
1092
|
setSelected(next);
|
|
1081
1093
|
}
|
|
1094
|
+
// crisp/#781: Shift+Click on a row checkbox selects the whole contiguous
|
|
1095
|
+
// range from the last plain click (the anchor) to this row -- confirmed
|
|
1096
|
+
// live, the mouse counterpart to #749's Shift+Arrow keyboard gesture,
|
|
1097
|
+
// sharing the same `rowSelectAnchor` state and the same recompute-the-
|
|
1098
|
+
// whole-span shape (not accumulate) so shift-clicking back toward the
|
|
1099
|
+
// anchor shrinks the same way clicking away from it grows. A plain click
|
|
1100
|
+
// both toggles normally AND re-anchors, so the NEXT Shift+Click extends
|
|
1101
|
+
// from wherever the user last plain-clicked, matching Attio.
|
|
1102
|
+
function toggleRowOrExtend(id, shiftKey) {
|
|
1103
|
+
if (shiftKey && rowSelectAnchor != null) {
|
|
1104
|
+
const anchorIdx = rows.findIndex((r) => r.id === rowSelectAnchor);
|
|
1105
|
+
const idx = rows.findIndex((r) => r.id === id);
|
|
1106
|
+
if (anchorIdx >= 0 && idx >= 0) {
|
|
1107
|
+
const lo = Math.min(anchorIdx, idx);
|
|
1108
|
+
const hi = Math.max(anchorIdx, idx);
|
|
1109
|
+
setSelected(new Set(rows.slice(lo, hi + 1).map((r) => r.id)));
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
setRowSelectAnchor(id);
|
|
1114
|
+
toggleRow(id);
|
|
1115
|
+
}
|
|
1082
1116
|
function cycleSort(key) {
|
|
1083
1117
|
// Clicking a header drives a single sort, as before. Multi-sort is supplied
|
|
1084
1118
|
// by the caller through the `sort` prop (built in a sort popover).
|
|
@@ -1285,6 +1319,28 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1285
1319
|
setSelected(new Set(rows.map((rw) => rw.id)));
|
|
1286
1320
|
return;
|
|
1287
1321
|
}
|
|
1322
|
+
// crisp/#772: Cmd/Ctrl+ArrowUp jumps the selected cell to the first row,
|
|
1323
|
+
// Cmd/Ctrl+ArrowDown to the last -- confirmed live (Attio's own help
|
|
1324
|
+
// drawer documents "Jump to top"/"Jump to bottom" on these exact
|
|
1325
|
+
// bindings). `!e.shiftKey` guards this from stealing Cmd+Shift+Arrow,
|
|
1326
|
+
// a separate gesture (#773, extend-selection-to-first/last) that falls
|
|
1327
|
+
// through to the Shift+Arrow branch below untouched. Placed before that
|
|
1328
|
+
// branch for the same reason: without the guard, Cmd+Shift+Arrow would
|
|
1329
|
+
// still reach it (that branch doesn't check metaKey/ctrlKey either),
|
|
1330
|
+
// just not do the "jump" part -- the guard here is what keeps the two
|
|
1331
|
+
// gestures from fighting over the same keys.
|
|
1332
|
+
if ((e.metaKey || e.ctrlKey) &&
|
|
1333
|
+
!e.shiftKey &&
|
|
1334
|
+
(e.key === "ArrowUp" || e.key === "ArrowDown")) {
|
|
1335
|
+
const r0 = rows.findIndex((row) => row.id === selCell.id);
|
|
1336
|
+
if (r0 < 0)
|
|
1337
|
+
return;
|
|
1338
|
+
e.preventDefault();
|
|
1339
|
+
const nr0 = e.key === "ArrowUp" ? 0 : rows.length - 1;
|
|
1340
|
+
setSelCell({ id: rows[nr0].id, key: selCell.key });
|
|
1341
|
+
clipboardProxyRef.current?.select();
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1288
1344
|
// crisp/#749: Shift+ArrowUp/Down extends the row-checkbox selection --
|
|
1289
1345
|
// confirmed live, distinct from Shift+Click's cell-range gesture above
|
|
1290
1346
|
// (that one is `selAnchor`; this is `rowSelectAnchor`, and the two
|
|
@@ -1436,15 +1492,21 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1436
1492
|
}
|
|
1437
1493
|
setEditing(null);
|
|
1438
1494
|
}
|
|
1495
|
+
const reduceMotion = (0, core_1.usePrefersReducedMotion)();
|
|
1439
1496
|
// crisp/#577 -- keyboard nav to an off-screen (virtualized-out) cell
|
|
1440
|
-
// scrolls it into the rendered window, on both axes.
|
|
1441
|
-
//
|
|
1442
|
-
//
|
|
1443
|
-
//
|
|
1444
|
-
//
|
|
1445
|
-
//
|
|
1446
|
-
//
|
|
1447
|
-
//
|
|
1497
|
+
// scrolls it into the rendered window, on both axes. `renderItems`/
|
|
1498
|
+
// `rowOffsets` are computed unconditionally (`height == null` just makes
|
|
1499
|
+
// them a no-op elsewhere, see the comment above `renderItems`), so this
|
|
1500
|
+
// runs on both axes regardless of `height` too (crisp/#780 -- it used to
|
|
1501
|
+
// gate the vertical half on `height != null`, on the reasoning that only
|
|
1502
|
+
// `height` gives the grid an internal scroll position to move; that's
|
|
1503
|
+
// wrong when the grid's own container still scrolls without an explicit
|
|
1504
|
+
// height, e.g. inside a shorter ancestor, matching `RecordsTable`'s own
|
|
1505
|
+
// already-shipped #257 fix, which had no such gate). `widths` is read only
|
|
1506
|
+
// indirectly, through `colWidth`'s closure over it -- biome can't see
|
|
1507
|
+
// that, but a column resize while a cell is selected genuinely needs to
|
|
1508
|
+
// re-run this to keep it in view, so the dependency is real even though
|
|
1509
|
+
// the lint rule can't prove it.
|
|
1448
1510
|
// biome-ignore lint/correctness/useExhaustiveDependencies: widths is read via colWidth's closure, see comment above
|
|
1449
1511
|
React.useEffect(() => {
|
|
1450
1512
|
if (!selCell)
|
|
@@ -1452,28 +1514,37 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1452
1514
|
const el = scrollRef.current;
|
|
1453
1515
|
if (!el)
|
|
1454
1516
|
return;
|
|
1455
|
-
//
|
|
1456
|
-
//
|
|
1457
|
-
//
|
|
1458
|
-
//
|
|
1459
|
-
//
|
|
1517
|
+
// `el.scrollTo` rather than a direct `el.scrollTop =`/`el.scrollLeft =`
|
|
1518
|
+
// assignment (crisp/#780, matching RecordsTable's own #208/#257 rule):
|
|
1519
|
+
// property assignment is ALWAYS instant, so it can never honour a
|
|
1520
|
+
// consumer's own `scroll-behavior: smooth` on this container; `scrollTo`
|
|
1521
|
+
// defers to that CSS when no `behavior` is given, and only forces
|
|
1522
|
+
// `"auto"` under `prefers-reduced-motion`, which is the one case that
|
|
1523
|
+
// must win even over a host page's own smooth-scroll opt-in.
|
|
1524
|
+
const scrollTo = (opts) => el.scrollTo({
|
|
1525
|
+
...opts,
|
|
1526
|
+
...(reduceMotion ? { behavior: "auto" } : null),
|
|
1527
|
+
});
|
|
1528
|
+
// Sets `viewport` directly from the SAME value just passed to
|
|
1529
|
+
// `scrollTo`, rather than waiting for a follow-up `scroll` event to
|
|
1530
|
+
// round-trip through the `onScroll` handler above -- a real browser
|
|
1531
|
+
// does fire one when the scroll position changes programmatically, but
|
|
1532
|
+
// relying on that would make this effect's own visible result (the
|
|
1460
1533
|
// newly-selected cell actually rendering) depend on a second render
|
|
1461
1534
|
// triggered from outside React's own update, which is both slower and
|
|
1462
1535
|
// one more thing that has to be true for this to work.
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
setViewport((v) => ({ ...v, top: newTop }));
|
|
1476
|
-
}
|
|
1536
|
+
const itemIndex = rowIdToItemIndex.get(selCell.id);
|
|
1537
|
+
if (itemIndex != null) {
|
|
1538
|
+
const itemTop = rowOffsets[itemIndex];
|
|
1539
|
+
const itemBottom = itemTop + renderItems[itemIndex].height;
|
|
1540
|
+
if (itemTop < el.scrollTop) {
|
|
1541
|
+
scrollTo({ top: itemTop });
|
|
1542
|
+
setViewport((v) => ({ ...v, top: itemTop }));
|
|
1543
|
+
}
|
|
1544
|
+
else if (itemBottom > el.scrollTop + el.clientHeight) {
|
|
1545
|
+
const newTop = itemBottom - el.clientHeight;
|
|
1546
|
+
scrollTo({ top: newTop });
|
|
1547
|
+
setViewport((v) => ({ ...v, top: newTop }));
|
|
1477
1548
|
}
|
|
1478
1549
|
}
|
|
1479
1550
|
const ci = columns.findIndex((c) => c.key === selCell.key);
|
|
@@ -1483,24 +1554,24 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1483
1554
|
left += colWidth(columns[i]);
|
|
1484
1555
|
const right = left + colWidth(columns[ci]);
|
|
1485
1556
|
if (left < el.scrollLeft) {
|
|
1486
|
-
|
|
1557
|
+
scrollTo({ left });
|
|
1487
1558
|
setViewport((v) => ({ ...v, left }));
|
|
1488
1559
|
}
|
|
1489
1560
|
else if (right > el.scrollLeft + el.clientWidth) {
|
|
1490
1561
|
const newLeft = right - el.clientWidth;
|
|
1491
|
-
|
|
1562
|
+
scrollTo({ left: newLeft });
|
|
1492
1563
|
setViewport((v) => ({ ...v, left: newLeft }));
|
|
1493
1564
|
}
|
|
1494
1565
|
}
|
|
1495
1566
|
}, [
|
|
1496
1567
|
selCell,
|
|
1497
|
-
height,
|
|
1498
1568
|
columns,
|
|
1499
1569
|
widths,
|
|
1500
1570
|
selectable,
|
|
1501
1571
|
rowIdToItemIndex,
|
|
1502
1572
|
rowOffsets,
|
|
1503
1573
|
renderItems,
|
|
1574
|
+
reduceMotion,
|
|
1504
1575
|
]);
|
|
1505
1576
|
const totalCols = columns.length + (selectable ? 1 : 0) + (showGrip ? 1 : 0);
|
|
1506
1577
|
const hasSummary = columns.some((c) => c.summary || c.calc);
|
|
@@ -1874,12 +1945,33 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1874
1945
|
}, onDragEnd: () => {
|
|
1875
1946
|
setDragRowId(null);
|
|
1876
1947
|
setDropRowId(null);
|
|
1877
|
-
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.GripVertical, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" }) }) })), selectable && ((0, jsx_runtime_1.jsx)(table_1.TableCell, { className: "crisp-datatable-col-check", "aria-colindex": showGrip ? 2 : 1, ...stickyCol(-1), onClick: (e) => e.stopPropagation(), children: (0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-check", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { "aria-label": selectRowLabel(row), checked: selected.has(row.id),
|
|
1948
|
+
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.GripVertical, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" }) }) })), selectable && ((0, jsx_runtime_1.jsx)(table_1.TableCell, { className: "crisp-datatable-col-check", "aria-colindex": showGrip ? 2 : 1, ...stickyCol(-1), onClick: (e) => e.stopPropagation(), children: (0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-check", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { "aria-label": selectRowLabel(row), checked: selected.has(row.id),
|
|
1949
|
+
// preventDefault stops the native check/change
|
|
1950
|
+
// this click would otherwise also fire -- this
|
|
1951
|
+
// handler is the single source of truth so a
|
|
1952
|
+
// Shift+Click's range-select and a plain
|
|
1953
|
+
// click's toggle-and-re-anchor never race each
|
|
1954
|
+
// other (crisp/#781).
|
|
1955
|
+
onClick: (e) => {
|
|
1956
|
+
e.preventDefault();
|
|
1957
|
+
toggleRowOrExtend(row.id, e.shiftKey);
|
|
1958
|
+
}, onChange: () => { } }) }) })), colSlots.map((slot) => {
|
|
1878
1959
|
if (slot.type === "spacer") {
|
|
1879
1960
|
return ((0, jsx_runtime_1.jsx)("td", { role: "presentation", "aria-hidden": "true", style: { padding: 0, border: "none" } }, `__spacer_${slot.side}`));
|
|
1880
1961
|
}
|
|
1881
1962
|
const col = columns[slot.i];
|
|
1882
1963
|
const i = slot.i;
|
|
1964
|
+
// crisp/#779, matching RecordsTable's own #231 fix:
|
|
1965
|
+
// column 0 is the row's own identity (its name), not
|
|
1966
|
+
// a value it holds -- a screen reader crossing the
|
|
1967
|
+
// row should read "Google, Employees, 182,000", not a
|
|
1968
|
+
// bare "182,000". Spread onto every TableCell this
|
|
1969
|
+
// column can render as (every editor branch, not just
|
|
1970
|
+
// the default one), since the row-identity semantics
|
|
1971
|
+
// don't depend on which editor is open.
|
|
1972
|
+
const rowHeaderProps = i === 0
|
|
1973
|
+
? { as: "th", scope: "row" }
|
|
1974
|
+
: undefined;
|
|
1883
1975
|
const isEditing = editing?.id === row.id && editing?.key === col.key;
|
|
1884
1976
|
const value = cellValue(col, row);
|
|
1885
1977
|
const sticky = dataStickyCol(i);
|
|
@@ -1902,14 +1994,14 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1902
1994
|
// right). See the `isEditing` block below for their
|
|
1903
1995
|
// actual editor.
|
|
1904
1996
|
if (col.editable && col.editor === "switch") {
|
|
1905
|
-
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(switch_1.Switch, { "aria-label": `Edit ${col.key}`, checked: value === true || value === "true", disabled: isPending, onCheckedChange: (checked) => commitEdit(row.id, col.key, String(checked)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
1997
|
+
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(switch_1.Switch, { "aria-label": `Edit ${col.key}`, checked: value === true || value === "true", disabled: isPending, onCheckedChange: (checked) => commitEdit(row.id, col.key, String(checked)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
1906
1998
|
}
|
|
1907
1999
|
// crisp/#760: `editor: "rating"` is the same always-
|
|
1908
2000
|
// live shape as `switch` above -- clicking a star IS
|
|
1909
2001
|
// the commit gesture, confirmed live.
|
|
1910
2002
|
if (col.editable && col.editor === "rating") {
|
|
1911
2003
|
const n = typeof value === "number" ? value : Number(value);
|
|
1912
|
-
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(RatingStars, { "aria-label": `Edit ${col.key}`, value: Number.isNaN(n) ? 0 : n, max: col.maxRating ?? 5, onChange: (next) => commitEdit(row.id, col.key, String(next)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
2004
|
+
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(RatingStars, { "aria-label": `Edit ${col.key}`, value: Number.isNaN(n) ? 0 : n, max: col.maxRating ?? 5, onChange: (next) => commitEdit(row.id, col.key, String(next)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
1913
2005
|
}
|
|
1914
2006
|
// crisp/#761: `editor: "checkbox"` is a THIRD always-
|
|
1915
2007
|
// live boolean shape, distinct from `switch` --
|
|
@@ -1918,13 +2010,13 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1918
2010
|
// toggle. Reuses crisp's own `Checkbox` (already the
|
|
1919
2011
|
// measured 16px/r6/brand-fill grid checkbox).
|
|
1920
2012
|
if (col.editable && col.editor === "checkbox") {
|
|
1921
|
-
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { "aria-label": `Edit ${col.key}`, checked: value === true || value === "true", disabled: isPending, onChange: (e) => commitEdit(row.id, col.key, String(e.currentTarget.checked)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
2013
|
+
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined, children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { "aria-label": `Edit ${col.key}`, checked: value === true || value === "true", disabled: isPending, onChange: (e) => commitEdit(row.id, col.key, String(e.currentTarget.checked)) }), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
1922
2014
|
}
|
|
1923
2015
|
if (isEditing &&
|
|
1924
2016
|
(col.editor === "select" ||
|
|
1925
2017
|
col.editor === "reference" ||
|
|
1926
2018
|
col.editor === "actor")) {
|
|
1927
|
-
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined,
|
|
2019
|
+
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, className: "crisp-datatable-td--picker", "data-pending": isPending ? "" : undefined,
|
|
1928
2020
|
// Same as the plain text editor's own cell:
|
|
1929
2021
|
// opening/using the picker must not also fire
|
|
1930
2022
|
// the row's onRowClick. Escape is handled by
|
|
@@ -1938,7 +2030,7 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1938
2030
|
onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-edit-picker", children: [col.editor === "select" ? ((0, jsx_runtime_1.jsx)(DataSelectEditor, { col: col, value: value, isPending: isPending, onCommit: (v) => commitEdit(row.id, col.key, v), onCancel: () => setEditing(null) })) : ((0, jsx_runtime_1.jsx)(DataReferenceEditor, { col: col, value: value, isPending: isPending, onCommit: (v) => commitEdit(row.id, col.key, v), onCancel: () => setEditing(null) })), isPending && ((0, jsx_runtime_1.jsx)(spinner_1.Spinner, { size: 14, className: "crisp-datatable-edit-pending" }))] }), errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere }))] }, col.key));
|
|
1939
2031
|
}
|
|
1940
2032
|
if (isEditing) {
|
|
1941
|
-
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)("input", { className: "crisp-datatable-edit",
|
|
2033
|
+
return ((0, jsx_runtime_1.jsxs)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)("input", { className: "crisp-datatable-edit",
|
|
1942
2034
|
// biome-ignore lint/a11y/noAutofocus: focus the field the moment it opens
|
|
1943
2035
|
autoFocus: true, ...editorFor(col), "data-editor": editorFor(col).type, disabled: isPending, defaultValue: col.type === "date"
|
|
1944
2036
|
? toDateInputValue(value)
|
|
@@ -1997,7 +2089,7 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
1997
2089
|
const isExpanded = expandedCell?.id === row.id &&
|
|
1998
2090
|
expandedCell?.key === col.key;
|
|
1999
2091
|
const cellContent = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!isExpanded && rendered, errorHere && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-edit-error", children: errorHere })), isExpanded && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-datatable-cell-overlay", onClick: (e) => e.stopPropagation(), children: rendered }))] }));
|
|
2000
|
-
return ((0, jsx_runtime_1.jsx)(contextmenu_1.ContextMenu, { asChild: true, variant: "dark", menuLabel: cellMenuLabel, items: cellMenuItems(row, col), children: (0, jsx_runtime_1.jsx)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, className: col.editable
|
|
2092
|
+
return ((0, jsx_runtime_1.jsx)(contextmenu_1.ContextMenu, { asChild: true, variant: "dark", menuLabel: cellMenuLabel, items: cellMenuItems(row, col), children: (0, jsx_runtime_1.jsx)(table_1.TableCell, { align: alignFor(col), "aria-colindex": colAriaIndex(i), ...sticky, ...rowHeaderProps, className: col.editable
|
|
2001
2093
|
? "crisp-datatable-editable"
|
|
2002
2094
|
: undefined, "data-selected": selCell?.id === row.id && selCell?.key === col.key
|
|
2003
2095
|
? ""
|
|
@@ -163,6 +163,15 @@ function ResizablePanel({ side = "left", size, defaultSize = 280, onSizeChange,
|
|
|
163
163
|
const finalWidth = rect ? Math.round(rect.width) : width;
|
|
164
164
|
commitSize(finalWidth);
|
|
165
165
|
}
|
|
166
|
+
// crisp/#795: double-click resets to `defaultSize`, confirmed live on
|
|
167
|
+
// Attio's own record-page divider (dragged 722px -> 924px, double-click
|
|
168
|
+
// snapped it back to exactly 722px -- its own default/initial width, not
|
|
169
|
+
// some other fixed value). Reuses `commitSize`, the same commit path a
|
|
170
|
+
// drag already uses, so persistence (`storageKey`) picks up the reset the
|
|
171
|
+
// same way it picks up a drag -- no separate reset-specific write.
|
|
172
|
+
function onHandleDoubleClick() {
|
|
173
|
+
commitSize(defaultSize);
|
|
174
|
+
}
|
|
166
175
|
const maxStyle = max == null ? undefined : typeof max === "number" ? `${max}px` : max;
|
|
167
176
|
const panelSizeStyle = {
|
|
168
177
|
width,
|
|
@@ -171,6 +180,6 @@ function ResizablePanel({ side = "left", size, defaultSize = 280, onSizeChange,
|
|
|
171
180
|
};
|
|
172
181
|
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: (0, resizablepanel_recipe_1.resizablepanelRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-resizablepanel-spacer", style: floating ? { width: 0 } : { width, minWidth: min, maxWidth: maxStyle } }), (0, jsx_runtime_1.jsxs)("div", { ref: panelRef, className: "crisp-resizablepanel-panel", "data-side": side, "data-floating": floating ? "true" : "false", style: panelSizeStyle, children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-resizablepanel-inner", children: children }), (0, jsx_runtime_1.jsx)("div", { className: handleVariant === "column"
|
|
173
182
|
? "crisp-resizablepanel-handle crisp-resizablepanel-handle--column"
|
|
174
|
-
: "crisp-resizablepanel-handle", "data-side": side, "data-dragging": dragging ? "true" : undefined, "data-handle": "", onPointerDown: onHandlePointerDown, onPointerMove: onHandlePointerMove, onPointerUp: onHandlePointerUp, children: handleVariant === "column" && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-resizablepanel-handle-inner", "aria-hidden": "true" })) })] })] }));
|
|
183
|
+
: "crisp-resizablepanel-handle", "data-side": side, "data-dragging": dragging ? "true" : undefined, "data-handle": "", onPointerDown: onHandlePointerDown, onPointerMove: onHandlePointerMove, onPointerUp: onHandlePointerUp, onDoubleClick: onHandleDoubleClick, children: handleVariant === "column" && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-resizablepanel-handle-inner", "aria-hidden": "true" })) })] })] }));
|
|
175
184
|
}
|
|
176
185
|
ResizablePanel.displayName = "ResizablePanel";
|
|
@@ -64,7 +64,14 @@ exports.TableRow = React.forwardRef((props, ref) => (0, jsx_runtime_1.jsx)("tr",
|
|
|
64
64
|
exports.TableRow.displayName = "TableRow";
|
|
65
65
|
exports.TableHead = React.forwardRef(({ align, ...props }, ref) => (0, jsx_runtime_1.jsx)("th", { ref: ref, "data-align": align, ...props }));
|
|
66
66
|
exports.TableHead.displayName = "TableHead";
|
|
67
|
-
exports.TableCell = React.forwardRef(({ align, ...props }, ref) =>
|
|
67
|
+
exports.TableCell = React.forwardRef(({ align, as, ...props }, ref) => {
|
|
68
|
+
// Cast to "td", same as RecordsTable's own dynamic-tag precedent --
|
|
69
|
+
// `props` (which may carry `scope`) would otherwise need to satisfy
|
|
70
|
+
// both <td> and <th>'s JSX attribute types at once for a bare union
|
|
71
|
+
// element name.
|
|
72
|
+
const Cell = (as ?? "td");
|
|
73
|
+
return (0, jsx_runtime_1.jsx)(Cell, { ref: ref, "data-align": align, ...props });
|
|
74
|
+
});
|
|
68
75
|
exports.TableCell.displayName = "TableCell";
|
|
69
76
|
exports.TableCaption = React.forwardRef((props, ref) => (0, jsx_runtime_1.jsx)("caption", { ref: ref, ...props }));
|
|
70
77
|
exports.TableCaption.displayName = "TableCaption";
|
|
@@ -451,6 +451,12 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
451
451
|
React.useEffect(() => {
|
|
452
452
|
setImportExportTarget(importExportRef?.current ?? null);
|
|
453
453
|
}, [importExportRef]);
|
|
454
|
+
const rootRef = React.useRef(null);
|
|
455
|
+
const viewSettingsTriggerRef = React.useRef(null);
|
|
456
|
+
const viewSettingsContentRef = React.useRef(null);
|
|
457
|
+
const [viewSettingsPos, setViewSettingsPos] = React.useState({});
|
|
458
|
+
const importExportTriggerRef = React.useRef(null);
|
|
459
|
+
const [importExportPos, setImportExportPos] = React.useState({});
|
|
454
460
|
const [openMenu, setOpenMenu] = React.useState(null);
|
|
455
461
|
const [dragSort, setDragSort] = React.useState(null);
|
|
456
462
|
const [filterQuery, setFilterQuery] = React.useState("");
|
|
@@ -478,6 +484,65 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
478
484
|
// built here -- hiding an attribute is a trailing control instead, see
|
|
479
485
|
// the hide button below).
|
|
480
486
|
const [addingAttribute, setAddingAttribute] = React.useState(false);
|
|
487
|
+
// crisp/#807: `viewSettingsRef`/`importExportRef` (#766) relocate the
|
|
488
|
+
// TRIGGER out of this toolbar's own row, but their POPOVERS stayed
|
|
489
|
+
// `position: absolute` inside the (now relocated) trigger's own
|
|
490
|
+
// `.crisp-tabletoolbar-toolgroup` -- correct chrome-wise (#772 already
|
|
491
|
+
// fixed that), but its stacking is trapped inside whatever DOM branch the
|
|
492
|
+
// consumer's own `viewSettingsRef` slot lives in. A consumer header
|
|
493
|
+
// sitting in an EARLIER sibling branch than the toolbar/grid below it
|
|
494
|
+
// (GRC's own layout) has that later branch simply paint over the popover
|
|
495
|
+
// regardless of its own z-index: 30, because z-index only orders siblings
|
|
496
|
+
// WITHIN the same stacking context, and the two branches aren't one.
|
|
497
|
+
// Fixed the same way `Menu`/`Select`/`Popover` already solve this: the
|
|
498
|
+
// popover content itself portals to `document.body` (`FloatingPortal`),
|
|
499
|
+
// positioned with `placeFloating` against the trigger's own rect (a real
|
|
500
|
+
// `position: fixed` box, anchored by viewport coordinates, escapes ANY
|
|
501
|
+
// ancestor's stacking context) -- not just relocated alongside the
|
|
502
|
+
// trigger. Wrapped in its own `tabletoolbarRecipe()` span (the same
|
|
503
|
+
// reason `ViewBarSlot` wraps the trigger) so every nested
|
|
504
|
+
// `.crisp-tabletoolbar-*` class inside the popover still resolves once
|
|
505
|
+
// portaled outside the toolbar's own root. Sort/Filter's own popovers
|
|
506
|
+
// are untouched -- they never relocate, so they were never trapped.
|
|
507
|
+
const placeViewSettingsMenu = () => {
|
|
508
|
+
const rect = viewSettingsTriggerRef.current?.getBoundingClientRect();
|
|
509
|
+
if (!rect)
|
|
510
|
+
return;
|
|
511
|
+
const { style } = (0, core_1.placeFloating)({
|
|
512
|
+
rect,
|
|
513
|
+
gap: 4,
|
|
514
|
+
flipBelow: 280,
|
|
515
|
+
anchor: viewSettingsTriggerRef.current,
|
|
516
|
+
});
|
|
517
|
+
setViewSettingsPos(style);
|
|
518
|
+
};
|
|
519
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: reposition each time it opens (and when its own screen changes, since the two screens differ in height)
|
|
520
|
+
React.useLayoutEffect(() => {
|
|
521
|
+
if (openMenu === "viewsettings")
|
|
522
|
+
placeViewSettingsMenu();
|
|
523
|
+
}, [openMenu, addingAttribute]);
|
|
524
|
+
React.useEffect(() => {
|
|
525
|
+
if (openMenu !== "viewsettings" || !viewSettingsContentRef.current)
|
|
526
|
+
return;
|
|
527
|
+
return (0, core_1.registerFloatingLayer)(viewSettingsContentRef.current);
|
|
528
|
+
}, [openMenu]);
|
|
529
|
+
const placeImportExportMenu = () => {
|
|
530
|
+
const rect = importExportTriggerRef.current?.getBoundingClientRect();
|
|
531
|
+
if (!rect)
|
|
532
|
+
return;
|
|
533
|
+
const { style } = (0, core_1.placeFloating)({
|
|
534
|
+
rect,
|
|
535
|
+
gap: 4,
|
|
536
|
+
flipBelow: 280,
|
|
537
|
+
anchor: importExportTriggerRef.current,
|
|
538
|
+
});
|
|
539
|
+
setImportExportPos(style);
|
|
540
|
+
};
|
|
541
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: reposition each time it opens
|
|
542
|
+
React.useLayoutEffect(() => {
|
|
543
|
+
if (openMenu === "importexport")
|
|
544
|
+
placeImportExportMenu();
|
|
545
|
+
}, [openMenu]);
|
|
481
546
|
// close any open menu on outside click (anything not inside a menu or its
|
|
482
547
|
// trigger) or Escape
|
|
483
548
|
React.useEffect(() => {
|
|
@@ -628,6 +693,13 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
628
693
|
close: () => setOpenMenu(null),
|
|
629
694
|
contentRef: importExportMenuRef,
|
|
630
695
|
});
|
|
696
|
+
// crisp/#807: registers the (now-portaled) Import/Export menu on the
|
|
697
|
+
// shared floating-layer stack, the same reason `Menu` itself does.
|
|
698
|
+
React.useEffect(() => {
|
|
699
|
+
if (openMenu !== "importexport" || !importExportMenuRef.current)
|
|
700
|
+
return;
|
|
701
|
+
return (0, core_1.registerFloatingLayer)(importExportMenuRef.current);
|
|
702
|
+
}, [openMenu]);
|
|
631
703
|
// #754: generalized from the Filter-only `filterFieldPicker` (#592) to
|
|
632
704
|
// also drive Sort's own field picker and View settings' add-attribute
|
|
633
705
|
// screen — all three offer the identical nested-drill-down construct on
|
|
@@ -700,7 +772,7 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
700
772
|
: sorts.length
|
|
701
773
|
? `${crispMessages["Sorted by"] ?? "Sorted by"} ${sortField}${sorts.length > 1 ? ` +${sorts.length - 1}` : ""}`
|
|
702
774
|
: sortLabel;
|
|
703
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-toolbar", "data-inline": inline ? "" : undefined, children: [showSort && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool${sorts.length ? " crisp-tabletoolbar-tool--active" : " crisp-tabletoolbar-tool--dashed"}`, onClick: () => setOpenMenu(openMenu === "sort" ? null : "sort"), "aria-haspopup": "dialog", "aria-expanded": openMenu === "sort", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), sortTriggerLabel || !sorts.length ? (sortedLabel) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-prefix", children: crispMessages["Sorted by"] ?? "Sorted by" }), " ", (0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-field", children: sortField }), sorts.length > 1 && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sorted-count", children: [" ", "+", sorts.length - 1] }))] }))] }), openMenu === "sort" && ((0, jsx_runtime_1.jsxs)("div", { ref: sortListRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": sortLabel, children: [sorts.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-empty", children: noSortsLabel })) : (sorts.map((s, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
775
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: rootRef, className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-toolbar", "data-inline": inline ? "" : undefined, children: [showSort && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool${sorts.length ? " crisp-tabletoolbar-tool--active" : " crisp-tabletoolbar-tool--dashed"}`, onClick: () => setOpenMenu(openMenu === "sort" ? null : "sort"), "aria-haspopup": "dialog", "aria-expanded": openMenu === "sort", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), sortTriggerLabel || !sorts.length ? (sortedLabel) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-prefix", children: crispMessages["Sorted by"] ?? "Sorted by" }), " ", (0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-field", children: sortField }), sorts.length > 1 && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sorted-count", children: [" ", "+", sorts.length - 1] }))] }))] }), openMenu === "sort" && ((0, jsx_runtime_1.jsxs)("div", { ref: sortListRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": sortLabel, children: [sorts.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-empty", children: noSortsLabel })) : (sorts.map((s, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
704
776
|
if (dragSort !== null)
|
|
705
777
|
e.preventDefault();
|
|
706
778
|
}, onDrop: () => {
|
|
@@ -836,7 +908,7 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
836
908
|
}, children: label }, label))) })] })) : ((0, jsx_runtime_1.jsx)("input", { className: "crisp-tabletoolbar-menu-input", type: col?.type === "number" ? "number" : "text", placeholder: filterValuePlaceholder, "aria-label": `${col?.label} filter value`,
|
|
837
909
|
// biome-ignore lint/a11y/noAutofocus: focus the value field
|
|
838
910
|
autoFocus: true, value: cond.value, onChange: (e) => patchFilter(cond.id, { value: e.target.value }) })) }))] }, cond.id));
|
|
839
|
-
}), showViewSettings && !viewSettingsTarget && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), showViewSettings && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: viewSettingsTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => {
|
|
911
|
+
}), showViewSettings && !viewSettingsTarget && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), showViewSettings && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: viewSettingsTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { ref: viewSettingsTriggerRef, type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => {
|
|
840
912
|
if (openMenu === "viewsettings") {
|
|
841
913
|
setOpenMenu(null);
|
|
842
914
|
}
|
|
@@ -846,33 +918,44 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
846
918
|
setFilterQuery("");
|
|
847
919
|
setOpenMenu("viewsettings");
|
|
848
920
|
}
|
|
849
|
-
}, "aria-haspopup": "dialog", "aria-expanded": openMenu === "viewsettings", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.SlidersHorizontal, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), viewSettingsLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "viewsettings" &&
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
921
|
+
}, "aria-haspopup": "dialog", "aria-expanded": openMenu === "viewsettings", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.SlidersHorizontal, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), viewSettingsLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "viewsettings" && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsx)("span", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)(), children: addingAttribute ? ((0, jsx_runtime_1.jsx)("div", { ref: viewSettingsContentRef, className: "crisp-tabletoolbar-menu", role: "dialog", "aria-label": addAttributeToViewLabel, style: {
|
|
922
|
+
position: "fixed",
|
|
923
|
+
zIndex: 70,
|
|
924
|
+
...viewSettingsPos,
|
|
925
|
+
}, children: nestedFieldPicker(hiddenAttrs, showAttr, searchAttributesPlaceholder, searchAttributesPlaceholder) })) : ((0, jsx_runtime_1.jsxs)("div", { ref: viewSettingsContentRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": viewSettingsLabel, style: {
|
|
926
|
+
position: "fixed",
|
|
927
|
+
zIndex: 70,
|
|
928
|
+
...viewSettingsPos,
|
|
929
|
+
}, children: [shownAttrs.map((col, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
930
|
+
if (dragAttr !== null)
|
|
931
|
+
e.preventDefault();
|
|
932
|
+
}, onDrop: () => {
|
|
933
|
+
if (dragAttr !== null)
|
|
934
|
+
moveAttr(dragAttr, i);
|
|
935
|
+
setDragAttr(null);
|
|
936
|
+
}, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-grip", "aria-label": reorderAttributeLabel, draggable: true, onDragStart: () => setDragAttr(i), onDragEnd: () => setDragAttr(null), children: (0, jsx_runtime_1.jsx)(lucide_react_1.GripVertical, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sort-optlabel crisp-tabletoolbar-sort-field", children: [col.icon ? ((0, jsx_runtime_1.jsx)(col.icon, { size: 15, strokeWidth: 1.75 })) : null, col.label] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-remove", onClick: () => hideAttr(col.key), "aria-label": hideAttributeLabel?.(col.label) ??
|
|
937
|
+
`${crispMessages.Hide ?? "Hide"} ${col.label} ${crispMessages["from view"] ?? "from view"}`, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15, strokeWidth: 1.75 }) })] }, col.key))), (0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-addrow", children: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-sort-add", onClick: () => {
|
|
938
|
+
setAddingAttribute(true);
|
|
939
|
+
setFieldPickerPath([]);
|
|
940
|
+
setFilterQuery("");
|
|
941
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), addAttributeToViewLabel] }) })] })) }) }))] }) })), (onImportCsv ||
|
|
863
942
|
onExportCsv ||
|
|
864
943
|
onExportExcel ||
|
|
865
|
-
importExportHelpHref) && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: importExportTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => setOpenMenu(openMenu === "importexport" ? null : "importexport"), "aria-haspopup": "menu", "aria-expanded": openMenu === "importexport", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), importExportLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "importexport" && ((0, jsx_runtime_1.
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
944
|
+
importExportHelpHref) && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: importExportTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { ref: importExportTriggerRef, type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => setOpenMenu(openMenu === "importexport" ? null : "importexport"), "aria-haspopup": "menu", "aria-expanded": openMenu === "importexport", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), importExportLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "importexport" && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsx)("span", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)(), children: (0, jsx_runtime_1.jsxs)("div", { ref: importExportMenuRef, className: "crisp-tabletoolbar-menu", role: "menu", "aria-label": importExportLabel, onKeyDown: onImportExportKeyDown, style: {
|
|
945
|
+
position: "fixed",
|
|
946
|
+
zIndex: 70,
|
|
947
|
+
...importExportPos,
|
|
948
|
+
}, children: [onImportCsv && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
949
|
+
onImportCsv();
|
|
950
|
+
setOpenMenu(null);
|
|
951
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 15, strokeWidth: 1.75 }), importCsvLabel] })), onImportCsv && (onExportCsv || onExportExcel) && ((0, jsx_runtime_1.jsx)("hr", { className: "crisp-tabletoolbar-menu-sep" })), onExportCsv && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
952
|
+
onExportCsv();
|
|
953
|
+
setOpenMenu(null);
|
|
954
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 15, strokeWidth: 1.75 }), exportCsvLabel] })), onExportExcel && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
955
|
+
onExportExcel();
|
|
956
|
+
setOpenMenu(null);
|
|
957
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 15, strokeWidth: 1.75 }), exportExcelLabel] })), importExportHelpHref &&
|
|
958
|
+
(onImportCsv || onExportCsv || onExportExcel) && ((0, jsx_runtime_1.jsx)("hr", { className: "crisp-tabletoolbar-menu-sep" })), importExportHelpHref && ((0, jsx_runtime_1.jsxs)("a", { className: "crisp-tabletoolbar-menu-item", role: "menuitem", href: importExportHelpHref, target: "_blank", rel: "noreferrer", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { size: 15, strokeWidth: 1.75 }), learnImportExportLabel] }))] }) }) }))] }) })), (0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-spacer" }), count != null && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-count", children: count })), children] }) }));
|
|
876
959
|
}
|
|
877
960
|
/**
|
|
878
961
|
* The Sort/Filter chip's own chrome (`.crisp-tabletoolbar-tool`), standalone
|
package/dist/cjs/index.js
CHANGED
|
@@ -102,7 +102,6 @@ __exportStar(require("./product/objectsettings"), exports);
|
|
|
102
102
|
__exportStar(require("./product/onboarding"), exports);
|
|
103
103
|
__exportStar(require("./product/recordpage"), exports);
|
|
104
104
|
__exportStar(require("./product/recordpanel"), exports);
|
|
105
|
-
__exportStar(require("./product/recordstable"), exports);
|
|
106
105
|
__exportStar(require("./product/richtext"), exports);
|
|
107
106
|
__exportStar(require("./product/savedviews"), exports);
|
|
108
107
|
__exportStar(require("./product/settingssection"), exports);
|
|
@@ -110,7 +109,6 @@ __exportStar(require("./product/settingsshell"), exports);
|
|
|
110
109
|
__exportStar(require("./product/sidebar"), exports);
|
|
111
110
|
__exportStar(require("./product/statlist"), exports);
|
|
112
111
|
__exportStar(require("./product/tasklist"), exports);
|
|
113
|
-
__exportStar(require("./product/taskstable"), exports);
|
|
114
112
|
__exportStar(require("./product/themepicker"), exports);
|
|
115
113
|
__exportStar(require("./product/trialbanner"), exports);
|
|
116
114
|
__exportStar(require("./product/viewtoggle"), exports);
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recordpageRecipe = exports.recordPageLabels = exports.RecordPage = exports.RecordDetails = void 0;
|
|
3
|
+
exports.recordpageRecipe = exports.recordPageLabels = exports.RecordPage = exports.RecordDetails = exports.useEditableField = exports.editableInputType = exports.tagTone = void 0;
|
|
4
|
+
var column_1 = require("./column");
|
|
5
|
+
Object.defineProperty(exports, "tagTone", { enumerable: true, get: function () { return column_1.tagTone; } });
|
|
6
|
+
var editable_field_1 = require("./editable-field");
|
|
7
|
+
Object.defineProperty(exports, "editableInputType", { enumerable: true, get: function () { return editable_field_1.editableInputType; } });
|
|
8
|
+
Object.defineProperty(exports, "useEditableField", { enumerable: true, get: function () { return editable_field_1.useEditableField; } });
|
|
4
9
|
var recordpage_1 = require("./recordpage");
|
|
5
10
|
Object.defineProperty(exports, "RecordDetails", { enumerable: true, get: function () { return recordpage_1.RecordDetails; } });
|
|
6
11
|
Object.defineProperty(exports, "RecordPage", { enumerable: true, get: function () { return recordpage_1.RecordPage; } });
|