@cutting/material-react-table 4.1.0 → 5.0.0-beta.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/dist/index.d.ts +360 -333
- package/dist/index.js +919 -928
- package/dist/index.js.map +1 -1
- package/locales/ar/package.json +2 -2
- package/locales/az/package.json +2 -2
- package/locales/bg/package.json +2 -2
- package/locales/cs/package.json +2 -2
- package/locales/da/package.json +2 -2
- package/locales/de/package.json +2 -2
- package/locales/el/package.json +2 -2
- package/locales/en/package.json +2 -2
- package/locales/es/package.json +2 -2
- package/locales/et/package.json +2 -2
- package/locales/fa/package.json +2 -2
- package/locales/fi/package.json +2 -2
- package/locales/fr/package.json +2 -2
- package/locales/he/package.json +2 -2
- package/locales/hr/package.json +2 -2
- package/locales/hu/package.json +2 -2
- package/locales/hy/package.json +2 -2
- package/locales/id/package.json +2 -2
- package/locales/it/package.json +2 -2
- package/locales/ja/package.json +2 -2
- package/locales/ko/package.json +2 -2
- package/locales/nl/package.json +2 -2
- package/locales/no/package.json +2 -2
- package/locales/np/package.json +2 -2
- package/locales/pl/package.json +2 -2
- package/locales/pt/package.json +2 -2
- package/locales/pt-BR/package.json +2 -2
- package/locales/ro/package.json +2 -2
- package/locales/ru/package.json +2 -2
- package/locales/sk/package.json +2 -2
- package/locales/sr-Cyrl-RS/package.json +2 -2
- package/locales/sr-Latn-RS/package.json +2 -2
- package/locales/sv/package.json +2 -2
- package/locales/tr/package.json +2 -2
- package/locales/uk/package.json +2 -2
- package/locales/vi/package.json +2 -2
- package/locales/zh-Hans/package.json +2 -2
- package/locales/zh-Hant/package.json +2 -2
- package/package.json +46 -61
- package/src/components/body/MRT_TableBody.tsx +1 -2
- package/src/components/body/MRT_TableBodyCell.tsx +4 -5
- package/src/components/body/MRT_TableBodyCellValue.tsx +1 -2
- package/src/components/body/MRT_TableBodyRow.tsx +1 -2
- package/src/components/body/MRT_TableBodyRowGrabHandle.test.tsx +42 -0
- package/src/components/body/MRT_TableBodyRowPinButton.tsx +1 -2
- package/src/components/body/MRT_TableDetailPanel.test.tsx +40 -0
- package/src/components/body/MRT_TableDetailPanel.tsx +1 -2
- package/src/components/buttons/MRT_ColumnPinningButtons.test.tsx +69 -0
- package/src/components/buttons/MRT_ColumnPinningButtons.tsx +3 -3
- package/src/components/buttons/MRT_EditActionButtons.test.tsx +50 -0
- package/src/components/buttons/MRT_EditActionButtons.tsx +1 -3
- package/src/components/buttons/MRT_ExpandAllButton.tsx +1 -2
- package/src/components/buttons/MRT_ExpandButton.tsx +1 -2
- package/src/components/buttons/MRT_ToggleDensePaddingButton.test.tsx +38 -0
- package/src/components/buttons/MRT_ToggleDensePaddingButton.tsx +1 -2
- package/src/components/buttons/MRT_ToggleFiltersButton.test.tsx +38 -0
- package/src/components/buttons/MRT_ToggleFiltersButton.tsx +1 -2
- package/src/components/buttons/MRT_ToggleFullScreenButton.test.tsx +36 -0
- package/src/components/buttons/MRT_ToggleFullScreenButton.tsx +1 -2
- package/src/components/buttons/MRT_ToggleGlobalFilterButton.tsx +1 -2
- package/src/components/buttons/MRT_ToggleRowActionMenuButton.tsx +2 -3
- package/src/components/footer/MRT_TableFooter.tsx +1 -2
- package/src/components/footer/MRT_TableFooterCell.tsx +1 -2
- package/src/components/head/MRT_TableHead.tsx +1 -2
- package/src/components/head/MRT_TableHeadCell.tsx +9 -9
- package/src/components/head/MRT_TableHeadCellFilterContainer.tsx +1 -2
- package/src/components/head/MRT_TableHeadCellGrabHandle.test.tsx +61 -0
- package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +4 -5
- package/src/components/head/MRT_TableHeadCellResizeHandle.test.tsx +45 -0
- package/src/components/head/MRT_TableHeadCellResizeHandle.tsx +4 -5
- package/src/components/head/MRT_TableHeadCellSortLabel.tsx +1 -2
- package/src/components/inputs/MRT_EditCellTextField.test.tsx +36 -0
- package/src/components/inputs/MRT_EditCellTextField.tsx +1 -3
- package/src/components/inputs/MRT_FilterCheckbox.tsx +1 -2
- package/src/components/inputs/MRT_FilterRangeSlider.tsx +2 -1
- package/src/components/inputs/MRT_FilterTextField.test.tsx +75 -0
- package/src/components/inputs/MRT_GlobalFilterTextField.tsx +1 -2
- package/src/components/inputs/MRT_SelectCheckbox.test.tsx +69 -0
- package/src/components/inputs/MRT_SelectCheckbox.tsx +1 -2
- package/src/components/menus/MRT_CellActionMenu.tsx +1 -2
- package/src/components/menus/MRT_ColumnActionMenu.tsx +12 -13
- package/src/components/menus/MRT_FilterOptionMenu.tsx +1 -2
- package/src/components/menus/MRT_RowActionMenu.tsx +1 -2
- package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +1 -2
- package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +4 -5
- package/src/components/modals/MRT_EditRowModal.test.tsx +54 -0
- package/src/components/modals/MRT_EditRowModal.tsx +1 -2
- package/src/components/table/MRT_Table.tsx +4 -5
- package/src/components/table/MRT_TableContainer.tsx +1 -2
- package/src/components/table/MRT_TablePaper.tsx +1 -2
- package/src/components/toolbar/MRT_BottomToolbar.tsx +2 -3
- package/src/components/toolbar/MRT_LinearProgressBar.tsx +1 -2
- package/src/components/toolbar/MRT_TablePagination.tsx +1 -2
- package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +3 -4
- package/src/components/toolbar/MRT_ToolbarDropZone.test.tsx +42 -0
- package/src/components/toolbar/MRT_ToolbarDropZone.tsx +1 -2
- package/src/components/toolbar/MRT_TopToolbar.tsx +1 -2
- package/src/fns/aggregationFns.test.tsx +57 -0
- package/src/fns/filterFns.test.tsx +156 -0
- package/src/fns/filterFns.ts +36 -22
- package/src/fns/sortingFns.ts +14 -5
- package/src/fns/tableFeatures.test.tsx +106 -0
- package/src/fns/tableFeatures.ts +103 -0
- package/src/hooks/display-columns/getMRT_RowExpandColumnDef.tsx +2 -2
- package/src/hooks/useMRT_ColumnVirtualizer.ts +6 -5
- package/src/hooks/useMRT_Effects.ts +3 -4
- package/src/hooks/useMRT_RowVirtualizer.ts +1 -2
- package/src/hooks/useMRT_Rows.ts +1 -2
- package/src/hooks/useMRT_TableInstance.ts +82 -63
- package/src/hooks/useMRT_TableOptions.ts +5 -37
- package/src/icons.ts +1 -1
- package/src/types.ts +162 -134
- package/src/utils/column.utils.ts +31 -24
- package/src/utils/row.utils.ts +7 -10
- package/src/utils/style.utils.ts +9 -10
- package/src/utils/tanstack.helpers.ts +2 -2
- package/dist/index.d.mts +0 -1925
- package/dist/index.mjs +0 -5409
- package/dist/index.mjs.map +0 -1
- package/locales/ar/index.d.ts +0 -3
- package/locales/ar/index.js +0 -98
- package/locales/az/index.d.ts +0 -3
- package/locales/az/index.js +0 -98
- package/locales/bg/index.d.ts +0 -3
- package/locales/bg/index.js +0 -98
- package/locales/cs/index.d.ts +0 -3
- package/locales/cs/index.js +0 -98
- package/locales/da/index.d.ts +0 -3
- package/locales/da/index.js +0 -98
- package/locales/de/index.d.ts +0 -3
- package/locales/de/index.js +0 -98
- package/locales/el/index.d.ts +0 -3
- package/locales/el/index.js +0 -98
- package/locales/en/index.d.ts +0 -3
- package/locales/en/index.js +0 -98
- package/locales/es/index.d.ts +0 -3
- package/locales/es/index.js +0 -98
- package/locales/et/index.d.ts +0 -3
- package/locales/et/index.js +0 -98
- package/locales/fa/index.d.ts +0 -3
- package/locales/fa/index.js +0 -98
- package/locales/fi/index.d.ts +0 -3
- package/locales/fi/index.js +0 -98
- package/locales/fr/index.d.ts +0 -3
- package/locales/fr/index.js +0 -98
- package/locales/he/index.d.ts +0 -3
- package/locales/he/index.js +0 -98
- package/locales/hr/index.d.ts +0 -3
- package/locales/hr/index.js +0 -98
- package/locales/hu/index.d.ts +0 -3
- package/locales/hu/index.js +0 -98
- package/locales/hy/index.d.ts +0 -3
- package/locales/hy/index.js +0 -98
- package/locales/id/index.d.ts +0 -3
- package/locales/id/index.js +0 -98
- package/locales/it/index.d.ts +0 -3
- package/locales/it/index.js +0 -98
- package/locales/ja/index.d.ts +0 -3
- package/locales/ja/index.js +0 -98
- package/locales/ko/index.d.ts +0 -3
- package/locales/ko/index.js +0 -98
- package/locales/nl/index.d.ts +0 -3
- package/locales/nl/index.js +0 -98
- package/locales/no/index.d.ts +0 -3
- package/locales/no/index.js +0 -98
- package/locales/np/index.d.ts +0 -3
- package/locales/np/index.js +0 -98
- package/locales/pl/index.d.ts +0 -3
- package/locales/pl/index.js +0 -98
- package/locales/pt/index.d.ts +0 -3
- package/locales/pt/index.js +0 -98
- package/locales/pt-BR/index.d.ts +0 -3
- package/locales/pt-BR/index.js +0 -98
- package/locales/ro/index.d.ts +0 -3
- package/locales/ro/index.js +0 -98
- package/locales/ru/index.d.ts +0 -3
- package/locales/ru/index.js +0 -98
- package/locales/sk/index.d.ts +0 -3
- package/locales/sk/index.js +0 -98
- package/locales/sr-Cyrl-RS/index.d.ts +0 -3
- package/locales/sr-Cyrl-RS/index.js +0 -98
- package/locales/sr-Latn-RS/index.d.ts +0 -3
- package/locales/sr-Latn-RS/index.js +0 -98
- package/locales/sv/index.d.ts +0 -3
- package/locales/sv/index.js +0 -98
- package/locales/tr/index.d.ts +0 -3
- package/locales/tr/index.js +0 -98
- package/locales/uk/index.d.ts +0 -3
- package/locales/uk/index.js +0 -98
- package/locales/vi/index.d.ts +0 -3
- package/locales/vi/index.js +0 -98
- package/locales/zh-Hans/index.d.ts +0 -3
- package/locales/zh-Hans/index.js +0 -98
- package/locales/zh-Hant/index.d.ts +0 -3
- package/locales/zh-Hant/index.js +0 -98
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { fireEvent, render } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { type MRT_ColumnDef } from '../../types';
|
|
5
|
+
import { MaterialReactTable } from '../MaterialReactTable';
|
|
6
|
+
|
|
7
|
+
interface Person {
|
|
8
|
+
city: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const data: Person[] = [{ city: 'Glasgow', name: 'Alice' }];
|
|
13
|
+
|
|
14
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
15
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
16
|
+
{ accessorKey: 'city', header: 'City' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const headerOrder = (container: HTMLElement) =>
|
|
20
|
+
Array.from(container.querySelectorAll('thead th')).map((th) =>
|
|
21
|
+
th.textContent?.replace(/[^A-Za-z]/g, ''),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const dragColumnOnto = (container: HTMLElement, from: string, to: string) => {
|
|
25
|
+
const handles = Array.from(
|
|
26
|
+
container.querySelectorAll<HTMLElement>('thead [aria-label="Move"]'),
|
|
27
|
+
);
|
|
28
|
+
const headerCells = Array.from(
|
|
29
|
+
container.querySelectorAll<HTMLElement>('thead th'),
|
|
30
|
+
);
|
|
31
|
+
const fromIndex = headerCells.findIndex((th) =>
|
|
32
|
+
th.textContent?.includes(from),
|
|
33
|
+
);
|
|
34
|
+
const toIndex = headerCells.findIndex((th) => th.textContent?.includes(to));
|
|
35
|
+
|
|
36
|
+
fireEvent.dragStart(handles[fromIndex], {
|
|
37
|
+
dataTransfer: { setDragImage: () => {} },
|
|
38
|
+
});
|
|
39
|
+
fireEvent.dragEnter(headerCells[toIndex]);
|
|
40
|
+
fireEvent.dragOver(headerCells[toIndex]);
|
|
41
|
+
fireEvent.drop(headerCells[toIndex]);
|
|
42
|
+
fireEvent.dragEnd(handles[fromIndex]);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe('column dragging', () => {
|
|
46
|
+
test('reorders columns when one is dragged onto another', () => {
|
|
47
|
+
const { container } = render(
|
|
48
|
+
<MaterialReactTable
|
|
49
|
+
columns={columns()}
|
|
50
|
+
data={data}
|
|
51
|
+
enableColumnOrdering
|
|
52
|
+
/>,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(headerOrder(container)).toEqual(['Name', 'City']);
|
|
56
|
+
|
|
57
|
+
dragColumnOnto(container, 'Name', 'City');
|
|
58
|
+
|
|
59
|
+
expect(headerOrder(container)).toEqual(['City', 'Name']);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -24,7 +24,6 @@ export const MRT_TableHeadCellGrabHandle = <TData extends MRT_RowData>({
|
|
|
24
24
|
...rest
|
|
25
25
|
}: MRT_TableHeadCellGrabHandleProps<TData>) => {
|
|
26
26
|
const {
|
|
27
|
-
getState,
|
|
28
27
|
options: { enableColumnOrdering, muiColumnDragHandleProps },
|
|
29
28
|
setColumnOrder,
|
|
30
29
|
setColumnPinning,
|
|
@@ -32,7 +31,7 @@ export const MRT_TableHeadCellGrabHandle = <TData extends MRT_RowData>({
|
|
|
32
31
|
setHoveredColumn,
|
|
33
32
|
} = table;
|
|
34
33
|
const { columnDef } = column;
|
|
35
|
-
const { columnOrder, draggingColumn, hoveredColumn } =
|
|
34
|
+
const { columnOrder, draggingColumn, hoveredColumn } = table.state;
|
|
36
35
|
|
|
37
36
|
const iconButtonProps = {
|
|
38
37
|
...parseFromValuesOrFunc(muiColumnDragHandleProps, { column, table }),
|
|
@@ -72,9 +71,9 @@ export const MRT_TableHeadCellGrabHandle = <TData extends MRT_RowData>({
|
|
|
72
71
|
columnOrder,
|
|
73
72
|
);
|
|
74
73
|
setColumnOrder(reorderedColumns);
|
|
75
|
-
setColumnPinning(({
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
setColumnPinning(({ end = [], start = [] }) => ({
|
|
75
|
+
end: reorderedColumns.filter((header) => end.includes(header)),
|
|
76
|
+
start: reorderedColumns.filter((header) => start.includes(header)),
|
|
78
77
|
}));
|
|
79
78
|
}
|
|
80
79
|
setDraggingColumn(null);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { fireEvent, render } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { type MRT_ColumnDef } from '../../types';
|
|
5
|
+
import { MaterialReactTable } from '../MaterialReactTable';
|
|
6
|
+
|
|
7
|
+
interface Person {
|
|
8
|
+
city: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const data: Person[] = [{ city: 'Glasgow', name: 'Alice' }];
|
|
13
|
+
|
|
14
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
15
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
16
|
+
{ accessorKey: 'city', header: 'City' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const nameColumnSize = (container: HTMLElement) =>
|
|
20
|
+
(container.querySelector('table') as HTMLElement).style.getPropertyValue(
|
|
21
|
+
'--header-name-size',
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
describe('column resizing', () => {
|
|
25
|
+
test('dragging the resize handle widens the column', () => {
|
|
26
|
+
const { container } = render(
|
|
27
|
+
<MaterialReactTable
|
|
28
|
+
columns={columns()}
|
|
29
|
+
data={data}
|
|
30
|
+
enableColumnResizing
|
|
31
|
+
/>,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const before = nameColumnSize(container);
|
|
35
|
+
const handle = container.querySelector(
|
|
36
|
+
'thead .Mui-TableHeadCell-ResizeHandle-Wrapper',
|
|
37
|
+
) as HTMLElement;
|
|
38
|
+
|
|
39
|
+
fireEvent.mouseDown(handle, { clientX: 0 });
|
|
40
|
+
fireEvent.mouseMove(document, { clientX: 120 });
|
|
41
|
+
fireEvent.mouseUp(document, { clientX: 120 });
|
|
42
|
+
|
|
43
|
+
expect(nameColumnSize(container)).not.toBe(before);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -20,11 +20,10 @@ export const MRT_TableHeadCellResizeHandle = <TData extends MRT_RowData>({
|
|
|
20
20
|
...rest
|
|
21
21
|
}: MRT_TableHeadCellResizeHandleProps<TData>) => {
|
|
22
22
|
const {
|
|
23
|
-
getState,
|
|
24
23
|
options: { columnResizeDirection, columnResizeMode },
|
|
25
|
-
|
|
24
|
+
setColumnResizing,
|
|
26
25
|
} = table;
|
|
27
|
-
const { density } =
|
|
26
|
+
const { density } = table.state;
|
|
28
27
|
const { column } = header;
|
|
29
28
|
|
|
30
29
|
const handler = header.getResizeHandler();
|
|
@@ -42,7 +41,7 @@ export const MRT_TableHeadCellResizeHandle = <TData extends MRT_RowData>({
|
|
|
42
41
|
<Box
|
|
43
42
|
className="Mui-TableHeadCell-ResizeHandle-Wrapper"
|
|
44
43
|
onDoubleClick={() => {
|
|
45
|
-
|
|
44
|
+
setColumnResizing((old) => ({
|
|
46
45
|
...old,
|
|
47
46
|
isResizingColumn: false,
|
|
48
47
|
}));
|
|
@@ -55,7 +54,7 @@ export const MRT_TableHeadCellResizeHandle = <TData extends MRT_RowData>({
|
|
|
55
54
|
column.getIsResizing() && columnResizeMode === 'onEnd'
|
|
56
55
|
? `translateX(${
|
|
57
56
|
(columnResizeDirection === 'rtl' ? -1 : 1) *
|
|
58
|
-
(
|
|
57
|
+
(table.state.columnResizing.deltaOffset ?? 0)
|
|
59
58
|
}px)`
|
|
60
59
|
: undefined,
|
|
61
60
|
}}
|
|
@@ -21,7 +21,6 @@ export const MRT_TableHeadCellSortLabel = <TData extends MRT_RowData>({
|
|
|
21
21
|
...rest
|
|
22
22
|
}: MRT_TableHeadCellSortLabelProps<TData>) => {
|
|
23
23
|
const {
|
|
24
|
-
getState,
|
|
25
24
|
options: {
|
|
26
25
|
icons: { ArrowDownwardIcon, SyncAltIcon },
|
|
27
26
|
localization,
|
|
@@ -29,7 +28,7 @@ export const MRT_TableHeadCellSortLabel = <TData extends MRT_RowData>({
|
|
|
29
28
|
} = table;
|
|
30
29
|
const { column } = header;
|
|
31
30
|
const { columnDef } = column;
|
|
32
|
-
const { isLoading, showSkeletons, sorting } =
|
|
31
|
+
const { isLoading, showSkeletons, sorting } = table.state;
|
|
33
32
|
|
|
34
33
|
const isSorted = !!column.getIsSorted();
|
|
35
34
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { type MRT_ColumnDef } from '../../types';
|
|
6
|
+
import { MaterialReactTable } from '../MaterialReactTable';
|
|
7
|
+
|
|
8
|
+
interface Person {
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const data: Person[] = [{ name: 'Alice' }];
|
|
13
|
+
|
|
14
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
15
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
describe('cell editing', () => {
|
|
19
|
+
test('opens a text field in the cell that was clicked', async () => {
|
|
20
|
+
const user = userEvent.setup();
|
|
21
|
+
const { container } = render(
|
|
22
|
+
<MaterialReactTable
|
|
23
|
+
columns={columns()}
|
|
24
|
+
data={data}
|
|
25
|
+
editDisplayMode="cell"
|
|
26
|
+
enableEditing
|
|
27
|
+
/>,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
expect(container.querySelectorAll('tbody input')).toHaveLength(0);
|
|
31
|
+
|
|
32
|
+
await user.dblClick(container.querySelector('tbody td') as HTMLElement);
|
|
33
|
+
|
|
34
|
+
expect(container.querySelectorAll('tbody input')).toHaveLength(1);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -28,7 +28,6 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
|
|
|
28
28
|
...rest
|
|
29
29
|
}: MRT_EditCellTextFieldProps<TData>) => {
|
|
30
30
|
const {
|
|
31
|
-
getState,
|
|
32
31
|
options: { createDisplayMode, editDisplayMode, muiEditTextFieldProps },
|
|
33
32
|
refs: { editInputRefs },
|
|
34
33
|
setCreatingRow,
|
|
@@ -37,7 +36,7 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
|
|
|
37
36
|
} = table;
|
|
38
37
|
const { column, row } = cell;
|
|
39
38
|
const { columnDef } = column;
|
|
40
|
-
const { creatingRow, editingRow } =
|
|
39
|
+
const { creatingRow, editingRow } = table.state;
|
|
41
40
|
const { editSelectOptions, editVariant } = columnDef;
|
|
42
41
|
|
|
43
42
|
const isCreating = creatingRow?.id === row.id;
|
|
@@ -72,7 +71,6 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
|
|
|
72
71
|
const isSelectEdit = editVariant === 'select' || textFieldProps?.select;
|
|
73
72
|
|
|
74
73
|
const saveInputValueToRowCache = (newValue: string) => {
|
|
75
|
-
//@ts-expect-error
|
|
76
74
|
row._valuesCache[column.id] = newValue;
|
|
77
75
|
if (isCreating) {
|
|
78
76
|
setCreatingRow(row);
|
|
@@ -22,10 +22,9 @@ export const MRT_FilterCheckbox = <TData extends MRT_RowData>({
|
|
|
22
22
|
...rest
|
|
23
23
|
}: MRT_FilterCheckboxProps<TData>) => {
|
|
24
24
|
const {
|
|
25
|
-
getState,
|
|
26
25
|
options: { localization, muiFilterCheckboxProps },
|
|
27
26
|
} = table;
|
|
28
|
-
const { density } =
|
|
27
|
+
const { density } = table.state;
|
|
29
28
|
const { columnDef } = column;
|
|
30
29
|
|
|
31
30
|
const checkboxProps = {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type MRT_RowData,
|
|
9
9
|
type MRT_TableInstance,
|
|
10
10
|
} from '../../types';
|
|
11
|
+
import { getColumnFilterInfo } from '../../utils/column.utils';
|
|
11
12
|
import { parseFromValuesOrFunc } from '../../utils/utils';
|
|
12
13
|
|
|
13
14
|
export interface MRT_FilterRangeSliderProps<TData extends MRT_RowData>
|
|
@@ -28,7 +29,7 @@ export const MRT_FilterRangeSlider = <TData extends MRT_RowData>({
|
|
|
28
29
|
const { column } = header;
|
|
29
30
|
const { columnDef } = column;
|
|
30
31
|
|
|
31
|
-
const currentFilterOption =
|
|
32
|
+
const { currentFilterOption } = getColumnFilterInfo({ header, table });
|
|
32
33
|
|
|
33
34
|
const showChangeModeButton =
|
|
34
35
|
enableColumnFilterModes && columnDef.enableColumnFilterModes !== false;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { render, waitFor } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { type MRT_ColumnDef } from '../../types';
|
|
6
|
+
import { MaterialReactTable } from '../MaterialReactTable';
|
|
7
|
+
|
|
8
|
+
interface Person {
|
|
9
|
+
city: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const data: Person[] = [
|
|
14
|
+
{ city: 'Glasgow', name: 'Alice' },
|
|
15
|
+
{ city: 'Dundee', name: 'Bob' },
|
|
16
|
+
{ city: 'Glasgow', name: 'Cara' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
20
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
21
|
+
{ accessorKey: 'city', filterVariant: 'select', header: 'City' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
describe('faceted select filter', () => {
|
|
25
|
+
test('offers the distinct values present in the data', async () => {
|
|
26
|
+
const user = userEvent.setup();
|
|
27
|
+
const { baseElement, container } = render(
|
|
28
|
+
<MaterialReactTable
|
|
29
|
+
columns={columns()}
|
|
30
|
+
data={data}
|
|
31
|
+
enableFacetedValues
|
|
32
|
+
initialState={{ showColumnFilters: true }}
|
|
33
|
+
/>,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const selects = container.querySelectorAll<HTMLElement>(
|
|
37
|
+
'thead [role="combobox"]',
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
await user.click(selects[selects.length - 1]);
|
|
41
|
+
|
|
42
|
+
const options = Array.from(
|
|
43
|
+
baseElement.querySelectorAll<HTMLElement>('li[role="option"]'),
|
|
44
|
+
).map((li) => li.textContent);
|
|
45
|
+
|
|
46
|
+
expect(options).toContain('Glasgow (2)');
|
|
47
|
+
expect(options).toContain('Dundee (1)');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('picking an option filters the rows', async () => {
|
|
51
|
+
const user = userEvent.setup();
|
|
52
|
+
const { container } = render(
|
|
53
|
+
<MaterialReactTable
|
|
54
|
+
columns={columns()}
|
|
55
|
+
data={data}
|
|
56
|
+
enableFacetedValues
|
|
57
|
+
initialState={{ showColumnFilters: true }}
|
|
58
|
+
/>,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const selects = container.querySelectorAll<HTMLElement>(
|
|
62
|
+
'thead [role="combobox"]',
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
await user.click(selects[selects.length - 1]);
|
|
66
|
+
await user.keyboard('{ArrowDown}{Enter}');
|
|
67
|
+
|
|
68
|
+
await waitFor(() => {
|
|
69
|
+
const names = Array.from(container.querySelectorAll('tbody tr')).map(
|
|
70
|
+
(tr) => tr.querySelector('td')?.textContent,
|
|
71
|
+
);
|
|
72
|
+
expect(names).toEqual(['Alice', 'Cara']);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -28,7 +28,6 @@ export const MRT_GlobalFilterTextField = <TData extends MRT_RowData>({
|
|
|
28
28
|
...rest
|
|
29
29
|
}: MRT_GlobalFilterTextFieldProps<TData>) => {
|
|
30
30
|
const {
|
|
31
|
-
getState,
|
|
32
31
|
options: {
|
|
33
32
|
enableGlobalFilterModes,
|
|
34
33
|
icons: { CloseIcon, SearchIcon },
|
|
@@ -39,7 +38,7 @@ export const MRT_GlobalFilterTextField = <TData extends MRT_RowData>({
|
|
|
39
38
|
refs: { searchInputRef },
|
|
40
39
|
setGlobalFilter,
|
|
41
40
|
} = table;
|
|
42
|
-
const { globalFilter, showGlobalFilter } =
|
|
41
|
+
const { globalFilter, showGlobalFilter } = table.state;
|
|
43
42
|
|
|
44
43
|
const textFieldProps = {
|
|
45
44
|
...parseFromValuesOrFunc(muiSearchTextFieldProps, {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { type MRT_ColumnDef } from '../../types';
|
|
6
|
+
import { MaterialReactTable } from '../MaterialReactTable';
|
|
7
|
+
|
|
8
|
+
interface Person {
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const data: Person[] = [{ name: 'Alice' }, { name: 'Bob' }];
|
|
13
|
+
|
|
14
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
15
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const selectAll = (container: HTMLElement) =>
|
|
19
|
+
container.querySelector('thead input[type="checkbox"]') as HTMLInputElement;
|
|
20
|
+
|
|
21
|
+
const rowBoxes = (container: HTMLElement) =>
|
|
22
|
+
Array.from(
|
|
23
|
+
container.querySelectorAll<HTMLInputElement>(
|
|
24
|
+
'tbody input[type="checkbox"]',
|
|
25
|
+
),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const renderTable = () =>
|
|
29
|
+
render(<MaterialReactTable columns={columns()} data={data} enableRowSelection />);
|
|
30
|
+
|
|
31
|
+
describe('row selection checkboxes', () => {
|
|
32
|
+
test('select all checks every row', async () => {
|
|
33
|
+
const user = userEvent.setup();
|
|
34
|
+
const { container } = renderTable();
|
|
35
|
+
|
|
36
|
+
await user.click(selectAll(container));
|
|
37
|
+
|
|
38
|
+
expect(rowBoxes(container).map((box) => box.checked)).toEqual([true, true]);
|
|
39
|
+
expect(selectAll(container).checked).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('select all is indeterminate when only some rows are selected', async () => {
|
|
43
|
+
const user = userEvent.setup();
|
|
44
|
+
const { container } = renderTable();
|
|
45
|
+
|
|
46
|
+
await user.click(rowBoxes(container)[0]);
|
|
47
|
+
|
|
48
|
+
expect(selectAll(container).checked).toBe(false);
|
|
49
|
+
expect(selectAll(container).dataset.indeterminate).toBe('true');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('select all is not indeterminate when every row is selected', async () => {
|
|
53
|
+
const user = userEvent.setup();
|
|
54
|
+
const { container } = renderTable();
|
|
55
|
+
|
|
56
|
+
await user.click(selectAll(container));
|
|
57
|
+
|
|
58
|
+
expect(selectAll(container).dataset.indeterminate).toBe('false');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('clicking a row checkbox toggles only that row', async () => {
|
|
62
|
+
const user = userEvent.setup();
|
|
63
|
+
const { container } = renderTable();
|
|
64
|
+
|
|
65
|
+
await user.click(rowBoxes(container)[0]);
|
|
66
|
+
|
|
67
|
+
expect(rowBoxes(container).map((box) => box.checked)).toEqual([true, false]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -31,7 +31,6 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
|
|
|
31
31
|
...rest
|
|
32
32
|
}: MRT_SelectCheckboxProps<TData>) => {
|
|
33
33
|
const {
|
|
34
|
-
getState,
|
|
35
34
|
options: {
|
|
36
35
|
enableMultiRowSelection,
|
|
37
36
|
localization,
|
|
@@ -40,7 +39,7 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
|
|
|
40
39
|
selectAllMode,
|
|
41
40
|
},
|
|
42
41
|
} = table;
|
|
43
|
-
const { density, isLoading } =
|
|
42
|
+
const { density, isLoading } = table.state;
|
|
44
43
|
|
|
45
44
|
const selectAll = !row;
|
|
46
45
|
|
|
@@ -15,7 +15,6 @@ export const MRT_CellActionMenu = <TData extends MRT_RowData>({
|
|
|
15
15
|
...rest
|
|
16
16
|
}: MRT_CellActionMenuProps<TData>) => {
|
|
17
17
|
const {
|
|
18
|
-
getState,
|
|
19
18
|
options: {
|
|
20
19
|
editDisplayMode,
|
|
21
20
|
enableClickToCopy,
|
|
@@ -27,7 +26,7 @@ export const MRT_CellActionMenu = <TData extends MRT_RowData>({
|
|
|
27
26
|
},
|
|
28
27
|
refs: { actionCellRef },
|
|
29
28
|
} = table;
|
|
30
|
-
const { actionCell, density } =
|
|
29
|
+
const { actionCell, density } = table.state;
|
|
31
30
|
const cell = actionCell!;
|
|
32
31
|
const { row } = cell;
|
|
33
32
|
const { column } = cell;
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type MRT_RowData,
|
|
7
7
|
type MRT_TableInstance,
|
|
8
8
|
} from '../../types';
|
|
9
|
+
import { getColumnFilterInfo } from '../../utils/column.utils';
|
|
9
10
|
import { MRT_ActionMenuItem } from './MRT_ActionMenuItem';
|
|
10
11
|
import { MRT_FilterOptionMenu } from './MRT_FilterOptionMenu';
|
|
11
12
|
|
|
@@ -26,10 +27,8 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
26
27
|
}: MRT_ColumnActionMenuProps<TData>) => {
|
|
27
28
|
const {
|
|
28
29
|
getAllLeafColumns,
|
|
29
|
-
getState,
|
|
30
30
|
options: {
|
|
31
31
|
columnFilterDisplayMode,
|
|
32
|
-
columnFilterModeOptions,
|
|
33
32
|
enableColumnFilterModes,
|
|
34
33
|
enableColumnFilters,
|
|
35
34
|
enableColumnPinning,
|
|
@@ -56,13 +55,13 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
56
55
|
refs: { filterInputRefs },
|
|
57
56
|
setColumnFilterFns,
|
|
58
57
|
setColumnOrder,
|
|
59
|
-
|
|
58
|
+
setColumnResizing,
|
|
60
59
|
setShowColumnFilters,
|
|
61
60
|
} = table;
|
|
62
61
|
const { column } = header;
|
|
63
62
|
const { columnDef } = column;
|
|
64
63
|
const { columnSizing, columnVisibility, density, showColumnFilters } =
|
|
65
|
-
|
|
64
|
+
table.state;
|
|
66
65
|
const columnFilterValue = column.getFilterValue();
|
|
67
66
|
|
|
68
67
|
const [filterMenuAnchorEl, setFilterMenuAnchorEl] =
|
|
@@ -84,7 +83,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
84
83
|
};
|
|
85
84
|
|
|
86
85
|
const handleResetColumnSize = () => {
|
|
87
|
-
|
|
86
|
+
setColumnResizing((old) => ({ ...old, isResizingColumn: false }));
|
|
88
87
|
column.resetSize();
|
|
89
88
|
setAnchorEl(null);
|
|
90
89
|
};
|
|
@@ -94,7 +93,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
94
93
|
setAnchorEl(null);
|
|
95
94
|
};
|
|
96
95
|
|
|
97
|
-
const handlePinColumn = (pinDirection: '
|
|
96
|
+
const handlePinColumn = (pinDirection: 'end' | 'start' | false) => {
|
|
98
97
|
column.pin(pinDirection);
|
|
99
98
|
setAnchorEl(null);
|
|
100
99
|
};
|
|
@@ -108,7 +107,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
108
107
|
const handleClearFilter = () => {
|
|
109
108
|
column.setFilterValue(undefined);
|
|
110
109
|
setAnchorEl(null);
|
|
111
|
-
if (['empty', 'notEmpty'].includes(
|
|
110
|
+
if (['empty', 'notEmpty'].includes(currentFilterOption)) {
|
|
112
111
|
setColumnFilterFns((prev) => ({
|
|
113
112
|
...prev,
|
|
114
113
|
[header.id]: allowedColumnFilterOptions?.[0] ?? 'fuzzy',
|
|
@@ -136,8 +135,8 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
136
135
|
|
|
137
136
|
const isSelectFilter = !!columnDef.filterSelectOptions;
|
|
138
137
|
|
|
139
|
-
const allowedColumnFilterOptions =
|
|
140
|
-
|
|
138
|
+
const { allowedColumnFilterOptions, currentFilterOption } =
|
|
139
|
+
getColumnFilterInfo({ header, table });
|
|
141
140
|
|
|
142
141
|
const showFilterModeSubMenu =
|
|
143
142
|
enableColumnFilterModes &&
|
|
@@ -250,19 +249,19 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
|
|
|
250
249
|
...(enableColumnPinning && column.getCanPin()
|
|
251
250
|
? [
|
|
252
251
|
<MRT_ActionMenuItem
|
|
253
|
-
disabled={column.getIsPinned() === '
|
|
252
|
+
disabled={column.getIsPinned() === 'start' || !column.getCanPin()}
|
|
254
253
|
icon={<PushPinIcon style={{ transform: 'rotate(90deg)' }} />}
|
|
255
254
|
key={7}
|
|
256
255
|
label={localization.pinToLeft}
|
|
257
|
-
onClick={() => handlePinColumn('
|
|
256
|
+
onClick={() => handlePinColumn('start')}
|
|
258
257
|
table={table}
|
|
259
258
|
/>,
|
|
260
259
|
<MRT_ActionMenuItem
|
|
261
|
-
disabled={column.getIsPinned() === '
|
|
260
|
+
disabled={column.getIsPinned() === 'end' || !column.getCanPin()}
|
|
262
261
|
icon={<PushPinIcon style={{ transform: 'rotate(-90deg)' }} />}
|
|
263
262
|
key={8}
|
|
264
263
|
label={localization.pinToRight}
|
|
265
|
-
onClick={() => handlePinColumn('
|
|
264
|
+
onClick={() => handlePinColumn('end')}
|
|
266
265
|
table={table}
|
|
267
266
|
/>,
|
|
268
267
|
<MRT_ActionMenuItem
|
|
@@ -125,7 +125,6 @@ export const MRT_FilterOptionMenu = <TData extends MRT_RowData>({
|
|
|
125
125
|
...rest
|
|
126
126
|
}: MRT_FilterOptionMenuProps<TData>) => {
|
|
127
127
|
const {
|
|
128
|
-
getState,
|
|
129
128
|
options: {
|
|
130
129
|
columnFilterModeOptions,
|
|
131
130
|
globalFilterModeOptions,
|
|
@@ -137,7 +136,7 @@ export const MRT_FilterOptionMenu = <TData extends MRT_RowData>({
|
|
|
137
136
|
setColumnFilterFns,
|
|
138
137
|
setGlobalFilterFn,
|
|
139
138
|
} = table;
|
|
140
|
-
const { density, globalFilterFn } =
|
|
139
|
+
const { density, globalFilterFn } = table.state;
|
|
141
140
|
const { column } = header ?? {};
|
|
142
141
|
const { columnDef } = column ?? {};
|
|
143
142
|
const currentFilterValue = column?.getFilterValue();
|
|
@@ -29,7 +29,6 @@ export const MRT_RowActionMenu = <TData extends MRT_RowData>({
|
|
|
29
29
|
...rest
|
|
30
30
|
}: MRT_RowActionMenuProps<TData>) => {
|
|
31
31
|
const {
|
|
32
|
-
getState,
|
|
33
32
|
options: {
|
|
34
33
|
editDisplayMode,
|
|
35
34
|
enableEditing,
|
|
@@ -39,7 +38,7 @@ export const MRT_RowActionMenu = <TData extends MRT_RowData>({
|
|
|
39
38
|
renderRowActionMenuItems,
|
|
40
39
|
},
|
|
41
40
|
} = table;
|
|
42
|
-
const { density } =
|
|
41
|
+
const { density } = table.state;
|
|
43
42
|
|
|
44
43
|
const menuItems = useMemo(() => {
|
|
45
44
|
const items: ReactNode[] = [];
|
|
@@ -36,7 +36,6 @@ export const MRT_ShowHideColumnsMenu = <TData extends MRT_RowData>({
|
|
|
36
36
|
getIsSomeColumnsVisible,
|
|
37
37
|
getLeftLeafColumns,
|
|
38
38
|
getRightLeafColumns,
|
|
39
|
-
getState,
|
|
40
39
|
initialState,
|
|
41
40
|
options: {
|
|
42
41
|
enableColumnOrdering,
|
|
@@ -46,7 +45,7 @@ export const MRT_ShowHideColumnsMenu = <TData extends MRT_RowData>({
|
|
|
46
45
|
mrtTheme: { menuBackgroundColor },
|
|
47
46
|
},
|
|
48
47
|
} = table;
|
|
49
|
-
const { columnOrder, columnPinning, density } =
|
|
48
|
+
const { columnOrder, columnPinning, density } = table.state;
|
|
50
49
|
|
|
51
50
|
const handleToggleAllColumns = (value?: boolean) => {
|
|
52
51
|
const updates =
|
|
@@ -43,7 +43,6 @@ export const MRT_ShowHideColumnsMenuItems = <TData extends MRT_RowData>({
|
|
|
43
43
|
...rest
|
|
44
44
|
}: MRT_ShowHideColumnsMenuItemsProps<TData>) => {
|
|
45
45
|
const {
|
|
46
|
-
getState,
|
|
47
46
|
options: {
|
|
48
47
|
enableColumnOrdering,
|
|
49
48
|
enableColumnPinning,
|
|
@@ -54,7 +53,7 @@ export const MRT_ShowHideColumnsMenuItems = <TData extends MRT_RowData>({
|
|
|
54
53
|
setColumnOrder,
|
|
55
54
|
setColumnPinning,
|
|
56
55
|
} = table;
|
|
57
|
-
const { columnOrder } =
|
|
56
|
+
const { columnOrder } = table.state;
|
|
58
57
|
const { columnDef } = column;
|
|
59
58
|
const { columnDefType } = columnDef;
|
|
60
59
|
|
|
@@ -93,9 +92,9 @@ export const MRT_ShowHideColumnsMenuItems = <TData extends MRT_RowData>({
|
|
|
93
92
|
columnOrder,
|
|
94
93
|
);
|
|
95
94
|
setColumnOrder(reorderedColumns);
|
|
96
|
-
setColumnPinning(({
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
setColumnPinning(({ end = [], start = [] }) => ({
|
|
96
|
+
end: reorderedColumns.filter((header) => end.includes(header)),
|
|
97
|
+
start: reorderedColumns.filter((header) => start.includes(header)),
|
|
99
98
|
}));
|
|
100
99
|
}
|
|
101
100
|
};
|