@crispy-seed/data-table 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +30 -0
  3. package/README.md +103 -0
  4. package/dist/DataTable-12s-8LMBtS2u.cjs +1532 -0
  5. package/dist/DataTable-12s-Bd20OuMs.js +1482 -0
  6. package/dist/DataTable-12s-Zml1x9Kr-12s-CTRzgvMT.cjs +161 -0
  7. package/dist/DataTable-12s-Zml1x9Kr-12s-Coi-3lUa.js +153 -0
  8. package/dist/Menu-12s-Db_zr1AP.cjs +104 -0
  9. package/dist/Menu-12s-Di5JADW4.js +78 -0
  10. package/dist/Select-12s-1Uh7XbkG.js +219 -0
  11. package/dist/Select-12s-D8DdKT-U.cjs +250 -0
  12. package/dist/body-cells-12s-BnOVUTKN.js +453 -0
  13. package/dist/body-cells-12s-BoOTcg-l.cjs +462 -0
  14. package/dist/column-calc-12s-C6IPSOaF.js +129 -0
  15. package/dist/column-calc-12s-CKuSpe-l.cjs +149 -0
  16. package/dist/column-layout-12s-CTu5yT_D.cjs +120 -0
  17. package/dist/column-layout-12s-s7wnxkMN.js +99 -0
  18. package/dist/column-menu-12s-BPE9N1gs.cjs +427 -0
  19. package/dist/column-menu-12s-mRBk-4oa.js +407 -0
  20. package/dist/data-table-recipe.css +442 -0
  21. package/dist/data-table-recipe.layered.css +505 -0
  22. package/dist/editors-12s-BO9Mp034.js +525 -0
  23. package/dist/editors-12s-DO8TZkYV.cjs +555 -0
  24. package/dist/index.cjs +14 -0
  25. package/dist/index.d.ts +323 -0
  26. package/dist/index.js +10 -0
  27. package/dist/resize-12s-jQY-PX67.cjs +58 -0
  28. package/dist/resize-12s-nsMvrmLt.js +58 -0
  29. package/dist/states-12s-CLO_uVue.cjs +125 -0
  30. package/dist/states-12s-DEFSxJCO.js +122 -0
  31. package/dist/styles.css +14660 -0
  32. package/dist/toolbar-12s-AVU-sbDW.js +69 -0
  33. package/dist/toolbar-12s-CaLgJrDo.cjs +71 -0
  34. package/dist/useDataTable-12s-BHiDUubw-12s-CBeCwTe7.js +61 -0
  35. package/dist/useDataTable-12s-BHiDUubw-12s-Dgvt7XDk.cjs +61 -0
  36. package/dist/useDataTableColumnCalc-12s-DTQQTtEJ-12s-CvD14JYo.cjs +207 -0
  37. package/dist/useDataTableColumnCalc-12s-DTQQTtEJ-12s-DsEse3uq.js +183 -0
  38. package/dist/useDataTableColumns-12s-Cn2ZAzFL-12s-CD6goR59.js +289 -0
  39. package/dist/useDataTableColumns-12s-Cn2ZAzFL-12s-CUk_CpYT.cjs +292 -0
  40. package/dist/useDataTableEdit-12s-9Wb_UCrN-12s-BoOHq3GB.js +98 -0
  41. package/dist/useDataTableEdit-12s-9Wb_UCrN-12s-De6YHBba.cjs +98 -0
  42. package/dist/useDataTableFilter-12s-ZzbmWMin-12s-CWyBeFna.js +74 -0
  43. package/dist/useDataTableFilter-12s-ZzbmWMin-12s-lpjzZY3_.cjs +74 -0
  44. package/dist/useDataTableInfiniteScroll-12s-8ZG31URd-12s-BexjP6iO.js +104 -0
  45. package/dist/useDataTableInfiniteScroll-12s-8ZG31URd-12s-Bt8gojr9.cjs +104 -0
  46. package/dist/useDataTableRow-12s-CPYaDa1p-12s-BmUSAnPe.js +30 -0
  47. package/dist/useDataTableRow-12s-CPYaDa1p-12s-D-DRjwAe.cjs +30 -0
  48. package/dist/useDataTableScroll-12s-BKDCr0en-12s-C7f2vHeG.js +61 -0
  49. package/dist/useDataTableScroll-12s-BKDCr0en-12s-CUvUYMtt.cjs +61 -0
  50. package/dist/useDataTableSearch-12s-Ck3iWcpX-12s-B-65V6gH.js +37 -0
  51. package/dist/useDataTableSearch-12s-Ck3iWcpX-12s-DhVfN2Hq.cjs +37 -0
  52. package/dist/useDataTableSelection-12s-BIDtiRQq-12s-IS__VAnU.cjs +71 -0
  53. package/dist/useDataTableSelection-12s-BIDtiRQq-12s-O6M_BhrH.js +71 -0
  54. package/dist/useDataTableSort-12s-DvJYtmeS-12s-C5VGnsq4.cjs +78 -0
  55. package/dist/useDataTableSort-12s-DvJYtmeS-12s-DABSNt6U.js +78 -0
  56. package/package.json +78 -0
@@ -0,0 +1,427 @@
1
+ 'use client';
2
+ function __insertCSS(code) {
3
+ if (!code || typeof document == 'undefined') return
4
+ let head = document.head || document.getElementsByTagName('head')[0]
5
+ let style = document.createElement('style')
6
+ style.type = 'text/css'
7
+ head.appendChild(style)
8
+ ;style.styleSheet ? (style.styleSheet.cssText = code) : style.appendChild(document.createTextNode(code))
9
+ }
10
+
11
+ var jsxRuntime = require('react/jsx-runtime');
12
+ var React = require('react');
13
+ var DataTable12s = require('./DataTable-12s-8LMBtS2u.cjs');
14
+ var domUtils = require('@seed-design/dom-utils');
15
+ var Menu12s = require('./Menu-12s-Db_zr1AP.cjs');
16
+ var segmentedControl = require('@seed-design/css/recipes/segmented-control');
17
+ var reactPrimitive = require('@seed-design/react-primitive');
18
+ var reactSegmentedControl = require('@seed-design/react-segmented-control');
19
+ var columnLayout12s = require('./column-layout-12s-CTu5yT_D.cjs');
20
+ var resize12s = require('./resize-12s-jQY-PX67.cjs');
21
+ var DataTable12sZml1x9Kr12s = require('./DataTable-12s-Zml1x9Kr-12s-CTRzgvMT.cjs');
22
+
23
+ function _interopNamespace(e) {
24
+ if (e && e.__esModule) return e;
25
+ var n = Object.create(null);
26
+ if (e) {
27
+ Object.keys(e).forEach(function (k) {
28
+ if (k !== 'default') {
29
+ var d = Object.getOwnPropertyDescriptor(e, k);
30
+ Object.defineProperty(n, k, d.get ? d : {
31
+ enumerable: true,
32
+ get: function () { return e[k]; }
33
+ });
34
+ }
35
+ });
36
+ }
37
+ n.default = e;
38
+ return n;
39
+ }
40
+
41
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
42
+
43
+ const { withProvider, withContext } = DataTable12s.createSlotRecipeContext(segmentedControl.segmentedControl);
44
+ const SegmentedControlRoot = withProvider(reactSegmentedControl.SegmentedControl.Root, "root");
45
+ const SegmentedControlIndicator = withContext(reactPrimitive.Primitive.div, "indicator");
46
+ const SegmentedControlItem = withContext(reactSegmentedControl.SegmentedControl.Item, "item");
47
+ const SegmentedControlItemHiddenInput = reactSegmentedControl.SegmentedControl.ItemHiddenInput;
48
+
49
+ // Same fix as cells.tsx's `CheckboxCell`/editors.tsx's `CheckboxEditor` -- seed's
50
+ // `CheckboxIndicator` needs a real icon for its `checked` prop (it renders exactly
51
+ // what's passed there, nothing automatically); `checked={null}` here used to render an
52
+ // empty box even once a value was actually checked. 12px, matching the row-selection
53
+ // checkbox's own already-correct icon size (`DataTable.tsx`'s `SELECTION_ICON_SIZE`).
54
+ const FILTER_CHECKED_ICON = /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconCheckmarkLine_default, {
55
+ size: 12
56
+ });
57
+ // Fix (bug report): karrot icons default to a 24px intrinsic `width`/`height`
58
+ // SVG ATTRIBUTE (not CSS) -- inside a fixed 16px `headerCellIcon` box (a flex
59
+ // item), flexbox only auto-shrinks the MAIN axis (width) to fit, leaving the
60
+ // CROSS axis (height) at its full 24px intrinsic size, so the glyph rendered
61
+ // visibly oversized/non-square and spilled out of its slot (measured live:
62
+ // 16×24, not 16×16). Passing `size` sets both attributes directly, sidestepping
63
+ // the mismatch entirely rather than fighting it with more CSS. Matches crisp's
64
+ // own measured `.crisp-datatable-chevron` size (14px).
65
+ const SORT_ICON_SIZE = 14;
66
+ const DEFAULT_SORT_ICON = {
67
+ idle: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconChevronDownLine_default, {
68
+ size: SORT_ICON_SIZE
69
+ }),
70
+ asc: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconChevronUpLine_default, {
71
+ size: SORT_ICON_SIZE
72
+ }),
73
+ desc: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconChevronDownLine_default, {
74
+ size: SORT_ICON_SIZE
75
+ })
76
+ };
77
+ /**
78
+ * Rendered for EVERY sortable column, sorted or not -- unlike a naive "only show the
79
+ * active column's arrow", Attio reveals a neutral chevron on ANY sortable header on
80
+ * hover (`data-chevron`'s own CSS in `data-table.ts` owns the opacity: 0 at rest, 0.6
81
+ * on header hover, 1 + full foreground once sorted). Conditionally rendering only the
82
+ * sorted state, the way this component used to, has nothing for that hover state to
83
+ * reveal.
84
+ */ function SortIndicator({ columnKey, icon }) {
85
+ const { sort } = DataTable12sZml1x9Kr12s.useDataTableContext();
86
+ const isSorted = sort?.key === columnKey;
87
+ const resolved = isSorted ? sort?.dir === "asc" ? icon?.asc ?? DEFAULT_SORT_ICON.asc : icon?.desc ?? DEFAULT_SORT_ICON.desc : icon?.idle ?? DEFAULT_SORT_ICON.idle;
88
+ return /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.DataTableHeaderCellIcon, {
89
+ "aria-hidden": true,
90
+ "data-chevron": "",
91
+ draggable: false,
92
+ children: resolved
93
+ });
94
+ }
95
+ /** Attio's own condition word: "Is"/"Is not" alone with zero or one value checked,
96
+ * "Is any of"/"Is not any of" once a second value joins the set -- the underlying
97
+ * predicate never changes (`useDataTableFilter.ts`'s own comment: membership in a
98
+ * set of one IS "is X"), only the word describing it does. */ function filterConditionLabel(mode, hasMultipleValues) {
99
+ if (mode === "isnot") return hasMultipleValues ? "Is not any of" : "Is not";
100
+ return hasMultipleValues ? "Is any of" : "Is";
101
+ }
102
+ /**
103
+ * A column's "is / is not / is any of" checkbox filter picker (DATATABLE-ATTIO-
104
+ * SPEC.md's Feature contract), Attio's own chrome: a two-way condition control above a
105
+ * checkbox value list, both built from seed's own documented components -- `Menu` for
106
+ * the popover shell (`MenuRoot`/`Trigger`/`Positioner`/`Content`, unchanged), seed's
107
+ * `SegmentedControl` (docs/content/react/components/segmented-control.mdx) for the
108
+ * is/is-not toggle in place of the two hand-styled buttons (hardcoded hex, no seed
109
+ * token) this used to be, and plain `<label>` + `CheckboxRoot` rows for the value
110
+ * list -- NOT `MenuItem` there either: `MenuItem`'s own `getItemProps` (`useMenu.ts`)
111
+ * closes the menu unconditionally after every click, which is correct for a normal
112
+ * command menu but would close this ENTIRE popover after a single condition pick or a
113
+ * single checked value -- exactly wrong for a control meant to stay open while the
114
+ * condition changes and several boxes get checked. `SegmentedControl` has no such
115
+ * auto-close (it's a plain controlled radio group, not a menu), which is exactly why
116
+ * it -- not `MenuItem` -- is the documented component that fits here.
117
+ */ function FilterMenu({ column }) {
118
+ const { filters, toggleFilterValue, setFilterMode } = DataTable12sZml1x9Kr12s.useDataTableContext();
119
+ const values = column.filterValues ?? [];
120
+ const current = filters[column.key];
121
+ const mode = current?.mode ?? "is";
122
+ const checkedValues = current?.values ?? [];
123
+ const hasMultipleValues = checkedValues.length > 1;
124
+ const columnLabel = typeof column.header === "string" ? column.header : column.key;
125
+ // A filter trigger lives INSIDE a (possibly sortable) header cell, whose own
126
+ // onClick/onKeyDown toggle sort -- stop the event here so opening the filter
127
+ // picker never also reorders the rows out from under it.
128
+ const stopPropagation = (event)=>event.stopPropagation();
129
+ return /*#__PURE__*/ jsxRuntime.jsxs(Menu12s.MenuRoot, {
130
+ children: [
131
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.DataTableHeaderCellIcon, {
132
+ asChild: true,
133
+ onClick: stopPropagation,
134
+ onKeyDown: stopPropagation,
135
+ draggable: false,
136
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuTrigger, {
137
+ "aria-label": `Filter ${columnLabel}`,
138
+ "data-active": domUtils.dataAttr(checkedValues.length > 0),
139
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconSlider2HorizontalLine_default, {
140
+ size: 16
141
+ })
142
+ })
143
+ }),
144
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuPositioner, {
145
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuContent, {
146
+ style: {
147
+ minWidth: 180
148
+ },
149
+ children: /*#__PURE__*/ jsxRuntime.jsxs(Menu12s.MenuScrollArea, {
150
+ children: [
151
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
152
+ style: {
153
+ padding: "0 8px"
154
+ },
155
+ children: /*#__PURE__*/ jsxRuntime.jsxs(SegmentedControlRoot, {
156
+ "aria-label": `${columnLabel} filter condition`,
157
+ value: mode,
158
+ onValueChange: (next)=>setFilterMode(column.key, next),
159
+ style: {
160
+ width: "100%"
161
+ },
162
+ children: [
163
+ /*#__PURE__*/ jsxRuntime.jsxs(SegmentedControlItem, {
164
+ value: "is",
165
+ children: [
166
+ /*#__PURE__*/ jsxRuntime.jsx(SegmentedControlItemHiddenInput, {}),
167
+ filterConditionLabel("is", hasMultipleValues)
168
+ ]
169
+ }),
170
+ /*#__PURE__*/ jsxRuntime.jsxs(SegmentedControlItem, {
171
+ value: "isnot",
172
+ children: [
173
+ /*#__PURE__*/ jsxRuntime.jsx(SegmentedControlItemHiddenInput, {}),
174
+ filterConditionLabel("isnot", hasMultipleValues)
175
+ ]
176
+ }),
177
+ /*#__PURE__*/ jsxRuntime.jsx(SegmentedControlIndicator, {})
178
+ ]
179
+ })
180
+ }),
181
+ values.map((value)=>// `CheckboxRoot` is ALREADY a `<label>` (`Checkbox.tsx`'s own
182
+ // `Primitive.label`) wrapping the hidden input + `CheckboxLabel` text --
183
+ // wrapping it in a SECOND `<label>` here used to nest one label inside
184
+ // another, which is invalid HTML and made a click on the row's own text
185
+ // reach the checkbox's native activation twice (once via each label),
186
+ // toggling it on then immediately back off. `CheckboxRoot` takes the
187
+ // row's own layout via `style` directly instead.
188
+ /*#__PURE__*/ jsxRuntime.jsxs(DataTable12s.CheckboxRoot, {
189
+ checked: checkedValues.includes(value),
190
+ onCheckedChange: ()=>toggleFilterValue(column.key, value),
191
+ style: {
192
+ display: "flex",
193
+ alignItems: "center",
194
+ gap: 8,
195
+ padding: "4px 8px",
196
+ cursor: "pointer"
197
+ },
198
+ children: [
199
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.CheckboxControl, {
200
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.CheckboxIndicator, {
201
+ checked: FILTER_CHECKED_ICON
202
+ })
203
+ }),
204
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.CheckboxLabel, {
205
+ children: value
206
+ }),
207
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.CheckboxHiddenInput, {
208
+ "aria-label": value
209
+ })
210
+ ]
211
+ }, value))
212
+ ]
213
+ })
214
+ })
215
+ })
216
+ ]
217
+ });
218
+ }
219
+ /** Every header cell, in the effective (ordered, visible) order -- a standalone
220
+ * component (not inlined in `DataTableInner`'s render) so it alone re-renders when
221
+ * `visibleColumnOrder`/labels/widths change, without also re-deriving `sortedData`'s
222
+ * render above it. */ function ColumnHeaderCells({ columns, columnMenu, reorderable, resizable, sortIcon, selectable, stickyFirst, stickyLast }) {
223
+ const { draggingColumnKey, beginColumnDrag, dragOverColumn, endColumnDrag } = DataTable12sZml1x9Kr12s.useDataTableContext();
224
+ const effective = columnLayout12s.useEffectiveColumns(columns);
225
+ const [renamingKey, setRenamingKey] = React__namespace.useState(null);
226
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
227
+ children: effective.map(({ column, label, width }, index)=>{
228
+ const isFirst = index === 0;
229
+ const isLast = index === effective.length - 1;
230
+ const sticky = columnLayout12s.stickyProps({
231
+ selectable,
232
+ stickyFirst,
233
+ stickyLast,
234
+ isSelectionCell: false,
235
+ isFirst,
236
+ isLast
237
+ });
238
+ return /*#__PURE__*/ jsxRuntime.jsxs(DataTable12s.DataTableHeaderCell, {
239
+ columnKey: column.key,
240
+ sortable: column.sortable,
241
+ "data-column-key": column.key,
242
+ draggable: reorderable && renamingKey !== column.key,
243
+ onDragStart: (event)=>{
244
+ event.dataTransfer.effectAllowed = "move";
245
+ beginColumnDrag(column.key);
246
+ },
247
+ onDragOver: (event)=>{
248
+ event.preventDefault();
249
+ if (draggingColumnKey && draggingColumnKey !== column.key) dragOverColumn(column.key);
250
+ },
251
+ onDrop: (event)=>event.preventDefault(),
252
+ onDragEnd: endColumnDrag,
253
+ "data-dragging": domUtils.dataAttr(draggingColumnKey === column.key),
254
+ style: sticky.style,
255
+ "data-sticky": sticky["data-sticky"],
256
+ "data-sticky-edge": sticky["data-sticky-edge"],
257
+ "data-sticky-edge-end": sticky["data-sticky-edge-end"],
258
+ children: [
259
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.DataTableHeaderCellInner, {
260
+ children: renamingKey === column.key ? /*#__PURE__*/ jsxRuntime.jsx(ColumnRenameInput, {
261
+ column: column,
262
+ initialLabel: typeof label === "string" ? label : column.key,
263
+ onDone: ()=>setRenamingKey(null)
264
+ }) : /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
265
+ children: [
266
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.DataTableHeaderCellLabel, {
267
+ children: label
268
+ }),
269
+ column.filterValues && column.filterValues.length > 0 && /*#__PURE__*/ jsxRuntime.jsx(FilterMenu, {
270
+ column: column
271
+ }),
272
+ column.sortable && /*#__PURE__*/ jsxRuntime.jsx(SortIndicator, {
273
+ columnKey: column.key,
274
+ icon: sortIcon
275
+ }),
276
+ columnMenu && /*#__PURE__*/ jsxRuntime.jsx(ColumnMenu, {
277
+ column: column,
278
+ onRename: ()=>setRenamingKey(column.key)
279
+ })
280
+ ]
281
+ })
282
+ }),
283
+ resizable && column.resizable !== false && /*#__PURE__*/ jsxRuntime.jsx(resize12s.ColumnResizeHandle, {
284
+ columnKey: column.key,
285
+ width: width
286
+ })
287
+ ]
288
+ }, column.key);
289
+ })
290
+ });
291
+ }
292
+ function ColumnRenameInput({ column, initialLabel, onDone }) {
293
+ const { renameColumn } = DataTable12sZml1x9Kr12s.useDataTableContext();
294
+ const [value, setValue] = React__namespace.useState(initialLabel);
295
+ // Opening this input is ITSELF the result of clicking a `MenuItem` -- the menu's own
296
+ // close (which happens on that same click) restores focus to its trigger a beat
297
+ // later, and that focus move fires as a `blur` on this input the instant it mounts
298
+ // with `autoFocus`. Committing on THAT blur would silently re-close the editor
299
+ // before anyone saw it (found writing this file's own rename test, which failed
300
+ // with the header reverting to its plain label with no visible input in between).
301
+ // `ready` flips true one frame after mount, so only a blur after that -- an actual
302
+ // click/tab away -- commits.
303
+ const readyRef = React__namespace.useRef(false);
304
+ const inputRef = React__namespace.useRef(null);
305
+ React__namespace.useEffect(()=>{
306
+ // The menu's close restores focus to its trigger one frame after this input
307
+ // mounts, stealing focus from `autoFocus`. Re-grab it in the SAME frame (after
308
+ // the restore) and select the text, so the user can type/replace immediately.
309
+ const frame = requestAnimationFrame(()=>{
310
+ readyRef.current = true;
311
+ inputRef.current?.focus();
312
+ inputRef.current?.select();
313
+ });
314
+ return ()=>cancelAnimationFrame(frame);
315
+ }, []);
316
+ const commit = ()=>{
317
+ if (value.trim()) renameColumn(column.key, value.trim());
318
+ onDone();
319
+ };
320
+ return(// A bare, minimal input -- NOT seed's `TextField` (its labeled root measures
321
+ // ~52px tall, per DATATABLE-ATTIO-SPEC.md's own note; this has to fit a 40px
322
+ // header cell with no label/description chrome of its own). Seed has no lighter
323
+ // input primitive at this level, so this follows crisp's own measured
324
+ // `.crisp-datatable-th-rename` (`datatable.recipe.ts`) instead: full-width,
325
+ // header-row height, a small inset, no border (an inset brand-solid box-shadow
326
+ // stands in for a focus ring), the header's own font weight/size inherited
327
+ // rather than a new size introduced for one input.
328
+ /*#__PURE__*/ jsxRuntime.jsx("input", {
329
+ ref: inputRef,
330
+ // biome-ignore lint/a11y/noAutofocus: opening this input IS the user's own click a moment earlier (crisp's `.crisp-datatable-th-rename` does the same), not an unannounced page-load autofocus.
331
+ autoFocus: true,
332
+ "aria-label": `Rename ${initialLabel}`,
333
+ value: value,
334
+ onClick: (event)=>event.stopPropagation(),
335
+ onChange: (event)=>setValue(event.target.value),
336
+ onBlur: ()=>{
337
+ if (readyRef.current) commit();
338
+ },
339
+ onKeyDown: (event)=>{
340
+ event.stopPropagation();
341
+ if (event.key === "Enter") commit();
342
+ if (event.key === "Escape") onDone();
343
+ },
344
+ // Bare inline input: no border/ring/background/radius -- it reads as the
345
+ // header label made editable in place, not a boxed field.
346
+ style: {
347
+ width: "100%",
348
+ minWidth: 0,
349
+ height: "100%",
350
+ margin: 0,
351
+ padding: 0,
352
+ border: "none",
353
+ borderRadius: 0,
354
+ background: "transparent",
355
+ boxShadow: "none",
356
+ font: "inherit",
357
+ fontWeight: "var(--seed-font-weight-medium)",
358
+ color: "var(--seed-color-fg-neutral)",
359
+ outline: "none"
360
+ }
361
+ }));
362
+ }
363
+ /** The per-column header menu (rename / hide / move left / move right) -- seed
364
+ * `Menu`, opened from the same `headerCellIcon` slot the filter trigger and sort
365
+ * chevron already share. Hover/focus-reveal (`data-column-menu`'s own CSS in
366
+ * `data-table.ts`) -- crisp's own header shows the trigger only on hover, not
367
+ * permanently, so this one carries its own marker attribute distinct from that
368
+ * slot's OTHER occupants (the sort chevron, the filter trigger), which stay visible
369
+ * under their own separate rules regardless of hover. */ function ColumnMenu({ column, onRename }) {
370
+ const { moveColumn, hideColumn } = DataTable12sZml1x9Kr12s.useDataTableContext();
371
+ const columnLabel = typeof column.header === "string" ? column.header : column.key;
372
+ const stopPropagation = (event)=>event.stopPropagation();
373
+ return /*#__PURE__*/ jsxRuntime.jsxs(Menu12s.MenuRoot, {
374
+ children: [
375
+ /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.DataTableHeaderCellIcon, {
376
+ asChild: true,
377
+ "data-column-menu": "",
378
+ onClick: stopPropagation,
379
+ onKeyDown: stopPropagation,
380
+ draggable: false,
381
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuTrigger, {
382
+ "aria-label": `${columnLabel} column menu`,
383
+ children: /*#__PURE__*/ jsxRuntime.jsx(DataTable12s.IconDot3HorizontalLine_default, {
384
+ size: 16
385
+ })
386
+ })
387
+ }),
388
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuPositioner, {
389
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuContent, {
390
+ style: {
391
+ minWidth: 160
392
+ },
393
+ children: /*#__PURE__*/ jsxRuntime.jsxs(Menu12s.MenuScrollArea, {
394
+ children: [
395
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItem, {
396
+ onClick: onRename,
397
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItemLabel, {
398
+ children: "Rename"
399
+ })
400
+ }),
401
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItem, {
402
+ onClick: ()=>moveColumn(column.key, "left"),
403
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItemLabel, {
404
+ children: "Move left"
405
+ })
406
+ }),
407
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItem, {
408
+ onClick: ()=>moveColumn(column.key, "right"),
409
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItemLabel, {
410
+ children: "Move right"
411
+ })
412
+ }),
413
+ /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItem, {
414
+ onClick: ()=>hideColumn(column.key),
415
+ children: /*#__PURE__*/ jsxRuntime.jsx(Menu12s.MenuItemLabel, {
416
+ children: "Hide column"
417
+ })
418
+ })
419
+ ]
420
+ })
421
+ })
422
+ })
423
+ ]
424
+ });
425
+ }
426
+
427
+ exports.ColumnHeaderCells = ColumnHeaderCells;