material-react-table 0.5.6 → 0.5.9

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 (57) hide show
  1. package/dist/MaterialReactTable.d.ts +8 -2
  2. package/dist/body/MRT_TableBodyCell.d.ts +1 -1
  3. package/dist/body/MRT_TableBodyRow.d.ts +1 -1
  4. package/dist/body/MRT_TableDetailPanel.d.ts +1 -1
  5. package/dist/buttons/MRT_EditActionButtons.d.ts +1 -1
  6. package/dist/buttons/MRT_ExpandButton.d.ts +1 -1
  7. package/dist/buttons/MRT_ToggleColumnActionMenuButton.d.ts +1 -1
  8. package/dist/buttons/MRT_ToggleRowActionMenuButton.d.ts +1 -1
  9. package/dist/enums.d.ts +12 -0
  10. package/dist/filtersFNs.d.ts +20 -0
  11. package/dist/footer/MRT_TableFooterCell.d.ts +1 -1
  12. package/dist/footer/MRT_TableFooterRow.d.ts +1 -1
  13. package/dist/head/MRT_TableHeadCell.d.ts +1 -1
  14. package/dist/head/MRT_TableHeadRow.d.ts +1 -1
  15. package/dist/inputs/MRT_EditCellTextField.d.ts +1 -1
  16. package/dist/inputs/MRT_FilterTextField.d.ts +1 -1
  17. package/dist/inputs/MRT_SelectCheckbox.d.ts +1 -1
  18. package/dist/localization.d.ts +3 -0
  19. package/dist/material-react-table.cjs.development.js +234 -68
  20. package/dist/material-react-table.cjs.development.js.map +1 -1
  21. package/dist/material-react-table.cjs.production.min.js +1 -1
  22. package/dist/material-react-table.cjs.production.min.js.map +1 -1
  23. package/dist/material-react-table.esm.js +235 -69
  24. package/dist/material-react-table.esm.js.map +1 -1
  25. package/dist/menus/MRT_ColumnActionMenu.d.ts +12 -1
  26. package/dist/menus/MRT_FilterTypeMenu.d.ts +1 -1
  27. package/dist/menus/MRT_RowActionMenu.d.ts +1 -1
  28. package/dist/menus/MRT_ShowHideColumnsMenu.d.ts +1 -1
  29. package/dist/useMRT.d.ts +1 -1
  30. package/package.json +3 -4
  31. package/src/MaterialReactTable.tsx +5 -9
  32. package/src/body/MRT_TableBody.tsx +1 -1
  33. package/src/body/MRT_TableBodyCell.tsx +1 -1
  34. package/src/body/MRT_TableBodyRow.tsx +1 -1
  35. package/src/body/MRT_TableDetailPanel.tsx +1 -1
  36. package/src/buttons/MRT_EditActionButtons.tsx +1 -1
  37. package/src/buttons/MRT_ExpandButton.tsx +1 -1
  38. package/src/buttons/MRT_ShowHideColumnsButton.tsx +1 -2
  39. package/src/buttons/MRT_ToggleColumnActionMenuButton.tsx +2 -1
  40. package/src/buttons/MRT_ToggleRowActionMenuButton.tsx +1 -1
  41. package/src/enums.ts +12 -0
  42. package/src/filtersFNs.ts +42 -0
  43. package/src/footer/MRT_TableFooter.tsx +1 -1
  44. package/src/footer/MRT_TableFooterCell.tsx +1 -1
  45. package/src/footer/MRT_TableFooterRow.tsx +1 -1
  46. package/src/head/MRT_TableHead.tsx +1 -1
  47. package/src/head/MRT_TableHeadCell.tsx +7 -16
  48. package/src/head/MRT_TableHeadRow.tsx +1 -1
  49. package/src/inputs/MRT_EditCellTextField.tsx +1 -1
  50. package/src/inputs/MRT_FilterTextField.tsx +70 -16
  51. package/src/inputs/MRT_SelectCheckbox.tsx +1 -1
  52. package/src/localization.ts +6 -0
  53. package/src/menus/MRT_ColumnActionMenu.tsx +51 -43
  54. package/src/menus/MRT_FilterTypeMenu.tsx +56 -16
  55. package/src/menus/MRT_RowActionMenu.tsx +6 -8
  56. package/src/menus/MRT_ShowHideColumnsMenu.tsx +6 -2
  57. package/src/useMRT.tsx +36 -14
@@ -1,17 +1,19 @@
1
1
  import React, { FC, useState } from 'react';
2
- import {
3
- IconButton,
4
- ListItemIcon,
5
- ListItemText,
6
- Menu,
7
- MenuItem,
8
- } from '@mui/material';
2
+ import { Box, IconButton, Menu, MenuItem } from '@mui/material';
9
3
  import { useMRT } from '../useMRT';
10
- import { MRT_HeaderGroup } from '..';
4
+ import type { MRT_HeaderGroup } from '..';
11
5
  import { MRT_FilterTypeMenu } from './MRT_FilterTypeMenu';
12
6
 
13
- const commonMenuItemStyles = {
7
+ export const commonMenuItemStyles = {
8
+ py: '6px',
9
+ my: 0,
10
+ justifyContent: 'space-between',
11
+ alignItems: 'center',
12
+ };
13
+
14
+ export const commonListItemStyles = {
14
15
  display: 'flex',
16
+ gap: '0.75rem',
15
17
  alignItems: 'center',
16
18
  };
17
19
 
@@ -36,6 +38,7 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
36
38
  ClearAllIcon,
37
39
  DynamicFeedIcon,
38
40
  FilterListIcon,
41
+ FilterListOffIcon,
39
42
  SortIcon,
40
43
  VisibilityOffIcon,
41
44
  },
@@ -73,6 +76,11 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
73
76
  setAnchorEl(null);
74
77
  };
75
78
 
79
+ const handleClearFilter = () => {
80
+ column.setFilter('');
81
+ setAnchorEl(null);
82
+ };
83
+
76
84
  const handleFilterByColumn = () => {
77
85
  setShowFilters(true);
78
86
  setTimeout(
@@ -101,23 +109,20 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
101
109
  onClose={() => setAnchorEl(null)}
102
110
  MenuListProps={{
103
111
  dense: tableInstance.state.densePadding,
104
- disablePadding: true,
105
112
  }}
106
113
  >
107
114
  {!disableSortBy &&
108
115
  column.canSort && [
109
116
  <MenuItem
110
- key={1}
111
117
  disabled={!column.isSorted}
118
+ key={1}
112
119
  onClick={handleClearSort}
113
120
  sx={commonMenuItemStyles}
114
121
  >
115
- <ListItemIcon>
122
+ <Box sx={commonListItemStyles}>
116
123
  <ClearAllIcon />
117
- </ListItemIcon>
118
- <ListItemText>
119
124
  {localization.columnActionMenuItemClearSort}
120
- </ListItemText>
125
+ </Box>
121
126
  </MenuItem>,
122
127
  <MenuItem
123
128
  disabled={column.isSorted && !column.isSortedDesc}
@@ -125,15 +130,13 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
125
130
  onClick={handleSortAsc}
126
131
  sx={commonMenuItemStyles}
127
132
  >
128
- <ListItemIcon>
133
+ <Box sx={commonListItemStyles}>
129
134
  <SortIcon />
130
- </ListItemIcon>
131
- <ListItemText>
132
135
  {localization.columnActionMenuItemSortAsc?.replace(
133
136
  '{column}',
134
137
  String(column.Header),
135
138
  )}
136
- </ListItemText>
139
+ </Box>
137
140
  </MenuItem>,
138
141
  <MenuItem
139
142
  divider={
@@ -144,42 +147,51 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
144
147
  onClick={handleSortDesc}
145
148
  sx={commonMenuItemStyles}
146
149
  >
147
- <ListItemIcon>
150
+ <Box sx={commonListItemStyles}>
148
151
  <SortIcon style={{ transform: 'rotate(180deg) scaleX(-1)' }} />
149
- </ListItemIcon>
150
- <ListItemText>
151
152
  {localization.columnActionMenuItemSortDesc?.replace(
152
153
  '{column}',
153
154
  String(column.Header),
154
155
  )}
155
- </ListItemText>
156
+ </Box>
156
157
  </MenuItem>,
157
158
  ]}
158
159
  {!disableFilters &&
159
160
  column.canFilter && [
161
+ <MenuItem
162
+ disabled={!column.filterValue}
163
+ key={0}
164
+ onClick={handleClearFilter}
165
+ sx={commonMenuItemStyles}
166
+ >
167
+ <Box sx={commonListItemStyles}>
168
+ <FilterListOffIcon />
169
+ {localization.filterTextFieldClearButtonTitle}
170
+ </Box>
171
+ </MenuItem>,
160
172
  <MenuItem
161
173
  divider={enableColumnGrouping || !disableColumnHiding}
162
174
  key={1}
163
175
  onClick={handleFilterByColumn}
164
176
  sx={commonMenuItemStyles}
165
177
  >
166
- <ListItemIcon>
178
+ <Box sx={commonListItemStyles}>
167
179
  <FilterListIcon />
168
- </ListItemIcon>
169
- <ListItemText>
170
180
  {localization.filterTextFieldPlaceholder?.replace(
171
181
  '{column}',
172
182
  String(column.Header),
173
183
  )}
174
- </ListItemText>
175
- <IconButton
176
- onClick={handleOpenFilterModeMenu}
177
- onMouseEnter={handleOpenFilterModeMenu}
178
- size="small"
179
- sx={{ p: 0 }}
180
- >
181
- <ArrowRightIcon />
182
- </IconButton>
184
+ </Box>
185
+ {!column.filterSelectOptions && (
186
+ <IconButton
187
+ onClick={handleOpenFilterModeMenu}
188
+ onMouseEnter={handleOpenFilterModeMenu}
189
+ size="small"
190
+ sx={{ p: 0 }}
191
+ >
192
+ <ArrowRightIcon />
193
+ </IconButton>
194
+ )}
183
195
  </MenuItem>,
184
196
  <MRT_FilterTypeMenu
185
197
  anchorEl={filterMenuAnchorEl}
@@ -197,29 +209,25 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
197
209
  onClick={handleGroupByColumn}
198
210
  sx={commonMenuItemStyles}
199
211
  >
200
- <ListItemIcon>
212
+ <Box sx={commonListItemStyles}>
201
213
  <DynamicFeedIcon />
202
- </ListItemIcon>
203
- <ListItemText>
204
214
  {localization[
205
215
  column.isGrouped
206
216
  ? 'columnActionMenuItemUnGroupBy'
207
217
  : 'columnActionMenuItemGroupBy'
208
218
  ]?.replace('{column}', String(column.Header))}
209
- </ListItemText>
219
+ </Box>
210
220
  </MenuItem>,
211
221
  ]}
212
222
  {!disableColumnHiding && [
213
223
  <MenuItem key={1} onClick={handleHideColumn} sx={commonMenuItemStyles}>
214
- <ListItemIcon>
224
+ <Box sx={commonListItemStyles}>
215
225
  <VisibilityOffIcon />
216
- </ListItemIcon>
217
- <ListItemText>
218
226
  {localization.columnActionMenuItemHideColumn?.replace(
219
227
  '{column}',
220
228
  String(column.Header),
221
229
  )}
222
- </ListItemText>
230
+ </Box>
223
231
  </MenuItem>,
224
232
  ]}
225
233
  </Menu>
@@ -1,7 +1,26 @@
1
1
  import React, { FC, useMemo } from 'react';
2
2
  import { Menu, MenuItem } from '@mui/material';
3
3
  import { useMRT } from '../useMRT';
4
- import { MRT_FilterType, MRT_HeaderGroup } from '..';
4
+ import type { MRT_FilterType, MRT_HeaderGroup } from '..';
5
+ import { MRT_FILTER_TYPE } from '../enums';
6
+ import {
7
+ containsFilterFN,
8
+ emptyFilterFN,
9
+ endsWithFilterFN,
10
+ equalsFilterFN,
11
+ fuzzyFilterFN,
12
+ greaterThanFilterFN,
13
+ lessThanFilterFN,
14
+ notEmptyFilterFN,
15
+ notEqualsFilterFN,
16
+ startsWithFilterFN,
17
+ } from '../filtersFNs';
18
+
19
+ const commonMenuItemStyles = {
20
+ py: '6px',
21
+ my: 0,
22
+ alignItems: 'center',
23
+ };
5
24
 
6
25
  interface Props {
7
26
  anchorEl: HTMLElement | null;
@@ -19,62 +38,83 @@ export const MRT_FilterTypeMenu: FC<Props> = ({
19
38
  const { localization, setCurrentFilterTypes, tableInstance } = useMRT();
20
39
 
21
40
  const filterTypes: {
22
- type: MRT_FilterType;
41
+ type: MRT_FILTER_TYPE;
23
42
  label: string;
24
43
  divider: boolean;
44
+ fn: Function;
25
45
  }[] = useMemo(
26
46
  () => [
27
47
  {
28
- type: 'fuzzy',
48
+ type: MRT_FILTER_TYPE.FUZZY,
29
49
  label: localization.filterMenuItemFuzzy,
30
50
  divider: false,
51
+ fn: fuzzyFilterFN,
31
52
  },
32
53
  {
33
- type: 'contains',
54
+ type: MRT_FILTER_TYPE.CONTAINS,
34
55
  label: localization.filterMenuItemContains,
35
56
  divider: true,
57
+ fn: containsFilterFN,
36
58
  },
37
59
  {
38
- type: 'startsWith',
60
+ type: MRT_FILTER_TYPE.STARTS_WITH,
39
61
  label: localization.filterMenuItemStartsWith,
40
62
  divider: false,
63
+ fn: startsWithFilterFN,
41
64
  },
42
65
  {
43
- type: 'endsWith',
66
+ type: MRT_FILTER_TYPE.ENDS_WITH,
44
67
  label: localization.filterMenuItemEndsWith,
45
68
  divider: true,
69
+ fn: endsWithFilterFN,
46
70
  },
47
71
  {
48
- type: 'equals',
72
+ type: MRT_FILTER_TYPE.EQUALS,
49
73
  label: localization.filterMenuItemEquals,
50
74
  divider: false,
75
+ fn: equalsFilterFN,
51
76
  },
52
77
  {
53
- type: 'notEquals',
78
+ type: MRT_FILTER_TYPE.NOT_EQUALS,
54
79
  label: localization.filterMenuItemNotEquals,
55
80
  divider: true,
81
+ fn: notEqualsFilterFN,
82
+ },
83
+ {
84
+ type: MRT_FILTER_TYPE.GREATER_THAN,
85
+ label: localization.filterMenuItemGreaterThan,
86
+ divider: false,
87
+ fn: greaterThanFilterFN,
88
+ },
89
+ {
90
+ type: MRT_FILTER_TYPE.LESS_THAN,
91
+ label: localization.filterMenuItemLessThan,
92
+ divider: true,
93
+ fn: lessThanFilterFN,
56
94
  },
57
95
  {
58
- type: 'empty',
96
+ type: MRT_FILTER_TYPE.EMPTY,
59
97
  label: localization.filterMenuItemEmpty,
60
98
  divider: false,
99
+ fn: emptyFilterFN,
61
100
  },
62
101
  {
63
- type: 'notEmpty',
102
+ type: MRT_FILTER_TYPE.NOT_EMPTY,
64
103
  label: localization.filterMenuItemNotEmpty,
65
104
  divider: false,
105
+ fn: notEmptyFilterFN,
66
106
  },
67
107
  ],
68
108
  [],
69
109
  );
70
110
 
71
- const handleSelectFilterType = (value: MRT_FilterType) => {
111
+ const handleSelectFilterType = (value: MRT_FILTER_TYPE) => {
72
112
  setAnchorEl(null);
73
113
  setCurrentFilterTypes((prev: { [key: string]: MRT_FilterType }) => ({
74
114
  ...prev,
75
115
  [column.id]: value,
76
116
  }));
77
- if (['empty', 'notEmpty'].includes(value)) {
117
+ if ([MRT_FILTER_TYPE.EMPTY, MRT_FILTER_TYPE.NOT_EMPTY].includes(value)) {
78
118
  column.setFilter(' ');
79
119
  }
80
120
  onSelect?.();
@@ -90,15 +130,15 @@ export const MRT_FilterTypeMenu: FC<Props> = ({
90
130
  open={!!anchorEl}
91
131
  MenuListProps={{
92
132
  dense: tableInstance.state.densePadding,
93
- disablePadding: true,
94
133
  }}
95
134
  >
96
- {filterTypes.map(({ type, label, divider }) => (
135
+ {filterTypes.map(({ type, label, divider, fn }, index) => (
97
136
  <MenuItem
98
137
  divider={divider}
99
- key={type}
138
+ key={index}
100
139
  onClick={() => handleSelectFilterType(type)}
101
- selected={type === filterType}
140
+ selected={type === filterType || fn === filterType}
141
+ sx={commonMenuItemStyles}
102
142
  value={type}
103
143
  >
104
144
  {label}
@@ -1,7 +1,8 @@
1
1
  import React, { FC } from 'react';
2
- import { ListItemIcon, ListItemText, Menu, MenuItem } from '@mui/material';
2
+ import { Menu, MenuItem } from '@mui/material';
3
3
  import { useMRT } from '../useMRT';
4
- import { MRT_Row } from '..';
4
+ import type { MRT_Row } from '..';
5
+ import { commonMenuItemStyles } from './MRT_ColumnActionMenu';
5
6
 
6
7
  interface Props {
7
8
  anchorEl: HTMLElement | null;
@@ -31,15 +32,12 @@ export const MRT_RowActionMenu: FC<Props> = ({
31
32
  onClose={() => setAnchorEl(null)}
32
33
  MenuListProps={{
33
34
  dense: tableInstance.state.densePadding,
34
- disablePadding: true,
35
35
  }}
36
36
  >
37
37
  {enableRowEditing && (
38
- <MenuItem onClick={handleEdit}>
39
- <ListItemIcon>
40
- <EditIcon />
41
- </ListItemIcon>
42
- <ListItemText>{localization.rowActionMenuItemEdit}</ListItemText>
38
+ <MenuItem onClick={handleEdit} sx={commonMenuItemStyles}>
39
+ <EditIcon />
40
+ {localization.rowActionMenuItemEdit}
43
41
  </MenuItem>
44
42
  )}
45
43
  {renderRowActionMenuItems?.(row, tableInstance, () =>
@@ -1,7 +1,8 @@
1
1
  import React, { FC } from 'react';
2
2
  import { FormControlLabel, MenuItem, Switch } from '@mui/material';
3
3
  import { ColumnInstance } from 'react-table';
4
- import { MRT_ColumnInstance } from '..';
4
+ import type { MRT_ColumnInstance } from '..';
5
+ import { commonMenuItemStyles } from './MRT_ColumnActionMenu';
5
6
 
6
7
  interface Props {
7
8
  column: MRT_ColumnInstance;
@@ -28,8 +29,11 @@ export const MRT_ShowHideColumnsMenu: FC<Props> = ({ column }) => {
28
29
 
29
30
  return (
30
31
  <>
31
- <MenuItem sx={{ pl: `${(column.depth + 0.5) * 2}rem` }}>
32
+ <MenuItem
33
+ sx={{ ...commonMenuItemStyles, pl: `${(column.depth + 0.5) * 2}rem` }}
34
+ >
32
35
  <FormControlLabel
36
+ componentsProps={{ typography: { sx: { marginBottom: 0 } } }}
33
37
  checked={switchChecked}
34
38
  control={<Switch />}
35
39
  label={column.Header as string}
package/src/useMRT.tsx CHANGED
@@ -21,7 +21,8 @@ import {
21
21
  useSortBy,
22
22
  useTable,
23
23
  } from 'react-table';
24
- import { MRT_FilterType, MRT_Row, MRT_TableInstance } from '.';
24
+ import type { MRT_FilterType, MRT_Row, MRT_TableInstance } from '.';
25
+ import { MRT_FILTER_TYPE } from './enums';
25
26
  import { defaultFilterFNs } from './filtersFNs';
26
27
  import { MRT_Icons } from './icons';
27
28
  import { MRT_Localization } from './localization';
@@ -81,7 +82,9 @@ export const MaterialReactTableProvider = <D extends {} = {}>(
81
82
  props.initialState?.showSearch ?? false,
82
83
  );
83
84
 
84
- const filterTypes = useMemo<Partial<{ [key in MRT_FilterType]: any }>>(
85
+ const filterTypes = useMemo<{
86
+ [key in MRT_FILTER_TYPE]: any;
87
+ }>(
85
88
  () => ({
86
89
  ...defaultFilterFNs,
87
90
  ...props.filterTypes,
@@ -89,25 +92,43 @@ export const MaterialReactTableProvider = <D extends {} = {}>(
89
92
  [props.filterTypes],
90
93
  );
91
94
 
95
+ const getInitialFilterTypeState = () => {
96
+ let lowestLevelColumns: any[] = props.columns;
97
+ let currentCols: any[] = props.columns;
98
+ while (!!currentCols.length && currentCols.some((col) => col.columns)) {
99
+ const nextCols = currentCols
100
+ .filter((col) => !!col.columns)
101
+ .map((col) => col.columns)
102
+ .flat();
103
+ if (nextCols.every((col) => !col.columns)) {
104
+ lowestLevelColumns = [...lowestLevelColumns, ...nextCols];
105
+ }
106
+ currentCols = nextCols;
107
+ }
108
+ lowestLevelColumns = lowestLevelColumns.filter((col) => !col.columns);
109
+
110
+ return Object.assign(
111
+ {},
112
+ ...lowestLevelColumns.map((c) => ({
113
+ [c.accessor as string]:
114
+ c.filter ??
115
+ props?.initialState?.filters?.[c.accessor as any] ??
116
+ (!!c.filterSelectOptions ? 'equals' : 'fuzzy'),
117
+ })),
118
+ );
119
+ };
120
+
92
121
  const [currentFilterTypes, setCurrentFilterTypes] = useState<{
93
122
  [key: string]: MRT_FilterType;
94
- }>(() =>
95
- Object.assign(
96
- {},
97
- ...props.columns
98
- .map((c) => c.accessor?.toString() as string)
99
- .map((accessor) => ({
100
- [accessor]:
101
- props?.initialState?.filters?.[accessor as any] ?? 'fuzzy',
102
- })),
103
- ),
104
- );
123
+ }>(() => getInitialFilterTypeState());
105
124
 
106
125
  const columns = useMemo(
107
126
  () =>
108
127
  props.columns.map((column) => {
109
128
  column.filter =
110
- filterTypes[currentFilterTypes[column.accessor as string]];
129
+ filterTypes[
130
+ currentFilterTypes[column.accessor as string] as MRT_FILTER_TYPE
131
+ ];
111
132
  return column;
112
133
  }),
113
134
  [props.columns, filterTypes, currentFilterTypes],
@@ -119,6 +140,7 @@ export const MaterialReactTableProvider = <D extends {} = {}>(
119
140
  columns,
120
141
  // @ts-ignore
121
142
  filterTypes,
143
+ globalFilterValue: 'fuzzy',
122
144
  useControlledState: (state) =>
123
145
  useMemo(
124
146
  () => ({