@neasg/design-system 0.4.24 → 0.4.25
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/index.d.ts +1 -1
- package/dist/multi-select.js +7 -0
- package/dist/table-column-filter.d.ts +9 -1
- package/dist/table-column-filter.js +19 -3
- package/dist/table.d.ts +10 -2
- package/dist/table.js +70 -17
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -133,7 +133,7 @@ export { useTableSort } from "./use-table-sort";
|
|
|
133
133
|
export type { UseTableSortOptions, UseTableSortReturn, } from "./use-table-sort";
|
|
134
134
|
export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, TableRowSkeleton, TABLE_SKELETON_PRESETS, } from "./table";
|
|
135
135
|
export type { TableColumn, TableColumnWidths, TableProps, TableResizeMode, TableRowExpansionProps, TableRowTone, TableSortDirection, TableSortingProps, TableSkeletonConfig, TableRowSkeletonProps, } from "./table";
|
|
136
|
-
export type { TableColumnFilter, TableColumnFilterOption, TableDateColumnFilter, TableOptionsColumnFilter, TableTextColumnFilter, } from "./table-column-filter";
|
|
136
|
+
export type { TableColumnFilter, TableColumnFilterOption, TableDateColumnFilter, TableDateRangeColumnFilter, TableOptionsColumnFilter, TableTextColumnFilter, } from "./table-column-filter";
|
|
137
137
|
export { Tabs, SubTabs, TabsRoot, TabWithDropdown, type TabsItem, type TabsItemLabel, type TabsItemLabelProps, type TabsProps, type SubTabsItem, type SubTabsProps, TabsList, TabsTrigger, TabsContent, type TabWithDropdownProps, useTabsContext, type TabDropdownSection, } from "./tabs";
|
|
138
138
|
export { Tooltip, TooltipRoot, TooltipTrigger, TooltipContent, TooltipProvider, type TooltipProps, } from "./tooltip";
|
|
139
139
|
export { Toaster, toast } from "./toaster";
|
package/dist/multi-select.js
CHANGED
|
@@ -136,6 +136,13 @@ function MultiSelect({ label, options, value, onValueChange, placeholder = "Sele
|
|
|
136
136
|
closeAndFocusTrigger();
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
if (currentIndex >= 0) {
|
|
142
|
+
enabledOptions[currentIndex].click();
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
139
146
|
if (event.key === "Home" || event.key === "End") {
|
|
140
147
|
event.preventDefault();
|
|
141
148
|
focusBoundaryOption(event.key === "Home" ? "first" : "last");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { type DateRangeInputValue } from "./date-input";
|
|
2
3
|
interface TableColumnFilterBase {
|
|
3
4
|
/** Overrides the column header text in accessible filter labels. */
|
|
4
5
|
label?: string;
|
|
@@ -33,7 +34,14 @@ export interface TableDateColumnFilter extends TableColumnFilterBase {
|
|
|
33
34
|
minDate?: Date;
|
|
34
35
|
maxDate?: Date;
|
|
35
36
|
}
|
|
36
|
-
export
|
|
37
|
+
export interface TableDateRangeColumnFilter extends TableColumnFilterBase {
|
|
38
|
+
type: "dateRange";
|
|
39
|
+
value: DateRangeInputValue;
|
|
40
|
+
onValueChange: (value: DateRangeInputValue) => void;
|
|
41
|
+
minDate?: Date;
|
|
42
|
+
maxDate?: Date;
|
|
43
|
+
}
|
|
44
|
+
export type TableColumnFilter = TableTextColumnFilter | TableOptionsColumnFilter | TableDateColumnFilter | TableDateRangeColumnFilter;
|
|
37
45
|
interface TableColumnFilterControlProps {
|
|
38
46
|
filter: TableColumnFilter;
|
|
39
47
|
label: string;
|
|
@@ -9,9 +9,15 @@ import { cn } from "./lib/utils";
|
|
|
9
9
|
import { Popover } from "./popover";
|
|
10
10
|
import { PopoverMenuFooter, PopoverMenuFooterAction, PopoverMenuSearch, } from "./popover-menu";
|
|
11
11
|
function isTableColumnFilterActive(filter) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
switch (filter.type) {
|
|
13
|
+
case "options":
|
|
14
|
+
return filter.values.length > 0;
|
|
15
|
+
case "dateRange":
|
|
16
|
+
return Boolean(filter.value.from || filter.value.to);
|
|
17
|
+
case "text":
|
|
18
|
+
case "date":
|
|
19
|
+
return filter.value.trim().length > 0;
|
|
20
|
+
}
|
|
15
21
|
}
|
|
16
22
|
function getOptionsFilterSummary(filter) {
|
|
17
23
|
var _a, _b, _c;
|
|
@@ -68,6 +74,13 @@ function DateColumnFilter({ filter, label, }) {
|
|
|
68
74
|
return (_jsx(DateInput, { label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick a date", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-9 w-full min-w-0 justify-start text-sm font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", !active &&
|
|
69
75
|
"border-0 bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
70
76
|
}
|
|
77
|
+
function DateRangeColumnFilter({ filter, label, }) {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const active = isTableColumnFilterActive(filter);
|
|
80
|
+
const accessibleLabel = (_a = filter.label) !== null && _a !== void 0 ? _a : label;
|
|
81
|
+
return (_jsx(DateInput, { mode: "range", label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick date range", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-9 w-full min-w-0 justify-start text-sm font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", !active &&
|
|
82
|
+
"border-0 bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
83
|
+
}
|
|
71
84
|
function TableColumnFilterControl({ filter, label, }) {
|
|
72
85
|
if (filter.type === "text") {
|
|
73
86
|
return _jsx(TextColumnFilter, { filter: filter, label: label });
|
|
@@ -75,6 +88,9 @@ function TableColumnFilterControl({ filter, label, }) {
|
|
|
75
88
|
if (filter.type === "options") {
|
|
76
89
|
return _jsx(OptionsColumnFilter, { filter: filter, label: label });
|
|
77
90
|
}
|
|
91
|
+
if (filter.type === "dateRange") {
|
|
92
|
+
return _jsx(DateRangeColumnFilter, { filter: filter, label: label });
|
|
93
|
+
}
|
|
78
94
|
return _jsx(DateColumnFilter, { filter: filter, label: label });
|
|
79
95
|
}
|
|
80
96
|
export { TableColumnFilterControl };
|
package/dist/table.d.ts
CHANGED
|
@@ -124,12 +124,14 @@ export interface TableRowExpansionProps<Row> {
|
|
|
124
124
|
getToggleLabel?: (row: Row, rowIndex: number, expanded: boolean) => string;
|
|
125
125
|
}
|
|
126
126
|
interface SortableTableHeadProps<T extends string> {
|
|
127
|
+
ref?: React.Ref<HTMLTableCellElement>;
|
|
127
128
|
field: T;
|
|
128
129
|
children: React.ReactNode;
|
|
129
130
|
currentSortField: T | null;
|
|
130
131
|
currentSortDirection: SortDirection;
|
|
131
132
|
onSort: (field: T) => void;
|
|
132
133
|
className?: string;
|
|
134
|
+
style?: React.CSSProperties;
|
|
133
135
|
allowWrap?: boolean;
|
|
134
136
|
width?: string;
|
|
135
137
|
minWidth?: string;
|
|
@@ -139,8 +141,10 @@ interface SortableTableHeadProps<T extends string> {
|
|
|
139
141
|
resizeHandle?: React.ReactNode;
|
|
140
142
|
treatWidthAsMinWidth?: boolean;
|
|
141
143
|
containOverflow?: boolean;
|
|
144
|
+
gripIcon?: React.ReactNode;
|
|
145
|
+
[key: string]: unknown;
|
|
142
146
|
}
|
|
143
|
-
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;
|
|
147
|
+
declare function SortableTableHead<T extends string>({ ref, field, children, currentSortField, currentSortDirection, onSort, className, style, allowWrap, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, gripIcon, ...rest }: SortableTableHeadProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
144
148
|
export interface TableColumnResizeHandleRenderProps<Row> {
|
|
145
149
|
column: TableColumn<Row>;
|
|
146
150
|
nextColumn: TableColumn<Row>;
|
|
@@ -194,6 +198,10 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
|
|
|
194
198
|
striped?: boolean;
|
|
195
199
|
/** Adds a disclosure column and full-width expandable content for nested tables or row details. */
|
|
196
200
|
rowExpansion?: TableRowExpansionProps<Row>;
|
|
201
|
+
/** When true, non-sticky header cells become draggable for column reordering. */
|
|
202
|
+
reorderableColumns?: boolean;
|
|
203
|
+
/** Called with the new ordered column key array after a drag-and-drop reorder. */
|
|
204
|
+
onColumnOrderChange?: (columnKeys: string[]) => void;
|
|
197
205
|
}
|
|
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;
|
|
206
|
+
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, reorderableColumns, onColumnOrderChange, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
199
207
|
export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, SortableTableHead, TableRowSkeleton, };
|
package/dist/table.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from "@dnd-kit/core";
|
|
4
|
+
import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, } from "@dnd-kit/sortable";
|
|
5
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
3
6
|
import { ArrowUpDown, ChevronRight } from "lucide-react";
|
|
4
7
|
import { ArrowDownIcon } from "./animated-icons/arrow-down";
|
|
5
8
|
import { ArrowUpIcon } from "./animated-icons/arrow-up";
|
|
@@ -148,7 +151,7 @@ function getColumnHeaderAriaLabel(column) {
|
|
|
148
151
|
}
|
|
149
152
|
return undefined;
|
|
150
153
|
}
|
|
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 })));
|
|
154
|
+
const TableHeader = React.forwardRef(({ className, ...props }, ref) => (_jsx("thead", { ref: ref, className: cn("sticky top-0 z-10 overflow-visible bg-[hsl(var(--table-header-background))] [&_tr]:border-b [&_tr]:border-[hsl(var(--table-border))] [&>tr]:bg-inherit", className), ...props })));
|
|
152
155
|
TableHeader.displayName = "TableHeader";
|
|
153
156
|
const TableBody = React.forwardRef(({ className, ...props }, ref) => (_jsx("tbody", { ref: ref, className: cn("[&_tr:last-child]:border-0", className), ...props })));
|
|
154
157
|
TableBody.displayName = "TableBody";
|
|
@@ -262,19 +265,35 @@ export const TABLE_SKELETON_PRESETS = {
|
|
|
262
265
|
})),
|
|
263
266
|
}),
|
|
264
267
|
};
|
|
265
|
-
function SortableTableHead({ field, children, currentSortField, currentSortDirection, onSort, className, allowWrap = false, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, }) {
|
|
268
|
+
function SortableTableHead({ ref, field, children, currentSortField, currentSortDirection, onSort, className, style, allowWrap = false, width, minWidth, maxWidth, align, sortLabel, resizeHandle, treatWidthAsMinWidth, containOverflow, gripIcon, ...rest }) {
|
|
266
269
|
const isSorted = currentSortField === field;
|
|
267
270
|
const resolvedSortLabel = sortLabel !== null && sortLabel !== void 0 ? sortLabel : (typeof children === "string" || typeof children === "number"
|
|
268
271
|
? String(children)
|
|
269
272
|
: field);
|
|
270
|
-
return (_jsxs(TableHead, { "data-slot": "table-column-head", scope: "col", "aria-sort": isSorted
|
|
273
|
+
return (_jsxs(TableHead, { ref: ref, "data-slot": "table-column-head", scope: "col", "aria-sort": isSorted
|
|
271
274
|
? currentSortDirection === "asc"
|
|
272
275
|
? "ascending"
|
|
273
276
|
: "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
|
|
277
|
+
: undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), style: style, wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, ...rest, children: [gripIcon, _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
|
|
275
278
|
? "max-w-full whitespace-normal text-left"
|
|
276
279
|
: "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] }));
|
|
277
280
|
}
|
|
281
|
+
const DragGripIcon = (_jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute bottom-0 left-1/2 z-20 -translate-x-1/2 translate-y-1/2 rounded border border-border bg-background px-1.5 py-0.5 text-muted-foreground opacity-0 shadow-sm transition-opacity group-hover/drag-col:opacity-100", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { transform: "rotate(90deg)" }, children: [_jsx("circle", { cx: "9", cy: "5", r: "1" }), _jsx("circle", { cx: "15", cy: "5", r: "1" }), _jsx("circle", { cx: "9", cy: "12", r: "1" }), _jsx("circle", { cx: "15", cy: "12", r: "1" }), _jsx("circle", { cx: "9", cy: "19", r: "1" }), _jsx("circle", { cx: "15", cy: "19", r: "1" })] }) }));
|
|
282
|
+
function DraggableColumnHead({ columnKey, disabled, children, }) {
|
|
283
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: columnKey, disabled });
|
|
284
|
+
return children({
|
|
285
|
+
ref: setNodeRef,
|
|
286
|
+
style: {
|
|
287
|
+
transform: CSS.Translate.toString(transform),
|
|
288
|
+
transition,
|
|
289
|
+
zIndex: isDragging ? 30 : undefined,
|
|
290
|
+
},
|
|
291
|
+
className: cn(!disabled &&
|
|
292
|
+
"group/drag-col relative !overflow-visible cursor-grab active:cursor-grabbing before:pointer-events-none before:absolute before:left-0 before:top-1/2 before:z-[1] before:h-6 before:-translate-y-1/2 before:w-px before:rounded-full before:bg-transparent before:transition-colors hover:before:bg-[hsl(var(--table-border))] after:pointer-events-none after:absolute after:right-0 after:top-1/2 after:z-[1] after:h-6 after:-translate-y-1/2 after:w-px after:rounded-full after:bg-transparent after:transition-colors hover:after:bg-[hsl(var(--table-border))]", isDragging && "z-10 opacity-90 shadow-lg"),
|
|
293
|
+
gripIcon: disabled ? null : DragGripIcon,
|
|
294
|
+
dragHandleProps: disabled ? {} : { ...attributes, ...listeners },
|
|
295
|
+
});
|
|
296
|
+
}
|
|
278
297
|
const TableColumnResizeHandle = React.forwardRef(function TableColumnResizeHandle({ column, nextColumn, currentWidth, minWidth, maxWidth, onResizeStart, onResizeByKeyboard, className, onClick, ...props }, ref) {
|
|
279
298
|
const label = getColumnResizeLabel(column);
|
|
280
299
|
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) => {
|
|
@@ -365,7 +384,7 @@ function getColumnPairResizeRange(column, nextColumn, columnWidths) {
|
|
|
365
384
|
maxWidth: Math.round(currentWidth + maxDelta),
|
|
366
385
|
};
|
|
367
386
|
}
|
|
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 }) {
|
|
387
|
+
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, reorderableColumns = false, onColumnOrderChange, onScroll, style, ...props }) {
|
|
369
388
|
const visibleColumns = getVisibleColumns(columns, visibleColumnKeys);
|
|
370
389
|
const hasExpansionColumn = Boolean(rowExpansion);
|
|
371
390
|
const hasColumnFilters = visibleColumns.some((column) => column.filter);
|
|
@@ -433,6 +452,24 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
433
452
|
var _a;
|
|
434
453
|
(_a = resizeCleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(resizeCleanupRef);
|
|
435
454
|
}, []);
|
|
455
|
+
const columnReorderSensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }), useSensor(KeyboardSensor, {
|
|
456
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
|
457
|
+
}));
|
|
458
|
+
const handleColumnDragEnd = React.useCallback((event) => {
|
|
459
|
+
const { active, over } = event;
|
|
460
|
+
if (!over || active.id === over.id || !onColumnOrderChange) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const currentKeys = visibleColumns.map((col) => col.key);
|
|
464
|
+
const oldIndex = currentKeys.indexOf(String(active.id));
|
|
465
|
+
const newIndex = currentKeys.indexOf(String(over.id));
|
|
466
|
+
if (oldIndex >= 0 && newIndex >= 0) {
|
|
467
|
+
onColumnOrderChange(arrayMove(currentKeys, oldIndex, newIndex));
|
|
468
|
+
}
|
|
469
|
+
}, [visibleColumns, onColumnOrderChange]);
|
|
470
|
+
const reorderableColumnIds = React.useMemo(() => reorderableColumns
|
|
471
|
+
? visibleColumns.filter((col) => !col.sticky).map((col) => col.key)
|
|
472
|
+
: [], [reorderableColumns, visibleColumns]);
|
|
436
473
|
const commitColumnWidths = React.useCallback((updater) => {
|
|
437
474
|
const nextColumnWidths = updater(columnWidthsRef.current);
|
|
438
475
|
columnWidthsRef.current = nextColumnWidths;
|
|
@@ -584,6 +621,33 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
584
621
|
}
|
|
585
622
|
(_a = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.onExpandedRowKeysChange) === null || _a === void 0 ? void 0 : _a.call(rowExpansion, Array.from(nextExpandedRowKeys));
|
|
586
623
|
}, [controlledExpandedRowKeys, rowExpansion, uncontrolledExpandedRowKeys]);
|
|
624
|
+
function renderColumnHead(column, columnIndex, dragProps) {
|
|
625
|
+
var _a;
|
|
626
|
+
const sortField = (_a = column.sortKey) !== null && _a !== void 0 ? _a : column.key;
|
|
627
|
+
const isSortable = column.sortable && sorting;
|
|
628
|
+
const columnWidth = getRenderedColumnWidth({
|
|
629
|
+
column,
|
|
630
|
+
columnWidths: resolvedColumnWidths,
|
|
631
|
+
resizing: isColumnResizingEnabled,
|
|
632
|
+
});
|
|
633
|
+
const resizeHandle = renderResizeHandle(column, columnIndex);
|
|
634
|
+
if (isSortable) {
|
|
635
|
+
return (_jsx(SortableTableHead, { ref: dragProps === null || dragProps === void 0 ? void 0 : dragProps.ref, field: sortField, currentSortField: sorting.field, currentSortDirection: sorting.direction, onSort: sorting.onSort, className: cn(stickyClassName(column.sticky, "head", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.headerClassName, dragProps === null || dragProps === void 0 ? void 0 : dragProps.className), style: dragProps === null || dragProps === void 0 ? void 0 : dragProps.style, allowWrap: column.wrap, width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), align: column.align, sortLabel: column.sortLabel, resizeHandle: resizeHandle, gripIcon: dragProps === null || dragProps === void 0 ? void 0 : dragProps.gripIcon, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, ...dragProps === null || dragProps === void 0 ? void 0 : dragProps.dragHandleProps, children: column.header }, column.key));
|
|
636
|
+
}
|
|
637
|
+
return (_jsxs(TableHead, { ref: dragProps === null || dragProps === void 0 ? void 0 : dragProps.ref, "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, dragProps === null || dragProps === void 0 ? void 0 : dragProps.className), style: dragProps === null || dragProps === void 0 ? void 0 : dragProps.style, ...dragProps === null || dragProps === void 0 ? void 0 : dragProps.dragHandleProps, children: [dragProps === null || dragProps === void 0 ? void 0 : dragProps.gripIcon, column.header, resizeHandle] }, column.key));
|
|
638
|
+
}
|
|
639
|
+
function renderColumnHeaders(cols) {
|
|
640
|
+
const headers = cols.map((column, columnIndex) => {
|
|
641
|
+
if (!reorderableColumns) {
|
|
642
|
+
return renderColumnHead(column, columnIndex);
|
|
643
|
+
}
|
|
644
|
+
return (_jsx(DraggableColumnHead, { columnKey: column.key, disabled: Boolean(column.sticky), children: (dragProps) => renderColumnHead(column, columnIndex, dragProps) }, column.key));
|
|
645
|
+
});
|
|
646
|
+
if (!reorderableColumns) {
|
|
647
|
+
return headers;
|
|
648
|
+
}
|
|
649
|
+
return (_jsx(DndContext, { sensors: columnReorderSensors, collisionDetection: closestCenter, onDragEnd: handleColumnDragEnd, children: _jsx(SortableContext, { items: reorderableColumnIds, strategy: horizontalListSortingStrategy, children: headers }) }));
|
|
650
|
+
}
|
|
587
651
|
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);
|
|
588
652
|
const container = (_jsxs(TableContainer, { ref: tableContainerRef, role: stickyScrollState.scrollable ? "region" : undefined, "aria-label": stickyScrollState.scrollable
|
|
589
653
|
? `${accessibleLabel} scroll area`
|
|
@@ -610,18 +674,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
610
674
|
minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
|
|
611
675
|
maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
|
|
612
676
|
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
|
|
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) => {
|
|
677
|
+
}) }, 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, renderColumnHeaders(visibleColumns)] }), 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
678
|
const columnWidth = getRenderedColumnWidth({
|
|
626
679
|
column,
|
|
627
680
|
columnWidths: resolvedColumnWidths,
|