material-react-table 3.0.3 → 3.2.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 (152) hide show
  1. package/dist/index.d.ts +23 -73
  2. package/dist/index.esm.js +130 -107
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +130 -107
  5. package/dist/index.js.map +1 -1
  6. package/locales/ar/index.esm.js +1 -0
  7. package/locales/ar/index.js +1 -0
  8. package/locales/az/index.esm.js +1 -0
  9. package/locales/az/index.js +1 -0
  10. package/locales/bg/index.esm.js +1 -0
  11. package/locales/bg/index.js +1 -0
  12. package/locales/cs/index.esm.js +1 -0
  13. package/locales/cs/index.js +1 -0
  14. package/locales/da/index.esm.js +1 -0
  15. package/locales/da/index.js +1 -0
  16. package/locales/de/index.esm.js +1 -0
  17. package/locales/de/index.js +1 -0
  18. package/locales/el/index.esm.js +1 -0
  19. package/locales/el/index.js +1 -0
  20. package/locales/en/index.esm.js +1 -0
  21. package/locales/en/index.js +1 -0
  22. package/locales/es/index.esm.js +1 -0
  23. package/locales/es/index.js +1 -0
  24. package/locales/et/index.esm.js +1 -0
  25. package/locales/et/index.js +1 -0
  26. package/locales/fa/index.esm.js +1 -0
  27. package/locales/fa/index.js +1 -0
  28. package/locales/fi/index.esm.js +1 -0
  29. package/locales/fi/index.js +1 -0
  30. package/locales/fr/index.esm.js +1 -0
  31. package/locales/fr/index.js +1 -0
  32. package/locales/he/index.esm.js +1 -0
  33. package/locales/he/index.js +1 -0
  34. package/locales/hr/index.esm.js +1 -0
  35. package/locales/hr/index.js +1 -0
  36. package/locales/hu/index.esm.js +1 -0
  37. package/locales/hu/index.js +1 -0
  38. package/locales/hy/index.esm.js +1 -0
  39. package/locales/hy/index.js +1 -0
  40. package/locales/id/index.esm.js +1 -0
  41. package/locales/id/index.js +1 -0
  42. package/locales/it/index.esm.js +1 -0
  43. package/locales/it/index.js +1 -0
  44. package/locales/ja/index.esm.js +1 -0
  45. package/locales/ja/index.js +1 -0
  46. package/locales/ko/index.esm.js +1 -0
  47. package/locales/ko/index.js +1 -0
  48. package/locales/nl/index.esm.js +1 -0
  49. package/locales/nl/index.js +1 -0
  50. package/locales/no/index.esm.js +1 -0
  51. package/locales/no/index.js +1 -0
  52. package/locales/np/index.esm.js +1 -0
  53. package/locales/np/index.js +1 -0
  54. package/locales/pl/index.esm.js +1 -0
  55. package/locales/pl/index.js +1 -0
  56. package/locales/pt/index.esm.js +1 -0
  57. package/locales/pt/index.js +1 -0
  58. package/locales/pt-BR/index.esm.js +1 -0
  59. package/locales/pt-BR/index.js +1 -0
  60. package/locales/ro/index.esm.js +1 -0
  61. package/locales/ro/index.js +1 -0
  62. package/locales/ru/index.esm.js +1 -0
  63. package/locales/ru/index.js +1 -0
  64. package/locales/sk/index.esm.js +1 -0
  65. package/locales/sk/index.js +1 -0
  66. package/locales/sr-Cyrl-RS/index.esm.js +1 -0
  67. package/locales/sr-Cyrl-RS/index.js +1 -0
  68. package/locales/sr-Latn-RS/index.esm.js +1 -0
  69. package/locales/sr-Latn-RS/index.js +1 -0
  70. package/locales/sv/index.esm.js +1 -0
  71. package/locales/sv/index.js +1 -0
  72. package/locales/tr/index.esm.js +1 -0
  73. package/locales/tr/index.js +1 -0
  74. package/locales/uk/index.esm.js +1 -0
  75. package/locales/uk/index.js +1 -0
  76. package/locales/vi/index.esm.js +1 -0
  77. package/locales/vi/index.js +1 -0
  78. package/locales/zh-Hans/index.esm.js +1 -0
  79. package/locales/zh-Hans/index.js +1 -0
  80. package/locales/zh-Hant/index.esm.js +1 -0
  81. package/locales/zh-Hant/index.js +1 -0
  82. package/package.json +31 -32
  83. package/src/components/body/MRT_TableBodyCell.tsx +2 -2
  84. package/src/components/body/MRT_TableBodyCellValue.tsx +1 -1
  85. package/src/components/body/MRT_TableBodyRow.tsx +1 -1
  86. package/src/components/body/MRT_TableBodyRowGrabHandle.tsx +1 -1
  87. package/src/components/body/MRT_TableDetailPanel.tsx +1 -1
  88. package/src/components/buttons/MRT_EditActionButtons.tsx +2 -2
  89. package/src/components/footer/MRT_TableFooter.tsx +1 -1
  90. package/src/components/head/MRT_TableHead.tsx +1 -1
  91. package/src/components/head/MRT_TableHeadCell.tsx +2 -2
  92. package/src/components/head/MRT_TableHeadCellFilterLabel.tsx +8 -10
  93. package/src/components/head/MRT_TableHeadCellGrabHandle.tsx +1 -1
  94. package/src/components/inputs/MRT_EditCellTextField.tsx +5 -3
  95. package/src/components/inputs/MRT_FilterRangeSlider.tsx +12 -5
  96. package/src/components/inputs/MRT_FilterTextField.tsx +106 -70
  97. package/src/components/menus/MRT_ColumnActionMenu.tsx +3 -2
  98. package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +12 -0
  99. package/src/components/table/MRT_TableContainer.tsx +1 -1
  100. package/src/components/table/MRT_TablePaper.tsx +1 -1
  101. package/src/components/toolbar/MRT_BottomToolbar.tsx +1 -1
  102. package/src/components/toolbar/MRT_TablePagination.tsx +5 -3
  103. package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +4 -4
  104. package/src/components/toolbar/MRT_TopToolbar.tsx +1 -1
  105. package/src/hooks/display-columns/getMRT_RowDragColumnDef.tsx +1 -1
  106. package/src/hooks/useMRT_ColumnVirtualizer.ts +1 -1
  107. package/src/hooks/useMRT_Effects.ts +3 -3
  108. package/src/hooks/useMRT_RowVirtualizer.ts +17 -5
  109. package/src/hooks/useMRT_TableInstance.ts +1 -1
  110. package/src/locales/ar.ts +1 -0
  111. package/src/locales/az.ts +1 -0
  112. package/src/locales/bg.ts +1 -0
  113. package/src/locales/cs.ts +1 -0
  114. package/src/locales/da.ts +1 -0
  115. package/src/locales/de.ts +1 -0
  116. package/src/locales/el.ts +1 -0
  117. package/src/locales/en.ts +1 -0
  118. package/src/locales/es.ts +1 -0
  119. package/src/locales/et.ts +1 -0
  120. package/src/locales/fa.ts +1 -0
  121. package/src/locales/fi.ts +1 -0
  122. package/src/locales/fr.ts +1 -0
  123. package/src/locales/he.ts +1 -0
  124. package/src/locales/hr.ts +1 -0
  125. package/src/locales/hu.ts +1 -0
  126. package/src/locales/hy.ts +1 -0
  127. package/src/locales/id.ts +1 -0
  128. package/src/locales/it.ts +1 -0
  129. package/src/locales/ja.ts +1 -0
  130. package/src/locales/ko.ts +1 -0
  131. package/src/locales/nl.ts +1 -0
  132. package/src/locales/no.ts +1 -0
  133. package/src/locales/np.ts +1 -0
  134. package/src/locales/pl.ts +1 -0
  135. package/src/locales/pt-BR.ts +1 -0
  136. package/src/locales/pt.ts +1 -0
  137. package/src/locales/ro.ts +1 -0
  138. package/src/locales/ru.ts +1 -0
  139. package/src/locales/sk.ts +1 -0
  140. package/src/locales/sr-Cyrl-RS.ts +1 -0
  141. package/src/locales/sr-Latn-RS.ts +1 -0
  142. package/src/locales/sv.ts +1 -0
  143. package/src/locales/tr.ts +1 -0
  144. package/src/locales/uk.ts +1 -0
  145. package/src/locales/vi.ts +1 -0
  146. package/src/locales/zh-Hans.ts +1 -0
  147. package/src/locales/zh-Hant.ts +1 -0
  148. package/src/types.ts +17 -67
  149. package/src/utils/cell.utils.ts +2 -2
  150. package/src/utils/column.utils.ts +1 -1
  151. package/src/utils/tanstack.helpers.ts +1 -1
  152. package/src/utils/virtualization.utils.ts +5 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.0.3",
2
+ "version": "3.2.0",
3
3
  "license": "MIT",
4
4
  "name": "material-react-table",
5
5
  "description": "A fully featured Material UI V6 implementation of TanStack React Table V8, written from the ground up in TypeScript.",
@@ -62,47 +62,46 @@
62
62
  "build-storybook": "storybook build"
63
63
  },
64
64
  "devDependencies": {
65
- "@emotion/react": "^11.13.5",
66
- "@emotion/styled": "^11.13.5",
67
- "@faker-js/faker": "^9.2.0",
68
- "@mui/icons-material": "^6.1.9",
69
- "@mui/material": "^6.1.9",
70
- "@mui/x-date-pickers": "^7.23.0",
65
+ "@emotion/react": "^11.14.0",
66
+ "@emotion/styled": "^11.14.0",
67
+ "@faker-js/faker": "^9.3.0",
68
+ "@mui/icons-material": "^6.2.1",
69
+ "@mui/material": "^6.2.1",
70
+ "@mui/x-date-pickers": "^7.23.3",
71
71
  "@rollup/plugin-typescript": "^11.1.6",
72
72
  "@size-limit/preset-small-lib": "^11.1.6",
73
- "@storybook/addon-a11y": "^8.4.6",
74
- "@storybook/addon-essentials": "^8.4.6",
75
- "@storybook/addon-links": "^8.4.6",
76
- "@storybook/addon-storysource": "^8.4.6",
77
- "@storybook/blocks": "^8.4.6",
78
- "@storybook/preview-api": "^8.4.6",
79
- "@storybook/react": "^8.4.6",
80
- "@storybook/react-vite": "^8.4.6",
81
- "@types/node": "^22.10.1",
82
- "@types/react": "^18.3.12",
83
- "@types/react-dom": "^18.3.1",
84
- "@typescript-eslint/eslint-plugin": "^8.16.0",
85
- "@typescript-eslint/parser": "^8.16.0",
73
+ "@storybook/addon-a11y": "^8.4.7",
74
+ "@storybook/addon-essentials": "^8.4.7",
75
+ "@storybook/addon-links": "^8.4.7",
76
+ "@storybook/addon-storysource": "^8.4.7",
77
+ "@storybook/blocks": "^8.4.7",
78
+ "@storybook/preview-api": "^8.4.7",
79
+ "@storybook/react": "^8.4.7",
80
+ "@storybook/react-vite": "^8.4.7",
81
+ "@types/node": "^22.10.2",
82
+ "@types/react": "^19.0.2",
83
+ "@types/react-dom": "^19.0.2",
84
+ "@typescript-eslint/eslint-plugin": "8.18.1",
85
+ "@typescript-eslint/parser": "8.18.1",
86
86
  "@vitejs/plugin-react": "^4.3.4",
87
- "eslint": "^9.16.0",
87
+ "eslint": "^9.17.0",
88
88
  "eslint-plugin-mui-path-imports": "^0.0.15",
89
- "eslint-plugin-perfectionist": "^4.1.2",
89
+ "eslint-plugin-perfectionist": "^4.4.0",
90
90
  "eslint-plugin-storybook": "^0.11.1",
91
- "prop-types": "^15.8.1",
92
- "react": "^18.3.1",
93
- "react-dom": "^18.3.1",
94
- "react-is": "^18.3.1",
91
+ "react": "^19.0.0",
92
+ "react-dom": "^19.0.0",
93
+ "react-is": "^19.0.0",
95
94
  "rollup": "^2.79.1",
96
95
  "rollup-plugin-copy": "^3.5.0",
97
96
  "rollup-plugin-delete": "^2.1.0",
98
97
  "rollup-plugin-dts": "^6.1.1",
99
98
  "rollup-plugin-peer-deps-external": "^2.2.4",
100
99
  "size-limit": "^11.1.6",
101
- "storybook": "^8.4.6",
100
+ "storybook": "^8.4.7",
102
101
  "storybook-dark-mode": "^4.0.2",
103
102
  "tslib": "^2.8.1",
104
- "typescript": "^5.7.2",
105
- "vite": "^6.0.1"
103
+ "typescript": "5.7.2",
104
+ "vite": "^6.0.5"
106
105
  },
107
106
  "peerDependencies": {
108
107
  "@emotion/react": ">=11.13",
@@ -115,8 +114,8 @@
115
114
  },
116
115
  "dependencies": {
117
116
  "@tanstack/match-sorter-utils": "8.19.4",
118
- "@tanstack/react-table": "8.20.5",
119
- "@tanstack/react-virtual": "3.10.9",
117
+ "@tanstack/react-table": "8.20.6",
118
+ "@tanstack/react-virtual": "3.11.2",
120
119
  "highlight-words": "2.0.0"
121
120
  }
122
- }
121
+ }
@@ -30,7 +30,7 @@ export interface MRT_TableBodyCellProps<TData extends MRT_RowData>
30
30
  extends TableCellProps {
31
31
  cell: MRT_Cell<TData>;
32
32
  numRows?: number;
33
- rowRef: RefObject<HTMLTableRowElement>;
33
+ rowRef: RefObject<HTMLTableRowElement | null>;
34
34
  staticColumnIndex?: number;
35
35
  staticRowIndex: number;
36
36
  table: MRT_TableInstance<TData>;
@@ -187,7 +187,7 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
187
187
  (parseFromValuesOrFunc(enableClickToCopy, cell) === true ||
188
188
  parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) &&
189
189
  !['context-menu', false].includes(
190
- // @ts-ignore
190
+ // @ts-expect-error
191
191
  parseFromValuesOrFunc(columnDef.enableClickToCopy, cell),
192
192
  );
193
193
 
@@ -11,7 +11,7 @@ const allowedTypes = ['string', 'number'];
11
11
 
12
12
  export interface MRT_TableBodyCellValueProps<TData extends MRT_RowData> {
13
13
  cell: MRT_Cell<TData>;
14
- rowRef?: RefObject<HTMLTableRowElement>;
14
+ rowRef?: RefObject<HTMLTableRowElement | null>;
15
15
  staticColumnIndex?: number;
16
16
  staticRowIndex?: number;
17
17
  table: MRT_TableInstance<TData>;
@@ -129,7 +129,7 @@ export const MRT_TableBodyRow = <TData extends MRT_RowData>({
129
129
  density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69;
130
130
 
131
131
  const customRowHeight =
132
- // @ts-ignore
132
+ // @ts-expect-error
133
133
  parseInt(tableRowProps?.style?.height ?? sx?.height, 10) || undefined;
134
134
 
135
135
  const rowHeight = customRowHeight || defaultRowHeight;
@@ -11,7 +11,7 @@ import { MRT_GrabHandleButton } from '../buttons/MRT_GrabHandleButton';
11
11
  export interface MRT_TableBodyRowGrabHandleProps<TData extends MRT_RowData>
12
12
  extends IconButtonProps {
13
13
  row: MRT_Row<TData>;
14
- rowRef: RefObject<HTMLTableRowElement>;
14
+ rowRef: RefObject<HTMLTableRowElement | null>;
15
15
  table: MRT_TableInstance<TData>;
16
16
  }
17
17
 
@@ -13,7 +13,7 @@ import { parseFromValuesOrFunc } from '../../utils/utils';
13
13
 
14
14
  export interface MRT_TableDetailPanelProps<TData extends MRT_RowData>
15
15
  extends TableCellProps {
16
- parentRowRef: RefObject<HTMLTableRowElement>;
16
+ parentRowRef: RefObject<HTMLTableRowElement | null>;
17
17
  row: MRT_Row<TData>;
18
18
  rowVirtualizer?: MRT_RowVirtualizer;
19
19
  staticRowIndex: number;
@@ -55,14 +55,14 @@ export const MRT_EditActionButtons = <TData extends MRT_RowData>({
55
55
 
56
56
  const handleSubmitRow = () => {
57
57
  //look for auto-filled input values
58
- Object.values(editInputRefs?.current)
58
+ Object.values(editInputRefs.current ?? {})
59
59
  .filter((inputRef) => row.id === inputRef?.name?.split('_')?.[0])
60
60
  ?.forEach((input) => {
61
61
  if (
62
62
  input.value !== undefined &&
63
63
  Object.hasOwn(row?._valuesCache as object, input.name)
64
64
  ) {
65
- // @ts-ignore
65
+ // @ts-expect-error
66
66
  row._valuesCache[input.name] = input.value;
67
67
  }
68
68
  });
@@ -57,7 +57,7 @@ export const MRT_TableFooter = <TData extends MRT_RowData>({
57
57
  ref={(ref: HTMLTableSectionElement) => {
58
58
  tableFooterRef.current = ref;
59
59
  if (tableFooterProps?.ref) {
60
- // @ts-ignore
60
+ // @ts-expect-error
61
61
  tableFooterProps.ref.current = ref;
62
62
  }
63
63
  }}
@@ -44,7 +44,7 @@ export const MRT_TableHead = <TData extends MRT_RowData>({
44
44
  ref={(ref: HTMLTableSectionElement) => {
45
45
  tableHeadRef.current = ref;
46
46
  if (tableHeadProps?.ref) {
47
- // @ts-ignore
47
+ // @ts-expect-error
48
48
  tableHeadProps.ref.current = ref;
49
49
  }
50
50
  }}
@@ -191,7 +191,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
191
191
  onDragOver={handleDragOver}
192
192
  ref={(node: HTMLTableCellElement) => {
193
193
  if (node) {
194
- tableHeadCellRefs.current[column.id] = node;
194
+ tableHeadCellRefs.current![column.id] = node;
195
195
  if (columnDefType !== 'group') {
196
196
  columnVirtualizer?.measureElement?.(node);
197
197
  }
@@ -319,7 +319,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
319
319
  column={column}
320
320
  table={table}
321
321
  tableHeadCellRef={{
322
- current: tableHeadCellRefs.current[column.id],
322
+ current: tableHeadCellRefs.current?.[column.id]!,
323
323
  }}
324
324
  />
325
325
  )}
@@ -76,12 +76,11 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData = {}>({
76
76
  .replace(
77
77
  '{filterType}',
78
78
  currentFilterOption
79
- ? // @ts-ignore
80
- localization[
79
+ ? localization[
81
80
  `filter${
82
- currentFilterOption?.charAt(0)?.toUpperCase() +
83
- currentFilterOption?.slice(1)
84
- }`
81
+ currentFilterOption.charAt(0).toUpperCase() +
82
+ currentFilterOption.slice(1)
83
+ }` as keyof typeof localization
85
84
  ]
86
85
  : '',
87
86
  )
@@ -109,8 +108,7 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData = {}>({
109
108
  in={
110
109
  columnFilterDisplayMode === 'popover' ||
111
110
  (!!filterValue && !isRangeFilter) ||
112
- (isRangeFilter && // @ts-ignore
113
- (!!filterValue?.[0] || !!filterValue?.[1]))
111
+ (isRangeFilter && (!!filterValue?.[0] || !!filterValue?.[1]))
114
112
  }
115
113
  unmountOnExit
116
114
  >
@@ -125,8 +123,8 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData = {}>({
125
123
  setShowColumnFilters(true);
126
124
  }
127
125
  queueMicrotask(() => {
128
- filterInputRefs.current[`${column.id}-0`]?.focus?.();
129
- filterInputRefs.current[`${column.id}-0`]?.select?.();
126
+ filterInputRefs.current?.[`${column.id}-0`]?.focus?.();
127
+ filterInputRefs.current?.[`${column.id}-0`]?.select?.();
130
128
  });
131
129
  event.stopPropagation();
132
130
  }}
@@ -158,7 +156,7 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData = {}>({
158
156
  disableScrollLock
159
157
  onClick={(event) => event.stopPropagation()}
160
158
  onClose={(event) => {
161
- //@ts-ignore
159
+ //@ts-expect-error
162
160
  event.stopPropagation();
163
161
  setAnchorEl(null);
164
162
  }}
@@ -13,7 +13,7 @@ export interface MRT_TableHeadCellGrabHandleProps<TData extends MRT_RowData>
13
13
  extends IconButtonProps {
14
14
  column: MRT_Column<TData>;
15
15
  table: MRT_TableInstance<TData>;
16
- tableHeadCellRef: RefObject<HTMLTableCellElement>;
16
+ tableHeadCellRef: RefObject<HTMLTableCellElement | null>;
17
17
  }
18
18
 
19
19
  export const MRT_TableHeadCellGrabHandle = <TData extends MRT_RowData>({
@@ -70,7 +70,7 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
70
70
  const isSelectEdit = editVariant === 'select' || textFieldProps?.select;
71
71
 
72
72
  const saveInputValueToRowCache = (newValue: string) => {
73
- //@ts-ignore
73
+ //@ts-expect-error
74
74
  row._valuesCache[column.id] = newValue;
75
75
  if (isCreating) {
76
76
  setCreatingRow(row);
@@ -96,7 +96,7 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
96
96
  const handleEnterKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
97
97
  textFieldProps.onKeyDown?.(event);
98
98
  if (event.key === 'Enter' && !event.shiftKey && completesComposition) {
99
- editInputRefs.current[column.id]?.blur();
99
+ editInputRefs.current?.[column.id]?.blur();
100
100
  }
101
101
  };
102
102
 
@@ -110,7 +110,9 @@ export const MRT_EditCellTextField = <TData extends MRT_RowData>({
110
110
  fullWidth
111
111
  inputRef={(inputRef) => {
112
112
  if (inputRef) {
113
- editInputRefs.current[column.id] = inputRef;
113
+ editInputRefs.current![column.id] = isSelectEdit
114
+ ? inputRef.node
115
+ : inputRef;
114
116
  if (textFieldProps.inputRef) {
115
117
  textFieldProps.inputRef = inputRef;
116
118
  }
@@ -54,6 +54,13 @@ export const MRT_FilterRangeSlider = <TData extends MRT_RowData>({
54
54
 
55
55
  const isMounted = useRef(false);
56
56
 
57
+ // prevent moving the focus to the next/prev cell when using the arrow keys
58
+ const handleKeyDown = (event: React.KeyboardEvent) => {
59
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
60
+ event.stopPropagation();
61
+ }
62
+ };
63
+
57
64
  useEffect(() => {
58
65
  if (isMounted.current) {
59
66
  if (columnFilterValue === undefined) {
@@ -84,6 +91,7 @@ export const MRT_FilterRangeSlider = <TData extends MRT_RowData>({
84
91
  }
85
92
  }
86
93
  }}
94
+ onKeyDown={handleKeyDown}
87
95
  value={filterValues}
88
96
  valueLabelDisplay="auto"
89
97
  {...sliderProps}
@@ -91,10 +99,10 @@ export const MRT_FilterRangeSlider = <TData extends MRT_RowData>({
91
99
  input: {
92
100
  ref: (node) => {
93
101
  if (node) {
94
- filterInputRefs.current[`${column.id}-0`] = node;
95
- // @ts-ignore
102
+ filterInputRefs.current![`${column.id}-0`] = node;
103
+ // @ts-expect-error
96
104
  if (sliderProps?.slotProps?.input?.ref) {
97
- //@ts-ignore
105
+ //@ts-expect-error
98
106
  sliderProps.slotProps.input.ref = node;
99
107
  }
100
108
  }
@@ -121,12 +129,11 @@ export const MRT_FilterRangeSlider = <TData extends MRT_RowData>({
121
129
  >
122
130
  {localization.filterMode.replace(
123
131
  '{filterType}',
124
- // @ts-ignore
125
132
  localization[
126
133
  `filter${
127
134
  currentFilterOption?.charAt(0)?.toUpperCase() +
128
135
  currentFilterOption?.slice(1)
129
- }`
136
+ }` as keyof typeof localization
130
137
  ],
131
138
  )}
132
139
  </FormHelperText>
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  type ChangeEvent,
3
3
  type MouseEvent,
4
+ SyntheticEvent,
4
5
  useCallback,
5
6
  useEffect,
6
7
  useRef,
7
8
  useState,
8
9
  } from 'react';
9
- import Autocomplete from '@mui/material/Autocomplete';
10
+ import Autocomplete, { AutocompleteInputChangeReason } from '@mui/material/Autocomplete';
10
11
  import Box from '@mui/material/Box';
11
12
  import Checkbox from '@mui/material/Checkbox';
12
13
  import Chip from '@mui/material/Chip';
@@ -107,12 +108,11 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
107
108
  const dropdownOptions = useDropdownOptions({ header, table });
108
109
 
109
110
  const filterChipLabel = ['empty', 'notEmpty'].includes(currentFilterOption)
110
- ? //@ts-ignore
111
- localization[
111
+ ? localization[
112
112
  `filter${
113
113
  currentFilterOption?.charAt?.(0)?.toUpperCase() +
114
114
  currentFilterOption?.slice(1)
115
- }`
115
+ }` as keyof typeof localization
116
116
  ]
117
117
  : '';
118
118
 
@@ -144,11 +144,13 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
144
144
  ? (column.getFilterValue() as [string, string])?.[
145
145
  rangeFilterIndex as number
146
146
  ] || ''
147
+ : isAutocompleteFilter
148
+ ? typeof column.getFilterValue() === 'string' ? column.getFilterValue() as string : ''
147
149
  : ((column.getFilterValue() as string) ?? ''),
148
150
  );
149
151
  const [autocompleteValue, setAutocompleteValue] =
150
152
  useState<DropdownOption | null>(
151
- isAutocompleteFilter ? (filterValue as DropdownOption | null) : null,
153
+ () => isAutocompleteFilter ? ((column.getFilterValue() || null) as DropdownOption | null) : null,
152
154
  );
153
155
 
154
156
  const handleChangeDebounced = useCallback(
@@ -185,9 +187,13 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
185
187
  textFieldProps?.onChange?.(event);
186
188
  };
187
189
 
190
+ const handleAutocompleteInputChange = (_event: SyntheticEvent, newValue: string, _reason: AutocompleteInputChangeReason) => {
191
+ handleChange(newValue)
192
+ };
193
+
188
194
  const handleAutocompleteChange = (newValue: DropdownOption | null) => {
189
195
  setAutocompleteValue(newValue);
190
- handleChange(getValueAndLabel(newValue).value);
196
+ handleChangeDebounced(getValueAndLabel(newValue).value);
191
197
  };
192
198
 
193
199
  const handleClear = () => {
@@ -201,6 +207,12 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
201
207
  newFilterValues[rangeFilterIndex as number] = undefined;
202
208
  return newFilterValues;
203
209
  });
210
+ } else if (isAutocompleteFilter) {
211
+ setAutocompleteValue(null)
212
+ setFilterValue('')
213
+ // when using 'autocomplete' this function is called only inside effect and only if the filterValue === undefined
214
+ // so the following call is excessive; should be uncommented if the handleClear becomes part of the Autocomplete component callbacks
215
+ // column.setFilterValue(undefined)
204
216
  } else {
205
217
  setFilterValue('');
206
218
  column.setFilterValue(undefined);
@@ -246,7 +258,10 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
246
258
  !isAutocompleteFilter && !isDateFilter && !filterChipLabel ? (
247
259
  <InputAdornment
248
260
  position="end"
249
- sx={{ mr: isSelectFilter || isMultiSelectFilter ? '20px' : undefined }}
261
+ sx={{
262
+ mr: isSelectFilter || isMultiSelectFilter ? '20px' : undefined,
263
+ visibility: (filterValue?.length ?? 0) > 0 ? 'visible' : 'hidden',
264
+ }}
250
265
  >
251
266
  <Tooltip placement="right" title={localization.clearFilter ?? ''}>
252
267
  <span>
@@ -288,44 +303,23 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
288
303
  </InputAdornment>
289
304
  ) : null;
290
305
 
291
- const commonTextFieldProps: TextFieldProps = {
292
- FormHelperTextProps: {
293
- sx: {
294
- fontSize: '0.75rem',
295
- lineHeight: '0.8rem',
296
- whiteSpace: 'nowrap',
297
- },
298
- },
299
- InputProps: endAdornment //hack because mui looks for presence of endAdornment key instead of undefined
300
- ? { endAdornment, startAdornment }
301
- : { startAdornment },
306
+ const commonTextFieldProps: TextFieldProps<any> = {
302
307
  fullWidth: true,
303
308
  helperText: showChangeModeButton ? (
304
309
  <label>
305
310
  {localization.filterMode.replace(
306
311
  '{filterType}',
307
- // @ts-ignore
308
312
  localization[
309
313
  `filter${
310
314
  currentFilterOption?.charAt(0)?.toUpperCase() +
311
315
  currentFilterOption?.slice(1)
312
- }`
316
+ }` as keyof typeof localization
313
317
  ],
314
318
  )}
315
319
  </label>
316
320
  ) : null,
317
- inputProps: {
318
- 'aria-label': filterPlaceholder,
319
- autoComplete: 'off',
320
- disabled: !!filterChipLabel,
321
- sx: {
322
- textOverflow: 'ellipsis',
323
- width: filterChipLabel ? 0 : undefined,
324
- },
325
- title: filterPlaceholder,
326
- },
327
321
  inputRef: (inputRef) => {
328
- filterInputRefs.current[`${column.id}-${rangeFilterIndex ?? 0}`] =
322
+ filterInputRefs.current![`${column.id}-${rangeFilterIndex ?? 0}`] =
329
323
  inputRef;
330
324
  if (textFieldProps.inputRef) {
331
325
  textFieldProps.inputRef = inputRef;
@@ -338,6 +332,31 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
338
332
  : filterPlaceholder,
339
333
  variant: 'standard',
340
334
  ...textFieldProps,
335
+ slotProps: {
336
+ ...textFieldProps.slotProps,
337
+ formHelperText: {
338
+ sx: {
339
+ fontSize: '0.75rem',
340
+ lineHeight: '0.8rem',
341
+ whiteSpace: 'nowrap',
342
+ },
343
+ ...textFieldProps.slotProps?.formHelperText,
344
+ },
345
+ input: endAdornment //hack because mui looks for presence of endAdornment key instead of undefined
346
+ ? { endAdornment, startAdornment }
347
+ : { startAdornment },
348
+ htmlInput: {
349
+ 'aria-label': filterPlaceholder,
350
+ autoComplete: 'off',
351
+ disabled: !!filterChipLabel,
352
+ sx: {
353
+ textOverflow: 'ellipsis',
354
+ width: filterChipLabel ? 0 : undefined,
355
+ },
356
+ title: filterPlaceholder,
357
+ ...textFieldProps.slotProps?.htmlInput,
358
+ },
359
+ },
341
360
  onKeyDown: (e) => {
342
361
  e.stopPropagation();
343
362
  textFieldProps.onKeyDown?.(e);
@@ -422,28 +441,35 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
422
441
  getOptionLabel={(option: DropdownOption) =>
423
442
  getValueAndLabel(option).label
424
443
  }
425
- // @ts-ignore
426
- onChange={(_e, newValue: DropdownOption | null) =>
427
- handleAutocompleteChange(newValue)
444
+ onChange={(_e, newValue) =>
445
+ handleAutocompleteChange(newValue as DropdownOption | null)
428
446
  }
429
447
  options={
430
448
  dropdownOptions?.map((option) => getValueAndLabel(option)) ?? []
431
449
  }
450
+ inputValue={filterValue as string}
451
+ onInputChange={handleAutocompleteInputChange}
432
452
  {...autocompleteProps}
433
- renderInput={(builtinTextFieldProps) => (
453
+ renderInput={(builtinTextFieldProps: TextFieldProps) => (
434
454
  <TextField
435
- {...builtinTextFieldProps}
436
455
  {...commonTextFieldProps}
437
- InputProps={{
438
- ...builtinTextFieldProps.InputProps,
439
- startAdornment:
440
- commonTextFieldProps?.InputProps?.startAdornment,
441
- }}
442
- inputProps={{
443
- ...builtinTextFieldProps.inputProps,
444
- ...commonTextFieldProps?.inputProps,
456
+ {...builtinTextFieldProps}
457
+ slotProps={{
458
+ ...builtinTextFieldProps.slotProps,
459
+ ...commonTextFieldProps.slotProps,
460
+ input: {
461
+ ...builtinTextFieldProps.InputProps,
462
+ ...builtinTextFieldProps.slotProps?.input,
463
+ startAdornment:
464
+ //@ts-expect-error
465
+ commonTextFieldProps?.slotProps?.input?.startAdornment,
466
+ },
467
+ htmlInput: {
468
+ ...builtinTextFieldProps.inputProps,
469
+ ...builtinTextFieldProps.slotProps?.htmlInput,
470
+ ...commonTextFieldProps?.slotProps?.htmlInput,
471
+ },
445
472
  }}
446
- onChange={handleTextFieldChange}
447
473
  onClick={(e: MouseEvent<HTMLInputElement>) => e.stopPropagation()}
448
474
  />
449
475
  )}
@@ -453,31 +479,41 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
453
479
  <TextField
454
480
  select={isSelectFilter || isMultiSelectFilter}
455
481
  {...commonTextFieldProps}
456
- SelectProps={{
457
- MenuProps: { disableScrollLock: true },
458
- displayEmpty: true,
459
- multiple: isMultiSelectFilter,
460
- renderValue: isMultiSelectFilter
461
- ? (selected: any) =>
462
- !Array.isArray(selected) || selected.length === 0 ? (
463
- <Box sx={{ opacity: 0.5 }}>{filterPlaceholder}</Box>
464
- ) : (
465
- <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '2px' }}>
466
- {selected.map((value: string) => {
467
- const selectedValue = dropdownOptions?.find(
468
- (option) => getValueAndLabel(option).value === value,
469
- );
470
- return (
471
- <Chip
472
- key={value}
473
- label={getValueAndLabel(selectedValue).label}
474
- />
475
- );
476
- })}
477
- </Box>
478
- )
479
- : undefined,
480
- ...commonTextFieldProps.SelectProps,
482
+ slotProps={{
483
+ ...commonTextFieldProps.slotProps,
484
+ inputLabel: {
485
+ shrink: isSelectFilter || isMultiSelectFilter,
486
+ ...(commonTextFieldProps.slotProps?.inputLabel as any),
487
+ },
488
+ select: {
489
+ MenuProps: { disableScrollLock: true },
490
+ displayEmpty: true,
491
+ multiple: isMultiSelectFilter,
492
+ renderValue: isMultiSelectFilter
493
+ ? (selected: any) =>
494
+ !Array.isArray(selected) || selected?.length === 0 ? (
495
+ <Box sx={{ opacity: 0.5 }}>{filterPlaceholder}</Box>
496
+ ) : (
497
+ <Box
498
+ sx={{ display: 'flex', flexWrap: 'wrap', gap: '2px' }}
499
+ >
500
+ {selected.map((value: string) => {
501
+ const selectedValue = dropdownOptions?.find(
502
+ (option) =>
503
+ getValueAndLabel(option).value === value,
504
+ );
505
+ return (
506
+ <Chip
507
+ key={value}
508
+ label={getValueAndLabel(selectedValue).label}
509
+ />
510
+ );
511
+ })}
512
+ </Box>
513
+ )
514
+ : undefined,
515
+ ...commonTextFieldProps.slotProps?.select,
516
+ },
481
517
  }}
482
518
  onChange={handleTextFieldChange}
483
519
  onClick={(e: MouseEvent<HTMLInputElement>) => e.stopPropagation()}
@@ -117,7 +117,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
117
117
 
118
118
  const handleFilterByColumn = () => {
119
119
  setShowColumnFilters(true);
120
- queueMicrotask(() => filterInputRefs.current[`${column.id}-0`]?.focus());
120
+ queueMicrotask(() => filterInputRefs.current?.[`${column.id}-0`]?.focus());
121
121
  setAnchorEl(null);
122
122
  };
123
123
 
@@ -150,6 +150,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
150
150
  ? [
151
151
  enableSortingRemoval !== false && (
152
152
  <MRT_ActionMenuItem
153
+ disabled={column.getIsSorted() === false}
153
154
  icon={<ClearAllIcon />}
154
155
  key={0}
155
156
  label={localization.clearSort}
@@ -277,7 +278,7 @@ export const MRT_ColumnActionMenu = <TData extends MRT_RowData>({
277
278
  ...(enableColumnResizing && column.getCanResize()
278
279
  ? [
279
280
  <MRT_ActionMenuItem
280
- disabled={!columnSizing[column.id]}
281
+ disabled={columnSizing[column.id] === undefined}
281
282
  icon={<RestartAltIcon />}
282
283
  key={10}
283
284
  label={localization.resetColumnSize}