@seekalfred/primitives 0.7.4 → 0.8.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 (87) hide show
  1. package/README.md +255 -3
  2. package/dist/alert/alert.d.ts +2 -2
  3. package/dist/alert/alert.js +1 -1
  4. package/dist/alert/alert.js.map +1 -1
  5. package/dist/alert-dialog/alert-dialog.js +1 -1
  6. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  7. package/dist/avatar/avatar.d.ts +1 -1
  8. package/dist/badge/badge.d.ts +16 -1
  9. package/dist/badge/badge.js +12 -5
  10. package/dist/badge/badge.js.map +1 -1
  11. package/dist/button/button.d.ts +24 -2
  12. package/dist/button/button.js +62 -13
  13. package/dist/button/button.js.map +1 -1
  14. package/dist/card/card.js +1 -1
  15. package/dist/card/card.js.map +1 -1
  16. package/dist/checkbox/checkbox.d.ts +25 -1
  17. package/dist/checkbox/checkbox.js +103 -28
  18. package/dist/checkbox/checkbox.js.map +1 -1
  19. package/dist/checkbox/index.d.ts +2 -2
  20. package/dist/checkbox/index.js +2 -2
  21. package/dist/code-block/code-block.d.ts +45 -0
  22. package/dist/code-block/code-block.js +74 -0
  23. package/dist/code-block/code-block.js.map +1 -0
  24. package/dist/code-block/index.d.ts +2 -0
  25. package/dist/code-block/index.js +2 -0
  26. package/dist/command-palette/command-palette.d.ts +128 -0
  27. package/dist/command-palette/command-palette.js +371 -0
  28. package/dist/command-palette/command-palette.js.map +1 -0
  29. package/dist/command-palette/index.d.ts +2 -0
  30. package/dist/command-palette/index.js +2 -0
  31. package/dist/dialog/dialog.js +1 -1
  32. package/dist/dialog/dialog.js.map +1 -1
  33. package/dist/empty-state/empty-state.d.ts +17 -0
  34. package/dist/empty-state/empty-state.js +9 -7
  35. package/dist/empty-state/empty-state.js.map +1 -1
  36. package/dist/index.d.ts +8 -4
  37. package/dist/index.js +12 -8
  38. package/dist/info-tooltip/index.d.ts +2 -0
  39. package/dist/info-tooltip/index.js +2 -0
  40. package/dist/info-tooltip/info-tooltip.d.ts +35 -0
  41. package/dist/info-tooltip/info-tooltip.js +49 -0
  42. package/dist/info-tooltip/info-tooltip.js.map +1 -0
  43. package/dist/input/input.js +1 -1
  44. package/dist/lib/selection-control.js +32 -1
  45. package/dist/lib/selection-control.js.map +1 -1
  46. package/dist/line-chart/line-chart.d.ts +2 -1
  47. package/dist/line-chart/line-chart.js +2 -2
  48. package/dist/line-chart/line-chart.js.map +1 -1
  49. package/dist/mention-input/mention-input.js +1 -1
  50. package/dist/money-input/money-input.js +1 -1
  51. package/dist/multi-select/multi-select.js +1 -1
  52. package/dist/number-field/number-field.js +1 -1
  53. package/dist/password-field/password-field.js +1 -1
  54. package/dist/password-strength/password-strength.js +1 -1
  55. package/dist/phone-input/phone-input.js +1 -1
  56. package/dist/popover/popover.js +1 -1
  57. package/dist/popover/popover.js.map +1 -1
  58. package/dist/progress/progress.d.ts +3 -3
  59. package/dist/radio-group/radio-group.d.ts +12 -3
  60. package/dist/radio-group/radio-group.js +62 -52
  61. package/dist/radio-group/radio-group.js.map +1 -1
  62. package/dist/rich-text-editor/rich-text-editor.js +1 -1
  63. package/dist/scroll-area/scroll-area.d.ts +1 -1
  64. package/dist/search-field/search-field.js +1 -1
  65. package/dist/select/select.d.ts +1 -1
  66. package/dist/select/select.js +1 -1
  67. package/dist/separator/separator.d.ts +1 -1
  68. package/dist/shortcut-recorder/shortcut-recorder.js +1 -1
  69. package/dist/stat-card/stat-card.d.ts +2 -2
  70. package/dist/styles.css +1 -1
  71. package/dist/table/index.d.ts +2 -2
  72. package/dist/table/index.js +2 -2
  73. package/dist/table/table.d.ts +99 -1
  74. package/dist/table/table.js +123 -23
  75. package/dist/table/table.js.map +1 -1
  76. package/dist/tabs/tabs.d.ts +4 -2
  77. package/dist/tabs/tabs.js +7 -5
  78. package/dist/tabs/tabs.js.map +1 -1
  79. package/dist/tag-input/tag-input.js +1 -1
  80. package/dist/textarea/textarea.js +1 -1
  81. package/dist/toast/toast.d.ts +2 -2
  82. package/dist/toggle-button/index.d.ts +2 -0
  83. package/dist/toggle-button/index.js +2 -0
  84. package/dist/toggle-button/toggle-button.d.ts +93 -0
  85. package/dist/toggle-button/toggle-button.js +199 -0
  86. package/dist/toggle-button/toggle-button.js.map +1 -0
  87. package/package.json +19 -3
@@ -1,2 +1,2 @@
1
- import { Column, RowKey, Table, TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants } from "./table.js";
2
- export { type Column, type RowKey, Table, type TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
1
+ import { Column, RowAttributes, RowKey, Table, TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableDetailCellVariants, tableDetailRowVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants } from "./table.js";
2
+ export { type Column, type RowAttributes, type RowKey, Table, type TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableDetailCellVariants, tableDetailRowVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
@@ -1,2 +1,2 @@
1
- import { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants } from "./table.js";
2
- export { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
1
+ import { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableDetailCellVariants, tableDetailRowVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants } from "./table.js";
2
+ export { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableDetailCellVariants, tableDetailRowVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
@@ -122,6 +122,15 @@ export declare const tableExpandButtonVariants: (props?: import("class-variance-
122
122
  * reads as a heading of the rows that follow rather than as one of them.
123
123
  */
124
124
  export declare const tableGroupRowVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
125
+ /**
126
+ * A detail row (`renderExpandedRow`): one cell spanning the row, under the row it
127
+ * belongs to. Not interactive, so it takes no hover, focus or selection fill and
128
+ * no rule of its own: it reads as part of the row above, and the next row's rule
129
+ * closes it.
130
+ */
131
+ export declare const tableDetailRowVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
132
+ /** The cell of a detail row. The table's own inset, so the content is not flush against the edge. */
133
+ export declare const tableDetailCellVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
125
134
  /**
126
135
  * The sort control of a column header in a plain table (`keyboardModel="table"`).
127
136
  *
@@ -132,7 +141,7 @@ export declare const tableGroupRowVariants: (props?: import("class-variance-auth
132
141
  */
133
142
  export declare const tableSortButtonVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
134
143
  export declare const tableRowVariants: (props?: ({
135
- variant?: "lined" | "plain" | null | undefined;
144
+ variant?: "plain" | "lined" | null | undefined;
136
145
  striped?: boolean | null | undefined;
137
146
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
138
147
  export declare const tableCellVariants: (props?: ({
@@ -190,6 +199,17 @@ type Column$1<T, V = unknown> = {
190
199
  value: V;
191
200
  row: T;
192
201
  index: number;
202
+ /**
203
+ * Whether the row is in the table's expanded set (`expandedKeys`). True for a
204
+ * row opened onto sub-rows or onto a detail row (`renderExpandedRow`).
205
+ */
206
+ isExpanded: boolean;
207
+ /**
208
+ * Opens the row if it is closed and closes it if it is open, through the same
209
+ * set as `expandedKeys` / `onExpandedChange`. For a trigger of your own in a
210
+ * cell (a "History" button), which is how a detail row is opened.
211
+ */
212
+ toggleExpanded: () => void;
193
213
  }): ReactNode;
194
214
  /**
195
215
  * Value to string. Deliberately separate from `cell`: this is what CSV
@@ -221,7 +241,50 @@ type Column$1<T, V = unknown> = {
221
241
  numeric?: boolean;
222
242
  /** Opts this column into sorting. Off by default. */
223
243
  sortable?: boolean;
244
+ /**
245
+ * Makes this cell span the columns after it, per row: return how many columns
246
+ * the row's cell in this column covers (1 or nothing is the usual single
247
+ * cell). The cells it covers are not rendered, so `cell` renders for THIS
248
+ * column alone and its content is what fills the span ("No impressions yet"
249
+ * across clicks and CTR; "Not enough data" across five figure columns).
250
+ *
251
+ * The span is clamped to the columns that are left, so it can never run past
252
+ * the row. A row's span never touches the header, which keeps one cell per
253
+ * column, so columns stay named and sortable. It is ignored on the first
254
+ * column while `stickyFirstColumn` is on (the frozen pane stays one column
255
+ * wide) and on group rows (`isGroupRow`), whose first cell already spans the
256
+ * row.
257
+ *
258
+ * Method syntax, for the same reason as `cell`.
259
+ */
260
+ colSpan?(row: T): number | undefined;
261
+ /**
262
+ * Content after the header label that is NOT part of the sort control: an
263
+ * info icon with a tooltip, a help link. It sits beside the label, so on a
264
+ * sortable column clicking or pressing Enter or Space on it does not sort,
265
+ * and in a plain table (`keyboardModel="table"`) it is a sibling of the sort
266
+ * button rather than inside it. It must name itself (`aria-label`) and be at
267
+ * least 24px square, like any control. Not rendered with `headerHidden`.
268
+ */
269
+ headerAddon?: ReactNode;
270
+ /**
271
+ * Marks this column as the one to look at (the latest run, the current
272
+ * plan): its header and every cell wear the library's highlight tint and
273
+ * carry `data-highlighted`, and the header takes the stronger text colour.
274
+ * The tint is not the message, so the column should say why in its own
275
+ * content, as with `isRowHighlighted`. Off by default.
276
+ */
277
+ highlighted?: boolean;
224
278
  };
279
+ /**
280
+ * What `getRowProps` may return: `data-*` attributes. Anything else is ignored.
281
+ *
282
+ * Not `aria-*`: React Aria's Row filters its props down to `data-*` and its own
283
+ * labelling, so an `aria-current` handed to a grid row is dropped with no error
284
+ * -- the same silent loss as `Column.width`. A type that allowed it would lie.
285
+ * Not `onClick` either -- see `onRowAction`.
286
+ */
287
+ export type RowAttributes = { [K in `data-${string}`]?: string | number | boolean | undefined; };
225
288
  export interface TableProps<T> extends VariantProps<typeof tableRowVariants> {
226
289
  /** The rows to render. */
227
290
  data: readonly T[];
@@ -269,6 +332,22 @@ export interface TableProps<T> extends VariantProps<typeof tableRowVariants> {
269
332
  isRowHighlighted?: (row: T) => boolean;
270
333
  /** Extra classes per row, for styling that depends on row DATA. */
271
334
  rowClassName?: (row: T) => string;
335
+ /**
336
+ * Extra `data-*` attributes per row, for what depends on row DATA and has to
337
+ * reach the `<tr>`: a `data-testid`, a `data-name` for a script. Only `data-*`
338
+ * keys are read (React Aria's grid row drops any `aria-*`). The library's own
339
+ * attributes (`data-slot`, `data-highlighted`, `data-depth`, `data-flip`, the
340
+ * row id and the grid's own roles and states) are applied after yours and
341
+ * win a clash.
342
+ *
343
+ * There is deliberately no `onClick`. In the grid a row is a React Aria
344
+ * control and its press is `onRowAction`, which receives the row; in a plain
345
+ * table a row is not a control, so put the action in a cell.
346
+ *
347
+ * Applies to data rows, not to a detail row. Called on every render for every
348
+ * shown row, so keep it cheap.
349
+ */
350
+ getRowProps?: (row: T) => RowAttributes | undefined;
272
351
  /**
273
352
  * Rendered in place of the rows when `data` is empty.
274
353
  *
@@ -414,6 +493,25 @@ export interface TableProps<T> extends VariantProps<typeof tableRowVariants> {
414
493
  * render.
415
494
  */
416
495
  getSubRows?: (row: T) => readonly T[] | null | undefined;
496
+ /**
497
+ * A full-width row under a row, shown while the row is expanded: arbitrary
498
+ * content (a history, a log, a form) rather than more rows. Return nothing
499
+ * (null, undefined or false) for a row that has no detail.
500
+ *
501
+ * This is NOT `getSubRows`. Sub-rows are data rows with the table's own
502
+ * columns, selection and actions, drawn with a disclosure button; a detail row
503
+ * is one cell spanning every column, holds anything, is never selected,
504
+ * sorted, counted or acted on, and has no built-in button. Open it with a
505
+ * trigger of your own in a cell, using `toggleExpanded` and `isExpanded` from
506
+ * the `cell` context (give it `aria-expanded`), or with `defaultExpandedKeys`
507
+ * / `expandedKeys`. It uses the same expanded set as `getSubRows`, so a row
508
+ * with both opens both: the detail row comes first, directly under its row,
509
+ * then the sub-rows.
510
+ *
511
+ * Called only for expanded rows, never for collapsed ones. Still return elements
512
+ * rather than doing work here, as it runs on every render while a row is open.
513
+ */
514
+ renderExpandedRow?: (row: T) => ReactNode;
417
515
  /** The expanded rows, CONTROLLED: their `getRowId` values. */
418
516
  expandedKeys?: Iterable<RowKey>;
419
517
  /** The rows expanded at the start, when uncontrolled. Nothing is, by default. */
@@ -6,7 +6,7 @@ import { useFlip } from "../lib/flip.js";
6
6
  import { Checkbox as Checkbox$1 } from "../checkbox/checkbox.js";
7
7
  import { Select as Select$1, SelectItem } from "../select/select.js";
8
8
  import { cva } from "class-variance-authority";
9
- import { forwardRef, useEffect, useId, useMemo, useRef, useState } from "react";
9
+ import { Fragment, forwardRef, useEffect, useId, useMemo, useRef, useState } from "react";
10
10
  import { Button, Cell, Column, Row, Table, TableBody, TableFooter, TableHeader } from "react-aria-components";
11
11
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
12
  import { flushSync } from "react-dom";
@@ -110,6 +110,34 @@ const CHEVRON_COLUMN_ID = "__table_row_action";
110
110
  const CHEVRON_CELL = "w-10 px-0 text-center";
111
111
  /** Reserved id for the checkbox column of a selectable table. */
112
112
  const SELECT_COLUMN_ID = "__table_row_select";
113
+ /** Prefix of a detail row's id in the grid, so it cannot collide with a real row's. */
114
+ const DETAIL_ROW_PREFIX = "__table_row_detail:";
115
+ /** Only `data-*` gets through `getRowProps`: the rest belongs to the library or to `onRowAction`. */
116
+ function rowAttributes(attributes) {
117
+ if (!attributes) return void 0;
118
+ const kept = {};
119
+ for (const [name, value] of Object.entries(attributes)) if (name.startsWith("data-")) kept[name] = value;
120
+ return kept;
121
+ }
122
+ /** Whether `renderExpandedRow` had anything to show. */
123
+ const hasContent = (content) => content !== null && content !== void 0 && content !== false;
124
+ /**
125
+ * A header add-on's wrapper in the grid, where the header CELL is the sort
126
+ * control. A press or Enter/Space on the add-on is not a request to sort, so
127
+ * those stop here; focus, hover and every other key (the arrows that walk the
128
+ * grid) pass.
129
+ */
130
+ const stopSort = {
131
+ onPointerDown: (e) => e.stopPropagation(),
132
+ onMouseDown: (e) => e.stopPropagation(),
133
+ onClick: (e) => e.stopPropagation(),
134
+ onKeyDown: (e) => {
135
+ if (e.key === "Enter" || e.key === " ") e.stopPropagation();
136
+ },
137
+ onKeyUp: (e) => {
138
+ if (e.key === "Enter" || e.key === " ") e.stopPropagation();
139
+ }
140
+ };
113
141
  /** The checkbox column is as wide as its box needs, with the table's usual inset on its leading side. */
114
142
  const SELECT_CELL = "w-11 px-0 ps-(--density-row-pad-x)";
115
143
  /** The horizontal scroll container. The table owns it; 5 of 6 consumers built one by hand. */
@@ -179,6 +207,8 @@ const tableColumnVariants = cva([
179
207
  "px-(--density-row-pad-x) py-(--density-row-pad-y)",
180
208
  "box-border align-middle text-sm font-semibold select-none",
181
209
  "data-[sorted]:bg-foreground/3 data-[sorted]:text-foreground",
210
+ "data-[highlighted]:bg-primary-subtle data-[highlighted]:text-foreground",
211
+ "data-[highlighted]:data-[sorted]:bg-primary-subtle",
182
212
  ...FOCUS_RING,
183
213
  "data-[allows-sorting]:cursor-pointer"
184
214
  ], {
@@ -237,6 +267,15 @@ const tableExpandButtonVariants = cva([
237
267
  */
238
268
  const tableGroupRowVariants = cva(["bg-header-fill hover:bg-header-fill", "[&>td]:text-sm [&>td]:font-semibold [&>td]:text-muted-foreground"]);
239
269
  /**
270
+ * A detail row (`renderExpandedRow`): one cell spanning the row, under the row it
271
+ * belongs to. Not interactive, so it takes no hover, focus or selection fill and
272
+ * no rule of its own: it reads as part of the row above, and the next row's rule
273
+ * closes it.
274
+ */
275
+ const tableDetailRowVariants = cva(["box-border bg-muted"]);
276
+ /** The cell of a detail row. The table's own inset, so the content is not flush against the edge. */
277
+ const tableDetailCellVariants = cva(["px-(--density-row-pad-x) py-(--density-row-pad-y)", "box-border align-top"]);
278
+ /**
240
279
  * The sort control of a column header in a plain table (`keyboardModel="table"`).
241
280
  *
242
281
  * In the grid the header cell is the control; in a plain table a cell cannot
@@ -279,6 +318,7 @@ const tableCellVariants = cva([
279
318
  "px-(--density-row-pad-x) py-(--density-row-pad-y)",
280
319
  "box-border align-middle wrap-anywhere",
281
320
  "data-[sorted]:bg-foreground/3",
321
+ "data-[highlighted]:bg-primary-subtle data-[highlighted]:data-[sorted]:bg-primary-subtle",
282
322
  ...FOCUS_RING
283
323
  ], {
284
324
  variants: {
@@ -584,7 +624,7 @@ function sortRows(level, columns, sort) {
584
624
  const direction = sort.direction === "descending" ? -1 : 1;
585
625
  return [...level].sort((a, b) => direction * compareKeys(sortKey(sorted, a), sortKey(sorted, b)));
586
626
  }
587
- const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant, sortDescriptor, defaultSortDescriptor, onSortChange, onRowAction, isRowHighlighted, rowClassName, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, selectionLabels, frame, headerType, headerFill, striped, totalRow, empty, minWidth, stickyFirstColumn, pageSize, pageSizeOptions, onPageSizeChange, pageLabels, getSubRows, expandedKeys, defaultExpandedKeys, onExpandedChange, isGroupRow, density, headerHidden, keyboardModel, className, ...props }, ref) {
627
+ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant, sortDescriptor, defaultSortDescriptor, onSortChange, onRowAction, isRowHighlighted, rowClassName, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, selectionLabels, frame, headerType, headerFill, striped, totalRow, empty, minWidth, stickyFirstColumn, pageSize, pageSizeOptions, onPageSizeChange, pageLabels, getSubRows, renderExpandedRow, getRowProps, expandedKeys, defaultExpandedKeys, onExpandedChange, isGroupRow, density, headerHidden, keyboardModel, className, ...props }, ref) {
588
628
  const isControlled = sortDescriptor !== void 0;
589
629
  const [uncontrolledSort, setUncontrolledSort] = useState(defaultSortDescriptor);
590
630
  const activeSort = isControlled ? sortDescriptor : uncontrolledSort;
@@ -645,19 +685,23 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
645
685
  const walk = (level, depth) => {
646
686
  for (const [index, row] of level.entries()) {
647
687
  const subRows = subRowsOf(row);
648
- const isExpanded = subRows.length > 0 && expanded.has(getRowId(row));
688
+ const key = getRowId(row);
689
+ const isExpanded = subRows.length > 0 && expanded.has(key);
690
+ const detail = renderExpandedRow && expanded.has(key) ? renderExpandedRow(row) : void 0;
649
691
  shownRows.push({
650
692
  row,
651
693
  depth,
652
694
  index,
653
695
  hasSubRows: subRows.length > 0,
654
- isExpanded
696
+ isExpanded,
697
+ detail: hasContent(detail) ? detail : void 0
655
698
  });
656
699
  if (isExpanded) walk(sortLevel(subRows), depth + 1);
657
700
  }
658
701
  };
659
702
  walk(visibleRows, 0);
660
703
  const idBase = useId();
704
+ const detailRowKeys = shownRows.filter((shown) => shown.detail !== void 0).map((shown) => `${DETAIL_ROW_PREFIX}${String(getRowId(shown.row))}`);
661
705
  const plain = keyboardModel === "table";
662
706
  const selectable = selectionMode === "multiple" && !plain;
663
707
  const rowAction = plain ? void 0 : onRowAction;
@@ -734,6 +778,12 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
734
778
  children: label
735
779
  }) : label;
736
780
  };
781
+ const headerAddon = (column, grid) => column.headerAddon && !headerHidden ? /* @__PURE__ */ jsx("span", {
782
+ "data-slot": "table-column-addon",
783
+ className: "ms-1 inline-flex items-center align-middle",
784
+ ...grid ? stopSort : void 0,
785
+ children: column.headerAddon
786
+ }) : null;
737
787
  const changeSort = (descriptor) => {
738
788
  if (!isControlled) setUncontrolledSort(descriptor);
739
789
  setPage(1);
@@ -741,11 +791,33 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
741
791
  };
742
792
  const cellContent = (column, row, index) => {
743
793
  const value = column.accessor(row);
744
- return column.cell ? column.cell({
794
+ if (!column.cell) return renderValue(column, value, row);
795
+ const key = getRowId(row);
796
+ return column.cell({
745
797
  value,
746
798
  row,
747
- index
748
- }) : renderValue(column, value, row);
799
+ index,
800
+ isExpanded: expanded.has(key),
801
+ toggleExpanded: () => toggleExpanded(key)
802
+ });
803
+ };
804
+ const cellsOf = (row, isGroup) => {
805
+ if (isGroup) return columns.slice(0, 1).map((column) => ({
806
+ column,
807
+ span: 1
808
+ }));
809
+ const cells = [];
810
+ for (let at = 0; at < columns.length;) {
811
+ const column = columns[at];
812
+ const asked = Math.floor(column.colSpan?.(row) ?? 1);
813
+ const span = stickyFirstColumn && at === 0 ? 1 : Number.isNaN(asked) ? 1 : Math.max(1, Math.min(asked, columns.length - at));
814
+ cells.push({
815
+ column,
816
+ span
817
+ });
818
+ at += span;
819
+ }
820
+ return cells;
749
821
  };
750
822
  const indentClass = (column) => expandable && column === columns[0] && "ps-[calc(var(--density-row-pad-x)+var(--table-row-depth)*--spacing(7))]";
751
823
  const depthStyle = (column, depth) => expandable && column === columns[0] ? { "--table-row-depth": depth } : void 0;
@@ -798,14 +870,15 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
798
870
  className: cnAll(tableHeaderVariants({ headerFill })),
799
871
  children: /* @__PURE__ */ jsx("tr", { children: columns.map((column) => {
800
872
  const sorted = activeSort?.column === column.id ? activeSort.direction : void 0;
801
- return /* @__PURE__ */ jsx("th", {
873
+ return /* @__PURE__ */ jsxs("th", {
802
874
  scope: "col",
803
875
  "data-slot": "table-column",
804
876
  "data-sorted": sortedColumn === column.id || void 0,
877
+ "data-highlighted": column.highlighted || void 0,
805
878
  "aria-sort": isSortable(column) ? sorted ?? "none" : void 0,
806
879
  className: columnClass(column),
807
880
  style: columnStyle(column),
808
- children: isSortable(column) ? /* @__PURE__ */ jsx("button", {
881
+ children: [isSortable(column) ? /* @__PURE__ */ jsx("button", {
809
882
  type: "button",
810
883
  "data-slot": "table-sort-button",
811
884
  className: cnAll(tableSortButtonVariants()),
@@ -814,7 +887,7 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
814
887
  direction: sorted === "ascending" ? "descending" : "ascending"
815
888
  }),
816
889
  children: headerLabel(column)
817
- }) : headerLabel(column)
890
+ }) : headerLabel(column), headerAddon(column, false)]
818
891
  }, column.id);
819
892
  }) })
820
893
  }),
@@ -827,9 +900,10 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
827
900
  const { row, depth, index } = shown;
828
901
  const key = getRowId(row);
829
902
  const isGroup = isGroupRow?.(row) ?? false;
830
- const shownColumns = isGroup ? columns.slice(0, 1) : columns;
903
+ const cells = cellsOf(row, isGroup);
831
904
  const labelId = `${idBase}-row-${String(position)}`;
832
- return /* @__PURE__ */ jsx("tr", {
905
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("tr", {
906
+ ...rowAttributes(getRowProps?.(row)),
833
907
  "data-slot": "table-row",
834
908
  "data-flip": String(key),
835
909
  "data-highlighted": isRowHighlighted?.(row) || void 0,
@@ -837,12 +911,13 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
837
911
  "data-open": shown.isExpanded || void 0,
838
912
  "data-group": isGroup || void 0,
839
913
  className: rowClass(row, isGroup),
840
- children: shownColumns.map((column) => {
914
+ children: cells.map(({ column, span }) => {
841
915
  const content = firstCellContent(column, cellContent(column, row, index), shown, labelId);
842
916
  const cellProps = {
843
917
  "data-slot": "table-cell",
844
918
  "data-sorted": sortedColumn === column.id || void 0,
845
- colSpan: isGroup ? columns.length : void 0,
919
+ "data-highlighted": column.highlighted || void 0,
920
+ colSpan: isGroup ? columns.length : span > 1 ? span : void 0,
846
921
  style: depthStyle(column, depth)
847
922
  };
848
923
  return column === columns[0] ? /* @__PURE__ */ jsx("th", {
@@ -856,7 +931,17 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
856
931
  children: content
857
932
  }, column.id);
858
933
  })
859
- }, String(key));
934
+ }), shown.detail === void 0 ? null : /* @__PURE__ */ jsx("tr", {
935
+ "data-slot": "table-detail-row",
936
+ "data-flip": `${String(key)}:detail`,
937
+ className: cnAll(tableDetailRowVariants()),
938
+ children: /* @__PURE__ */ jsx("td", {
939
+ "data-slot": "table-detail-cell",
940
+ colSpan: columns.length,
941
+ className: cnAll(tableDetailCellVariants()),
942
+ children: shown.detail
943
+ })
944
+ })] }, String(key));
860
945
  })
861
946
  }),
862
947
  totalRow ? /* @__PURE__ */ jsx("tfoot", {
@@ -880,6 +965,7 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
880
965
  onSelectionChange: selectable ? commitSelection : void 0,
881
966
  sortDescriptor: activeSort,
882
967
  onSortChange: changeSort,
968
+ disabledKeys: detailRowKeys.length > 0 ? detailRowKeys : void 0,
883
969
  onRowAction: rowAction ? (key) => {
884
970
  const row = rowsByKey.get(key);
885
971
  if (row !== void 0 && !isGroupRow?.(row)) rowAction(row);
@@ -905,15 +991,16 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
905
991
  })
906
992
  })
907
993
  }) : null,
908
- columns.map((column) => /* @__PURE__ */ jsx(Column, {
994
+ columns.map((column) => /* @__PURE__ */ jsxs(Column, {
909
995
  id: column.id,
910
996
  isRowHeader: column === columns[0],
911
997
  allowsSorting: isSortable(column),
912
998
  "data-slot": "table-column",
913
999
  "data-sorted": sortedColumn === column.id || void 0,
1000
+ "data-highlighted": column.highlighted || void 0,
914
1001
  className: columnClass(column),
915
1002
  style: columnStyle(column),
916
- children: headerLabel(column)
1003
+ children: [headerLabel(column), headerAddon(column, true)]
917
1004
  }, column.id)),
918
1005
  rowAction ? /* @__PURE__ */ jsx(Column, {
919
1006
  id: CHEVRON_COLUMN_ID,
@@ -934,9 +1021,10 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
934
1021
  const { row, depth, index } = shown;
935
1022
  const key = getRowId(row);
936
1023
  const isGroup = isGroupRow?.(row) ?? false;
937
- const shownColumns = isGroup ? columns.slice(0, 1) : columns;
1024
+ const cells = cellsOf(row, isGroup);
938
1025
  const labelId = `${idBase}-row-${String(position)}`;
939
- return /* @__PURE__ */ jsxs(Row, {
1026
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Row, {
1027
+ ...rowAttributes(getRowProps?.(row)),
940
1028
  id: key,
941
1029
  "data-slot": "table-row",
942
1030
  "data-flip": String(key),
@@ -954,10 +1042,11 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
954
1042
  "aria-label": selectionLabels?.selectRow
955
1043
  })
956
1044
  }) : null,
957
- shownColumns.map((column) => /* @__PURE__ */ jsx(Cell, {
1045
+ cells.map(({ column, span }) => /* @__PURE__ */ jsx(Cell, {
958
1046
  "data-slot": "table-cell",
959
1047
  "data-sorted": sortedColumn === column.id || void 0,
960
- colSpan: isGroup ? columns.length + (rowAction ? 1 : 0) : void 0,
1048
+ "data-highlighted": column.highlighted || void 0,
1049
+ colSpan: isGroup ? columns.length + (rowAction ? 1 : 0) : span > 1 ? span : void 0,
961
1050
  className: cnAll(cellClass(column, "body"), indentClass(column)),
962
1051
  style: depthStyle(column, depth),
963
1052
  children: firstCellContent(column, cellContent(column, row, index), shown, labelId)
@@ -968,7 +1057,18 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
968
1057
  children: /* @__PURE__ */ jsx(RowChevronGlyph, {})
969
1058
  }) : null
970
1059
  ]
971
- }, String(key));
1060
+ }), shown.detail === void 0 ? null : /* @__PURE__ */ jsx(Row, {
1061
+ id: `${DETAIL_ROW_PREFIX}${String(key)}`,
1062
+ "data-slot": "table-detail-row",
1063
+ "data-flip": `${String(key)}:detail`,
1064
+ className: cnAll(tableDetailRowVariants()),
1065
+ children: /* @__PURE__ */ jsx(Cell, {
1066
+ "data-slot": "table-detail-cell",
1067
+ colSpan: columns.length + (selectable ? 1 : 0) + (rowAction ? 1 : 0),
1068
+ className: cnAll(tableDetailCellVariants()),
1069
+ children: shown.detail
1070
+ })
1071
+ })] }, String(key));
972
1072
  })
973
1073
  }),
974
1074
  totalRow ? /* @__PURE__ */ jsx(TableFooter, {
@@ -1065,6 +1165,6 @@ const Table$1 = forwardRef(function Table$2({ data, columns, getRowId, variant,
1065
1165
  });
1066
1166
  });
1067
1167
  //#endregion
1068
- export { Table$1 as Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
1168
+ export { Table$1 as Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableDetailCellVariants, tableDetailRowVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableStickyCellVariants, tableVariants };
1069
1169
 
1070
1170
  //# sourceMappingURL=table.js.map