@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.
Files changed (190) hide show
  1. package/README.md +1 -4
  2. package/dist/index.d.ts +189 -524
  3. package/dist/index.js +329 -345
  4. package/dist/index.js.map +1 -1
  5. package/locales/ar/index.mjs +1 -2
  6. package/locales/az/index.mjs +1 -2
  7. package/locales/bg/index.mjs +1 -2
  8. package/locales/cs/index.mjs +1 -2
  9. package/locales/da/index.mjs +1 -2
  10. package/locales/de/index.mjs +1 -2
  11. package/locales/el/index.mjs +1 -2
  12. package/locales/en/index.mjs +1 -2
  13. package/locales/es/index.mjs +1 -2
  14. package/locales/et/index.mjs +1 -2
  15. package/locales/fa/index.mjs +1 -2
  16. package/locales/fi/index.mjs +1 -2
  17. package/locales/fr/index.mjs +1 -2
  18. package/locales/he/index.mjs +1 -2
  19. package/locales/hr/index.mjs +1 -2
  20. package/locales/hu/index.mjs +1 -2
  21. package/locales/hy/index.mjs +1 -2
  22. package/locales/id/index.mjs +1 -2
  23. package/locales/it/index.mjs +1 -2
  24. package/locales/ja/index.mjs +1 -2
  25. package/locales/ko/index.mjs +1 -2
  26. package/locales/nl/index.mjs +1 -2
  27. package/locales/no/index.mjs +1 -2
  28. package/locales/np/index.mjs +1 -2
  29. package/locales/pl/index.mjs +1 -2
  30. package/locales/pt/index.mjs +1 -2
  31. package/locales/pt-BR/index.mjs +1 -2
  32. package/locales/ro/index.mjs +1 -2
  33. package/locales/ru/index.mjs +1 -2
  34. package/locales/sk/index.mjs +1 -2
  35. package/locales/sr-Cyrl-RS/index.mjs +1 -2
  36. package/locales/sr-Latn-RS/index.mjs +1 -2
  37. package/locales/sv/index.mjs +1 -2
  38. package/locales/tr/index.mjs +1 -2
  39. package/locales/uk/index.mjs +1 -2
  40. package/locales/vi/index.mjs +1 -2
  41. package/locales/zh-Hans/index.mjs +1 -2
  42. package/locales/zh-Hant/index.mjs +1 -2
  43. package/package.json +32 -40
  44. package/src/MaterialReactTable.smoke.test.tsx +3 -9
  45. package/src/components/MaterialReactTable.tsx +13 -21
  46. package/src/components/body/MRT_TableBody.tsx +67 -82
  47. package/src/components/body/MRT_TableBodyCell.tsx +38 -80
  48. package/src/components/body/MRT_TableBodyCellValue.tsx +5 -14
  49. package/src/components/body/MRT_TableBodyRow.tsx +55 -102
  50. package/src/components/body/MRT_TableBodyRowGrabHandle.test.tsx +2 -6
  51. package/src/components/body/MRT_TableBodyRowGrabHandle.tsx +4 -9
  52. package/src/components/body/MRT_TableBodyRowPinButton.tsx +8 -14
  53. package/src/components/body/MRT_TableDetailPanel.test.tsx +3 -9
  54. package/src/components/body/MRT_TableDetailPanel.tsx +8 -14
  55. package/src/components/buttons/MRT_ColumnPinningButtons.test.tsx +6 -16
  56. package/src/components/buttons/MRT_ColumnPinningButtons.tsx +6 -12
  57. package/src/components/buttons/MRT_CopyButton.tsx +7 -15
  58. package/src/components/buttons/MRT_EditActionButtons.test.tsx +2 -6
  59. package/src/components/buttons/MRT_EditActionButtons.tsx +15 -37
  60. package/src/components/buttons/MRT_ExpandAllButton.tsx +8 -16
  61. package/src/components/buttons/MRT_ExpandButton.tsx +9 -21
  62. package/src/components/buttons/MRT_GrabHandleButton.tsx +6 -10
  63. package/src/components/buttons/MRT_RowPinButton.tsx +8 -23
  64. package/src/components/buttons/MRT_ShowHideColumnsButton.tsx +5 -18
  65. package/src/components/buttons/MRT_ToggleDensePaddingButton.test.tsx +4 -12
  66. package/src/components/buttons/MRT_ToggleDensePaddingButton.tsx +4 -11
  67. package/src/components/buttons/MRT_ToggleFiltersButton.test.tsx +4 -13
  68. package/src/components/buttons/MRT_ToggleFiltersButton.tsx +3 -5
  69. package/src/components/buttons/MRT_ToggleFullScreenButton.test.tsx +3 -11
  70. package/src/components/buttons/MRT_ToggleFullScreenButton.tsx +4 -9
  71. package/src/components/buttons/MRT_ToggleGlobalFilterButton.tsx +3 -5
  72. package/src/components/buttons/MRT_ToggleRowActionMenuButton.tsx +7 -15
  73. package/src/components/footer/MRT_TableFooter.tsx +9 -16
  74. package/src/components/footer/MRT_TableFooterCell.tsx +9 -32
  75. package/src/components/footer/MRT_TableFooterRow.tsx +18 -32
  76. package/src/components/head/MRT_TableHead.tsx +8 -18
  77. package/src/components/head/MRT_TableHeadCell.tsx +46 -100
  78. package/src/components/head/MRT_TableHeadCellColumnActionsButton.tsx +10 -30
  79. package/src/components/head/MRT_TableHeadCellFilterContainer.tsx +4 -15
  80. package/src/components/head/MRT_TableHeadCellFilterLabel.tsx +20 -54
  81. package/src/components/head/MRT_TableHeadCellGrabHandle.test.tsx +5 -19
  82. package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +9 -38
  83. package/src/components/head/MRT_TableHeadCellResizeHandle.test.tsx +3 -13
  84. package/src/components/head/MRT_TableHeadCellResizeHandle.tsx +10 -24
  85. package/src/components/head/MRT_TableHeadCellSortLabel.tsx +10 -26
  86. package/src/components/head/MRT_TableHeadRow.tsx +24 -36
  87. package/src/components/inputs/MRT_EditCellTextField.test.tsx +2 -9
  88. package/src/components/inputs/MRT_EditCellTextField.tsx +9 -28
  89. package/src/components/inputs/MRT_FilterCheckbox.tsx +9 -23
  90. package/src/components/inputs/MRT_FilterRangeFields.tsx +6 -15
  91. package/src/components/inputs/MRT_FilterRangeSlider.tsx +24 -32
  92. package/src/components/inputs/MRT_FilterTextField.test.tsx +72 -14
  93. package/src/components/inputs/MRT_FilterTextField.tsx +77 -138
  94. package/src/components/inputs/MRT_GlobalFilterTextField.tsx +10 -32
  95. package/src/components/inputs/MRT_SelectCheckbox.test.tsx +4 -11
  96. package/src/components/inputs/MRT_SelectCheckbox.tsx +17 -36
  97. package/src/components/menus/MRT_ActionMenuItem.tsx +6 -15
  98. package/src/components/menus/MRT_CellActionMenu.tsx +6 -9
  99. package/src/components/menus/MRT_ColumnActionMenu.tsx +22 -57
  100. package/src/components/menus/MRT_FilterOptionMenu.tsx +38 -65
  101. package/src/components/menus/MRT_RowActionMenu.tsx +33 -22
  102. package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +29 -65
  103. package/src/components/menus/MRT_ShowHideColumnsMenuItems.test.tsx +43 -0
  104. package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +14 -50
  105. package/src/components/modals/MRT_EditRowModal.test.tsx +5 -21
  106. package/src/components/modals/MRT_EditRowModal.tsx +8 -26
  107. package/src/components/table/MRT_Table.tsx +12 -20
  108. package/src/components/table/MRT_TableContainer.test.tsx +147 -0
  109. package/src/components/table/MRT_TableContainer.tsx +33 -37
  110. package/src/components/table/MRT_TableLoadingOverlay.tsx +3 -5
  111. package/src/components/table/MRT_TablePaper.tsx +7 -14
  112. package/src/components/toolbar/MRT_BottomToolbar.tsx +11 -23
  113. package/src/components/toolbar/MRT_LinearProgressBar.tsx +4 -11
  114. package/src/components/toolbar/MRT_TablePagination.tsx +33 -40
  115. package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +21 -50
  116. package/src/components/toolbar/MRT_ToolbarDropZone.test.tsx +26 -10
  117. package/src/components/toolbar/MRT_ToolbarDropZone.tsx +23 -21
  118. package/src/components/toolbar/MRT_ToolbarInternalButtons.tsx +11 -21
  119. package/src/components/toolbar/MRT_TopToolbar.tsx +12 -28
  120. package/src/fns/aggregationFns.test.tsx +1 -3
  121. package/src/fns/filterFns.test.tsx +9 -37
  122. package/src/fns/filterFns.ts +73 -96
  123. package/src/fns/sortingFns.test.tsx +39 -0
  124. package/src/fns/sortingFns.ts +15 -15
  125. package/src/fns/tableFeatures.test.tsx +6 -29
  126. package/src/fns/tableFeatures.ts +5 -4
  127. package/src/hooks/display-columns/getMRT_RowActionsColumnDef.tsx +2 -11
  128. package/src/hooks/display-columns/getMRT_RowDragColumnDef.tsx +2 -10
  129. package/src/hooks/display-columns/getMRT_RowExpandColumnDef.tsx +8 -17
  130. package/src/hooks/display-columns/getMRT_RowNumbersColumnDef.tsx +3 -8
  131. package/src/hooks/display-columns/getMRT_RowPinningColumnDef.tsx +2 -8
  132. package/src/hooks/display-columns/getMRT_RowSelectColumnDef.tsx +3 -13
  133. package/src/hooks/display-columns/getMRT_RowSpacerColumnDef.tsx +1 -5
  134. package/src/hooks/useMRT_ColumnVirtualizer.ts +28 -49
  135. package/src/hooks/useMRT_Effects.test.tsx +114 -0
  136. package/src/hooks/useMRT_Effects.ts +26 -27
  137. package/src/hooks/useMRT_RowVirtualizer.ts +18 -33
  138. package/src/hooks/useMRT_Rows.ts +3 -42
  139. package/src/hooks/useMRT_TableInstance.ts +63 -129
  140. package/src/hooks/useMRT_TableOptions.ts +15 -29
  141. package/src/hooks/useMaterialReactTable.ts +2 -7
  142. package/src/icons.ts +38 -1
  143. package/src/index.ts +0 -4
  144. package/src/locales/ar.ts +1 -2
  145. package/src/locales/az.ts +1 -2
  146. package/src/locales/bg.ts +1 -2
  147. package/src/locales/cs.ts +2 -4
  148. package/src/locales/da.ts +1 -2
  149. package/src/locales/de.ts +1 -2
  150. package/src/locales/el.ts +1 -2
  151. package/src/locales/en.ts +1 -2
  152. package/src/locales/es.ts +1 -2
  153. package/src/locales/et.ts +2 -4
  154. package/src/locales/fa.ts +1 -2
  155. package/src/locales/fi.ts +2 -4
  156. package/src/locales/fr.ts +1 -2
  157. package/src/locales/he.ts +1 -2
  158. package/src/locales/hr.ts +1 -2
  159. package/src/locales/hu.ts +1 -2
  160. package/src/locales/hy.ts +1 -2
  161. package/src/locales/id.ts +2 -4
  162. package/src/locales/it.ts +1 -2
  163. package/src/locales/ja.ts +1 -2
  164. package/src/locales/ko.ts +1 -2
  165. package/src/locales/nl.ts +1 -2
  166. package/src/locales/no.ts +2 -4
  167. package/src/locales/np.ts +2 -4
  168. package/src/locales/pl.ts +1 -2
  169. package/src/locales/pt-BR.ts +1 -2
  170. package/src/locales/pt.ts +1 -2
  171. package/src/locales/ro.ts +1 -2
  172. package/src/locales/ru.ts +1 -2
  173. package/src/locales/sk.ts +2 -4
  174. package/src/locales/sr-Cyrl-RS.ts +1 -2
  175. package/src/locales/sr-Latn-RS.ts +1 -2
  176. package/src/locales/sv.ts +1 -2
  177. package/src/locales/tr.ts +1 -2
  178. package/src/locales/uk.ts +1 -2
  179. package/src/locales/vi.ts +1 -2
  180. package/src/types.ts +156 -349
  181. package/src/utils/cell.utils.ts +30 -68
  182. package/src/utils/column.utils.ts +61 -49
  183. package/src/utils/displayColumn.utils.ts +16 -38
  184. package/src/utils/highlight.utils.ts +7 -11
  185. package/src/utils/row.utils.ts +40 -65
  186. package/src/utils/slotProps.utils.ts +1 -4
  187. package/src/utils/style.utils.ts +18 -46
  188. package/src/utils/tanstack.helpers.ts +10 -17
  189. package/src/utils/utils.ts +6 -10
  190. package/src/utils/virtualization.utils.ts +5 -9
@@ -1,29 +1,25 @@
1
- import { Box, type BoxProps } from '@mui/material';
2
- import { Fade } from '@mui/material';
3
- import { Typography } from '@mui/material';
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 (table.options.state?.showToolbarDropZone !== undefined) {
38
- setShowToolbarDropZone(
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, draggingColumn, grouping]);
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 any),
69
+ ...(parseFromValuesOrFunc(rest?.sx, theme) as CSSObject),
67
70
  })}
68
71
  >
69
- <Typography sx={{
70
- fontStyle: "italic"
71
- }}>
72
- {localization.dropToGroupBy.replace(
73
- '{column}',
74
- draggingColumn?.columnDef?.header ?? '',
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 any),
43
+ ...(parseFromValuesOrFunc(rest?.sx, theme) as CSSObject),
44
44
  })}
45
45
  >
46
46
  {renderToolbarInternalActions?.({
47
47
  table,
48
48
  }) ?? (
49
49
  <>
50
- {enableFilters &&
51
- enableGlobalFilter &&
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
- {enableDensityToggle && (
64
- <MRT_ToggleDensePaddingButton table={table} />
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 any),
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
- ['both', 'top'].includes(positionPagination ?? '') && (
124
- <MRT_TablePagination position="top" table={table} />
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
  });
@@ -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<any, TData>,
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
- row.getValue<null | number | string>(columnId),
25
- filterValue as string,
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: any) => !val;
32
+ fuzzy.autoRemove = (val: unknown): boolean => !val;
35
33
 
36
- const contains = <TData extends MRT_RowData>(
37
- row: Row<any, TData>,
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: any) => !val;
50
+ contains.autoRemove = (val: unknown): boolean => !val;
49
51
 
50
- const startsWith = <TData extends MRT_RowData>(
51
- row: Row<any, TData>,
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: any) => !val;
58
+ startsWith.autoRemove = (val: unknown): boolean => !val;
63
59
 
64
- const endsWith = <TData extends MRT_RowData>(
65
- row: Row<any, TData>,
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: any) => !val;
66
+ endsWith.autoRemove = (val: unknown): boolean => !val;
77
67
 
78
- const equals = <TData extends MRT_RowData>(
79
- row: Row<any, TData>,
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: any) => !val;
74
+ equals.autoRemove = (val: unknown): boolean => !val;
87
75
 
88
- const notEquals = <TData extends MRT_RowData>(
89
- row: Row<any, TData>,
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: any) => !val;
82
+ notEquals.autoRemove = (val: unknown): boolean => !val;
97
83
 
98
- const greaterThan = <TData extends MRT_RowData>(
99
- row: Row<any, TData>,
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.getValue<null | number | string>(id) ?? '')
106
- ?.toString()
107
- .toLowerCase()
108
- .trim() > filterValue.toString().toLowerCase().trim();
91
+ : (getNormalizedValue(row, id) ?? '') > normalize(filterValue);
109
92
 
110
- greaterThan.autoRemove = (val: any) => !val;
93
+ greaterThan.autoRemove = (val: unknown): boolean => !val;
111
94
 
112
- const greaterThanOrEqualTo = <TData extends MRT_RowData>(
113
- row: Row<any, TData>,
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: any) => !val;
101
+ greaterThanOrEqualTo.autoRemove = (val: unknown): boolean => !val;
119
102
 
120
- const lessThan = <TData extends MRT_RowData>(
121
- row: Row<any, TData>,
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.getValue<null | number | string>(id) ?? '')
128
- ?.toString()
129
- .toLowerCase()
130
- .trim() < filterValue.toString().toLowerCase().trim();
110
+ : (getNormalizedValue(row, id) ?? '') < normalize(filterValue);
131
111
 
132
- lessThan.autoRemove = (val: any) => !val;
112
+ lessThan.autoRemove = (val: unknown): boolean => !val;
133
113
 
134
- const lessThanOrEqualTo = <TData extends MRT_RowData>(
135
- row: Row<any, TData>,
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: any) => !val;
120
+ lessThanOrEqualTo.autoRemove = (val: unknown): boolean => !val;
141
121
 
142
- const between = <TData extends MRT_RowData>(
143
- row: Row<any, TData>,
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
- ((['', undefined] as any[]).includes(filterValues[0]) ||
148
- greaterThan(row, id, filterValues[0])) &&
149
- ((!isNaN(+filterValues[0]) &&
150
- !isNaN(+filterValues[1]) &&
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: any) => !val;
133
+ between.autoRemove = (val: unknown): boolean => !val;
156
134
 
157
- const betweenInclusive = <TData extends MRT_RowData>(
158
- row: Row<any, TData>,
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
- ((['', undefined] as any[]).includes(filterValues[0]) ||
163
- greaterThanOrEqualTo(row, id, filterValues[0])) &&
164
- ((!isNaN(+filterValues[0]) &&
165
- !isNaN(+filterValues[1]) &&
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: any) => !val;
146
+ betweenInclusive.autoRemove = (val: unknown): boolean => !val;
171
147
 
172
- const empty = <TData extends MRT_RowData>(
173
- row: Row<any, TData>,
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: any) => !val;
154
+ empty.autoRemove = (val: unknown): boolean => !val;
179
155
 
180
- const notEmpty = <TData extends MRT_RowData>(
181
- row: Row<any, TData>,
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: any) => !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
+ });