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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/index.d.ts +360 -333
  2. package/dist/index.js +919 -928
  3. package/dist/index.js.map +1 -1
  4. package/locales/ar/package.json +2 -2
  5. package/locales/az/package.json +2 -2
  6. package/locales/bg/package.json +2 -2
  7. package/locales/cs/package.json +2 -2
  8. package/locales/da/package.json +2 -2
  9. package/locales/de/package.json +2 -2
  10. package/locales/el/package.json +2 -2
  11. package/locales/en/package.json +2 -2
  12. package/locales/es/package.json +2 -2
  13. package/locales/et/package.json +2 -2
  14. package/locales/fa/package.json +2 -2
  15. package/locales/fi/package.json +2 -2
  16. package/locales/fr/package.json +2 -2
  17. package/locales/he/package.json +2 -2
  18. package/locales/hr/package.json +2 -2
  19. package/locales/hu/package.json +2 -2
  20. package/locales/hy/package.json +2 -2
  21. package/locales/id/package.json +2 -2
  22. package/locales/it/package.json +2 -2
  23. package/locales/ja/package.json +2 -2
  24. package/locales/ko/package.json +2 -2
  25. package/locales/nl/package.json +2 -2
  26. package/locales/no/package.json +2 -2
  27. package/locales/np/package.json +2 -2
  28. package/locales/pl/package.json +2 -2
  29. package/locales/pt/package.json +2 -2
  30. package/locales/pt-BR/package.json +2 -2
  31. package/locales/ro/package.json +2 -2
  32. package/locales/ru/package.json +2 -2
  33. package/locales/sk/package.json +2 -2
  34. package/locales/sr-Cyrl-RS/package.json +2 -2
  35. package/locales/sr-Latn-RS/package.json +2 -2
  36. package/locales/sv/package.json +2 -2
  37. package/locales/tr/package.json +2 -2
  38. package/locales/uk/package.json +2 -2
  39. package/locales/vi/package.json +2 -2
  40. package/locales/zh-Hans/package.json +2 -2
  41. package/locales/zh-Hant/package.json +2 -2
  42. package/package.json +46 -61
  43. package/src/components/body/MRT_TableBody.tsx +1 -2
  44. package/src/components/body/MRT_TableBodyCell.tsx +4 -5
  45. package/src/components/body/MRT_TableBodyCellValue.tsx +1 -2
  46. package/src/components/body/MRT_TableBodyRow.tsx +1 -2
  47. package/src/components/body/MRT_TableBodyRowGrabHandle.test.tsx +42 -0
  48. package/src/components/body/MRT_TableBodyRowPinButton.tsx +1 -2
  49. package/src/components/body/MRT_TableDetailPanel.test.tsx +40 -0
  50. package/src/components/body/MRT_TableDetailPanel.tsx +1 -2
  51. package/src/components/buttons/MRT_ColumnPinningButtons.test.tsx +69 -0
  52. package/src/components/buttons/MRT_ColumnPinningButtons.tsx +3 -3
  53. package/src/components/buttons/MRT_EditActionButtons.test.tsx +50 -0
  54. package/src/components/buttons/MRT_EditActionButtons.tsx +1 -3
  55. package/src/components/buttons/MRT_ExpandAllButton.tsx +1 -2
  56. package/src/components/buttons/MRT_ExpandButton.tsx +1 -2
  57. package/src/components/buttons/MRT_ToggleDensePaddingButton.test.tsx +38 -0
  58. package/src/components/buttons/MRT_ToggleDensePaddingButton.tsx +1 -2
  59. package/src/components/buttons/MRT_ToggleFiltersButton.test.tsx +38 -0
  60. package/src/components/buttons/MRT_ToggleFiltersButton.tsx +1 -2
  61. package/src/components/buttons/MRT_ToggleFullScreenButton.test.tsx +36 -0
  62. package/src/components/buttons/MRT_ToggleFullScreenButton.tsx +1 -2
  63. package/src/components/buttons/MRT_ToggleGlobalFilterButton.tsx +1 -2
  64. package/src/components/buttons/MRT_ToggleRowActionMenuButton.tsx +2 -3
  65. package/src/components/footer/MRT_TableFooter.tsx +1 -2
  66. package/src/components/footer/MRT_TableFooterCell.tsx +1 -2
  67. package/src/components/head/MRT_TableHead.tsx +1 -2
  68. package/src/components/head/MRT_TableHeadCell.tsx +9 -9
  69. package/src/components/head/MRT_TableHeadCellFilterContainer.tsx +1 -2
  70. package/src/components/head/MRT_TableHeadCellGrabHandle.test.tsx +61 -0
  71. package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +4 -5
  72. package/src/components/head/MRT_TableHeadCellResizeHandle.test.tsx +45 -0
  73. package/src/components/head/MRT_TableHeadCellResizeHandle.tsx +4 -5
  74. package/src/components/head/MRT_TableHeadCellSortLabel.tsx +1 -2
  75. package/src/components/inputs/MRT_EditCellTextField.test.tsx +36 -0
  76. package/src/components/inputs/MRT_EditCellTextField.tsx +1 -3
  77. package/src/components/inputs/MRT_FilterCheckbox.tsx +1 -2
  78. package/src/components/inputs/MRT_FilterRangeSlider.tsx +2 -1
  79. package/src/components/inputs/MRT_FilterTextField.test.tsx +75 -0
  80. package/src/components/inputs/MRT_GlobalFilterTextField.tsx +1 -2
  81. package/src/components/inputs/MRT_SelectCheckbox.test.tsx +69 -0
  82. package/src/components/inputs/MRT_SelectCheckbox.tsx +1 -2
  83. package/src/components/menus/MRT_CellActionMenu.tsx +1 -2
  84. package/src/components/menus/MRT_ColumnActionMenu.tsx +12 -13
  85. package/src/components/menus/MRT_FilterOptionMenu.tsx +1 -2
  86. package/src/components/menus/MRT_RowActionMenu.tsx +1 -2
  87. package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +1 -2
  88. package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +4 -5
  89. package/src/components/modals/MRT_EditRowModal.test.tsx +54 -0
  90. package/src/components/modals/MRT_EditRowModal.tsx +1 -2
  91. package/src/components/table/MRT_Table.tsx +4 -5
  92. package/src/components/table/MRT_TableContainer.tsx +1 -2
  93. package/src/components/table/MRT_TablePaper.tsx +1 -2
  94. package/src/components/toolbar/MRT_BottomToolbar.tsx +2 -3
  95. package/src/components/toolbar/MRT_LinearProgressBar.tsx +1 -2
  96. package/src/components/toolbar/MRT_TablePagination.tsx +1 -2
  97. package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +3 -4
  98. package/src/components/toolbar/MRT_ToolbarDropZone.test.tsx +42 -0
  99. package/src/components/toolbar/MRT_ToolbarDropZone.tsx +1 -2
  100. package/src/components/toolbar/MRT_TopToolbar.tsx +1 -2
  101. package/src/fns/aggregationFns.test.tsx +57 -0
  102. package/src/fns/filterFns.test.tsx +156 -0
  103. package/src/fns/filterFns.ts +36 -22
  104. package/src/fns/sortingFns.ts +14 -5
  105. package/src/fns/tableFeatures.test.tsx +106 -0
  106. package/src/fns/tableFeatures.ts +103 -0
  107. package/src/hooks/display-columns/getMRT_RowExpandColumnDef.tsx +2 -2
  108. package/src/hooks/useMRT_ColumnVirtualizer.ts +6 -5
  109. package/src/hooks/useMRT_Effects.ts +3 -4
  110. package/src/hooks/useMRT_RowVirtualizer.ts +1 -2
  111. package/src/hooks/useMRT_Rows.ts +1 -2
  112. package/src/hooks/useMRT_TableInstance.ts +82 -63
  113. package/src/hooks/useMRT_TableOptions.ts +5 -37
  114. package/src/icons.ts +1 -1
  115. package/src/types.ts +162 -134
  116. package/src/utils/column.utils.ts +31 -24
  117. package/src/utils/row.utils.ts +7 -10
  118. package/src/utils/style.utils.ts +9 -10
  119. package/src/utils/tanstack.helpers.ts +2 -2
  120. package/dist/index.d.mts +0 -1925
  121. package/dist/index.mjs +0 -5409
  122. package/dist/index.mjs.map +0 -1
  123. package/locales/ar/index.d.ts +0 -3
  124. package/locales/ar/index.js +0 -98
  125. package/locales/az/index.d.ts +0 -3
  126. package/locales/az/index.js +0 -98
  127. package/locales/bg/index.d.ts +0 -3
  128. package/locales/bg/index.js +0 -98
  129. package/locales/cs/index.d.ts +0 -3
  130. package/locales/cs/index.js +0 -98
  131. package/locales/da/index.d.ts +0 -3
  132. package/locales/da/index.js +0 -98
  133. package/locales/de/index.d.ts +0 -3
  134. package/locales/de/index.js +0 -98
  135. package/locales/el/index.d.ts +0 -3
  136. package/locales/el/index.js +0 -98
  137. package/locales/en/index.d.ts +0 -3
  138. package/locales/en/index.js +0 -98
  139. package/locales/es/index.d.ts +0 -3
  140. package/locales/es/index.js +0 -98
  141. package/locales/et/index.d.ts +0 -3
  142. package/locales/et/index.js +0 -98
  143. package/locales/fa/index.d.ts +0 -3
  144. package/locales/fa/index.js +0 -98
  145. package/locales/fi/index.d.ts +0 -3
  146. package/locales/fi/index.js +0 -98
  147. package/locales/fr/index.d.ts +0 -3
  148. package/locales/fr/index.js +0 -98
  149. package/locales/he/index.d.ts +0 -3
  150. package/locales/he/index.js +0 -98
  151. package/locales/hr/index.d.ts +0 -3
  152. package/locales/hr/index.js +0 -98
  153. package/locales/hu/index.d.ts +0 -3
  154. package/locales/hu/index.js +0 -98
  155. package/locales/hy/index.d.ts +0 -3
  156. package/locales/hy/index.js +0 -98
  157. package/locales/id/index.d.ts +0 -3
  158. package/locales/id/index.js +0 -98
  159. package/locales/it/index.d.ts +0 -3
  160. package/locales/it/index.js +0 -98
  161. package/locales/ja/index.d.ts +0 -3
  162. package/locales/ja/index.js +0 -98
  163. package/locales/ko/index.d.ts +0 -3
  164. package/locales/ko/index.js +0 -98
  165. package/locales/nl/index.d.ts +0 -3
  166. package/locales/nl/index.js +0 -98
  167. package/locales/no/index.d.ts +0 -3
  168. package/locales/no/index.js +0 -98
  169. package/locales/np/index.d.ts +0 -3
  170. package/locales/np/index.js +0 -98
  171. package/locales/pl/index.d.ts +0 -3
  172. package/locales/pl/index.js +0 -98
  173. package/locales/pt/index.d.ts +0 -3
  174. package/locales/pt/index.js +0 -98
  175. package/locales/pt-BR/index.d.ts +0 -3
  176. package/locales/pt-BR/index.js +0 -98
  177. package/locales/ro/index.d.ts +0 -3
  178. package/locales/ro/index.js +0 -98
  179. package/locales/ru/index.d.ts +0 -3
  180. package/locales/ru/index.js +0 -98
  181. package/locales/sk/index.d.ts +0 -3
  182. package/locales/sk/index.js +0 -98
  183. package/locales/sr-Cyrl-RS/index.d.ts +0 -3
  184. package/locales/sr-Cyrl-RS/index.js +0 -98
  185. package/locales/sr-Latn-RS/index.d.ts +0 -3
  186. package/locales/sr-Latn-RS/index.js +0 -98
  187. package/locales/sv/index.d.ts +0 -3
  188. package/locales/sv/index.js +0 -98
  189. package/locales/tr/index.d.ts +0 -3
  190. package/locales/tr/index.js +0 -98
  191. package/locales/uk/index.d.ts +0 -3
  192. package/locales/uk/index.js +0 -98
  193. package/locales/vi/index.d.ts +0 -3
  194. package/locales/vi/index.js +0 -98
  195. package/locales/zh-Hans/index.d.ts +0 -3
  196. package/locales/zh-Hans/index.js +0 -98
  197. package/locales/zh-Hant/index.d.ts +0 -3
  198. package/locales/zh-Hant/index.js +0 -98
@@ -0,0 +1,42 @@
1
+ import { fireEvent, render } from '@testing-library/react';
2
+ import { describe, expect, test, vi } from 'vitest';
3
+
4
+ import { type MRT_ColumnDef } from '../../types';
5
+ import { MaterialReactTable } from '../MaterialReactTable';
6
+
7
+ interface Person {
8
+ name: string;
9
+ }
10
+
11
+ const data: Person[] = [{ name: 'Alice' }, { name: 'Bob' }];
12
+
13
+ const columns = (): MRT_ColumnDef<Person>[] => [
14
+ { accessorKey: 'name', header: 'Name' },
15
+ ];
16
+
17
+ describe('row ordering', () => {
18
+ test('dragging a row over another reports both rows to the drop handler', () => {
19
+ const muiRowDragHandleProps = { onDragEnd: vi.fn() };
20
+ const { container } = render(
21
+ <MaterialReactTable
22
+ columns={columns()}
23
+ data={data}
24
+ enableRowOrdering
25
+ muiRowDragHandleProps={muiRowDragHandleProps}
26
+ />,
27
+ );
28
+
29
+ const handles = container.querySelectorAll<HTMLElement>(
30
+ 'tbody button[aria-label="Move"]',
31
+ );
32
+ const rows = container.querySelectorAll<HTMLElement>('tbody tr');
33
+
34
+ fireEvent.dragStart(handles[0], {
35
+ dataTransfer: { setDragImage: () => {} },
36
+ });
37
+ fireEvent.dragEnter(rows[1]);
38
+ fireEvent.dragEnd(handles[0]);
39
+
40
+ expect(muiRowDragHandleProps.onDragEnd).toHaveBeenCalled();
41
+ });
42
+ });
@@ -21,10 +21,9 @@ export const MRT_TableBodyRowPinButton = <TData extends MRT_RowData>({
21
21
  ...rest
22
22
  }: MRT_TableBodyRowPinButtonProps<TData>) => {
23
23
  const {
24
- getState,
25
24
  options: { enableRowPinning, rowPinningDisplayMode },
26
25
  } = table;
27
- const { density } = getState();
26
+ const { density } = table.state;
28
27
 
29
28
  const canPin = parseFromValuesOrFunc(enableRowPinning, row as any);
30
29
 
@@ -0,0 +1,40 @@
1
+ import { render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ city: string;
10
+ name: string;
11
+ }
12
+
13
+ const data: Person[] = [{ city: 'Glasgow', name: 'Alice' }];
14
+
15
+ const columns = (): MRT_ColumnDef<Person>[] => [
16
+ { accessorKey: 'name', header: 'Name' },
17
+ ];
18
+
19
+ describe('detail panel', () => {
20
+ test('reveals the panel content when the expand button is clicked', async () => {
21
+ const user = userEvent.setup();
22
+ const { container } = render(
23
+ <MaterialReactTable
24
+ columns={columns()}
25
+ data={data}
26
+ renderDetailPanel={({ row }) => (
27
+ <span>Lives in {row.original.city}</span>
28
+ )}
29
+ />,
30
+ );
31
+
32
+ expect(container.textContent).not.toContain('Lives in Glasgow');
33
+
34
+ await user.click(
35
+ container.querySelector('tbody button[aria-label="Expand"]') as HTMLElement,
36
+ );
37
+
38
+ expect(container.textContent).toContain('Lives in Glasgow');
39
+ });
40
+ });
@@ -32,7 +32,6 @@ export const MRT_TableDetailPanel = <TData extends MRT_RowData>({
32
32
  ...rest
33
33
  }: MRT_TableDetailPanelProps<TData>) => {
34
34
  const {
35
- getState,
36
35
  getVisibleLeafColumns,
37
36
  options: {
38
37
  layoutMode,
@@ -42,7 +41,7 @@ export const MRT_TableDetailPanel = <TData extends MRT_RowData>({
42
41
  renderDetailPanel,
43
42
  },
44
43
  } = table;
45
- const { isLoading } = getState();
44
+ const { isLoading } = table.state;
46
45
 
47
46
  const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, {
48
47
  isDetailPanel: true,
@@ -0,0 +1,69 @@
1
+ import { render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ city: string;
10
+ name: string;
11
+ }
12
+
13
+ const data: Person[] = [{ city: 'Glasgow', name: 'Alice' }];
14
+
15
+ const columns = (): MRT_ColumnDef<Person>[] => [
16
+ { accessorKey: 'name', header: 'Name' },
17
+ { accessorKey: 'city', header: 'City' },
18
+ ];
19
+
20
+ const headerOrder = (container: HTMLElement) =>
21
+ Array.from(container.querySelectorAll('thead th')).map((th) =>
22
+ th.textContent?.replace(/[^A-Za-z]/g, ''),
23
+ );
24
+
25
+ describe('column pinning', () => {
26
+ test('pinning to start moves the column to the front', async () => {
27
+ const user = userEvent.setup();
28
+ const { baseElement, container } = render(
29
+ <MaterialReactTable
30
+ columns={columns()}
31
+ data={data}
32
+ enableColumnPinning
33
+ />,
34
+ );
35
+
36
+ expect(headerOrder(container)).toEqual(['Name', 'City']);
37
+
38
+ const cityHeader = Array.from(
39
+ container.querySelectorAll<HTMLElement>('thead th'),
40
+ ).find((th) => th.textContent?.includes('City'));
41
+
42
+ await user.click(
43
+ cityHeader?.querySelector(
44
+ 'button[aria-label="Column Actions"]',
45
+ ) as HTMLElement,
46
+ );
47
+
48
+ await user.click(
49
+ Array.from(baseElement.querySelectorAll<HTMLElement>('li')).find((li) =>
50
+ li.textContent?.includes('Pin to left'),
51
+ ) as HTMLElement,
52
+ );
53
+
54
+ expect(headerOrder(container)).toEqual(['City', 'Name']);
55
+ });
56
+
57
+ test('start and end pinning both apply from initial state', () => {
58
+ const { container } = render(
59
+ <MaterialReactTable
60
+ columns={columns()}
61
+ data={data}
62
+ enableColumnPinning
63
+ initialState={{ columnPinning: { end: ['name'], start: ['city'] } }}
64
+ />,
65
+ );
66
+
67
+ expect(headerOrder(container)).toEqual(['City', 'Name']);
68
+ });
69
+ });
@@ -27,7 +27,7 @@ export const MRT_ColumnPinningButtons = <TData extends MRT_RowData>({
27
27
  },
28
28
  } = table;
29
29
 
30
- const handlePinColumn = (pinDirection: 'left' | 'right' | false) => {
30
+ const handlePinColumn = (pinDirection: 'end' | 'start' | false) => {
31
31
  column.pin(pinDirection);
32
32
  };
33
33
 
@@ -49,7 +49,7 @@ export const MRT_ColumnPinningButtons = <TData extends MRT_RowData>({
49
49
  ) : (
50
50
  <>
51
51
  <Tooltip title={localization.pinToLeft}>
52
- <IconButton onClick={() => handlePinColumn('left')} size="small">
52
+ <IconButton onClick={() => handlePinColumn('start')} size="small">
53
53
  <PushPinIcon
54
54
  style={{
55
55
  transform: 'rotate(90deg)',
@@ -58,7 +58,7 @@ export const MRT_ColumnPinningButtons = <TData extends MRT_RowData>({
58
58
  </IconButton>
59
59
  </Tooltip>
60
60
  <Tooltip title={localization.pinToRight}>
61
- <IconButton onClick={() => handlePinColumn('right')} size="small">
61
+ <IconButton onClick={() => handlePinColumn('end')} size="small">
62
62
  <PushPinIcon
63
63
  style={{
64
64
  transform: 'rotate(-90deg)',
@@ -0,0 +1,50 @@
1
+ import { act, render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test, vi } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef, type MRT_TableInstance } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ name: string;
10
+ }
11
+
12
+ const data: Person[] = [{ name: 'Alice' }];
13
+
14
+ const columns = (): MRT_ColumnDef<Person>[] => [
15
+ { accessorKey: 'name', header: 'Name' },
16
+ ];
17
+
18
+ describe('creating a row', () => {
19
+ test('calls onCreatingRowSave when save is clicked', async () => {
20
+ const user = userEvent.setup();
21
+ const onCreatingRowSave = vi.fn();
22
+ let table: MRT_TableInstance<Person> | undefined;
23
+
24
+ const { container } = render(
25
+ <MaterialReactTable
26
+ columns={columns()}
27
+ createDisplayMode="row"
28
+ data={data}
29
+ enableEditing
30
+ onCreatingRowSave={onCreatingRowSave}
31
+ renderTopToolbarCustomActions={({ table: t }) => {
32
+ table = t;
33
+ return null;
34
+ }}
35
+ />,
36
+ );
37
+
38
+ act(() => {
39
+ table?.setCreatingRow(true);
40
+ });
41
+
42
+ expect(container.querySelectorAll('tbody input').length).toBeGreaterThan(0);
43
+
44
+ await user.click(
45
+ container.querySelector('[aria-label="Save"]') as HTMLElement,
46
+ );
47
+
48
+ expect(onCreatingRowSave).toHaveBeenCalled();
49
+ });
50
+ });
@@ -25,7 +25,6 @@ export const MRT_EditActionButtons = <TData extends MRT_RowData>({
25
25
  ...rest
26
26
  }: MRT_EditActionButtonsProps<TData>) => {
27
27
  const {
28
- getState,
29
28
  options: {
30
29
  icons: { CancelIcon, SaveIcon },
31
30
  localization,
@@ -38,7 +37,7 @@ export const MRT_EditActionButtons = <TData extends MRT_RowData>({
38
37
  setCreatingRow,
39
38
  setEditingRow,
40
39
  } = table;
41
- const { creatingRow, editingRow, isSaving } = getState();
40
+ const { creatingRow, editingRow, isSaving } = table.state;
42
41
 
43
42
  const isCreating = creatingRow?.id === row.id;
44
43
  const isEditing = editingRow?.id === row.id;
@@ -63,7 +62,6 @@ export const MRT_EditActionButtons = <TData extends MRT_RowData>({
63
62
  input.value !== undefined &&
64
63
  Object.hasOwn(row?._valuesCache as object, input.name)
65
64
  ) {
66
- // @ts-expect-error
67
65
  row._valuesCache[input.name] = input.value;
68
66
  }
69
67
  });
@@ -18,7 +18,6 @@ export const MRT_ExpandAllButton = <TData extends MRT_RowData>({
18
18
  getCanSomeRowsExpand,
19
19
  getIsAllRowsExpanded,
20
20
  getIsSomeRowsExpanded,
21
- getState,
22
21
  options: {
23
22
  icons: { KeyboardDoubleArrowDownIcon },
24
23
  localization,
@@ -27,7 +26,7 @@ export const MRT_ExpandAllButton = <TData extends MRT_RowData>({
27
26
  },
28
27
  toggleAllRowsExpanded,
29
28
  } = table;
30
- const { density, isLoading } = getState();
29
+ const { density, isLoading } = table.state;
31
30
 
32
31
  const iconButtonProps = {
33
32
  ...parseFromValuesOrFunc(muiExpandAllButtonProps, {
@@ -25,7 +25,6 @@ export const MRT_ExpandButton = <TData extends MRT_RowData>({
25
25
  }: MRT_ExpandButtonProps<TData>) => {
26
26
  const theme = useTheme();
27
27
  const {
28
- getState,
29
28
  options: {
30
29
  icons: { ExpandMoreIcon },
31
30
  localization,
@@ -34,7 +33,7 @@ export const MRT_ExpandButton = <TData extends MRT_RowData>({
34
33
  renderDetailPanel,
35
34
  },
36
35
  } = table;
37
- const { density } = getState();
36
+ const { density } = table.state;
38
37
 
39
38
  const iconButtonProps = parseFromValuesOrFunc(muiExpandButtonProps, {
40
39
  row,
@@ -0,0 +1,38 @@
1
+ import { render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ name: string;
10
+ }
11
+
12
+ const data: Person[] = [{ name: 'Alice' }];
13
+
14
+ const columns = (): MRT_ColumnDef<Person>[] => [
15
+ { accessorKey: 'name', header: 'Name' },
16
+ ];
17
+
18
+ const bodyCellPadding = (container: HTMLElement) =>
19
+ getComputedStyle(
20
+ container.querySelector('tbody td') as HTMLElement,
21
+ ).getPropertyValue('padding');
22
+
23
+ describe('density toggle', () => {
24
+ test('changes body cell padding when clicked', async () => {
25
+ const user = userEvent.setup();
26
+ const { container } = render(
27
+ <MaterialReactTable columns={columns()} data={data} />,
28
+ );
29
+
30
+ const before = bodyCellPadding(container);
31
+
32
+ await user.click(
33
+ container.querySelector('[aria-label="Toggle density"]') as HTMLElement,
34
+ );
35
+
36
+ expect(bodyCellPadding(container)).not.toBe(before);
37
+ });
38
+ });
@@ -13,14 +13,13 @@ export const MRT_ToggleDensePaddingButton = <TData extends MRT_RowData>({
13
13
  ...rest
14
14
  }: MRT_ToggleDensePaddingButtonProps<TData>) => {
15
15
  const {
16
- getState,
17
16
  options: {
18
17
  icons: { DensityLargeIcon, DensityMediumIcon, DensitySmallIcon },
19
18
  localization,
20
19
  },
21
20
  setDensity,
22
21
  } = table;
23
- const { density } = getState();
22
+ const { density } = table.state;
24
23
 
25
24
  const handleToggleDensePadding = () => {
26
25
  const nextDensity =
@@ -0,0 +1,38 @@
1
+ import { render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ name: string;
10
+ }
11
+
12
+ const data: Person[] = [{ name: 'Alice' }];
13
+
14
+ const columns = (): MRT_ColumnDef<Person>[] => [
15
+ { accessorKey: 'name', header: 'Name' },
16
+ ];
17
+
18
+ const filterInputCount = (container: HTMLElement) =>
19
+ container.querySelectorAll('thead input').length;
20
+
21
+ describe('filters toggle', () => {
22
+ test('reveals the column filter inputs when clicked', async () => {
23
+ const user = userEvent.setup();
24
+ const { container } = render(
25
+ <MaterialReactTable columns={columns()} data={data} />,
26
+ );
27
+
28
+ expect(filterInputCount(container)).toBe(0);
29
+
30
+ await user.click(
31
+ container.querySelector(
32
+ '[aria-label="Show/Hide filters"]',
33
+ ) as HTMLElement,
34
+ );
35
+
36
+ expect(filterInputCount(container)).toBeGreaterThan(0);
37
+ });
38
+ });
@@ -13,14 +13,13 @@ export const MRT_ToggleFiltersButton = <TData extends MRT_RowData>({
13
13
  ...rest
14
14
  }: MRT_ToggleFiltersButtonProps<TData>) => {
15
15
  const {
16
- getState,
17
16
  options: {
18
17
  icons: { FilterListIcon, FilterListOffIcon },
19
18
  localization,
20
19
  },
21
20
  setShowColumnFilters,
22
21
  } = table;
23
- const { showColumnFilters } = getState();
22
+ const { showColumnFilters } = table.state;
24
23
 
25
24
  const handleToggleShowFilters = () => {
26
25
  setShowColumnFilters(!showColumnFilters);
@@ -0,0 +1,36 @@
1
+ import { render } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { type MRT_ColumnDef } from '../../types';
6
+ import { MaterialReactTable } from '../MaterialReactTable';
7
+
8
+ interface Person {
9
+ name: string;
10
+ }
11
+
12
+ const data: Person[] = [{ name: 'Alice' }];
13
+
14
+ const columns = (): MRT_ColumnDef<Person>[] => [
15
+ { accessorKey: 'name', header: 'Name' },
16
+ ];
17
+
18
+ describe('full screen toggle', () => {
19
+ test('fixes the table paper to the viewport when clicked', async () => {
20
+ const user = userEvent.setup();
21
+ const { container } = render(
22
+ <MaterialReactTable columns={columns()} data={data} />,
23
+ );
24
+
25
+ const paper = container.firstElementChild as HTMLElement;
26
+ expect(getComputedStyle(paper).position).not.toBe('fixed');
27
+
28
+ await user.click(
29
+ container.querySelector(
30
+ '[aria-label="Toggle full screen"]',
31
+ ) as HTMLElement,
32
+ );
33
+
34
+ expect(getComputedStyle(paper).position).toBe('fixed');
35
+ });
36
+ });
@@ -14,14 +14,13 @@ export const MRT_ToggleFullScreenButton = <TData extends MRT_RowData>({
14
14
  ...rest
15
15
  }: MRT_ToggleFullScreenButtonProps<TData>) => {
16
16
  const {
17
- getState,
18
17
  options: {
19
18
  icons: { FullscreenExitIcon, FullscreenIcon },
20
19
  localization,
21
20
  },
22
21
  setIsFullScreen,
23
22
  } = table;
24
- const { isFullScreen } = getState();
23
+ const { isFullScreen } = table.state;
25
24
 
26
25
  const [tooltipOpened, setTooltipOpened] = useState(false);
27
26
 
@@ -13,7 +13,6 @@ export const MRT_ToggleGlobalFilterButton = <TData extends MRT_RowData>({
13
13
  ...rest
14
14
  }: MRT_ToggleGlobalFilterButtonProps<TData>) => {
15
15
  const {
16
- getState,
17
16
  options: {
18
17
  icons: { SearchIcon, SearchOffIcon },
19
18
 
@@ -22,7 +21,7 @@ export const MRT_ToggleGlobalFilterButton = <TData extends MRT_RowData>({
22
21
  refs: { searchInputRef },
23
22
  setShowGlobalFilter,
24
23
  } = table;
25
- const { globalFilter, showGlobalFilter } = getState();
24
+ const { globalFilter, showGlobalFilter } = table.state;
26
25
 
27
26
  const handleToggleSearch = () => {
28
27
  setShowGlobalFilter(!showGlobalFilter);
@@ -40,7 +40,6 @@ export const MRT_ToggleRowActionMenuButton = <TData extends MRT_RowData>({
40
40
  ...rest
41
41
  }: MRT_ToggleRowActionMenuButtonProps<TData>) => {
42
42
  const {
43
- getState,
44
43
  options: {
45
44
  createDisplayMode,
46
45
  editDisplayMode,
@@ -53,7 +52,7 @@ export const MRT_ToggleRowActionMenuButton = <TData extends MRT_RowData>({
53
52
  setEditingRow,
54
53
  } = table;
55
54
 
56
- const { creatingRow, editingRow } = getState();
55
+ const { creatingRow, editingRow } = table.state;
57
56
 
58
57
  const isCreating = creatingRow?.id === row.id;
59
58
  const isEditing = editingRow?.id === row.id;
@@ -72,7 +71,7 @@ export const MRT_ToggleRowActionMenuButton = <TData extends MRT_RowData>({
72
71
 
73
72
  const handleStartEditMode = (event: MouseEvent) => {
74
73
  event.stopPropagation();
75
- setEditingRow({ ...row });
74
+ setEditingRow(row);
76
75
  setAnchorEl(null);
77
76
  };
78
77
 
@@ -20,11 +20,10 @@ export const MRT_TableFooter = <TData extends MRT_RowData>({
20
20
  ...rest
21
21
  }: MRT_TableFooterProps<TData>) => {
22
22
  const {
23
- getState,
24
23
  options: { enableStickyFooter, layoutMode, muiTableFooterProps },
25
24
  refs: { tableFooterRef },
26
25
  } = table;
27
- const { isFullScreen } = getState();
26
+ const { isFullScreen } = table.state;
28
27
 
29
28
  const tableFooterProps = {
30
29
  ...parseFromValuesOrFunc(muiTableFooterProps, {
@@ -25,14 +25,13 @@ export const MRT_TableFooterCell = <TData extends MRT_RowData>({
25
25
  }: MRT_TableFooterCellProps<TData>) => {
26
26
  const theme = useTheme();
27
27
  const {
28
- getState,
29
28
  options: {
30
29
  enableColumnPinning,
31
30
  enableKeyboardShortcuts,
32
31
  muiTableFooterCellProps,
33
32
  },
34
33
  } = table;
35
- const { density } = getState();
34
+ const { density } = table.state;
36
35
  const { column } = footer;
37
36
  const { columnDef } = column;
38
37
  const { columnDefType } = columnDef;
@@ -21,7 +21,6 @@ export const MRT_TableHead = <TData extends MRT_RowData>({
21
21
  ...rest
22
22
  }: MRT_TableHeadProps<TData>) => {
23
23
  const {
24
- getState,
25
24
  options: {
26
25
  enableStickyHeader,
27
26
  layoutMode,
@@ -30,7 +29,7 @@ export const MRT_TableHead = <TData extends MRT_RowData>({
30
29
  },
31
30
  refs: { tableHeadRef },
32
31
  } = table;
33
- const { isFullScreen, showAlertBanner } = getState();
32
+ const { isFullScreen, showAlertBanner } = table.state;
34
33
 
35
34
  const tableHeadProps = {
36
35
  ...parseFromValuesOrFunc(muiTableHeadProps, { table }),
@@ -2,7 +2,7 @@ import { Box } from '@mui/material';
2
2
  import { TableCell, type TableCellProps } from '@mui/material';
3
3
  import { useTheme } from '@mui/material/styles';
4
4
  import { type Theme } from '@mui/material/styles';
5
- import { type DragEvent, useCallback, useMemo } from 'react';
5
+ import { type DragEvent, useCallback, useMemo, useRef } from 'react';
6
6
 
7
7
  import {
8
8
  type MRT_ColumnVirtualizer,
@@ -37,7 +37,6 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
37
37
  }: MRT_TableHeadCellProps<TData>) => {
38
38
  const theme = useTheme();
39
39
  const {
40
- getState,
41
40
  options: {
42
41
  columnFilterDisplayMode,
43
42
  columnResizeDirection,
@@ -57,13 +56,13 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
57
56
  setHoveredColumn,
58
57
  } = table;
59
58
  const {
60
- columnSizingInfo,
59
+ columnResizing,
61
60
  density,
62
61
  draggingColumn,
63
62
  grouping,
64
63
  hoveredColumn,
65
64
  showColumnFilters,
66
- } = getState();
65
+ } = table.state;
67
66
  const { column } = header;
68
67
  const { columnDef } = column;
69
68
  const { columnDefType } = columnDef;
@@ -105,7 +104,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
105
104
 
106
105
  const draggingBorders = useMemo(() => {
107
106
  const showResizeBorder =
108
- columnSizingInfo.isResizingColumn === column.id &&
107
+ columnResizing.isResizingColumn === column.id &&
109
108
  columnResizeMode === 'onChange' &&
110
109
  !header.subHeaders.length;
111
110
 
@@ -131,7 +130,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
131
130
  : undefined;
132
131
 
133
132
  return draggingBorders;
134
- }, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]);
133
+ }, [draggingColumn, hoveredColumn, columnResizing.isResizingColumn]);
135
134
 
136
135
  const handleDragEnter = (_e: DragEvent) => {
137
136
  if (enableGrouping && hoveredColumn?.id === 'drop-zone') {
@@ -160,8 +159,11 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
160
159
  });
161
160
  };
162
161
 
162
+ const tableHeadCellRef = useRef<HTMLTableCellElement | null>(null);
163
+
163
164
  const handleRef = useCallback(
164
165
  (node: HTMLTableCellElement) => {
166
+ tableHeadCellRef.current = node;
165
167
  if (node) {
166
168
  if (tableHeadCellRefs.current) {
167
169
  tableHeadCellRefs.current[column.id] = node;
@@ -326,9 +328,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
326
328
  <MRT_TableHeadCellGrabHandle
327
329
  column={column}
328
330
  table={table}
329
- tableHeadCellRef={{
330
- current: tableHeadCellRefs.current?.[column.id]!,
331
- }}
331
+ tableHeadCellRef={tableHeadCellRef}
332
332
  />
333
333
  )}
334
334
  {showColumnActions && (
@@ -24,10 +24,9 @@ export const MRT_TableHeadCellFilterContainer = <TData extends MRT_RowData>({
24
24
  ...rest
25
25
  }: MRT_TableHeadCellFilterContainerProps<TData>) => {
26
26
  const {
27
- getState,
28
27
  options: { columnFilterDisplayMode },
29
28
  } = table;
30
- const { showColumnFilters } = getState();
29
+ const { showColumnFilters } = table.state;
31
30
  const { column } = header;
32
31
  const { columnDef } = column;
33
32
  const { isRangeFilter } = getColumnFilterInfo({ header, table });