@neasg/design-system 0.4.11 → 0.4.12

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.
@@ -13,10 +13,11 @@ export interface TableColumnVisibilityMenuProps<Row> extends PopoverPlacementPro
13
13
  triggerClassName?: string;
14
14
  contentClassName?: string;
15
15
  className?: string;
16
+ title?: React.ReactNode;
16
17
  searchPlaceholder?: string;
17
18
  restoreDefaultsLabel?: string;
18
19
  emptyMessage?: React.ReactNode;
19
20
  minVisibleColumns?: number;
20
21
  }
21
- declare function TableColumnVisibilityMenu<Row>({ columns, visibleColumnKeys, onVisibleColumnKeysChange, defaultVisibleColumnKeys, trigger, triggerLabel, triggerClassName, contentClassName, className, searchPlaceholder, restoreDefaultsLabel, emptyMessage, minVisibleColumns, align, sideOffset, side, }: TableColumnVisibilityMenuProps<Row>): import("react/jsx-runtime").JSX.Element;
22
+ declare function TableColumnVisibilityMenu<Row>({ columns, visibleColumnKeys, onVisibleColumnKeysChange, defaultVisibleColumnKeys, trigger, triggerLabel, triggerClassName, contentClassName, className, title, searchPlaceholder, restoreDefaultsLabel, emptyMessage, minVisibleColumns, align, sideOffset, side, }: TableColumnVisibilityMenuProps<Row>): import("react/jsx-runtime").JSX.Element;
22
23
  export { TableColumnVisibilityMenu };
@@ -10,7 +10,7 @@ import { Checkbox } from "./checkbox";
10
10
  import { InputControl } from "./input-control";
11
11
  import { cn } from "./lib/utils";
12
12
  import { Popover } from "./popover";
13
- import { PopoverMenuFooter, PopoverMenuFooterAction, PopoverMenuFooterMeta, } from "./popover-menu";
13
+ import { PopoverMenuFooter, PopoverMenuFooterAction, PopoverMenuFooterMeta, PopoverMenuGroupLabel, } from "./popover-menu";
14
14
  import { SearchInputShell } from "./search-input-shell";
15
15
  function getColumnVisibilityLabel(column) {
16
16
  if (column.visibilityLabel) {
@@ -52,7 +52,7 @@ function SortableColumnOption({ columnKey, label, checked, disabled, onToggle, }
52
52
  ? "cursor-grab active:cursor-grabbing"
53
53
  : "cursor-not-allowed opacity-40"), ...(checked ? { ...attributes, ...listeners } : {}), children: _jsx(GripVertical, { className: "h-4 w-4", "aria-hidden": "true" }) }), _jsx(Checkbox, { id: checkboxId, checked: checked, disabled: disabled, onChange: onToggle, "aria-label": label }), _jsx("label", { htmlFor: checkboxId, className: cn("min-w-0 flex-1 cursor-pointer truncate", disabled && "cursor-not-allowed text-muted-foreground"), children: label })] }));
54
54
  }
55
- function TableColumnVisibilityMenu({ columns, visibleColumnKeys, onVisibleColumnKeysChange, defaultVisibleColumnKeys, trigger, triggerLabel = "Customize columns", triggerClassName, contentClassName, className, searchPlaceholder = "Search columns", restoreDefaultsLabel = "Restore defaults", emptyMessage = "No columns found", minVisibleColumns = 1, align = "end", sideOffset = 4, side, }) {
55
+ function TableColumnVisibilityMenu({ columns, visibleColumnKeys, onVisibleColumnKeysChange, defaultVisibleColumnKeys, trigger, triggerLabel = "Customize columns", triggerClassName, contentClassName, className, title = "Customize columns", searchPlaceholder = "Search columns", restoreDefaultsLabel = "Restore defaults", emptyMessage = "No columns found", minVisibleColumns = 1, align = "end", sideOffset = 4, side, }) {
56
56
  const [query, setQuery] = React.useState("");
57
57
  const sensors = useSensors(useSensor(PointerSensor, {
58
58
  activationConstraint: {
@@ -62,6 +62,7 @@ function TableColumnVisibilityMenu({ columns, visibleColumnKeys, onVisibleColumn
62
62
  coordinateGetter: sortableKeyboardCoordinates,
63
63
  }));
64
64
  const searchInputId = React.useId();
65
+ const titleId = React.useId();
65
66
  const requiredVisibleColumns = Math.max(0, minVisibleColumns);
66
67
  const selectableColumns = React.useMemo(() => columns.filter((column) => column.hideable !== false), [columns]);
67
68
  const defaultKeys = React.useMemo(() => orderColumnKeys(columns, defaultVisibleColumnKeys !== null && defaultVisibleColumnKeys !== void 0 ? defaultVisibleColumnKeys : columns
@@ -110,11 +111,11 @@ function TableColumnVisibilityMenu({ columns, visibleColumnKeys, onVisibleColumn
110
111
  commitVisibleColumnKeys(arrayMove(currentKeys, oldIndex, newIndex));
111
112
  }, [commitVisibleColumnKeys, currentKeys]);
112
113
  const defaultTrigger = (_jsx(Button, { type: "button", variant: "outline", size: "icon", "aria-label": triggerLabel, className: triggerClassName, children: _jsx(Columns3, { "aria-hidden": "true" }) }));
113
- return (_jsx(Popover, { trigger: trigger !== null && trigger !== void 0 ? trigger : defaultTrigger, align: align, side: side, sideOffset: sideOffset, contentClassName: cn("w-80 p-0", contentClassName), children: _jsxs("div", { className: cn("flex max-h-96 flex-col", className), children: [_jsxs("div", { className: "border-b p-2", children: [_jsx("label", { htmlFor: searchInputId, className: "sr-only", children: searchPlaceholder }), _jsx(SearchInputShell, { children: _jsx(InputControl, { id: searchInputId, value: query, onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, className: "h-8 bg-background pl-8 pr-2" }) })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-1", children: filteredColumns.length ? (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: filteredColumns.map((column) => column.key), strategy: verticalListSortingStrategy, children: filteredColumns.map((column) => {
114
- const label = getColumnVisibilityLabel(column);
115
- const checked = visibleColumnKeySet.has(column.key);
116
- const disabled = checked && visibleColumnCount <= requiredVisibleColumns;
117
- return (_jsx(SortableColumnOption, { columnKey: column.key, label: label, checked: checked, disabled: disabled, onToggle: () => toggleColumn(column.key) }, column.key));
118
- }) }) })) : (_jsx("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage })) }), _jsxs(PopoverMenuFooter, { inset: "flush", className: "justify-between", children: [_jsx(PopoverMenuFooterAction, { onClick: () => commitVisibleColumnKeys(defaultKeys), disabled: !canRestoreDefaults, className: "w-auto min-w-0 flex-1", children: restoreDefaultsLabel }), _jsxs(PopoverMenuFooterMeta, { children: [visibleColumnCount, " of ", columns.length] })] })] }) }));
114
+ return (_jsx(Popover, { trigger: trigger !== null && trigger !== void 0 ? trigger : defaultTrigger, align: align, side: side, sideOffset: sideOffset, contentClassName: cn("w-80 p-0", contentClassName), "aria-labelledby": title ? titleId : undefined, children: _jsxs("div", { className: cn("flex max-h-96 flex-col", className), children: [_jsxs("div", { className: "border-b p-2", children: [_jsx("label", { htmlFor: searchInputId, className: "sr-only", children: searchPlaceholder }), _jsx(SearchInputShell, { children: _jsx(InputControl, { id: searchInputId, value: query, onChange: (event) => setQuery(event.target.value), placeholder: searchPlaceholder, className: "h-8 bg-background pl-8 pr-2" }) })] }), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-1", children: [title ? (_jsx(PopoverMenuGroupLabel, { id: titleId, children: title })) : null, filteredColumns.length ? (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: filteredColumns.map((column) => column.key), strategy: verticalListSortingStrategy, children: filteredColumns.map((column) => {
115
+ const label = getColumnVisibilityLabel(column);
116
+ const checked = visibleColumnKeySet.has(column.key);
117
+ const disabled = checked && visibleColumnCount <= requiredVisibleColumns;
118
+ return (_jsx(SortableColumnOption, { columnKey: column.key, label: label, checked: checked, disabled: disabled, onToggle: () => toggleColumn(column.key) }, column.key));
119
+ }) }) })) : (_jsx("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }))] }), _jsxs(PopoverMenuFooter, { inset: "flush", className: "justify-between", children: [_jsx(PopoverMenuFooterAction, { onClick: () => commitVisibleColumnKeys(defaultKeys), disabled: !canRestoreDefaults, className: "w-auto min-w-0 flex-1", children: restoreDefaultsLabel }), _jsxs(PopoverMenuFooterMeta, { children: [visibleColumnCount, " of ", columns.length] })] })] }) }));
119
120
  }
120
121
  export { TableColumnVisibilityMenu };
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { type SearchInputProps } from "./search-input";
3
3
  export interface TableToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  search?: SearchInputProps;
5
+ actionsClassName?: string;
5
6
  }
6
- declare function TableToolbar({ search, className, children, ...props }: TableToolbarProps): import("react/jsx-runtime").JSX.Element;
7
+ declare function TableToolbar({ search, className, actionsClassName, children, ...props }: TableToolbarProps): import("react/jsx-runtime").JSX.Element;
7
8
  export { TableToolbar };
@@ -1,7 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { SearchInput } from "./search-input";
3
3
  import { cn } from "./lib/utils";
4
- function TableToolbar({ search, className, children, ...props }) {
5
- return (_jsxs("div", { className: cn("flex flex-wrap items-center gap-1.5", className), ...props, children: [search ? (_jsx(SearchInput, { ...search, containerClassName: cn("min-w-[200px] flex-1 max-w-md", search.containerClassName) })) : null, children] }));
4
+ function TableToolbar({ search, className, actionsClassName, children, ...props }) {
5
+ const hasSearch = Boolean(search);
6
+ return (_jsxs("div", { className: cn(hasSearch
7
+ ? "grid w-full grid-cols-1 items-center gap-[calc(var(--space-1)+0.125rem)] sm:grid-cols-[minmax(calc(var(--space-10)*5),28rem)_minmax(0,1fr)]"
8
+ : "flex w-full flex-wrap items-center justify-end gap-[calc(var(--space-1)+0.125rem)]", className), ...props, children: [search ? (_jsx(SearchInput, { ...search, containerClassName: cn("w-full min-w-[calc(var(--space-10)*5)] max-w-md", search.containerClassName) })) : null, children ? (_jsx("div", { className: cn("flex flex-wrap items-center gap-[calc(var(--space-1)+0.125rem)]", hasSearch
9
+ ? "justify-start sm:justify-end sm:justify-self-end"
10
+ : "justify-end", actionsClassName), children: children })) : null] }));
6
11
  }
7
12
  export { TableToolbar };
package/dist/table.d.ts CHANGED
@@ -7,6 +7,7 @@ declare const TableRoot: React.ForwardRefExoticComponent<TableRootProps & React.
7
7
  interface TableContainerProps extends React.HTMLAttributes<HTMLDivElement> {
8
8
  }
9
9
  declare const TableContainer: React.ForwardRefExoticComponent<TableContainerProps & React.RefAttributes<HTMLDivElement>>;
10
+ export type TableColumnWidths = Record<string, number>;
10
11
  declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
11
12
  declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
12
13
  declare const TableFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
@@ -16,12 +17,16 @@ declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<
16
17
  minWidth?: string;
17
18
  maxWidth?: string;
18
19
  wrap?: boolean;
20
+ treatWidthAsMinWidth?: boolean;
21
+ containOverflow?: boolean;
19
22
  } & React.RefAttributes<HTMLTableCellElement>>;
20
23
  declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & {
21
24
  width?: string;
22
25
  minWidth?: string;
23
26
  maxWidth?: string;
24
27
  wrap?: boolean;
28
+ treatWidthAsMinWidth?: boolean;
29
+ containOverflow?: boolean;
25
30
  } & React.RefAttributes<HTMLTableCellElement>>;
26
31
  declare const TableCaption: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>;
27
32
  type TableAlign = "left" | "center" | "right";
@@ -76,6 +81,12 @@ export interface TableColumn<Row> {
76
81
  cellClassName?: string;
77
82
  /** Pins the column to the left or right edge while the table scrolls horizontally. */
78
83
  sticky?: "left" | "right";
84
+ /** Enables a resize handle for this column. Use `resizableColumns` on Table to opt every column in by default. */
85
+ resizable?: boolean;
86
+ /** Minimum pixel width while resizing. Defaults to `minWidth`, then 64. */
87
+ resizeMinWidth?: number;
88
+ /** Maximum pixel width while resizing. Omit to allow the column to grow. */
89
+ resizeMaxWidth?: number;
79
90
  }
80
91
  export interface TableSortingProps {
81
92
  field: string | null;
@@ -95,8 +106,16 @@ interface SortableTableHeadProps<T extends string> {
95
106
  maxWidth?: string;
96
107
  align?: TableAlign;
97
108
  sortLabel?: string;
109
+ resizeHandle?: React.ReactNode;
110
+ treatWidthAsMinWidth?: boolean;
111
+ containOverflow?: boolean;
112
+ }
113
+ declare function SortableTableHead<T extends string>({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, }: SortableTableHeadProps<T>): import("react/jsx-runtime").JSX.Element;
114
+ export interface TableColumnResizeHandleRenderProps<Row> {
115
+ column: TableColumn<Row>;
116
+ nextColumn: TableColumn<Row>;
117
+ handle: React.ReactElement;
98
118
  }
99
- declare function SortableTableHead<T extends string>({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap, width, minWidth, maxWidth, align, sortLabel, }: SortableTableHeadProps<T>): import("react/jsx-runtime").JSX.Element;
100
119
  export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
101
120
  columns: TableColumn<Row>[];
102
121
  rows: Row[];
@@ -117,10 +136,20 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
117
136
  loadingRows?: number;
118
137
  /** Optional controlled ordered list of visible column keys. Omit to render every column in config order. */
119
138
  visibleColumnKeys?: readonly string[];
139
+ /** When true, every column is resizable unless its column config sets `resizable: false`. */
140
+ resizableColumns?: boolean;
141
+ /** Controlled pixel widths keyed by column key. */
142
+ columnWidths?: TableColumnWidths;
143
+ /** Initial pixel widths keyed by column key for uncontrolled resizing. */
144
+ defaultColumnWidths?: TableColumnWidths;
145
+ /** Emits whenever a resize handle changes column widths. */
146
+ onColumnWidthsChange?: (columnWidths: TableColumnWidths) => void;
147
+ /** Optional hook for decorating resize handles without replacing table sizing behavior. */
148
+ renderColumnResizeHandle?: (props: TableColumnResizeHandleRenderProps<Row>) => React.ReactNode;
120
149
  /** When true, applies alternating row backgrounds for easier scanning. */
121
150
  striped?: boolean;
122
151
  /** When set, rows become interactive: cursor-pointer, hover highlight, and click handling. */
123
152
  onRowClick?: (row: Row, index: number) => void;
124
153
  }
125
- declare function Table<Row>({ columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, sorting, pagination, loading, loadingRows, visibleColumnKeys, striped, onRowClick, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
154
+ declare function Table<Row>({ columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, sorting, pagination, loading, loadingRows, visibleColumnKeys, resizableColumns, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, striped, onRowClick, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
126
155
  export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption, SortableTableHead, TableRowSkeleton, };
package/dist/table.js CHANGED
@@ -11,8 +11,11 @@ const TableRoot = React.forwardRef(({ className, wrapperClassName: _wrapperClass
11
11
  TableRoot.displayName = "TableRoot";
12
12
  const TableContainer = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("min-h-0 overflow-auto rounded-lg border border-[hsl(var(--table-border))] bg-card text-card-foreground", className), ...props })));
13
13
  TableContainer.displayName = "TableContainer";
14
- function getTableColumnSizingStyle({ style, width, minWidth, maxWidth, }) {
15
- const resolvedMinWidth = minWidth !== null && minWidth !== void 0 ? minWidth : width;
14
+ const DEFAULT_COLUMN_RESIZE_MIN_WIDTH = 64;
15
+ const DEFAULT_COLUMN_RESIZE_START_WIDTH = 160;
16
+ const COLUMN_RESIZE_KEYBOARD_STEP = 16;
17
+ function getTableColumnSizingStyle({ style, width, minWidth, maxWidth, treatWidthAsMinWidth = true, }) {
18
+ const resolvedMinWidth = minWidth !== null && minWidth !== void 0 ? minWidth : (treatWidthAsMinWidth ? width : undefined);
16
19
  return {
17
20
  ...style,
18
21
  ...(width ? { width } : {}),
@@ -20,6 +23,94 @@ function getTableColumnSizingStyle({ style, width, minWidth, maxWidth, }) {
20
23
  ...(maxWidth ? { maxWidth } : {}),
21
24
  };
22
25
  }
26
+ function overflowContainmentClassName({ containOverflow, wrap, }) {
27
+ if (!containOverflow) {
28
+ return undefined;
29
+ }
30
+ return wrap
31
+ ? "break-words [overflow-wrap:anywhere]"
32
+ : "overflow-hidden text-ellipsis";
33
+ }
34
+ function parsePixelSize(value) {
35
+ if (typeof value === "number") {
36
+ return Number.isFinite(value) ? value : undefined;
37
+ }
38
+ if (!value) {
39
+ return undefined;
40
+ }
41
+ const match = /^(\d+(?:\.\d+)?)px$/.exec(value.trim());
42
+ return match ? Number(match[1]) : undefined;
43
+ }
44
+ function clampColumnWidth(column, width) {
45
+ var _a;
46
+ const minWidth = (_a = parsePixelSize(column.minWidth)) !== null && _a !== void 0 ? _a : DEFAULT_COLUMN_RESIZE_MIN_WIDTH;
47
+ const maxWidth = parsePixelSize(column.maxWidth);
48
+ const roundedWidth = Math.round(width);
49
+ const clampedWidth = Math.max(minWidth, roundedWidth);
50
+ return maxWidth !== undefined
51
+ ? Math.min(clampedWidth, maxWidth)
52
+ : clampedWidth;
53
+ }
54
+ function getColumnResizeMinWidth(column) {
55
+ var _a, _b;
56
+ return ((_b = (_a = parsePixelSize(column.resizeMinWidth)) !== null && _a !== void 0 ? _a : parsePixelSize(column.minWidth)) !== null && _b !== void 0 ? _b : DEFAULT_COLUMN_RESIZE_MIN_WIDTH);
57
+ }
58
+ function getColumnResizeMaxWidth(column) {
59
+ var _a;
60
+ return (_a = parsePixelSize(column.resizeMaxWidth)) !== null && _a !== void 0 ? _a : Number.POSITIVE_INFINITY;
61
+ }
62
+ function getColumnResizeMaxWidthStyle(column) {
63
+ const maxWidth = getColumnResizeMaxWidth(column);
64
+ return Number.isFinite(maxWidth) ? `${maxWidth}px` : undefined;
65
+ }
66
+ function clampColumnResizeWidth(column, width) {
67
+ const minWidth = getColumnResizeMinWidth(column);
68
+ const maxWidth = getColumnResizeMaxWidth(column);
69
+ const roundedWidth = Math.round(width);
70
+ const clampedWidth = Math.max(minWidth, roundedWidth);
71
+ return Number.isFinite(maxWidth)
72
+ ? Math.min(clampedWidth, maxWidth)
73
+ : clampedWidth;
74
+ }
75
+ function clampNumber(value, min, max) {
76
+ return Math.min(Math.max(value, min), max);
77
+ }
78
+ function getResolvedColumnWidth(column, columnWidths) {
79
+ const resizedWidth = columnWidths[column.key];
80
+ if (resizedWidth === undefined) {
81
+ return column.width;
82
+ }
83
+ return `${clampColumnWidth(column, resizedWidth)}px`;
84
+ }
85
+ function getResolvedResizableColumnWidth(column, columnWidths) {
86
+ return clampColumnResizeWidth(column, getColumnResizeBaseWidth(column, columnWidths));
87
+ }
88
+ function getRenderedColumnWidth({ column, columnWidths, resizing, }) {
89
+ if (resizing) {
90
+ return `${getResolvedResizableColumnWidth(column, columnWidths)}px`;
91
+ }
92
+ return getResolvedColumnWidth(column, columnWidths);
93
+ }
94
+ function getRenderedColumnMinWidth(column, resizing) {
95
+ return resizing ? `${getColumnResizeMinWidth(column)}px` : column.minWidth;
96
+ }
97
+ function getRenderedColumnMaxWidth(column, resizing) {
98
+ return resizing ? getColumnResizeMaxWidthStyle(column) : column.maxWidth;
99
+ }
100
+ function getColumnResizeBaseWidth(column, columnWidths, elementWidth) {
101
+ var _a, _b, _c, _d;
102
+ return ((_d = (_c = (_b = (_a = columnWidths[column.key]) !== null && _a !== void 0 ? _a : parsePixelSize(column.width)) !== null && _b !== void 0 ? _b : (elementWidth && elementWidth > 0 ? elementWidth : undefined)) !== null && _c !== void 0 ? _c : parsePixelSize(column.minWidth)) !== null && _d !== void 0 ? _d : DEFAULT_COLUMN_RESIZE_START_WIDTH);
103
+ }
104
+ function getColumnResizeLabel(column) {
105
+ if (column.visibilityLabel) {
106
+ return column.visibilityLabel;
107
+ }
108
+ if (typeof column.header === "string" ||
109
+ typeof column.header === "number") {
110
+ return String(column.header);
111
+ }
112
+ return column.key;
113
+ }
23
114
  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 })));
24
115
  TableHeader.displayName = "TableHeader";
25
116
  const TableBody = React.forwardRef(({ className, ...props }, ref) => (_jsx("tbody", { ref: ref, className: cn("[&_tr:last-child]:border-0", className), ...props })));
@@ -28,7 +119,7 @@ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("tf
28
119
  TableFooter.displayName = "TableFooter";
29
120
  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 })));
30
121
  TableRow.displayName = "TableRow";
31
- const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, ...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", className), style: getTableColumnSizingStyle({
122
+ 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({
32
123
  style: {
33
124
  ...style,
34
125
  fontWeight: 500,
@@ -36,24 +127,43 @@ const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidt
36
127
  width,
37
128
  minWidth,
38
129
  maxWidth,
130
+ treatWidthAsMinWidth,
39
131
  }), ...props })));
40
132
  TableHead.displayName = "TableHead";
41
- const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-2 align-middle text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", className), style: getTableColumnSizingStyle({ style, width, minWidth, maxWidth }), ...props })));
133
+ const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-2 align-middle text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
134
+ style,
135
+ width,
136
+ minWidth,
137
+ maxWidth,
138
+ treatWidthAsMinWidth,
139
+ }), ...props })));
42
140
  TableCell.displayName = "TableCell";
43
141
  const TableCaption = React.forwardRef(({ className, ...props }, ref) => (_jsx("caption", { ref: ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props })));
44
142
  TableCaption.displayName = "TableCaption";
45
- function stickyClassName(sticky, kind) {
143
+ const STICKY_SCROLL_EDGE_THRESHOLD = 1;
144
+ function stickyClassName(sticky, kind, showShadow = false) {
46
145
  if (!sticky)
47
146
  return undefined;
48
147
  const side = sticky === "left" ? "left-0" : "right-0";
49
- const shadow = sticky === "left"
50
- ? "shadow-[inset_-1px_0_0_0_var(--color-border)]"
51
- : "shadow-[inset_1px_0_0_0_var(--color-border)]";
148
+ const shadow = showShadow
149
+ ? sticky === "left"
150
+ ? "shadow-[inset_-1px_0_0_0_hsl(var(--table-border)),_8px_0_12px_-10px_hsl(var(--foreground)_/_0.35)]"
151
+ : "shadow-[inset_1px_0_0_0_hsl(var(--table-border)),_-8px_0_12px_-10px_hsl(var(--foreground)_/_0.35)]"
152
+ : undefined;
52
153
  const background = kind === "head" ? "bg-[hsl(var(--table-header-background))]" : "bg-card";
53
154
  // z-20 on header cells so they layer above sticky body cells on the other axis.
54
155
  const z = kind === "head" ? "z-20" : "z-10";
55
156
  return cn("sticky", background, side, z, shadow);
56
157
  }
158
+ function getStickyShadowVisibility(sticky, scrollState) {
159
+ if (sticky === "left") {
160
+ return scrollState.left;
161
+ }
162
+ if (sticky === "right") {
163
+ return scrollState.right;
164
+ }
165
+ return false;
166
+ }
57
167
  function alignClassName(align) {
58
168
  switch (align) {
59
169
  case "center":
@@ -107,12 +217,32 @@ export const TABLE_SKELETON_PRESETS = {
107
217
  })),
108
218
  }),
109
219
  };
110
- function SortableTableHead({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap = false, width, minWidth, maxWidth, align, sortLabel, }) {
220
+ function SortableTableHead({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap = false, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, }) {
111
221
  const isSorted = currentSortField === field;
112
- return (_jsx(TableHead, { className: cn(alignClassName(align), className), wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, 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", allowWrap
113
- ? "max-w-full whitespace-normal text-left"
114
- : "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: [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" })) })] }) }));
222
+ return (_jsxs(TableHead, { 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
223
+ ? "max-w-full whitespace-normal text-left"
224
+ : "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] }));
115
225
  }
226
+ const TableColumnResizeHandle = React.forwardRef(function TableColumnResizeHandle({ column, nextColumn, currentWidth, minWidth, maxWidth, onResizeStart, onResizeByKeyboard, className, onClick, ...props }, ref) {
227
+ const label = getColumnResizeLabel(column);
228
+ 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) => {
229
+ onClick === null || onClick === void 0 ? void 0 : onClick(event);
230
+ if (event.defaultPrevented) {
231
+ return;
232
+ }
233
+ event.preventDefault();
234
+ event.stopPropagation();
235
+ }, onKeyDown: (event) => {
236
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") {
237
+ return;
238
+ }
239
+ event.preventDefault();
240
+ event.stopPropagation();
241
+ onResizeByKeyboard(column, nextColumn, event.key === "ArrowLeft"
242
+ ? -COLUMN_RESIZE_KEYBOARD_STEP
243
+ : COLUMN_RESIZE_KEYBOARD_STEP);
244
+ }, 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" }) }));
245
+ });
116
246
  function getDefaultSkeleton(column) {
117
247
  var _a, _b;
118
248
  return {
@@ -149,23 +279,163 @@ function getVisibleColumns(columns, visibleColumnKeys) {
149
279
  });
150
280
  return visibleColumns;
151
281
  }
152
- 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, sorting, pagination, loading = false, loadingRows = 5, visibleColumnKeys, striped = false, onRowClick, style, ...props }) {
153
- // Use auto layout so the browser can grow a column to contain its (nowrap)
154
- // header. Caller can opt back into fixed layout via `tableClassName="table-fixed"`.
155
- const shouldUseFixedLayout = false;
282
+ function isStickyResizeBoundary(column, nextColumn) {
283
+ return Boolean(column.sticky === "right" || nextColumn.sticky);
284
+ }
285
+ 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, sorting, pagination, loading = false, loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, striped = false, onRowClick, onScroll, style, ...props }) {
156
286
  const visibleColumns = getVisibleColumns(columns, visibleColumnKeys);
157
- const container = (_jsx(TableContainer, { className: cn("w-full", loading && "pointer-events-none select-none", className, containerClassName), style: {
287
+ const isColumnResizingEnabled = resizableColumns || visibleColumns.some((column) => column.resizable);
288
+ // Use auto layout by default so the browser can grow a column to contain its
289
+ // nowrap header. Resizable columns need fixed layout so neighbour columns do
290
+ // not redistribute width while a handle is dragged.
291
+ const shouldUseFixedLayout = isColumnResizingEnabled;
292
+ const [uncontrolledColumnWidths, setUncontrolledColumnWidths] = React.useState(() => ({ ...(defaultColumnWidths !== null && defaultColumnWidths !== void 0 ? defaultColumnWidths : {}) }));
293
+ const resolvedColumnWidths = columnWidths !== null && columnWidths !== void 0 ? columnWidths : uncontrolledColumnWidths;
294
+ const columnWidthsRef = React.useRef(resolvedColumnWidths);
295
+ const resizeCleanupRef = React.useRef(null);
296
+ const tableContainerRef = React.useRef(null);
297
+ const [stickyScrollState, setStickyScrollState] = React.useState({
298
+ left: false,
299
+ right: false,
300
+ });
301
+ const updateStickyScrollState = React.useCallback((element = tableContainerRef.current) => {
302
+ if (!element) {
303
+ return;
304
+ }
305
+ const maxScrollLeft = Math.max(0, element.scrollWidth - element.clientWidth);
306
+ const scrollLeft = Math.max(0, element.scrollLeft);
307
+ const nextScrollState = {
308
+ left: scrollLeft > STICKY_SCROLL_EDGE_THRESHOLD,
309
+ right: scrollLeft < maxScrollLeft - STICKY_SCROLL_EDGE_THRESHOLD,
310
+ };
311
+ setStickyScrollState((currentScrollState) => currentScrollState.left === nextScrollState.left &&
312
+ currentScrollState.right === nextScrollState.right
313
+ ? currentScrollState
314
+ : nextScrollState);
315
+ }, []);
316
+ React.useEffect(() => {
317
+ columnWidthsRef.current = resolvedColumnWidths;
318
+ }, [resolvedColumnWidths]);
319
+ React.useEffect(() => {
320
+ updateStickyScrollState();
321
+ });
322
+ React.useEffect(() => {
323
+ const element = tableContainerRef.current;
324
+ if (!element || typeof ResizeObserver === "undefined") {
325
+ return;
326
+ }
327
+ const observer = new ResizeObserver(() => updateStickyScrollState(element));
328
+ observer.observe(element);
329
+ return () => observer.disconnect();
330
+ }, [updateStickyScrollState]);
331
+ React.useEffect(() => () => {
332
+ var _a;
333
+ (_a = resizeCleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(resizeCleanupRef);
334
+ }, []);
335
+ const commitColumnWidths = React.useCallback((updater) => {
336
+ const nextColumnWidths = updater(columnWidthsRef.current);
337
+ columnWidthsRef.current = nextColumnWidths;
338
+ if (!columnWidths) {
339
+ setUncontrolledColumnWidths(nextColumnWidths);
340
+ }
341
+ onColumnWidthsChange === null || onColumnWidthsChange === void 0 ? void 0 : onColumnWidthsChange(nextColumnWidths);
342
+ }, [columnWidths, onColumnWidthsChange]);
343
+ const resizeColumnPairByDelta = React.useCallback((column, nextColumn, delta, startColumnWidths = columnWidthsRef.current) => {
344
+ const currentWidth = getResolvedResizableColumnWidth(column, startColumnWidths);
345
+ const nextWidth = getResolvedResizableColumnWidth(nextColumn, startColumnWidths);
346
+ const minDelta = Math.max(getColumnResizeMinWidth(column) - currentWidth, nextWidth - getColumnResizeMaxWidth(nextColumn));
347
+ const maxDelta = Math.min(getColumnResizeMaxWidth(column) - currentWidth, nextWidth - getColumnResizeMinWidth(nextColumn));
348
+ const resolvedDelta = clampNumber(delta, minDelta, maxDelta);
349
+ commitColumnWidths((currentColumnWidths) => ({
350
+ ...currentColumnWidths,
351
+ [column.key]: Math.round(currentWidth + resolvedDelta),
352
+ [nextColumn.key]: Math.round(nextWidth - resolvedDelta),
353
+ }));
354
+ }, [commitColumnWidths]);
355
+ const resizeColumnByKeyboard = React.useCallback((column, nextColumn, delta) => {
356
+ resizeColumnPairByDelta(column, nextColumn, delta);
357
+ }, [resizeColumnPairByDelta]);
358
+ const startColumnResize = React.useCallback((column, nextColumn, event) => {
359
+ var _a;
360
+ event.preventDefault();
361
+ event.stopPropagation();
362
+ (_a = resizeCleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(resizeCleanupRef);
363
+ const ownerDocument = event.currentTarget.ownerDocument;
364
+ const startX = event.clientX;
365
+ const startColumnWidths = columnWidthsRef.current;
366
+ const previousCursor = ownerDocument.documentElement.style.cursor;
367
+ ownerDocument.documentElement.style.cursor = "col-resize";
368
+ const handlePointerMove = (pointerEvent) => {
369
+ resizeColumnPairByDelta(column, nextColumn, pointerEvent.clientX - startX, startColumnWidths);
370
+ };
371
+ const handlePointerUp = () => {
372
+ var _a;
373
+ (_a = resizeCleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(resizeCleanupRef);
374
+ };
375
+ const cleanup = () => {
376
+ ownerDocument.removeEventListener("pointermove", handlePointerMove);
377
+ ownerDocument.removeEventListener("pointerup", handlePointerUp);
378
+ ownerDocument.documentElement.style.cursor = previousCursor;
379
+ resizeCleanupRef.current = null;
380
+ };
381
+ resizeCleanupRef.current = cleanup;
382
+ ownerDocument.addEventListener("pointermove", handlePointerMove);
383
+ ownerDocument.addEventListener("pointerup", handlePointerUp);
384
+ }, [resizeColumnPairByDelta]);
385
+ const renderResizeHandle = React.useCallback((column, columnIndex) => {
386
+ var _a, _b;
387
+ const nextColumn = visibleColumns[columnIndex + 1];
388
+ const isResizable = (_a = column.resizable) !== null && _a !== void 0 ? _a : resizableColumns;
389
+ const isNextResizable = nextColumn && ((_b = nextColumn.resizable) !== null && _b !== void 0 ? _b : resizableColumns);
390
+ if (!isResizable || !nextColumn || !isNextResizable) {
391
+ return null;
392
+ }
393
+ const stickyResizeBoundary = isStickyResizeBoundary(column, nextColumn);
394
+ if (stickyResizeBoundary) {
395
+ return null;
396
+ }
397
+ const handle = (_jsx(TableColumnResizeHandle, { column: column, nextColumn: nextColumn, currentWidth: getResolvedResizableColumnWidth(column, resolvedColumnWidths), minWidth: getColumnResizeMinWidth(column), maxWidth: Number.isFinite(getColumnResizeMaxWidth(column))
398
+ ? getColumnResizeMaxWidth(column)
399
+ : undefined, onResizeStart: startColumnResize, onResizeByKeyboard: resizeColumnByKeyboard }));
400
+ if (renderColumnResizeHandle) {
401
+ return renderColumnResizeHandle({ column, nextColumn, handle });
402
+ }
403
+ return handle;
404
+ }, [
405
+ resizableColumns,
406
+ renderColumnResizeHandle,
407
+ resizeColumnByKeyboard,
408
+ resolvedColumnWidths,
409
+ startColumnResize,
410
+ visibleColumns,
411
+ ]);
412
+ const handleTableContainerScroll = React.useCallback((event) => {
413
+ onScroll === null || onScroll === void 0 ? void 0 : onScroll(event);
414
+ updateStickyScrollState(event.currentTarget);
415
+ }, [onScroll, updateStickyScrollState]);
416
+ const container = (_jsx(TableContainer, { ref: tableContainerRef, onScroll: handleTableContainerScroll, className: cn("w-full", loading && "pointer-events-none select-none", className, containerClassName), style: {
158
417
  ...style,
159
418
  ...(maxHeight !== undefined ? { maxHeight } : {}),
160
419
  }, ...props, children: _jsxs(TableRoot, { className: cn(shouldUseFixedLayout && "table-fixed", tableClassName), children: [caption ? _jsx(TableCaption, { children: caption }) : null, _jsx("colgroup", { children: visibleColumns.map((column) => (_jsx("col", { style: getTableColumnSizingStyle({
161
- width: column.width,
162
- minWidth: column.minWidth,
163
- maxWidth: column.maxWidth,
164
- }) }, column.key))) }), _jsx(TableHeader, { children: _jsx(TableRow, { children: visibleColumns.map((column) => {
420
+ width: getRenderedColumnWidth({
421
+ column,
422
+ columnWidths: resolvedColumnWidths,
423
+ resizing: isColumnResizingEnabled,
424
+ }),
425
+ minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
426
+ maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
427
+ treatWidthAsMinWidth: !isColumnResizingEnabled,
428
+ }) }, column.key))) }), _jsx(TableHeader, { children: _jsx(TableRow, { children: visibleColumns.map((column, columnIndex) => {
165
429
  var _a;
166
430
  const sortField = (_a = column.sortKey) !== null && _a !== void 0 ? _a : column.key;
167
431
  const isSortable = column.sortable && sorting;
168
- return (isSortable ? (_jsx(SortableTableHead, { field: sortField, currentSortField: sorting.field, currentSortDirection: sorting.direction, onSort: sorting.onSort, className: cn(stickyClassName(column.sticky, "head"), column.headerClassName), allowWrap: column.wrap, width: column.width, minWidth: column.minWidth, maxWidth: column.maxWidth, align: column.align, sortLabel: column.sortLabel, children: column.header }, column.key)) : (_jsx(TableHead, { width: column.width, minWidth: column.minWidth, maxWidth: column.maxWidth, wrap: column.wrap, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "head"), column.headerClassName), children: column.header }, column.key)));
432
+ const columnWidth = getRenderedColumnWidth({
433
+ column,
434
+ columnWidths: resolvedColumnWidths,
435
+ resizing: isColumnResizingEnabled,
436
+ });
437
+ const resizeHandle = renderResizeHandle(column, columnIndex);
438
+ 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, { 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)));
169
439
  }) }) }), _jsx(TableBody, { children: loading ? (_jsx(TableRowSkeleton, { rows: loadingRows, columns: visibleColumns.map((column) => { var _a; return (_a = column.skeleton) !== null && _a !== void 0 ? _a : getDefaultSkeleton(column); }) })) : rows.length ? (rows.map((row, rowIndex) => {
170
440
  const resolvedTone = typeof rowTone === "function"
171
441
  ? rowTone(row, rowIndex)
@@ -178,10 +448,15 @@ function Table({ columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { mess
178
448
  ? rowClassName(row, rowIndex)
179
449
  : rowClassName), children: visibleColumns.map((column) => {
180
450
  var _a, _b;
451
+ const columnWidth = getRenderedColumnWidth({
452
+ column,
453
+ columnWidths: resolvedColumnWidths,
454
+ resizing: isColumnResizingEnabled,
455
+ });
181
456
  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
182
457
  ? row[column.accessorKey]
183
458
  : null);
184
- return (_jsx(TableCell, { width: column.width, minWidth: column.minWidth, maxWidth: column.maxWidth, wrap: column.wrap, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell"), column.cellClassName), children: value }, column.key));
459
+ 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));
185
460
  }) }, getRowKey(row, rowIndex)));
186
461
  })) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length, 1), className: "p-6", children: emptyState }) })) })] }) }));
187
462
  if (!pagination) {
package/dist/tabs.d.ts CHANGED
@@ -55,8 +55,9 @@ export interface TabWithDropdownProps {
55
55
  onSectionSelect?: (sectionId: string) => void;
56
56
  activeSection?: string;
57
57
  className?: string;
58
+ contentClassName?: string;
58
59
  }
59
- declare function TabWithDropdown({ value, label, sections, disabled, scrollOffset, onSectionSelect, activeSection, className, }: TabWithDropdownProps): import("react/jsx-runtime").JSX.Element;
60
+ declare function TabWithDropdown({ value, label, sections, disabled, scrollOffset, onSectionSelect, activeSection, className, contentClassName, }: TabWithDropdownProps): import("react/jsx-runtime").JSX.Element;
60
61
  export interface TabsProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, "children" | "value" | "defaultValue" | "onValueChange"> {
61
62
  items: TabsItem[];
62
63
  defaultValue?: string;