@purpurds/table 8.5.2 → 8.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LICENSE.txt +16 -16
- package/dist/styles.css +1 -1
- package/dist/table-content.d.ts +16 -27
- package/dist/table-content.d.ts.map +1 -1
- package/dist/table-settings-drawer.d.ts +4 -1
- package/dist/table-settings-drawer.d.ts.map +1 -1
- package/dist/table.cjs.js +65 -65
- package/dist/table.cjs.js.map +1 -1
- package/dist/table.d.ts.map +1 -1
- package/dist/table.es.js +3320 -3407
- package/dist/table.es.js.map +1 -1
- package/dist/test-utils/helpers.d.ts +39 -0
- package/dist/test-utils/helpers.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/cell-types/date-cell.tsx +1 -1
- package/src/table-content-drag.test.tsx +43 -430
- package/src/table-content.tsx +62 -118
- package/src/table-settings-drawer.module.scss +1 -1
- package/src/table-settings-drawer.test.tsx +62 -0
- package/src/table-settings-drawer.tsx +17 -7
- package/src/table.stories.tsx +16 -1
- package/src/table.tsx +91 -135
- package/src/test-utils/helpers.ts +40 -0
package/src/table-content.tsx
CHANGED
|
@@ -9,137 +9,53 @@ import { EmptyTable } from "./empty-table";
|
|
|
9
9
|
import { LoadingTableRows } from "./loading-table-rows";
|
|
10
10
|
import styles from "./table.module.scss";
|
|
11
11
|
import { TableBody } from "./table-body";
|
|
12
|
-
import { TableHeader } from "./table-header";
|
|
13
12
|
import { TableRow } from "./table-row";
|
|
14
13
|
import { TableRowCell } from "./table-row-cell";
|
|
15
14
|
|
|
16
15
|
const cx = c.bind(styles);
|
|
17
16
|
const rootClassName = "purpur-table";
|
|
18
17
|
|
|
19
|
-
type
|
|
18
|
+
type TableContentProps<TData extends RowData> = {
|
|
20
19
|
tanstackTable: Table<TData>;
|
|
21
20
|
tableRows: Row<TData>[];
|
|
22
|
-
showColumnFiltersEnabled: boolean;
|
|
23
21
|
fullWidth: boolean;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
stickyFirstColumn
|
|
29
|
-
getStickyColumn
|
|
30
|
-
isScrolled
|
|
31
|
-
showBorder
|
|
32
|
-
enableColumnDrag
|
|
33
|
-
activeId
|
|
22
|
+
tableHeader: React.ReactNode;
|
|
23
|
+
loading?: boolean;
|
|
24
|
+
skeletonRows?: number;
|
|
25
|
+
isEmptyTable?: boolean;
|
|
26
|
+
stickyFirstColumn?: boolean;
|
|
27
|
+
getStickyColumn?: (index: number) => boolean;
|
|
28
|
+
isScrolled?: boolean;
|
|
29
|
+
showBorder?: (index: number) => boolean;
|
|
30
|
+
enableColumnDrag?: boolean;
|
|
31
|
+
activeId?: UniqueIdentifier | null;
|
|
32
|
+
getColumnWidths?: () => (string | number)[];
|
|
33
|
+
variant?: "primary" | "secondary";
|
|
34
|
+
emptyTableHeadingTag?: HeadingTagType;
|
|
35
|
+
emptyTableCopy?: { title: string; description: string };
|
|
36
|
+
emptyTableIcon?: React.ReactNode;
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
export function
|
|
39
|
+
export function TableContent<TData extends RowData>({
|
|
40
|
+
tanstackTable,
|
|
37
41
|
tableRows,
|
|
38
|
-
showColumnFiltersEnabled,
|
|
39
42
|
fullWidth,
|
|
40
|
-
|
|
43
|
+
tableHeader,
|
|
44
|
+
loading,
|
|
45
|
+
skeletonRows,
|
|
46
|
+
isEmptyTable,
|
|
41
47
|
stickyFirstColumn,
|
|
42
48
|
getStickyColumn,
|
|
43
49
|
isScrolled,
|
|
44
50
|
showBorder,
|
|
45
51
|
enableColumnDrag,
|
|
46
52
|
activeId,
|
|
47
|
-
}: NormalTableContentProps<TData>) {
|
|
48
|
-
return (
|
|
49
|
-
<table
|
|
50
|
-
className={cx([
|
|
51
|
-
`${rootClassName}__table`,
|
|
52
|
-
{ [`${rootClassName}__table--full-width`]: fullWidth },
|
|
53
|
-
])}
|
|
54
|
-
>
|
|
55
|
-
<TableHeader columnFiltersEnabled={showColumnFiltersEnabled}>
|
|
56
|
-
{renderTableHeaders()}
|
|
57
|
-
</TableHeader>
|
|
58
|
-
<TableBody>
|
|
59
|
-
{tableRows.map((row, rowIndex) => (
|
|
60
|
-
<TableRow key={row.id} isSelected={row.getIsSelected()}>
|
|
61
|
-
{row.getVisibleCells().map((cell, cellIndex) => (
|
|
62
|
-
<TableRowCell
|
|
63
|
-
key={cell.id}
|
|
64
|
-
cell={cell}
|
|
65
|
-
isLastRow={rowIndex === tableRows.length - 1}
|
|
66
|
-
isFirstCell={cellIndex === 0}
|
|
67
|
-
isLastCell={cellIndex === row.getVisibleCells().length - 1}
|
|
68
|
-
stickyColumn={stickyFirstColumn && getStickyColumn(cellIndex)}
|
|
69
|
-
isScrolled={isScrolled}
|
|
70
|
-
showBorder={showBorder(cellIndex)}
|
|
71
|
-
enableColumnDrag={enableColumnDrag || false}
|
|
72
|
-
draggingActive={activeId === cell.column.id}
|
|
73
|
-
/>
|
|
74
|
-
))}
|
|
75
|
-
</TableRow>
|
|
76
|
-
))}
|
|
77
|
-
</TableBody>
|
|
78
|
-
</table>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
type LoadingTableContentProps<TData extends RowData> = BaseTableContentProps<TData> & {
|
|
83
|
-
skeletonRows: number;
|
|
84
|
-
getStickyColumn: (index: number) => boolean;
|
|
85
|
-
stickyFirstColumn: boolean;
|
|
86
|
-
isScrolled: boolean;
|
|
87
|
-
showBorder: (index: number) => boolean;
|
|
88
|
-
getColumnWidths: () => (string | number)[];
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export function LoadingTableContent<TData extends RowData>({
|
|
92
|
-
showColumnFiltersEnabled,
|
|
93
|
-
fullWidth,
|
|
94
|
-
renderTableHeaders,
|
|
95
|
-
skeletonRows,
|
|
96
|
-
getStickyColumn,
|
|
97
|
-
stickyFirstColumn,
|
|
98
|
-
isScrolled,
|
|
99
|
-
showBorder,
|
|
100
53
|
getColumnWidths,
|
|
101
|
-
}: LoadingTableContentProps<TData>) {
|
|
102
|
-
return (
|
|
103
|
-
<table
|
|
104
|
-
className={cx([
|
|
105
|
-
`${rootClassName}__table`,
|
|
106
|
-
{ [`${rootClassName}__table--full-width`]: fullWidth },
|
|
107
|
-
])}
|
|
108
|
-
>
|
|
109
|
-
<TableHeader columnFiltersEnabled={showColumnFiltersEnabled}>
|
|
110
|
-
{renderTableHeaders()}
|
|
111
|
-
</TableHeader>
|
|
112
|
-
<TableBody>
|
|
113
|
-
<LoadingTableRows
|
|
114
|
-
rowCount={skeletonRows}
|
|
115
|
-
getStickyColumn={getStickyColumn}
|
|
116
|
-
stickyFirstColumn={stickyFirstColumn}
|
|
117
|
-
isScrolled={isScrolled}
|
|
118
|
-
cellWidths={getColumnWidths()}
|
|
119
|
-
showBorder={showBorder}
|
|
120
|
-
/>
|
|
121
|
-
</TableBody>
|
|
122
|
-
</table>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
type EmptyTableContentProps<TData extends RowData> = BaseTableContentProps<TData> & {
|
|
127
|
-
variant: "primary" | "secondary";
|
|
128
|
-
emptyTableHeadingTag: HeadingTagType;
|
|
129
|
-
emptyTableCopy: { title: string; description: string };
|
|
130
|
-
emptyTableIcon?: React.ReactNode;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export function EmptyTableContent<TData extends RowData>({
|
|
134
|
-
tanstackTable,
|
|
135
|
-
showColumnFiltersEnabled,
|
|
136
|
-
fullWidth,
|
|
137
|
-
renderTableHeaders,
|
|
138
54
|
variant,
|
|
139
55
|
emptyTableHeadingTag,
|
|
140
56
|
emptyTableCopy,
|
|
141
57
|
emptyTableIcon,
|
|
142
|
-
}:
|
|
58
|
+
}: TableContentProps<TData>) {
|
|
143
59
|
return (
|
|
144
60
|
<table
|
|
145
61
|
className={cx([
|
|
@@ -147,18 +63,46 @@ export function EmptyTableContent<TData extends RowData>({
|
|
|
147
63
|
{ [`${rootClassName}__table--full-width`]: fullWidth },
|
|
148
64
|
])}
|
|
149
65
|
>
|
|
150
|
-
|
|
151
|
-
{renderTableHeaders()}
|
|
152
|
-
</TableHeader>
|
|
66
|
+
{tableHeader}
|
|
153
67
|
<TableBody>
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
68
|
+
{loading && skeletonRows ? (
|
|
69
|
+
<LoadingTableRows
|
|
70
|
+
rowCount={skeletonRows}
|
|
71
|
+
getStickyColumn={getStickyColumn!}
|
|
72
|
+
stickyFirstColumn={stickyFirstColumn!}
|
|
73
|
+
isScrolled={isScrolled!}
|
|
74
|
+
cellWidths={getColumnWidths!()}
|
|
75
|
+
showBorder={showBorder!}
|
|
76
|
+
/>
|
|
77
|
+
) : isEmptyTable && emptyTableCopy && emptyTableHeadingTag ? (
|
|
78
|
+
<EmptyTable
|
|
79
|
+
variant={variant!}
|
|
80
|
+
tag={emptyTableHeadingTag}
|
|
81
|
+
title={emptyTableCopy.title}
|
|
82
|
+
description={emptyTableCopy.description}
|
|
83
|
+
colSpan={tanstackTable.getVisibleLeafColumns().length}
|
|
84
|
+
icon={emptyTableIcon}
|
|
85
|
+
/>
|
|
86
|
+
) : (
|
|
87
|
+
tableRows.map((row, rowIndex) => (
|
|
88
|
+
<TableRow key={row.id} isSelected={row.getIsSelected()}>
|
|
89
|
+
{row.getVisibleCells().map((cell, cellIndex) => (
|
|
90
|
+
<TableRowCell
|
|
91
|
+
key={cell.id}
|
|
92
|
+
cell={cell}
|
|
93
|
+
isLastRow={rowIndex === tableRows.length - 1}
|
|
94
|
+
isFirstCell={cellIndex === 0}
|
|
95
|
+
isLastCell={cellIndex === row.getVisibleCells().length - 1}
|
|
96
|
+
stickyColumn={stickyFirstColumn && getStickyColumn!(cellIndex)}
|
|
97
|
+
isScrolled={isScrolled!}
|
|
98
|
+
showBorder={showBorder!(cellIndex)}
|
|
99
|
+
enableColumnDrag={enableColumnDrag || false}
|
|
100
|
+
draggingActive={activeId === cell.column.id}
|
|
101
|
+
/>
|
|
102
|
+
))}
|
|
103
|
+
</TableRow>
|
|
104
|
+
))
|
|
105
|
+
)}
|
|
162
106
|
</TableBody>
|
|
163
107
|
</table>
|
|
164
108
|
);
|
|
@@ -248,4 +248,66 @@ describe("Data Table - Settings drawer", () => {
|
|
|
248
248
|
});
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
|
+
|
|
252
|
+
describe("Column drag enabled", () => {
|
|
253
|
+
const onColumnOrderChangeMock = vi.fn();
|
|
254
|
+
let withinDrawerContent: ReturnType<typeof within>;
|
|
255
|
+
|
|
256
|
+
beforeEach(() => {
|
|
257
|
+
render(
|
|
258
|
+
<TableSettingsDrawer
|
|
259
|
+
id="purpur-table-settings-drawer"
|
|
260
|
+
isDrawerOpen={true}
|
|
261
|
+
showColumnFilters={true}
|
|
262
|
+
columnFiltersEnabled={true}
|
|
263
|
+
stickyFirstColumn={true}
|
|
264
|
+
stickyHeaders={true}
|
|
265
|
+
copy={copy.settingsDrawerWithColumnDrag}
|
|
266
|
+
setDrawerIsOpen={setDrawerIsOpenMock}
|
|
267
|
+
setShowColumnFiltersEnabled={setColumnFiltersEnabledMock}
|
|
268
|
+
setStickyFirstColumn={setStickyFirstColumnMock}
|
|
269
|
+
setStickyHeaders={setStickyHeadersMock}
|
|
270
|
+
getAllColumns={getAllColumnsMock}
|
|
271
|
+
onResetSettings={onResetSettingsMock}
|
|
272
|
+
enableColumnDrag={true}
|
|
273
|
+
onColumnOrderChange={onColumnOrderChangeMock}
|
|
274
|
+
columnOrder={["column_1", "column_2", "column_3"]}
|
|
275
|
+
/>
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
withinDrawerContent = within(screen.getByTestId(Selectors.SETTINGS_DRAWER.CONTENT));
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
describe("Visible columns with rearrange mode", () => {
|
|
282
|
+
let withinVisibleColumns: ReturnType<typeof within>;
|
|
283
|
+
|
|
284
|
+
beforeEach(() => {
|
|
285
|
+
withinVisibleColumns = within(
|
|
286
|
+
withinDrawerContent.getByTestId(Selectors.SETTINGS_DRAWER.VISIBLE_COLUMNS)
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("should have a rearrange button", () => {
|
|
291
|
+
const rearrangeButton = withinVisibleColumns.getByRole("button", {
|
|
292
|
+
name: copy.settingsDrawerWithColumnDrag.visibleColumns.ariaLabels.buttons.rearrange,
|
|
293
|
+
});
|
|
294
|
+
expect(rearrangeButton).toBeInTheDocument();
|
|
295
|
+
expect(rearrangeButton).toHaveTextContent(copy.settingsDrawerWithColumnDrag.visibleColumns.buttons.rearrange);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("should update aria-label when entering rearrange mode", async () => {
|
|
299
|
+
const rearrangeButton = withinVisibleColumns.getByRole("button", {
|
|
300
|
+
name: copy.settingsDrawerWithColumnDrag.visibleColumns.ariaLabels.buttons.rearrange,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
await userEvent.click(rearrangeButton);
|
|
304
|
+
|
|
305
|
+
const doneButton = withinVisibleColumns.getByRole("button", {
|
|
306
|
+
name: copy.settingsDrawerWithColumnDrag.visibleColumns.ariaLabels.buttons.done,
|
|
307
|
+
});
|
|
308
|
+
expect(doneButton).toBeInTheDocument();
|
|
309
|
+
expect(doneButton).toHaveTextContent(copy.settingsDrawerWithColumnDrag.visibleColumns.buttons.done);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
});
|
|
251
313
|
});
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
purpurMotionDuration150,
|
|
35
35
|
purpurMotionEasingEaseInOut,
|
|
36
36
|
} from "@purpurds/tokens/motion/variables";
|
|
37
|
+
import { VisuallyHidden } from "@purpurds/visually-hidden";
|
|
37
38
|
import { type Column, type RowData } from "@tanstack/react-table";
|
|
38
39
|
import c from "classnames/bind";
|
|
39
40
|
|
|
@@ -80,7 +81,10 @@ type VisibleColumnsWithColumnDragCopyProps = VisibleColumnsCopyBaseProps & {
|
|
|
80
81
|
up: string;
|
|
81
82
|
down: string;
|
|
82
83
|
};
|
|
83
|
-
|
|
84
|
+
buttons: {
|
|
85
|
+
rearrange: string;
|
|
86
|
+
done: string;
|
|
87
|
+
};
|
|
84
88
|
};
|
|
85
89
|
};
|
|
86
90
|
|
|
@@ -358,7 +362,11 @@ const VisibleColumns = <TData extends RowData>({
|
|
|
358
362
|
variant={isRearrangeMode ? "primary" : "tertiary-purple"}
|
|
359
363
|
onClick={() => setIsRearrangeMode((v) => !v)}
|
|
360
364
|
data-testid={`${rootTestId}-rearrange-button`}
|
|
361
|
-
aria-label={
|
|
365
|
+
aria-label={
|
|
366
|
+
isRearrangeMode
|
|
367
|
+
? copy.visibleColumns.ariaLabels.buttons.done
|
|
368
|
+
: copy.visibleColumns.ariaLabels.buttons.rearrange
|
|
369
|
+
}
|
|
362
370
|
>
|
|
363
371
|
<IconSorter size="xs" />
|
|
364
372
|
{isRearrangeMode
|
|
@@ -476,13 +484,15 @@ const DraggableColumnItem = ({
|
|
|
476
484
|
})}
|
|
477
485
|
{...listeners}
|
|
478
486
|
{...attributes}
|
|
487
|
+
aria-label={`${copy.visibleColumns.ariaLabels.dragHandle.action} ${label}`}
|
|
488
|
+
aria-describedby={`drag-instructions-${id}`}
|
|
479
489
|
>
|
|
480
|
-
<IconDragVertical
|
|
481
|
-
className={cx(`${rootClassName}__draggable-handle-icon`, "terre")}
|
|
482
|
-
size="sm"
|
|
483
|
-
/>
|
|
490
|
+
<IconDragVertical className={cx(`${rootClassName}__draggable-handle-icon`)} size="sm" />
|
|
484
491
|
</div>
|
|
485
|
-
<
|
|
492
|
+
<Paragraph>{label}</Paragraph>
|
|
493
|
+
<VisuallyHidden id={`drag-instructions-${id}`}>
|
|
494
|
+
{copy.visibleColumns.ariaLabels.dragHandle.instructions}
|
|
495
|
+
</VisuallyHidden>
|
|
486
496
|
</div>
|
|
487
497
|
|
|
488
498
|
<div className={cx(`${rootClassName}__draggable-item-buttons`)}>
|
package/src/table.stories.tsx
CHANGED
|
@@ -274,7 +274,10 @@ const commonSettingsDrawerCopyWithColumnDrag = {
|
|
|
274
274
|
up: "up",
|
|
275
275
|
down: "down",
|
|
276
276
|
},
|
|
277
|
-
|
|
277
|
+
buttons: {
|
|
278
|
+
rearrange: "Reorder columns",
|
|
279
|
+
done: "Save column order and exit reorder mode",
|
|
280
|
+
},
|
|
278
281
|
},
|
|
279
282
|
},
|
|
280
283
|
};
|
|
@@ -324,6 +327,7 @@ export const Showcase: StoryTableData = {
|
|
|
324
327
|
stickyHeaders: true,
|
|
325
328
|
enableColumnDrag: true,
|
|
326
329
|
onColumnOrderChange: () => {},
|
|
330
|
+
columnDragAriaLabelsCopy: commonColumnDragAriaLabels,
|
|
327
331
|
},
|
|
328
332
|
parameters: {
|
|
329
333
|
docs: {
|
|
@@ -399,6 +403,14 @@ manages filtering, sorting and pagination internally.
|
|
|
399
403
|
stepNumberPrefix: "Go to page",
|
|
400
404
|
};
|
|
401
405
|
|
|
406
|
+
const emptyTableProps = {
|
|
407
|
+
emptyTableCopy: {
|
|
408
|
+
title: args.emptyTableCopy?.title || "No data found",
|
|
409
|
+
description: args.emptyTableCopy?.description || "There are no items to display.",
|
|
410
|
+
},
|
|
411
|
+
emptyTableHeadingTag: args.emptyTableHeadingTag || "h2",
|
|
412
|
+
};
|
|
413
|
+
|
|
402
414
|
return renderTableContainer(
|
|
403
415
|
{ ...args, isExpanded: tableExpanded },
|
|
404
416
|
/* @ts-expect-error Props are incompatible. Storybook issue after adding argTypes. */
|
|
@@ -442,6 +454,9 @@ manages filtering, sorting and pagination internally.
|
|
|
442
454
|
stickyHeaders={args.stickyHeaders}
|
|
443
455
|
enableColumnDrag={args.enableColumnDrag}
|
|
444
456
|
columnDragAriaLabelsCopy={commonColumnDragAriaLabels}
|
|
457
|
+
emptyTableCopy={emptyTableProps.emptyTableCopy}
|
|
458
|
+
emptyTableHeadingTag={emptyTableProps.emptyTableHeadingTag}
|
|
459
|
+
emptyTableIcon={<IllustrativeIconTableQuestionDuocolorStatic />}
|
|
445
460
|
/>
|
|
446
461
|
);
|
|
447
462
|
},
|
package/src/table.tsx
CHANGED
|
@@ -38,8 +38,9 @@ export type {
|
|
|
38
38
|
|
|
39
39
|
import styles from "./table.module.scss";
|
|
40
40
|
import { TableActionBar } from "./table-action-bar";
|
|
41
|
-
import {
|
|
41
|
+
import { TableContent } from "./table-content";
|
|
42
42
|
import { TableExportDrawer } from "./table-export-drawer";
|
|
43
|
+
import { TableHeader } from "./table-header";
|
|
43
44
|
import { SortableTableHeaders, StandardTableHeaders } from "./table-headers";
|
|
44
45
|
import { TableSettingsDrawer, type TableSettingsDrawerCopyProps } from "./table-settings-drawer";
|
|
45
46
|
import { TableToolbar } from "./table-toolbar";
|
|
@@ -140,12 +141,12 @@ export const Table = <TData extends RowData>({
|
|
|
140
141
|
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
|
|
141
142
|
|
|
142
143
|
const classes = cx([
|
|
143
|
-
className,
|
|
144
144
|
rootClassName,
|
|
145
145
|
{
|
|
146
146
|
[`${rootClassName}--${variant}`]: variant,
|
|
147
147
|
[`${rootClassName}--without-toolbar`]: !enableToolbar || !settingsDrawerCopy,
|
|
148
148
|
},
|
|
149
|
+
className,
|
|
149
150
|
]);
|
|
150
151
|
|
|
151
152
|
// Only add row selection columns when enableRowSelection is true
|
|
@@ -316,140 +317,95 @@ export const Table = <TData extends RowData>({
|
|
|
316
317
|
const emptyTable = tableRows.length === 0 && Boolean(emptyTableCopy);
|
|
317
318
|
|
|
318
319
|
const memoizedGetColumnWidths = React.useCallback(() => {
|
|
319
|
-
return tanstackTable.
|
|
320
|
+
return tanstackTable.getVisibleLeafColumns().map((column) => column.getSize() || "100%");
|
|
320
321
|
}, [tanstackTable]);
|
|
321
322
|
|
|
322
|
-
//
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (loading && skeletonRows) {
|
|
384
|
-
return (
|
|
385
|
-
<LoadingTableContent
|
|
386
|
-
tanstackTable={tanstackTable}
|
|
387
|
-
tableRows={tableRows}
|
|
388
|
-
showColumnFiltersEnabled={showColumnFiltersEnabled}
|
|
389
|
-
fullWidth={fullWidth}
|
|
390
|
-
renderTableHeaders={renderTableHeaders}
|
|
391
|
-
skeletonRows={skeletonRows}
|
|
392
|
-
getStickyColumn={getStickyColumn}
|
|
393
|
-
stickyFirstColumn={stickyFirstColumn}
|
|
394
|
-
isScrolled={isScrolled}
|
|
395
|
-
showBorder={showBorder}
|
|
396
|
-
getColumnWidths={memoizedGetColumnWidths}
|
|
397
|
-
/>
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const isEmptyTable = tableRows.length === 0 && Boolean(emptyTableCopy);
|
|
402
|
-
if (isEmptyTable && emptyTableCopy && emptyTableHeadingTag) {
|
|
403
|
-
return (
|
|
404
|
-
<EmptyTableContent
|
|
405
|
-
tanstackTable={tanstackTable}
|
|
406
|
-
tableRows={tableRows}
|
|
407
|
-
showColumnFiltersEnabled={showColumnFiltersEnabled}
|
|
408
|
-
fullWidth={fullWidth}
|
|
409
|
-
renderTableHeaders={renderTableHeaders}
|
|
410
|
-
variant={variant}
|
|
411
|
-
emptyTableHeadingTag={emptyTableHeadingTag}
|
|
412
|
-
emptyTableCopy={emptyTableCopy}
|
|
413
|
-
emptyTableIcon={emptyTableIcon}
|
|
414
|
-
/>
|
|
415
|
-
);
|
|
416
|
-
}
|
|
323
|
+
// Extract header groups to avoid complex expression in dependency array
|
|
324
|
+
const headerGroups = tanstackTable.getHeaderGroups();
|
|
325
|
+
|
|
326
|
+
// Memoized table header to prevent re-renders and maintain filter focus
|
|
327
|
+
const tableHeader = React.useMemo(
|
|
328
|
+
() => (
|
|
329
|
+
<TableHeader columnFiltersEnabled={showColumnFiltersEnabled}>
|
|
330
|
+
{headerGroups.map((headerGroup) => {
|
|
331
|
+
if (enableColumnDrag && state?.columnOrder) {
|
|
332
|
+
return (
|
|
333
|
+
<SortableTableHeaders
|
|
334
|
+
key={headerGroup.id}
|
|
335
|
+
headerGroup={headerGroup}
|
|
336
|
+
tanstackTable={tanstackTable}
|
|
337
|
+
tableHasFilters={showColumnFiltersEnabled}
|
|
338
|
+
emptyTable={emptyTable}
|
|
339
|
+
stickyFirstColumn={stickyFirstColumn}
|
|
340
|
+
stickyHeaders={stickyHeaders}
|
|
341
|
+
isScrolled={isScrolled}
|
|
342
|
+
getStickyColumn={getStickyColumn}
|
|
343
|
+
showBorder={showBorder}
|
|
344
|
+
enableSorting={props.enableSorting || false}
|
|
345
|
+
sortingAriaLabels={sortingAriaLabels}
|
|
346
|
+
columnOrder={state.columnOrder}
|
|
347
|
+
activeId={activeId}
|
|
348
|
+
enableColumnDrag={enableColumnDrag}
|
|
349
|
+
columnDragAriaLabelsCopy={columnDragAriaLabelsCopy}
|
|
350
|
+
/>
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return (
|
|
355
|
+
<StandardTableHeaders
|
|
356
|
+
key={headerGroup.id}
|
|
357
|
+
headerGroup={headerGroup}
|
|
358
|
+
tanstackTable={tanstackTable}
|
|
359
|
+
tableHasFilters={showColumnFiltersEnabled}
|
|
360
|
+
emptyTable={emptyTable}
|
|
361
|
+
stickyFirstColumn={stickyFirstColumn}
|
|
362
|
+
stickyHeaders={stickyHeaders}
|
|
363
|
+
isScrolled={isScrolled}
|
|
364
|
+
getStickyColumn={getStickyColumn}
|
|
365
|
+
showBorder={showBorder}
|
|
366
|
+
enableSorting={props.enableSorting || false}
|
|
367
|
+
sortingAriaLabels={sortingAriaLabels}
|
|
368
|
+
/>
|
|
369
|
+
);
|
|
370
|
+
})}
|
|
371
|
+
</TableHeader>
|
|
372
|
+
),
|
|
373
|
+
[
|
|
374
|
+
showColumnFiltersEnabled,
|
|
375
|
+
headerGroups,
|
|
376
|
+
enableColumnDrag,
|
|
377
|
+
state?.columnOrder,
|
|
378
|
+
props.enableSorting,
|
|
379
|
+
sortingAriaLabels,
|
|
380
|
+
columnDragAriaLabelsCopy,
|
|
381
|
+
tanstackTable,
|
|
382
|
+
]
|
|
383
|
+
);
|
|
417
384
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
loading,
|
|
443
|
-
memoizedGetColumnWidths,
|
|
444
|
-
renderTableHeaders,
|
|
445
|
-
showBorder,
|
|
446
|
-
showColumnFiltersEnabled,
|
|
447
|
-
skeletonRows,
|
|
448
|
-
stickyFirstColumn,
|
|
449
|
-
tableRows,
|
|
450
|
-
tanstackTable,
|
|
451
|
-
variant,
|
|
452
|
-
]);
|
|
385
|
+
const isEmptyTable = tableRows.length === 0 && Boolean(emptyTableCopy);
|
|
386
|
+
|
|
387
|
+
const tableContent = (
|
|
388
|
+
<TableContent
|
|
389
|
+
tanstackTable={tanstackTable}
|
|
390
|
+
tableRows={tableRows}
|
|
391
|
+
fullWidth={fullWidth}
|
|
392
|
+
tableHeader={tableHeader}
|
|
393
|
+
loading={loading}
|
|
394
|
+
skeletonRows={skeletonRows}
|
|
395
|
+
isEmptyTable={isEmptyTable}
|
|
396
|
+
stickyFirstColumn={stickyFirstColumn}
|
|
397
|
+
getStickyColumn={getStickyColumn}
|
|
398
|
+
isScrolled={isScrolled}
|
|
399
|
+
showBorder={showBorder}
|
|
400
|
+
enableColumnDrag={enableColumnDrag}
|
|
401
|
+
activeId={activeId}
|
|
402
|
+
getColumnWidths={memoizedGetColumnWidths}
|
|
403
|
+
variant={variant}
|
|
404
|
+
emptyTableHeadingTag={emptyTableHeadingTag}
|
|
405
|
+
emptyTableCopy={emptyTableCopy}
|
|
406
|
+
emptyTableIcon={emptyTableIcon}
|
|
407
|
+
/>
|
|
408
|
+
);
|
|
453
409
|
|
|
454
410
|
return (
|
|
455
411
|
<div id={`${uid}-table`} className={classes}>
|
|
@@ -491,10 +447,10 @@ export const Table = <TData extends RowData>({
|
|
|
491
447
|
columnDragAriaLabelsCopy={columnDragAriaLabelsCopy}
|
|
492
448
|
rootClassName={rootClassName}
|
|
493
449
|
>
|
|
494
|
-
{
|
|
450
|
+
{tableContent}
|
|
495
451
|
</DraggableTable>
|
|
496
452
|
) : (
|
|
497
|
-
|
|
453
|
+
tableContent
|
|
498
454
|
)}
|
|
499
455
|
</div>
|
|
500
456
|
{paginationComponent}
|