@coveord/plasma-mantine 56.8.0 → 56.9.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/.turbo/turbo-build.log +4 -4
- package/.turbo/turbo-test.log +108 -103
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/components/CodeEditor/languages/xml.d.ts.map +1 -1
- package/dist/cjs/components/CodeEditor/languages/xml.js.map +1 -1
- package/dist/cjs/components/Collection/enhanceWithCollectionProps.d.ts.map +1 -1
- package/dist/cjs/components/Collection/enhanceWithCollectionProps.js.map +1 -1
- package/dist/cjs/components/DateRangePicker/DateRange.module.css +4 -0
- package/dist/cjs/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/cjs/components/DateRangePicker/DateRangePicker.js +2 -1
- package/dist/cjs/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/cjs/components/RadioCard/RadioCard.d.ts +26 -0
- package/dist/cjs/components/RadioCard/RadioCard.d.ts.map +1 -0
- package/dist/cjs/components/RadioCard/RadioCard.js +82 -0
- package/dist/cjs/components/RadioCard/RadioCard.js.map +1 -0
- package/dist/cjs/components/Table/Table.d.ts +2 -12
- package/dist/cjs/components/Table/Table.d.ts.map +1 -1
- package/dist/cjs/components/Table/Table.js +0 -3
- package/dist/cjs/components/Table/Table.js.map +1 -1
- package/dist/cjs/components/Table/table-column/TableActionsColumn.d.ts +15 -0
- package/dist/cjs/components/Table/table-column/TableActionsColumn.d.ts.map +1 -1
- package/dist/cjs/components/Table/table-column/TableActionsColumn.js +14 -1
- package/dist/cjs/components/Table/table-column/TableActionsColumn.js.map +1 -1
- package/dist/cjs/components/Table/table-columns-selector/TableColumnsSelector.d.ts +11 -32
- package/dist/cjs/components/Table/table-columns-selector/TableColumnsSelector.d.ts.map +1 -1
- package/dist/cjs/components/Table/table-columns-selector/TableColumnsSelector.js +101 -97
- package/dist/cjs/components/Table/table-columns-selector/TableColumnsSelector.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/styles/RadioCard.module.css +44 -0
- package/dist/esm/components/CodeEditor/languages/xml.d.ts.map +1 -1
- package/dist/esm/components/CodeEditor/languages/xml.js.map +1 -1
- package/dist/esm/components/Collection/enhanceWithCollectionProps.d.ts.map +1 -1
- package/dist/esm/components/Collection/enhanceWithCollectionProps.js.map +1 -1
- package/dist/esm/components/DateRangePicker/DateRange.module.css +4 -0
- package/dist/esm/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/esm/components/DateRangePicker/DateRangePicker.js +2 -1
- package/dist/esm/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/esm/components/RadioCard/RadioCard.d.ts +26 -0
- package/dist/esm/components/RadioCard/RadioCard.d.ts.map +1 -0
- package/dist/esm/components/RadioCard/RadioCard.js +63 -0
- package/dist/esm/components/RadioCard/RadioCard.js.map +1 -0
- package/dist/esm/components/Table/Table.d.ts +2 -12
- package/dist/esm/components/Table/Table.d.ts.map +1 -1
- package/dist/esm/components/Table/Table.js +0 -3
- package/dist/esm/components/Table/Table.js.map +1 -1
- package/dist/esm/components/Table/table-column/TableActionsColumn.d.ts +15 -0
- package/dist/esm/components/Table/table-column/TableActionsColumn.d.ts.map +1 -1
- package/dist/esm/components/Table/table-column/TableActionsColumn.js +12 -1
- package/dist/esm/components/Table/table-column/TableActionsColumn.js.map +1 -1
- package/dist/esm/components/Table/table-columns-selector/TableColumnsSelector.d.ts +11 -32
- package/dist/esm/components/Table/table-columns-selector/TableColumnsSelector.d.ts.map +1 -1
- package/dist/esm/components/Table/table-columns-selector/TableColumnsSelector.js +94 -84
- package/dist/esm/components/Table/table-columns-selector/TableColumnsSelector.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/styles/RadioCard.module.css +44 -0
- package/package.json +19 -19
- package/src/components/CodeEditor/languages/xml.ts +2 -1
- package/src/components/Collection/enhanceWithCollectionProps.ts +2 -2
- package/src/components/DateRangePicker/DateRange.module.css +4 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +2 -1
- package/src/components/RadioCard/RadioCard.tsx +73 -0
- package/src/components/RadioCard/__tests__/RadioCard.component.spec.tsx +25 -0
- package/src/components/Table/Table.tsx +4 -9
- package/src/components/Table/__tests__/TableColumnsSelectorHeader.spec.tsx +325 -0
- package/src/components/Table/table-column/TableActionsColumn.tsx +28 -1
- package/src/components/Table/table-columns-selector/TableColumnsSelector.tsx +96 -125
- package/src/index.ts +4 -0
- package/src/styles/RadioCard.module.css +44 -0
- package/src/components/Table/__tests__/TableColumnsSelector.spec.tsx +0 -352
|
@@ -1,50 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
CompoundStylesApiProps,
|
|
6
|
-
Divider,
|
|
7
|
-
factory,
|
|
8
|
-
Factory,
|
|
9
|
-
Grid,
|
|
10
|
-
Popover,
|
|
11
|
-
ScrollArea,
|
|
12
|
-
Stack,
|
|
13
|
-
Tooltip,
|
|
14
|
-
useProps,
|
|
15
|
-
} from '@mantine/core';
|
|
16
|
-
import {flexRender, Header} from '@tanstack/react-table';
|
|
17
|
-
import {ReactNode} from 'react';
|
|
18
|
-
import {TableComponentsOrder} from '../Table.js';
|
|
19
|
-
import {useTableContext} from '../TableContext.js';
|
|
1
|
+
import {IconSettings} from '@coveord/plasma-react-icons';
|
|
2
|
+
import {Checkbox, Combobox, Text, Tooltip, useCombobox} from '@mantine/core';
|
|
3
|
+
import {flexRender, Header, Table} from '@tanstack/react-table';
|
|
4
|
+
import {ActionIcon} from '../../ActionIcon/ActionIcon';
|
|
20
5
|
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
export interface TableColumnsSelectorProps extends BoxProps, CompoundStylesApiProps<TableColumnsSelectorFactory> {
|
|
24
|
-
/**
|
|
25
|
-
* The label of the button
|
|
26
|
-
* @default 'Edit columns'
|
|
27
|
-
*/
|
|
28
|
-
label?: ReactNode;
|
|
29
|
-
/**
|
|
30
|
-
* The style variant of the button
|
|
31
|
-
* @default 'outline'
|
|
32
|
-
*/
|
|
33
|
-
buttonVariant?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Whether the count of visible columns is shown in the button label.
|
|
36
|
-
* @default false
|
|
37
|
-
*/
|
|
38
|
-
showVisibleCountLabel?: boolean;
|
|
6
|
+
export interface TableColumnsSelectorOptions {
|
|
39
7
|
/**
|
|
40
8
|
* The maximum number of columns that can be selected at the same time.
|
|
41
9
|
* If defined a footer will render with the remaining number of columns that can be selected.
|
|
10
|
+
* Must be a positive integer (greater than 0).
|
|
42
11
|
*/
|
|
43
12
|
maxSelectableColumns?: number;
|
|
44
13
|
/**
|
|
45
14
|
* The content to display in the footer when maxSelectableColumns is defined.
|
|
15
|
+
* Can be a string or a function that receives the maxSelectableColumns value.
|
|
16
|
+
* @default (max) => `You can display up to ${max} columns.`
|
|
46
17
|
*/
|
|
47
|
-
footer?:
|
|
18
|
+
footer?: string | ((maxSelectableColumns: number) => string);
|
|
48
19
|
/**
|
|
49
20
|
* The tooltip to display when the user hovers over a disabled checkbox because of the limit.
|
|
50
21
|
* @default 'You have reached the maximum display limit.'
|
|
@@ -57,108 +28,108 @@ export interface TableColumnsSelectorProps extends BoxProps, CompoundStylesApiPr
|
|
|
57
28
|
alwaysVisibleTooltip?: string;
|
|
58
29
|
}
|
|
59
30
|
|
|
60
|
-
export
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
compound: true;
|
|
65
|
-
}>;
|
|
31
|
+
export interface TableColumnsSelectorHeaderProps {
|
|
32
|
+
table: Table<unknown>;
|
|
33
|
+
options?: TableColumnsSelectorOptions;
|
|
34
|
+
}
|
|
66
35
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
36
|
+
const DEFAULT_OPTIONS: Omit<TableColumnsSelectorOptions, 'footer'> & {
|
|
37
|
+
footer: (maxSelectableColumns: number) => string;
|
|
38
|
+
} = {
|
|
39
|
+
footer: (max) => `You can display up to ${max} columns.`,
|
|
70
40
|
limitReachedTooltip: 'You have reached the maximum display limit.',
|
|
71
41
|
alwaysVisibleTooltip: 'This column is always visible.',
|
|
72
|
-
showVisibleCountLabel: false,
|
|
73
42
|
};
|
|
74
43
|
|
|
75
|
-
export const
|
|
76
|
-
const {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
showVisibleCountLabel,
|
|
81
|
-
maxSelectableColumns,
|
|
82
|
-
footer,
|
|
83
|
-
limitReachedTooltip,
|
|
84
|
-
alwaysVisibleTooltip,
|
|
85
|
-
classNames,
|
|
86
|
-
className,
|
|
87
|
-
styles,
|
|
88
|
-
style,
|
|
89
|
-
vars,
|
|
90
|
-
...others
|
|
91
|
-
} = useProps('TableColumnsSelector', defaultProps, props);
|
|
92
|
-
const {table} = useTableContext();
|
|
44
|
+
export const TableColumnsSelectorHeader = ({table, options}: TableColumnsSelectorHeaderProps) => {
|
|
45
|
+
const {maxSelectableColumns, footer, limitReachedTooltip, alwaysVisibleTooltip} = {
|
|
46
|
+
...DEFAULT_OPTIONS,
|
|
47
|
+
...options,
|
|
48
|
+
};
|
|
93
49
|
|
|
94
|
-
const
|
|
50
|
+
const combobox = useCombobox({
|
|
51
|
+
onDropdownClose: () => {
|
|
52
|
+
combobox.resetSelectedOption();
|
|
53
|
+
},
|
|
54
|
+
onDropdownOpen: () => combobox.updateSelectedOptionIndex('active'),
|
|
55
|
+
});
|
|
95
56
|
|
|
57
|
+
const allColumns = table.getAllLeafColumns();
|
|
96
58
|
const filteredColumns = allColumns.filter((column) => !column.columnDef.meta?.controlColumn);
|
|
97
59
|
const selectedColumnsCount = filteredColumns.filter((column) => column.getIsVisible()).length;
|
|
98
60
|
|
|
61
|
+
// Validate maxSelectableColumns - must be a positive integer to be effective
|
|
62
|
+
const effectiveMaxColumns =
|
|
63
|
+
maxSelectableColumns !== undefined && maxSelectableColumns > 0 ? maxSelectableColumns : undefined;
|
|
64
|
+
|
|
99
65
|
if (filteredColumns.length <= 0) {
|
|
100
66
|
return null;
|
|
101
67
|
}
|
|
102
68
|
|
|
103
|
-
const
|
|
69
|
+
const getColumnState = (column: (typeof filteredColumns)[number]) => {
|
|
70
|
+
const alwaysVisible = !column.getCanHide();
|
|
71
|
+
const isDisabled =
|
|
72
|
+
(effectiveMaxColumns !== undefined &&
|
|
73
|
+
selectedColumnsCount >= effectiveMaxColumns &&
|
|
74
|
+
!column.getIsVisible()) ||
|
|
75
|
+
alwaysVisible;
|
|
76
|
+
const isVisible = column.getIsVisible() || alwaysVisible;
|
|
77
|
+
return {alwaysVisible, isDisabled, isVisible};
|
|
78
|
+
};
|
|
104
79
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<Button variant={buttonVariant}>
|
|
115
|
-
{label}
|
|
116
|
-
{showVisibleCountLabel ? ` (${selectedColumnsCount})` : ''}
|
|
117
|
-
</Button>
|
|
118
|
-
</Popover.Target>
|
|
119
|
-
<Popover.Dropdown miw={240}>
|
|
120
|
-
<ScrollArea.Autosize mah={154}>
|
|
121
|
-
<Stack {...getStyles('columnSelectorWrapper', stylesApiProps)}>
|
|
122
|
-
{filteredColumns.map((column) => {
|
|
123
|
-
const alwaysVisible = !column.getCanHide();
|
|
124
|
-
const isDisabled =
|
|
125
|
-
(selectedColumnsCount >= maxSelectableColumns && !column.getIsVisible()) ||
|
|
126
|
-
alwaysVisible;
|
|
80
|
+
const handleOptionClick = (columnId: string) => {
|
|
81
|
+
const column = filteredColumns.find((col) => col.id === columnId);
|
|
82
|
+
if (column) {
|
|
83
|
+
const {isDisabled} = getColumnState(column);
|
|
84
|
+
if (!isDisabled) {
|
|
85
|
+
column.toggleVisibility();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
127
89
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
disabled={isDisabled}
|
|
146
|
-
onChange={column.getToggleVisibilityHandler()}
|
|
147
|
-
/>
|
|
148
|
-
</div>
|
|
149
|
-
</Tooltip>
|
|
150
|
-
);
|
|
90
|
+
const columnOptions = filteredColumns.map((column) => {
|
|
91
|
+
const {alwaysVisible, isDisabled, isVisible} = getColumnState(column);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Combobox.Option value={column.id} key={column.id} disabled={isDisabled} active={isVisible}>
|
|
95
|
+
<Tooltip
|
|
96
|
+
label={alwaysVisible ? alwaysVisibleTooltip : limitReachedTooltip}
|
|
97
|
+
disabled={!isDisabled}
|
|
98
|
+
position="left"
|
|
99
|
+
>
|
|
100
|
+
<div>
|
|
101
|
+
<Checkbox
|
|
102
|
+
checked={isVisible}
|
|
103
|
+
label={flexRender(column.columnDef.header, {
|
|
104
|
+
table,
|
|
105
|
+
column,
|
|
106
|
+
header: {column} as Header<unknown, unknown>,
|
|
151
107
|
})}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
108
|
+
disabled={isDisabled}
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
</Tooltip>
|
|
112
|
+
</Combobox.Option>
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Combobox store={combobox} position="bottom-end" shadow="md" onOptionSubmit={handleOptionClick}>
|
|
118
|
+
<Combobox.Target>
|
|
119
|
+
<ActionIcon.Tertiary onClick={() => combobox.toggleDropdown()} aria-label="settings">
|
|
120
|
+
<IconSettings height={16} />
|
|
121
|
+
</ActionIcon.Tertiary>
|
|
122
|
+
</Combobox.Target>
|
|
123
|
+
<Combobox.Dropdown miw={270}>
|
|
124
|
+
<Combobox.Options>{columnOptions}</Combobox.Options>
|
|
125
|
+
{effectiveMaxColumns && (
|
|
126
|
+
<Combobox.Footer>
|
|
127
|
+
<Text size="sm" c="dimmed">
|
|
128
|
+
{typeof footer === 'function' ? footer(effectiveMaxColumns) : footer}
|
|
129
|
+
</Text>
|
|
130
|
+
</Combobox.Footer>
|
|
131
|
+
)}
|
|
132
|
+
</Combobox.Dropdown>
|
|
133
|
+
</Combobox>
|
|
163
134
|
);
|
|
164
|
-
}
|
|
135
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -106,6 +106,9 @@ export * from './components/Modal/ModalFooter.js';
|
|
|
106
106
|
// Prompt
|
|
107
107
|
export * from './components/Prompt/Prompt.js';
|
|
108
108
|
|
|
109
|
+
// RadioCard - override Mantine RadioCard
|
|
110
|
+
export {RadioCard, type RadioCardProps} from './components/RadioCard/RadioCard.js';
|
|
111
|
+
|
|
109
112
|
// Read Only - override Mantine PasswordInput and Select
|
|
110
113
|
export {PasswordInput} from './components/PasswordInput/PasswordInput.js';
|
|
111
114
|
export {Select} from './components/Select/Select.js';
|
|
@@ -115,6 +118,7 @@ export * from './components/StickyFooter/StickyFooter.js';
|
|
|
115
118
|
|
|
116
119
|
// Table - override Mantine Table
|
|
117
120
|
export {flexRender as renderTableCell} from '@tanstack/react-table';
|
|
121
|
+
export {TableActionsColumn} from './components/Table/table-column/TableActionsColumn.js';
|
|
118
122
|
export {type TablePredicateProps} from './components/Table/table-predicate/TablePredicate.js';
|
|
119
123
|
export {Table, TableComponentsOrder, type PlasmaTableFactory} from './components/Table/Table.js';
|
|
120
124
|
export {
|
|
@@ -5,7 +5,51 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.card {
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
align-items: flex-start;
|
|
11
|
+
padding: var(--mantine-spacing-sm);
|
|
12
|
+
border-radius: var(--mantine-radius-lg);
|
|
13
|
+
|
|
14
|
+
&[data-checked] {
|
|
15
|
+
border-color: var(--mantine-primary-color-filled);
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
&[disabled] {
|
|
9
19
|
pointer-events: none;
|
|
20
|
+
|
|
21
|
+
.title {
|
|
22
|
+
color: var(--mantine-color-disabled-color);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.description {
|
|
26
|
+
color: var(--mantine-color-disabled-color);
|
|
27
|
+
}
|
|
10
28
|
}
|
|
11
29
|
}
|
|
30
|
+
|
|
31
|
+
.container {
|
|
32
|
+
flex-wrap: nowrap;
|
|
33
|
+
gap: var(--mantine-spacing-sm);
|
|
34
|
+
align-items: baseline;
|
|
35
|
+
justify-content: flex-start;
|
|
36
|
+
width: 100%;
|
|
37
|
+
margin-bottom: var(--mantine-spacing-xs);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.title {
|
|
41
|
+
flex: 1;
|
|
42
|
+
color: var(--coveo-color-title);
|
|
43
|
+
word-break: break-word;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.description {
|
|
47
|
+
padding-left: var(--mantine-spacing-lg);
|
|
48
|
+
color: var(--mantine-color-dimmed);
|
|
49
|
+
font-weight: 400;
|
|
50
|
+
font-size: var(--mantine-font-size-xs);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.indicator {
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
import {Box} from '@mantine/core';
|
|
2
|
-
import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
|
|
3
|
-
import {render, screen, userEvent, waitFor, within} from '@test-utils';
|
|
4
|
-
import {Table} from '../Table.js';
|
|
5
|
-
import {TableColumnsSelector} from '../table-columns-selector/TableColumnsSelector.js';
|
|
6
|
-
import {useTable} from '../use-table.js';
|
|
7
|
-
|
|
8
|
-
const mockData = [
|
|
9
|
-
{
|
|
10
|
-
name: 'John Doe',
|
|
11
|
-
age: 30,
|
|
12
|
-
email: 'john.doe@example.com',
|
|
13
|
-
phone: '123-456-7890',
|
|
14
|
-
body: 'coucou',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
name: 'Jane Doe',
|
|
18
|
-
age: 25,
|
|
19
|
-
email: 'jane.doe@example.com',
|
|
20
|
-
phone: '098-765-4321',
|
|
21
|
-
body: 'coucou 2',
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
type RowData = {
|
|
26
|
-
name: string;
|
|
27
|
-
age: number;
|
|
28
|
-
email: string;
|
|
29
|
-
phone: string;
|
|
30
|
-
body: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const columnHelper = createColumnHelper<RowData>();
|
|
34
|
-
const baseColumns: Array<ColumnDef<RowData>> = [
|
|
35
|
-
columnHelper.accessor('name', {header: 'Name', enableSorting: false}),
|
|
36
|
-
columnHelper.accessor('age', {header: 'Age', enableSorting: false}),
|
|
37
|
-
columnHelper.accessor('email', {header: 'Email', enableSorting: false}),
|
|
38
|
-
columnHelper.accessor('phone', {header: 'Phone', enableSorting: false}),
|
|
39
|
-
Table.CollapsibleColumn as ColumnDef<RowData>,
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
describe('TableColumnsSelector', () => {
|
|
43
|
-
it('render the edit button in the table header', () => {
|
|
44
|
-
const Fixture = () => {
|
|
45
|
-
const store = useTable<RowData>();
|
|
46
|
-
return (
|
|
47
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
48
|
-
<Table.Header>
|
|
49
|
-
<TableColumnsSelector />
|
|
50
|
-
</Table.Header>
|
|
51
|
-
</Table>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
render(<Fixture />);
|
|
55
|
-
|
|
56
|
-
expect(screen.getByRole('button', {name: 'Edit columns'})).toBeVisible();
|
|
57
|
-
expect(screen.queryByRole('button', {name: 'Edit columns (4)'})).not.toBeInTheDocument();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('renders the custom label when defined', () => {
|
|
61
|
-
const Fixture = () => {
|
|
62
|
-
const store = useTable<RowData>();
|
|
63
|
-
return (
|
|
64
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
65
|
-
<Table.Header>
|
|
66
|
-
<TableColumnsSelector label="Custom label" />
|
|
67
|
-
</Table.Header>
|
|
68
|
-
</Table>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
71
|
-
render(<Fixture />);
|
|
72
|
-
|
|
73
|
-
expect(screen.getByRole('button', {name: 'Custom label'})).toBeVisible();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('renders the count of visible columns if showVisibleCountLabel is true', () => {
|
|
77
|
-
const Fixture = () => {
|
|
78
|
-
const store = useTable<RowData>();
|
|
79
|
-
return (
|
|
80
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
81
|
-
<Table.Header>
|
|
82
|
-
<TableColumnsSelector showVisibleCountLabel />
|
|
83
|
-
</Table.Header>
|
|
84
|
-
</Table>
|
|
85
|
-
);
|
|
86
|
-
};
|
|
87
|
-
render(<Fixture />);
|
|
88
|
-
|
|
89
|
-
expect(screen.getByRole('button', {name: 'Edit columns (4)'})).toBeVisible();
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('renders all columns in the dropdown, except the collapsible and the multiselectRow by default', async () => {
|
|
93
|
-
const user = userEvent.setup();
|
|
94
|
-
const Fixture = () => {
|
|
95
|
-
const store = useTable<RowData>({enableMultiRowSelection: true});
|
|
96
|
-
return (
|
|
97
|
-
<Table
|
|
98
|
-
store={store}
|
|
99
|
-
data={mockData}
|
|
100
|
-
columns={baseColumns}
|
|
101
|
-
getRowExpandedContent={(datum) => <Box py="xs">{datum.body}</Box>}
|
|
102
|
-
>
|
|
103
|
-
<Table.Header>
|
|
104
|
-
<TableColumnsSelector />
|
|
105
|
-
</Table.Header>
|
|
106
|
-
</Table>
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
render(<Fixture />);
|
|
110
|
-
|
|
111
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
112
|
-
const dropdown = await screen.findByRole('dialog', {name: 'Edit columns'});
|
|
113
|
-
const columnsCheckboxes = within(dropdown).getAllByRole('checkbox');
|
|
114
|
-
|
|
115
|
-
expect(columnsCheckboxes).toHaveLength(4);
|
|
116
|
-
expect(columnsCheckboxes[0]).toHaveAccessibleName('Name');
|
|
117
|
-
expect(columnsCheckboxes[1]).toHaveAccessibleName('Age');
|
|
118
|
-
expect(columnsCheckboxes[2]).toHaveAccessibleName('Email');
|
|
119
|
-
expect(columnsCheckboxes[3]).toHaveAccessibleName('Phone');
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('renders all checkboxes checked by default', async () => {
|
|
123
|
-
const user = userEvent.setup();
|
|
124
|
-
const Fixture = () => {
|
|
125
|
-
const store = useTable<RowData>();
|
|
126
|
-
return (
|
|
127
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
128
|
-
<Table.Header>
|
|
129
|
-
<TableColumnsSelector />
|
|
130
|
-
</Table.Header>
|
|
131
|
-
</Table>
|
|
132
|
-
);
|
|
133
|
-
};
|
|
134
|
-
render(<Fixture />);
|
|
135
|
-
|
|
136
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
137
|
-
|
|
138
|
-
expect(await screen.findByRole('checkbox', {name: 'Name'})).toBeChecked();
|
|
139
|
-
expect(screen.getByRole('checkbox', {name: 'Age'})).toBeChecked();
|
|
140
|
-
expect(screen.getByRole('checkbox', {name: 'Email'})).toBeChecked();
|
|
141
|
-
expect(screen.getByRole('checkbox', {name: 'Phone'})).toBeChecked();
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('renders a disabled checked checkbox for columns that are always visible', async () => {
|
|
145
|
-
const columns: Array<ColumnDef<RowData>> = [
|
|
146
|
-
columnHelper.accessor('name', {header: 'Name', enableSorting: false}),
|
|
147
|
-
columnHelper.accessor('age', {header: 'Age', enableSorting: false, enableHiding: false}),
|
|
148
|
-
columnHelper.accessor('email', {header: 'Email', enableSorting: false}),
|
|
149
|
-
columnHelper.accessor('phone', {header: 'Phone', enableSorting: false}),
|
|
150
|
-
];
|
|
151
|
-
const user = userEvent.setup();
|
|
152
|
-
const Fixture = () => {
|
|
153
|
-
const store = useTable<RowData>();
|
|
154
|
-
return (
|
|
155
|
-
<Table store={store} data={mockData} columns={columns}>
|
|
156
|
-
<Table.Header>
|
|
157
|
-
<TableColumnsSelector />
|
|
158
|
-
</Table.Header>
|
|
159
|
-
</Table>
|
|
160
|
-
);
|
|
161
|
-
};
|
|
162
|
-
render(<Fixture />);
|
|
163
|
-
|
|
164
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
165
|
-
|
|
166
|
-
expect(await screen.findByRole('checkbox', {name: 'Name'})).toBeChecked();
|
|
167
|
-
expect(screen.getByRole('checkbox', {name: 'Email'})).toBeChecked();
|
|
168
|
-
expect(screen.getByRole('checkbox', {name: 'Phone'})).toBeChecked();
|
|
169
|
-
|
|
170
|
-
const ageColumn = screen.getByRole('checkbox', {name: 'Age'});
|
|
171
|
-
expect(ageColumn).toBeChecked();
|
|
172
|
-
expect(ageColumn).toBeDisabled();
|
|
173
|
-
await user.hover(ageColumn.parentElement);
|
|
174
|
-
await waitFor(() => {
|
|
175
|
-
expect(screen.getByRole('tooltip', {name: 'This column is always visible.'})).toBeVisible();
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('renders unchecked checkboxes for the columns that are not visible in the inital state of the table', async () => {
|
|
180
|
-
const user = userEvent.setup();
|
|
181
|
-
const Fixture = () => {
|
|
182
|
-
const store = useTable<RowData>({initialState: {columnVisibility: {email: false}}});
|
|
183
|
-
return (
|
|
184
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
185
|
-
<Table.Header>
|
|
186
|
-
<TableColumnsSelector />
|
|
187
|
-
</Table.Header>
|
|
188
|
-
</Table>
|
|
189
|
-
);
|
|
190
|
-
};
|
|
191
|
-
render(<Fixture />);
|
|
192
|
-
|
|
193
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
194
|
-
|
|
195
|
-
expect(await screen.findByRole('checkbox', {name: 'Name'})).toBeChecked();
|
|
196
|
-
expect(screen.getByRole('checkbox', {name: 'Age'})).toBeChecked();
|
|
197
|
-
expect(screen.getByRole('checkbox', {name: 'Email'})).not.toBeChecked();
|
|
198
|
-
expect(screen.getByRole('checkbox', {name: 'Phone'})).toBeChecked();
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it('renders disabled checkboxes when the maxSelectableColumns is set and the maximum number of columns is checked', async () => {
|
|
202
|
-
const user = userEvent.setup();
|
|
203
|
-
const Fixture = () => {
|
|
204
|
-
const store = useTable<RowData>({initialState: {columnVisibility: {email: false}}});
|
|
205
|
-
return (
|
|
206
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
207
|
-
<Table.Header>
|
|
208
|
-
<TableColumnsSelector maxSelectableColumns={3} />
|
|
209
|
-
</Table.Header>
|
|
210
|
-
</Table>
|
|
211
|
-
);
|
|
212
|
-
};
|
|
213
|
-
render(<Fixture />);
|
|
214
|
-
|
|
215
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
216
|
-
|
|
217
|
-
const nameCheckBox = await screen.findByRole('checkbox', {name: /name/i});
|
|
218
|
-
const ageCheckBox = screen.getByRole('checkbox', {name: /age/i});
|
|
219
|
-
const emailCheckBox = screen.getByRole('checkbox', {name: /email/i});
|
|
220
|
-
const phoneCheckBox = screen.getByRole('checkbox', {name: /phone/i});
|
|
221
|
-
|
|
222
|
-
expect(nameCheckBox).toBeChecked();
|
|
223
|
-
expect(nameCheckBox).toBeEnabled();
|
|
224
|
-
expect(ageCheckBox).toBeChecked();
|
|
225
|
-
expect(ageCheckBox).toBeEnabled();
|
|
226
|
-
expect(emailCheckBox).not.toBeChecked();
|
|
227
|
-
expect(emailCheckBox).toBeDisabled();
|
|
228
|
-
expect(phoneCheckBox).toBeChecked();
|
|
229
|
-
expect(phoneCheckBox).toBeEnabled();
|
|
230
|
-
|
|
231
|
-
await user.click(nameCheckBox);
|
|
232
|
-
|
|
233
|
-
expect(nameCheckBox).toBeEnabled();
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('renders a tooltip when the maxSelectableColumns is set and the maximum number of columns is checked and the user hover a disabled checkbox', async () => {
|
|
237
|
-
const user = userEvent.setup();
|
|
238
|
-
const Fixture = () => {
|
|
239
|
-
const store = useTable<RowData>({initialState: {columnVisibility: {email: false}}});
|
|
240
|
-
return (
|
|
241
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
242
|
-
<Table.Header>
|
|
243
|
-
<TableColumnsSelector
|
|
244
|
-
maxSelectableColumns={3}
|
|
245
|
-
limitReachedTooltip="You can display up to 3 columns"
|
|
246
|
-
/>
|
|
247
|
-
</Table.Header>
|
|
248
|
-
</Table>
|
|
249
|
-
);
|
|
250
|
-
};
|
|
251
|
-
render(<Fixture />);
|
|
252
|
-
|
|
253
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
254
|
-
|
|
255
|
-
const emailCheckBoxWrapper = (await screen.findByRole('checkbox', {name: /email/i})).parentElement;
|
|
256
|
-
|
|
257
|
-
await user.hover(emailCheckBoxWrapper);
|
|
258
|
-
|
|
259
|
-
await waitFor(() => expect(screen.getByText('You can display up to 3 columns')).toBeVisible());
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
describe('footer', () => {
|
|
263
|
-
it('does not render the footer when maxSelectableColumns is not defined', async () => {
|
|
264
|
-
const user = userEvent.setup();
|
|
265
|
-
const Fixture = () => {
|
|
266
|
-
const store = useTable<RowData>();
|
|
267
|
-
return (
|
|
268
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
269
|
-
<Table.Header>
|
|
270
|
-
<TableColumnsSelector />
|
|
271
|
-
</Table.Header>
|
|
272
|
-
</Table>
|
|
273
|
-
);
|
|
274
|
-
};
|
|
275
|
-
render(<Fixture />);
|
|
276
|
-
|
|
277
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
278
|
-
|
|
279
|
-
expect(screen.queryByText('You can display up to 3 columns')).not.toBeInTheDocument();
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('renders the footer when maxSelectableColumns is defined and footer is defined', async () => {
|
|
283
|
-
const user = userEvent.setup();
|
|
284
|
-
const Fixture = () => {
|
|
285
|
-
const store = useTable<RowData>();
|
|
286
|
-
return (
|
|
287
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
288
|
-
<Table.Header>
|
|
289
|
-
<TableColumnsSelector maxSelectableColumns={3} footer="You can display so many patate" />
|
|
290
|
-
</Table.Header>
|
|
291
|
-
</Table>
|
|
292
|
-
);
|
|
293
|
-
};
|
|
294
|
-
render(<Fixture />);
|
|
295
|
-
|
|
296
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
297
|
-
|
|
298
|
-
await waitFor(() => expect(screen.getByText('You can display so many patate')).toBeVisible());
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
describe('when url sync is activated', () => {
|
|
303
|
-
afterEach(() => {
|
|
304
|
-
window.history.replaceState(null, '', '/');
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('sets the current visible column ids in the url', async () => {
|
|
308
|
-
const user = userEvent.setup();
|
|
309
|
-
const Fixture = () => {
|
|
310
|
-
const store = useTable<RowData>({
|
|
311
|
-
syncWithUrl: true,
|
|
312
|
-
initialState: {columnVisibility: {email: false, phone: true}},
|
|
313
|
-
});
|
|
314
|
-
return (
|
|
315
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
316
|
-
<Table.Header>
|
|
317
|
-
<TableColumnsSelector />
|
|
318
|
-
</Table.Header>
|
|
319
|
-
</Table>
|
|
320
|
-
);
|
|
321
|
-
};
|
|
322
|
-
render(<Fixture />);
|
|
323
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
324
|
-
const emailCheckBox = await screen.findByRole('checkbox', {name: /email/i});
|
|
325
|
-
await user.click(emailCheckBox);
|
|
326
|
-
await user.click(screen.getByRole('checkbox', {name: /phone/i}));
|
|
327
|
-
expect(window.location.search).toBe('?show=email&hide=phone');
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('determines the initial visible columns from the url', async () => {
|
|
331
|
-
window.history.replaceState(null, '', '?show=email%2Cphone');
|
|
332
|
-
const user = userEvent.setup();
|
|
333
|
-
const Fixture = () => {
|
|
334
|
-
const store = useTable<RowData>({
|
|
335
|
-
syncWithUrl: true,
|
|
336
|
-
initialState: {columnVisibility: {email: false, phone: false}},
|
|
337
|
-
});
|
|
338
|
-
return (
|
|
339
|
-
<Table store={store} data={mockData} columns={baseColumns}>
|
|
340
|
-
<Table.Header>
|
|
341
|
-
<TableColumnsSelector />
|
|
342
|
-
</Table.Header>
|
|
343
|
-
</Table>
|
|
344
|
-
);
|
|
345
|
-
};
|
|
346
|
-
render(<Fixture />);
|
|
347
|
-
await user.click(screen.getByRole('button', {name: 'Edit columns'}));
|
|
348
|
-
expect(await screen.findByRole('checkbox', {name: /email/i})).toBeChecked();
|
|
349
|
-
expect(screen.getByRole('checkbox', {name: /phone/i})).toBeChecked();
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
});
|