@purpurds/table 6.12.5 → 7.0.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/cell-types/body-text-cell.d.ts.map +1 -1
- package/dist/cell-types/link-cell.d.ts.map +1 -1
- package/dist/story-utils/column-def.d.ts.map +1 -1
- package/dist/story-utils/table-data.d.ts +2 -4
- package/dist/story-utils/table-data.d.ts.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/table-action-bar.d.ts.map +1 -1
- package/dist/table-export-drawer.d.ts +3 -2
- package/dist/table-export-drawer.d.ts.map +1 -1
- package/dist/table-row-cell.d.ts.map +1 -1
- package/dist/table-settings-drawer.d.ts +2 -1
- package/dist/table-settings-drawer.d.ts.map +1 -1
- package/dist/table-toolbar.d.ts +6 -4
- package/dist/table-toolbar.d.ts.map +1 -1
- package/dist/table.cjs.js +63 -63
- package/dist/table.cjs.js.map +1 -1
- package/dist/table.d.ts +2 -1
- package/dist/table.d.ts.map +1 -1
- package/dist/table.es.js +3930 -3932
- package/dist/table.es.js.map +1 -1
- package/dist/test-utils/helpers.d.ts +2 -1
- package/dist/test-utils/helpers.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/use-truncated-hook.d.ts +3 -5
- package/dist/use-truncated-hook.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/cell-types/body-text-cell.tsx +7 -8
- package/src/cell-types/link-cell.tsx +13 -6
- package/src/story-utils/column-def.ts +2 -0
- package/src/story-utils/table-data.tsx +10 -8
- package/src/table-action-bar.tsx +3 -2
- package/src/table-column-header-cell.tsx +16 -6
- package/src/table-export-drawer.test.tsx +1 -0
- package/src/table-export-drawer.tsx +5 -3
- package/src/table-kitchen-sink.test.tsx +5 -18
- package/src/table-row-cell.tsx +1 -30
- package/src/table-settings-drawer.test.tsx +4 -0
- package/src/table-settings-drawer.tsx +46 -41
- package/src/table-toolbar.test.tsx +3 -0
- package/src/table-toolbar.tsx +12 -7
- package/src/table.module.scss +27 -18
- package/src/table.stories.tsx +10 -9
- package/src/table.tsx +32 -26
- package/src/test-utils/helpers.ts +2 -1
- package/src/types.ts +1 -1
- package/src/use-truncated-hook.tsx +16 -60
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useId } from "react";
|
|
2
2
|
import { Button } from "@purpurds/button";
|
|
3
3
|
import { Drawer } from "@purpurds/drawer";
|
|
4
4
|
import { Heading } from "@purpurds/heading";
|
|
@@ -30,6 +30,7 @@ export type TableSettingsDrawerCopyProps = {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
export type TableSettingsDrawerProps<TData> = {
|
|
33
|
+
id: string;
|
|
33
34
|
getAllColumns: () => Column<TData, unknown>[];
|
|
34
35
|
onResetSettings: () => void;
|
|
35
36
|
setDrawerIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
@@ -52,6 +53,7 @@ const cx = c.bind(styles);
|
|
|
52
53
|
const rootTestId = "purpur-table-settings-drawer";
|
|
53
54
|
|
|
54
55
|
export const TableSettingsDrawer = <TData extends RowData>({
|
|
56
|
+
id,
|
|
55
57
|
columnFiltersEnabled,
|
|
56
58
|
copy,
|
|
57
59
|
isDrawerOpen,
|
|
@@ -69,12 +71,12 @@ export const TableSettingsDrawer = <TData extends RowData>({
|
|
|
69
71
|
setRowSelectionEnabled,
|
|
70
72
|
}: TableSettingsDrawerProps<TData>) => {
|
|
71
73
|
return (
|
|
72
|
-
<div id=
|
|
74
|
+
<div id={id}>
|
|
73
75
|
<Drawer data-testid={rootTestId} open={isDrawerOpen} onOpenChange={setDrawerIsOpen}>
|
|
74
76
|
<Drawer.Content
|
|
75
77
|
data-testid={`${rootTestId}-content`}
|
|
76
78
|
zIndex={6}
|
|
77
|
-
|
|
79
|
+
closeButtonAriaLabel={copy.buttons.closeDrawer}
|
|
78
80
|
title={copy.title}
|
|
79
81
|
footerContent={
|
|
80
82
|
<FooterContent text={copy.buttons.resetSettings} onClick={onResetSettings} />
|
|
@@ -147,45 +149,48 @@ const GeneralSettings = ({
|
|
|
147
149
|
enableRowSelection,
|
|
148
150
|
rowSelectionEnabled,
|
|
149
151
|
setRowSelectionEnabled,
|
|
150
|
-
}: GeneralSettingsProps) =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
152
|
+
}: GeneralSettingsProps) => {
|
|
153
|
+
const uid = useId();
|
|
154
|
+
return (
|
|
155
|
+
<div
|
|
156
|
+
data-testid={`${rootTestId}-general-settings`}
|
|
157
|
+
className={cx(`${rootClassName}__general-settings`)}
|
|
158
|
+
aria-labelledby={`${uid}-general-settings`}
|
|
159
|
+
>
|
|
160
|
+
<Heading id={`${uid}-general-settings`} variant="title-100" tag="h3">
|
|
161
|
+
{copy.header}
|
|
162
|
+
</Heading>
|
|
163
|
+
{columnFiltersEnabled && (
|
|
164
|
+
<ToggleWrapper
|
|
165
|
+
id={`${uid}-show-filters`}
|
|
166
|
+
checked={showColumnFilters}
|
|
167
|
+
label={copy.toggles.showFilters}
|
|
168
|
+
onChange={setShowColumnFiltersEnabled}
|
|
169
|
+
/>
|
|
170
|
+
)}
|
|
160
171
|
<ToggleWrapper
|
|
161
|
-
id=
|
|
162
|
-
checked={
|
|
163
|
-
label={copy.toggles.
|
|
164
|
-
onChange={
|
|
172
|
+
id={`${uid}-lock-first-column`}
|
|
173
|
+
checked={stickyFirstColumn}
|
|
174
|
+
label={copy.toggles.lockFirstcolumn}
|
|
175
|
+
onChange={setStickyFirstColumn}
|
|
165
176
|
/>
|
|
166
|
-
)}
|
|
167
|
-
<ToggleWrapper
|
|
168
|
-
id="lock-first-column"
|
|
169
|
-
checked={stickyFirstColumn}
|
|
170
|
-
label={copy.toggles.lockFirstcolumn}
|
|
171
|
-
onChange={setStickyFirstColumn}
|
|
172
|
-
/>
|
|
173
|
-
<ToggleWrapper
|
|
174
|
-
id="sticky-header"
|
|
175
|
-
checked={stickyHeaders}
|
|
176
|
-
label={copy.toggles.stickyHeader}
|
|
177
|
-
onChange={setStickyHeaders}
|
|
178
|
-
/>
|
|
179
|
-
{enableRowSelection && copy.toggles.rowSelection && setRowSelectionEnabled && (
|
|
180
177
|
<ToggleWrapper
|
|
181
|
-
id=
|
|
182
|
-
checked={
|
|
183
|
-
label={copy.toggles.
|
|
184
|
-
onChange={
|
|
178
|
+
id={`${uid}-sticky-header`}
|
|
179
|
+
checked={stickyHeaders}
|
|
180
|
+
label={copy.toggles.stickyHeader}
|
|
181
|
+
onChange={setStickyHeaders}
|
|
185
182
|
/>
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
183
|
+
{enableRowSelection && copy.toggles.rowSelection && setRowSelectionEnabled && (
|
|
184
|
+
<ToggleWrapper
|
|
185
|
+
id={`${uid}-row-selection`}
|
|
186
|
+
checked={rowSelectionEnabled || false}
|
|
187
|
+
label={copy.toggles.rowSelection}
|
|
188
|
+
onChange={setRowSelectionEnabled}
|
|
189
|
+
/>
|
|
190
|
+
)}
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
};
|
|
189
194
|
|
|
190
195
|
const VisibleColumns = <TData extends RowData>({
|
|
191
196
|
header,
|
|
@@ -204,14 +209,14 @@ const VisibleColumns = <TData extends RowData>({
|
|
|
204
209
|
const isDisabled = (column: Column<TData, unknown>) => {
|
|
205
210
|
return !column.getCanHide() || (visible.length === 1 && visible.includes(column));
|
|
206
211
|
};
|
|
207
|
-
|
|
212
|
+
const uid = useId();
|
|
208
213
|
return (
|
|
209
214
|
<section
|
|
210
215
|
data-testid={`${rootTestId}-visible-columns`}
|
|
211
216
|
className={cx(`${rootClassName}__visible-columns`)}
|
|
212
|
-
aria-labelledby=
|
|
217
|
+
aria-labelledby={`${uid}-visible-columns`}
|
|
213
218
|
>
|
|
214
|
-
<Heading id=
|
|
219
|
+
<Heading id={`${uid}-visible-columns`} variant="title-100" tag="h3">
|
|
215
220
|
{header}
|
|
216
221
|
</Heading>
|
|
217
222
|
{filteredColumns.map((column) => (
|
|
@@ -20,6 +20,9 @@ describe("Data table - Tool bar", () => {
|
|
|
20
20
|
// Needs an element with id purpur-table for the ally tests to not fail with "ARIA attributes must conform to valid values (aria-valid-attr-value)" rule
|
|
21
21
|
<div id="purpur-table">
|
|
22
22
|
<TableToolbar
|
|
23
|
+
aria-controls="purpur-table"
|
|
24
|
+
settingsDrawerAriaControls="purpur-table-settings-drawer"
|
|
25
|
+
exportDrawerAriaControls="purpur-table-export-drawer"
|
|
23
26
|
onResetColumnFilters={resetColumnFiltersMock}
|
|
24
27
|
onSetDrawerIsOpen={setDrawerIsOpenMock}
|
|
25
28
|
onToggleExpand={toggleExpandMock}
|
package/src/table-toolbar.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { type Dispatch, type HTMLAttributes, type SetStateAction } from "react";
|
|
2
2
|
import { Button } from "@purpurds/button";
|
|
3
3
|
import { IconDownload } from "@purpurds/icon/download";
|
|
4
4
|
import { IconMaximize } from "@purpurds/icon/maximize";
|
|
@@ -28,8 +28,8 @@ export type TableToolbarCopyProps = {
|
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export type TableToolbarProps = {
|
|
32
|
-
onSetDrawerIsOpen:
|
|
31
|
+
export type TableToolbarProps = HTMLAttributes<HTMLDivElement> & {
|
|
32
|
+
onSetDrawerIsOpen: Dispatch<SetStateAction<boolean>>;
|
|
33
33
|
onResetColumnFilters: () => void;
|
|
34
34
|
onToggleExpand?: () => void;
|
|
35
35
|
onExportData?: () => void;
|
|
@@ -41,6 +41,8 @@ export type TableToolbarProps = {
|
|
|
41
41
|
hasExportsDrawer: boolean;
|
|
42
42
|
showFilters: boolean;
|
|
43
43
|
disableClearFilters: boolean;
|
|
44
|
+
settingsDrawerAriaControls: string;
|
|
45
|
+
exportDrawerAriaControls: string;
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
const rootClassName = "purpur-table-toolbar";
|
|
@@ -48,6 +50,9 @@ const cx = c.bind(styles);
|
|
|
48
50
|
const rootTestId = "purpur-table-toolbar";
|
|
49
51
|
|
|
50
52
|
export const TableToolbar = ({
|
|
53
|
+
["aria-controls"]: ariaControls,
|
|
54
|
+
settingsDrawerAriaControls,
|
|
55
|
+
exportDrawerAriaControls,
|
|
51
56
|
onExportData,
|
|
52
57
|
onResetColumnFilters,
|
|
53
58
|
onSetDrawerIsOpen,
|
|
@@ -76,7 +81,7 @@ export const TableToolbar = ({
|
|
|
76
81
|
onClick={onResetColumnFilters}
|
|
77
82
|
type="button"
|
|
78
83
|
aria-label={copy?.ariaLabels?.clearFilters}
|
|
79
|
-
aria-controls=
|
|
84
|
+
aria-controls={ariaControls}
|
|
80
85
|
disabled={disableClearFilters}
|
|
81
86
|
>
|
|
82
87
|
{copy.buttons.clearFilters}
|
|
@@ -94,7 +99,7 @@ export const TableToolbar = ({
|
|
|
94
99
|
aria-label={copy?.ariaLabels?.export}
|
|
95
100
|
{...(hasExportsDrawer && {
|
|
96
101
|
"aria-expanded": isExportDrawerOpen,
|
|
97
|
-
"aria-controls":
|
|
102
|
+
"aria-controls": exportDrawerAriaControls,
|
|
98
103
|
"aria-haspopup": "dialog",
|
|
99
104
|
})}
|
|
100
105
|
>
|
|
@@ -110,7 +115,7 @@ export const TableToolbar = ({
|
|
|
110
115
|
type="button"
|
|
111
116
|
aria-label={copy?.ariaLabels?.settings}
|
|
112
117
|
aria-expanded={isSettingsDrawerOpen}
|
|
113
|
-
aria-controls=
|
|
118
|
+
aria-controls={settingsDrawerAriaControls}
|
|
114
119
|
aria-haspopup="dialog"
|
|
115
120
|
>
|
|
116
121
|
<IconSettings size="xs" />
|
|
@@ -124,7 +129,7 @@ export const TableToolbar = ({
|
|
|
124
129
|
onClick={() => onToggleExpand()}
|
|
125
130
|
type="button"
|
|
126
131
|
aria-label={copy?.ariaLabels?.expand}
|
|
127
|
-
aria-controls=
|
|
132
|
+
aria-controls={ariaControls}
|
|
128
133
|
>
|
|
129
134
|
<IconMaximize size="xs" />
|
|
130
135
|
{copy.buttons.expand}
|
package/src/table.module.scss
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
flex-direction: column;
|
|
9
9
|
gap: var(--purpur-spacing-200);
|
|
10
10
|
z-index: 1;
|
|
11
|
-
max-width: fit-content;
|
|
12
11
|
background-color: inherit;
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -38,6 +37,10 @@
|
|
|
38
37
|
border-collapse: separate;
|
|
39
38
|
border-spacing: 0;
|
|
40
39
|
position: relative;
|
|
40
|
+
|
|
41
|
+
&--full-width {
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
.purpur-table-header {
|
|
@@ -72,11 +75,16 @@
|
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
.purpur-table-column-header-cell {
|
|
75
|
-
padding: var(--purpur-spacing-
|
|
78
|
+
padding: var(--purpur-spacing-100) var(--purpur-spacing-150) var(--purpur-spacing-100)
|
|
76
79
|
var(--purpur-spacing-300);
|
|
77
80
|
border-bottom: var(--table-border);
|
|
78
81
|
text-align: left;
|
|
79
82
|
|
|
83
|
+
&:has([role="checkbox"]) {
|
|
84
|
+
padding: calc(var(--purpur-spacing-25) + var(--purpur-spacing-50)) var(--purpur-spacing-150)
|
|
85
|
+
calc(var(--purpur-spacing-25) + var(--purpur-spacing-50)) var(--purpur-spacing-300);
|
|
86
|
+
}
|
|
87
|
+
|
|
80
88
|
&__checkbox {
|
|
81
89
|
vertical-align: middle;
|
|
82
90
|
}
|
|
@@ -93,7 +101,7 @@
|
|
|
93
101
|
display: flex;
|
|
94
102
|
flex-direction: column;
|
|
95
103
|
align-items: flex-start;
|
|
96
|
-
gap: var(--purpur-spacing-
|
|
104
|
+
gap: var(--purpur-spacing-50);
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
&__title {
|
|
@@ -101,6 +109,10 @@
|
|
|
101
109
|
align-items: center;
|
|
102
110
|
gap: var(--purpur-spacing-50);
|
|
103
111
|
align-self: stretch;
|
|
112
|
+
|
|
113
|
+
&--default {
|
|
114
|
+
padding: var(--purpur-spacing-100) var(--purpur-spacing-0);
|
|
115
|
+
}
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
&__sortable-title {
|
|
@@ -110,9 +122,9 @@
|
|
|
110
122
|
&__filter-wrapper {
|
|
111
123
|
display: flex;
|
|
112
124
|
padding-right: var(--purpur-spacing-150);
|
|
125
|
+
padding-bottom: var(--purpur-spacing-150);
|
|
113
126
|
flex-direction: column;
|
|
114
127
|
align-items: flex-start;
|
|
115
|
-
gap: var(--purpur-spacing-100);
|
|
116
128
|
align-self: stretch;
|
|
117
129
|
}
|
|
118
130
|
}
|
|
@@ -194,7 +206,7 @@
|
|
|
194
206
|
}
|
|
195
207
|
|
|
196
208
|
.purpur-table-row-cell {
|
|
197
|
-
height: var(--purpur-spacing-
|
|
209
|
+
height: calc(var(--purpur-spacing-600) + var(--purpur-spacing-150));
|
|
198
210
|
padding: var(--purpur-spacing-0) var(--purpur-spacing-300);
|
|
199
211
|
align-items: center;
|
|
200
212
|
align-self: stretch;
|
|
@@ -263,30 +275,27 @@
|
|
|
263
275
|
text-align: right;
|
|
264
276
|
}
|
|
265
277
|
|
|
278
|
+
&__truncate-wrapper {
|
|
279
|
+
width: 100%;
|
|
280
|
+
display: grid;
|
|
281
|
+
grid-template-columns: 1fr;
|
|
282
|
+
}
|
|
283
|
+
|
|
266
284
|
&__truncate {
|
|
267
285
|
position: relative;
|
|
268
286
|
max-width: 100%;
|
|
269
287
|
width: 100%;
|
|
270
288
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
289
|
+
display: block;
|
|
290
|
+
overflow: hidden;
|
|
291
|
+
white-space: nowrap;
|
|
292
|
+
text-overflow: ellipsis;
|
|
276
293
|
|
|
277
294
|
a {
|
|
278
295
|
display: inline;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
a,
|
|
282
|
-
p,
|
|
283
|
-
span,
|
|
284
|
-
div {
|
|
285
296
|
overflow: hidden;
|
|
286
297
|
white-space: nowrap;
|
|
287
298
|
text-overflow: ellipsis;
|
|
288
|
-
max-width: 100%;
|
|
289
|
-
width: inherit;
|
|
290
299
|
}
|
|
291
300
|
}
|
|
292
301
|
|
package/src/table.stories.tsx
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
3
|
import React, { useEffect, useState } from "react";
|
|
6
4
|
import { Grid } from "@purpurds/grid";
|
|
7
5
|
import { IllustrativeIconSearchQuestionDuocolor } from "@purpurds/illustrative-icon/search-question-duocolor";
|
|
@@ -154,6 +152,10 @@ const meta = {
|
|
|
154
152
|
options: ["primary", "secondary"],
|
|
155
153
|
description: "Style variant for the table",
|
|
156
154
|
},
|
|
155
|
+
fullWidth: {
|
|
156
|
+
control: "boolean",
|
|
157
|
+
description: "Full width of the table",
|
|
158
|
+
},
|
|
157
159
|
},
|
|
158
160
|
} satisfies Meta<typeof Table<TableData>>;
|
|
159
161
|
|
|
@@ -245,7 +247,7 @@ const commonSettingsDrawerCopy = {
|
|
|
245
247
|
const commonExportDrawerCopy = {
|
|
246
248
|
title: "Export table",
|
|
247
249
|
bodyText: "Choose the format you want to export the table in.",
|
|
248
|
-
|
|
250
|
+
closeButtonAriaLabel: "Close drawer",
|
|
249
251
|
link: "Export as",
|
|
250
252
|
};
|
|
251
253
|
|
|
@@ -277,6 +279,7 @@ export const Showcase: StoryTableData = {
|
|
|
277
279
|
data: generatedTableData,
|
|
278
280
|
columns: columnDef,
|
|
279
281
|
loading: true,
|
|
282
|
+
fullWidth: true,
|
|
280
283
|
},
|
|
281
284
|
parameters: {
|
|
282
285
|
docs: {
|
|
@@ -345,8 +348,7 @@ manages filtering, sorting and pagination internally.
|
|
|
345
348
|
nextButtonAriaLabel: "Go to next page",
|
|
346
349
|
nextButtonText: "Next",
|
|
347
350
|
outOfLabel: "of",
|
|
348
|
-
|
|
349
|
-
pageSelectorNoOptionsText: "Page does not exist",
|
|
351
|
+
pageSelectorLabel: "Select a page",
|
|
350
352
|
previousButtonAriaLabel: "Go to previous page",
|
|
351
353
|
previousButtonText: "Previous",
|
|
352
354
|
stepNumberPrefix: "Go to page",
|
|
@@ -389,6 +391,7 @@ manages filtering, sorting and pagination internally.
|
|
|
389
391
|
onPrimaryButtonClick={handlePrimaryButtonClick}
|
|
390
392
|
onSecondaryButtonClick={() => console.log("Secondary button clicked")}
|
|
391
393
|
rowSelectionAriaLabels={args.rowSelectionAriaLabels}
|
|
394
|
+
fullWidth={args.fullWidth}
|
|
392
395
|
/>
|
|
393
396
|
);
|
|
394
397
|
},
|
|
@@ -730,8 +733,7 @@ This example demonstrates pagination functionality in the Table.
|
|
|
730
733
|
nextButtonAriaLabel: "Go to next page",
|
|
731
734
|
nextButtonText: "Next",
|
|
732
735
|
outOfLabel: "of",
|
|
733
|
-
|
|
734
|
-
pageSelectorNoOptionsText: "Page does not exist",
|
|
736
|
+
pageSelectorLabel: "Select a page",
|
|
735
737
|
previousButtonAriaLabel: "Go to previous page",
|
|
736
738
|
previousButtonText: "Previous",
|
|
737
739
|
stepNumberPrefix: "Go to page",
|
|
@@ -1150,8 +1152,7 @@ sorting, and filtering are managed by a server API instead of in the browser.
|
|
|
1150
1152
|
nextButtonAriaLabel: "Go to next page",
|
|
1151
1153
|
nextButtonText: "Next",
|
|
1152
1154
|
outOfLabel: "of",
|
|
1153
|
-
|
|
1154
|
-
pageSelectorNoOptionsText: "Page does not exist",
|
|
1155
|
+
pageSelectorLabel: "Select a page",
|
|
1155
1156
|
previousButtonAriaLabel: "Go to previous page",
|
|
1156
1157
|
previousButtonText: "Previous",
|
|
1157
1158
|
stepNumberPrefix: "Go to page",
|
package/src/table.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ReactElement, useEffect, useRef, useState } from "react";
|
|
1
|
+
import React, { ReactElement, useEffect, useId, useRef, useState } from "react";
|
|
2
2
|
import type {
|
|
3
3
|
ColumnDef,
|
|
4
4
|
ColumnFiltersState,
|
|
@@ -70,6 +70,7 @@ export type TableProps<TData extends RowData> = {
|
|
|
70
70
|
columns: CoreOptions<TData>["columns"];
|
|
71
71
|
data: TData[];
|
|
72
72
|
paginationComponent?: ReactElement<PaginationProps>;
|
|
73
|
+
fullWidth?: boolean;
|
|
73
74
|
onRowsCountChange?: (rowsCount: number) => void;
|
|
74
75
|
} & (WithToolbarProps | WithoutToolbarProps) &
|
|
75
76
|
(WithSortingProps | WithoutSortingProps) &
|
|
@@ -94,6 +95,7 @@ export const Table = <TData extends RowData>({
|
|
|
94
95
|
enableToolbar: enableToolbar,
|
|
95
96
|
exportDrawerCopy,
|
|
96
97
|
exportFormats,
|
|
98
|
+
fullWidth = true,
|
|
97
99
|
loading,
|
|
98
100
|
paginationComponent,
|
|
99
101
|
rowSelectionAriaLabels,
|
|
@@ -123,10 +125,11 @@ export const Table = <TData extends RowData>({
|
|
|
123
125
|
);
|
|
124
126
|
const [stickyFirstColumn, setStickyFirstColumn] = useState(true);
|
|
125
127
|
const [stickyHeaders, setStickyHeaders] = useState(true);
|
|
126
|
-
const [rowSelectionEnabled, setRowSelectionEnabled] = useState(true);
|
|
127
128
|
const prevShowOnlySelectedRows = useRef(showOnlySelectedRows);
|
|
128
129
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
129
130
|
const tableContainerRef = useRef<HTMLTableElement>(null);
|
|
131
|
+
const uid = useId();
|
|
132
|
+
const [rowSelectionEnabled, setRowSelectionEnabled] = useState(true);
|
|
130
133
|
|
|
131
134
|
const classes = cx([
|
|
132
135
|
className,
|
|
@@ -252,7 +255,9 @@ export const Table = <TData extends RowData>({
|
|
|
252
255
|
};
|
|
253
256
|
|
|
254
257
|
const getStickyColumn = (index: number) => {
|
|
255
|
-
|
|
258
|
+
// When rowSelectionEnabled is true, the first two columns are sticky
|
|
259
|
+
// Otherwise, only the first column is sticky
|
|
260
|
+
return props.enableRowSelection && rowSelectionEnabled ? index <= 1 : index === 0;
|
|
256
261
|
};
|
|
257
262
|
|
|
258
263
|
const handleResetColumnFilters = () => {
|
|
@@ -275,11 +280,15 @@ export const Table = <TData extends RowData>({
|
|
|
275
280
|
setShowColumnFiltersEnabled(true);
|
|
276
281
|
setStickyFirstColumn(true);
|
|
277
282
|
setStickyHeaders(true);
|
|
278
|
-
setRowSelectionEnabled(true);
|
|
279
283
|
|
|
280
284
|
tanstackTable.resetColumnVisibility();
|
|
281
285
|
};
|
|
282
286
|
|
|
287
|
+
const showBorder = (index: number) => {
|
|
288
|
+
// Only show the border for sticky columns when the table is scrolled
|
|
289
|
+
return isScrolled && getStickyColumn(index);
|
|
290
|
+
};
|
|
291
|
+
|
|
283
292
|
const tableRows = tanstackTable.getRowModel().rows;
|
|
284
293
|
const emptyTable = tableRows.length === 0 && Boolean(emptyTableCopy);
|
|
285
294
|
|
|
@@ -294,8 +303,8 @@ export const Table = <TData extends RowData>({
|
|
|
294
303
|
getStickyColumn={getStickyColumn}
|
|
295
304
|
stickyFirstColumn={stickyFirstColumn}
|
|
296
305
|
isScrolled={isScrolled}
|
|
297
|
-
rowSelectionEnabled={rowSelectionEnabled}
|
|
298
306
|
cellWidths={getColumnWidths()}
|
|
307
|
+
showBorder={showBorder}
|
|
299
308
|
/>
|
|
300
309
|
) : emptyTable && emptyTableCopy && emptyTableHeadingTag ? (
|
|
301
310
|
<EmptyTable
|
|
@@ -318,11 +327,7 @@ export const Table = <TData extends RowData>({
|
|
|
318
327
|
isLastCell={cellIndex === row.getVisibleCells().length - 1}
|
|
319
328
|
stickyColumn={stickyFirstColumn && getStickyColumn(cellIndex)}
|
|
320
329
|
isScrolled={isScrolled}
|
|
321
|
-
showBorder={
|
|
322
|
-
isScrolled &&
|
|
323
|
-
((props.enableRowSelection && cellIndex === 1) ||
|
|
324
|
-
(!props.enableRowSelection && cellIndex === 0))
|
|
325
|
-
}
|
|
330
|
+
showBorder={showBorder(cellIndex)}
|
|
326
331
|
/>
|
|
327
332
|
))}
|
|
328
333
|
</TableRow>
|
|
@@ -330,9 +335,12 @@ export const Table = <TData extends RowData>({
|
|
|
330
335
|
);
|
|
331
336
|
|
|
332
337
|
return (
|
|
333
|
-
<div id=
|
|
338
|
+
<div id={`${uid}-table`} className={classes}>
|
|
334
339
|
{enableToolbar && (
|
|
335
340
|
<TableToolbar
|
|
341
|
+
aria-controls={`${uid}-table`}
|
|
342
|
+
settingsDrawerAriaControls={`${uid}-settings-drawer`}
|
|
343
|
+
exportDrawerAriaControls={`${uid}-export-drawer`}
|
|
336
344
|
onSetDrawerIsOpen={setSettingsDrawerIsOpen}
|
|
337
345
|
onResetColumnFilters={handleResetColumnFilters}
|
|
338
346
|
onToggleExpand={onToggleExpand}
|
|
@@ -353,7 +361,12 @@ export const Table = <TData extends RowData>({
|
|
|
353
361
|
})}
|
|
354
362
|
ref={tableContainerRef}
|
|
355
363
|
>
|
|
356
|
-
<table
|
|
364
|
+
<table
|
|
365
|
+
className={cx([
|
|
366
|
+
`${rootClassName}__table`,
|
|
367
|
+
{ [`${rootClassName}__table--full-width`]: fullWidth },
|
|
368
|
+
])}
|
|
369
|
+
>
|
|
357
370
|
<TableHeader columnFiltersEnabled={showColumnFiltersEnabled}>
|
|
358
371
|
{tanstackTable.getHeaderGroups().map((headerGroup) => (
|
|
359
372
|
<TableRow key={headerGroup.id}>
|
|
@@ -365,11 +378,7 @@ export const Table = <TData extends RowData>({
|
|
|
365
378
|
stickyColumn={!emptyTable && stickyFirstColumn && getStickyColumn(index)}
|
|
366
379
|
stickyHeaders={!emptyTable && stickyHeaders}
|
|
367
380
|
isScrolled={isScrolled}
|
|
368
|
-
showBorder={
|
|
369
|
-
isScrolled &&
|
|
370
|
-
((props.enableRowSelection && index === 1) ||
|
|
371
|
-
(!props.enableRowSelection && index === 0))
|
|
372
|
-
}
|
|
381
|
+
showBorder={showBorder(index)}
|
|
373
382
|
{...(props.enableSorting && sortingAriaLabels
|
|
374
383
|
? { enableSorting: props.enableSorting, sortingAriaLabels }
|
|
375
384
|
: { enableSorting: false })}
|
|
@@ -396,6 +405,7 @@ export const Table = <TData extends RowData>({
|
|
|
396
405
|
)}
|
|
397
406
|
{enableToolbar && settingsDrawerCopy && (
|
|
398
407
|
<TableSettingsDrawer
|
|
408
|
+
id={`${uid}-settings-drawer`}
|
|
399
409
|
setDrawerIsOpen={setSettingsDrawerIsOpen}
|
|
400
410
|
setShowColumnFiltersEnabled={setShowColumnFiltersEnabled}
|
|
401
411
|
setStickyFirstColumn={setStickyFirstColumn}
|
|
@@ -415,6 +425,7 @@ export const Table = <TData extends RowData>({
|
|
|
415
425
|
)}
|
|
416
426
|
{Array.isArray(exportFormats) && exportDrawerCopy && (
|
|
417
427
|
<TableExportDrawer
|
|
428
|
+
id={`${uid}-export-drawer`}
|
|
418
429
|
isOpen={isExportDrawerOpen}
|
|
419
430
|
setDrawerIsOpen={setExportDrawerIsOpen}
|
|
420
431
|
exportFormats={exportFormats}
|
|
@@ -446,7 +457,7 @@ const EmptyTable = ({ variant, tag, title, description, colSpan, icon }: EmptyTa
|
|
|
446
457
|
`${rootClassName}__empty-section--${variant}`,
|
|
447
458
|
])}
|
|
448
459
|
>
|
|
449
|
-
<div className={cx(`${rootClassName}__empty-section__icon`)}>{icon}</div>
|
|
460
|
+
{icon && <div className={cx(`${rootClassName}__empty-section__icon`)}>{icon}</div>}
|
|
450
461
|
<div className={cx(`${rootClassName}__empty-section__texts`)}>
|
|
451
462
|
<Heading data-testid="purpur-table-empty-table-title" variant="title-100" tag={tag}>
|
|
452
463
|
{title}
|
|
@@ -460,21 +471,20 @@ const EmptyTable = ({ variant, tag, title, description, colSpan, icon }: EmptyTa
|
|
|
460
471
|
|
|
461
472
|
type LoadingTableRowsProps = {
|
|
462
473
|
rowCount: number;
|
|
463
|
-
rowSelectionEnabled: boolean;
|
|
464
474
|
isScrolled: boolean;
|
|
465
475
|
stickyFirstColumn: boolean;
|
|
466
476
|
getStickyColumn: (index: number) => boolean;
|
|
467
477
|
cellWidths: (string | number)[];
|
|
478
|
+
showBorder: (index: number) => boolean;
|
|
468
479
|
};
|
|
469
480
|
|
|
470
481
|
const LoadingTableRows = ({
|
|
471
482
|
rowCount,
|
|
472
|
-
// cellCount,
|
|
473
483
|
getStickyColumn,
|
|
474
484
|
stickyFirstColumn,
|
|
475
485
|
isScrolled,
|
|
476
|
-
rowSelectionEnabled,
|
|
477
486
|
cellWidths,
|
|
487
|
+
showBorder,
|
|
478
488
|
}: LoadingTableRowsProps) => (
|
|
479
489
|
<>
|
|
480
490
|
{Array.from({ length: rowCount }, (_value, index) => index).map((row, rowIndex) => (
|
|
@@ -487,11 +497,7 @@ const LoadingTableRows = ({
|
|
|
487
497
|
isLastCell={cellIndex === cellWidths.length - 1}
|
|
488
498
|
stickyColumn={stickyFirstColumn && getStickyColumn(cellIndex)}
|
|
489
499
|
isScrolled={isScrolled}
|
|
490
|
-
showBorder={
|
|
491
|
-
isScrolled &&
|
|
492
|
-
((rowSelectionEnabled && cellIndex === 1) ||
|
|
493
|
-
(!rowSelectionEnabled && cellIndex === 0))
|
|
494
|
-
}
|
|
500
|
+
showBorder={showBorder(cellIndex)}
|
|
495
501
|
cellWidth={cellWidth}
|
|
496
502
|
/>
|
|
497
503
|
))}
|
|
@@ -145,6 +145,7 @@ export const Selectors = {
|
|
|
145
145
|
PAGINATION: {
|
|
146
146
|
ROOT: "purpur-pagination",
|
|
147
147
|
PAGE_SIZE_SELECT: "purpur-pagination-page-size-selector-select-select",
|
|
148
|
+
PAGE_BUTTON: (pageNumber: number) => `purpur-pagination-pages-page-${pageNumber}-button`,
|
|
148
149
|
},
|
|
149
150
|
SKELETON: "purpur-table-cell-skeleton",
|
|
150
151
|
};
|
|
@@ -164,7 +165,7 @@ export const copy = {
|
|
|
164
165
|
},
|
|
165
166
|
exportDrawer: {
|
|
166
167
|
bodyText: "Choose the format you want to export the table in.",
|
|
167
|
-
|
|
168
|
+
closeButtonAriaLabel: "Close drawer",
|
|
168
169
|
link: "Export as",
|
|
169
170
|
title: "Export table",
|
|
170
171
|
},
|
package/src/types.ts
CHANGED