@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.
Files changed (50) hide show
  1. package/dist/cjs/components/datatable/datatable.js +130 -38
  2. package/dist/cjs/components/resizablepanel/resizablepanel.js +10 -1
  3. package/dist/cjs/components/table/table.js +8 -1
  4. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +110 -27
  5. package/dist/cjs/index.js +0 -2
  6. package/dist/cjs/product/recordpage/index.js +6 -1
  7. package/dist/cjs/product/recordpage/recordpage.js +20 -4
  8. package/dist/esm/components/datatable/datatable.js +131 -39
  9. package/dist/esm/components/resizablepanel/resizablepanel.js +10 -1
  10. package/dist/esm/components/table/table.js +8 -1
  11. package/dist/esm/components/tabletoolbar/tabletoolbar.js +111 -28
  12. package/dist/esm/index.js +0 -2
  13. package/dist/esm/product/recordpage/index.js +2 -0
  14. package/dist/esm/product/recordpage/recordpage.js +20 -4
  15. package/dist/styles.css +0 -272
  16. package/dist/styles.layered.css +0 -272
  17. package/dist/types/components/table/table.d.ts +14 -0
  18. package/dist/types/index.d.ts +0 -2
  19. package/dist/types/product/recordpage/index.d.ts +2 -0
  20. package/package.json +2 -12
  21. package/dist/cjs/product/recordstable/company-logos.js +0 -29
  22. package/dist/cjs/product/recordstable/index.js +0 -13
  23. package/dist/cjs/product/recordstable/recordstable.js +0 -1362
  24. package/dist/cjs/product/recordstable/recordstable.recipe.js +0 -175
  25. package/dist/cjs/product/recordstable/recordstable.tag.js +0 -26
  26. package/dist/cjs/product/taskstable/index.js +0 -7
  27. package/dist/cjs/product/taskstable/taskstable.js +0 -32
  28. package/dist/cjs/product/taskstable/taskstable.recipe.js +0 -56
  29. package/dist/esm/product/recordstable/company-logos.js +0 -26
  30. package/dist/esm/product/recordstable/index.js +0 -3
  31. package/dist/esm/product/recordstable/recordstable.js +0 -1322
  32. package/dist/esm/product/recordstable/recordstable.recipe.js +0 -172
  33. package/dist/esm/product/recordstable/recordstable.tag.js +0 -23
  34. package/dist/esm/product/taskstable/index.js +0 -2
  35. package/dist/esm/product/taskstable/taskstable.js +0 -29
  36. package/dist/esm/product/taskstable/taskstable.recipe.js +0 -53
  37. package/dist/recordstable.css +0 -240
  38. package/dist/recordstable.d.ts +0 -7
  39. package/dist/recordstable.layered.css +0 -242
  40. package/dist/taskstable.css +0 -30
  41. package/dist/taskstable.d.ts +0 -7
  42. package/dist/taskstable.layered.css +0 -32
  43. package/dist/types/product/recordstable/company-logos.d.ts +0 -1
  44. package/dist/types/product/recordstable/index.d.ts +0 -3
  45. package/dist/types/product/recordstable/recordstable.d.ts +0 -294
  46. package/dist/types/product/recordstable/recordstable.recipe.d.ts +0 -5
  47. package/dist/types/product/recordstable/recordstable.tag.d.ts +0 -15
  48. package/dist/types/product/taskstable/index.d.ts +0 -2
  49. package/dist/types/product/taskstable/taskstable.d.ts +0 -59
  50. 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
- setSelected(allSelected ? new Set() : new Set(rows.map((r) => r.id)));
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. Column scroll-into-
1441
- // view runs regardless of `height` -- the horizontal scroll container (and
1442
- // its own virtualization) exists either way; row scroll-into-view only
1443
- // makes sense once `height` gives the grid an internal vertical scroll
1444
- // position to move. `widths` is read only indirectly, through `colWidth`'s
1445
- // closure over it -- biome can't see that, but a column resize while a
1446
- // cell is selected genuinely needs to re-run this to keep it in view, so
1447
- // the dependency is real even though the lint rule can't prove it.
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
- // Sets `viewport` directly from the SAME value just assigned to the
1456
- // real DOM property, rather than waiting for a follow-up `scroll` event
1457
- // to round-trip through the `onScroll` handler above -- a real browser
1458
- // does fire one when `scrollTop`/`scrollLeft` is set programmatically,
1459
- // but relying on that would make this effect's own visible result (the
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
- if (height != null) {
1464
- const itemIndex = rowIdToItemIndex.get(selCell.id);
1465
- if (itemIndex != null) {
1466
- const itemTop = rowOffsets[itemIndex];
1467
- const itemBottom = itemTop + renderItems[itemIndex].height;
1468
- if (itemTop < el.scrollTop) {
1469
- el.scrollTop = itemTop;
1470
- setViewport((v) => ({ ...v, top: itemTop }));
1471
- }
1472
- else if (itemBottom > el.scrollTop + el.clientHeight) {
1473
- const newTop = itemBottom - el.clientHeight;
1474
- el.scrollTop = newTop;
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
- el.scrollLeft = left;
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
- el.scrollLeft = newLeft;
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), onChange: () => toggleRow(row.id) }) }) })), colSlots.map((slot) => {
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) => (0, jsx_runtime_1.jsx)("td", { ref: ref, "data-align": align, ...props }));
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
- (addingAttribute ? ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-menu", role: "dialog", "aria-label": addAttributeToViewLabel, children: nestedFieldPicker(hiddenAttrs, showAttr, searchAttributesPlaceholder, searchAttributesPlaceholder) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": viewSettingsLabel, children: [shownAttrs.map((col, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
851
- if (dragAttr !== null)
852
- e.preventDefault();
853
- }, onDrop: () => {
854
- if (dragAttr !== null)
855
- moveAttr(dragAttr, i);
856
- setDragAttr(null);
857
- }, 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) ??
858
- `${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: () => {
859
- setAddingAttribute(true);
860
- setFieldPickerPath([]);
861
- setFilterQuery("");
862
- }, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), addAttributeToViewLabel] }) })] })))] }) })), (onImportCsv ||
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.jsxs)("div", { ref: importExportMenuRef, className: "crisp-tabletoolbar-menu", role: "menu", "aria-label": importExportLabel, onKeyDown: onImportExportKeyDown, children: [onImportCsv && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
866
- onImportCsv();
867
- setOpenMenu(null);
868
- }, 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: () => {
869
- onExportCsv();
870
- setOpenMenu(null);
871
- }, 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: () => {
872
- onExportExcel();
873
- setOpenMenu(null);
874
- }, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 15, strokeWidth: 1.75 }), exportExcelLabel] })), importExportHelpHref &&
875
- (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] }) }));
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; } });