@neasg/design-system 0.4.22 → 0.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/table.d.ts CHANGED
@@ -30,6 +30,14 @@ declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<
30
30
  treatWidthAsMinWidth?: boolean;
31
31
  containOverflow?: boolean;
32
32
  } & React.RefAttributes<HTMLTableCellElement>>;
33
+ declare const TableRowHeader: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & {
34
+ width?: string;
35
+ minWidth?: string;
36
+ maxWidth?: string;
37
+ wrap?: boolean;
38
+ treatWidthAsMinWidth?: boolean;
39
+ containOverflow?: boolean;
40
+ } & React.RefAttributes<HTMLTableCellElement>>;
33
41
  declare const TableCaption: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>;
34
42
  type TableAlign = "left" | "center" | "right";
35
43
  export type TableRowTone = "default" | "muted" | "warning";
@@ -85,13 +93,15 @@ export interface TableColumn<Row> {
85
93
  skeleton?: TableSkeletonConfig;
86
94
  headerClassName?: string;
87
95
  cellClassName?: string;
96
+ /** Renders this column's body cells as semantic row headers. */
97
+ rowHeader?: boolean;
88
98
  /** Pins the column to the left or right edge while the table scrolls horizontally. */
89
99
  sticky?: "left" | "right";
90
100
  /** Enables a resize handle for this column. Use `resizableColumns` on Table to opt every column in by default. */
91
101
  resizable?: boolean;
92
102
  /** Minimum pixel width while resizing. Defaults to `minWidth`, then 64. */
93
103
  resizeMinWidth?: number;
94
- /** Maximum pixel width while resizing. Omit to allow the column to grow. */
104
+ /** Maximum pixel width while resizing. Defaults to 1200. */
95
105
  resizeMaxWidth?: number;
96
106
  }
97
107
  export interface TableSortingProps {
@@ -137,6 +147,8 @@ export interface TableColumnResizeHandleRenderProps<Row> {
137
147
  handle: React.ReactElement;
138
148
  }
139
149
  export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
150
+ /** Accessible name used as a visually hidden caption when `caption` is omitted. */
151
+ accessibleLabel: string;
140
152
  columns: TableColumn<Row>[];
141
153
  rows: Row[];
142
154
  getRowKey: (row: Row, index: number) => string;
@@ -155,6 +167,8 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
155
167
  sorting?: TableSortingProps;
156
168
  pagination?: Omit<PaginationProps, "className">;
157
169
  loading?: boolean;
170
+ /** Status announced while loading. */
171
+ loadingLabel?: string;
158
172
  loadingRows?: number;
159
173
  /** Optional controlled ordered list of visible column keys. Omit to render every column in config order. */
160
174
  visibleColumnKeys?: readonly string[];
@@ -180,8 +194,6 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
180
194
  striped?: boolean;
181
195
  /** Adds a disclosure column and full-width expandable content for nested tables or row details. */
182
196
  rowExpansion?: TableRowExpansionProps<Row>;
183
- /** When set, rows become interactive: cursor-pointer, hover highlight, and click handling. */
184
- onRowClick?: (row: Row, index: number) => void;
185
197
  }
186
- declare function Table<Row>({ columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowExpansion, onRowClick, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
187
- export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, SortableTableHead, TableRowSkeleton, };
198
+ declare function Table<Row>({ accessibleLabel, columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingLabel, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowExpansion, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
199
+ export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, SortableTableHead, TableRowSkeleton, };
package/dist/table.js CHANGED
@@ -14,6 +14,7 @@ const TableContainer = React.forwardRef(({ className, ...props }, ref) => (_jsx(
14
14
  TableContainer.displayName = "TableContainer";
15
15
  const DEFAULT_COLUMN_RESIZE_MIN_WIDTH = 64;
16
16
  const DEFAULT_COLUMN_RESIZE_START_WIDTH = 160;
17
+ const DEFAULT_COLUMN_RESIZE_MAX_WIDTH = 1200;
17
18
  const COLUMN_RESIZE_KEYBOARD_STEP = 16;
18
19
  const TABLE_EXPANSION_COLUMN_WIDTH = 48;
19
20
  const TABLE_MIN_WIDTH_CSS_VAR = "--table-min-width";
@@ -62,7 +63,7 @@ function getColumnResizeMinWidth(column) {
62
63
  }
63
64
  function getColumnResizeMaxWidth(column) {
64
65
  var _a;
65
- return (_a = parsePixelSize(column.resizeMaxWidth)) !== null && _a !== void 0 ? _a : Number.POSITIVE_INFINITY;
66
+ return (_a = parsePixelSize(column.resizeMaxWidth)) !== null && _a !== void 0 ? _a : DEFAULT_COLUMN_RESIZE_MAX_WIDTH;
66
67
  }
67
68
  function getColumnResizeMaxWidthStyle(column) {
68
69
  const maxWidth = getColumnResizeMaxWidth(column);
@@ -138,6 +139,15 @@ function getColumnResizeLabel(column) {
138
139
  }
139
140
  return column.key;
140
141
  }
142
+ function getColumnHeaderAriaLabel(column) {
143
+ if (column.header === null ||
144
+ column.header === undefined ||
145
+ column.header === false ||
146
+ column.header === "") {
147
+ return getColumnResizeLabel(column);
148
+ }
149
+ return undefined;
150
+ }
141
151
  const TableHeader = React.forwardRef(({ className, ...props }, ref) => (_jsx("thead", { ref: ref, className: cn("sticky top-0 z-10 bg-[hsl(var(--table-header-background))] [&_tr]:border-b [&_tr]:border-[hsl(var(--table-border))] [&>tr]:bg-inherit", className), ...props })));
142
152
  TableHeader.displayName = "TableHeader";
143
153
  const TableBody = React.forwardRef(({ className, ...props }, ref) => (_jsx("tbody", { ref: ref, className: cn("[&_tr:last-child]:border-0", className), ...props })));
@@ -146,7 +156,7 @@ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("tf
146
156
  TableFooter.displayName = "TableFooter";
147
157
  const TableRow = React.forwardRef(({ className, ...props }, ref) => (_jsx("tr", { ref: ref, className: cn("border-b border-[hsl(var(--table-border))] bg-card text-card-foreground transition-colors data-[state=selected]:bg-muted", className), ...props })));
148
158
  TableRow.displayName = "TableRow";
149
- const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
159
+ const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-2 text-left align-middle font-medium text-instructional [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
150
160
  style: {
151
161
  ...style,
152
162
  fontWeight: 500,
@@ -165,6 +175,14 @@ const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidt
165
175
  treatWidthAsMinWidth,
166
176
  }), ...props })));
167
177
  TableCell.displayName = "TableCell";
178
+ const TableRowHeader = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, scope = "row", ...props }, ref) => (_jsx("th", { ref: ref, scope: scope, className: cn("h-12 px-4 py-2 text-left align-middle font-medium text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
179
+ style,
180
+ width,
181
+ minWidth,
182
+ maxWidth,
183
+ treatWidthAsMinWidth,
184
+ }), ...props })));
185
+ TableRowHeader.displayName = "TableRowHeader";
168
186
  const TableCaption = React.forwardRef(({ className, ...props }, ref) => (_jsx("caption", { ref: ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props })));
169
187
  TableCaption.displayName = "TableCaption";
170
188
  const STICKY_SCROLL_EDGE_THRESHOLD = 1;
@@ -246,13 +264,20 @@ export const TABLE_SKELETON_PRESETS = {
246
264
  };
247
265
  function SortableTableHead({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap = false, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, }) {
248
266
  const isSorted = currentSortField === field;
249
- return (_jsxs(TableHead, { "data-slot": "table-column-head", className: cn(resizeHandle && "relative", alignClassName(align), className), wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, children: [_jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
267
+ const resolvedSortLabel = sortLabel !== null && sortLabel !== void 0 ? sortLabel : (typeof children === "string" || typeof children === "number"
268
+ ? String(children)
269
+ : field);
270
+ return (_jsxs(TableHead, { "data-slot": "table-column-head", scope: "col", "aria-sort": isSorted
271
+ ? currentSortDirection === "asc"
272
+ ? "ascending"
273
+ : "descending"
274
+ : undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, children: [_jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
250
275
  ? "max-w-full whitespace-normal text-left"
251
- : "whitespace-nowrap", align === "right" && "ml-auto justify-end", align === "center" && "mx-auto justify-center"), style: { font: "inherit", color: "inherit", fontWeight: 500 }, "aria-label": `Sort by ${sortLabel !== null && sortLabel !== void 0 ? sortLabel : field}`, children: [_jsx("span", { className: cn("min-w-0", containOverflow && !allowWrap && "truncate", containOverflow && allowWrap && "break-words [overflow-wrap:anywhere]"), children: children }), _jsx("span", { className: "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center", children: isSorted ? (currentSortDirection === "asc" ? (_jsx(ArrowUpIcon, { className: "shrink-0", size: 14 })) : (_jsx(ArrowDownIcon, { className: "shrink-0", size: 14 }))) : (_jsx(ArrowUpDown, { className: "h-3.5 w-3.5 shrink-0 opacity-50" })) })] }), resizeHandle] }));
276
+ : "whitespace-nowrap", align === "right" && "ml-auto justify-end", align === "center" && "mx-auto justify-center"), style: { font: "inherit", color: "inherit", fontWeight: 500 }, "aria-label": `Sort by ${resolvedSortLabel}`, children: [_jsx("span", { className: cn("min-w-0", containOverflow && !allowWrap && "truncate", containOverflow && allowWrap && "break-words [overflow-wrap:anywhere]"), children: children }), _jsx("span", { "aria-hidden": "true", className: "inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center", children: isSorted ? (currentSortDirection === "asc" ? (_jsx(ArrowUpIcon, { className: "shrink-0", size: 14 })) : (_jsx(ArrowDownIcon, { className: "shrink-0", size: 14 }))) : (_jsx(ArrowUpDown, { className: "h-3.5 w-3.5 shrink-0 opacity-50" })) })] }), resizeHandle] }));
252
277
  }
253
278
  const TableColumnResizeHandle = React.forwardRef(function TableColumnResizeHandle({ column, nextColumn, currentWidth, minWidth, maxWidth, onResizeStart, onResizeByKeyboard, className, onClick, ...props }, ref) {
254
279
  const label = getColumnResizeLabel(column);
255
- return (_jsx("button", { ...props, ref: ref, type: "button", "aria-label": `Resize ${label} column`, title: `Resize ${label} column`, "aria-valuenow": currentWidth, "aria-valuemin": minWidth, "aria-valuemax": maxWidth, onPointerDown: (event) => onResizeStart(column, nextColumn, event), onClick: (event) => {
280
+ return (_jsx("div", { ...props, ref: ref, role: "separator", tabIndex: 0, "aria-orientation": "vertical", "aria-label": `Resize ${label} column`, title: `Resize ${label} column`, "aria-valuenow": currentWidth, "aria-valuemin": minWidth, "aria-valuemax": maxWidth, "aria-valuetext": currentWidth === undefined ? undefined : `${currentWidth} pixels`, onPointerDown: (event) => onResizeStart(column, nextColumn, event), onClick: (event) => {
256
281
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
257
282
  if (event.defaultPrevented) {
258
283
  return;
@@ -268,11 +293,11 @@ const TableColumnResizeHandle = React.forwardRef(function TableColumnResizeHandl
268
293
  onResizeByKeyboard(column, nextColumn, event.key === "ArrowLeft"
269
294
  ? -COLUMN_RESIZE_KEYBOARD_STEP
270
295
  : COLUMN_RESIZE_KEYBOARD_STEP);
271
- }, className: cn("group absolute right-0 top-0 z-[1] flex h-full w-4 cursor-col-resize touch-none items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className), children: _jsx("span", { "aria-hidden": "true", className: "h-6 w-px rounded-full bg-[hsl(var(--table-border))] transition-colors group-hover:bg-primary group-focus-visible:bg-primary" }) }));
296
+ }, className: cn("group absolute right-0 top-0 z-[1] flex h-full w-4 cursor-col-resize touch-none items-center justify-center rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring", className), children: _jsx("span", { "aria-hidden": "true", className: "h-6 w-px rounded-full bg-[hsl(var(--table-border))] transition-colors group-hover:bg-primary group-focus-visible:bg-primary" }) }));
272
297
  });
273
298
  const TableColumnGrowResizeHandle = React.forwardRef(function TableColumnGrowResizeHandle({ column, currentWidth, minWidth, maxWidth, onResizeStart, onResizeByKeyboard, className, onClick, ...props }, ref) {
274
299
  const label = getColumnResizeLabel(column);
275
- return (_jsx("button", { ...props, ref: ref, type: "button", "aria-label": `Resize ${label} column`, title: `Resize ${label} column`, "aria-valuenow": currentWidth, "aria-valuemin": minWidth, "aria-valuemax": maxWidth, onPointerDown: (event) => onResizeStart(column, event), onClick: (event) => {
300
+ return (_jsx("div", { ...props, ref: ref, role: "separator", tabIndex: 0, "aria-orientation": "vertical", "aria-label": `Resize ${label} column`, title: `Resize ${label} column`, "aria-valuenow": currentWidth, "aria-valuemin": minWidth, "aria-valuemax": maxWidth, "aria-valuetext": currentWidth === undefined ? undefined : `${currentWidth} pixels`, onPointerDown: (event) => onResizeStart(column, event), onClick: (event) => {
276
301
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
277
302
  if (event.defaultPrevented) {
278
303
  return;
@@ -288,7 +313,7 @@ const TableColumnGrowResizeHandle = React.forwardRef(function TableColumnGrowRes
288
313
  onResizeByKeyboard(column, event.key === "ArrowLeft"
289
314
  ? -COLUMN_RESIZE_KEYBOARD_STEP
290
315
  : COLUMN_RESIZE_KEYBOARD_STEP);
291
- }, className: cn("group absolute right-0 top-0 z-[1] flex h-full w-4 cursor-col-resize touch-none items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className), children: _jsx("span", { "aria-hidden": "true", className: "h-6 w-px rounded-full bg-[hsl(var(--table-border))] transition-colors group-hover:bg-primary group-focus-visible:bg-primary" }) }));
316
+ }, className: cn("group absolute right-0 top-0 z-[1] flex h-full w-4 cursor-col-resize touch-none items-center justify-center rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring", className), children: _jsx("span", { "aria-hidden": "true", className: "h-6 w-px rounded-full bg-[hsl(var(--table-border))] transition-colors group-hover:bg-primary group-focus-visible:bg-primary" }) }));
292
317
  });
293
318
  function getDefaultSkeleton(column) {
294
319
  var _a, _b;
@@ -329,7 +354,18 @@ function getVisibleColumns(columns, visibleColumnKeys) {
329
354
  function isStickyResizeBoundary(column, nextColumn) {
330
355
  return Boolean(column.sticky === "right" || nextColumn.sticky);
331
356
  }
332
- function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowExpansion, onRowClick, onScroll, style, ...props }) {
357
+ function getColumnPairResizeRange(column, nextColumn, columnWidths) {
358
+ const currentWidth = getResolvedResizableColumnWidth(column, columnWidths);
359
+ const nextWidth = getResolvedResizableColumnWidth(nextColumn, columnWidths);
360
+ const minDelta = Math.max(getColumnResizeMinWidth(column) - currentWidth, nextWidth - getColumnResizeMaxWidth(nextColumn));
361
+ const maxDelta = Math.min(getColumnResizeMaxWidth(column) - currentWidth, nextWidth - getColumnResizeMinWidth(nextColumn));
362
+ return {
363
+ currentWidth,
364
+ minWidth: Math.round(currentWidth + minDelta),
365
+ maxWidth: Math.round(currentWidth + maxDelta),
366
+ };
367
+ }
368
+ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingLabel = "Loading table data", loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowExpansion, onScroll, style, ...props }) {
333
369
  const visibleColumns = getVisibleColumns(columns, visibleColumnKeys);
334
370
  const hasExpansionColumn = Boolean(rowExpansion);
335
371
  const hasColumnFilters = visibleColumns.some((column) => column.filter);
@@ -353,6 +389,7 @@ function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { mess
353
389
  const [stickyScrollState, setStickyScrollState] = React.useState({
354
390
  left: false,
355
391
  right: false,
392
+ scrollable: false,
356
393
  });
357
394
  const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = React.useState(() => { var _a; return new Set((_a = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.defaultExpandedRowKeys) !== null && _a !== void 0 ? _a : []); });
358
395
  const controlledExpandedRowKeys = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.expandedRowKeys;
@@ -364,12 +401,16 @@ function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { mess
364
401
  }
365
402
  const maxScrollLeft = Math.max(0, element.scrollWidth - element.clientWidth);
366
403
  const scrollLeft = Math.max(0, element.scrollLeft);
404
+ const maxScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
367
405
  const nextScrollState = {
368
406
  left: scrollLeft > STICKY_SCROLL_EDGE_THRESHOLD,
369
407
  right: scrollLeft < maxScrollLeft - STICKY_SCROLL_EDGE_THRESHOLD,
408
+ scrollable: maxScrollLeft > STICKY_SCROLL_EDGE_THRESHOLD ||
409
+ maxScrollTop > STICKY_SCROLL_EDGE_THRESHOLD,
370
410
  };
371
411
  setStickyScrollState((currentScrollState) => currentScrollState.left === nextScrollState.left &&
372
- currentScrollState.right === nextScrollState.right
412
+ currentScrollState.right === nextScrollState.right &&
413
+ currentScrollState.scrollable === nextScrollState.scrollable
373
414
  ? currentScrollState
374
415
  : nextScrollState);
375
416
  }, []);
@@ -499,13 +540,17 @@ function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { mess
499
540
  if (stickyResizeBoundary) {
500
541
  return null;
501
542
  }
543
+ const pairRange = getColumnPairResizeRange(column, nextColumn, resolvedColumnWidths);
502
544
  const currentWidth = isGrowResizeMode
503
545
  ? getColumnResizeBaseWidth(column, resolvedColumnWidths)
504
- : getResolvedResizableColumnWidth(column, resolvedColumnWidths);
505
- const maxWidth = Number.isFinite(getColumnResizeMaxWidth(column))
546
+ : pairRange.currentWidth;
547
+ const minWidth = isGrowResizeMode
548
+ ? getColumnResizeMinWidth(column)
549
+ : pairRange.minWidth;
550
+ const maxWidth = isGrowResizeMode
506
551
  ? getColumnResizeMaxWidth(column)
507
- : undefined;
508
- const handle = isGrowResizeMode ? (_jsx(TableColumnGrowResizeHandle, { column: column, currentWidth: currentWidth, minWidth: getColumnResizeMinWidth(column), maxWidth: maxWidth, onResizeStart: startGrowColumnResize, onResizeByKeyboard: resizeGrowColumnByKeyboard })) : (_jsx(TableColumnResizeHandle, { column: column, nextColumn: nextColumn, currentWidth: currentWidth, minWidth: getColumnResizeMinWidth(column), maxWidth: maxWidth, onResizeStart: startColumnResize, onResizeByKeyboard: resizeColumnByKeyboard }));
552
+ : pairRange.maxWidth;
553
+ const handle = isGrowResizeMode ? (_jsx(TableColumnGrowResizeHandle, { column: column, currentWidth: currentWidth, minWidth: minWidth, maxWidth: maxWidth, onResizeStart: startGrowColumnResize, onResizeByKeyboard: resizeGrowColumnByKeyboard })) : (_jsx(TableColumnResizeHandle, { column: column, nextColumn: nextColumn, currentWidth: currentWidth, minWidth: minWidth, maxWidth: maxWidth, onResizeStart: startColumnResize, onResizeByKeyboard: resizeColumnByKeyboard }));
509
554
  if (renderColumnResizeHandle) {
510
555
  return renderColumnResizeHandle({ column, nextColumn, handle });
511
556
  }
@@ -540,89 +585,94 @@ function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { mess
540
585
  (_a = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.onExpandedRowKeysChange) === null || _a === void 0 ? void 0 : _a.call(rowExpansion, Array.from(nextExpandedRowKeys));
541
586
  }, [controlledExpandedRowKeys, rowExpansion, uncontrolledExpandedRowKeys]);
542
587
  const resolvedEmptyState = centerEmptyState ? (_jsx("div", { "data-slot": "table-empty-state", className: "flex w-full min-w-0 items-center justify-center whitespace-normal text-center [&>*]:mx-auto", style: { minHeight: emptyStateMinHeight }, children: emptyState })) : (emptyState);
543
- const container = (_jsx(TableContainer, { ref: tableContainerRef, onScroll: handleTableContainerScroll, className: cn("w-full", loading && "pointer-events-none select-none", className, containerClassName), style: {
588
+ const container = (_jsxs(TableContainer, { ref: tableContainerRef, role: stickyScrollState.scrollable ? "region" : undefined, "aria-label": stickyScrollState.scrollable
589
+ ? `${accessibleLabel} scroll area`
590
+ : undefined, tabIndex: stickyScrollState.scrollable ? 0 : undefined, onScroll: handleTableContainerScroll, className: cn("w-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", loading && "pointer-events-none select-none", className, containerClassName), style: {
544
591
  ...style,
545
592
  ...(growTableMinWidth !== undefined
546
593
  ? { [TABLE_MIN_WIDTH_CSS_VAR]: `${growTableMinWidth}px` }
547
594
  : {}),
548
595
  ...(maxHeight !== undefined ? { maxHeight } : {}),
549
596
  ...(resolvedMinHeight !== undefined ? { minHeight: resolvedMinHeight } : {}),
550
- }, ...props, children: _jsxs(TableRoot, { className: cn(shouldUseFixedLayout && "table-fixed", isGrowResizeMode &&
551
- (hasResolvedColumnWidths
552
- ? "w-[var(--table-min-width)]"
553
- : "min-w-[var(--table-min-width)]"), tableClassName), children: [caption ? _jsx(TableCaption, { children: caption }) : null, _jsxs("colgroup", { children: [hasExpansionColumn ? (_jsx("col", { style: {
554
- width: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
555
- minWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
556
- maxWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
557
- } })) : null, visibleColumns.map((column) => (_jsx("col", { style: getTableColumnSizingStyle({
558
- width: getRenderedColumnWidth({
559
- column,
560
- columnWidths: resolvedColumnWidths,
561
- resizing: isColumnResizingEnabled,
562
- }),
563
- minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
564
- maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
565
- treatWidthAsMinWidth: !isColumnResizingEnabled,
566
- }) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", className: "w-12 px-2" })) : null, visibleColumns.map((column, columnIndex) => {
567
- var _a;
568
- const sortField = (_a = column.sortKey) !== null && _a !== void 0 ? _a : column.key;
569
- const isSortable = column.sortable && sorting;
570
- const columnWidth = getRenderedColumnWidth({
597
+ }, ...props, children: [_jsxs(TableRoot, { "aria-busy": loading, className: cn(shouldUseFixedLayout && "table-fixed", isGrowResizeMode &&
598
+ (hasResolvedColumnWidths
599
+ ? "w-[var(--table-min-width)]"
600
+ : "min-w-[var(--table-min-width)]"), tableClassName), children: [_jsx(TableCaption, { className: caption ? undefined : "sr-only !m-0", children: caption !== null && caption !== void 0 ? caption : accessibleLabel }), _jsxs("colgroup", { children: [hasExpansionColumn ? (_jsx("col", { style: {
601
+ width: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
602
+ minWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
603
+ maxWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
604
+ } })) : null, visibleColumns.map((column) => (_jsx("col", { style: getTableColumnSizingStyle({
605
+ width: getRenderedColumnWidth({
571
606
  column,
572
607
  columnWidths: resolvedColumnWidths,
573
608
  resizing: isColumnResizingEnabled,
574
- });
575
- const resizeHandle = renderResizeHandle(column, columnIndex);
576
- return (isSortable ? (_jsx(SortableTableHead, { field: sortField, currentSortField: sorting.field, currentSortDirection: sorting.direction, onSort: sorting.onSort, className: cn(stickyClassName(column.sticky, "head", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.headerClassName), allowWrap: column.wrap, width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), align: column.align, sortLabel: column.sortLabel, resizeHandle: resizeHandle, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, children: column.header }, column.key)) : (_jsxs(TableHead, { "data-slot": "table-column-head", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(resizeHandle && "relative", alignClassName(column.align), stickyClassName(column.sticky, "head", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.headerClassName), children: [column.header, resizeHandle] }, column.key)));
577
- })] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "w-12 px-2" })) : null, visibleColumns.map((column) => {
578
- const columnWidth = getRenderedColumnWidth({
579
- column,
580
- columnWidths: resolvedColumnWidths,
581
- resizing: isColumnResizingEnabled,
582
- });
583
- return (_jsx(TableHead, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-1 font-normal", stickyClassName(column.sticky, "filter", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.filterClassName), children: column.filter ? (_jsx("div", { "data-slot": "table-filter-control", className: "absolute inset-x-2 inset-y-1 min-w-0", children: _jsx(TableColumnFilterControl, { filter: column.filter, label: getColumnResizeLabel(column) }) })) : null }, column.key));
584
- })] })) : null] }), _jsx(TableBody, { children: loading ? (_jsx(TableRowSkeleton, { rows: loadingRows, columns: [
585
- ...(hasExpansionColumn
586
- ? [{ width: "1rem", height: "1rem" }]
587
- : []),
588
- ...visibleColumns.map((column) => {
589
- var _a;
590
- return (_a = column.skeleton) !== null && _a !== void 0 ? _a : getDefaultSkeleton(column);
591
- }),
592
- ] })) : rows.length ? (rows.map((row, rowIndex) => {
593
- var _a, _b, _c, _d;
594
- const rowKey = getRowKey(row, rowIndex);
595
- const resolvedTone = typeof rowTone === "function"
596
- ? rowTone(row, rowIndex)
597
- : rowTone;
598
- const isRowExpandable = (_b = (_a = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.isRowExpandable) === null || _a === void 0 ? void 0 : _a.call(rowExpansion, row, rowIndex)) !== null && _b !== void 0 ? _b : hasExpansionColumn;
599
- const isExpanded = isRowExpandable && resolvedExpandedRowKeys.has(rowKey);
600
- const expandedContentId = `${expansionIdPrefix}-expanded-row-${rowIndex}`;
601
- return (_jsxs(React.Fragment, { children: [_jsxs(TableRow, { "data-expanded": isExpanded ? "true" : undefined, onClick: onRowClick ? () => onRowClick(row, rowIndex) : undefined, className: cn(onRowClick && "cursor-pointer hover:bg-muted", striped &&
602
- rowIndex % 2 === 1 &&
603
- !resolvedTone &&
604
- "bg-[hsl(var(--table-row-striped-background))]", tableRowToneClassName(resolvedTone), typeof rowClassName === "function"
605
- ? rowClassName(row, rowIndex)
606
- : rowClassName), children: [hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": expandedContentId, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
607
- event.stopPropagation();
608
- toggleExpandedRow(rowKey);
609
- }, className: "inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(ChevronRight, { "aria-hidden": "true", className: cn("h-4 w-4 transition-transform duration-150", isExpanded && "rotate-90") }) })) : null })) : null, visibleColumns.map((column) => {
610
- var _a, _b;
611
- const columnWidth = getRenderedColumnWidth({
612
- column,
613
- columnWidths: resolvedColumnWidths,
614
- resizing: isColumnResizingEnabled,
615
- });
616
- const value = (_b = (_a = column.cell) === null || _a === void 0 ? void 0 : _a.call(column, row, rowIndex)) !== null && _b !== void 0 ? _b : (column.accessorKey !== undefined
617
- ? row[column.accessorKey]
618
- : null);
619
- return (_jsx(TableCell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
620
- })] }), isExpanded ? (_jsx(TableRow, { id: expandedContentId, "data-slot": "table-expanded-row", className: "bg-[hsl(var(--table-row-striped-background))] hover:bg-[hsl(var(--table-row-striped-background))]", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
621
- (hasExpansionColumn ? 1 : 0), 1), className: "h-auto whitespace-normal p-4", children: rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.renderExpandedContent(row, rowIndex) }) })) : null] }, rowKey));
622
- })) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length + (hasExpansionColumn ? 1 : 0), 1), className: "p-6", children: resolvedEmptyState }) })) })] }) }));
609
+ }),
610
+ minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
611
+ maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
612
+ treatWidthAsMinWidth: !isColumnResizingEnabled,
613
+ }) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", scope: "col", className: "w-12 px-2" })) : null, visibleColumns.map((column, columnIndex) => {
614
+ var _a;
615
+ const sortField = (_a = column.sortKey) !== null && _a !== void 0 ? _a : column.key;
616
+ const isSortable = column.sortable && sorting;
617
+ const columnWidth = getRenderedColumnWidth({
618
+ column,
619
+ columnWidths: resolvedColumnWidths,
620
+ resizing: isColumnResizingEnabled,
621
+ });
622
+ const resizeHandle = renderResizeHandle(column, columnIndex);
623
+ return (isSortable ? (_jsx(SortableTableHead, { field: sortField, currentSortField: sorting.field, currentSortDirection: sorting.direction, onSort: sorting.onSort, className: cn(stickyClassName(column.sticky, "head", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.headerClassName), allowWrap: column.wrap, width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), align: column.align, sortLabel: column.sortLabel, resizeHandle: resizeHandle, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, children: column.header }, column.key)) : (_jsxs(TableHead, { "data-slot": "table-column-head", "aria-label": getColumnHeaderAriaLabel(column), scope: "col", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(resizeHandle && "relative", alignClassName(column.align), stickyClassName(column.sticky, "head", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.headerClassName), children: [column.header, resizeHandle] }, column.key)));
624
+ })] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasExpansionColumn ? (_jsx(TableCell, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "w-12 px-2" })) : null, visibleColumns.map((column) => {
625
+ const columnWidth = getRenderedColumnWidth({
626
+ column,
627
+ columnWidths: resolvedColumnWidths,
628
+ resizing: isColumnResizingEnabled,
629
+ });
630
+ return (_jsx(TableCell, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-1 font-normal", stickyClassName(column.sticky, "filter", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.filterClassName), children: column.filter ? (_jsx("div", { "data-slot": "table-filter-control", className: "absolute inset-x-2 inset-y-1 min-w-0", children: _jsx(TableColumnFilterControl, { filter: column.filter, label: getColumnResizeLabel(column) }) })) : null }, column.key));
631
+ })] })) : null] }), _jsx(TableBody, { "aria-hidden": loading ? "true" : undefined, children: loading ? (_jsx(TableRowSkeleton, { rows: loadingRows, columns: [
632
+ ...(hasExpansionColumn
633
+ ? [{ width: "1rem", height: "1rem" }]
634
+ : []),
635
+ ...visibleColumns.map((column) => {
636
+ var _a;
637
+ return (_a = column.skeleton) !== null && _a !== void 0 ? _a : getDefaultSkeleton(column);
638
+ }),
639
+ ] })) : rows.length ? (rows.map((row, rowIndex) => {
640
+ var _a, _b, _c, _d;
641
+ const rowKey = getRowKey(row, rowIndex);
642
+ const resolvedTone = typeof rowTone === "function"
643
+ ? rowTone(row, rowIndex)
644
+ : rowTone;
645
+ const isRowExpandable = (_b = (_a = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.isRowExpandable) === null || _a === void 0 ? void 0 : _a.call(rowExpansion, row, rowIndex)) !== null && _b !== void 0 ? _b : hasExpansionColumn;
646
+ const isExpanded = isRowExpandable && resolvedExpandedRowKeys.has(rowKey);
647
+ const expandedContentId = `${expansionIdPrefix}-expanded-row-${rowIndex}`;
648
+ return (_jsxs(React.Fragment, { children: [_jsxs(TableRow, { "data-expanded": isExpanded ? "true" : undefined, className: cn(striped &&
649
+ rowIndex % 2 === 1 &&
650
+ !resolvedTone &&
651
+ "bg-[hsl(var(--table-row-striped-background))]", tableRowToneClassName(resolvedTone), typeof rowClassName === "function"
652
+ ? rowClassName(row, rowIndex)
653
+ : rowClassName), children: [hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": isExpanded ? expandedContentId : undefined, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
654
+ event.stopPropagation();
655
+ toggleExpandedRow(rowKey);
656
+ }, className: "inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(ChevronRight, { "aria-hidden": "true", className: cn("h-4 w-4 transition-transform duration-150", isExpanded && "rotate-90") }) })) : null })) : null, visibleColumns.map((column) => {
657
+ var _a, _b;
658
+ const columnWidth = getRenderedColumnWidth({
659
+ column,
660
+ columnWidths: resolvedColumnWidths,
661
+ resizing: isColumnResizingEnabled,
662
+ });
663
+ const value = (_b = (_a = column.cell) === null || _a === void 0 ? void 0 : _a.call(column, row, rowIndex)) !== null && _b !== void 0 ? _b : (column.accessorKey !== undefined
664
+ ? row[column.accessorKey]
665
+ : null);
666
+ const Cell = column.rowHeader
667
+ ? TableRowHeader
668
+ : TableCell;
669
+ return (_jsx(Cell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
670
+ })] }), isExpanded ? (_jsx(TableRow, { id: expandedContentId, "data-slot": "table-expanded-row", className: "bg-[hsl(var(--table-row-striped-background))] hover:bg-[hsl(var(--table-row-striped-background))]", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
671
+ (hasExpansionColumn ? 1 : 0), 1), className: "h-auto whitespace-normal p-4", children: rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.renderExpandedContent(row, rowIndex) }) })) : null] }, rowKey));
672
+ })) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length + (hasExpansionColumn ? 1 : 0), 1), className: "p-6", children: resolvedEmptyState }) })) })] }), _jsx("div", { role: "status", className: "sr-only", children: loading ? loadingLabel : null })] }));
623
673
  if (!pagination) {
624
674
  return (_jsxs("div", { className: "space-y-4", children: [toolbar, container] }));
625
675
  }
626
676
  return (_jsxs("div", { className: "space-y-4", children: [toolbar, container, _jsx(Pagination, { ...pagination })] }));
627
677
  }
628
- export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, SortableTableHead, TableRowSkeleton, };
678
+ export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, SortableTableHead, TableRowSkeleton, };
@@ -38,6 +38,21 @@ export const neaTailwindPreset = {
38
38
  DEFAULT: "hsl(var(--primary))",
39
39
  foreground: "hsl(var(--primary-foreground))",
40
40
  },
41
+ interactive: "hsl(var(--interactive-foreground))",
42
+ highlight: {
43
+ DEFAULT: "hsl(var(--highlight-background))",
44
+ foreground: "hsl(var(--highlight-foreground))",
45
+ },
46
+ "button-primary": {
47
+ DEFAULT: "hsl(var(--button-primary-background))",
48
+ foreground: "hsl(var(--button-primary-foreground))",
49
+ },
50
+ "button-primary-hover": "hsl(var(--button-primary-hover-background))",
51
+ "count-badge": {
52
+ DEFAULT: "hsl(var(--count-badge-background))",
53
+ foreground: "hsl(var(--count-badge-foreground))",
54
+ },
55
+ instructional: "hsl(var(--instructional-foreground))",
41
56
  secondary: {
42
57
  DEFAULT: "hsl(var(--secondary))",
43
58
  foreground: "hsl(var(--secondary-foreground))",
package/dist/theme.d.ts CHANGED
@@ -357,6 +357,15 @@ export declare const darkThemeTokenMapping: {
357
357
  readonly "--tooltip-foreground": "var(--nea-dark-neutral-50)";
358
358
  readonly "--primary": "148 30% 38%";
359
359
  readonly "--primary-foreground": "var(--nea-dark-neutral-50)";
360
+ readonly "--interactive-foreground": "143 44% 67%";
361
+ readonly "--highlight-background": "148 20% 18%";
362
+ readonly "--highlight-foreground": "143 44% 67%";
363
+ readonly "--button-primary-background": "148 30% 38%";
364
+ readonly "--button-primary-hover-background": "148 30% 39%";
365
+ readonly "--button-primary-foreground": "0 0% 100%";
366
+ readonly "--count-badge-background": "148 24% 24%";
367
+ readonly "--count-badge-foreground": "143 44% 67%";
368
+ readonly "--instructional-foreground": "var(--nea-dark-neutral-200)";
360
369
  readonly "--secondary": "var(--nea-dark-neutral-500)";
361
370
  readonly "--secondary-foreground": "var(--nea-dark-neutral-100)";
362
371
  readonly "--muted": "var(--nea-dark-neutral-500)";
@@ -448,6 +457,42 @@ export declare const semanticColorTokens: readonly [{
448
457
  readonly foregroundToken: "--primary-foreground";
449
458
  readonly darkValue: "148 30% 38%";
450
459
  readonly darkForegroundValue: "var(--nea-dark-neutral-50)";
460
+ }, {
461
+ readonly name: "Interactive Foreground";
462
+ readonly token: "--interactive-foreground";
463
+ readonly foregroundToken?: undefined;
464
+ readonly darkValue: "143 44% 67%";
465
+ readonly darkForegroundValue?: undefined;
466
+ }, {
467
+ readonly name: "Highlight";
468
+ readonly token: "--highlight-background";
469
+ readonly foregroundToken: "--highlight-foreground";
470
+ readonly darkValue: "148 20% 18%";
471
+ readonly darkForegroundValue: "143 44% 67%";
472
+ }, {
473
+ readonly name: "Primary Button";
474
+ readonly token: "--button-primary-background";
475
+ readonly foregroundToken: "--button-primary-foreground";
476
+ readonly darkValue: "148 30% 38%";
477
+ readonly darkForegroundValue: "0 0% 100%";
478
+ }, {
479
+ readonly name: "Primary Button Hover";
480
+ readonly token: "--button-primary-hover-background";
481
+ readonly foregroundToken?: undefined;
482
+ readonly darkValue: "148 30% 39%";
483
+ readonly darkForegroundValue?: undefined;
484
+ }, {
485
+ readonly name: "Count Badge";
486
+ readonly token: "--count-badge-background";
487
+ readonly foregroundToken: "--count-badge-foreground";
488
+ readonly darkValue: "148 24% 24%";
489
+ readonly darkForegroundValue: "143 44% 67%";
490
+ }, {
491
+ readonly name: "Instructional Foreground";
492
+ readonly token: "--instructional-foreground";
493
+ readonly foregroundToken?: undefined;
494
+ readonly darkValue: "var(--nea-dark-neutral-200)";
495
+ readonly darkForegroundValue?: undefined;
451
496
  }, {
452
497
  readonly name: "Secondary";
453
498
  readonly token: "--secondary";
package/dist/theme.js CHANGED
@@ -186,6 +186,15 @@ export const darkThemeTokenMapping = {
186
186
  "--tooltip-foreground": "var(--nea-dark-neutral-50)",
187
187
  "--primary": "148 30% 38%",
188
188
  "--primary-foreground": "var(--nea-dark-neutral-50)",
189
+ "--interactive-foreground": "143 44% 67%",
190
+ "--highlight-background": "148 20% 18%",
191
+ "--highlight-foreground": "143 44% 67%",
192
+ "--button-primary-background": "148 30% 38%",
193
+ "--button-primary-hover-background": "148 30% 39%",
194
+ "--button-primary-foreground": "0 0% 100%",
195
+ "--count-badge-background": "148 24% 24%",
196
+ "--count-badge-foreground": "143 44% 67%",
197
+ "--instructional-foreground": "var(--nea-dark-neutral-200)",
189
198
  "--secondary": "var(--nea-dark-neutral-500)",
190
199
  "--secondary-foreground": "var(--nea-dark-neutral-100)",
191
200
  "--muted": "var(--nea-dark-neutral-500)",
@@ -273,6 +282,33 @@ export const semanticColorTokens = [
273
282
  token: "--primary",
274
283
  foregroundToken: "--primary-foreground",
275
284
  }),
285
+ withDarkThemeMapping({
286
+ name: "Interactive Foreground",
287
+ token: "--interactive-foreground",
288
+ }),
289
+ withDarkThemeMapping({
290
+ name: "Highlight",
291
+ token: "--highlight-background",
292
+ foregroundToken: "--highlight-foreground",
293
+ }),
294
+ withDarkThemeMapping({
295
+ name: "Primary Button",
296
+ token: "--button-primary-background",
297
+ foregroundToken: "--button-primary-foreground",
298
+ }),
299
+ withDarkThemeMapping({
300
+ name: "Primary Button Hover",
301
+ token: "--button-primary-hover-background",
302
+ }),
303
+ withDarkThemeMapping({
304
+ name: "Count Badge",
305
+ token: "--count-badge-background",
306
+ foregroundToken: "--count-badge-foreground",
307
+ }),
308
+ withDarkThemeMapping({
309
+ name: "Instructional Foreground",
310
+ token: "--instructional-foreground",
311
+ }),
276
312
  withDarkThemeMapping({
277
313
  name: "Secondary",
278
314
  token: "--secondary",
package/dist/toaster.js CHANGED
@@ -32,11 +32,11 @@ function Toaster({ position = "top-right", visibleToasts = 3, closeButton = true
32
32
  style: toastLayoutStyle,
33
33
  classNames: {
34
34
  toast: "group relative !grid w-[var(--width)] !grid-cols-[auto_var(--space-2)_auto_minmax(0,1fr)] !items-start !gap-x-0 !gap-y-2 !rounded-overlay !border !border-border/80 !bg-popover !p-3 !pr-10 !text-popover-foreground !shadow-overlay-strong [&_[data-action]]:col-start-1 [&_[data-button]]:row-start-2 [&_[data-button]]:!ml-0 [&_[data-button]]:!mr-0 [&_[data-cancel]]:col-start-1 [&_[data-content]]:col-span-full [&_[data-content]]:col-start-1 [&_[data-content]]:row-start-1 [&_[data-icon]]:col-start-1 [&_[data-icon]]:row-start-1 [&:has([data-cancel])_[data-action]]:col-start-3 [&:has([data-icon])]:!grid-cols-[auto_var(--space-3)_auto_var(--space-2)_auto_minmax(0,1fr)] [&:has([data-icon])_[data-action]]:col-start-3 [&:has([data-icon])_[data-cancel]]:col-start-3 [&:has([data-icon])_[data-content]]:col-start-3 [&:has([data-icon]):has([data-cancel])_[data-action]]:col-start-5",
35
- content: "flex min-w-0 flex-col gap-1",
35
+ content: "flex min-w-0 flex-col gap-1 [&:not(:has([data-description]))]:min-h-8 [&:not(:has([data-description]))]:justify-center",
36
36
  title: cn(typographyVariants({ variant: "bodySm" }), "!font-medium !text-popover-foreground"),
37
37
  description: cn(typographyVariants({ variant: "bodySm" }), "!text-muted-foreground"),
38
38
  icon: "!mx-0 flex !h-8 !w-8 shrink-0 !items-center !justify-center self-start rounded-control !border !border-border !bg-muted !text-muted-foreground [&>svg]:!m-0 [&>svg]:!h-4 [&>svg]:!w-4",
39
- actionButton: cn(buttonVariants({ variant: "default", size: "compact" }), toastActionClassName, "!bg-primary !text-primary-foreground hover:!bg-primary/90"),
39
+ actionButton: cn(buttonVariants({ variant: "default", size: "compact" }), toastActionClassName, "!bg-button-primary !text-button-primary-foreground hover:!bg-button-primary-hover"),
40
40
  cancelButton: cn(buttonVariants({ variant: "outline", size: "compact" }), toastActionClassName, "!border-[hsl(var(--button-outline-border))] !bg-[hsl(var(--button-outline-background))] !text-foreground hover:!bg-[hsl(var(--button-outline-hover-background))]"),
41
41
  closeButton: "!absolute !left-auto !right-2.5 !top-2.5 !flex !h-6 !w-6 !translate-x-0 !translate-y-0 !items-center !justify-center !rounded-control !border-0 !bg-transparent !text-muted-foreground hover:!bg-accent hover:!text-foreground",
42
42
  success: "border-[hsl(var(--status-success-foreground))]/20 [&_[data-icon]]:!border-status-success-foreground/20 [&_[data-icon]]:!bg-status-success [&_[data-icon]]:!text-status-success-foreground",
package/dist/tooltip.js CHANGED
@@ -8,7 +8,15 @@ function TooltipProvider({ delayDuration = 100, ...props }) {
8
8
  }
9
9
  const TooltipRoot = TooltipPrimitive.Root;
10
10
  const TooltipTrigger = TooltipPrimitive.Trigger;
11
- const TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Content, { ref: ref, sideOffset: sideOffset, className: cn("z-50 overflow-hidden rounded-overlay bg-[hsl(var(--tooltip-background))] px-3 py-1.5 text-sm text-[hsl(var(--tooltip-foreground))] shadow-[var(--overlay-shadow)] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) })));
11
+ const TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
12
+ const [mounted, setMounted] = React.useState(false);
13
+ React.useEffect(() => {
14
+ setMounted(true);
15
+ }, []);
16
+ if (!mounted)
17
+ return null;
18
+ return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Content, { ref: ref, sideOffset: sideOffset, className: cn("z-50 overflow-hidden rounded-overlay bg-[hsl(var(--tooltip-background))] px-3 py-1.5 text-sm text-[hsl(var(--tooltip-foreground))] shadow-[var(--overlay-shadow)] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) }));
19
+ });
12
20
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
13
21
  function Tooltip({ content, children, delayDuration = 100, side = "top", sideOffset = 4, contentClassName, open, defaultOpen, onOpenChange, }) {
14
22
  return (_jsx(TooltipProvider, { delayDuration: delayDuration, children: _jsxs(TooltipRoot, { open: open, defaultOpen: defaultOpen, onOpenChange: onOpenChange, children: [_jsx(TooltipTrigger, { asChild: true, children: children }), _jsx(TooltipContent, { side: side, sideOffset: sideOffset, className: contentClassName, children: content })] }) }));