@cutting/material-react-table 4.0.5 → 5.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/dist/index.d.ts +1825 -1737
  2. package/dist/index.js +5332 -4317
  3. package/dist/index.js.map +1 -1
  4. package/locales/ar/index.mjs +97 -0
  5. package/locales/ar/package.json +3 -3
  6. package/locales/az/index.mjs +97 -0
  7. package/locales/az/package.json +3 -3
  8. package/locales/bg/index.mjs +97 -0
  9. package/locales/bg/package.json +3 -3
  10. package/locales/cs/index.mjs +97 -0
  11. package/locales/cs/package.json +3 -3
  12. package/locales/da/index.mjs +97 -0
  13. package/locales/da/package.json +3 -3
  14. package/locales/de/index.mjs +97 -0
  15. package/locales/de/package.json +3 -3
  16. package/locales/el/index.mjs +97 -0
  17. package/locales/el/package.json +3 -3
  18. package/locales/en/index.mjs +97 -0
  19. package/locales/en/package.json +3 -3
  20. package/locales/es/index.mjs +97 -0
  21. package/locales/es/package.json +3 -3
  22. package/locales/et/index.mjs +97 -0
  23. package/locales/et/package.json +3 -3
  24. package/locales/fa/index.mjs +97 -0
  25. package/locales/fa/package.json +3 -3
  26. package/locales/fi/index.mjs +97 -0
  27. package/locales/fi/package.json +3 -3
  28. package/locales/fr/index.mjs +97 -0
  29. package/locales/fr/package.json +3 -3
  30. package/locales/he/index.mjs +97 -0
  31. package/locales/he/package.json +3 -3
  32. package/locales/hr/index.mjs +97 -0
  33. package/locales/hr/package.json +3 -3
  34. package/locales/hu/index.mjs +97 -0
  35. package/locales/hu/package.json +3 -3
  36. package/locales/hy/index.mjs +97 -0
  37. package/locales/hy/package.json +3 -3
  38. package/locales/id/index.mjs +97 -0
  39. package/locales/id/package.json +3 -3
  40. package/locales/it/index.mjs +97 -0
  41. package/locales/it/package.json +3 -3
  42. package/locales/ja/index.mjs +97 -0
  43. package/locales/ja/package.json +3 -3
  44. package/locales/ko/index.mjs +97 -0
  45. package/locales/ko/package.json +3 -3
  46. package/locales/nl/index.mjs +97 -0
  47. package/locales/nl/package.json +3 -3
  48. package/locales/no/index.mjs +97 -0
  49. package/locales/no/package.json +3 -3
  50. package/locales/np/index.mjs +97 -0
  51. package/locales/np/package.json +3 -3
  52. package/locales/pl/index.mjs +97 -0
  53. package/locales/pl/package.json +3 -3
  54. package/locales/pt/index.mjs +97 -0
  55. package/locales/pt/package.json +3 -3
  56. package/locales/pt-BR/index.mjs +97 -0
  57. package/locales/pt-BR/package.json +3 -3
  58. package/locales/ro/index.mjs +97 -0
  59. package/locales/ro/package.json +3 -3
  60. package/locales/ru/index.mjs +97 -0
  61. package/locales/ru/package.json +3 -3
  62. package/locales/sk/index.mjs +97 -0
  63. package/locales/sk/package.json +3 -3
  64. package/locales/sr-Cyrl-RS/index.mjs +97 -0
  65. package/locales/sr-Cyrl-RS/package.json +3 -3
  66. package/locales/sr-Latn-RS/index.mjs +97 -0
  67. package/locales/sr-Latn-RS/package.json +3 -3
  68. package/locales/sv/index.mjs +97 -0
  69. package/locales/sv/package.json +3 -3
  70. package/locales/tr/index.mjs +97 -0
  71. package/locales/tr/package.json +3 -3
  72. package/locales/uk/index.mjs +97 -0
  73. package/locales/uk/package.json +3 -3
  74. package/locales/vi/index.mjs +97 -0
  75. package/locales/vi/package.json +3 -3
  76. package/locales/zh-Hans/index.mjs +97 -0
  77. package/locales/zh-Hans/package.json +3 -3
  78. package/locales/zh-Hant/index.mjs +97 -0
  79. package/locales/zh-Hant/package.json +3 -3
  80. package/package.json +57 -53
  81. package/src/components/body/MRT_TableBody.tsx +1 -2
  82. package/src/components/body/MRT_TableBodyCell.tsx +4 -5
  83. package/src/components/body/MRT_TableBodyCellValue.tsx +1 -2
  84. package/src/components/body/MRT_TableBodyRow.tsx +1 -2
  85. package/src/components/body/MRT_TableBodyRowGrabHandle.test.tsx +42 -0
  86. package/src/components/body/MRT_TableBodyRowPinButton.tsx +1 -2
  87. package/src/components/body/MRT_TableDetailPanel.test.tsx +40 -0
  88. package/src/components/body/MRT_TableDetailPanel.tsx +1 -2
  89. package/src/components/buttons/MRT_ColumnPinningButtons.test.tsx +69 -0
  90. package/src/components/buttons/MRT_ColumnPinningButtons.tsx +3 -3
  91. package/src/components/buttons/MRT_EditActionButtons.test.tsx +50 -0
  92. package/src/components/buttons/MRT_EditActionButtons.tsx +1 -3
  93. package/src/components/buttons/MRT_ExpandAllButton.tsx +1 -2
  94. package/src/components/buttons/MRT_ExpandButton.tsx +1 -2
  95. package/src/components/buttons/MRT_ToggleDensePaddingButton.test.tsx +38 -0
  96. package/src/components/buttons/MRT_ToggleDensePaddingButton.tsx +1 -2
  97. package/src/components/buttons/MRT_ToggleFiltersButton.test.tsx +38 -0
  98. package/src/components/buttons/MRT_ToggleFiltersButton.tsx +1 -2
  99. package/src/components/buttons/MRT_ToggleFullScreenButton.test.tsx +36 -0
  100. package/src/components/buttons/MRT_ToggleFullScreenButton.tsx +1 -2
  101. package/src/components/buttons/MRT_ToggleGlobalFilterButton.tsx +1 -2
  102. package/src/components/buttons/MRT_ToggleRowActionMenuButton.tsx +2 -3
  103. package/src/components/footer/MRT_TableFooter.tsx +1 -2
  104. package/src/components/footer/MRT_TableFooterCell.tsx +1 -2
  105. package/src/components/head/MRT_TableHead.tsx +1 -2
  106. package/src/components/head/MRT_TableHeadCell.tsx +9 -9
  107. package/src/components/head/MRT_TableHeadCellFilterContainer.tsx +1 -2
  108. package/src/components/head/MRT_TableHeadCellGrabHandle.test.tsx +61 -0
  109. package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +4 -5
  110. package/src/components/head/MRT_TableHeadCellResizeHandle.test.tsx +45 -0
  111. package/src/components/head/MRT_TableHeadCellResizeHandle.tsx +4 -5
  112. package/src/components/head/MRT_TableHeadCellSortLabel.tsx +1 -2
  113. package/src/components/inputs/MRT_EditCellTextField.test.tsx +36 -0
  114. package/src/components/inputs/MRT_EditCellTextField.tsx +1 -3
  115. package/src/components/inputs/MRT_FilterCheckbox.tsx +1 -2
  116. package/src/components/inputs/MRT_FilterRangeSlider.tsx +2 -1
  117. package/src/components/inputs/MRT_FilterTextField.test.tsx +75 -0
  118. package/src/components/inputs/MRT_GlobalFilterTextField.tsx +1 -2
  119. package/src/components/inputs/MRT_SelectCheckbox.test.tsx +69 -0
  120. package/src/components/inputs/MRT_SelectCheckbox.tsx +1 -2
  121. package/src/components/menus/MRT_CellActionMenu.tsx +1 -2
  122. package/src/components/menus/MRT_ColumnActionMenu.tsx +12 -13
  123. package/src/components/menus/MRT_FilterOptionMenu.tsx +1 -2
  124. package/src/components/menus/MRT_RowActionMenu.tsx +1 -2
  125. package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +1 -2
  126. package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +4 -5
  127. package/src/components/modals/MRT_EditRowModal.test.tsx +54 -0
  128. package/src/components/modals/MRT_EditRowModal.tsx +1 -2
  129. package/src/components/table/MRT_Table.tsx +4 -5
  130. package/src/components/table/MRT_TableContainer.tsx +1 -2
  131. package/src/components/table/MRT_TablePaper.tsx +1 -2
  132. package/src/components/toolbar/MRT_BottomToolbar.tsx +2 -3
  133. package/src/components/toolbar/MRT_LinearProgressBar.tsx +1 -2
  134. package/src/components/toolbar/MRT_TablePagination.tsx +1 -2
  135. package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +3 -4
  136. package/src/components/toolbar/MRT_ToolbarDropZone.test.tsx +42 -0
  137. package/src/components/toolbar/MRT_ToolbarDropZone.tsx +1 -2
  138. package/src/components/toolbar/MRT_TopToolbar.tsx +1 -2
  139. package/src/fns/aggregationFns.test.tsx +57 -0
  140. package/src/fns/filterFns.test.tsx +156 -0
  141. package/src/fns/filterFns.ts +36 -22
  142. package/src/fns/sortingFns.ts +14 -5
  143. package/src/fns/tableFeatures.test.tsx +106 -0
  144. package/src/fns/tableFeatures.ts +103 -0
  145. package/src/hooks/display-columns/getMRT_RowExpandColumnDef.tsx +2 -2
  146. package/src/hooks/useMRT_ColumnVirtualizer.ts +6 -5
  147. package/src/hooks/useMRT_Effects.ts +3 -4
  148. package/src/hooks/useMRT_RowVirtualizer.ts +1 -2
  149. package/src/hooks/useMRT_Rows.ts +1 -2
  150. package/src/hooks/useMRT_TableInstance.ts +82 -63
  151. package/src/hooks/useMRT_TableOptions.ts +5 -37
  152. package/src/icons.ts +1 -1
  153. package/src/types.ts +162 -134
  154. package/src/utils/column.utils.ts +31 -24
  155. package/src/utils/row.utils.ts +7 -10
  156. package/src/utils/style.utils.ts +9 -10
  157. package/src/utils/tanstack.helpers.ts +2 -2
  158. package/dist/index.esm.js +0 -4384
  159. package/dist/index.esm.js.map +0 -1
  160. package/locales/ar/index.esm.d.ts +0 -3
  161. package/locales/ar/index.esm.js +0 -96
  162. package/locales/ar/index.js +0 -98
  163. package/locales/az/index.esm.d.ts +0 -3
  164. package/locales/az/index.esm.js +0 -96
  165. package/locales/az/index.js +0 -98
  166. package/locales/bg/index.esm.d.ts +0 -3
  167. package/locales/bg/index.esm.js +0 -96
  168. package/locales/bg/index.js +0 -98
  169. package/locales/cs/index.esm.d.ts +0 -3
  170. package/locales/cs/index.esm.js +0 -96
  171. package/locales/cs/index.js +0 -98
  172. package/locales/da/index.esm.d.ts +0 -3
  173. package/locales/da/index.esm.js +0 -96
  174. package/locales/da/index.js +0 -98
  175. package/locales/de/index.esm.d.ts +0 -3
  176. package/locales/de/index.esm.js +0 -96
  177. package/locales/de/index.js +0 -98
  178. package/locales/el/index.esm.d.ts +0 -3
  179. package/locales/el/index.esm.js +0 -96
  180. package/locales/el/index.js +0 -98
  181. package/locales/en/index.esm.d.ts +0 -3
  182. package/locales/en/index.esm.js +0 -96
  183. package/locales/en/index.js +0 -98
  184. package/locales/es/index.esm.d.ts +0 -3
  185. package/locales/es/index.esm.js +0 -96
  186. package/locales/es/index.js +0 -98
  187. package/locales/et/index.esm.d.ts +0 -3
  188. package/locales/et/index.esm.js +0 -96
  189. package/locales/et/index.js +0 -98
  190. package/locales/fa/index.esm.d.ts +0 -3
  191. package/locales/fa/index.esm.js +0 -96
  192. package/locales/fa/index.js +0 -98
  193. package/locales/fi/index.esm.d.ts +0 -3
  194. package/locales/fi/index.esm.js +0 -96
  195. package/locales/fi/index.js +0 -98
  196. package/locales/fr/index.esm.d.ts +0 -3
  197. package/locales/fr/index.esm.js +0 -96
  198. package/locales/fr/index.js +0 -98
  199. package/locales/he/index.esm.d.ts +0 -3
  200. package/locales/he/index.esm.js +0 -96
  201. package/locales/he/index.js +0 -98
  202. package/locales/hr/index.esm.d.ts +0 -3
  203. package/locales/hr/index.esm.js +0 -96
  204. package/locales/hr/index.js +0 -98
  205. package/locales/hu/index.esm.d.ts +0 -3
  206. package/locales/hu/index.esm.js +0 -96
  207. package/locales/hu/index.js +0 -98
  208. package/locales/hy/index.esm.d.ts +0 -3
  209. package/locales/hy/index.esm.js +0 -96
  210. package/locales/hy/index.js +0 -98
  211. package/locales/id/index.esm.d.ts +0 -3
  212. package/locales/id/index.esm.js +0 -96
  213. package/locales/id/index.js +0 -98
  214. package/locales/it/index.esm.d.ts +0 -3
  215. package/locales/it/index.esm.js +0 -96
  216. package/locales/it/index.js +0 -98
  217. package/locales/ja/index.esm.d.ts +0 -3
  218. package/locales/ja/index.esm.js +0 -96
  219. package/locales/ja/index.js +0 -98
  220. package/locales/ko/index.esm.d.ts +0 -3
  221. package/locales/ko/index.esm.js +0 -96
  222. package/locales/ko/index.js +0 -98
  223. package/locales/nl/index.esm.d.ts +0 -3
  224. package/locales/nl/index.esm.js +0 -96
  225. package/locales/nl/index.js +0 -98
  226. package/locales/no/index.esm.d.ts +0 -3
  227. package/locales/no/index.esm.js +0 -96
  228. package/locales/no/index.js +0 -98
  229. package/locales/np/index.esm.d.ts +0 -3
  230. package/locales/np/index.esm.js +0 -96
  231. package/locales/np/index.js +0 -98
  232. package/locales/pl/index.esm.d.ts +0 -3
  233. package/locales/pl/index.esm.js +0 -96
  234. package/locales/pl/index.js +0 -98
  235. package/locales/pt/index.esm.d.ts +0 -3
  236. package/locales/pt/index.esm.js +0 -96
  237. package/locales/pt/index.js +0 -98
  238. package/locales/pt-BR/index.esm.d.ts +0 -3
  239. package/locales/pt-BR/index.esm.js +0 -96
  240. package/locales/pt-BR/index.js +0 -98
  241. package/locales/ro/index.esm.d.ts +0 -3
  242. package/locales/ro/index.esm.js +0 -96
  243. package/locales/ro/index.js +0 -98
  244. package/locales/ru/index.esm.d.ts +0 -3
  245. package/locales/ru/index.esm.js +0 -96
  246. package/locales/ru/index.js +0 -98
  247. package/locales/sk/index.esm.d.ts +0 -3
  248. package/locales/sk/index.esm.js +0 -96
  249. package/locales/sk/index.js +0 -98
  250. package/locales/sr-Cyrl-RS/index.esm.d.ts +0 -3
  251. package/locales/sr-Cyrl-RS/index.esm.js +0 -96
  252. package/locales/sr-Cyrl-RS/index.js +0 -98
  253. package/locales/sr-Latn-RS/index.esm.d.ts +0 -3
  254. package/locales/sr-Latn-RS/index.esm.js +0 -96
  255. package/locales/sr-Latn-RS/index.js +0 -98
  256. package/locales/sv/index.esm.d.ts +0 -3
  257. package/locales/sv/index.esm.js +0 -96
  258. package/locales/sv/index.js +0 -98
  259. package/locales/tr/index.esm.d.ts +0 -3
  260. package/locales/tr/index.esm.js +0 -96
  261. package/locales/tr/index.js +0 -98
  262. package/locales/uk/index.esm.d.ts +0 -3
  263. package/locales/uk/index.esm.js +0 -96
  264. package/locales/uk/index.js +0 -98
  265. package/locales/vi/index.esm.d.ts +0 -3
  266. package/locales/vi/index.esm.js +0 -96
  267. package/locales/vi/index.js +0 -98
  268. package/locales/zh-Hans/index.esm.d.ts +0 -3
  269. package/locales/zh-Hans/index.esm.js +0 -96
  270. package/locales/zh-Hans/index.js +0 -98
  271. package/locales/zh-Hant/index.esm.d.ts +0 -3
  272. package/locales/zh-Hant/index.esm.js +0 -96
  273. package/locales/zh-Hant/index.js +0 -98
  274. /package/locales/ar/{index.d.ts → index.d.mts} +0 -0
  275. /package/locales/az/{index.d.ts → index.d.mts} +0 -0
  276. /package/locales/bg/{index.d.ts → index.d.mts} +0 -0
  277. /package/locales/cs/{index.d.ts → index.d.mts} +0 -0
  278. /package/locales/da/{index.d.ts → index.d.mts} +0 -0
  279. /package/locales/de/{index.d.ts → index.d.mts} +0 -0
  280. /package/locales/el/{index.d.ts → index.d.mts} +0 -0
  281. /package/locales/en/{index.d.ts → index.d.mts} +0 -0
  282. /package/locales/es/{index.d.ts → index.d.mts} +0 -0
  283. /package/locales/et/{index.d.ts → index.d.mts} +0 -0
  284. /package/locales/fa/{index.d.ts → index.d.mts} +0 -0
  285. /package/locales/fi/{index.d.ts → index.d.mts} +0 -0
  286. /package/locales/fr/{index.d.ts → index.d.mts} +0 -0
  287. /package/locales/he/{index.d.ts → index.d.mts} +0 -0
  288. /package/locales/hr/{index.d.ts → index.d.mts} +0 -0
  289. /package/locales/hu/{index.d.ts → index.d.mts} +0 -0
  290. /package/locales/hy/{index.d.ts → index.d.mts} +0 -0
  291. /package/locales/id/{index.d.ts → index.d.mts} +0 -0
  292. /package/locales/it/{index.d.ts → index.d.mts} +0 -0
  293. /package/locales/ja/{index.d.ts → index.d.mts} +0 -0
  294. /package/locales/ko/{index.d.ts → index.d.mts} +0 -0
  295. /package/locales/nl/{index.d.ts → index.d.mts} +0 -0
  296. /package/locales/no/{index.d.ts → index.d.mts} +0 -0
  297. /package/locales/np/{index.d.ts → index.d.mts} +0 -0
  298. /package/locales/pl/{index.d.ts → index.d.mts} +0 -0
  299. /package/locales/pt/{index.d.ts → index.d.mts} +0 -0
  300. /package/locales/pt-BR/{index.d.ts → index.d.mts} +0 -0
  301. /package/locales/ro/{index.d.ts → index.d.mts} +0 -0
  302. /package/locales/ru/{index.d.ts → index.d.mts} +0 -0
  303. /package/locales/sk/{index.d.ts → index.d.mts} +0 -0
  304. /package/locales/sr-Cyrl-RS/{index.d.ts → index.d.mts} +0 -0
  305. /package/locales/sr-Latn-RS/{index.d.ts → index.d.mts} +0 -0
  306. /package/locales/sv/{index.d.ts → index.d.mts} +0 -0
  307. /package/locales/tr/{index.d.ts → index.d.mts} +0 -0
  308. /package/locales/uk/{index.d.ts → index.d.mts} +0 -0
  309. /package/locales/vi/{index.d.ts → index.d.mts} +0 -0
  310. /package/locales/zh-Hans/{index.d.ts → index.d.mts} +0 -0
  311. /package/locales/zh-Hant/{index.d.ts → index.d.mts} +0 -0
@@ -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 } = getState();
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).columnDef.header}
104
- onDelete={() => table.getColumn(columnId).toggleGrouping()}
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
- getState();
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 } = getState();
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
+ });
@@ -1,17 +1,24 @@
1
+ import { rankings, rankItem } from '@tanstack/match-sorter-utils';
1
2
  import {
2
- type RankingInfo,
3
- rankings,
4
- rankItem,
5
- } from '@tanstack/match-sorter-utils';
6
- import { filterFns, type Row } from '@tanstack/react-table';
3
+ filterFn_arrIncludes,
4
+ filterFn_arrIncludesAll,
5
+ filterFn_arrIncludesSome,
6
+ filterFn_equalsString,
7
+ filterFn_equalsStringSensitive,
8
+ filterFn_includesString,
9
+ filterFn_includesStringSensitive,
10
+ filterFn_inNumberRange,
11
+ type FilterMeta,
12
+ type Row,
13
+ } from '@tanstack/react-table';
7
14
 
8
15
  import { type MRT_RowData } from '../types';
9
16
 
10
17
  const fuzzy = <TData extends MRT_RowData>(
11
- row: Row<TData>,
18
+ row: Row<any, TData>,
12
19
  columnId: string,
13
20
  filterValue: number | string,
14
- addMeta: (item: RankingInfo) => void,
21
+ addMeta?: (meta: FilterMeta) => void,
15
22
  ): boolean => {
16
23
  const itemRank = rankItem(
17
24
  row.getValue<null | number | string>(columnId),
@@ -20,14 +27,14 @@ const fuzzy = <TData extends MRT_RowData>(
20
27
  threshold: rankings.MATCHES,
21
28
  },
22
29
  );
23
- addMeta(itemRank);
30
+ addMeta?.(itemRank);
24
31
  return itemRank.passed;
25
32
  };
26
33
 
27
34
  fuzzy.autoRemove = (val: any) => !val;
28
35
 
29
36
  const contains = <TData extends MRT_RowData>(
30
- row: Row<TData>,
37
+ row: Row<any, TData>,
31
38
  id: string,
32
39
  filterValue: number | string,
33
40
  ): boolean =>
@@ -41,7 +48,7 @@ const contains = <TData extends MRT_RowData>(
41
48
  contains.autoRemove = (val: any) => !val;
42
49
 
43
50
  const startsWith = <TData extends MRT_RowData>(
44
- row: Row<TData>,
51
+ row: Row<any, TData>,
45
52
  id: string,
46
53
  filterValue: number | string,
47
54
  ): boolean =>
@@ -55,7 +62,7 @@ const startsWith = <TData extends MRT_RowData>(
55
62
  startsWith.autoRemove = (val: any) => !val;
56
63
 
57
64
  const endsWith = <TData extends MRT_RowData>(
58
- row: Row<TData>,
65
+ row: Row<any, TData>,
59
66
  id: string,
60
67
  filterValue: number | string,
61
68
  ): boolean =>
@@ -69,7 +76,7 @@ const endsWith = <TData extends MRT_RowData>(
69
76
  endsWith.autoRemove = (val: any) => !val;
70
77
 
71
78
  const equals = <TData extends MRT_RowData>(
72
- row: Row<TData>,
79
+ row: Row<any, TData>,
73
80
  id: string,
74
81
  filterValue: number | string,
75
82
  ): boolean =>
@@ -79,7 +86,7 @@ const equals = <TData extends MRT_RowData>(
79
86
  equals.autoRemove = (val: any) => !val;
80
87
 
81
88
  const notEquals = <TData extends MRT_RowData>(
82
- row: Row<TData>,
89
+ row: Row<any, TData>,
83
90
  id: string,
84
91
  filterValue: number | string,
85
92
  ): boolean =>
@@ -89,7 +96,7 @@ const notEquals = <TData extends MRT_RowData>(
89
96
  notEquals.autoRemove = (val: any) => !val;
90
97
 
91
98
  const greaterThan = <TData extends MRT_RowData>(
92
- row: Row<TData>,
99
+ row: Row<any, TData>,
93
100
  id: string,
94
101
  filterValue: number | string,
95
102
  ): boolean =>
@@ -103,7 +110,7 @@ const greaterThan = <TData extends MRT_RowData>(
103
110
  greaterThan.autoRemove = (val: any) => !val;
104
111
 
105
112
  const greaterThanOrEqualTo = <TData extends MRT_RowData>(
106
- row: Row<TData>,
113
+ row: Row<any, TData>,
107
114
  id: string,
108
115
  filterValue: number | string,
109
116
  ): boolean => equals(row, id, filterValue) || greaterThan(row, id, filterValue);
@@ -111,7 +118,7 @@ const greaterThanOrEqualTo = <TData extends MRT_RowData>(
111
118
  greaterThanOrEqualTo.autoRemove = (val: any) => !val;
112
119
 
113
120
  const lessThan = <TData extends MRT_RowData>(
114
- row: Row<TData>,
121
+ row: Row<any, TData>,
115
122
  id: string,
116
123
  filterValue: number | string,
117
124
  ): boolean =>
@@ -125,7 +132,7 @@ const lessThan = <TData extends MRT_RowData>(
125
132
  lessThan.autoRemove = (val: any) => !val;
126
133
 
127
134
  const lessThanOrEqualTo = <TData extends MRT_RowData>(
128
- row: Row<TData>,
135
+ row: Row<any, TData>,
129
136
  id: string,
130
137
  filterValue: number | string,
131
138
  ): boolean => equals(row, id, filterValue) || lessThan(row, id, filterValue);
@@ -133,7 +140,7 @@ const lessThanOrEqualTo = <TData extends MRT_RowData>(
133
140
  lessThanOrEqualTo.autoRemove = (val: any) => !val;
134
141
 
135
142
  const between = <TData extends MRT_RowData>(
136
- row: Row<TData>,
143
+ row: Row<any, TData>,
137
144
  id: string,
138
145
  filterValues: [number | string, number | string],
139
146
  ): boolean =>
@@ -148,7 +155,7 @@ const between = <TData extends MRT_RowData>(
148
155
  between.autoRemove = (val: any) => !val;
149
156
 
150
157
  const betweenInclusive = <TData extends MRT_RowData>(
151
- row: Row<TData>,
158
+ row: Row<any, TData>,
152
159
  id: string,
153
160
  filterValues: [number | string, number | string],
154
161
  ): boolean =>
@@ -163,7 +170,7 @@ const betweenInclusive = <TData extends MRT_RowData>(
163
170
  betweenInclusive.autoRemove = (val: any) => !val;
164
171
 
165
172
  const empty = <TData extends MRT_RowData>(
166
- row: Row<TData>,
173
+ row: Row<any, TData>,
167
174
  id: string,
168
175
  _filterValue: number | string,
169
176
  ): boolean => !row.getValue<null | number | string>(id)?.toString().trim();
@@ -171,7 +178,7 @@ const empty = <TData extends MRT_RowData>(
171
178
  empty.autoRemove = (val: any) => !val;
172
179
 
173
180
  const notEmpty = <TData extends MRT_RowData>(
174
- row: Row<TData>,
181
+ row: Row<any, TData>,
175
182
  id: string,
176
183
  _filterValue: number | string,
177
184
  ): boolean => !!row.getValue<null | number | string>(id)?.toString().trim();
@@ -179,16 +186,23 @@ const notEmpty = <TData extends MRT_RowData>(
179
186
  notEmpty.autoRemove = (val: any) => !val;
180
187
 
181
188
  export const MRT_FilterFns = {
182
- ...filterFns,
189
+ arrIncludes: filterFn_arrIncludes,
190
+ arrIncludesAll: filterFn_arrIncludesAll,
191
+ arrIncludesSome: filterFn_arrIncludesSome,
183
192
  between,
184
193
  betweenInclusive,
185
194
  contains,
186
195
  empty,
187
196
  endsWith,
188
197
  equals,
198
+ equalsString: filterFn_equalsString,
199
+ equalsStringSensitive: filterFn_equalsStringSensitive,
189
200
  fuzzy,
190
201
  greaterThan,
191
202
  greaterThanOrEqualTo,
203
+ includesString: filterFn_includesString,
204
+ includesStringSensitive: filterFn_includesStringSensitive,
205
+ inNumberRange: filterFn_inNumberRange,
192
206
  lessThan,
193
207
  lessThanOrEqualTo,
194
208
  notEmpty,
@@ -1,11 +1,17 @@
1
1
  import { compareItems, type RankingInfo } from '@tanstack/match-sorter-utils';
2
- import { type Row, sortingFns } from '@tanstack/react-table';
2
+ import {
3
+ sortFn_alphanumeric,
4
+ sortFn_basic,
5
+ sortFn_datetime,
6
+ sortFn_text,
7
+ } from '@tanstack/react-table';
8
+ import { type Row } from '@tanstack/react-table';
3
9
 
4
10
  import { type MRT_Row, type MRT_RowData } from '../types';
5
11
 
6
12
  const fuzzy = <TData extends MRT_RowData>(
7
- rowA: Row<TData>,
8
- rowB: Row<TData>,
13
+ rowA: Row<any, TData>,
14
+ rowB: Row<any, TData>,
9
15
  columnId: string,
10
16
  ) => {
11
17
  let dir = 0;
@@ -17,13 +23,16 @@ const fuzzy = <TData extends MRT_RowData>(
17
23
  }
18
24
  // Provide a fallback for when the item ranks are equal
19
25
  return dir === 0
20
- ? sortingFns.alphanumeric(rowA as Row<any>, rowB as Row<any>, columnId)
26
+ ? sortFn_alphanumeric(rowA, rowB, columnId)
21
27
  : dir;
22
28
  };
23
29
 
24
30
  export const MRT_SortingFns = {
25
- ...sortingFns,
31
+ alphanumeric: sortFn_alphanumeric,
32
+ basic: sortFn_basic,
33
+ datetime: sortFn_datetime,
26
34
  fuzzy,
35
+ text: sortFn_text,
27
36
  };
28
37
 
29
38
  export const rankGlobalFuzzy = <TData extends MRT_RowData>(
@@ -0,0 +1,106 @@
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 Person {
8
+ name: string;
9
+ }
10
+
11
+ const data: Person[] = [
12
+ { name: 'Jonathan' },
13
+ { name: 'Aaron' },
14
+ { name: 'Sara' },
15
+ ];
16
+
17
+ const columns: MRT_ColumnDef<Person>[] = [
18
+ { accessorKey: 'name', header: 'Name' },
19
+ ];
20
+
21
+ const renderedNames = (container: HTMLElement) =>
22
+ Array.from(container.querySelectorAll('tbody tr')).map(
23
+ (row) => row.textContent,
24
+ );
25
+
26
+ describe('server-side options suppress client-side row models', () => {
27
+ test('manualPagination renders the whole server page, ignoring pageSize', () => {
28
+ const { container } = render(
29
+ <MaterialReactTable
30
+ columns={columns}
31
+ data={data}
32
+ manualPagination
33
+ rowCount={300}
34
+ state={{ pagination: { pageIndex: 0, pageSize: 2 } }}
35
+ />,
36
+ );
37
+
38
+ expect(renderedNames(container)).toEqual(['Jonathan', 'Aaron', 'Sara']);
39
+ });
40
+
41
+ test('manualFiltering keeps every row when a global filter is set', () => {
42
+ const { container } = render(
43
+ <MaterialReactTable
44
+ columns={columns}
45
+ data={data}
46
+ manualFiltering
47
+ state={{ globalFilter: 'zzz' }}
48
+ />,
49
+ );
50
+
51
+ expect(renderedNames(container)).toEqual(['Jonathan', 'Aaron', 'Sara']);
52
+ });
53
+
54
+ test('manualSorting preserves server order when a sort is set', () => {
55
+ const { container } = render(
56
+ <MaterialReactTable
57
+ columns={columns}
58
+ data={data}
59
+ enableSorting
60
+ manualSorting
61
+ state={{ sorting: [{ desc: false, id: 'name' }] }}
62
+ />,
63
+ );
64
+
65
+ expect(renderedNames(container)).toEqual(['Jonathan', 'Aaron', 'Sara']);
66
+ });
67
+ });
68
+
69
+ describe('client-side row models stay active by default', () => {
70
+ test('pagination slices to pageSize', () => {
71
+ const { container } = render(
72
+ <MaterialReactTable
73
+ columns={columns}
74
+ data={data}
75
+ state={{ pagination: { pageIndex: 0, pageSize: 2 } }}
76
+ />,
77
+ );
78
+
79
+ expect(renderedNames(container)).toEqual(['Jonathan', 'Aaron']);
80
+ });
81
+
82
+ test('global filter drops non-matching rows', () => {
83
+ const { container } = render(
84
+ <MaterialReactTable
85
+ columns={columns}
86
+ data={data}
87
+ state={{ globalFilter: 'zzz' }}
88
+ />,
89
+ );
90
+
91
+ expect(renderedNames(container)).toEqual(['No results found']);
92
+ });
93
+
94
+ test('sorting reorders rows', () => {
95
+ const { container } = render(
96
+ <MaterialReactTable
97
+ columns={columns}
98
+ data={data}
99
+ enableSorting
100
+ state={{ sorting: [{ desc: false, id: 'name' }] }}
101
+ />,
102
+ );
103
+
104
+ expect(renderedNames(container)).toEqual(['Aaron', 'Jonathan', 'Sara']);
105
+ });
106
+ });