@cutting/material-react-table 4.1.0 → 5.0.0-beta.2
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,54 @@
|
|
|
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('row editing', () => {
|
|
19
|
+
test('opens the edit modal when the edit button is clicked', async () => {
|
|
20
|
+
const user = userEvent.setup();
|
|
21
|
+
const { baseElement, container } = render(
|
|
22
|
+
<MaterialReactTable
|
|
23
|
+
columns={columns()}
|
|
24
|
+
data={data}
|
|
25
|
+
editDisplayMode="modal"
|
|
26
|
+
enableEditing
|
|
27
|
+
/>,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
await user.click(
|
|
31
|
+
container.querySelector('[aria-label="Edit"]') as HTMLElement,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(baseElement.querySelectorAll('input').length).toBeGreaterThan(0);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('opens inline inputs when editDisplayMode is row', async () => {
|
|
38
|
+
const user = userEvent.setup();
|
|
39
|
+
const { container } = render(
|
|
40
|
+
<MaterialReactTable
|
|
41
|
+
columns={columns()}
|
|
42
|
+
data={data}
|
|
43
|
+
editDisplayMode="row"
|
|
44
|
+
enableEditing
|
|
45
|
+
/>,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
await user.click(
|
|
49
|
+
container.querySelector('[aria-label="Edit"]') as HTMLElement,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(container.querySelectorAll('tbody input').length).toBeGreaterThan(0);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -25,7 +25,6 @@ export const MRT_EditRowModal = <TData extends MRT_RowData>({
|
|
|
25
25
|
...rest
|
|
26
26
|
}: MRT_EditRowModalProps<TData>) => {
|
|
27
27
|
const {
|
|
28
|
-
getState,
|
|
29
28
|
options: {
|
|
30
29
|
localization,
|
|
31
30
|
muiCreateRowModalProps,
|
|
@@ -38,7 +37,7 @@ export const MRT_EditRowModal = <TData extends MRT_RowData>({
|
|
|
38
37
|
setCreatingRow,
|
|
39
38
|
setEditingRow,
|
|
40
39
|
} = table;
|
|
41
|
-
const { creatingRow, editingRow } =
|
|
40
|
+
const { creatingRow, editingRow } = table.state;
|
|
42
41
|
const row = (creatingRow ?? editingRow) as MRT_Row<TData>;
|
|
43
42
|
|
|
44
43
|
const dialogProps = {
|
|
@@ -19,7 +19,6 @@ export const MRT_Table = <TData extends MRT_RowData>({
|
|
|
19
19
|
}: MRT_TableProps<TData>) => {
|
|
20
20
|
const {
|
|
21
21
|
getFlatHeaders,
|
|
22
|
-
getState,
|
|
23
22
|
options: {
|
|
24
23
|
columns,
|
|
25
24
|
enableStickyHeader,
|
|
@@ -31,8 +30,8 @@ export const MRT_Table = <TData extends MRT_RowData>({
|
|
|
31
30
|
renderCaption,
|
|
32
31
|
},
|
|
33
32
|
} = table;
|
|
34
|
-
const {
|
|
35
|
-
|
|
33
|
+
const { columnResizing, columnSizing, columnVisibility, isFullScreen } =
|
|
34
|
+
table.state;
|
|
36
35
|
|
|
37
36
|
const tableProps = {
|
|
38
37
|
...parseFromValuesOrFunc(muiTableProps, { table }),
|
|
@@ -51,7 +50,7 @@ export const MRT_Table = <TData extends MRT_RowData>({
|
|
|
51
50
|
colSizes[`--col-${parseCSSVarId(header.column.id)}-size`] = colSize;
|
|
52
51
|
}
|
|
53
52
|
return colSizes;
|
|
54
|
-
}, [columns, columnSizing,
|
|
53
|
+
}, [columns, columnSizing, columnResizing, columnVisibility]);
|
|
55
54
|
|
|
56
55
|
const columnVirtualizer = useMRT_ColumnVirtualizer(table);
|
|
57
56
|
|
|
@@ -74,7 +73,7 @@ export const MRT_Table = <TData extends MRT_RowData>({
|
|
|
74
73
|
>
|
|
75
74
|
{!!Caption && <caption>{Caption}</caption>}
|
|
76
75
|
{enableTableHead && <MRT_TableHead {...commonTableGroupProps} />}
|
|
77
|
-
{memoMode === 'table-body' ||
|
|
76
|
+
{memoMode === 'table-body' || columnResizing.isResizingColumn ? (
|
|
78
77
|
<Memo_MRT_TableBody {...commonTableGroupProps} />
|
|
79
78
|
) : (
|
|
80
79
|
<MRT_TableBody {...commonTableGroupProps} />
|
|
@@ -21,7 +21,6 @@ export const MRT_TableContainer = <TData extends MRT_RowData>({
|
|
|
21
21
|
...rest
|
|
22
22
|
}: MRT_TableContainerProps<TData>) => {
|
|
23
23
|
const {
|
|
24
|
-
getState,
|
|
25
24
|
options: {
|
|
26
25
|
createDisplayMode,
|
|
27
26
|
editDisplayMode,
|
|
@@ -38,7 +37,7 @@ export const MRT_TableContainer = <TData extends MRT_RowData>({
|
|
|
38
37
|
isFullScreen,
|
|
39
38
|
isLoading,
|
|
40
39
|
showLoadingOverlay,
|
|
41
|
-
} =
|
|
40
|
+
} = table.state;
|
|
42
41
|
|
|
43
42
|
const loading =
|
|
44
43
|
showLoadingOverlay !== false && (isLoading || showLoadingOverlay);
|
|
@@ -17,7 +17,6 @@ export const MRT_TablePaper = <TData extends MRT_RowData>({
|
|
|
17
17
|
...rest
|
|
18
18
|
}: MRT_TablePaperProps<TData>) => {
|
|
19
19
|
const {
|
|
20
|
-
getState,
|
|
21
20
|
options: {
|
|
22
21
|
enableBottomToolbar,
|
|
23
22
|
enableTopToolbar,
|
|
@@ -28,7 +27,7 @@ export const MRT_TablePaper = <TData extends MRT_RowData>({
|
|
|
28
27
|
},
|
|
29
28
|
refs: { tablePaperRef },
|
|
30
29
|
} = table;
|
|
31
|
-
const { isFullScreen } =
|
|
30
|
+
const { isFullScreen } = table.state;
|
|
32
31
|
|
|
33
32
|
const paperProps = {
|
|
34
33
|
...parseFromValuesOrFunc(muiTablePaperProps, { table }),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box,
|
|
1
|
+
import { Box, type BoxProps, useMediaQuery } from '@mui/material';
|
|
2
2
|
import { alpha } from '@mui/material/styles';
|
|
3
3
|
|
|
4
4
|
import { type MRT_RowData, type MRT_TableInstance } from '../../types';
|
|
@@ -19,7 +19,6 @@ export const MRT_BottomToolbar = <TData extends MRT_RowData>({
|
|
|
19
19
|
...rest
|
|
20
20
|
}: MRT_BottomToolbarProps<TData>) => {
|
|
21
21
|
const {
|
|
22
|
-
getState,
|
|
23
22
|
options: {
|
|
24
23
|
enablePagination,
|
|
25
24
|
muiBottomToolbarProps,
|
|
@@ -30,7 +29,7 @@ export const MRT_BottomToolbar = <TData extends MRT_RowData>({
|
|
|
30
29
|
},
|
|
31
30
|
refs: { bottomToolbarRef },
|
|
32
31
|
} = table;
|
|
33
|
-
const { isFullScreen } =
|
|
32
|
+
const { isFullScreen } = table.state;
|
|
34
33
|
|
|
35
34
|
const isMobile = useMediaQuery('(max-width:720px)');
|
|
36
35
|
|
|
@@ -16,10 +16,9 @@ export const MRT_LinearProgressBar = <TData extends MRT_RowData>({
|
|
|
16
16
|
...rest
|
|
17
17
|
}: MRT_LinearProgressBarProps<TData>) => {
|
|
18
18
|
const {
|
|
19
|
-
getState,
|
|
20
19
|
options: { muiLinearProgressProps },
|
|
21
20
|
} = table;
|
|
22
|
-
const { isSaving, showProgressBars } =
|
|
21
|
+
const { isSaving, showProgressBars } = table.state;
|
|
23
22
|
|
|
24
23
|
const linearProgressProps = {
|
|
25
24
|
...parseFromValuesOrFunc(muiLinearProgressProps, {
|
|
@@ -37,7 +37,6 @@ export const MRT_TablePagination = <TData extends MRT_RowData>({
|
|
|
37
37
|
const isMobile = useMediaQuery('(max-width: 720px)');
|
|
38
38
|
|
|
39
39
|
const {
|
|
40
|
-
getState,
|
|
41
40
|
options: {
|
|
42
41
|
enableToolbarInternalActions,
|
|
43
42
|
icons: { ChevronLeftIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon },
|
|
@@ -49,7 +48,7 @@ export const MRT_TablePagination = <TData extends MRT_RowData>({
|
|
|
49
48
|
} = table;
|
|
50
49
|
const {
|
|
51
50
|
pagination: { pageIndex = 0, pageSize = 10 },
|
|
52
|
-
} =
|
|
51
|
+
} = table.state;
|
|
53
52
|
|
|
54
53
|
const paginationProps = {
|
|
55
54
|
...parseFromValuesOrFunc(muiPaginationProps, {
|
|
@@ -26,7 +26,6 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
|
|
|
26
26
|
const {
|
|
27
27
|
getCoreRowModel,
|
|
28
28
|
getFilteredSelectedRowModel,
|
|
29
|
-
getState,
|
|
30
29
|
options: {
|
|
31
30
|
enableRowSelection,
|
|
32
31
|
enableSelectAll,
|
|
@@ -40,7 +39,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
|
|
|
40
39
|
},
|
|
41
40
|
refs: { tablePaperRef },
|
|
42
41
|
} = table;
|
|
43
|
-
const { density, grouping, rowSelection, showAlertBanner } =
|
|
42
|
+
const { density, grouping, rowSelection, showAlertBanner } = table.state;
|
|
44
43
|
|
|
45
44
|
const alertProps = {
|
|
46
45
|
...parseFromValuesOrFunc(muiToolbarAlertBannerProps, {
|
|
@@ -100,8 +99,8 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
|
|
|
100
99
|
<Fragment key={`${index}-${columnId}`}>
|
|
101
100
|
{index > 0 ? localization.thenBy : ''}
|
|
102
101
|
<Chip
|
|
103
|
-
label={table.getColumn(columnId)
|
|
104
|
-
onDelete={() => table.getColumn(columnId)
|
|
102
|
+
label={table.getColumn(columnId)?.columnDef.header}
|
|
103
|
+
onDelete={() => table.getColumn(columnId)?.toggleGrouping()}
|
|
105
104
|
{...chipProps}
|
|
106
105
|
/>
|
|
107
106
|
</Fragment>
|
|
@@ -0,0 +1,42 @@
|
|
|
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[] = [
|
|
13
|
+
{ city: 'Glasgow', name: 'Alice' },
|
|
14
|
+
{ city: 'Glasgow', name: 'Bob' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const columns = (): MRT_ColumnDef<Person>[] => [
|
|
18
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
19
|
+
{ accessorKey: 'city', header: 'City' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
describe('grouping drop zone', () => {
|
|
23
|
+
test('dropping a column on it groups by that column', () => {
|
|
24
|
+
const { container } = render(
|
|
25
|
+
<MaterialReactTable columns={columns()} data={data} enableGrouping />,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const handle = container.querySelector(
|
|
29
|
+
'thead button[aria-label="Move"]',
|
|
30
|
+
) as HTMLElement;
|
|
31
|
+
|
|
32
|
+
fireEvent.dragStart(handle, {
|
|
33
|
+
dataTransfer: { setDragImage: () => {} },
|
|
34
|
+
});
|
|
35
|
+
fireEvent.dragEnter(
|
|
36
|
+
container.querySelector('[class*="ToolbarDropZone"]') as HTMLElement,
|
|
37
|
+
);
|
|
38
|
+
fireEvent.dragEnd(handle);
|
|
39
|
+
|
|
40
|
+
expect(container.textContent).toContain('Grouped by');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -17,14 +17,13 @@ export const MRT_ToolbarDropZone = <TData extends MRT_RowData>({
|
|
|
17
17
|
...rest
|
|
18
18
|
}: MRT_ToolbarDropZoneProps<TData>) => {
|
|
19
19
|
const {
|
|
20
|
-
getState,
|
|
21
20
|
options: { enableGrouping, localization },
|
|
22
21
|
setHoveredColumn,
|
|
23
22
|
setShowToolbarDropZone,
|
|
24
23
|
} = table;
|
|
25
24
|
|
|
26
25
|
const { draggingColumn, grouping, hoveredColumn, showToolbarDropZone } =
|
|
27
|
-
|
|
26
|
+
table.state;
|
|
28
27
|
|
|
29
28
|
const handleDragEnter = (_event: DragEvent<HTMLDivElement>) => {
|
|
30
29
|
setHoveredColumn({ id: 'drop-zone' });
|
|
@@ -18,7 +18,6 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
18
18
|
table,
|
|
19
19
|
}: MRT_TopToolbarProps<TData>) => {
|
|
20
20
|
const {
|
|
21
|
-
getState,
|
|
22
21
|
options: {
|
|
23
22
|
enableGlobalFilter,
|
|
24
23
|
enablePagination,
|
|
@@ -33,7 +32,7 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
33
32
|
refs: { topToolbarRef },
|
|
34
33
|
} = table;
|
|
35
34
|
|
|
36
|
-
const { isFullScreen, showGlobalFilter } =
|
|
35
|
+
const { isFullScreen, showGlobalFilter } = table.state;
|
|
37
36
|
|
|
38
37
|
const isMobile = useMediaQuery('(max-width:720px)');
|
|
39
38
|
const isTablet = useMediaQuery('(max-width:1024px)');
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { MaterialReactTable } from '../components/MaterialReactTable';
|
|
5
|
+
import { type MRT_ColumnDef } from '../types';
|
|
6
|
+
|
|
7
|
+
interface Sale {
|
|
8
|
+
amount: number;
|
|
9
|
+
region: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const data: Sale[] = [
|
|
13
|
+
{ amount: 10, region: 'North' },
|
|
14
|
+
{ amount: 30, region: 'North' },
|
|
15
|
+
{ amount: 100, region: 'South' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const columns = (aggregationFn: string): MRT_ColumnDef<Sale>[] => [
|
|
19
|
+
{ accessorKey: 'region', header: 'Region' },
|
|
20
|
+
{
|
|
21
|
+
accessorKey: 'amount',
|
|
22
|
+
AggregatedCell: ({ cell }) => <span>agg:{String(cell.getValue())}</span>,
|
|
23
|
+
aggregationFn,
|
|
24
|
+
header: 'Amount',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const renderGrouped = (aggregationFn: string) =>
|
|
29
|
+
render(
|
|
30
|
+
<MaterialReactTable
|
|
31
|
+
columns={columns(aggregationFn)}
|
|
32
|
+
data={data}
|
|
33
|
+
enableExpanding
|
|
34
|
+
enableGrouping
|
|
35
|
+
initialState={{ expanded: true, grouping: ['region'] }}
|
|
36
|
+
/>,
|
|
37
|
+
).container;
|
|
38
|
+
|
|
39
|
+
describe('aggregation fns', () => {
|
|
40
|
+
test.each([
|
|
41
|
+
['sum', ['agg:40', 'agg:100']],
|
|
42
|
+
['max', ['agg:30', 'agg:100']],
|
|
43
|
+
['min', ['agg:10', 'agg:100']],
|
|
44
|
+
['mean', ['agg:20', 'agg:100']],
|
|
45
|
+
['count', ['agg:2', 'agg:1']],
|
|
46
|
+
])('%s aggregates each group', (aggregationFn, expected) => {
|
|
47
|
+
const container = renderGrouped(aggregationFn);
|
|
48
|
+
|
|
49
|
+
const aggregated = Array.from(
|
|
50
|
+
container.querySelectorAll('tbody td'),
|
|
51
|
+
)
|
|
52
|
+
.map((td) => td.textContent)
|
|
53
|
+
.filter((text) => text?.startsWith('agg:'));
|
|
54
|
+
|
|
55
|
+
expect(aggregated).toEqual(expected);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { MaterialReactTable } from '../components/MaterialReactTable';
|
|
5
|
+
import { type MRT_ColumnDef } from '../types';
|
|
6
|
+
|
|
7
|
+
interface Person {
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const data: Person[] = [
|
|
12
|
+
{ name: 'Jonathan' },
|
|
13
|
+
{ name: 'John' },
|
|
14
|
+
{ name: 'Sara' },
|
|
15
|
+
{ name: 'Aaron' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const columns: MRT_ColumnDef<Person>[] = [
|
|
19
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const renderedNames = (container: HTMLElement) =>
|
|
23
|
+
Array.from(container.querySelectorAll('tbody tr')).map(
|
|
24
|
+
(row) => row.textContent,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
describe('fuzzy global filter', () => {
|
|
28
|
+
test('keeps rows whose value matches the term and drops the rest', () => {
|
|
29
|
+
render(
|
|
30
|
+
<MaterialReactTable
|
|
31
|
+
columns={columns}
|
|
32
|
+
data={data}
|
|
33
|
+
initialState={{ globalFilter: 'john' }}
|
|
34
|
+
/>,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
expect(screen.getByText('John')).toBeInTheDocument();
|
|
38
|
+
expect(screen.getByText('Jonathan')).toBeInTheDocument();
|
|
39
|
+
expect(screen.queryByText('Sara')).not.toBeInTheDocument();
|
|
40
|
+
expect(screen.queryByText('Aaron')).not.toBeInTheDocument();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('orders matches by rank rather than by source order', () => {
|
|
44
|
+
const { container } = render(
|
|
45
|
+
<MaterialReactTable
|
|
46
|
+
columns={columns}
|
|
47
|
+
data={data}
|
|
48
|
+
initialState={{ globalFilter: 'john' }}
|
|
49
|
+
/>,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(renderedNames(container)).toEqual(['John', 'Jonathan']);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('falls back to source order when ranked results are disabled', () => {
|
|
56
|
+
const { container } = render(
|
|
57
|
+
<MaterialReactTable
|
|
58
|
+
columns={columns}
|
|
59
|
+
data={data}
|
|
60
|
+
enableGlobalFilterRankedResults={false}
|
|
61
|
+
initialState={{ globalFilter: 'john' }}
|
|
62
|
+
/>,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(renderedNames(container)).toEqual(['Jonathan', 'John']);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('drops every row when no value matches the term', () => {
|
|
69
|
+
const { container } = render(
|
|
70
|
+
<MaterialReactTable
|
|
71
|
+
columns={columns}
|
|
72
|
+
data={data}
|
|
73
|
+
initialState={{ globalFilter: 'zzz' }}
|
|
74
|
+
/>,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(renderedNames(container)).toEqual(['No results found']);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
interface Employee {
|
|
82
|
+
age: number;
|
|
83
|
+
name: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const employees: Employee[] = [
|
|
87
|
+
{ age: 30, name: 'Alice' },
|
|
88
|
+
{ age: 20, name: 'Bob' },
|
|
89
|
+
{ age: 40, name: 'alice' },
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const employeeColumns = (): MRT_ColumnDef<Employee>[] => [
|
|
93
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
94
|
+
{ accessorKey: 'age', header: 'Age' },
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
const renderFiltered = (
|
|
98
|
+
columnId: string,
|
|
99
|
+
filterFn: string,
|
|
100
|
+
value: unknown,
|
|
101
|
+
) => {
|
|
102
|
+
const { container } = render(
|
|
103
|
+
<MaterialReactTable
|
|
104
|
+
columns={employeeColumns()}
|
|
105
|
+
data={employees}
|
|
106
|
+
initialState={{
|
|
107
|
+
columnFilterFns: { [columnId]: filterFn },
|
|
108
|
+
columnFilters: [{ id: columnId, value }],
|
|
109
|
+
}}
|
|
110
|
+
/>,
|
|
111
|
+
);
|
|
112
|
+
return Array.from(container.querySelectorAll('tbody tr')).map(
|
|
113
|
+
(row) => row.querySelector('td')?.textContent,
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
describe('column filter fns', () => {
|
|
118
|
+
test.each([
|
|
119
|
+
['contains', 'ali', ['Alice', 'alice']],
|
|
120
|
+
['startsWith', 'al', ['Alice', 'alice']],
|
|
121
|
+
['endsWith', 'ce', ['Alice', 'alice']],
|
|
122
|
+
['equals', 'alice', ['Alice', 'alice']],
|
|
123
|
+
['notEquals', 'alice', ['Bob']],
|
|
124
|
+
['fuzzy', 'bob', ['Bob']],
|
|
125
|
+
['includesString', 'ali', ['Alice', 'alice']],
|
|
126
|
+
['includesStringSensitive', 'ali', ['alice']],
|
|
127
|
+
['equalsString', 'alice', ['Alice', 'alice']],
|
|
128
|
+
['equalsStringSensitive', 'alice', ['alice']],
|
|
129
|
+
])('%s filters the name column', (filterFn, value, expected) => {
|
|
130
|
+
expect(renderFiltered('name', filterFn, value)).toEqual(expected);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test.each([
|
|
134
|
+
['greaterThan', 25, ['Alice', 'alice']],
|
|
135
|
+
['greaterThanOrEqualTo', 30, ['Alice', 'alice']],
|
|
136
|
+
['lessThan', 30, ['Bob']],
|
|
137
|
+
['lessThanOrEqualTo', 20, ['Bob']],
|
|
138
|
+
])('%s filters the age column', (filterFn, value, expected) => {
|
|
139
|
+
expect(renderFiltered('age', filterFn, value)).toEqual(expected);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test.each([
|
|
143
|
+
['between', [25, 45], ['Alice', 'alice']],
|
|
144
|
+
['betweenInclusive', [20, 30], ['Alice', 'Bob']],
|
|
145
|
+
['inNumberRange', [20, 30], ['Alice', 'Bob']],
|
|
146
|
+
])('%s filters the age column by range', (filterFn, value, expected) => {
|
|
147
|
+
expect(renderFiltered('age', filterFn, value)).toEqual(expected);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test.each([
|
|
151
|
+
['empty', ['No results found']],
|
|
152
|
+
['notEmpty', ['Alice', 'Bob', 'alice']],
|
|
153
|
+
])('%s applies to the name column', (filterFn, expected) => {
|
|
154
|
+
expect(renderFiltered('name', filterFn, 'x')).toEqual(expected);
|
|
155
|
+
});
|
|
156
|
+
});
|