@cutting/material-react-table 5.0.0-beta.2 → 5.1.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/README.md +1 -4
- package/dist/index.d.ts +189 -524
- package/dist/index.js +329 -345
- package/dist/index.js.map +1 -1
- package/locales/ar/index.mjs +1 -2
- package/locales/az/index.mjs +1 -2
- package/locales/bg/index.mjs +1 -2
- package/locales/cs/index.mjs +1 -2
- package/locales/da/index.mjs +1 -2
- package/locales/de/index.mjs +1 -2
- package/locales/el/index.mjs +1 -2
- package/locales/en/index.mjs +1 -2
- package/locales/es/index.mjs +1 -2
- package/locales/et/index.mjs +1 -2
- package/locales/fa/index.mjs +1 -2
- package/locales/fi/index.mjs +1 -2
- package/locales/fr/index.mjs +1 -2
- package/locales/he/index.mjs +1 -2
- package/locales/hr/index.mjs +1 -2
- package/locales/hu/index.mjs +1 -2
- package/locales/hy/index.mjs +1 -2
- package/locales/id/index.mjs +1 -2
- package/locales/it/index.mjs +1 -2
- package/locales/ja/index.mjs +1 -2
- package/locales/ko/index.mjs +1 -2
- package/locales/nl/index.mjs +1 -2
- package/locales/no/index.mjs +1 -2
- package/locales/np/index.mjs +1 -2
- package/locales/pl/index.mjs +1 -2
- package/locales/pt/index.mjs +1 -2
- package/locales/pt-BR/index.mjs +1 -2
- package/locales/ro/index.mjs +1 -2
- package/locales/ru/index.mjs +1 -2
- package/locales/sk/index.mjs +1 -2
- package/locales/sr-Cyrl-RS/index.mjs +1 -2
- package/locales/sr-Latn-RS/index.mjs +1 -2
- package/locales/sv/index.mjs +1 -2
- package/locales/tr/index.mjs +1 -2
- package/locales/uk/index.mjs +1 -2
- package/locales/vi/index.mjs +1 -2
- package/locales/zh-Hans/index.mjs +1 -2
- package/locales/zh-Hant/index.mjs +1 -2
- package/package.json +32 -40
- package/src/MaterialReactTable.smoke.test.tsx +3 -9
- package/src/components/MaterialReactTable.tsx +13 -21
- package/src/components/body/MRT_TableBody.tsx +67 -82
- package/src/components/body/MRT_TableBodyCell.tsx +38 -80
- package/src/components/body/MRT_TableBodyCellValue.tsx +5 -14
- package/src/components/body/MRT_TableBodyRow.tsx +55 -102
- package/src/components/body/MRT_TableBodyRowGrabHandle.test.tsx +2 -6
- package/src/components/body/MRT_TableBodyRowGrabHandle.tsx +4 -9
- package/src/components/body/MRT_TableBodyRowPinButton.tsx +8 -14
- package/src/components/body/MRT_TableDetailPanel.test.tsx +3 -9
- package/src/components/body/MRT_TableDetailPanel.tsx +8 -14
- package/src/components/buttons/MRT_ColumnPinningButtons.test.tsx +6 -16
- package/src/components/buttons/MRT_ColumnPinningButtons.tsx +6 -12
- package/src/components/buttons/MRT_CopyButton.tsx +7 -15
- package/src/components/buttons/MRT_EditActionButtons.test.tsx +2 -6
- package/src/components/buttons/MRT_EditActionButtons.tsx +15 -37
- package/src/components/buttons/MRT_ExpandAllButton.tsx +8 -16
- package/src/components/buttons/MRT_ExpandButton.tsx +9 -21
- package/src/components/buttons/MRT_GrabHandleButton.tsx +6 -10
- package/src/components/buttons/MRT_RowPinButton.tsx +8 -23
- package/src/components/buttons/MRT_ShowHideColumnsButton.tsx +5 -18
- package/src/components/buttons/MRT_ToggleDensePaddingButton.test.tsx +4 -12
- package/src/components/buttons/MRT_ToggleDensePaddingButton.tsx +4 -11
- package/src/components/buttons/MRT_ToggleFiltersButton.test.tsx +4 -13
- package/src/components/buttons/MRT_ToggleFiltersButton.tsx +3 -5
- package/src/components/buttons/MRT_ToggleFullScreenButton.test.tsx +3 -11
- package/src/components/buttons/MRT_ToggleFullScreenButton.tsx +4 -9
- package/src/components/buttons/MRT_ToggleGlobalFilterButton.tsx +3 -5
- package/src/components/buttons/MRT_ToggleRowActionMenuButton.tsx +7 -15
- package/src/components/footer/MRT_TableFooter.tsx +9 -16
- package/src/components/footer/MRT_TableFooterCell.tsx +9 -32
- package/src/components/footer/MRT_TableFooterRow.tsx +18 -32
- package/src/components/head/MRT_TableHead.tsx +8 -18
- package/src/components/head/MRT_TableHeadCell.tsx +46 -100
- package/src/components/head/MRT_TableHeadCellColumnActionsButton.tsx +10 -30
- package/src/components/head/MRT_TableHeadCellFilterContainer.tsx +4 -15
- package/src/components/head/MRT_TableHeadCellFilterLabel.tsx +20 -54
- package/src/components/head/MRT_TableHeadCellGrabHandle.test.tsx +5 -19
- package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +9 -38
- package/src/components/head/MRT_TableHeadCellResizeHandle.test.tsx +3 -13
- package/src/components/head/MRT_TableHeadCellResizeHandle.tsx +10 -24
- package/src/components/head/MRT_TableHeadCellSortLabel.tsx +10 -26
- package/src/components/head/MRT_TableHeadRow.tsx +24 -36
- package/src/components/inputs/MRT_EditCellTextField.test.tsx +2 -9
- package/src/components/inputs/MRT_EditCellTextField.tsx +9 -28
- package/src/components/inputs/MRT_FilterCheckbox.tsx +9 -23
- package/src/components/inputs/MRT_FilterRangeFields.tsx +6 -15
- package/src/components/inputs/MRT_FilterRangeSlider.tsx +24 -32
- package/src/components/inputs/MRT_FilterTextField.test.tsx +72 -14
- package/src/components/inputs/MRT_FilterTextField.tsx +77 -138
- package/src/components/inputs/MRT_GlobalFilterTextField.tsx +10 -32
- package/src/components/inputs/MRT_SelectCheckbox.test.tsx +4 -11
- package/src/components/inputs/MRT_SelectCheckbox.tsx +17 -36
- package/src/components/menus/MRT_ActionMenuItem.tsx +6 -15
- package/src/components/menus/MRT_CellActionMenu.tsx +6 -9
- package/src/components/menus/MRT_ColumnActionMenu.tsx +22 -57
- package/src/components/menus/MRT_FilterOptionMenu.tsx +38 -65
- package/src/components/menus/MRT_RowActionMenu.tsx +33 -22
- package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +29 -65
- package/src/components/menus/MRT_ShowHideColumnsMenuItems.test.tsx +43 -0
- package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +14 -50
- package/src/components/modals/MRT_EditRowModal.test.tsx +5 -21
- package/src/components/modals/MRT_EditRowModal.tsx +8 -26
- package/src/components/table/MRT_Table.tsx +12 -20
- package/src/components/table/MRT_TableContainer.test.tsx +147 -0
- package/src/components/table/MRT_TableContainer.tsx +33 -37
- package/src/components/table/MRT_TableLoadingOverlay.tsx +3 -5
- package/src/components/table/MRT_TablePaper.tsx +7 -14
- package/src/components/toolbar/MRT_BottomToolbar.tsx +11 -23
- package/src/components/toolbar/MRT_LinearProgressBar.tsx +4 -11
- package/src/components/toolbar/MRT_TablePagination.tsx +33 -40
- package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +21 -50
- package/src/components/toolbar/MRT_ToolbarDropZone.test.tsx +26 -10
- package/src/components/toolbar/MRT_ToolbarDropZone.tsx +23 -21
- package/src/components/toolbar/MRT_ToolbarInternalButtons.tsx +11 -21
- package/src/components/toolbar/MRT_TopToolbar.tsx +12 -28
- package/src/fns/aggregationFns.test.tsx +1 -3
- package/src/fns/filterFns.test.tsx +9 -37
- package/src/fns/filterFns.ts +73 -96
- package/src/fns/sortingFns.test.tsx +39 -0
- package/src/fns/sortingFns.ts +15 -15
- package/src/fns/tableFeatures.test.tsx +6 -29
- package/src/fns/tableFeatures.ts +5 -4
- package/src/hooks/display-columns/getMRT_RowActionsColumnDef.tsx +2 -11
- package/src/hooks/display-columns/getMRT_RowDragColumnDef.tsx +2 -10
- package/src/hooks/display-columns/getMRT_RowExpandColumnDef.tsx +8 -17
- package/src/hooks/display-columns/getMRT_RowNumbersColumnDef.tsx +3 -8
- package/src/hooks/display-columns/getMRT_RowPinningColumnDef.tsx +2 -8
- package/src/hooks/display-columns/getMRT_RowSelectColumnDef.tsx +3 -13
- package/src/hooks/display-columns/getMRT_RowSpacerColumnDef.tsx +1 -5
- package/src/hooks/useMRT_ColumnVirtualizer.ts +28 -49
- package/src/hooks/useMRT_Effects.test.tsx +114 -0
- package/src/hooks/useMRT_Effects.ts +26 -27
- package/src/hooks/useMRT_RowVirtualizer.ts +18 -33
- package/src/hooks/useMRT_Rows.ts +3 -42
- package/src/hooks/useMRT_TableInstance.ts +63 -129
- package/src/hooks/useMRT_TableOptions.ts +15 -29
- package/src/hooks/useMaterialReactTable.ts +2 -7
- package/src/icons.ts +38 -1
- package/src/index.ts +0 -4
- package/src/locales/ar.ts +1 -2
- package/src/locales/az.ts +1 -2
- package/src/locales/bg.ts +1 -2
- package/src/locales/cs.ts +2 -4
- package/src/locales/da.ts +1 -2
- package/src/locales/de.ts +1 -2
- package/src/locales/el.ts +1 -2
- package/src/locales/en.ts +1 -2
- package/src/locales/es.ts +1 -2
- package/src/locales/et.ts +2 -4
- package/src/locales/fa.ts +1 -2
- package/src/locales/fi.ts +2 -4
- package/src/locales/fr.ts +1 -2
- package/src/locales/he.ts +1 -2
- package/src/locales/hr.ts +1 -2
- package/src/locales/hu.ts +1 -2
- package/src/locales/hy.ts +1 -2
- package/src/locales/id.ts +2 -4
- package/src/locales/it.ts +1 -2
- package/src/locales/ja.ts +1 -2
- package/src/locales/ko.ts +1 -2
- package/src/locales/nl.ts +1 -2
- package/src/locales/no.ts +2 -4
- package/src/locales/np.ts +2 -4
- package/src/locales/pl.ts +1 -2
- package/src/locales/pt-BR.ts +1 -2
- package/src/locales/pt.ts +1 -2
- package/src/locales/ro.ts +1 -2
- package/src/locales/ru.ts +1 -2
- package/src/locales/sk.ts +2 -4
- package/src/locales/sr-Cyrl-RS.ts +1 -2
- package/src/locales/sr-Latn-RS.ts +1 -2
- package/src/locales/sv.ts +1 -2
- package/src/locales/tr.ts +1 -2
- package/src/locales/uk.ts +1 -2
- package/src/locales/vi.ts +1 -2
- package/src/types.ts +156 -349
- package/src/utils/cell.utils.ts +30 -68
- package/src/utils/column.utils.ts +61 -49
- package/src/utils/displayColumn.utils.ts +16 -38
- package/src/utils/highlight.utils.ts +7 -11
- package/src/utils/row.utils.ts +40 -65
- package/src/utils/slotProps.utils.ts +1 -4
- package/src/utils/style.utils.ts +18 -46
- package/src/utils/tanstack.helpers.ts +10 -17
- package/src/utils/utils.ts +6 -10
- package/src/utils/virtualization.utils.ts +5 -9
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import { Box, type BoxProps } from '@mui/material';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { alpha } from '@mui/material/styles';
|
|
5
|
-
import { type DragEvent, useEffect } from 'react';
|
|
1
|
+
import { Box, type BoxProps, Fade, Typography } from '@mui/material';
|
|
2
|
+
import { alpha, type CSSObject } from '@mui/material/styles';
|
|
3
|
+
import { type DragEvent, useEffect, useRef } from 'react';
|
|
6
4
|
|
|
7
5
|
import { type MRT_RowData, type MRT_TableInstance } from '../../types';
|
|
8
6
|
import { parseFromValuesOrFunc } from '../../utils/utils';
|
|
9
7
|
|
|
10
|
-
export interface MRT_ToolbarDropZoneProps<TData extends MRT_RowData>
|
|
11
|
-
extends BoxProps {
|
|
8
|
+
export interface MRT_ToolbarDropZoneProps<TData extends MRT_RowData> extends BoxProps {
|
|
12
9
|
table: MRT_TableInstance<TData>;
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
export const MRT_ToolbarDropZone = <TData extends MRT_RowData>({
|
|
16
13
|
table,
|
|
17
14
|
...rest
|
|
18
|
-
}: MRT_ToolbarDropZoneProps<TData>) => {
|
|
15
|
+
}: MRT_ToolbarDropZoneProps<TData>): JSX.Element => {
|
|
19
16
|
const {
|
|
20
17
|
options: { enableGrouping, localization },
|
|
21
18
|
setHoveredColumn,
|
|
22
19
|
setShowToolbarDropZone,
|
|
23
20
|
} = table;
|
|
24
21
|
|
|
25
|
-
const { draggingColumn, grouping, hoveredColumn, showToolbarDropZone } =
|
|
26
|
-
table.state;
|
|
22
|
+
const { draggingColumn, grouping, hoveredColumn, showToolbarDropZone } = table.state;
|
|
27
23
|
|
|
28
24
|
const handleDragEnter = (_event: DragEvent<HTMLDivElement>) => {
|
|
29
25
|
setHoveredColumn({ id: 'drop-zone' });
|
|
@@ -33,16 +29,23 @@ export const MRT_ToolbarDropZone = <TData extends MRT_RowData>({
|
|
|
33
29
|
e.preventDefault();
|
|
34
30
|
};
|
|
35
31
|
|
|
32
|
+
const isShowToolbarDropZoneControlled = table.options.state?.showToolbarDropZone !== undefined;
|
|
33
|
+
const setShowToolbarDropZoneRef = useRef(setShowToolbarDropZone);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setShowToolbarDropZoneRef.current = setShowToolbarDropZone;
|
|
37
|
+
});
|
|
38
|
+
|
|
36
39
|
useEffect(() => {
|
|
37
|
-
if (
|
|
38
|
-
|
|
40
|
+
if (isShowToolbarDropZoneControlled) {
|
|
41
|
+
setShowToolbarDropZoneRef.current(
|
|
39
42
|
!!enableGrouping &&
|
|
40
43
|
!!draggingColumn &&
|
|
41
44
|
draggingColumn.columnDef.enableGrouping !== false &&
|
|
42
45
|
!grouping.includes(draggingColumn.id),
|
|
43
46
|
);
|
|
44
47
|
}
|
|
45
|
-
}, [enableGrouping,
|
|
48
|
+
}, [draggingColumn, enableGrouping, grouping, isShowToolbarDropZoneControlled]);
|
|
46
49
|
|
|
47
50
|
return (
|
|
48
51
|
<Fade in={showToolbarDropZone}>
|
|
@@ -63,16 +66,15 @@ export const MRT_ToolbarDropZone = <TData extends MRT_RowData>({
|
|
|
63
66
|
position: 'absolute',
|
|
64
67
|
width: '100%',
|
|
65
68
|
zIndex: 4,
|
|
66
|
-
...(parseFromValuesOrFunc(rest?.sx, theme) as
|
|
69
|
+
...(parseFromValuesOrFunc(rest?.sx, theme) as CSSObject),
|
|
67
70
|
})}
|
|
68
71
|
>
|
|
69
|
-
<Typography
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)}
|
|
72
|
+
<Typography
|
|
73
|
+
sx={{
|
|
74
|
+
fontStyle: 'italic',
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{localization.dropToGroupBy.replace('{column}', draggingColumn?.columnDef?.header ?? '')}
|
|
76
78
|
</Typography>
|
|
77
79
|
</Box>
|
|
78
80
|
</Fade>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Box, type BoxProps } from '@mui/material';
|
|
2
|
+
import { type CSSObject } from '@mui/material/styles';
|
|
2
3
|
|
|
3
4
|
import { type MRT_RowData, type MRT_TableInstance } from '../../types';
|
|
4
5
|
import { parseFromValuesOrFunc } from '../../utils/utils';
|
|
@@ -8,15 +9,14 @@ import { MRT_ToggleFiltersButton } from '../buttons/MRT_ToggleFiltersButton';
|
|
|
8
9
|
import { MRT_ToggleFullScreenButton } from '../buttons/MRT_ToggleFullScreenButton';
|
|
9
10
|
import { MRT_ToggleGlobalFilterButton } from '../buttons/MRT_ToggleGlobalFilterButton';
|
|
10
11
|
|
|
11
|
-
export interface MRT_ToolbarInternalButtonsProps<TData extends MRT_RowData>
|
|
12
|
-
extends BoxProps {
|
|
12
|
+
export interface MRT_ToolbarInternalButtonsProps<TData extends MRT_RowData> extends BoxProps {
|
|
13
13
|
table: MRT_TableInstance<TData>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export const MRT_ToolbarInternalButtons = <TData extends MRT_RowData>({
|
|
17
17
|
table,
|
|
18
18
|
...rest
|
|
19
|
-
}: MRT_ToolbarInternalButtonsProps<TData>) => {
|
|
19
|
+
}: MRT_ToolbarInternalButtonsProps<TData>): JSX.Element => {
|
|
20
20
|
const {
|
|
21
21
|
options: {
|
|
22
22
|
columnFilterDisplayMode,
|
|
@@ -40,32 +40,22 @@ export const MRT_ToolbarInternalButtons = <TData extends MRT_RowData>({
|
|
|
40
40
|
alignItems: 'center',
|
|
41
41
|
display: 'flex',
|
|
42
42
|
zIndex: 3,
|
|
43
|
-
...(parseFromValuesOrFunc(rest?.sx, theme) as
|
|
43
|
+
...(parseFromValuesOrFunc(rest?.sx, theme) as CSSObject),
|
|
44
44
|
})}
|
|
45
45
|
>
|
|
46
46
|
{renderToolbarInternalActions?.({
|
|
47
47
|
table,
|
|
48
48
|
}) ?? (
|
|
49
49
|
<>
|
|
50
|
-
{enableFilters &&
|
|
51
|
-
|
|
52
|
-
!initialState?.showGlobalFilter && (
|
|
53
|
-
<MRT_ToggleGlobalFilterButton table={table} />
|
|
54
|
-
)}
|
|
55
|
-
{enableFilters &&
|
|
56
|
-
enableColumnFilters &&
|
|
57
|
-
columnFilterDisplayMode !== 'popover' && (
|
|
58
|
-
<MRT_ToggleFiltersButton table={table} />
|
|
59
|
-
)}
|
|
60
|
-
{(enableHiding || enableColumnOrdering || enableColumnPinning) && (
|
|
61
|
-
<MRT_ShowHideColumnsButton table={table} />
|
|
50
|
+
{enableFilters && enableGlobalFilter && !initialState?.showGlobalFilter && (
|
|
51
|
+
<MRT_ToggleGlobalFilterButton table={table} />
|
|
62
52
|
)}
|
|
63
|
-
{
|
|
64
|
-
<
|
|
65
|
-
)}
|
|
66
|
-
{enableFullScreenToggle && (
|
|
67
|
-
<MRT_ToggleFullScreenButton table={table} />
|
|
53
|
+
{enableFilters && enableColumnFilters && columnFilterDisplayMode !== 'popover' && (
|
|
54
|
+
<MRT_ToggleFiltersButton table={table} />
|
|
68
55
|
)}
|
|
56
|
+
{(enableHiding || enableColumnOrdering || enableColumnPinning) && <MRT_ShowHideColumnsButton table={table} />}
|
|
57
|
+
{enableDensityToggle && <MRT_ToggleDensePaddingButton table={table} />}
|
|
58
|
+
{enableFullScreenToggle && <MRT_ToggleFullScreenButton table={table} />}
|
|
69
59
|
</>
|
|
70
60
|
)}
|
|
71
61
|
</Box>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Box, useMediaQuery } from '@mui/material';
|
|
2
|
+
import { type CSSObject } from '@mui/material/styles';
|
|
2
3
|
|
|
3
4
|
import { type MRT_RowData, type MRT_TableInstance } from '../../types';
|
|
4
5
|
import { getCommonToolbarStyles } from '../../utils/style.utils';
|
|
@@ -14,9 +15,7 @@ export interface MRT_TopToolbarProps<TData extends MRT_RowData> {
|
|
|
14
15
|
table: MRT_TableInstance<TData>;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
18
|
-
table,
|
|
19
|
-
}: MRT_TopToolbarProps<TData>) => {
|
|
18
|
+
export const MRT_TopToolbar = <TData extends MRT_RowData>({ table }: MRT_TopToolbarProps<TData>): JSX.Element => {
|
|
20
19
|
const {
|
|
21
20
|
options: {
|
|
22
21
|
enableGlobalFilter,
|
|
@@ -39,10 +38,7 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
39
38
|
|
|
40
39
|
const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table });
|
|
41
40
|
|
|
42
|
-
const stackAlertBanner =
|
|
43
|
-
isMobile ||
|
|
44
|
-
!!renderTopToolbarCustomActions ||
|
|
45
|
-
(showGlobalFilter && isTablet);
|
|
41
|
+
const stackAlertBanner = isMobile || !!renderTopToolbarCustomActions || (showGlobalFilter && isTablet);
|
|
46
42
|
|
|
47
43
|
const globalFilterProps = {
|
|
48
44
|
sx: !isTablet
|
|
@@ -58,8 +54,7 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
58
54
|
{...toolbarProps}
|
|
59
55
|
ref={(ref: HTMLDivElement) => {
|
|
60
56
|
topToolbarRef.current = ref;
|
|
61
|
-
if (toolbarProps?.ref) {
|
|
62
|
-
// @ts-expect-error
|
|
57
|
+
if (toolbarProps?.ref && typeof toolbarProps.ref === 'object') {
|
|
63
58
|
toolbarProps.ref.current = ref;
|
|
64
59
|
}
|
|
65
60
|
}}
|
|
@@ -67,18 +62,13 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
67
62
|
...getCommonToolbarStyles({ table, theme }),
|
|
68
63
|
position: isFullScreen ? 'sticky' : 'relative',
|
|
69
64
|
top: isFullScreen ? '0' : undefined,
|
|
70
|
-
...(parseFromValuesOrFunc(toolbarProps?.sx, theme) as
|
|
65
|
+
...(parseFromValuesOrFunc(toolbarProps?.sx, theme) as CSSObject),
|
|
71
66
|
})}
|
|
72
67
|
>
|
|
73
68
|
{positionToolbarAlertBanner === 'top' && (
|
|
74
|
-
<MRT_ToolbarAlertBanner
|
|
75
|
-
stackAlertBanner={stackAlertBanner}
|
|
76
|
-
table={table}
|
|
77
|
-
/>
|
|
78
|
-
)}
|
|
79
|
-
{['both', 'top'].includes(positionToolbarDropZone ?? '') && (
|
|
80
|
-
<MRT_ToolbarDropZone table={table} />
|
|
69
|
+
<MRT_ToolbarAlertBanner stackAlertBanner={stackAlertBanner} table={table} />
|
|
81
70
|
)}
|
|
71
|
+
{['both', 'top'].includes(positionToolbarDropZone ?? '') && <MRT_ToolbarDropZone table={table} />}
|
|
82
72
|
<Box
|
|
83
73
|
sx={{
|
|
84
74
|
alignItems: 'flex-start',
|
|
@@ -93,9 +83,7 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
93
83
|
width: '100%',
|
|
94
84
|
}}
|
|
95
85
|
>
|
|
96
|
-
{enableGlobalFilter && positionGlobalFilter === 'left' &&
|
|
97
|
-
<MRT_GlobalFilterTextField {...globalFilterProps} />
|
|
98
|
-
)}
|
|
86
|
+
{enableGlobalFilter && positionGlobalFilter === 'left' && <MRT_GlobalFilterTextField {...globalFilterProps} />}
|
|
99
87
|
{renderTopToolbarCustomActions?.({ table }) ?? <span />}
|
|
100
88
|
{enableToolbarInternalActions ? (
|
|
101
89
|
<Box
|
|
@@ -113,16 +101,12 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
|
|
|
113
101
|
<MRT_ToolbarInternalButtons table={table} />
|
|
114
102
|
</Box>
|
|
115
103
|
) : (
|
|
116
|
-
enableGlobalFilter &&
|
|
117
|
-
positionGlobalFilter === 'right' && (
|
|
118
|
-
<MRT_GlobalFilterTextField {...globalFilterProps} />
|
|
119
|
-
)
|
|
104
|
+
enableGlobalFilter && positionGlobalFilter === 'right' && <MRT_GlobalFilterTextField {...globalFilterProps} />
|
|
120
105
|
)}
|
|
121
106
|
</Box>
|
|
122
|
-
{enablePagination &&
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
)}
|
|
107
|
+
{enablePagination && ['both', 'top'].includes(positionPagination ?? '') && (
|
|
108
|
+
<MRT_TablePagination position="top" table={table} />
|
|
109
|
+
)}
|
|
126
110
|
<MRT_LinearProgressBar isTopToolbar table={table} />
|
|
127
111
|
</Box>
|
|
128
112
|
);
|
|
@@ -46,9 +46,7 @@ describe('aggregation fns', () => {
|
|
|
46
46
|
])('%s aggregates each group', (aggregationFn, expected) => {
|
|
47
47
|
const container = renderGrouped(aggregationFn);
|
|
48
48
|
|
|
49
|
-
const aggregated = Array.from(
|
|
50
|
-
container.querySelectorAll('tbody td'),
|
|
51
|
-
)
|
|
49
|
+
const aggregated = Array.from(container.querySelectorAll('tbody td'))
|
|
52
50
|
.map((td) => td.textContent)
|
|
53
51
|
.filter((text) => text?.startsWith('agg:'));
|
|
54
52
|
|
|
@@ -8,31 +8,16 @@ interface Person {
|
|
|
8
8
|
name: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const data: Person[] = [
|
|
12
|
-
{ name: 'Jonathan' },
|
|
13
|
-
{ name: 'John' },
|
|
14
|
-
{ name: 'Sara' },
|
|
15
|
-
{ name: 'Aaron' },
|
|
16
|
-
];
|
|
11
|
+
const data: Person[] = [{ name: 'Jonathan' }, { name: 'John' }, { name: 'Sara' }, { name: 'Aaron' }];
|
|
17
12
|
|
|
18
|
-
const columns: MRT_ColumnDef<Person>[] = [
|
|
19
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
20
|
-
];
|
|
13
|
+
const columns: MRT_ColumnDef<Person>[] = [{ accessorKey: 'name', header: 'Name' }];
|
|
21
14
|
|
|
22
15
|
const renderedNames = (container: HTMLElement) =>
|
|
23
|
-
Array.from(container.querySelectorAll('tbody tr')).map(
|
|
24
|
-
(row) => row.textContent,
|
|
25
|
-
);
|
|
16
|
+
Array.from(container.querySelectorAll('tbody tr')).map((row) => row.textContent);
|
|
26
17
|
|
|
27
18
|
describe('fuzzy global filter', () => {
|
|
28
19
|
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
|
-
);
|
|
20
|
+
render(<MaterialReactTable columns={columns} data={data} initialState={{ globalFilter: 'john' }} />);
|
|
36
21
|
|
|
37
22
|
expect(screen.getByText('John')).toBeInTheDocument();
|
|
38
23
|
expect(screen.getByText('Jonathan')).toBeInTheDocument();
|
|
@@ -42,11 +27,7 @@ describe('fuzzy global filter', () => {
|
|
|
42
27
|
|
|
43
28
|
test('orders matches by rank rather than by source order', () => {
|
|
44
29
|
const { container } = render(
|
|
45
|
-
<MaterialReactTable
|
|
46
|
-
columns={columns}
|
|
47
|
-
data={data}
|
|
48
|
-
initialState={{ globalFilter: 'john' }}
|
|
49
|
-
/>,
|
|
30
|
+
<MaterialReactTable columns={columns} data={data} initialState={{ globalFilter: 'john' }} />,
|
|
50
31
|
);
|
|
51
32
|
|
|
52
33
|
expect(renderedNames(container)).toEqual(['John', 'Jonathan']);
|
|
@@ -67,11 +48,7 @@ describe('fuzzy global filter', () => {
|
|
|
67
48
|
|
|
68
49
|
test('drops every row when no value matches the term', () => {
|
|
69
50
|
const { container } = render(
|
|
70
|
-
<MaterialReactTable
|
|
71
|
-
columns={columns}
|
|
72
|
-
data={data}
|
|
73
|
-
initialState={{ globalFilter: 'zzz' }}
|
|
74
|
-
/>,
|
|
51
|
+
<MaterialReactTable columns={columns} data={data} initialState={{ globalFilter: 'zzz' }} />,
|
|
75
52
|
);
|
|
76
53
|
|
|
77
54
|
expect(renderedNames(container)).toEqual(['No results found']);
|
|
@@ -94,11 +71,7 @@ const employeeColumns = (): MRT_ColumnDef<Employee>[] => [
|
|
|
94
71
|
{ accessorKey: 'age', header: 'Age' },
|
|
95
72
|
];
|
|
96
73
|
|
|
97
|
-
const renderFiltered = (
|
|
98
|
-
columnId: string,
|
|
99
|
-
filterFn: string,
|
|
100
|
-
value: unknown,
|
|
101
|
-
) => {
|
|
74
|
+
const renderFiltered = (columnId: string, filterFn: string, value: unknown) => {
|
|
102
75
|
const { container } = render(
|
|
103
76
|
<MaterialReactTable
|
|
104
77
|
columns={employeeColumns()}
|
|
@@ -109,9 +82,7 @@ const renderFiltered = (
|
|
|
109
82
|
}}
|
|
110
83
|
/>,
|
|
111
84
|
);
|
|
112
|
-
return Array.from(container.querySelectorAll('tbody tr')).map(
|
|
113
|
-
(row) => row.querySelector('td')?.textContent,
|
|
114
|
-
);
|
|
85
|
+
return Array.from(container.querySelectorAll('tbody tr')).map((row) => row.querySelector('td')?.textContent);
|
|
115
86
|
};
|
|
116
87
|
|
|
117
88
|
describe('column filter fns', () => {
|
|
@@ -135,6 +106,7 @@ describe('column filter fns', () => {
|
|
|
135
106
|
['greaterThanOrEqualTo', 30, ['Alice', 'alice']],
|
|
136
107
|
['lessThan', 30, ['Bob']],
|
|
137
108
|
['lessThanOrEqualTo', 20, ['Bob']],
|
|
109
|
+
['weakEquals', '30', ['Alice']],
|
|
138
110
|
])('%s filters the age column', (filterFn, value, expected) => {
|
|
139
111
|
expect(renderFiltered('age', filterFn, value)).toEqual(expected);
|
|
140
112
|
});
|
package/src/fns/filterFns.ts
CHANGED
|
@@ -8,182 +8,158 @@ import {
|
|
|
8
8
|
filterFn_includesString,
|
|
9
9
|
filterFn_includesStringSensitive,
|
|
10
10
|
filterFn_inNumberRange,
|
|
11
|
+
filterFn_weakEquals,
|
|
11
12
|
type FilterMeta,
|
|
12
13
|
type Row,
|
|
14
|
+
type TableFeatures,
|
|
13
15
|
} from '@tanstack/react-table';
|
|
14
16
|
|
|
15
17
|
import { type MRT_RowData } from '../types';
|
|
16
18
|
|
|
17
|
-
const fuzzy = <TData extends MRT_RowData>(
|
|
18
|
-
row: Row<
|
|
19
|
+
const fuzzy = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
20
|
+
row: Row<TFeatures, TData>,
|
|
19
21
|
columnId: string,
|
|
20
22
|
filterValue: number | string,
|
|
21
23
|
addMeta?: (meta: FilterMeta) => void,
|
|
22
24
|
): boolean => {
|
|
23
|
-
const itemRank = rankItem(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
threshold: rankings.MATCHES,
|
|
28
|
-
},
|
|
29
|
-
);
|
|
25
|
+
const itemRank = rankItem(row.getValue<null | number | string>(columnId), filterValue as string, {
|
|
26
|
+
threshold: rankings.MATCHES,
|
|
27
|
+
});
|
|
30
28
|
addMeta?.(itemRank);
|
|
31
29
|
return itemRank.passed;
|
|
32
30
|
};
|
|
33
31
|
|
|
34
|
-
fuzzy.autoRemove = (val:
|
|
32
|
+
fuzzy.autoRemove = (val: unknown): boolean => !val;
|
|
35
33
|
|
|
36
|
-
const
|
|
37
|
-
|
|
34
|
+
const normalize = (value: number | string): string => value.toString().toLowerCase().trim();
|
|
35
|
+
|
|
36
|
+
const getNormalizedValue = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
37
|
+
row: Row<TFeatures, TData>,
|
|
38
|
+
id: string,
|
|
39
|
+
): string | undefined => {
|
|
40
|
+
const value = row.getValue<null | number | string>(id);
|
|
41
|
+
return value === null || value === undefined ? undefined : normalize(value);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const contains = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
45
|
+
row: Row<TFeatures, TData>,
|
|
38
46
|
id: string,
|
|
39
47
|
filterValue: number | string,
|
|
40
|
-
): boolean =>
|
|
41
|
-
!!row
|
|
42
|
-
.getValue<null | number | string>(id)
|
|
43
|
-
?.toString()
|
|
44
|
-
.toLowerCase()
|
|
45
|
-
.trim()
|
|
46
|
-
.includes(filterValue.toString().toLowerCase().trim());
|
|
48
|
+
): boolean => !!getNormalizedValue(row, id)?.includes(normalize(filterValue));
|
|
47
49
|
|
|
48
|
-
contains.autoRemove = (val:
|
|
50
|
+
contains.autoRemove = (val: unknown): boolean => !val;
|
|
49
51
|
|
|
50
|
-
const startsWith = <TData extends MRT_RowData>(
|
|
51
|
-
row: Row<
|
|
52
|
+
const startsWith = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
53
|
+
row: Row<TFeatures, TData>,
|
|
52
54
|
id: string,
|
|
53
55
|
filterValue: number | string,
|
|
54
|
-
): boolean =>
|
|
55
|
-
!!row
|
|
56
|
-
.getValue<null | number | string>(id)
|
|
57
|
-
?.toString()
|
|
58
|
-
.toLowerCase()
|
|
59
|
-
.trim()
|
|
60
|
-
.startsWith(filterValue.toString().toLowerCase().trim());
|
|
56
|
+
): boolean => !!getNormalizedValue(row, id)?.startsWith(normalize(filterValue));
|
|
61
57
|
|
|
62
|
-
startsWith.autoRemove = (val:
|
|
58
|
+
startsWith.autoRemove = (val: unknown): boolean => !val;
|
|
63
59
|
|
|
64
|
-
const endsWith = <TData extends MRT_RowData>(
|
|
65
|
-
row: Row<
|
|
60
|
+
const endsWith = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
61
|
+
row: Row<TFeatures, TData>,
|
|
66
62
|
id: string,
|
|
67
63
|
filterValue: number | string,
|
|
68
|
-
): boolean =>
|
|
69
|
-
!!row
|
|
70
|
-
.getValue<null | number | string>(id)
|
|
71
|
-
?.toString()
|
|
72
|
-
.toLowerCase()
|
|
73
|
-
.trim()
|
|
74
|
-
.endsWith(filterValue.toString().toLowerCase().trim());
|
|
64
|
+
): boolean => !!getNormalizedValue(row, id)?.endsWith(normalize(filterValue));
|
|
75
65
|
|
|
76
|
-
endsWith.autoRemove = (val:
|
|
66
|
+
endsWith.autoRemove = (val: unknown): boolean => !val;
|
|
77
67
|
|
|
78
|
-
const equals = <TData extends MRT_RowData>(
|
|
79
|
-
row: Row<
|
|
68
|
+
const equals = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
69
|
+
row: Row<TFeatures, TData>,
|
|
80
70
|
id: string,
|
|
81
71
|
filterValue: number | string,
|
|
82
|
-
): boolean =>
|
|
83
|
-
row.getValue<null | number | string>(id)?.toString().toLowerCase().trim() ===
|
|
84
|
-
filterValue.toString().toLowerCase().trim();
|
|
72
|
+
): boolean => getNormalizedValue(row, id) === normalize(filterValue);
|
|
85
73
|
|
|
86
|
-
equals.autoRemove = (val:
|
|
74
|
+
equals.autoRemove = (val: unknown): boolean => !val;
|
|
87
75
|
|
|
88
|
-
const notEquals = <TData extends MRT_RowData>(
|
|
89
|
-
row: Row<
|
|
76
|
+
const notEquals = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
77
|
+
row: Row<TFeatures, TData>,
|
|
90
78
|
id: string,
|
|
91
79
|
filterValue: number | string,
|
|
92
|
-
): boolean =>
|
|
93
|
-
row.getValue<null | number | string>(id)?.toString().toLowerCase().trim() !==
|
|
94
|
-
filterValue.toString().toLowerCase().trim();
|
|
80
|
+
): boolean => getNormalizedValue(row, id) !== normalize(filterValue);
|
|
95
81
|
|
|
96
|
-
notEquals.autoRemove = (val:
|
|
82
|
+
notEquals.autoRemove = (val: unknown): boolean => !val;
|
|
97
83
|
|
|
98
|
-
const greaterThan = <TData extends MRT_RowData>(
|
|
99
|
-
row: Row<
|
|
84
|
+
const greaterThan = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
85
|
+
row: Row<TFeatures, TData>,
|
|
100
86
|
id: string,
|
|
101
87
|
filterValue: number | string,
|
|
102
88
|
): boolean =>
|
|
103
89
|
!isNaN(+filterValue) && !isNaN(+row.getValue<number | string>(id))
|
|
104
90
|
? +(row.getValue<null | number | string>(id) ?? 0) > +filterValue
|
|
105
|
-
: (row
|
|
106
|
-
?.toString()
|
|
107
|
-
.toLowerCase()
|
|
108
|
-
.trim() > filterValue.toString().toLowerCase().trim();
|
|
91
|
+
: (getNormalizedValue(row, id) ?? '') > normalize(filterValue);
|
|
109
92
|
|
|
110
|
-
greaterThan.autoRemove = (val:
|
|
93
|
+
greaterThan.autoRemove = (val: unknown): boolean => !val;
|
|
111
94
|
|
|
112
|
-
const greaterThanOrEqualTo = <TData extends MRT_RowData>(
|
|
113
|
-
row: Row<
|
|
95
|
+
const greaterThanOrEqualTo = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
96
|
+
row: Row<TFeatures, TData>,
|
|
114
97
|
id: string,
|
|
115
98
|
filterValue: number | string,
|
|
116
99
|
): boolean => equals(row, id, filterValue) || greaterThan(row, id, filterValue);
|
|
117
100
|
|
|
118
|
-
greaterThanOrEqualTo.autoRemove = (val:
|
|
101
|
+
greaterThanOrEqualTo.autoRemove = (val: unknown): boolean => !val;
|
|
119
102
|
|
|
120
|
-
const lessThan = <TData extends MRT_RowData>(
|
|
121
|
-
row: Row<
|
|
103
|
+
const lessThan = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
104
|
+
row: Row<TFeatures, TData>,
|
|
122
105
|
id: string,
|
|
123
106
|
filterValue: number | string,
|
|
124
107
|
): boolean =>
|
|
125
108
|
!isNaN(+filterValue) && !isNaN(+row.getValue<number | string>(id))
|
|
126
109
|
? +(row.getValue<null | number | string>(id) ?? 0) < +filterValue
|
|
127
|
-
: (row
|
|
128
|
-
?.toString()
|
|
129
|
-
.toLowerCase()
|
|
130
|
-
.trim() < filterValue.toString().toLowerCase().trim();
|
|
110
|
+
: (getNormalizedValue(row, id) ?? '') < normalize(filterValue);
|
|
131
111
|
|
|
132
|
-
lessThan.autoRemove = (val:
|
|
112
|
+
lessThan.autoRemove = (val: unknown): boolean => !val;
|
|
133
113
|
|
|
134
|
-
const lessThanOrEqualTo = <TData extends MRT_RowData>(
|
|
135
|
-
row: Row<
|
|
114
|
+
const lessThanOrEqualTo = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
115
|
+
row: Row<TFeatures, TData>,
|
|
136
116
|
id: string,
|
|
137
117
|
filterValue: number | string,
|
|
138
118
|
): boolean => equals(row, id, filterValue) || lessThan(row, id, filterValue);
|
|
139
119
|
|
|
140
|
-
lessThanOrEqualTo.autoRemove = (val:
|
|
120
|
+
lessThanOrEqualTo.autoRemove = (val: unknown): boolean => !val;
|
|
141
121
|
|
|
142
|
-
const between = <TData extends MRT_RowData>(
|
|
143
|
-
row: Row<
|
|
122
|
+
const between = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
123
|
+
row: Row<TFeatures, TData>,
|
|
144
124
|
id: string,
|
|
145
125
|
filterValues: [number | string, number | string],
|
|
146
126
|
): boolean =>
|
|
147
|
-
(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
+filterValues[0] > +filterValues[1]) ||
|
|
152
|
-
(['', undefined] as any[]).includes(filterValues[1]) ||
|
|
127
|
+
(filterValues[0] === '' || filterValues[0] === undefined || greaterThan(row, id, filterValues[0])) &&
|
|
128
|
+
((!isNaN(+filterValues[0]) && !isNaN(+filterValues[1]) && +filterValues[0] > +filterValues[1]) ||
|
|
129
|
+
filterValues[1] === '' ||
|
|
130
|
+
filterValues[1] === undefined ||
|
|
153
131
|
lessThan(row, id, filterValues[1]));
|
|
154
132
|
|
|
155
|
-
between.autoRemove = (val:
|
|
133
|
+
between.autoRemove = (val: unknown): boolean => !val;
|
|
156
134
|
|
|
157
|
-
const betweenInclusive = <TData extends MRT_RowData>(
|
|
158
|
-
row: Row<
|
|
135
|
+
const betweenInclusive = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
136
|
+
row: Row<TFeatures, TData>,
|
|
159
137
|
id: string,
|
|
160
138
|
filterValues: [number | string, number | string],
|
|
161
139
|
): boolean =>
|
|
162
|
-
(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
+filterValues[0] > +filterValues[1]) ||
|
|
167
|
-
(['', undefined] as any[]).includes(filterValues[1]) ||
|
|
140
|
+
(filterValues[0] === '' || filterValues[0] === undefined || greaterThanOrEqualTo(row, id, filterValues[0])) &&
|
|
141
|
+
((!isNaN(+filterValues[0]) && !isNaN(+filterValues[1]) && +filterValues[0] > +filterValues[1]) ||
|
|
142
|
+
filterValues[1] === '' ||
|
|
143
|
+
filterValues[1] === undefined ||
|
|
168
144
|
lessThanOrEqualTo(row, id, filterValues[1]));
|
|
169
145
|
|
|
170
|
-
betweenInclusive.autoRemove = (val:
|
|
146
|
+
betweenInclusive.autoRemove = (val: unknown): boolean => !val;
|
|
171
147
|
|
|
172
|
-
const empty = <TData extends MRT_RowData>(
|
|
173
|
-
row: Row<
|
|
148
|
+
const empty = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
149
|
+
row: Row<TFeatures, TData>,
|
|
174
150
|
id: string,
|
|
175
151
|
_filterValue: number | string,
|
|
176
152
|
): boolean => !row.getValue<null | number | string>(id)?.toString().trim();
|
|
177
153
|
|
|
178
|
-
empty.autoRemove = (val:
|
|
154
|
+
empty.autoRemove = (val: unknown): boolean => !val;
|
|
179
155
|
|
|
180
|
-
const notEmpty = <TData extends MRT_RowData>(
|
|
181
|
-
row: Row<
|
|
156
|
+
const notEmpty = <TFeatures extends TableFeatures, TData extends MRT_RowData>(
|
|
157
|
+
row: Row<TFeatures, TData>,
|
|
182
158
|
id: string,
|
|
183
159
|
_filterValue: number | string,
|
|
184
160
|
): boolean => !!row.getValue<null | number | string>(id)?.toString().trim();
|
|
185
161
|
|
|
186
|
-
notEmpty.autoRemove = (val:
|
|
162
|
+
notEmpty.autoRemove = (val: unknown): boolean => !val;
|
|
187
163
|
|
|
188
164
|
export const MRT_FilterFns = {
|
|
189
165
|
arrIncludes: filterFn_arrIncludes,
|
|
@@ -208,4 +184,5 @@ export const MRT_FilterFns = {
|
|
|
208
184
|
notEmpty,
|
|
209
185
|
notEquals,
|
|
210
186
|
startsWith,
|
|
187
|
+
weakEquals: filterFn_weakEquals,
|
|
211
188
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
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 Item {
|
|
8
|
+
code: string;
|
|
9
|
+
count: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const items: Item[] = [
|
|
13
|
+
{ code: 'item10', count: 100 },
|
|
14
|
+
{ code: 'item9', count: 9 },
|
|
15
|
+
{ code: 'item100', count: 10 },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const renderSorted = (columnId: keyof Item, sortFn: string) => {
|
|
19
|
+
const columns: MRT_ColumnDef<Item>[] = [
|
|
20
|
+
{ accessorKey: 'code', header: 'Code' },
|
|
21
|
+
{ accessorKey: 'count', header: 'Count' },
|
|
22
|
+
].map((column) => (column.accessorKey === columnId ? { ...column, sortFn } : column));
|
|
23
|
+
|
|
24
|
+
const { container } = render(
|
|
25
|
+
<MaterialReactTable columns={columns} data={items} initialState={{ sorting: [{ desc: false, id: columnId }] }} />,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return Array.from(container.querySelectorAll('tbody tr')).map((row) => row.querySelector('td')?.textContent);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('sort fns', () => {
|
|
32
|
+
test('alphanumericCaseSensitive sorts the numbers inside the code', () => {
|
|
33
|
+
expect(renderSorted('code', 'alphanumericCaseSensitive')).toEqual(['item9', 'item10', 'item100']);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('textCaseSensitive sorts the count as text', () => {
|
|
37
|
+
expect(renderSorted('count', 'textCaseSensitive')).toEqual(['item100', 'item10', 'item9']);
|
|
38
|
+
});
|
|
39
|
+
});
|