@coveord/plasma-mantine 52.9.0 → 52.10.1
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/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-test.log +33 -32
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/components/code-editor/CodeEditor.d.ts.map +1 -1
- package/dist/cjs/components/code-editor/CodeEditor.js +8 -3
- package/dist/cjs/components/code-editor/CodeEditor.js.map +1 -1
- package/dist/cjs/components/collection/Collection.js +5 -3
- package/dist/cjs/components/collection/Collection.js.map +1 -1
- package/dist/cjs/components/date-range-picker/DateRangePickerPresetSelect.d.ts.map +1 -1
- package/dist/cjs/components/date-range-picker/DateRangePickerPresetSelect.js +2 -1
- package/dist/cjs/components/date-range-picker/DateRangePickerPresetSelect.js.map +1 -1
- package/dist/cjs/components/date-range-picker/EditableDateRangePicker.js +2 -2
- package/dist/cjs/components/date-range-picker/EditableDateRangePicker.js.map +1 -1
- package/dist/cjs/components/modal-wizard/ModalWizard.js +2 -2
- package/dist/cjs/components/modal-wizard/ModalWizard.js.map +1 -1
- package/dist/cjs/components/table/Table.d.ts.map +1 -1
- package/dist/cjs/components/table/Table.js +25 -13
- package/dist/cjs/components/table/Table.js.map +1 -1
- package/dist/cjs/components/table/Table.styles.d.ts.map +1 -1
- package/dist/cjs/components/table/Table.styles.js +1 -10
- package/dist/cjs/components/table/Table.styles.js.map +1 -1
- package/dist/cjs/components/table/Table.types.d.ts +14 -3
- package/dist/cjs/components/table/Table.types.d.ts.map +1 -1
- package/dist/cjs/components/table/TableFooter.js +2 -2
- package/dist/cjs/components/table/TableFooter.js.map +1 -1
- package/dist/cjs/components/table/TableHeader.js +1 -1
- package/dist/cjs/components/table/TableHeader.js.map +1 -1
- package/dist/cjs/components/table/TableLastUpdated.d.ts +24 -0
- package/dist/cjs/components/table/TableLastUpdated.d.ts.map +1 -0
- package/dist/cjs/components/table/TableLastUpdated.js +73 -0
- package/dist/cjs/components/table/TableLastUpdated.js.map +1 -0
- package/dist/cjs/components/table/TablePagination.d.ts.map +1 -1
- package/dist/cjs/components/table/TablePagination.js +1 -0
- package/dist/cjs/components/table/TablePagination.js.map +1 -1
- package/dist/cjs/components/table/TablePerPage.js +5 -3
- package/dist/cjs/components/table/TablePerPage.js.map +1 -1
- package/dist/cjs/components/table/layouts/RowLayout.d.ts.map +1 -1
- package/dist/cjs/components/table/layouts/RowLayout.js +41 -9
- package/dist/cjs/components/table/layouts/RowLayout.js.map +1 -1
- package/dist/cjs/components/table/useRowSelection.d.ts +2 -2
- package/dist/cjs/components/table/useRowSelection.d.ts.map +1 -1
- package/dist/cjs/components/table/useRowSelection.js +8 -3
- package/dist/cjs/components/table/useRowSelection.js.map +1 -1
- package/dist/cjs/theme/Theme.js +1 -1
- package/dist/cjs/theme/Theme.js.map +1 -1
- package/dist/esm/components/code-editor/CodeEditor.d.ts.map +1 -1
- package/dist/esm/components/code-editor/CodeEditor.js +8 -3
- package/dist/esm/components/code-editor/CodeEditor.js.map +1 -1
- package/dist/esm/components/collection/Collection.js +5 -3
- package/dist/esm/components/collection/Collection.js.map +1 -1
- package/dist/esm/components/date-range-picker/DateRangePickerPresetSelect.d.ts.map +1 -1
- package/dist/esm/components/date-range-picker/DateRangePickerPresetSelect.js +2 -1
- package/dist/esm/components/date-range-picker/DateRangePickerPresetSelect.js.map +1 -1
- package/dist/esm/components/date-range-picker/EditableDateRangePicker.js +2 -2
- package/dist/esm/components/date-range-picker/EditableDateRangePicker.js.map +1 -1
- package/dist/esm/components/modal-wizard/ModalWizard.js +2 -2
- package/dist/esm/components/modal-wizard/ModalWizard.js.map +1 -1
- package/dist/esm/components/table/Table.d.ts.map +1 -1
- package/dist/esm/components/table/Table.js +27 -15
- package/dist/esm/components/table/Table.js.map +1 -1
- package/dist/esm/components/table/Table.styles.d.ts.map +1 -1
- package/dist/esm/components/table/Table.styles.js +1 -10
- package/dist/esm/components/table/Table.styles.js.map +1 -1
- package/dist/esm/components/table/Table.types.d.ts +14 -3
- package/dist/esm/components/table/Table.types.d.ts.map +1 -1
- package/dist/esm/components/table/Table.types.js.map +1 -1
- package/dist/esm/components/table/TableFooter.js +2 -2
- package/dist/esm/components/table/TableFooter.js.map +1 -1
- package/dist/esm/components/table/TableHeader.js +1 -1
- package/dist/esm/components/table/TableHeader.js.map +1 -1
- package/dist/esm/components/table/TableLastUpdated.d.ts +24 -0
- package/dist/esm/components/table/TableLastUpdated.d.ts.map +1 -0
- package/dist/esm/components/table/TableLastUpdated.js +62 -0
- package/dist/esm/components/table/TableLastUpdated.js.map +1 -0
- package/dist/esm/components/table/TablePagination.d.ts.map +1 -1
- package/dist/esm/components/table/TablePagination.js +1 -0
- package/dist/esm/components/table/TablePagination.js.map +1 -1
- package/dist/esm/components/table/TablePerPage.js +5 -3
- package/dist/esm/components/table/TablePerPage.js.map +1 -1
- package/dist/esm/components/table/layouts/RowLayout.d.ts.map +1 -1
- package/dist/esm/components/table/layouts/RowLayout.js +42 -10
- package/dist/esm/components/table/layouts/RowLayout.js.map +1 -1
- package/dist/esm/components/table/useRowSelection.d.ts +2 -2
- package/dist/esm/components/table/useRowSelection.d.ts.map +1 -1
- package/dist/esm/components/table/useRowSelection.js +8 -3
- package/dist/esm/components/table/useRowSelection.js.map +1 -1
- package/dist/esm/theme/Theme.js +1 -1
- package/dist/esm/theme/Theme.js.map +1 -1
- package/package.json +17 -17
- package/src/__tests__/VitestSetup.ts +12 -0
- package/src/components/code-editor/CodeEditor.tsx +5 -3
- package/src/components/code-editor/__tests__/CodeEditor.spec.tsx +1 -0
- package/src/components/date-range-picker/DateRangePickerPresetSelect.tsx +1 -0
- package/src/components/date-range-picker/__tests__/DateRangePickerInlineCalendar.spec.tsx +2 -0
- package/src/components/date-range-picker/__tests__/DateRangePickerPopoverCalendar.spec.tsx +4 -19
- package/src/components/date-range-picker/__tests__/EditableDateRangePicker.spec.tsx +3 -3
- package/src/components/modal-wizard/__tests__/ModalWizard.spec.tsx +19 -4
- package/src/components/table/Table.styles.ts +0 -9
- package/src/components/table/Table.tsx +22 -13
- package/src/components/table/Table.types.ts +14 -3
- package/src/components/table/TableFooter.tsx +1 -1
- package/src/components/table/TableHeader.tsx +1 -1
- package/src/components/table/TableLastUpdated.tsx +51 -0
- package/src/components/table/TablePagination.tsx +1 -0
- package/src/components/table/TablePerPage.tsx +3 -3
- package/src/components/table/__tests__/Table.spec.tsx +44 -5
- package/src/components/table/__tests__/TableActions.spec.tsx +4 -3
- package/src/components/table/__tests__/TableDateRangePicker.spec.tsx +26 -59
- package/src/components/table/__tests__/TableLastUpdated.spec.tsx +97 -0
- package/src/components/table/__tests__/TablePredicate.spec.tsx +7 -55
- package/src/components/table/layouts/RowLayout.tsx +45 -11
- package/src/components/table/useRowSelection.ts +13 -6
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {DateRangePickerValue} from '@mantine/dates';
|
|
2
1
|
import {render, screen, userEvent} from '@test-utils';
|
|
3
2
|
import {useState} from 'react';
|
|
4
3
|
|
|
5
4
|
import {EditableDateRangePicker} from '../EditableDateRangePicker';
|
|
5
|
+
import {DateRangePickerValue} from '../DateRangePickerInlineCalendar';
|
|
6
6
|
|
|
7
7
|
describe('EditableDateRangePicker', () => {
|
|
8
8
|
it('renders an input for the start and an input for the end', () => {
|
|
@@ -19,7 +19,7 @@ describe('EditableDateRangePicker', () => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('updates when editing values', async () => {
|
|
22
|
-
const user = userEvent.setup(
|
|
22
|
+
const user = userEvent.setup();
|
|
23
23
|
const Fixture = () => {
|
|
24
24
|
const [value, setValue] = useState<DateRangePickerValue>([null, null]);
|
|
25
25
|
return (
|
|
@@ -44,5 +44,5 @@ describe('EditableDateRangePicker', () => {
|
|
|
44
44
|
await user.type(endInput, 'Jan 14, 2022');
|
|
45
45
|
|
|
46
46
|
expect(screen.getByTestId('json')).toHaveTextContent('["2022-01-08T00:00:00.000Z","2022-01-14T23:59:59.999Z"]');
|
|
47
|
-
});
|
|
47
|
+
}, 10000);
|
|
48
48
|
});
|
|
@@ -8,24 +8,28 @@ describe('ModalWizard', () => {
|
|
|
8
8
|
|
|
9
9
|
const modelSteps = [
|
|
10
10
|
{
|
|
11
|
+
id: 'step1',
|
|
11
12
|
docLink: 'https://google.com',
|
|
12
13
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
13
14
|
validateStep: () => ({isValid: true}),
|
|
14
15
|
element: <div> Slide 1</div>,
|
|
15
16
|
},
|
|
16
17
|
{
|
|
18
|
+
id: 'step2',
|
|
17
19
|
docLink: 'https://google.com',
|
|
18
20
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
19
21
|
validateStep: () => ({isValid: true}),
|
|
20
22
|
element: <div> Slide 2</div>,
|
|
21
23
|
},
|
|
22
24
|
{
|
|
25
|
+
id: 'step3',
|
|
23
26
|
docLink: 'https://google.com',
|
|
24
27
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
25
28
|
validateStep: () => ({isValid: false}),
|
|
26
29
|
element: <div> Slide 3</div>,
|
|
27
30
|
},
|
|
28
31
|
{
|
|
32
|
+
id: 'step4',
|
|
29
33
|
docLink: 'https://google.com',
|
|
30
34
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
31
35
|
validateStep: () => ({isValid: false}),
|
|
@@ -46,13 +50,14 @@ describe('ModalWizard', () => {
|
|
|
46
50
|
onNext={onNextSpy}
|
|
47
51
|
onPrevious={onPreviousSpy}
|
|
48
52
|
>
|
|
49
|
-
{modelSteps.map((
|
|
53
|
+
{modelSteps.map((step) => (
|
|
50
54
|
<ModalWizard.Step
|
|
51
|
-
|
|
55
|
+
key={step.id}
|
|
56
|
+
docLink={step.docLink}
|
|
52
57
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
53
|
-
validateStep={
|
|
58
|
+
validateStep={step.validateStep}
|
|
54
59
|
>
|
|
55
|
-
{
|
|
60
|
+
{step.element}
|
|
56
61
|
</ModalWizard.Step>
|
|
57
62
|
))}
|
|
58
63
|
</ModalWizard>
|
|
@@ -165,6 +170,7 @@ describe('ModalWizard', () => {
|
|
|
165
170
|
|
|
166
171
|
const modelSteps = [
|
|
167
172
|
{
|
|
173
|
+
id: 'step1',
|
|
168
174
|
docLink: 'https://google.com',
|
|
169
175
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
170
176
|
validateStep: () => ({isValid: true}),
|
|
@@ -179,6 +185,7 @@ describe('ModalWizard', () => {
|
|
|
179
185
|
<ModalWizard isDirty={isDirty} onClose={onClose} opened={true}>
|
|
180
186
|
{modelSteps.map((model_item) => (
|
|
181
187
|
<ModalWizard.Step
|
|
188
|
+
key={model_item.id}
|
|
182
189
|
docLink={model_item.docLink}
|
|
183
190
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
184
191
|
validateStep={model_item.validateStep}
|
|
@@ -201,6 +208,7 @@ describe('ModalWizard', () => {
|
|
|
201
208
|
const user = userEvent.setup();
|
|
202
209
|
const modelSteps = [
|
|
203
210
|
{
|
|
211
|
+
id: 'step1',
|
|
204
212
|
docLink: 'https://google.com',
|
|
205
213
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
206
214
|
validateStep: () => ({isValid: true}),
|
|
@@ -215,6 +223,7 @@ describe('ModalWizard', () => {
|
|
|
215
223
|
<ModalWizard isDirty={isDirty} onClose={onClose} opened={true}>
|
|
216
224
|
{modelSteps.map((model_item) => (
|
|
217
225
|
<ModalWizard.Step
|
|
226
|
+
key={model_item.id}
|
|
218
227
|
docLink={model_item.docLink}
|
|
219
228
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
220
229
|
validateStep={model_item.validateStep}
|
|
@@ -237,6 +246,7 @@ describe('ModalWizard', () => {
|
|
|
237
246
|
const user = userEvent.setup();
|
|
238
247
|
const modelSteps = [
|
|
239
248
|
{
|
|
249
|
+
id: 'step1',
|
|
240
250
|
docLink: 'https://google.com',
|
|
241
251
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
242
252
|
validateStep: () => ({isValid: true}),
|
|
@@ -252,6 +262,7 @@ describe('ModalWizard', () => {
|
|
|
252
262
|
<ModalWizard isDirty={isDirty} onClose={onClose} onFinish={onFinish} opened={true}>
|
|
253
263
|
{modelSteps.map((model_item) => (
|
|
254
264
|
<ModalWizard.Step
|
|
265
|
+
key={model_item.id}
|
|
255
266
|
docLink={model_item.docLink}
|
|
256
267
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
257
268
|
validateStep={model_item.validateStep}
|
|
@@ -274,6 +285,7 @@ describe('ModalWizard', () => {
|
|
|
274
285
|
const user = userEvent.setup();
|
|
275
286
|
const modelSteps = [
|
|
276
287
|
{
|
|
288
|
+
id: 'step1',
|
|
277
289
|
docLink: 'https://google.com',
|
|
278
290
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
279
291
|
validateStep: () => ({isValid: true}),
|
|
@@ -289,6 +301,7 @@ describe('ModalWizard', () => {
|
|
|
289
301
|
<ModalWizard isDirty={isDirty} onClose={onClose} handleDirtyState={handleDirtyState} opened={true}>
|
|
290
302
|
{modelSteps.map((model_item) => (
|
|
291
303
|
<ModalWizard.Step
|
|
304
|
+
key={model_item.id}
|
|
292
305
|
docLink={model_item.docLink}
|
|
293
306
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
294
307
|
validateStep={model_item.validateStep}
|
|
@@ -313,6 +326,7 @@ describe('ModalWizard', () => {
|
|
|
313
326
|
const user = userEvent.setup();
|
|
314
327
|
const modelSteps = [
|
|
315
328
|
{
|
|
329
|
+
id: 'step1',
|
|
316
330
|
docLink: 'https://google.com',
|
|
317
331
|
title: (currentStep: string) => 'Current Step is: ' + currentStep,
|
|
318
332
|
validateStep: () => ({isValid: true}),
|
|
@@ -328,6 +342,7 @@ describe('ModalWizard', () => {
|
|
|
328
342
|
<ModalWizard isDirty={isDirty} onClose={onClose} handleDirtyState={handleDirtyState} opened={true}>
|
|
329
343
|
{modelSteps.map((model_item) => (
|
|
330
344
|
<ModalWizard.Step
|
|
345
|
+
key={model_item.id}
|
|
331
346
|
docLink={model_item.docLink}
|
|
332
347
|
title={(currentStep) => 'Current Step is: ' + currentStep}
|
|
333
348
|
validateStep={model_item.validateStep}
|
|
@@ -3,15 +3,6 @@ import {createStyles} from '@mantine/core';
|
|
|
3
3
|
const useStyles = createStyles<string>((theme) => ({
|
|
4
4
|
table: {
|
|
5
5
|
width: '100%',
|
|
6
|
-
'& thead tr th': {
|
|
7
|
-
borderBottom: 'none',
|
|
8
|
-
},
|
|
9
|
-
'& td:first-of-type': {
|
|
10
|
-
paddingLeft: theme.spacing.xl,
|
|
11
|
-
},
|
|
12
|
-
'& tbody td': {
|
|
13
|
-
verticalAlign: 'top',
|
|
14
|
-
},
|
|
15
6
|
},
|
|
16
7
|
|
|
17
8
|
header: {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {Box, Center, Loader
|
|
1
|
+
import {Box, Center, Loader} from '@mantine/core';
|
|
2
2
|
import {useForm} from '@mantine/form';
|
|
3
3
|
import {useDidUpdate} from '@mantine/hooks';
|
|
4
|
-
import {ColumnDef, Row, TableState as TanstackTableState,
|
|
4
|
+
import {ColumnDef, getCoreRowModel, Row, TableState as TanstackTableState, useReactTable} from '@tanstack/react-table';
|
|
5
5
|
import debounce from 'lodash.debounce';
|
|
6
6
|
import defaultsDeep from 'lodash.defaultsdeep';
|
|
7
|
-
import {Children, Dispatch, ReactElement, useCallback, useEffect, useState} from 'react';
|
|
7
|
+
import {Children, cloneElement, Dispatch, ReactElement, useCallback, useEffect, useState} from 'react';
|
|
8
8
|
|
|
9
|
+
import {TableLayouts} from './layouts/TableLayouts';
|
|
9
10
|
import useStyles from './Table.styles';
|
|
10
11
|
import {TableFormType, TableProps, TableState, TableType} from './Table.types';
|
|
11
12
|
import {TableActions} from './TableActions';
|
|
@@ -16,13 +17,13 @@ import {TableDateRangePicker} from './TableDateRangePicker';
|
|
|
16
17
|
import {TableFilter} from './TableFilter';
|
|
17
18
|
import {TableFooter} from './TableFooter';
|
|
18
19
|
import {TableHeader} from './TableHeader';
|
|
20
|
+
import {TableLastUpdated} from './TableLastUpdated';
|
|
21
|
+
import {TableLoading} from './TableLoading';
|
|
19
22
|
import {TablePagination} from './TablePagination';
|
|
20
23
|
import {TablePerPage} from './TablePerPage';
|
|
21
24
|
import {TablePredicate} from './TablePredicate';
|
|
22
25
|
import {TableSelectableColumn} from './TableSelectableColumn';
|
|
23
26
|
import {useRowSelection} from './useRowSelection';
|
|
24
|
-
import {TableLoading} from './TableLoading';
|
|
25
|
-
import {TableLayouts} from './layouts/TableLayouts';
|
|
26
27
|
|
|
27
28
|
export const Table: TableType = <T,>({
|
|
28
29
|
data,
|
|
@@ -40,12 +41,14 @@ export const Table: TableType = <T,>({
|
|
|
40
41
|
multiRowSelectionEnabled,
|
|
41
42
|
disableRowSelection,
|
|
42
43
|
onRowSelectionChange,
|
|
44
|
+
additionalRootNodes,
|
|
43
45
|
options = {},
|
|
44
46
|
}: TableProps<T>) => {
|
|
45
47
|
const convertedChildren = Children.toArray(children) as ReactElement[];
|
|
46
48
|
const header = convertedChildren.find((child) => child.type === TableHeader);
|
|
47
49
|
const footer = convertedChildren.find((child) => child.type === TableFooter);
|
|
48
50
|
const consumer = convertedChildren.find((child) => child.type === TableConsumer);
|
|
51
|
+
const lastUpdated = convertedChildren.find((child) => child.type === TableLastUpdated);
|
|
49
52
|
|
|
50
53
|
const {predicates, dateRange, ...initialStateWithoutForm} = initialState;
|
|
51
54
|
const form = useForm<TableFormType>({
|
|
@@ -58,7 +61,10 @@ export const Table: TableType = <T,>({
|
|
|
58
61
|
const {classes} = useStyles();
|
|
59
62
|
|
|
60
63
|
const table = useReactTable({
|
|
61
|
-
initialState: defaultsDeep(initialStateWithoutForm, {
|
|
64
|
+
initialState: defaultsDeep(initialStateWithoutForm, {
|
|
65
|
+
pagination: {pageSize: TablePerPage.DEFAULT_SIZE},
|
|
66
|
+
globalFilter: '',
|
|
67
|
+
}),
|
|
62
68
|
data,
|
|
63
69
|
columns: multiRowSelectionEnabled ? [TableSelectableColumn as ColumnDef<T>].concat(columns) : columns,
|
|
64
70
|
getCoreRowModel: getCoreRowModel(),
|
|
@@ -79,6 +85,7 @@ export const Table: TableType = <T,>({
|
|
|
79
85
|
const {clearSelection, getSelectedRow, getSelectedRows, outsideClickRef} = useRowSelection(table, {
|
|
80
86
|
multiRowSelectionEnabled,
|
|
81
87
|
onRowSelectionChange,
|
|
88
|
+
additionalRootNodes,
|
|
82
89
|
});
|
|
83
90
|
const isFiltered =
|
|
84
91
|
!!state.globalFilter ||
|
|
@@ -149,15 +156,11 @@ export const Table: TableType = <T,>({
|
|
|
149
156
|
noDataChildren
|
|
150
157
|
) : (
|
|
151
158
|
<>
|
|
152
|
-
<
|
|
159
|
+
<Box component="table" className={classes.table} pb="sm">
|
|
153
160
|
<thead className={classes.header}>
|
|
154
161
|
{!!header ? (
|
|
155
162
|
<tr>
|
|
156
|
-
<th
|
|
157
|
-
// need to use inline style because Mantine define style on `.mantine-{id} thead tr th`
|
|
158
|
-
style={{padding: 0, fontWeight: 'unset'}}
|
|
159
|
-
colSpan={table.getAllColumns().length}
|
|
160
|
-
>
|
|
163
|
+
<th style={{padding: 0}} colSpan={table.getAllColumns().length}>
|
|
161
164
|
{header}
|
|
162
165
|
</th>
|
|
163
166
|
</tr>
|
|
@@ -185,8 +188,13 @@ export const Table: TableType = <T,>({
|
|
|
185
188
|
</tr>
|
|
186
189
|
)}
|
|
187
190
|
</tbody>
|
|
188
|
-
</
|
|
191
|
+
</Box>
|
|
189
192
|
{footer}
|
|
193
|
+
{lastUpdated
|
|
194
|
+
? cloneElement(lastUpdated, {
|
|
195
|
+
dependencies: [data, ...(lastUpdated.props.dependencies ?? [])],
|
|
196
|
+
})
|
|
197
|
+
: null}
|
|
190
198
|
</>
|
|
191
199
|
)}
|
|
192
200
|
</TableContext.Provider>
|
|
@@ -198,6 +206,7 @@ Table.Actions = TableActions;
|
|
|
198
206
|
Table.Filter = TableFilter;
|
|
199
207
|
Table.Footer = TableFooter;
|
|
200
208
|
Table.Header = TableHeader;
|
|
209
|
+
Table.LastUpdated = TableLastUpdated;
|
|
201
210
|
Table.Pagination = TablePagination;
|
|
202
211
|
Table.Predicate = TablePredicate;
|
|
203
212
|
Table.PerPage = TablePerPage;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import {Icon} from '@coveord/plasma-react-icons';
|
|
1
2
|
import {UseFormReturnType} from '@mantine/form';
|
|
2
3
|
import {
|
|
3
4
|
ColumnDef,
|
|
4
5
|
CoreOptions,
|
|
6
|
+
InitialTableState as TanstackInitialTableState,
|
|
5
7
|
Table,
|
|
6
8
|
TableOptions,
|
|
7
|
-
InitialTableState as TanstackInitialTableState,
|
|
8
9
|
TableState as TanstackTableState,
|
|
9
10
|
} from '@tanstack/table-core';
|
|
10
11
|
import {Dispatch, ReactElement, ReactNode, RefObject} from 'react';
|
|
11
12
|
|
|
12
|
-
import {Icon} from '@coveord/plasma-react-icons';
|
|
13
13
|
import {DateRangePickerValue} from '../date-range-picker/DateRangePickerInlineCalendar';
|
|
14
|
+
import {TableLayouts} from './layouts/TableLayouts';
|
|
14
15
|
import {TableActions} from './TableActions';
|
|
15
16
|
import {TableAccordionColumn, TableCollapsibleColumn} from './TableCollapsibleColumn';
|
|
16
17
|
import {TableConsumer} from './TableConsumer';
|
|
@@ -18,11 +19,11 @@ import {TableDateRangePicker} from './TableDateRangePicker';
|
|
|
18
19
|
import {TableFilter} from './TableFilter';
|
|
19
20
|
import {TableFooter} from './TableFooter';
|
|
20
21
|
import {TableHeader} from './TableHeader';
|
|
22
|
+
import {TableLastUpdated} from './TableLastUpdated';
|
|
21
23
|
import {TableLoading} from './TableLoading';
|
|
22
24
|
import {TablePagination} from './TablePagination';
|
|
23
25
|
import {TablePerPage} from './TablePerPage';
|
|
24
26
|
import {TablePredicate} from './TablePredicate';
|
|
25
|
-
import {TableLayouts} from './layouts/TableLayouts';
|
|
26
27
|
|
|
27
28
|
export type RowSelectionWithData<TData> = Record<string, TData>;
|
|
28
29
|
export interface RowSelectionState<TData> {
|
|
@@ -245,6 +246,15 @@ export interface TableProps<T> {
|
|
|
245
246
|
* @default false
|
|
246
247
|
*/
|
|
247
248
|
disableRowSelection?: boolean;
|
|
249
|
+
/**
|
|
250
|
+
* Nodes that are considered inside the table.
|
|
251
|
+
*
|
|
252
|
+
* Rows normally get unselected when clicking outside the table, but sometimes it has difficulties guessing what is inside or outside, for example when using modals.
|
|
253
|
+
* You can use this prop to force the table to consider some nodes to be inside the table.
|
|
254
|
+
*
|
|
255
|
+
* @see https://mantine.dev/hooks/use-click-outside/#multiple-nodes
|
|
256
|
+
*/
|
|
257
|
+
additionalRootNodes?: HTMLElement[];
|
|
248
258
|
/**
|
|
249
259
|
* Additional options that can be passed to the table
|
|
250
260
|
*/
|
|
@@ -268,6 +278,7 @@ export interface TableType {
|
|
|
268
278
|
Filter: typeof TableFilter;
|
|
269
279
|
Footer: typeof TableFooter;
|
|
270
280
|
Header: typeof TableHeader;
|
|
281
|
+
LastUpdated: typeof TableLastUpdated;
|
|
271
282
|
Pagination: typeof TablePagination;
|
|
272
283
|
PerPage: typeof TablePerPage;
|
|
273
284
|
Predicate: typeof TablePredicate;
|
|
@@ -5,7 +5,7 @@ interface TableFooterProps extends DefaultProps {
|
|
|
5
5
|
children?: ReactNode;
|
|
6
6
|
}
|
|
7
7
|
export const TableFooter: FunctionComponent<TableFooterProps> = ({children, ...others}) => (
|
|
8
|
-
<Group position="apart" px="
|
|
8
|
+
<Group position="apart" px="xl" py="md" {...others}>
|
|
9
9
|
{children}
|
|
10
10
|
</Group>
|
|
11
11
|
);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {createStyles, DefaultProps, Group, Selectors, Text} from '@mantine/core';
|
|
2
|
+
import {useDidUpdate} from '@mantine/hooks';
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import {FunctionComponent, useState} from 'react';
|
|
5
|
+
import {useTable} from './TableContext';
|
|
6
|
+
|
|
7
|
+
const useStyles = createStyles((theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
minHeight: '98px',
|
|
10
|
+
},
|
|
11
|
+
label: {
|
|
12
|
+
color: theme.colors.gray[6],
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
type TableLastUpdatedStylesNames = Selectors<typeof useStyles>;
|
|
17
|
+
|
|
18
|
+
interface TableLastUpdatedProps extends DefaultProps<TableLastUpdatedStylesNames> {
|
|
19
|
+
/**
|
|
20
|
+
* Label to contextualize the date
|
|
21
|
+
*
|
|
22
|
+
* @default "Last update:"
|
|
23
|
+
*/
|
|
24
|
+
label?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const TableLastUpdated: FunctionComponent<TableLastUpdatedProps & {dependencies?: never}> = ({
|
|
28
|
+
label = 'Last update:',
|
|
29
|
+
dependencies,
|
|
30
|
+
classNames,
|
|
31
|
+
styles,
|
|
32
|
+
unstyled,
|
|
33
|
+
...others
|
|
34
|
+
}) => {
|
|
35
|
+
const {classes} = useStyles(null, {name: 'TableLastUpdated', classNames, styles, unstyled});
|
|
36
|
+
const {state} = useTable();
|
|
37
|
+
const [time, setTime] = useState(new Date());
|
|
38
|
+
|
|
39
|
+
useDidUpdate(() => {
|
|
40
|
+
setTime(new Date());
|
|
41
|
+
}, [state, ...dependencies]);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Group className={classes.root} px="xl" position="right">
|
|
45
|
+
<Text size="xs" className={classes.label} {...others}>
|
|
46
|
+
{label}
|
|
47
|
+
<span role="timer">{dayjs(time).format('h:mm:ss A')}</span>
|
|
48
|
+
</Text>
|
|
49
|
+
</Group>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -32,14 +32,14 @@ export const TablePerPage: FunctionComponent<TablePerPageProps> & {DEFAULT_SIZE:
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<Group>
|
|
36
|
-
<Text>{label}</Text>
|
|
35
|
+
<Group spacing="sm">
|
|
36
|
+
<Text fw={500}>{label}</Text>
|
|
37
37
|
<SegmentedControl
|
|
38
38
|
value={state.pagination.pageSize.toString() ?? values?.[1].toString()}
|
|
39
39
|
onChange={updatePerPage}
|
|
40
40
|
data={values.map((value) => value.toString())}
|
|
41
41
|
color="action"
|
|
42
|
-
size="
|
|
42
|
+
size="sm"
|
|
43
43
|
/>
|
|
44
44
|
</Group>
|
|
45
45
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
|
|
2
|
-
import {render, screen, userEvent, waitFor} from '@test-utils';
|
|
2
|
+
import {render, screen, userEvent, waitFor, within} from '@test-utils';
|
|
3
3
|
|
|
4
|
+
import {useState} from 'react';
|
|
4
5
|
import {Table} from '../Table';
|
|
5
|
-
import {useTable} from '../TableContext';
|
|
6
6
|
import {TableLayout} from '../Table.types';
|
|
7
|
+
import {useTable} from '../TableContext';
|
|
7
8
|
|
|
8
9
|
type RowData = {id: string; firstName: string; lastName?: string};
|
|
9
10
|
|
|
@@ -141,6 +142,44 @@ describe('Table', () => {
|
|
|
141
142
|
expect(screen.getByRole('row', {name: 'patate king', selected: false})).toBeInTheDocument();
|
|
142
143
|
});
|
|
143
144
|
|
|
145
|
+
it('does not reset row selection when clicking within one of the specified additionalRootNodes, even if it is outside the table', async () => {
|
|
146
|
+
const user = userEvent.setup();
|
|
147
|
+
|
|
148
|
+
const Fixture = () => {
|
|
149
|
+
const [cousinNode, setCousinNode] = useState<HTMLDivElement>();
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<>
|
|
153
|
+
<div key="inside" ref={setCousinNode} data-testid="table-cousin">
|
|
154
|
+
clicking inside here does not clear rows selection
|
|
155
|
+
</div>
|
|
156
|
+
<div key="outside" data-testid="outside-element">
|
|
157
|
+
clicking inside here clears rows selection
|
|
158
|
+
</div>
|
|
159
|
+
<Table
|
|
160
|
+
getRowId={({id}) => id}
|
|
161
|
+
data={[
|
|
162
|
+
{id: '🆔-1', firstName: 'John', lastName: 'Doe'},
|
|
163
|
+
{id: '🆔-2', firstName: 'Jane', lastName: 'Doe'},
|
|
164
|
+
]}
|
|
165
|
+
columns={columns}
|
|
166
|
+
additionalRootNodes={[cousinNode]}
|
|
167
|
+
/>
|
|
168
|
+
</>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
render(<Fixture />);
|
|
172
|
+
|
|
173
|
+
const row = screen.getByRole('row', {name: /John Doe/i, selected: false});
|
|
174
|
+
expect(row).toBeInTheDocument();
|
|
175
|
+
await user.click(row);
|
|
176
|
+
expect(screen.getByRole('row', {name: /John Doe/i, selected: true})).toBeInTheDocument();
|
|
177
|
+
await user.click(screen.getByTestId('table-cousin'));
|
|
178
|
+
expect(screen.getByRole('row', {name: /John Doe/i, selected: true})).toBeInTheDocument();
|
|
179
|
+
await user.click(screen.getByTestId('outside-element'));
|
|
180
|
+
expect(screen.getByRole('row', {name: /John Doe/i, selected: false})).toBeInTheDocument();
|
|
181
|
+
});
|
|
182
|
+
|
|
144
183
|
describe('with multiple layouts', () => {
|
|
145
184
|
const layouts: TableLayout[] = [
|
|
146
185
|
{
|
|
@@ -243,13 +282,13 @@ describe('Table', () => {
|
|
|
243
282
|
onRowSelectionChange={onRowSelectionChangeSpy}
|
|
244
283
|
/>
|
|
245
284
|
);
|
|
246
|
-
await user.click(screen.getByRole('row', {name: /jane doe/i}));
|
|
285
|
+
await user.click(within(screen.getByRole('row', {name: /jane doe/i})).getByRole('checkbox'));
|
|
247
286
|
expect(onRowSelectionChangeSpy).toHaveBeenCalledTimes(1);
|
|
248
287
|
expect(onRowSelectionChangeSpy).toHaveBeenCalledWith([{id: '🆔-2', firstName: 'Jane', lastName: 'Doe'}]);
|
|
249
288
|
|
|
250
289
|
onRowSelectionChangeSpy.mockClear();
|
|
251
290
|
|
|
252
|
-
await user.click(screen.getByRole('row', {name: /john smith/i}));
|
|
291
|
+
await user.click(within(screen.getByRole('row', {name: /john smith/i})).getByRole('checkbox'));
|
|
253
292
|
expect(onRowSelectionChangeSpy).toHaveBeenCalledTimes(1);
|
|
254
293
|
expect(onRowSelectionChangeSpy).toHaveBeenCalledWith([
|
|
255
294
|
{id: '🆔-2', firstName: 'Jane', lastName: 'Doe'},
|
|
@@ -284,7 +323,7 @@ describe('Table', () => {
|
|
|
284
323
|
|
|
285
324
|
expect(row).toBeInTheDocument();
|
|
286
325
|
|
|
287
|
-
await user.click(row);
|
|
326
|
+
await user.click(within(row).getByRole('checkbox'));
|
|
288
327
|
|
|
289
328
|
expect(screen.getByRole('row', {name: /patate king/i, selected: true})).toBeInTheDocument();
|
|
290
329
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
|
|
2
|
-
import {render, screen, userEvent} from '@test-utils';
|
|
2
|
+
import {render, screen, userEvent, within} from '@test-utils';
|
|
3
3
|
|
|
4
4
|
import {Button} from '../../button';
|
|
5
5
|
import {Table} from '../Table';
|
|
@@ -57,6 +57,7 @@ describe('Table.Actions', () => {
|
|
|
57
57
|
const renderSpy = vi.fn().mockImplementation(() => <div />);
|
|
58
58
|
render(
|
|
59
59
|
<Table<RowData>
|
|
60
|
+
getRowId={(row) => row.name}
|
|
60
61
|
data={[{name: 'fruit'}, {name: 'vegetable'}, {name: 'bread'}]}
|
|
61
62
|
columns={columns}
|
|
62
63
|
multiRowSelectionEnabled
|
|
@@ -66,8 +67,8 @@ describe('Table.Actions', () => {
|
|
|
66
67
|
</Table.Header>
|
|
67
68
|
</Table>
|
|
68
69
|
);
|
|
69
|
-
await user.click(screen.getByRole('
|
|
70
|
-
await user.click(screen.getByRole('
|
|
70
|
+
await user.click(within(screen.getByRole('row', {name: /fruit/})).getByRole('checkbox'));
|
|
71
|
+
await user.click(within(screen.getByRole('row', {name: /vegetable/})).getByRole('checkbox'));
|
|
71
72
|
expect(renderSpy).toHaveBeenCalledWith([{name: 'fruit'}, {name: 'vegetable'}]);
|
|
72
73
|
});
|
|
73
74
|
});
|