@crispy-seed/data-table 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1668,6 +1668,11 @@ const ROOT_MARGIN = "160px";
1668
1668
  const elementRef = React.useRef(null);
1669
1669
  const [scrolledStart, setScrolledStart] = React.useState(false);
1670
1670
  const [scrolledEnd, setScrolledEnd] = React.useState(false);
1671
+ // The scroll container's own content-box width (0 until first measured). The
1672
+ // styled layer reads it to cap how much of a narrow viewport the sticky-left
1673
+ // pinned group may occupy (`useEffectiveColumns`) -- without a cap, a pinned
1674
+ // group wider than the container covers every scrolling column for good.
1675
+ const [viewportWidth, setViewportWidth] = React.useState(0);
1671
1676
  const [viewport, setViewport] = React.useState({
1672
1677
  scrollTop: 0,
1673
1678
  viewportHeight: 0
@@ -1688,6 +1693,7 @@ const ROOT_MARGIN = "160px";
1688
1693
  viewportHeight
1689
1694
  });
1690
1695
  }
1696
+ setViewportWidth(element.clientWidth);
1691
1697
  setScrolledStart(element.scrollLeft > 0);
1692
1698
  // A 1px slop: sub-pixel layout can leave `scrollLeft + clientWidth` a fraction
1693
1699
  // short of `scrollWidth` even when fully scrolled, which would otherwise leave
@@ -1697,16 +1703,16 @@ const ROOT_MARGIN = "160px";
1697
1703
  virtualized,
1698
1704
  rowHeight
1699
1705
  ]);
1700
- // The container can resize without scrolling (window resize, a bounded parent
1701
- // changing height) -- the viewport height feeds the window, so re-measure then too.
1706
+ // The container can resize without scrolling (window resize, rotating a phone, a
1707
+ // bounded parent changing height) -- the viewport height feeds the virtual window
1708
+ // and the width feeds the pinned-group cap, so re-measure then too.
1702
1709
  React.useEffect(()=>{
1703
1710
  const element = elementRef.current;
1704
- if (!virtualized || !element || typeof ResizeObserver === "undefined") return;
1711
+ if (!element || typeof ResizeObserver === "undefined") return;
1705
1712
  const observer = new ResizeObserver(()=>remeasure());
1706
1713
  observer.observe(element);
1707
1714
  return ()=>observer.disconnect();
1708
1715
  }, [
1709
- virtualized,
1710
1716
  remeasure
1711
1717
  ]);
1712
1718
  const scrollAreaRef = React.useCallback((node)=>{
@@ -1722,6 +1728,7 @@ const ROOT_MARGIN = "160px";
1722
1728
  scrollAreaRef,
1723
1729
  scrolledStart,
1724
1730
  scrolledEnd,
1731
+ viewportWidth,
1725
1732
  onScroll,
1726
1733
  remeasure,
1727
1734
  /** Row-virtualization state; `enabled: false` (the default) means render every row. */ virtual: {
@@ -3251,19 +3258,20 @@ function StatusCell({ value }) {
3251
3258
  * same "literal color as a computed prop" call `RatingCell`'s star fill already
3252
3259
  * makes. Shared by `ChipCell` (Feature A, single value) and `ChipListCell`/
3253
3260
  * editors.tsx's `ChipListEditor` (Feature B, multi value) so all three chip
3254
- * renderings stay byte-identical. */ function SwatchChip({ value, className, children }) {
3261
+ * renderings stay byte-identical. */ function SwatchChip({ value, label, color, className, children }) {
3255
3262
  return /*#__PURE__*/ jsxRuntime.jsxs("span", {
3256
3263
  className: className,
3257
3264
  style: {
3258
- backgroundColor: swatchColorFor(value),
3259
- color: swatchInkFor(value)
3265
+ backgroundColor: color ?? swatchColorFor(value),
3266
+ color: color ? CHIP_CUSTOM_COLOR_INK : swatchInkFor(value)
3260
3267
  },
3261
3268
  children: [
3262
- value,
3269
+ label ?? value,
3263
3270
  children
3264
3271
  ]
3265
3272
  });
3266
3273
  }
3274
+ const CHIP_CUSTOM_COLOR_INK = "#1f2937";
3267
3275
  /** `type: "chip"` (Feature A, #9) -- a single value rendered as one colored chip,
3268
3276
  * the color derived deterministically from the value string (`swatchColorFor`):
3269
3277
  * same value, same color, every render, every column. For a column like provider/
@@ -3276,6 +3284,14 @@ function StatusCell({ value }) {
3276
3284
  className: className
3277
3285
  });
3278
3286
  }
3287
+ /** The `label`/`color` a `chipOptions` entry gives `tag`, spread onto its chip so a
3288
+ * tag looks identical in the closed cell and in the editor's option list. */ function optionProps(chipOptions, tag) {
3289
+ const option = chipOptions?.find((entry)=>entry.value === tag);
3290
+ return option ? {
3291
+ label: option.label,
3292
+ color: option.color
3293
+ } : {};
3294
+ }
3279
3295
  // Feature B rework (#8) -- the chip-list DISPLAY row's own gap, mirrored from the
3280
3296
  // qvism recipe's `chipList` slot (`packages/qvism-preset/src/recipes/data-table.ts`'s
3281
3297
  // `CHIP_GAP`, measured live off Attio at 3px between chips). Kept as a literal here
@@ -3308,7 +3324,7 @@ const CHIP_LIST_GAP_PX = 3;
3308
3324
  * times, not just while a `ResizeObserver` fires, because widening the column back
3309
3325
  * out needs to know the width of chips currently hidden behind "+N" to decide
3310
3326
  * whether they now fit again.
3311
- */ function ChipListCell({ value, className, chipClassName, overflowClassName }) {
3327
+ */ function ChipListCell({ value, className, chipClassName, overflowClassName, chipOptions }) {
3312
3328
  const tags = Array.isArray(value) ? value.filter((tag)=>!!tag) : [];
3313
3329
  const containerRef = React__namespace.useRef(null);
3314
3330
  const measureRef = React__namespace.useRef(null);
@@ -3357,6 +3373,7 @@ const CHIP_LIST_GAP_PX = 3;
3357
3373
  children: [
3358
3374
  tags.slice(0, clampedVisible).map((tag)=>/*#__PURE__*/ jsxRuntime.jsx(SwatchChip, {
3359
3375
  value: tag,
3376
+ ...optionProps(chipOptions, tag),
3360
3377
  className: chipClassName
3361
3378
  }, tag)),
3362
3379
  overflowCount > 0 && /*#__PURE__*/ jsxRuntime.jsxs("span", {
@@ -3377,6 +3394,7 @@ const CHIP_LIST_GAP_PX = 3;
3377
3394
  },
3378
3395
  children: tags.map((tag)=>/*#__PURE__*/ jsxRuntime.jsx(SwatchChip, {
3379
3396
  value: tag,
3397
+ ...optionProps(chipOptions, tag),
3380
3398
  className: chipClassName
3381
3399
  }, tag))
3382
3400
  }),
@@ -3647,6 +3665,13 @@ function RatingCell({ value, maxRating = 5 }) {
3647
3665
  });
3648
3666
  }
3649
3667
 
3668
+ /** Share of the scroll container's width the sticky-left pinned group may occupy
3669
+ * before FURTHER pinned columns stop sticking and scroll like any other column. A
3670
+ * pinned group at or past the container's width pins every pixel of it: the
3671
+ * scrolling columns slide in underneath the sticky cells and can never be seen (a
3672
+ * 375px phone with Serial + one more pinned column showed nothing else, ever). The
3673
+ * FIRST pinned column always sticks regardless -- the entity/name column staying
3674
+ * frozen is the whole point of pinning. */ const MAX_PINNED_VIEWPORT_SHARE = 0.6;
3650
3675
  /** Fallback width (px) used to compute a pinned column's cumulative sticky offset when
3651
3676
  * it has no explicit `width` and hasn't been drag-resized -- pinning needs a STATIC
3652
3677
  * number to put in an inline `insetInlineStart`, and `table-layout: fixed` only
@@ -3666,7 +3691,7 @@ function RatingCell({ value, maxRating = 5 }) {
3666
3691
  * one and a header row built from the other drift out of sync under `table-layout:
3667
3692
  * fixed`'s own column-to-cell matching.
3668
3693
  */ function useEffectiveColumns(columns, options) {
3669
- const { visibleColumnOrder, getColumnLabel, getColumnWidth, pinnedColumnKeys } = useDataTableContext();
3694
+ const { visibleColumnOrder, getColumnLabel, getColumnWidth, pinnedColumnKeys, viewportWidth } = useDataTableContext();
3670
3695
  const { selectable, stickyFirst } = options;
3671
3696
  return React__namespace.useMemo(()=>{
3672
3697
  const byKey = new Map(columns.map((column)=>[
@@ -3692,11 +3717,14 @@ function RatingCell({ value, maxRating = 5 }) {
3692
3717
  const bPinned = pinnedSet.has(b) ? 0 : 1;
3693
3718
  return aPinned - bPinned;
3694
3719
  });
3720
+ // 0 = not measured yet (first paint / jsdom) -- no cap rather than a guess.
3721
+ const pinBudget = viewportWidth ? viewportWidth * MAX_PINNED_VIEWPORT_SHARE : Number.POSITIVE_INFINITY;
3695
3722
  let cursor = selectable ? 40 : 0;
3696
3723
  let pinnedCount = 0;
3724
+ let budgetSpent = false;
3697
3725
  const entries = ordered.map((key)=>byKey.get(key)).filter((column)=>Boolean(column)).map((column)=>{
3698
3726
  const rawWidth = getColumnWidth(column.key) ?? column.width;
3699
- const pinned = pinnedSet.has(column.key);
3727
+ const inPinnedSet = pinnedSet.has(column.key);
3700
3728
  // Fix (0.10.4, screenshot-confirmed pinned-column overlay): a pinned column
3701
3729
  // with no explicit/resized width used to keep `width` as `undefined` here,
3702
3730
  // which `DataTableColGroup` (DataTable.tsx) renders as an AUTO `<col>` --
@@ -3716,7 +3744,15 @@ function RatingCell({ value, maxRating = 5 }) {
3716
3744
  // without its own width now always renders at exactly
3717
3745
  // `DEFAULT_PINNED_COLUMN_WIDTH`, matching what every other pinned column's
3718
3746
  // offset already assumed it would be.
3719
- const width = pinned && rawWidth === undefined ? DEFAULT_PINNED_COLUMN_WIDTH : rawWidth;
3747
+ const width = inPinnedSet && rawWidth === undefined ? DEFAULT_PINNED_COLUMN_WIDTH : rawWidth;
3748
+ // Sticks only while the group still fits the pin budget (see
3749
+ // MAX_PINNED_VIEWPORT_SHARE); the first pinned column always sticks.
3750
+ // Once one pinned column overflows, every later one scrolls too -- a narrower
3751
+ // late column must not stick past a gap.
3752
+ if (inPinnedSet && pinnedCount > 0 && cursor + (width ?? DEFAULT_PINNED_COLUMN_WIDTH) > pinBudget) {
3753
+ budgetSpent = true;
3754
+ }
3755
+ const pinned = inPinnedSet && !budgetSpent;
3720
3756
  const pinOffset = pinned ? cursor : 0;
3721
3757
  if (pinned) {
3722
3758
  cursor += width ?? DEFAULT_PINNED_COLUMN_WIDTH;
@@ -3755,7 +3791,8 @@ function RatingCell({ value, maxRating = 5 }) {
3755
3791
  getColumnWidth,
3756
3792
  pinnedColumnKeys,
3757
3793
  selectable,
3758
- stickyFirst
3794
+ stickyFirst,
3795
+ viewportWidth
3759
3796
  ]);
3760
3797
  }
3761
3798
  /** The 40px selection column's own sticky-left state -- `stickyFirst` (the table-wide
@@ -4139,7 +4176,45 @@ const TextFieldTextarea = /*#__PURE__*/ React.forwardRef(({ className, autoresiz
4139
4176
  });
4140
4177
  TextFieldTextarea.displayName = "TextFieldTextarea";
4141
4178
 
4142
- __insertCSS(".seed-data-table__root{box-sizing:border-box;position:relative;display:flex;flex-direction:column;width:100%;border-width:1px;border-style:solid;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}.seed-data-table__table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.seed-data-table__headerCell{box-sizing:border-box;position:sticky;top:0;z-index:2;vertical-align:middle;text-align:start;padding:0;height:var(--seed-dimension-x10);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium);letter-spacing:-.14px}.seed-data-table__headerCell:last-child{border-inline-end:none}.seed-data-table__headerCell[data-sortable]{cursor:pointer;user-select:none}.seed-data-table__headerCell [data-chevron]{opacity:0;transition:opacity .12s}.seed-data-table__headerCell[data-sortable]:hover [data-chevron]{opacity:.6}.seed-data-table__headerCell[data-sorted] [data-chevron]{opacity:1;color:var(--seed-color-fg-neutral)}.seed-data-table__headerCell:hover [data-column-menu]{opacity:1}.seed-data-table__headerCell [data-column-menu]:focus-visible,.seed-data-table__headerCell [data-column-menu][data-open]{opacity:1}.seed-data-table__headerCell[data-dragging]{opacity:.5}.seed-data-table__headerCell[data-sticky]{position:sticky;z-index:3;background-color:var(--seed-color-bg-layer-default)}.seed-data-table__headerCell{outline:var(--seed-dimension-x0_5) solid transparent;outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell:is(:focus-visible,[data-focus-visible]){outline:var(--seed-dimension-x0_5) solid var(--seed-color-stroke-focus-ring);outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell .seed-data-table-resize-handle{position:absolute;top:0;inset-inline-end:calc(7px / -2);width:7px;height:100%;z-index:4;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none}.seed-data-table__headerCell .seed-data-table-resize-handle-inner{width:3px;height:100%;border-radius:3px;background-color:#0298d9;opacity:0;transition:opacity .1s}.seed-data-table__headerCell .seed-data-table-resize-handle:hover .seed-data-table-resize-handle-inner,.seed-data-table__headerCell .seed-data-table-resize-handle[data-resizing] .seed-data-table-resize-handle-inner{opacity:1}.seed-data-table__headerCellInner{box-sizing:border-box;display:flex;align-items:center;width:100%;height:100%;min-width:0;gap:var(--seed-dimension-x1_5);padding-inline:var(--seed-dimension-x3)}.seed-data-table__headerCellLabel{min-width:0;flex:1 1 0%;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__headerCellIcon{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;justify-content:center;width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-subtle);border:none;background:0 0;padding:0;font:inherit;cursor:pointer}.seed-data-table__headerCellIcon[data-active]{color:var(--seed-color-fg-neutral)}.seed-data-table__headerCellIcon[data-column-menu]{opacity:0;transition:opacity .12s}.seed-data-table__row{position:relative;background-color:var(--seed-color-bg-layer-default);--seed-data-table-row-bg:var(--seed-color-bg-layer-default)}.seed-data-table__row[data-clickable]{cursor:pointer}.seed-data-table__row:is([aria-selected=true],[data-selected]){background-color:color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default));--seed-data-table-row-bg:color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default))}.seed-data-table__row:is([aria-selected=true],[data-selected]):is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default)));--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default)))}.seed-data-table__cell{box-sizing:border-box;position:relative;vertical-align:middle;text-align:start;height:var(--seed-dimension-x9);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-top:none;border-inline-start:none;padding-block:0;padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-regular);letter-spacing:-.14px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cell:not([data-editable]){user-select:none}.seed-data-table__cell:last-child{border-inline-end:none}tbody tr:last-child .seed-data-table__cell{border-bottom:none}.seed-data-table__cell[data-numeric]{text-align:end;font-variant-numeric:tabular-nums}.seed-data-table__cell[data-sticky]{position:sticky;z-index:1;background-color:var(--seed-data-table-row-bg)}.seed-data-table__cell[data-overlay-open]{overflow:visible;z-index:20}.seed-data-table__cell[data-editable]{cursor:default}.seed-data-table__cell .seed-data-table-edit-picker{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);min-width:0}.seed-data-table__cell .seed-data-table-edit-pending{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);animation:rotate .6s linear infinite}.seed-data-table__cell .seed-data-table-edit-error{position:absolute;top:100%;inset-inline-start:var(--seed-dimension-x3);inset-inline-end:var(--seed-dimension-x3);z-index:2;padding-top:2px;font-size:12px;line-height:1.3;color:var(--seed-color-fg-critical);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entity{display:flex;align-items:center;min-width:0;gap:var(--seed-dimension-x1_5)}.seed-data-table__entityName{min-width:0;font-weight:var(--seed-font-weight-medium);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entityName[data-clickable]{cursor:pointer;border:none;background:0 0;padding:0;margin:0;font-family:inherit;font-size:inherit;line-height:inherit;color:inherit;text-align:start}.seed-data-table__entityName[data-clickable]:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__tagList{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);overflow:hidden;min-width:0}.seed-data-table__entityActions{display:flex;align-items:center;gap:6px;margin-inline-start:auto;flex-shrink:0;opacity:0;transition:opacity .15s}tr:hover .seed-data-table__entityActions{opacity:1}.seed-data-table__entityActions:focus-within{opacity:1}.seed-data-table__entityAction{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;flex-shrink:0;transition:background-color .2s,color .2s,box-shadow .2s}.seed-data-table__entityAction:hover{background:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__link{color:var(--seed-color-fg-neutral);text-decoration:none;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__link:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__chip{box-sizing:border-box;display:inline-flex;align-items:center;flex-shrink:0;max-width:100%;height:22px;padding:0 4px;border-radius:7px;font-size:13px;font-weight:var(--seed-font-weight-medium);line-height:15px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__chipList{position:relative;display:flex;align-items:center;flex-wrap:nowrap;gap:3px;overflow:hidden;min-width:0;width:100%}.seed-data-table__chipOverflow{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:20px;padding:0 4px;border-radius:6px;background-color:#f6f7f7;color:#000;font-size:10px;font-weight:var(--seed-font-weight-regular);line-height:15px;white-space:nowrap}.seed-data-table__chipListEditor{display:flex;align-items:center;flex-wrap:wrap;gap:3px;min-width:0;width:100%}.seed-data-table__chipRemove{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:12px;height:12px;margin:0;margin-inline-start:2px;padding:0;border:none;border-radius:999px;background:0 0;color:inherit;opacity:.6;cursor:pointer;transition:opacity .12s,background-color .12s}.seed-data-table__chipRemove:hover{opacity:1;background-color:rgba(0,0,0,.08)}.seed-data-table__chipInput{flex:1 1 auto;min-width:40px;height:22px;margin:0;padding:0;border:none;outline:0;background:0 0;font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);letter-spacing:-.14px}.seed-data-table__expandOverlay{box-sizing:border-box;position:absolute;top:-1px;inset-inline-start:-1px;inset-inline-end:-1px;z-index:10;min-height:calc(100% + 2px);display:flex;align-items:flex-start;padding-inline:var(--seed-dimension-x3);padding-block:var(--seed-dimension-x3);background-color:var(--seed-color-bg-layer-floating);border-radius:4px;box-shadow:none;border:1px solid #266df0;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);letter-spacing:-.14px;cursor:default}.seed-data-table__expandOverlayText{width:100%;min-width:0;white-space:normal;word-break:break-word}.seed-data-table__cellSuffixRow{display:flex;align-items:center;gap:4px;min-width:0;width:100%}.seed-data-table__cellSuffixText{flex:1 1 0%;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cellSuffixIcon{flex-shrink:0;display:inline-flex;align-items:center;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent)}.seed-data-table__toolbar{box-sizing:border-box;display:flex;align-items:center;width:100%;flex-shrink:0;min-height:49px;gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x3);border-top:1px solid var(--seed-color-stroke-neutral-muted)}.seed-data-table__search{position:relative;display:inline-flex;align-items:center;flex:1 1 0%;max-width:280px}.seed-data-table__search svg{position:absolute;inset-inline-start:var(--seed-dimension-x2);width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-muted);pointer-events:none}.seed-data-table__search input{width:100%;height:var(--seed-dimension-x8);padding-inline-start:var(--seed-dimension-x7);padding-inline-end:var(--seed-dimension-x2);border:none;border-radius:var(--seed-radius-r2);background-color:var(--seed-color-bg-layer-default);box-shadow:inset 0 0 0 1px var(--seed-color-stroke-neutral-weak);font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);outline:0;transition:box-shadow .1s var(--seed-timing-function-easing)}.seed-data-table__search input::placeholder{color:var(--seed-color-fg-neutral-subtle)}.seed-data-table__search input:focus{box-shadow:inset 0 0 0 2px var(--seed-color-stroke-neutral-contrast)}.seed-data-table__count{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t3);font-variant-numeric:tabular-nums}.seed-data-table__toolbarEnd{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;gap:var(--seed-dimension-x2)}.seed-data-table__scrollArea{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;flex:1 1 auto;min-height:0;overflow-x:auto;overflow-y:auto}.seed-data-table__scrollArea[data-scrolled-start] [data-sticky-edge]{clip-path:inset(0 -38px 0 0);box-shadow:6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__scrollArea[data-scrolled-end] [data-sticky-edge-end]{clip-path:inset(0 0 0 -38px);box-shadow:-6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__footerCell{box-sizing:border-box;position:sticky;bottom:0;z-index:2;vertical-align:middle;padding:0;height:var(--seed-dimension-x9);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none}.seed-data-table__footerCell:last-child{border-inline-end:none}.seed-data-table__footerCell[data-sticky]{z-index:3}.seed-data-table__footerCell .seed-data-table-column-calc-trigger{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);width:100%;height:100%;min-width:0;margin:0;padding:0 var(--seed-dimension-x3);border:none;background:0 0;color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap;overflow:clip;cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__footerCell .seed-data-table-column-calc-trigger:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__footerCell .seed-data-table-column-calc-trigger[data-align=right]{justify-content:flex-end}.seed-data-table__footerCell .seed-data-table-column-calc-trigger svg{flex-shrink:0;opacity:.7}.seed-data-table__footerCell .seed-data-table-column-calc-placeholder{overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-value{min-width:0;flex-shrink:1;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-op{min-width:0;flex-shrink:1;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__emptyState{box-sizing:border-box;text-align:center;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t4)}.seed-data-table__loadingState{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:10px;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium)}.seed-data-table__loadingState[data-inline]{padding-block:0;padding-inline:0;height:var(--seed-dimension-x9)}.seed-data-table__loadingState .seed-data-table-loading-spinner{flex-shrink:0;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);animation:rotate .6s linear infinite}.seed-data-table__addRowCell{box-sizing:border-box;padding:0;border-top:none}.seed-data-table__addRow{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;border:none;border-top:1px solid var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);height:var(--seed-dimension-x9);gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x2);color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__addRow:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,var(--seed-color-bg-layer-default));color:var(--seed-color-fg-neutral)}.seed-data-table__addRow svg{flex-shrink:0}.seed-data-table__selectionCell{text-align:center;padding:0}.seed-data-table__bulkBar{box-sizing:border-box;position:absolute;inset-inline-start:50%;transform:translateX(-50%);bottom:var(--seed-dimension-x4);z-index:30;display:flex;align-items:center;gap:var(--seed-dimension-x3);min-height:36px;padding-inline:var(--seed-dimension-x3_5);padding-block:var(--seed-dimension-x2);border-radius:var(--seed-radius-full);box-shadow:var(--seed-shadow-s3);background-color:var(--seed-color-bg-layer-floating);color:var(--seed-color-fg-neutral);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap}.seed-data-table__bulkBar[data-above-footer]{bottom:calc(var(--seed-dimension-x4) + var(--seed-dimension-x9))}.seed-data-table__bulkBarCount{flex-shrink:0;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums}.seed-data-table__bulkBarClear{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;transition:background-color .2s,color .2s}.seed-data-table__bulkBarClear:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 8%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__bulkBarActions{display:flex;align-items:center;flex-shrink:0;gap:var(--seed-dimension-x3);padding-inline-start:var(--seed-dimension-x3);border-inline-start:1px solid color-mix(in srgb,var(--seed-color-fg-neutral) 16%,transparent)}.seed-data-table__root--surface_card{border-color:var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);border-radius:var(--seed-radius-r3)}.seed-data-table__root--surface_bleed{border-color:var(--seed-color-bg-transparent);background-color:var(--seed-color-bg-transparent)}.seed-data-table__row--interactive_true{transition:background-color .12s}.seed-data-table__row--interactive_true:is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,transparent);--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, var(--seed-color-bg-layer-default))}");
4179
+ // Row-narrowing for the toolbar's search box -- split out of DataTable.tsx the way
4180
+ // cells.tsx splits out cell-type rendering: a self-contained, independently testable
4181
+ // concern DataTable.tsx just calls, rather than inline `.filter()` calls piling up in
4182
+ // the same component that also owns markup. The toolbar's typed Filter CONDITIONS
4183
+ // (field/operator/value chips, DATATABLE-ATTIO-SPEC.md's Attio/crisp model) live in
4184
+ // `toolbar-conditions.tsx` instead, alongside the Sort/Filter chrome that manages
4185
+ // them -- this file is search only now; the old per-column "is/is not" picker
4186
+ // (`matchesFilter`/`DataTableFilterState`) is gone, replaced by that toolbar model.
4187
+ /**
4188
+ * A column's `value(row)` if it supplies one, else the raw field at `column.key` --
4189
+ * the single accessor sort/search/filter/export all read through
4190
+ * (DATATABLE-ATTIO-SPEC.md's Column API), so a consumer only teaches the table how to
4191
+ * read a value ONCE rather than once per feature.
4192
+ */ function getColumnValue(column, row) {
4193
+ return column.value ? column.value(row) : row[column.key];
4194
+ }
4195
+ /**
4196
+ * Case-insensitive substring match against a row's stringified value -- crisp's own
4197
+ * `applyFilters` "contains" semantics (`tabletoolbar.tsx`), reused here for the
4198
+ * toolbar's single free-text query. `null`/`undefined` never match a non-empty query --
4199
+ * there is no text to search.
4200
+ */ function matchesSearch(value, query) {
4201
+ if (!query) return true;
4202
+ if (value == null) return false;
4203
+ return String(value).toLowerCase().includes(query.toLowerCase());
4204
+ }
4205
+ /**
4206
+ * The toolbar's search query -- an OR across `searchable` columns, matching GRC's own
4207
+ * `useFilteredRows`. The toolbar's own typed Filter conditions apply SEPARATELY, as a
4208
+ * second pass over this function's result (`toolbar-conditions.tsx`'s
4209
+ * `applyToolbarFilters`, called by `DataTable.tsx` right after this) -- narrowing what
4210
+ * the search box already found, not the other way round.
4211
+ */ function getVisibleRows(data, columns, query) {
4212
+ const searchableColumns = columns.filter((column)=>column.searchable);
4213
+ if (!query) return data;
4214
+ return data.filter((row)=>searchableColumns.some((column)=>matchesSearch(getColumnValue(column, row), query)));
4215
+ }
4216
+
4217
+ __insertCSS(".seed-data-table__root{box-sizing:border-box;position:relative;display:flex;flex-direction:column;width:100%;border-width:1px;border-style:solid;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}.seed-data-table__table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.seed-data-table__headerCell{box-sizing:border-box;position:sticky;top:0;z-index:2;vertical-align:middle;text-align:start;padding:0;height:var(--seed-dimension-x10);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium);letter-spacing:-.14px}.seed-data-table__headerCell:last-child{border-inline-end:none}.seed-data-table__headerCell[data-sortable]{cursor:pointer;user-select:none}.seed-data-table__headerCell [data-chevron]{opacity:0;transition:opacity .12s}.seed-data-table__headerCell[data-sortable]:hover [data-chevron]{opacity:.6}.seed-data-table__headerCell[data-sorted] [data-chevron]{opacity:1;color:var(--seed-color-fg-neutral)}.seed-data-table__headerCell:hover [data-column-menu]{opacity:1}.seed-data-table__headerCell [data-column-menu]:focus-visible,.seed-data-table__headerCell [data-column-menu][data-open]{opacity:1}.seed-data-table__headerCell[data-dragging]{opacity:.5}.seed-data-table__headerCell[data-sticky]{position:sticky;z-index:3;background-color:var(--seed-color-bg-layer-default)}.seed-data-table__headerCell{outline:var(--seed-dimension-x0_5) solid transparent;outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell:is(:focus-visible,[data-focus-visible]){outline:var(--seed-dimension-x0_5) solid var(--seed-color-stroke-focus-ring);outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell .seed-data-table-resize-handle{position:absolute;top:0;inset-inline-end:calc(7px / -2);width:7px;height:100%;z-index:4;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none}.seed-data-table__headerCell .seed-data-table-resize-handle-inner{width:3px;height:100%;border-radius:3px;background-color:#0298d9;opacity:0;transition:opacity .1s}.seed-data-table__headerCell .seed-data-table-resize-handle:hover .seed-data-table-resize-handle-inner,.seed-data-table__headerCell .seed-data-table-resize-handle[data-resizing] .seed-data-table-resize-handle-inner{opacity:1}.seed-data-table__headerCellInner{box-sizing:border-box;display:flex;align-items:center;width:100%;height:100%;min-width:0;gap:var(--seed-dimension-x1_5);padding-inline:var(--seed-dimension-x3)}.seed-data-table__headerCellLabel{min-width:0;flex:1 1 0%;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__headerCellIcon{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;justify-content:center;width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-subtle);border:none;background:0 0;padding:0;font:inherit;cursor:pointer}.seed-data-table__headerCellIcon[data-active]{color:var(--seed-color-fg-neutral)}.seed-data-table__headerCellIcon[data-column-menu]{opacity:0;transition:opacity .12s}.seed-data-table__row{position:relative;background-color:var(--seed-color-bg-layer-default);--seed-data-table-row-bg:var(--seed-color-bg-layer-default)}.seed-data-table__row[data-clickable]{cursor:pointer}.seed-data-table__row:is([aria-selected=true],[data-selected]){background-color:color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default));--seed-data-table-row-bg:color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default))}.seed-data-table__row:is([aria-selected=true],[data-selected]):is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default)));--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default)))}.seed-data-table__cell{box-sizing:border-box;position:relative;vertical-align:middle;text-align:start;height:var(--seed-dimension-x9);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-top:none;border-inline-start:none;padding-block:0;padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-regular);letter-spacing:-.14px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cell:not([data-editable]){user-select:none}.seed-data-table__cell:last-child{border-inline-end:none}tbody tr:last-child .seed-data-table__cell{border-bottom:none}.seed-data-table__cell[data-numeric]{text-align:end;font-variant-numeric:tabular-nums}.seed-data-table__cell[data-sticky]{position:sticky;z-index:1;background-color:var(--seed-data-table-row-bg)}.seed-data-table__cell[data-overlay-open]{overflow:visible;z-index:20}.seed-data-table__cell[data-editable]{cursor:default}.seed-data-table__cell .seed-data-table-edit-picker{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);min-width:0}.seed-data-table__cell .seed-data-table-edit-pending{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);animation:rotate .6s linear infinite}.seed-data-table__cell .seed-data-table-edit-error{position:absolute;top:100%;inset-inline-start:var(--seed-dimension-x3);inset-inline-end:var(--seed-dimension-x3);z-index:2;padding-top:2px;font-size:12px;line-height:1.3;color:var(--seed-color-fg-critical);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entity{display:flex;align-items:center;min-width:0;gap:var(--seed-dimension-x1_5)}.seed-data-table__entityName{min-width:0;font-weight:var(--seed-font-weight-medium);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entityName[data-clickable]{cursor:pointer;border:none;background:0 0;padding:0;margin:0;font-family:inherit;font-size:inherit;line-height:inherit;color:inherit;text-align:start}.seed-data-table__entityName[data-clickable]:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__tagList{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);overflow:hidden;min-width:0}.seed-data-table__entityActions{display:flex;align-items:center;gap:6px;margin-inline-start:auto;flex-shrink:0;opacity:0;transition:opacity .15s}tr:hover .seed-data-table__entityActions{opacity:1}.seed-data-table__entityActions:focus-within{opacity:1}.seed-data-table__entityAction{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;flex-shrink:0;transition:background-color .2s,color .2s,box-shadow .2s}.seed-data-table__entityAction:hover{background:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__link{color:var(--seed-color-fg-neutral);text-decoration:none;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__link:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__chip{box-sizing:border-box;display:inline-flex;align-items:center;flex-shrink:0;max-width:100%;height:22px;padding:0 4px;border-radius:7px;font-size:13px;font-weight:var(--seed-font-weight-medium);line-height:15px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__chipList{position:relative;display:flex;align-items:center;flex-wrap:nowrap;gap:3px;overflow:hidden;min-width:0;width:100%}.seed-data-table__chipOverflow{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:20px;padding:0 4px;border-radius:6px;background-color:#f6f7f7;color:#000;font-size:10px;font-weight:var(--seed-font-weight-regular);line-height:15px;white-space:nowrap}.seed-data-table__chipPicker{display:flex;flex-direction:column;width:100%;min-width:0}.seed-data-table__chipPickerList{display:flex;flex-direction:column;max-height:240px;overflow-y:auto;padding:0 4px 4px}.seed-data-table__chipPickerRow{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:32px;margin:0;padding:4px 8px;border:none;border-radius:6px;background:0 0;font:inherit;color:inherit;text-align:start;cursor:pointer}.seed-data-table__chipPickerRow:hover{background-color:#f6f7f7}.seed-data-table__chipPickerRow:disabled{cursor:default;opacity:.6}.seed-data-table__chipPickerBox{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:16px;height:16px;border-radius:4px;border:1px solid rgba(0,0,0,.25);background-color:#fff;color:#fff}.seed-data-table__chipPickerBox[data-checked]{border-color:#266df0;background-color:#266df0}.seed-data-table__chipPickerBox svg{width:12px;height:12px}.seed-data-table__chipPickerCreate{box-sizing:border-box;display:flex;align-items:center;gap:6px;width:100%;min-height:32px;margin:0;padding:4px 8px;border:none;border-radius:6px;background:0 0;font:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);text-align:start;cursor:pointer}.seed-data-table__chipPickerCreate:hover{background-color:#f6f7f7}.seed-data-table__expandOverlay{box-sizing:border-box;position:absolute;top:-1px;inset-inline-start:-1px;inset-inline-end:-1px;z-index:10;min-height:calc(100% + 2px);display:flex;align-items:flex-start;padding-inline:var(--seed-dimension-x3);padding-block:var(--seed-dimension-x3);background-color:var(--seed-color-bg-layer-floating);border-radius:4px;box-shadow:none;border:1px solid #266df0;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);letter-spacing:-.14px;cursor:default}.seed-data-table__expandOverlayText{width:100%;min-width:0;white-space:normal;word-break:break-word}.seed-data-table__cellSuffixRow{display:flex;align-items:center;gap:4px;min-width:0;width:100%}.seed-data-table__cellSuffixText{flex:1 1 0%;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cellSuffixIcon{flex-shrink:0;display:inline-flex;align-items:center;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent)}.seed-data-table__toolbar{box-sizing:border-box;display:flex;align-items:center;width:100%;flex-shrink:0;min-height:49px;gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x3);border-top:1px solid var(--seed-color-stroke-neutral-muted)}.seed-data-table__search{position:relative;display:inline-flex;align-items:center;flex:1 1 0%;max-width:280px}.seed-data-table__search svg{position:absolute;inset-inline-start:var(--seed-dimension-x2);width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-muted);pointer-events:none}.seed-data-table__search input{width:100%;height:var(--seed-dimension-x8);padding-inline-start:var(--seed-dimension-x7);padding-inline-end:var(--seed-dimension-x2);border:none;border-radius:var(--seed-radius-r2);background-color:var(--seed-color-bg-layer-default);box-shadow:inset 0 0 0 1px var(--seed-color-stroke-neutral-weak);font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);outline:0;transition:box-shadow .1s var(--seed-timing-function-easing)}.seed-data-table__search input::placeholder{color:var(--seed-color-fg-neutral-subtle)}.seed-data-table__search input:focus{box-shadow:inset 0 0 0 2px var(--seed-color-stroke-neutral-contrast)}.seed-data-table__count{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t3);font-variant-numeric:tabular-nums}.seed-data-table__toolbarEnd{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;gap:var(--seed-dimension-x2)}.seed-data-table__scrollArea{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;flex:1 1 auto;min-height:0;overflow-x:auto;overflow-y:auto}.seed-data-table__scrollArea[data-scrolled-start] [data-sticky-edge]{clip-path:inset(0 -38px 0 0);box-shadow:6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__scrollArea[data-scrolled-end] [data-sticky-edge-end]{clip-path:inset(0 0 0 -38px);box-shadow:-6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__footerCell{box-sizing:border-box;position:sticky;bottom:0;z-index:2;vertical-align:middle;padding:0;height:var(--seed-dimension-x9);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none}.seed-data-table__footerCell:last-child{border-inline-end:none}.seed-data-table__footerCell[data-sticky]{z-index:3}.seed-data-table__footerCell .seed-data-table-column-calc-trigger{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);width:100%;height:100%;min-width:0;margin:0;padding:0 var(--seed-dimension-x3);border:none;background:0 0;color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap;overflow:clip;cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__footerCell .seed-data-table-column-calc-trigger:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__footerCell .seed-data-table-column-calc-trigger[data-align=right]{justify-content:flex-end}.seed-data-table__footerCell .seed-data-table-column-calc-trigger svg{flex-shrink:0;opacity:.7}.seed-data-table__footerCell .seed-data-table-column-calc-placeholder{overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-value{min-width:0;flex-shrink:1;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-op{min-width:0;flex-shrink:1;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__emptyState{box-sizing:border-box;text-align:center;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t4)}.seed-data-table__loadingState{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:10px;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium)}.seed-data-table__loadingState[data-inline]{padding-block:0;padding-inline:0;height:var(--seed-dimension-x9)}.seed-data-table__loadingState .seed-data-table-loading-spinner{flex-shrink:0;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);animation:rotate .6s linear infinite}.seed-data-table__addRowCell{box-sizing:border-box;padding:0;border-top:none}.seed-data-table__addRow{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;border:none;border-top:1px solid var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);height:var(--seed-dimension-x9);gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x2);color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__addRow:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,var(--seed-color-bg-layer-default));color:var(--seed-color-fg-neutral)}.seed-data-table__addRow svg{flex-shrink:0}.seed-data-table__selectionCell{text-align:center;padding:0}.seed-data-table__bulkBar{box-sizing:border-box;position:absolute;inset-inline-start:50%;transform:translateX(-50%);bottom:var(--seed-dimension-x4);z-index:30;display:flex;align-items:center;gap:var(--seed-dimension-x3);min-height:36px;padding-inline:var(--seed-dimension-x3_5);padding-block:var(--seed-dimension-x2);border-radius:var(--seed-radius-full);box-shadow:var(--seed-shadow-s3);background-color:var(--seed-color-bg-layer-floating);color:var(--seed-color-fg-neutral);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap}.seed-data-table__bulkBar[data-above-footer]{bottom:calc(var(--seed-dimension-x4) + var(--seed-dimension-x9))}.seed-data-table__bulkBarCount{flex-shrink:0;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums}.seed-data-table__bulkBarClear{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;transition:background-color .2s,color .2s}.seed-data-table__bulkBarClear:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 8%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__bulkBarActions{display:flex;align-items:center;flex-shrink:0;gap:var(--seed-dimension-x3);padding-inline-start:var(--seed-dimension-x3);border-inline-start:1px solid color-mix(in srgb,var(--seed-color-fg-neutral) 16%,transparent)}.seed-data-table__root--surface_card{border-color:var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);border-radius:var(--seed-radius-r3)}.seed-data-table__root--surface_bleed{border-color:var(--seed-color-bg-transparent);background-color:var(--seed-color-bg-transparent)}.seed-data-table__row--interactive_true{transition:background-color .12s}.seed-data-table__row--interactive_true:is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,transparent);--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, var(--seed-color-bg-layer-default))}");
4143
4218
 
4144
4219
  const createClassName = (className, variants, compoundVariants = [])=>{
4145
4220
  const variantKeys = Object.keys(variants);
@@ -4247,16 +4322,24 @@ const dataTableSlotNames = [
4247
4322
  "seed-data-table__chipOverflow"
4248
4323
  ],
4249
4324
  [
4250
- "chipListEditor",
4251
- "seed-data-table__chipListEditor"
4325
+ "chipPicker",
4326
+ "seed-data-table__chipPicker"
4327
+ ],
4328
+ [
4329
+ "chipPickerList",
4330
+ "seed-data-table__chipPickerList"
4331
+ ],
4332
+ [
4333
+ "chipPickerRow",
4334
+ "seed-data-table__chipPickerRow"
4252
4335
  ],
4253
4336
  [
4254
- "chipRemove",
4255
- "seed-data-table__chipRemove"
4337
+ "chipPickerBox",
4338
+ "seed-data-table__chipPickerBox"
4256
4339
  ],
4257
4340
  [
4258
- "chipInput",
4259
- "seed-data-table__chipInput"
4341
+ "chipPickerCreate",
4342
+ "seed-data-table__chipPickerCreate"
4260
4343
  ],
4261
4344
  [
4262
4345
  "expandOverlay",
@@ -4875,94 +4958,154 @@ function RatingEditor({ column, value, pending, onCommit }) {
4875
4958
  });
4876
4959
  }
4877
4960
  ////////////////////////////////////////////////////////////////////////////////////
4878
- // -- editable: "chip-list" (Feature B rework, #8) -- click-to-edit, Attio's own model
4879
- // rather than the always-live widget this replaced (crispy-seed#1094: every row
4880
- // rendering a live add-tag editor at once overflowed the cell and collided with
4881
- // sticky columns). `body-cells.tsx`'s `DataTableBodyCell` opens this INSIDE the
4882
- // same anchored `CellExpandOverlay` Feature C already built for a gated editor's
4883
- // expanded state, on a plain single click (no truncation gate, unlike every other
4884
- // read-only cell's peek) -- clicking a short 2-tag cell must open the editor just
4885
- // as readily as a 10-tag one. It stays open across MULTIPLE add/remove commits
4886
- // (closes only on blur/outside-click/Escape, `DataTableBodyCell`'s own effect) by
4887
- // NOT going through `useDataTableEdit`'s `isEditing` gate the way `SelectEditor`/
4888
- // `TextEditor` do -- `commitEdit` closes `editingCell` the instant a SYNC commit
4889
- // resolves (its own doc comment), which would have closed a gated chip editor
4890
- // after the very first tag. `DataTableBodyCell` instead tracks THIS editor's own
4891
- // open/closed state in its local `overlayOpen`, independent of `editingCell`.
4892
- // Every add/remove still commits the FULL next array through the same one-string
4893
- // contract every other editor already uses (`useDataTableEdit`'s own doc
4894
- // comment): `JSON.stringify(nextTags)`, which the consumer's `onEdit` parses back
4895
- // -- crisp/GRC's contract stays "one string in, no typed union", not a second
4896
- // commit shape invented for just this column.
4961
+ // -- editable: "chip-list" -- Attio's multi-select popover (0.14.0; replaces the
4962
+ // 0.10.0-0.13.0 free-text "Add..." tag adder, which stacked an empty input over the
4963
+ // chips and read as broken on an empty cell). Measured off Attio's Company
4964
+ // "Categories" cell: a search field pinned on top, below it a scrolling list of the
4965
+ // column's OPTIONS, each drawn as its own colored chip with a checkbox on the RIGHT
4966
+ // edge (filled blue when the tag is on this row); clicking a row toggles that tag
4967
+ // and the popover STAYS OPEN across toggles; typing filters the list; text matching
4968
+ // no option offers a "Create '<text>'" row (freeform tag columns, e.g. tether's
4969
+ // Labels). `body-cells.tsx`'s `DataTableBodyCell` opens this inside a portaled
4970
+ // `expandOverlay` on a plain click and closes it on blur/outside-click/Escape; it
4971
+ // tracks its own `overlayOpen` rather than `useDataTableEdit`'s `isEditing` gate,
4972
+ // since a sync commit closes `editingCell` on the first toggle.
4897
4973
  //
4898
- // Renders through `classNames.chipListEditor`, NOT the read-only `chipList` slot
4899
- // (cells.tsx's `ChipListCell`) -- the display row clips to one line with a "+N"
4900
- // badge; this editor instead WRAPS onto as many lines as it needs inside the
4901
- // overlay's own grow-in-height box, since every tag (plus the add-input) has to
4902
- // stay visible and editable at once.
4903
- function ChipListEditor({ column, value, pending, onCommit, classNames }) {
4974
+ // Commit contract is unchanged: every toggle/create commits the FULL next array as
4975
+ // `JSON.stringify(nextTags)` through the one-string `onCommit`, which the consumer's
4976
+ // `onEdit` parses back.
4977
+ //
4978
+ // Option source: `column.chipOptions` (value/label?/color?); tags already on the row
4979
+ // but absent from it are still listed (so they can be unchecked); with no
4980
+ // `chipOptions` at all, the distinct tags across the table's rows.
4981
+ /** Adds `tag` when absent, removes it when present -- the picker's one toggle. */ function toggleTag(tags, tag) {
4982
+ return tags.includes(tag) ? tags.filter((existing)=>existing !== tag) : [
4983
+ ...tags,
4984
+ tag
4985
+ ];
4986
+ }
4987
+ /** The option list a `chip-list` popover shows: declared `chipOptions` first, then any
4988
+ * selected tag not declared, then (only when nothing was declared) the distinct tags
4989
+ * across `rows`. */ function buildChipPickerOptions(column, tags, rows) {
4990
+ const seen = new Set();
4991
+ const out = [];
4992
+ function push(option) {
4993
+ if (!option.value || seen.has(option.value)) return;
4994
+ seen.add(option.value);
4995
+ out.push(option);
4996
+ }
4997
+ for (const option of column.chipOptions ?? [])push(option);
4998
+ for (const tag of tags)push({
4999
+ value: tag
5000
+ });
5001
+ if (!column.chipOptions) {
5002
+ const distinct = new Set();
5003
+ for (const row of rows){
5004
+ const raw = getColumnValue(column, row);
5005
+ if (Array.isArray(raw)) {
5006
+ for (const tag of raw)if (typeof tag === "string") distinct.add(tag);
5007
+ }
5008
+ }
5009
+ for (const tag of [
5010
+ ...distinct
5011
+ ].sort((x, y)=>x.localeCompare(y)))push({
5012
+ value: tag
5013
+ });
5014
+ }
5015
+ return out;
5016
+ }
5017
+ function ChipListEditor({ column, value, pending, onCommit, classNames, allRows = [] }) {
4904
5018
  const tags = Array.isArray(value) ? value.filter((tag)=>!!tag) : [];
4905
- const [draft, setDraft] = React__namespace.useState("");
5019
+ const built = buildChipPickerOptions(column, tags, allRows);
5020
+ // Options only ever GROW while the popover is open: with the row-derived fallback,
5021
+ // unchecking a tag that no other row carries would otherwise drop it from the list
5022
+ // and leave no way to re-check it.
5023
+ const knownRef = React__namespace.useRef([]);
5024
+ const known = knownRef.current;
5025
+ for (const option of built){
5026
+ const at = known.findIndex((entry)=>entry.value === option.value);
5027
+ if (at === -1) known.push(option);
5028
+ else known[at] = option;
5029
+ }
5030
+ const options = [
5031
+ ...known
5032
+ ];
5033
+ const optionText = React__namespace.useCallback((option)=>option.label ?? option.value, []);
5034
+ const { query, setQuery, filtered } = useSelectSearch(options, optionText);
5035
+ const trimmed = query.trim();
5036
+ const canCreate = column.chipCreatable !== false && trimmed !== "" && !options.some((option)=>option.value.toLowerCase() === trimmed.toLowerCase() || optionText(option).toLowerCase() === trimmed.toLowerCase());
4906
5037
  function commitTags(next) {
4907
5038
  onCommit(JSON.stringify(next));
4908
5039
  }
4909
- function addTag() {
4910
- const tag = draft.trim();
4911
- setDraft("");
4912
- if (!tag || tags.includes(tag)) return;
4913
- commitTags([
4914
- ...tags,
4915
- tag
4916
- ]);
4917
- }
4918
- function removeTag(tag) {
4919
- commitTags(tags.filter((existing)=>existing !== tag));
5040
+ function create() {
5041
+ setQuery("");
5042
+ commitTags(toggleTag(tags, trimmed));
4920
5043
  }
4921
- return(// biome-ignore lint/a11y/noStaticElementInteractions: not a widget -- this span never responds to interaction on ITSELF, only stops propagation of events that already occurred on a real interactive descendant (the remove buttons, the add-tag input). No role fits it because it isn't a control.
4922
- /*#__PURE__*/ jsxRuntime.jsxs("span", {
4923
- className: classNames.chipListEditor,
5044
+ return(// biome-ignore lint/a11y/noStaticElementInteractions: not a widget -- this wrapper never responds to interaction on ITSELF, only stops propagation of events that already occurred on a real interactive descendant (the search input, the option rows). No role fits it because it isn't a control.
5045
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
5046
+ className: classNames.chipPicker,
4924
5047
  onClick: (event)=>event.stopPropagation(),
4925
5048
  children: [
4926
- tags.map((tag)=>/*#__PURE__*/ jsxRuntime.jsx(SwatchChip, {
4927
- value: tag,
4928
- className: classNames.chip,
4929
- children: /*#__PURE__*/ jsxRuntime.jsx("button", {
4930
- type: "button",
4931
- disabled: pending,
4932
- "aria-label": `Remove ${tag}`,
4933
- className: classNames.chipRemove,
4934
- onClick: ()=>removeTag(tag),
4935
- children: /*#__PURE__*/ jsxRuntime.jsx(IconXmarkLine_default, {
4936
- size: 10
4937
- })
4938
- })
4939
- }, tag)),
4940
- /*#__PURE__*/ jsxRuntime.jsx("input", {
4941
- // biome-ignore lint/a11y/noAutofocus: this editor only ever mounts in response to an explicit click that just opened it (never on page load), matching `SelectEditor`'s own `open` (controlled, always-open-on-mount) -- the same UX every gated editor in this file already gives via a component the linter can't see through (`TextFieldInput`/`SelectSearchField`), just on a bare `<input>` here since `chipInput` has no such wrapper.
5049
+ /*#__PURE__*/ jsxRuntime.jsx(SelectSearchField, {
4942
5050
  autoFocus: true,
4943
- className: classNames.chipInput,
4944
- value: draft,
4945
- disabled: pending,
4946
- placeholder: tags.length ? "" : "Add…",
4947
- "aria-label": `Add tag to ${column.key}`,
4948
- onChange: (event)=>setDraft(event.target.value),
5051
+ value: query,
5052
+ onChange: setQuery,
5053
+ placeholder: column.editorSearchPlaceholder ?? "Search…",
5054
+ "aria-label": `Search ${column.key}`,
4949
5055
  onKeyDown: (event)=>{
4950
- // Escape is the ONE key this input must NOT stop propagation for: there is
4951
- // no in-progress draft state worth clearing locally (every add/remove
4952
- // already commits immediately), so it needs to bubble all the way to
4953
- // `document` -- `DataTableBodyCell`'s own Escape listener is what actually
4954
- // closes this popover. Every other key stops here, same as before, so it
4955
- // never reaches the row's own click/keyboard handling.
4956
- if (event.key === "Escape") return;
4957
- event.stopPropagation();
4958
- if (event.key === "Enter") {
4959
- event.preventDefault();
4960
- addTag();
4961
- } else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
4962
- removeTag(tags[tags.length - 1]);
4963
- }
5056
+ if (event.key !== "Enter") return;
5057
+ event.preventDefault();
5058
+ if (pending) return;
5059
+ if (canCreate) create();
5060
+ else if (trimmed && filtered.length > 0) commitTags(toggleTag(tags, filtered[0].value));
4964
5061
  }
4965
5062
  }),
5063
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
5064
+ className: classNames.chipPickerList,
5065
+ role: "group",
5066
+ "aria-label": `${column.key} options`,
5067
+ children: [
5068
+ filtered.map((option)=>{
5069
+ const checked = tags.includes(option.value);
5070
+ return /*#__PURE__*/ jsxRuntime.jsxs("button", {
5071
+ type: "button",
5072
+ role: "checkbox",
5073
+ "aria-checked": checked,
5074
+ disabled: pending,
5075
+ className: classNames.chipPickerRow,
5076
+ // Keep focus in the search field so typing keeps filtering after a toggle.
5077
+ onMouseDown: (event)=>event.preventDefault(),
5078
+ onClick: ()=>commitTags(toggleTag(tags, option.value)),
5079
+ children: [
5080
+ /*#__PURE__*/ jsxRuntime.jsx(SwatchChip, {
5081
+ value: option.value,
5082
+ label: option.label,
5083
+ color: option.color,
5084
+ className: classNames.chip
5085
+ }),
5086
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
5087
+ className: classNames.chipPickerBox,
5088
+ "data-checked": checked ? "" : undefined,
5089
+ children: checked && /*#__PURE__*/ jsxRuntime.jsx(IconCheckmarkFatFill_default, {
5090
+ "aria-hidden": "true"
5091
+ })
5092
+ })
5093
+ ]
5094
+ }, option.value);
5095
+ }),
5096
+ canCreate && /*#__PURE__*/ jsxRuntime.jsx("button", {
5097
+ type: "button",
5098
+ disabled: pending,
5099
+ className: classNames.chipPickerCreate,
5100
+ onMouseDown: (event)=>event.preventDefault(),
5101
+ onClick: create,
5102
+ children: `Create '${trimmed}'`
5103
+ }),
5104
+ !canCreate && filtered.length === 0 && /*#__PURE__*/ jsxRuntime.jsx(SelectSearchEmpty, {
5105
+ children: column.editorEmptyLabel ?? "No results"
5106
+ })
5107
+ ]
5108
+ }),
4966
5109
  pending && /*#__PURE__*/ jsxRuntime.jsx(EditPendingIndicator, {})
4967
5110
  ]
4968
5111
  }));
@@ -5051,44 +5194,6 @@ function CellExpandOverlay({ className, anchorRef, contentRef, children }) {
5051
5194
  }), document.body);
5052
5195
  }
5053
5196
 
5054
- // Row-narrowing for the toolbar's search box -- split out of DataTable.tsx the way
5055
- // cells.tsx splits out cell-type rendering: a self-contained, independently testable
5056
- // concern DataTable.tsx just calls, rather than inline `.filter()` calls piling up in
5057
- // the same component that also owns markup. The toolbar's typed Filter CONDITIONS
5058
- // (field/operator/value chips, DATATABLE-ATTIO-SPEC.md's Attio/crisp model) live in
5059
- // `toolbar-conditions.tsx` instead, alongside the Sort/Filter chrome that manages
5060
- // them -- this file is search only now; the old per-column "is/is not" picker
5061
- // (`matchesFilter`/`DataTableFilterState`) is gone, replaced by that toolbar model.
5062
- /**
5063
- * A column's `value(row)` if it supplies one, else the raw field at `column.key` --
5064
- * the single accessor sort/search/filter/export all read through
5065
- * (DATATABLE-ATTIO-SPEC.md's Column API), so a consumer only teaches the table how to
5066
- * read a value ONCE rather than once per feature.
5067
- */ function getColumnValue(column, row) {
5068
- return column.value ? column.value(row) : row[column.key];
5069
- }
5070
- /**
5071
- * Case-insensitive substring match against a row's stringified value -- crisp's own
5072
- * `applyFilters` "contains" semantics (`tabletoolbar.tsx`), reused here for the
5073
- * toolbar's single free-text query. `null`/`undefined` never match a non-empty query --
5074
- * there is no text to search.
5075
- */ function matchesSearch(value, query) {
5076
- if (!query) return true;
5077
- if (value == null) return false;
5078
- return String(value).toLowerCase().includes(query.toLowerCase());
5079
- }
5080
- /**
5081
- * The toolbar's search query -- an OR across `searchable` columns, matching GRC's own
5082
- * `useFilteredRows`. The toolbar's own typed Filter conditions apply SEPARATELY, as a
5083
- * second pass over this function's result (`toolbar-conditions.tsx`'s
5084
- * `applyToolbarFilters`, called by `DataTable.tsx` right after this) -- narrowing what
5085
- * the search box already found, not the other way round.
5086
- */ function getVisibleRows(data, columns, query) {
5087
- const searchableColumns = columns.filter((column)=>column.searchable);
5088
- if (!query) return data;
5089
- return data.filter((row)=>searchableColumns.some((column)=>matchesSearch(getColumnValue(column, row), query)));
5090
- }
5091
-
5092
5197
  // Feature C (#12) -- the click-to-expand gate: measures whether a cell's rendered
5093
5198
  // content is ACTUALLY truncated right now, so a single click only opens the
5094
5199
  // anchored overlay (editors.tsx's `CellExpandOverlay`) when there's real hidden
@@ -5154,7 +5259,10 @@ function isCellTruncated(cell) {
5154
5259
  * `overflow: visible` on every element in between and regardless of how high its
5155
5260
  * `z-index` is raised -- neither of which is a stacking-context or overflow bug
5156
5261
  * fixable from the INSIDE. A portal sidesteps it entirely by not being a
5157
- * descendant of the sticky `<td>` at all once mounted. */ function isChipListEditable(column) {
5262
+ * descendant of the sticky `<td>` at all once mounted. */ /** The table's full `data`, so an editable chip-list column with no `chipOptions` can
5263
+ * fall back to the distinct tags already present across rows. */ const DataTableRowsContext = /*#__PURE__*/ React__namespace.createContext([]);
5264
+ /** Attio's multi-select popover is wider than a narrow tags column. */ const CHIP_PICKER_MIN_WIDTH = 240;
5265
+ function isChipListEditable(column) {
5158
5266
  return !!column.editable && column.type === "chip-list";
5159
5267
  }
5160
5268
  function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyFirst, stickyLast, cellContextMenu, onViewEditHistory, cellContextMenuItems }) {
@@ -5214,6 +5322,7 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5214
5322
  const [contextMenuOpen, setContextMenuOpen] = React__namespace.useState(false);
5215
5323
  const alwaysLive = isAlwaysLiveEditable(column);
5216
5324
  const chipListEditable = isChipListEditable(column);
5325
+ const allRows = React__namespace.useContext(DataTableRowsContext);
5217
5326
  // A gated `editable` column (everything except the always-live widgets AND the
5218
5327
  // click-to-edit chip-list) opens on double-click -- Attio's own measured gesture
5219
5328
  // (crisp's #411), matched here rather than a single click, which stays "select
@@ -5243,7 +5352,10 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5243
5352
  top: rect.bottom,
5244
5353
  insetInlineStart: rect.left,
5245
5354
  insetInlineEnd: "auto",
5246
- minWidth: rect.width,
5355
+ minWidth: Math.max(rect.width, CHIP_PICKER_MIN_WIDTH),
5356
+ // The multi-select popover owns its own inner padding (search field + option
5357
+ // rows inset themselves); the overlay's cell-editor padding would double it.
5358
+ padding: 0,
5247
5359
  // Both override the SAME `expandOverlay` class properties this box also
5248
5360
  // carries (`className={classNames.expandOverlay}`, below) -- that class's
5249
5361
  // `minHeight: calc(100% + 2px)` resolves against an ANCHORED box's own
@@ -5390,7 +5502,10 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5390
5502
  chipListEditorOpen,
5391
5503
  measurePopoverPosition
5392
5504
  ]);
5393
- const overlayActive = overlayOpen && (alwaysLive || isEditing(row.id, column.key) || isPeeking(row.id, column.key));
5505
+ // Never for a chip-list cell: its picker is its own portaled popover, and the
5506
+ // in-cell overlay box would show for the first frame only (a sync commit closes
5507
+ // `isEditing` on the first toggle) and overlap the popover's top edge.
5508
+ const overlayActive = overlayOpen && !chipListEditable && (alwaysLive || isEditing(row.id, column.key) || isPeeking(row.id, column.key));
5394
5509
  const rawValue = getColumnValue(column, row);
5395
5510
  const pending = isPending(row.id, column.key);
5396
5511
  return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
@@ -5448,7 +5563,8 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5448
5563
  value: resolveEditValue(column, row, rawValue),
5449
5564
  pending: pending,
5450
5565
  onCommit: (value)=>commitEdit(row.id, column.key, value),
5451
- classNames: classNames
5566
+ classNames: classNames,
5567
+ allRows: allRows
5452
5568
  })
5453
5569
  }), document.body)
5454
5570
  ]
@@ -5502,7 +5618,8 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5502
5618
  value: rawValue,
5503
5619
  className: classNames.chipList,
5504
5620
  chipClassName: classNames.chip,
5505
- overflowClassName: classNames.chipOverflow
5621
+ overflowClassName: classNames.chipOverflow,
5622
+ chipOptions: column.chipOptions
5506
5623
  });
5507
5624
  } else if (column.editable && isEditing(rowId, column.key)) {
5508
5625
  if (column.editor === "select") {
@@ -5619,7 +5736,8 @@ function DisplayCellContent({ column, row, value, classNames, locale }) {
5619
5736
  value: value,
5620
5737
  className: classNames.chipList,
5621
5738
  chipClassName: classNames.chip,
5622
- overflowClassName: classNames.chipOverflow
5739
+ overflowClassName: classNames.chipOverflow,
5740
+ chipOptions: column.chipOptions
5623
5741
  });
5624
5742
  case "number":
5625
5743
  return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
@@ -12039,223 +12157,226 @@ function DataTableInner(props, ref) {
12039
12157
  const totalCols = columns.length + (selectable ? 1 : 0);
12040
12158
  return /*#__PURE__*/ jsxRuntime.jsx(ClassNamesProvider, {
12041
12159
  value: classNames,
12042
- children: /*#__PURE__*/ jsxRuntime.jsxs(DataTableRoot, {
12043
- ref: ref,
12044
- className: clsx(classNames.root, className),
12045
- rowIds: rowIds,
12046
- selectable: selectable,
12047
- selectedIds: selectedIds,
12048
- defaultSelectedIds: defaultSelectedIds,
12049
- onSelectionChange: onSelectionChange,
12050
- sort: sort,
12051
- defaultSort: defaultSort,
12052
- onSortChange: handleSortChange,
12053
- query: resolvedQuery,
12054
- onQueryChange: handleQueryChange,
12055
- toolbarSorts: resolvedToolbarSorts,
12056
- onToolbarSortsChange: handleToolbarSortsChange,
12057
- toolbarFilters: resolvedToolbarFilters,
12058
- onToolbarFiltersChange: handleToolbarFiltersChange,
12059
- columnKeys: columnKeys,
12060
- actionsColumnKey: actionsColumnKey,
12061
- columnOrder: columnOrder,
12062
- defaultColumnOrder: defaultColumnOrder,
12063
- onColumnOrderChange: onColumnOrderChange,
12064
- hiddenColumnKeys: hiddenColumnKeys,
12065
- defaultHiddenColumnKeys: defaultHiddenColumnKeys,
12066
- onHiddenColumnKeysChange: onHiddenColumnKeysChange,
12067
- columnWidths: columnWidths,
12068
- defaultColumnWidths: defaultColumnWidths,
12069
- onColumnWidthsChange: onColumnWidthsChange,
12070
- columnLabels: columnLabels,
12071
- defaultColumnLabels: defaultColumnLabels,
12072
- onColumnLabelsChange: onColumnLabelsChange,
12073
- pinnedColumnKeys: pinnedColumnKeys,
12074
- defaultPinnedColumnKeys: defaultPinnedColumnKeys,
12075
- onPinnedColumnKeysChange: onPinnedColumnKeysChange,
12076
- columnCalcOps: columnCalcOps,
12077
- defaultColumnCalcOps: defaultColumnCalcOps,
12078
- onColumnCalcOpsChange: onColumnCalcOpsChange,
12079
- onEdit: onEdit,
12080
- onLoadMore: onLoadMore,
12081
- hasMore: hasMore,
12082
- loadingMore: loadingMore,
12083
- virtualized: virtualized,
12084
- rowHeight: rowHeight,
12085
- overscan: overscan,
12086
- ...restProps,
12087
- children: [
12088
- onColumnsChange && /*#__PURE__*/ jsxRuntime.jsx(ColumnsChangeEffect, {
12089
- columns: columns,
12090
- onColumnsChange: onColumnsChange
12091
- }),
12092
- showToolbar && /*#__PURE__*/ jsxRuntime.jsxs(DataTableToolbar, {
12093
- children: [
12094
- searchable && /*#__PURE__*/ jsxRuntime.jsx(SearchBox, {
12095
- placeholder: searchPlaceholder,
12096
- label: searchLabel
12097
- }),
12098
- /*#__PURE__*/ jsxRuntime.jsx(SortControl, {
12099
- columns: columns
12100
- }),
12101
- /*#__PURE__*/ jsxRuntime.jsx(FilterControl, {
12102
- columns: columns
12103
- }),
12104
- (showCount || toolbarActions) && /*#__PURE__*/ jsxRuntime.jsxs(DataTableToolbarEnd, {
12105
- children: [
12106
- toolbarActions,
12107
- showCount && /*#__PURE__*/ jsxRuntime.jsx(RowCount, {
12108
- shown: sortedData.length,
12109
- total: data.length,
12110
- countLabel: countLabel
12111
- })
12112
- ]
12113
- })
12114
- ]
12115
- }),
12116
- /*#__PURE__*/ jsxRuntime.jsx(DataTableScrollBody, {
12117
- scrollProps: scrollProps,
12118
- virtualized: virtualized,
12119
- children: /*#__PURE__*/ jsxRuntime.jsxs(DataTableTable, {
12120
- "aria-rowcount": virtualized ? sortedData.length + 1 : undefined,
12160
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTableRowsContext.Provider, {
12161
+ value: data,
12162
+ children: /*#__PURE__*/ jsxRuntime.jsxs(DataTableRoot, {
12163
+ ref: ref,
12164
+ className: clsx(classNames.root, className),
12165
+ rowIds: rowIds,
12166
+ selectable: selectable,
12167
+ selectedIds: selectedIds,
12168
+ defaultSelectedIds: defaultSelectedIds,
12169
+ onSelectionChange: onSelectionChange,
12170
+ sort: sort,
12171
+ defaultSort: defaultSort,
12172
+ onSortChange: handleSortChange,
12173
+ query: resolvedQuery,
12174
+ onQueryChange: handleQueryChange,
12175
+ toolbarSorts: resolvedToolbarSorts,
12176
+ onToolbarSortsChange: handleToolbarSortsChange,
12177
+ toolbarFilters: resolvedToolbarFilters,
12178
+ onToolbarFiltersChange: handleToolbarFiltersChange,
12179
+ columnKeys: columnKeys,
12180
+ actionsColumnKey: actionsColumnKey,
12181
+ columnOrder: columnOrder,
12182
+ defaultColumnOrder: defaultColumnOrder,
12183
+ onColumnOrderChange: onColumnOrderChange,
12184
+ hiddenColumnKeys: hiddenColumnKeys,
12185
+ defaultHiddenColumnKeys: defaultHiddenColumnKeys,
12186
+ onHiddenColumnKeysChange: onHiddenColumnKeysChange,
12187
+ columnWidths: columnWidths,
12188
+ defaultColumnWidths: defaultColumnWidths,
12189
+ onColumnWidthsChange: onColumnWidthsChange,
12190
+ columnLabels: columnLabels,
12191
+ defaultColumnLabels: defaultColumnLabels,
12192
+ onColumnLabelsChange: onColumnLabelsChange,
12193
+ pinnedColumnKeys: pinnedColumnKeys,
12194
+ defaultPinnedColumnKeys: defaultPinnedColumnKeys,
12195
+ onPinnedColumnKeysChange: onPinnedColumnKeysChange,
12196
+ columnCalcOps: columnCalcOps,
12197
+ defaultColumnCalcOps: defaultColumnCalcOps,
12198
+ onColumnCalcOpsChange: onColumnCalcOpsChange,
12199
+ onEdit: onEdit,
12200
+ onLoadMore: onLoadMore,
12201
+ hasMore: hasMore,
12202
+ loadingMore: loadingMore,
12203
+ virtualized: virtualized,
12204
+ rowHeight: rowHeight,
12205
+ overscan: overscan,
12206
+ ...restProps,
12207
+ children: [
12208
+ onColumnsChange && /*#__PURE__*/ jsxRuntime.jsx(ColumnsChangeEffect, {
12209
+ columns: columns,
12210
+ onColumnsChange: onColumnsChange
12211
+ }),
12212
+ showToolbar && /*#__PURE__*/ jsxRuntime.jsxs(DataTableToolbar, {
12121
12213
  children: [
12122
- /*#__PURE__*/ jsxRuntime.jsx(DataTableColGroup, {
12123
- columns: columns,
12124
- selectable: !!selectable,
12125
- stickyFirst: stickyFirst
12214
+ searchable && /*#__PURE__*/ jsxRuntime.jsx(SearchBox, {
12215
+ placeholder: searchPlaceholder,
12216
+ label: searchLabel
12126
12217
  }),
12127
- /*#__PURE__*/ jsxRuntime.jsxs(DataTableHeader, {
12218
+ /*#__PURE__*/ jsxRuntime.jsx(SortControl, {
12219
+ columns: columns
12220
+ }),
12221
+ /*#__PURE__*/ jsxRuntime.jsx(FilterControl, {
12222
+ columns: columns
12223
+ }),
12224
+ (showCount || toolbarActions) && /*#__PURE__*/ jsxRuntime.jsxs(DataTableToolbarEnd, {
12128
12225
  children: [
12129
- selectable && /*#__PURE__*/ jsxRuntime.jsx(SelectionHeaderCell, {
12130
- stickyFirst: stickyFirst,
12131
- children: /*#__PURE__*/ jsxRuntime.jsx(SelectAllCheckbox, {
12132
- label: selectAllLabel,
12133
- checkedIcon: selectionCheckedIcon ?? DEFAULT_CHECKED_ICON,
12134
- indeterminateIcon: selectionIndeterminateIcon ?? DEFAULT_INDETERMINATE_ICON
12135
- })
12136
- }),
12137
- /*#__PURE__*/ jsxRuntime.jsx(ColumnHeaderCells, {
12138
- columns: columns,
12139
- columnMenu: columnMenu,
12140
- reorderable: reorderable,
12141
- resizable: resizable,
12142
- sortIcon: sortIcon,
12143
- selectable: !!selectable,
12144
- stickyFirst: stickyFirst,
12145
- stickyLast: resolvedStickyLast
12226
+ toolbarActions,
12227
+ showCount && /*#__PURE__*/ jsxRuntime.jsx(RowCount, {
12228
+ shown: sortedData.length,
12229
+ total: data.length,
12230
+ countLabel: countLabel
12146
12231
  })
12147
12232
  ]
12148
- }),
12149
- /*#__PURE__*/ jsxRuntime.jsx(DataTableBody, {
12150
- children: loading ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12151
- children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12152
- colSpan: totalCols,
12153
- children: /*#__PURE__*/ jsxRuntime.jsx(LoadingStateContent, {
12154
- label: loadingLabel,
12155
- classNames: classNames
12233
+ })
12234
+ ]
12235
+ }),
12236
+ /*#__PURE__*/ jsxRuntime.jsx(DataTableScrollBody, {
12237
+ scrollProps: scrollProps,
12238
+ virtualized: virtualized,
12239
+ children: /*#__PURE__*/ jsxRuntime.jsxs(DataTableTable, {
12240
+ "aria-rowcount": virtualized ? sortedData.length + 1 : undefined,
12241
+ children: [
12242
+ /*#__PURE__*/ jsxRuntime.jsx(DataTableColGroup, {
12243
+ columns: columns,
12244
+ selectable: !!selectable,
12245
+ stickyFirst: stickyFirst
12246
+ }),
12247
+ /*#__PURE__*/ jsxRuntime.jsxs(DataTableHeader, {
12248
+ children: [
12249
+ selectable && /*#__PURE__*/ jsxRuntime.jsx(SelectionHeaderCell, {
12250
+ stickyFirst: stickyFirst,
12251
+ children: /*#__PURE__*/ jsxRuntime.jsx(SelectAllCheckbox, {
12252
+ label: selectAllLabel,
12253
+ checkedIcon: selectionCheckedIcon ?? DEFAULT_CHECKED_ICON,
12254
+ indeterminateIcon: selectionIndeterminateIcon ?? DEFAULT_INDETERMINATE_ICON
12255
+ })
12256
+ }),
12257
+ /*#__PURE__*/ jsxRuntime.jsx(ColumnHeaderCells, {
12258
+ columns: columns,
12259
+ columnMenu: columnMenu,
12260
+ reorderable: reorderable,
12261
+ resizable: resizable,
12262
+ sortIcon: sortIcon,
12263
+ selectable: !!selectable,
12264
+ stickyFirst: stickyFirst,
12265
+ stickyLast: resolvedStickyLast
12156
12266
  })
12157
- })
12158
- }) : error ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12159
- children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12160
- colSpan: totalCols,
12161
- children: /*#__PURE__*/ jsxRuntime.jsx(EmptyStateContent, {
12162
- classNames: classNames,
12163
- children: error
12267
+ ]
12268
+ }),
12269
+ /*#__PURE__*/ jsxRuntime.jsx(DataTableBody, {
12270
+ children: loading ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12271
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12272
+ colSpan: totalCols,
12273
+ children: /*#__PURE__*/ jsxRuntime.jsx(LoadingStateContent, {
12274
+ label: loadingLabel,
12275
+ classNames: classNames
12276
+ })
12164
12277
  })
12165
- })
12166
- }) : sortedData.length === 0 ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12167
- children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12168
- colSpan: totalCols,
12169
- children: /*#__PURE__*/ jsxRuntime.jsx(EmptyStateContent, {
12170
- classNames: classNames,
12171
- children: empty
12278
+ }) : error ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12279
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12280
+ colSpan: totalCols,
12281
+ children: /*#__PURE__*/ jsxRuntime.jsx(EmptyStateContent, {
12282
+ classNames: classNames,
12283
+ children: error
12284
+ })
12172
12285
  })
12173
- })
12174
- }) : /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
12175
- children: [
12176
- /*#__PURE__*/ jsxRuntime.jsx(WindowedRows, {
12177
- rows: sortedData,
12178
- virtualized: virtualized,
12286
+ }) : sortedData.length === 0 ? /*#__PURE__*/ jsxRuntime.jsx("tr", {
12287
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTableCell, {
12179
12288
  colSpan: totalCols,
12180
- children: (windowRows, firstIndex)=>/*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
12181
- children: windowRows.map((row, offset)=>/*#__PURE__*/ jsxRuntime.jsxs(DataTableRow, {
12182
- rowId: row.id,
12183
- "aria-rowindex": virtualized ? firstIndex + offset + 2 : undefined,
12184
- "data-clickable": onRowClick ? "" : undefined,
12185
- onClick: onRowClick ? ()=>onRowClick(row) : undefined,
12186
- children: [
12187
- selectable && /*#__PURE__*/ jsxRuntime.jsx(SelectionCell, {
12188
- // The row itself carries `onClick={onRowClick}` above, and a
12189
- // native click on this cell's checkbox bubbles up through it
12190
- // (React attaches DataTableRow's handler on the <tr>, which
12191
- // sits between the checkbox and anything a consumer could stop
12192
- // it from at -- so this has to live here, not in the consumer).
12193
- // Without this, checking a row's box also fires `onRowClick`.
12194
- onClick: (event)=>event.stopPropagation(),
12195
- stickyFirst: stickyFirst,
12196
- children: /*#__PURE__*/ jsxRuntime.jsx(RowCheckbox, {
12197
- label: getRowSelectionLabel(row),
12198
- checkedIcon: selectionCheckedIcon ?? DEFAULT_CHECKED_ICON
12289
+ children: /*#__PURE__*/ jsxRuntime.jsx(EmptyStateContent, {
12290
+ classNames: classNames,
12291
+ children: empty
12292
+ })
12293
+ })
12294
+ }) : /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
12295
+ children: [
12296
+ /*#__PURE__*/ jsxRuntime.jsx(WindowedRows, {
12297
+ rows: sortedData,
12298
+ virtualized: virtualized,
12299
+ colSpan: totalCols,
12300
+ children: (windowRows, firstIndex)=>/*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
12301
+ children: windowRows.map((row, offset)=>/*#__PURE__*/ jsxRuntime.jsxs(DataTableRow, {
12302
+ rowId: row.id,
12303
+ "aria-rowindex": virtualized ? firstIndex + offset + 2 : undefined,
12304
+ "data-clickable": onRowClick ? "" : undefined,
12305
+ onClick: onRowClick ? ()=>onRowClick(row) : undefined,
12306
+ children: [
12307
+ selectable && /*#__PURE__*/ jsxRuntime.jsx(SelectionCell, {
12308
+ // The row itself carries `onClick={onRowClick}` above, and a
12309
+ // native click on this cell's checkbox bubbles up through it
12310
+ // (React attaches DataTableRow's handler on the <tr>, which
12311
+ // sits between the checkbox and anything a consumer could stop
12312
+ // it from at -- so this has to live here, not in the consumer).
12313
+ // Without this, checking a row's box also fires `onRowClick`.
12314
+ onClick: (event)=>event.stopPropagation(),
12315
+ stickyFirst: stickyFirst,
12316
+ children: /*#__PURE__*/ jsxRuntime.jsx(RowCheckbox, {
12317
+ label: getRowSelectionLabel(row),
12318
+ checkedIcon: selectionCheckedIcon ?? DEFAULT_CHECKED_ICON
12319
+ })
12320
+ }),
12321
+ /*#__PURE__*/ jsxRuntime.jsx(ColumnBodyCells, {
12322
+ columns: columns,
12323
+ row: row,
12324
+ classNames: classNames,
12325
+ locale: locale,
12326
+ selectable: !!selectable,
12327
+ stickyFirst: stickyFirst,
12328
+ stickyLast: resolvedStickyLast,
12329
+ cellContextMenu: cellContextMenu,
12330
+ onViewEditHistory: onViewEditHistory,
12331
+ cellContextMenuItems: cellContextMenuItems
12199
12332
  })
12200
- }),
12201
- /*#__PURE__*/ jsxRuntime.jsx(ColumnBodyCells, {
12202
- columns: columns,
12203
- row: row,
12204
- classNames: classNames,
12205
- locale: locale,
12206
- selectable: !!selectable,
12207
- stickyFirst: stickyFirst,
12208
- stickyLast: resolvedStickyLast,
12209
- cellContextMenu: cellContextMenu,
12210
- onViewEditHistory: onViewEditHistory,
12211
- cellContextMenuItems: cellContextMenuItems
12212
- })
12213
- ]
12214
- }, row.id))
12215
- })
12333
+ ]
12334
+ }, row.id))
12335
+ })
12336
+ }),
12337
+ onLoadMore && /*#__PURE__*/ jsxRuntime.jsx(InfiniteScrollRow, {
12338
+ colSpan: totalCols,
12339
+ classNames: classNames,
12340
+ loadingLabel: loadingLabel
12341
+ })
12342
+ ]
12343
+ })
12344
+ }),
12345
+ showFooter && /*#__PURE__*/ jsxRuntime.jsxs(DataTableFooter, {
12346
+ children: [
12347
+ selectable && // The 40px-wide selection SPACER cell is now a plain `DataTableFooterCell`
12348
+ // (not the `selectionCell` slot) -- the `<colgroup>`'s own 40px `<col>`
12349
+ // is what makes every row's selection column line up now, not a matching
12350
+ // per-slot width formula, so there is no more reason for this cell to
12351
+ // borrow a different slot than its footer siblings.
12352
+ /*#__PURE__*/ jsxRuntime.jsx(SelectionFooterCell, {
12353
+ stickyFirst: stickyFirst
12216
12354
  }),
12217
- onLoadMore && /*#__PURE__*/ jsxRuntime.jsx(InfiniteScrollRow, {
12218
- colSpan: totalCols,
12219
- classNames: classNames,
12220
- loadingLabel: loadingLabel
12355
+ /*#__PURE__*/ jsxRuntime.jsx(ColumnCalcCells, {
12356
+ columns: columns,
12357
+ rows: sortedData,
12358
+ selectable: !!selectable,
12359
+ stickyFirst: stickyFirst,
12360
+ stickyLast: resolvedStickyLast
12221
12361
  })
12222
12362
  ]
12363
+ }),
12364
+ onAddRow && /*#__PURE__*/ jsxRuntime.jsx(AddRowFooter, {
12365
+ onAddRow: onAddRow,
12366
+ addRowLabel: addRowLabel,
12367
+ colSpan: totalCols,
12368
+ classNames: classNames
12223
12369
  })
12224
- }),
12225
- showFooter && /*#__PURE__*/ jsxRuntime.jsxs(DataTableFooter, {
12226
- children: [
12227
- selectable && // The 40px-wide selection SPACER cell is now a plain `DataTableFooterCell`
12228
- // (not the `selectionCell` slot) -- the `<colgroup>`'s own 40px `<col>`
12229
- // is what makes every row's selection column line up now, not a matching
12230
- // per-slot width formula, so there is no more reason for this cell to
12231
- // borrow a different slot than its footer siblings.
12232
- /*#__PURE__*/ jsxRuntime.jsx(SelectionFooterCell, {
12233
- stickyFirst: stickyFirst
12234
- }),
12235
- /*#__PURE__*/ jsxRuntime.jsx(ColumnCalcCells, {
12236
- columns: columns,
12237
- rows: sortedData,
12238
- selectable: !!selectable,
12239
- stickyFirst: stickyFirst,
12240
- stickyLast: resolvedStickyLast
12241
- })
12242
- ]
12243
- }),
12244
- onAddRow && /*#__PURE__*/ jsxRuntime.jsx(AddRowFooter, {
12245
- onAddRow: onAddRow,
12246
- addRowLabel: addRowLabel,
12247
- colSpan: totalCols,
12248
- classNames: classNames
12249
- })
12250
- ]
12370
+ ]
12371
+ })
12372
+ }),
12373
+ selectable && /*#__PURE__*/ jsxRuntime.jsx(DataTableBulkBar, {
12374
+ clearLabel: clearSelectionLabel,
12375
+ aboveFooter: showFooter || !!onAddRow,
12376
+ children: bulkActions
12251
12377
  })
12252
- }),
12253
- selectable && /*#__PURE__*/ jsxRuntime.jsx(DataTableBulkBar, {
12254
- clearLabel: clearSelectionLabel,
12255
- aboveFooter: showFooter || !!onAddRow,
12256
- children: bulkActions
12257
- })
12258
- ]
12378
+ ]
12379
+ })
12259
12380
  })
12260
12381
  });
12261
12382
  }