@crispy-seed/data-table 0.11.0 → 0.11.2

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.
@@ -238,6 +238,21 @@ tbody tr:last-child .seed-data-table__cell {
238
238
  text-overflow: ellipsis;
239
239
  white-space: nowrap;
240
240
  }
241
+ .seed-data-table__entityName[data-clickable] {
242
+ cursor: pointer;
243
+ border: none;
244
+ background: none;
245
+ padding: 0;
246
+ margin: 0;
247
+ font-family: inherit;
248
+ font-size: inherit;
249
+ line-height: inherit;
250
+ color: inherit;
251
+ text-align: start;
252
+ }
253
+ .seed-data-table__entityName[data-clickable]:is(:hover, [data-hover]) {
254
+ text-decoration: underline;
255
+ }
241
256
  .seed-data-table__tagList {
242
257
  display: flex;
243
258
  align-items: center;
@@ -301,8 +316,8 @@ tr:hover .seed-data-table__entityActions {
301
316
  height: 22px;
302
317
  padding: 0 4px;
303
318
  border-radius: 7px;
304
- font-size: 10px;
305
- font-weight: var(--seed-font-weight-regular);
319
+ font-size: 13px;
320
+ font-weight: var(--seed-font-weight-medium);
306
321
  line-height: 15px;
307
322
  overflow: clip;
308
323
  text-overflow: ellipsis;
@@ -275,6 +275,23 @@
275
275
  overflow: clip;
276
276
  }
277
277
 
278
+ .seed-data-table__entityName[data-clickable] {
279
+ cursor: pointer;
280
+ font-family: inherit;
281
+ font-size: inherit;
282
+ line-height: inherit;
283
+ color: inherit;
284
+ text-align: start;
285
+ background: none;
286
+ border: none;
287
+ margin: 0;
288
+ padding: 0;
289
+ }
290
+
291
+ .seed-data-table__entityName[data-clickable]:is(:hover, [data-hover]) {
292
+ text-decoration: underline;
293
+ }
294
+
278
295
  .seed-data-table__tagList {
279
296
  align-items: center;
280
297
  gap: var(--seed-dimension-x1_5);
@@ -337,8 +354,8 @@
337
354
  box-sizing: border-box;
338
355
  max-width: 100%;
339
356
  height: 22px;
340
- font-size: 10px;
341
- font-weight: var(--seed-font-weight-regular);
357
+ font-size: 13px;
358
+ font-weight: var(--seed-font-weight-medium);
342
359
  text-overflow: ellipsis;
343
360
  white-space: nowrap;
344
361
  border-radius: 7px;
package/dist/index.cjs CHANGED
@@ -987,15 +987,33 @@ function sameCell$1(a, id, key) {
987
987
  * first captured) nor keeps a ghost entry for one that was removed. Known keys keep
988
988
  * their position from `order`; any key in `keys` missing from `order` is appended, in
989
989
  * `keys`' own order; any entry in `order` no longer in `keys` is dropped.
990
- */ function reconcileColumnOrder(order, keys) {
990
+ *
991
+ * `actionsKey` (the styled layer's `actions`-flagged column, e.g. the row-menu `⋯`
992
+ * column) is kept LAST no matter what -- without this, a brand-new column added to
993
+ * `columns` after the table first mounted got appended past it (the "any key in `keys`
994
+ * missing from `order` is appended" rule above has no notion of "past the end" vs. "at
995
+ * the very end"), stranding it in the middle of the table since `stickyLast`/`actions`
996
+ * only sticks the actual trailing column. A real consumer hit this: their newly-added
997
+ * column landed to the right of the already-pinned-sticky `actions` column, covered by
998
+ * it under horizontal scroll. Column-layout's own `pinnedCellProps` independently
999
+ * targets the `actions` column by FLAG rather than by position (belt and suspenders --
1000
+ * see that file's own doc comment), but this still keeps the VISUAL order sane so nothing
1001
+ * renders hidden behind the sticky cell in the first place.
1002
+ */ function reconcileColumnOrder(order, keys, actionsKey) {
991
1003
  const keySet = new Set(keys);
992
1004
  const known = order.filter((key)=>keySet.has(key));
993
1005
  const knownSet = new Set(known);
994
1006
  const added = keys.filter((key)=>!knownSet.has(key));
995
- return [
1007
+ const merged = [
996
1008
  ...known,
997
1009
  ...added
998
1010
  ];
1011
+ if (actionsKey === undefined || !keySet.has(actionsKey)) return merged;
1012
+ const withoutActions = merged.filter((key)=>key !== actionsKey);
1013
+ return [
1014
+ ...withoutActions,
1015
+ actionsKey
1016
+ ];
999
1017
  }
1000
1018
  /**
1001
1019
  * Moves `key` one step toward `direction` in `order` -- a no-op (same array, well,
@@ -1174,7 +1192,7 @@ const EMPTY_RECORD = {};
1174
1192
  * state this hook already owns, not independent state
1175
1193
  * of their own.
1176
1194
  */ function useDataTableColumns(props) {
1177
- const { columnKeys = EMPTY_STRINGS, columnOrder: columnOrderProp, defaultColumnOrder, onColumnOrderChange, hiddenColumnKeys: hiddenProp, defaultHiddenColumnKeys = EMPTY_STRINGS, onHiddenColumnKeysChange, columnWidths: widthsProp, defaultColumnWidths = EMPTY_RECORD, onColumnWidthsChange, columnLabels: labelsProp, defaultColumnLabels = EMPTY_RECORD, onColumnLabelsChange, pinnedColumnKeys: pinnedProp, defaultPinnedColumnKeys = EMPTY_STRINGS, onPinnedColumnKeysChange } = props;
1195
+ const { columnKeys = EMPTY_STRINGS, actionsColumnKey, columnOrder: columnOrderProp, defaultColumnOrder, onColumnOrderChange, hiddenColumnKeys: hiddenProp, defaultHiddenColumnKeys = EMPTY_STRINGS, onHiddenColumnKeysChange, columnWidths: widthsProp, defaultColumnWidths = EMPTY_RECORD, onColumnWidthsChange, columnLabels: labelsProp, defaultColumnLabels = EMPTY_RECORD, onColumnLabelsChange, pinnedColumnKeys: pinnedProp, defaultPinnedColumnKeys = EMPTY_STRINGS, onPinnedColumnKeysChange } = props;
1178
1196
  const [rawOrder, setRawOrder] = useControllableState$1({
1179
1197
  prop: columnOrderProp,
1180
1198
  defaultProp: defaultColumnOrder ?? columnKeys,
@@ -1185,9 +1203,10 @@ const EMPTY_RECORD = {};
1185
1203
  // consumer persisted before a new column existed must still show that new column
1186
1204
  // (appended), and one holding a column that got removed from `columns` must not
1187
1205
  // render a ghost header for it.
1188
- const columnOrder = React.useMemo(()=>reconcileColumnOrder(rawOrder ?? columnKeys, columnKeys), [
1206
+ const columnOrder = React.useMemo(()=>reconcileColumnOrder(rawOrder ?? columnKeys, columnKeys, actionsColumnKey), [
1189
1207
  rawOrder,
1190
- columnKeys
1208
+ columnKeys,
1209
+ actionsColumnKey
1191
1210
  ]);
1192
1211
  const [hiddenColumnKeys = EMPTY_STRINGS, setHiddenColumnKeys] = useControllableState$1({
1193
1212
  prop: hiddenProp,
@@ -2169,7 +2188,7 @@ function useDataTableRowContext({ strict = true } = {}) {
2169
2188
  return context;
2170
2189
  }
2171
2190
  const DataTableRoot = /*#__PURE__*/ React.forwardRef((props, ref)=>{
2172
- const { sort, defaultSort, onSortChange, rowIds, selectable, selectedIds, defaultSelectedIds, onSelectionChange, query, defaultQuery, onQueryChange, toolbarSorts, defaultToolbarSorts, onToolbarSortsChange, toolbarFilters, defaultToolbarFilters, onToolbarFiltersChange, columnKeys, columnOrder, defaultColumnOrder, onColumnOrderChange, hiddenColumnKeys, defaultHiddenColumnKeys, onHiddenColumnKeysChange, columnWidths, defaultColumnWidths, onColumnWidthsChange, columnLabels, defaultColumnLabels, onColumnLabelsChange, pinnedColumnKeys, defaultPinnedColumnKeys, onPinnedColumnKeysChange, columnCalcOps, defaultColumnCalcOps, onColumnCalcOpsChange, onEdit, onLoadMore, hasMore, loadingMore, ...otherProps } = props;
2191
+ const { sort, defaultSort, onSortChange, rowIds, selectable, selectedIds, defaultSelectedIds, onSelectionChange, query, defaultQuery, onQueryChange, toolbarSorts, defaultToolbarSorts, onToolbarSortsChange, toolbarFilters, defaultToolbarFilters, onToolbarFiltersChange, columnKeys, actionsColumnKey, columnOrder, defaultColumnOrder, onColumnOrderChange, hiddenColumnKeys, defaultHiddenColumnKeys, onHiddenColumnKeysChange, columnWidths, defaultColumnWidths, onColumnWidthsChange, columnLabels, defaultColumnLabels, onColumnLabelsChange, pinnedColumnKeys, defaultPinnedColumnKeys, onPinnedColumnKeysChange, columnCalcOps, defaultColumnCalcOps, onColumnCalcOpsChange, onEdit, onLoadMore, hasMore, loadingMore, ...otherProps } = props;
2173
2192
  const api = useDataTable({
2174
2193
  sort,
2175
2194
  defaultSort,
@@ -2189,6 +2208,7 @@ const DataTableRoot = /*#__PURE__*/ React.forwardRef((props, ref)=>{
2189
2208
  defaultToolbarFilters,
2190
2209
  onToolbarFiltersChange,
2191
2210
  columnKeys,
2211
+ actionsColumnKey,
2192
2212
  columnOrder,
2193
2213
  defaultColumnOrder,
2194
2214
  onColumnOrderChange,
@@ -2991,6 +3011,40 @@ function EntityCell({ value, className, nameClassName, actionsClassName, actionC
2991
3011
  name: String(value ?? "")
2992
3012
  };
2993
3013
  if (!entity.name) return null;
3014
+ // Click-to-navigate (your-moon/crisp, Attio parity) -- `onOpenRecord` wins over a
3015
+ // plain `href` when both are set (see `onOpenRecord`'s own doc comment,
3016
+ // `DataTable.tsx`); neither -> the original plain, non-clickable `<span>`. Both
3017
+ // clickable variants carry `data-clickable` -- the ONLY thing the recipe's
3018
+ // `entityName` hover-underline rule keys off (`data-table.ts`), so a plain name
3019
+ // never underlines and a clickable one always does, regardless of which variant
3020
+ // rendered it.
3021
+ const nameNode = column?.onOpenRecord && row !== undefined ? // A real `<button>`, not a `<span role="link">` -- `onOpenRecord` is an
3022
+ // arbitrary consumer callback (like `onOpenPreview`'s own button below), never
3023
+ // a genuine URL, so `<button>` is the correct semantic element (native
3024
+ // keyboard activation/focusability for free, no `role`/`tabIndex`/`onKeyDown`
3025
+ // needed) -- unlike the `href` branch just below, which IS a real URL and
3026
+ // gets a real `<a>`. The recipe's `entityName` slot resets this button's own
3027
+ // chrome (border/background/padding/font/color/text-align) back to plain
3028
+ // inline text (`data-table.ts`).
3029
+ /*#__PURE__*/ jsxRuntime.jsx("button", {
3030
+ type: "button",
3031
+ className: nameClassName,
3032
+ "data-clickable": "",
3033
+ onClick: (event)=>{
3034
+ event.stopPropagation();
3035
+ column.onOpenRecord?.(row);
3036
+ },
3037
+ children: entity.name
3038
+ }) : entity.href ? /*#__PURE__*/ jsxRuntime.jsx("a", {
3039
+ className: nameClassName,
3040
+ "data-clickable": "",
3041
+ href: entity.href,
3042
+ onClick: (event)=>event.stopPropagation(),
3043
+ children: entity.name
3044
+ }) : /*#__PURE__*/ jsxRuntime.jsx("span", {
3045
+ className: nameClassName,
3046
+ children: entity.name
3047
+ });
2994
3048
  return /*#__PURE__*/ jsxRuntime.jsxs("span", {
2995
3049
  className: className,
2996
3050
  children: [
@@ -3006,10 +3060,7 @@ function EntityCell({ value, className, nameClassName, actionsClassName, actionC
3006
3060
  })
3007
3061
  ]
3008
3062
  }),
3009
- /*#__PURE__*/ jsxRuntime.jsx("span", {
3010
- className: nameClassName,
3011
- children: entity.name
3012
- }),
3063
+ nameNode,
3013
3064
  column?.onOpenPreview && row !== undefined && /*#__PURE__*/ jsxRuntime.jsx("span", {
3014
3065
  className: actionsClassName,
3015
3066
  children: /*#__PURE__*/ jsxRuntime.jsx("button", {
@@ -3533,10 +3584,25 @@ function RatingCell({ value, maxRating = 5 }) {
3533
3584
  width,
3534
3585
  pinned,
3535
3586
  pinOffset,
3536
- pinnedEdge: false
3587
+ pinnedEdge: false,
3588
+ stickyLastTarget: false
3537
3589
  };
3538
3590
  });
3539
3591
  if (pinnedCount > 0) entries[pinnedCount - 1].pinnedEdge = true;
3592
+ // `stickyLast` sticks the `actions`-flagged column specifically -- not whichever
3593
+ // column merely landed last in render order. Without this, `reconcileColumnOrder`
3594
+ // appending a brand-new column past `actions` (this file's own `<colgroup>` doc
3595
+ // comment on why order must stay in lockstep) silently moved the sticky-right
3596
+ // treatment onto that new column instead, stranding `actions` in the middle of the
3597
+ // table -- a real consumer hit this. Falls back to the genuine last entry when no
3598
+ // column is flagged `actions` at all, matching `stickyLast`'s original single-
3599
+ // column behavior.
3600
+ if (entries.length > 0) {
3601
+ const actionsColumn = columns.find((column)=>column.actions);
3602
+ const actionsIndex = actionsColumn ? entries.findIndex((entry)=>entry.column.key === actionsColumn.key) : -1;
3603
+ const stickyLastIndex = actionsIndex !== -1 ? actionsIndex : entries.length - 1;
3604
+ entries[stickyLastIndex].stickyLastTarget = true;
3605
+ }
3540
3606
  return entries;
3541
3607
  }, [
3542
3608
  columns,
@@ -3576,9 +3642,12 @@ function RatingCell({ value, maxRating = 5 }) {
3576
3642
  }
3577
3643
  /** Sticky positioning for one DATA cell (header, body, or ColumnCalc footer) -- pinned-
3578
3644
  * left (this column's own `pinOffset`, `data-sticky-edge` only on the group's
3579
- * trailing-most member) takes priority over sticky-right (`stickyLast`, always just
3580
- * the last VISIBLE column, e.g. an `actions` column) since a column can only stick to
3581
- * one edge. */ function pinnedCellProps(entry, stickyLast, isLast) {
3645
+ * trailing-most member) takes priority over sticky-right (`stickyLast`, the
3646
+ * `actions`-flagged column when one exists, else the genuine last VISIBLE column)
3647
+ * since a column can only stick to one edge. Reads `entry.stickyLastTarget`
3648
+ * (`useEffectiveColumns`) rather than an `isLast` index the caller computes itself --
3649
+ * that index is just "last in render order", which is exactly what stranded a
3650
+ * reordered-past `actions` column in the first place. */ function pinnedCellProps(entry, stickyLast) {
3582
3651
  if (entry.pinned) {
3583
3652
  return {
3584
3653
  "data-sticky": "",
@@ -3590,7 +3659,7 @@ function RatingCell({ value, maxRating = 5 }) {
3590
3659
  }
3591
3660
  };
3592
3661
  }
3593
- if (stickyLast && isLast) {
3662
+ if (stickyLast && entry.stickyLastTarget) {
3594
3663
  return {
3595
3664
  "data-sticky": "",
3596
3665
  "data-sticky-edge-end": "",
@@ -3926,7 +3995,7 @@ const TextFieldTextarea = /*#__PURE__*/ React.forwardRef(({ className, autoresiz
3926
3995
  });
3927
3996
  TextFieldTextarea.displayName = "TextFieldTextarea";
3928
3997
 
3929
- __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__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:10px;font-weight:var(--seed-font-weight-regular);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 .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__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))}");
3998
+ __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 .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__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))}");
3930
3999
 
3931
4000
  const createClassName = (className, variants, compoundVariants = [])=>{
3932
4001
  const variantKeys = Object.keys(variants);
@@ -4749,26 +4818,87 @@ function ChipListEditor({ column, value, pending, onCommit, classNames }) {
4749
4818
  }));
4750
4819
  }
4751
4820
  ////////////////////////////////////////////////////////////////////////////////////
4752
- // -- Feature C (#12): cell-expand "show full content" overlay -- an anchored box
4753
- // (position:absolute over the cell it belongs to, grows in HEIGHT, elevated)
4754
- // that wraps whatever a truncated cell would otherwise show inline: an editable
4755
- // column's OWN editor node (unchanged, just relocated into this box instead of
4756
- // rendered flush in the 36px row) for the editable case, or the plain full value
4757
- // for a read-only one. `body-cells.tsx` decides WHEN to render this (a click on a
4758
- // cell whose content is actually truncated, `truncate.ts`'s `isCellTruncated`);
4759
- // this component only supplies the box.
4760
- function CellExpandOverlay({ className, children }) {
4761
- return(// `stopPropagation` -- an overlay sits on top of (and past) its own cell/row;
4821
+ // -- Feature C (#12): cell-expand "show full content" overlay -- a box that wraps
4822
+ // whatever a truncated cell would otherwise show inline: an editable column's OWN
4823
+ // editor node (unchanged, just relocated into this box instead of rendered flush in
4824
+ // the 36px row) for the editable case, or the plain full value for a read-only one.
4825
+ // `body-cells.tsx` decides WHEN to render this (a click on a cell whose content is
4826
+ // actually truncated, `truncate.ts`'s `isCellTruncated`); this component only
4827
+ // supplies the box.
4828
+ //
4829
+ // Portals to `document.body` (crispy-seed#1094's own pinned-column follow-up,
4830
+ // ported from the chip-list editor's popover, `body-cells.tsx`'s
4831
+ // `isChipListEditable` -- that one shipped this exact fix in 0.10.3) rather than
4832
+ // positioning `absolute` against its own cell: a `position: sticky` `<td>` clips ANY
4833
+ // descendant that grows past its own box, in every browser tested, regardless of
4834
+ // `overflow`/`z-index` on anything in between, so a pinned column's own truncated
4835
+ // cell used to clip this overlay's grown content instead of showing it in full. A
4836
+ // portal sidesteps that by not being a descendant of the sticky `<td>` at all once
4837
+ // mounted -- position is instead measured live off `anchorRef`'s own
4838
+ // `getBoundingClientRect()`, the same technique the chip-list popover already uses.
4839
+ function CellExpandOverlay({ className, anchorRef, contentRef, children }) {
4840
+ const [style, setStyle] = React__namespace.useState(null);
4841
+ // Grows 1px past the cell's own edges in every direction, matching this box's
4842
+ // pre-portal `top: -1px; insetInlineStart: -1px; insetInlineEnd: -1px` (the recipe's
4843
+ // `expandOverlay` class, `data-table.ts`) -- hides the 1px border seam against the
4844
+ // cell it's expanding out of. `minHeight`/`insetInlineEnd` from that same class no
4845
+ // longer apply once portaled (they resolved against the `<td>` as this box's own
4846
+ // containing block, meaningless once it's a `position: fixed` child of `<body>`
4847
+ // instead -- the same override the chip-list popover's own `measurePopoverPosition`,
4848
+ // `body-cells.tsx`, already makes), so this overrides both explicitly.
4849
+ const measure = React__namespace.useCallback(()=>{
4850
+ const cell = anchorRef.current;
4851
+ if (!cell) return;
4852
+ const rect = cell.getBoundingClientRect();
4853
+ setStyle({
4854
+ position: "fixed",
4855
+ top: rect.top - 1,
4856
+ insetInlineStart: rect.left - 1,
4857
+ insetInlineEnd: "auto",
4858
+ width: rect.width + 2,
4859
+ minHeight: "auto",
4860
+ zIndex: 1000
4861
+ });
4862
+ }, [
4863
+ anchorRef
4864
+ ]);
4865
+ // Measured before paint, on mount -- see this component's own prop doc comment for
4866
+ // why it can't just trust a caller to have measured first.
4867
+ React__namespace.useLayoutEffect(()=>{
4868
+ measure();
4869
+ }, [
4870
+ measure
4871
+ ]);
4872
+ // Same capture-phase listeners as the chip-list popover's own reposition effect
4873
+ // (`body-cells.tsx`) -- `scroll` doesn't bubble, so the table's own horizontal/
4874
+ // vertical scroll container (an arbitrary ancestor, not necessarily `window` itself)
4875
+ // is only observable this way.
4876
+ React__namespace.useEffect(()=>{
4877
+ window.addEventListener("scroll", measure, true);
4878
+ window.addEventListener("resize", measure);
4879
+ return ()=>{
4880
+ window.removeEventListener("scroll", measure, true);
4881
+ window.removeEventListener("resize", measure);
4882
+ };
4883
+ }, [
4884
+ measure
4885
+ ]);
4886
+ // Nothing to portal until the first measurement lands (avoids a one-frame flash at
4887
+ // the origin corner before `useLayoutEffect` runs).
4888
+ if (!style) return null;
4889
+ return /*#__PURE__*/ reactDom.createPortal(// `stopPropagation` -- an overlay sits on top of (and past) its own cell/row;
4762
4890
  // a click anywhere inside it must never ALSO fire the row's own `onRowClick`,
4763
4891
  // the same guard every other interactive cell affordance in this directory
4764
4892
  // already applies (`LinkCell`, `EntityCell`'s preview button, editors.tsx's
4765
4893
  // `TextEditor` root).
4766
4894
  // biome-ignore lint/a11y/noStaticElementInteractions: not a widget -- this div never responds to interaction on ITSELF, only stops propagation of events that already occurred on a real interactive descendant (the editor/text it wraps). No role fits it because it isn't a control.
4767
4895
  /*#__PURE__*/ jsxRuntime.jsx("div", {
4896
+ ref: contentRef,
4768
4897
  className: className,
4898
+ style: style,
4769
4899
  onClick: (event)=>event.stopPropagation(),
4770
4900
  children: children
4771
- }));
4901
+ }), document.body);
4772
4902
  }
4773
4903
 
4774
4904
  // Row-narrowing for the toolbar's search box -- split out of DataTable.tsx the way
@@ -4864,21 +4994,17 @@ function isCellTruncated(cell) {
4864
4994
  * close itself after the first tag commits, see `ChipListEditor`'s own doc
4865
4995
  * comment).
4866
4996
  *
4867
- * Unlike every OTHER open editor in this file, this one does NOT render inside
4868
- * Feature C's `CellExpandOverlay` (an anchored box positioned relative to the
4869
- * `<td>`, `position: absolute` against it) -- it renders through a REAL React
4870
- * portal to `document.body` instead (`DataTableBodyCell`'s own `popoverStyle`).
4871
- * Confirmed live, crispy-seed#1094's pinned-column follow-up: a `position: sticky`
4872
- * `<td>` clips ANY descendant content that grows past its own box to the table's
4873
- * scrollport, in EVERY browser tested, regardless of `overflow: visible` on every
4874
- * element in between and regardless of how high its `z-index` is raised -- neither
4875
- * of which is a stacking-context or overflow bug this file can fix from the
4876
- * INSIDE. A portal sidesteps it entirely by not being a descendant of the sticky
4877
- * `<td>` at all once mounted. The same sticky-clip almost certainly affects the
4878
- * OTHER gated editors' `CellExpandOverlay` too when their own column is pinned,
4879
- * but porting all of Feature C to this same portal model is its own change,
4880
- * out of scope here -- this fix is scoped to the one editor crispy-seed#1094
4881
- * actually reported against a pinned column. */ function isChipListEditable(column) {
4997
+ * This one renders through its OWN REAL React portal to `document.body`
4998
+ * (`DataTableBodyCell`'s own `popoverStyle`) rather than `editors.tsx`'s shared
4999
+ * `CellExpandOverlay`, since its shape is different (Attio's own click-anywhere-
5000
+ * opens gesture, no truncation gate). `CellExpandOverlay` itself ALSO portals to
5001
+ * `document.body` now (ported from this exact fix) -- both exist because a
5002
+ * `position: sticky` `<td>` clips ANY descendant content that grows past its own
5003
+ * box to the table's scrollport, in EVERY browser tested, regardless of
5004
+ * `overflow: visible` on every element in between and regardless of how high its
5005
+ * `z-index` is raised -- neither of which is a stacking-context or overflow bug
5006
+ * fixable from the INSIDE. A portal sidesteps it entirely by not being a
5007
+ * descendant of the sticky `<td>` at all once mounted. */ function isChipListEditable(column) {
4882
5008
  return !!column.editable && column.type === "chip-list";
4883
5009
  }
4884
5010
  function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyFirst, stickyLast, cellContextMenu, onViewEditHistory, cellContextMenuItems }) {
@@ -4887,10 +5013,9 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
4887
5013
  stickyFirst
4888
5014
  });
4889
5015
  return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
4890
- children: effective.map((entry, index)=>{
5016
+ children: effective.map((entry)=>{
4891
5017
  const { column } = entry;
4892
- const isLast = index === effective.length - 1;
4893
- const sticky = pinnedCellProps(entry, stickyLast, isLast);
5018
+ const sticky = pinnedCellProps(entry, stickyLast);
4894
5019
  return /*#__PURE__*/ jsxRuntime.jsx(DataTableBodyCell, {
4895
5020
  column: column,
4896
5021
  row: row,
@@ -5038,6 +5163,16 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5038
5163
  // mounted, in `document.body` -- see `isChipListEditable`'s doc comment) and by
5039
5164
  // the reposition effect further down.
5040
5165
  const popoverRef = React__namespace.useRef(null);
5166
+ // Feature C's own portaled overlay (`CellExpandOverlay`, editors.tsx) -- its own DOM
5167
+ // node, once mounted, same reasoning as `popoverRef` above: it lives outside
5168
+ // `cellRef`'s subtree (a sibling of the table in `document.body`, not a descendant of
5169
+ // the `<td>`), so the outside-click detector below needs a ref to it too. Without
5170
+ // this, `isInside` saw every click/keystroke INSIDE the portaled editor as "outside"
5171
+ // once the overlay actually escaped the `<td>` (this fix's whole point) -- e.g.
5172
+ // typing into the overlay's own `TextEditor` fires a pointerdown on an input that is
5173
+ // no longer `cellRef.current`'s descendant, so every keystroke closed the overlay and
5174
+ // cancelled the edit before the user finished typing.
5175
+ const expandOverlayRef = React__namespace.useRef(null);
5041
5176
  // Closes the overlay on Escape or an outside click/pointerdown -- a gated
5042
5177
  // editor's OWN Escape/blur handling already ends `isEditing` on its own (see
5043
5178
  // `TextEditor`/`SelectEditor`'s existing onCancel/onOpenChange wiring), which
@@ -5050,7 +5185,7 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5050
5185
  React__namespace.useEffect(()=>{
5051
5186
  if (!overlayOpen) return;
5052
5187
  function isInside(target) {
5053
- return (cellRef.current?.contains(target) ?? false) || (popoverRef.current?.contains(target) ?? false);
5188
+ return (cellRef.current?.contains(target) ?? false) || (popoverRef.current?.contains(target) ?? false) || (expandOverlayRef.current?.contains(target) ?? false);
5054
5189
  }
5055
5190
  function handlePointerDown(event) {
5056
5191
  if (!isInside(event.target)) {
@@ -5123,7 +5258,9 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5123
5258
  rowId: row.id,
5124
5259
  classNames: classNames,
5125
5260
  locale: locale,
5126
- overlayActive: overlayActive
5261
+ overlayActive: overlayActive,
5262
+ cellRef: cellRef,
5263
+ expandOverlayRef: expandOverlayRef
5127
5264
  }),
5128
5265
  cellContextMenu && contextMenuOpen && contextMenuPoint && // A `<td>` (unlike its own parent `<tr>`) can validly hold any flow
5129
5266
  // content, so `CellContextMenu`'s own 0x0 `MenuAnchor` -- itself never
@@ -5168,7 +5305,7 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5168
5305
  * display (a custom `render` wins there, same as before `editable` existed; it never
5169
5306
  * overrides an actual editing/always-live state, matching crisp's own split between
5170
5307
  * `renderTyped`'s rest-state branch and the editing branches above it).
5171
- */ function CellContent({ column, row, rowId, classNames, locale, overlayActive }) {
5308
+ */ function CellContent({ column, row, rowId, classNames, locale, overlayActive, cellRef, expandOverlayRef }) {
5172
5309
  const { isEditing, isPending, getEditError, commitEdit, cancelEdit } = useDataTableContext();
5173
5310
  const rawValue = getColumnValue(column, row);
5174
5311
  const pending = isPending(rowId, column.key);
@@ -5262,6 +5399,8 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
5262
5399
  children: [
5263
5400
  overlayActive ? /*#__PURE__*/ jsxRuntime.jsx(CellExpandOverlay, {
5264
5401
  className: classNames.expandOverlay,
5402
+ anchorRef: cellRef,
5403
+ contentRef: expandOverlayRef,
5265
5404
  children: column.editable ? node : /*#__PURE__*/ jsxRuntime.jsx("span", {
5266
5405
  className: classNames.expandOverlayText,
5267
5406
  children: node
@@ -5425,10 +5564,9 @@ function ColumnCalcCells({ columns, rows, selectable, stickyFirst, stickyLast })
5425
5564
  stickyFirst
5426
5565
  });
5427
5566
  return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
5428
- children: effective.map((entry, index)=>{
5567
+ children: effective.map((entry)=>{
5429
5568
  const { column } = entry;
5430
- const isLast = index === effective.length - 1;
5431
- const sticky = pinnedCellProps(entry, stickyLast, isLast);
5569
+ const sticky = pinnedCellProps(entry, stickyLast);
5432
5570
  return /*#__PURE__*/ jsxRuntime.jsx(DataTableFooterCell, {
5433
5571
  "data-sticky": sticky["data-sticky"],
5434
5572
  "data-sticky-edge": sticky["data-sticky-edge"],
@@ -5493,9 +5631,20 @@ function formatCalcValue(value, op) {
5493
5631
  size: 14
5494
5632
  })
5495
5633
  ]
5496
- }) : /*#__PURE__*/ jsxRuntime.jsx("span", {
5634
+ }) : /*#__PURE__*/ jsxRuntime.jsxs("span", {
5497
5635
  className: "seed-data-table-column-calc-placeholder",
5498
- children: "Add calculation"
5636
+ style: {
5637
+ display: "inline-flex",
5638
+ alignItems: "center",
5639
+ gap: 4
5640
+ },
5641
+ children: [
5642
+ /*#__PURE__*/ jsxRuntime.jsx(IconPlusLine_default, {
5643
+ size: 13,
5644
+ strokeWidth: 1.75
5645
+ }),
5646
+ "Add calculation"
5647
+ ]
5499
5648
  })
5500
5649
  })
5501
5650
  }),
@@ -5651,10 +5800,9 @@ const DEFAULT_SORT_ICON = {
5651
5800
  });
5652
5801
  const [renamingKey, setRenamingKey] = React__namespace.useState(null);
5653
5802
  return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
5654
- children: effective.map((entry, index)=>{
5803
+ children: effective.map((entry)=>{
5655
5804
  const { column, label, width } = entry;
5656
- const isLast = index === effective.length - 1;
5657
- const sticky = pinnedCellProps(entry, stickyLast, isLast);
5805
+ const sticky = pinnedCellProps(entry, stickyLast);
5658
5806
  return /*#__PURE__*/ jsxRuntime.jsxs(DataTableHeaderCell, {
5659
5807
  columnKey: column.key,
5660
5808
  sortable: column.sortable,
@@ -11664,6 +11812,12 @@ function DataTableInner(props, ref) {
11664
11812
  const columnKeys = React__namespace.useMemo(()=>columns.map((column)=>column.key), [
11665
11813
  columns
11666
11814
  ]);
11815
+ // Threaded down to `reconcileColumnOrder` (react-headless's `dom.ts`) so a brand-new
11816
+ // column added to `columns` after mount gets appended BEFORE this one, not past it --
11817
+ // see that function's own doc comment for the bug this prevents.
11818
+ const actionsColumnKey = React__namespace.useMemo(()=>columns.find((column)=>column.actions)?.key, [
11819
+ columns
11820
+ ]);
11667
11821
  const searchable = React__namespace.useMemo(()=>columns.some((column)=>column.searchable), [
11668
11822
  columns
11669
11823
  ]);
@@ -11706,6 +11860,7 @@ function DataTableInner(props, ref) {
11706
11860
  toolbarFilters: resolvedToolbarFilters,
11707
11861
  onToolbarFiltersChange: handleToolbarFiltersChange,
11708
11862
  columnKeys: columnKeys,
11863
+ actionsColumnKey: actionsColumnKey,
11709
11864
  columnOrder: columnOrder,
11710
11865
  defaultColumnOrder: defaultColumnOrder,
11711
11866
  onColumnOrderChange: onColumnOrderChange,