material-react-table 0.5.3 → 0.5.6

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 (35) hide show
  1. package/dist/MaterialReactTable.d.ts +8 -1
  2. package/dist/filtersFNs.d.ts +67 -0
  3. package/dist/icons.d.ts +3 -0
  4. package/dist/localization.d.ts +14 -1
  5. package/dist/material-react-table.cjs.development.js +447 -81
  6. package/dist/material-react-table.cjs.development.js.map +1 -1
  7. package/dist/material-react-table.cjs.production.min.js +1 -1
  8. package/dist/material-react-table.cjs.production.min.js.map +1 -1
  9. package/dist/material-react-table.esm.js +448 -82
  10. package/dist/material-react-table.esm.js.map +1 -1
  11. package/dist/menus/MRT_FilterTypeMenu.d.ts +10 -0
  12. package/dist/useMRT.d.ts +13 -9
  13. package/package.json +9 -5
  14. package/src/MaterialReactTable.tsx +23 -1
  15. package/src/body/MRT_TableBodyCell.tsx +12 -3
  16. package/src/buttons/MRT_EditActionButtons.tsx +3 -1
  17. package/src/buttons/MRT_ShowHideColumnsButton.tsx +7 -3
  18. package/src/buttons/MRT_ToggleColumnActionMenuButton.tsx +4 -3
  19. package/src/buttons/MRT_ToggleFiltersButton.tsx +3 -1
  20. package/src/buttons/MRT_ToggleSearchButton.tsx +5 -2
  21. package/src/filtersFNs.ts +112 -0
  22. package/src/footer/MRT_TableFooterCell.tsx +1 -1
  23. package/src/head/MRT_TableHeadCell.tsx +91 -44
  24. package/src/{icons.tsx → icons.ts} +9 -0
  25. package/src/index.tsx +0 -2
  26. package/src/inputs/MRT_FilterTextField.tsx +121 -52
  27. package/src/inputs/MRT_SearchTextField.tsx +2 -1
  28. package/src/inputs/MRT_SelectCheckbox.tsx +5 -7
  29. package/src/localization.ts +30 -4
  30. package/src/menus/MRT_ColumnActionMenu.tsx +103 -39
  31. package/src/menus/MRT_FilterTypeMenu.tsx +109 -0
  32. package/src/menus/MRT_RowActionMenu.tsx +10 -3
  33. package/src/menus/MRT_ShowHideColumnsMenu.tsx +1 -1
  34. package/src/table/MRT_TableContainer.tsx +7 -1
  35. package/src/useMRT.tsx +67 -13
@@ -1,8 +1,16 @@
1
- import React, { ChangeEvent, FC, useState } from 'react';
2
- import { IconButton, InputAdornment, TextField, Tooltip } from '@mui/material';
1
+ import React, { ChangeEvent, FC, MouseEvent, useState } from 'react';
2
+ import {
3
+ Chip,
4
+ IconButton,
5
+ InputAdornment,
6
+ TextField,
7
+ TextFieldProps,
8
+ Tooltip,
9
+ } from '@mui/material';
3
10
  import { useAsyncDebounce } from 'react-table';
4
11
  import { useMRT } from '../useMRT';
5
12
  import { MRT_HeaderGroup } from '..';
13
+ import { MRT_FilterTypeMenu } from '../menus/MRT_FilterTypeMenu';
6
14
 
7
15
  interface Props {
8
16
  column: MRT_HeaderGroup;
@@ -11,79 +19,140 @@ interface Props {
11
19
  export const MRT_FilterTextField: FC<Props> = ({ column }) => {
12
20
  const {
13
21
  icons: { FilterListIcon, CloseIcon },
22
+ idPrefix,
14
23
  localization,
24
+ muiTableHeadCellFilterTextFieldProps,
25
+ setCurrentFilterTypes,
26
+ tableInstance,
15
27
  } = useMRT();
16
28
 
29
+ const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
30
+
31
+ const mTableHeadCellFilterTextFieldProps =
32
+ muiTableHeadCellFilterTextFieldProps instanceof Function
33
+ ? muiTableHeadCellFilterTextFieldProps(column)
34
+ : muiTableHeadCellFilterTextFieldProps;
35
+
36
+ const mcTableHeadCellFilterTextFieldProps =
37
+ column.muiTableHeadCellFilterTextFieldProps instanceof Function
38
+ ? column.muiTableHeadCellFilterTextFieldProps(column)
39
+ : column.muiTableHeadCellFilterTextFieldProps;
40
+
41
+ const textFieldProps = {
42
+ ...mTableHeadCellFilterTextFieldProps,
43
+ ...mcTableHeadCellFilterTextFieldProps,
44
+ style: {
45
+ ...mTableHeadCellFilterTextFieldProps?.style,
46
+ ...mcTableHeadCellFilterTextFieldProps?.style,
47
+ },
48
+ } as TextFieldProps;
49
+
17
50
  const [filterValue, setFilterValue] = useState('');
18
51
 
19
52
  const handleChange = useAsyncDebounce((value) => {
20
53
  column.setFilter(value ?? undefined);
21
54
  }, 150);
22
55
 
56
+ const handleFilterMenuOpen = (event: MouseEvent<HTMLElement>) => {
57
+ setAnchorEl(event.currentTarget);
58
+ };
59
+
23
60
  const handleClear = () => {
24
61
  setFilterValue('');
25
62
  column.setFilter(undefined);
26
63
  };
27
64
 
65
+ const handleClearFilterChip = () => {
66
+ setFilterValue('');
67
+ column.setFilter(undefined);
68
+ setCurrentFilterTypes((prev) => ({ ...prev, [column.id]: 'fuzzy' }));
69
+ };
70
+
28
71
  if (column.Filter) {
29
72
  return <>{column.Filter?.({ column })}</>;
30
73
  }
31
74
 
75
+ const filterType = tableInstance.state.currentFilterTypes[column.id];
76
+ const filterChipLabel = ['empty', 'notEmpty'].includes(filterType);
77
+ const filterPlaceholder = localization.filterTextFieldPlaceholder?.replace(
78
+ '{column}',
79
+ String(column.Header),
80
+ );
81
+
32
82
  return (
33
- <TextField
34
- fullWidth
35
- id={`filter-${column.id}-column`}
36
- inputProps={{
37
- style: {
38
- textOverflow: 'ellipsis',
39
- },
40
- }}
41
- margin="dense"
42
- placeholder={localization.filterTextFieldPlaceholder?.replace(
43
- '{column}',
44
- String(column.Header),
45
- )}
46
- onChange={(e: ChangeEvent<HTMLInputElement>) => {
47
- setFilterValue(e.target.value);
48
- handleChange(e.target.value);
49
- }}
50
- onClick={(e) => e.stopPropagation()}
51
- value={filterValue ?? ''}
52
- variant="standard"
53
- InputProps={{
54
- startAdornment: (
55
- <Tooltip
56
- arrow
57
- title={localization.filterTextFieldPlaceholder?.replace(
58
- '{column}',
59
- String(column.Header),
60
- )}
61
- >
83
+ <>
84
+ <TextField
85
+ fullWidth
86
+ id={`mrt-${idPrefix}-${column.id}-filter-text-field`}
87
+ inputProps={{
88
+ disabled: !!filterChipLabel,
89
+ sx: {
90
+ textOverflow: 'ellipsis',
91
+ width: filterChipLabel ? 0 : undefined,
92
+ },
93
+ title: filterPlaceholder,
94
+ }}
95
+ margin="none"
96
+ placeholder={filterChipLabel ? '' : filterPlaceholder}
97
+ onChange={(e: ChangeEvent<HTMLInputElement>) => {
98
+ setFilterValue(e.target.value);
99
+ handleChange(e.target.value);
100
+ }}
101
+ onClick={(e) => e.stopPropagation()}
102
+ value={filterValue ?? ''}
103
+ variant="standard"
104
+ InputProps={{
105
+ startAdornment: (
62
106
  <InputAdornment position="start">
63
- <FilterListIcon />
64
- </InputAdornment>
65
- </Tooltip>
66
- ),
67
- endAdornment: (
68
- <InputAdornment position="end">
69
- <Tooltip
70
- arrow
71
- title={localization.filterTextFieldClearButtonTitle ?? ''}
72
- >
73
- <span>
107
+ <Tooltip arrow title="Change Filter Mode">
74
108
  <IconButton
75
- aria-label={localization.filterTextFieldClearButtonTitle}
76
- disabled={filterValue?.length === 0}
77
- onClick={handleClear}
109
+ onClick={handleFilterMenuOpen}
78
110
  size="small"
111
+ sx={{ height: '1.75rem', width: '1.75rem' }}
79
112
  >
80
- <CloseIcon fontSize="small" />
113
+ <FilterListIcon />
81
114
  </IconButton>
82
- </span>
83
- </Tooltip>
84
- </InputAdornment>
85
- ),
86
- }}
87
- />
115
+ </Tooltip>
116
+ {filterChipLabel && (
117
+ <Chip onDelete={handleClearFilterChip} label={filterType} />
118
+ )}
119
+ </InputAdornment>
120
+ ),
121
+ endAdornment: !filterChipLabel && (
122
+ <InputAdornment position="end">
123
+ <Tooltip
124
+ arrow
125
+ placement="right"
126
+ title={localization.filterTextFieldClearButtonTitle ?? ''}
127
+ >
128
+ <span>
129
+ <IconButton
130
+ aria-label={localization.filterTextFieldClearButtonTitle}
131
+ disabled={filterValue?.length === 0}
132
+ onClick={handleClear}
133
+ size="small"
134
+ sx={{ height: '1.75rem', width: '1.75rem' }}
135
+ >
136
+ <CloseIcon fontSize="small" />
137
+ </IconButton>
138
+ </span>
139
+ </Tooltip>
140
+ </InputAdornment>
141
+ ),
142
+ }}
143
+ {...textFieldProps}
144
+ sx={{
145
+ m: '0 -0.25rem',
146
+ minWidth: !filterChipLabel ? '5rem' : 'auto',
147
+ width: 'calc(100% + 0.5rem)',
148
+ ...textFieldProps?.sx,
149
+ }}
150
+ />
151
+ <MRT_FilterTypeMenu
152
+ anchorEl={anchorEl}
153
+ column={column}
154
+ setAnchorEl={setAnchorEl}
155
+ />
156
+ </>
88
157
  );
89
158
  };
@@ -8,6 +8,7 @@ interface Props {}
8
8
  export const MRT_SearchTextField: FC<Props> = () => {
9
9
  const {
10
10
  icons: { SearchIcon, CloseIcon },
11
+ idPrefix,
11
12
  localization,
12
13
  muiSearchTextFieldProps,
13
14
  onGlobalFilterChange,
@@ -32,7 +33,7 @@ export const MRT_SearchTextField: FC<Props> = () => {
32
33
  return (
33
34
  <Collapse in={tableInstance.state.showSearch} orientation="horizontal">
34
35
  <TextField
35
- id="global-search-text-field"
36
+ id={`mrt-${idPrefix}-search-text-field`}
36
37
  placeholder={localization.searchTextFieldPlaceholder}
37
38
  onChange={(event: ChangeEvent<HTMLInputElement>) => {
38
39
  setSearchValue(event.target.value);
@@ -10,12 +10,8 @@ interface Props {
10
10
  }
11
11
 
12
12
  export const MRT_SelectCheckbox: FC<Props> = ({ row, selectAll }) => {
13
- const {
14
- localization,
15
- onRowSelectChange,
16
- onSelectAllChange,
17
- tableInstance,
18
- } = useMRT();
13
+ const { localization, onRowSelectChange, onSelectAllChange, tableInstance } =
14
+ useMRT();
19
15
 
20
16
  const onSelectChange = (event: ChangeEvent<HTMLInputElement>) => {
21
17
  if (selectAll) {
@@ -32,7 +28,9 @@ export const MRT_SelectCheckbox: FC<Props> = ({ row, selectAll }) => {
32
28
  : row?.getToggleRowSelectedProps();
33
29
 
34
30
  return (
35
- <TableCell sx={commonTableBodyButtonCellStyles(tableInstance.state.densePadding)} >
31
+ <TableCell
32
+ sx={commonTableBodyButtonCellStyles(tableInstance.state.densePadding)}
33
+ >
36
34
  <Tooltip
37
35
  arrow
38
36
  enterDelay={1000}
@@ -11,6 +11,19 @@ export interface MRT_Localization {
11
11
  columnShowHideMenuShowAll: string;
12
12
  expandAllButtonTitle: string;
13
13
  expandButtonTitle: string;
14
+ filterApplied: string;
15
+ filterMenuItemContains: string;
16
+ filterMenuItemEmpty: string;
17
+ filterMenuItemEndsWith: string;
18
+ filterMenuItemEquals: string;
19
+ filterMenuItemFuzzy: string;
20
+ filterMenuItemNotEmpty: string;
21
+ filterMenuItemNotEquals: string;
22
+ filterMenuItemStartsWith: string;
23
+ filterMenuTitle: string;
24
+ filterTextFieldChangeFilterButtonTitle: string;
25
+ filterTextFieldChipLabelEmpty: string;
26
+ filterTextFieldChipLabelNotEmpty: string;
14
27
  filterTextFieldClearButtonTitle: string;
15
28
  filterTextFieldPlaceholder: string;
16
29
  rowActionButtonCancel: string;
@@ -27,9 +40,9 @@ export interface MRT_Localization {
27
40
  toggleFilterButtonTitle: string;
28
41
  toggleFullScreenButtonTitle: string;
29
42
  toggleSearchButtonTitle: string;
30
- toolbarAlertSelectionMessage: string;
31
43
  toolbarAlertGroupedByMessage: string;
32
44
  toolbarAlertGroupedThenByMessage: string;
45
+ toolbarAlertSelectionMessage: string;
33
46
  }
34
47
 
35
48
  export const MRT_DefaultLocalization_EN: MRT_Localization = {
@@ -45,6 +58,19 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
45
58
  columnShowHideMenuShowAll: 'Show all',
46
59
  expandAllButtonTitle: 'Expand all',
47
60
  expandButtonTitle: 'Expand',
61
+ filterApplied: 'Filtering by {column} - ({filterType})',
62
+ filterMenuItemContains: 'Contains Exact',
63
+ filterMenuItemEmpty: 'Empty',
64
+ filterMenuItemEndsWith: 'Ends With',
65
+ filterMenuItemEquals: 'Equals',
66
+ filterMenuItemFuzzy: 'Fuzzy Match (Default)',
67
+ filterMenuItemNotEmpty: 'Not Empty',
68
+ filterMenuItemNotEquals: 'Not Equals',
69
+ filterMenuItemStartsWith: 'Starts With',
70
+ filterMenuTitle: 'Filter Mode',
71
+ filterTextFieldChangeFilterButtonTitle: 'Change Filter Mode',
72
+ filterTextFieldChipLabelEmpty: 'Empty',
73
+ filterTextFieldChipLabelNotEmpty: 'Not Empty',
48
74
  filterTextFieldClearButtonTitle: 'Clear filter',
49
75
  filterTextFieldPlaceholder: 'Filter by {column}',
50
76
  rowActionButtonCancel: 'Cancel',
@@ -58,10 +84,10 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
58
84
  selectCheckboxTitle: 'Toggle select row',
59
85
  showHideColumnsButtonTitle: 'Show/Hide columns',
60
86
  toggleDensePaddingSwitchTitle: 'Toggle dense padding',
61
- toggleFilterButtonTitle: 'Toggle filters',
87
+ toggleFilterButtonTitle: 'Show/Hide filters',
62
88
  toggleFullScreenButtonTitle: 'Toggle full screen',
63
- toggleSearchButtonTitle: 'Toggle search',
64
- toolbarAlertSelectionMessage: '{selectedCount} of {rowCount} row(s) selected',
89
+ toggleSearchButtonTitle: 'Show/Hide search',
65
90
  toolbarAlertGroupedByMessage: 'Grouped by ',
66
91
  toolbarAlertGroupedThenByMessage: ', then by ',
92
+ toolbarAlertSelectionMessage: '{selectedCount} of {rowCount} row(s) selected',
67
93
  };
@@ -1,11 +1,18 @@
1
- import React, { FC } from 'react';
2
- import { Divider, Menu, MenuItem } from '@mui/material';
1
+ import React, { FC, useState } from 'react';
2
+ import {
3
+ IconButton,
4
+ ListItemIcon,
5
+ ListItemText,
6
+ Menu,
7
+ MenuItem,
8
+ } from '@mui/material';
3
9
  import { useMRT } from '../useMRT';
4
10
  import { MRT_HeaderGroup } from '..';
11
+ import { MRT_FilterTypeMenu } from './MRT_FilterTypeMenu';
5
12
 
6
13
  const commonMenuItemStyles = {
7
14
  display: 'flex',
8
- gap: '0.75rem',
15
+ alignItems: 'center',
9
16
  };
10
17
 
11
18
  interface Props {
@@ -24,17 +31,23 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
24
31
  disableFilters,
25
32
  disableSortBy,
26
33
  enableColumnGrouping,
27
- localization,
28
- setShowFilters,
29
34
  icons: {
30
- FilterListIcon,
31
- SortIcon,
35
+ ArrowRightIcon,
32
36
  ClearAllIcon,
33
37
  DynamicFeedIcon,
38
+ FilterListIcon,
39
+ SortIcon,
34
40
  VisibilityOffIcon,
35
41
  },
42
+ idPrefix,
43
+ localization,
44
+ setShowFilters,
45
+ tableInstance,
36
46
  } = useMRT();
37
47
 
48
+ const [filterMenuAnchorEl, setFilterMenuAnchorEl] =
49
+ useState<null | HTMLElement>(null);
50
+
38
51
  const handleClearSort = () => {
39
52
  column.clearSortBy();
40
53
  setAnchorEl(null);
@@ -68,7 +81,7 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
68
81
  .getElementById(
69
82
  // @ts-ignore
70
83
  column.muiTableHeadCellFilterTextFieldProps?.id ??
71
- `filter-${column.id}-column`,
84
+ `mrt-${idPrefix}-${column.id}-filter-text-field`,
72
85
  )
73
86
  ?.focus(),
74
87
  200,
@@ -76,11 +89,20 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
76
89
  setAnchorEl(null);
77
90
  };
78
91
 
92
+ const handleOpenFilterModeMenu = (event: React.MouseEvent<HTMLElement>) => {
93
+ event.stopPropagation();
94
+ setFilterMenuAnchorEl(event.currentTarget);
95
+ };
96
+
79
97
  return (
80
98
  <Menu
81
99
  anchorEl={anchorEl}
82
100
  open={!!anchorEl}
83
101
  onClose={() => setAnchorEl(null)}
102
+ MenuListProps={{
103
+ dense: tableInstance.state.densePadding,
104
+ disablePadding: true,
105
+ }}
84
106
  >
85
107
  {!disableSortBy &&
86
108
  column.canSort && [
@@ -90,72 +112,114 @@ export const MRT_ColumnActionMenu: FC<Props> = ({
90
112
  onClick={handleClearSort}
91
113
  sx={commonMenuItemStyles}
92
114
  >
93
- <ClearAllIcon /> {localization.columnActionMenuItemClearSort}
115
+ <ListItemIcon>
116
+ <ClearAllIcon />
117
+ </ListItemIcon>
118
+ <ListItemText>
119
+ {localization.columnActionMenuItemClearSort}
120
+ </ListItemText>
94
121
  </MenuItem>,
95
122
  <MenuItem
96
- key={2}
97
123
  disabled={column.isSorted && !column.isSortedDesc}
124
+ key={2}
98
125
  onClick={handleSortAsc}
99
126
  sx={commonMenuItemStyles}
100
127
  >
101
- <SortIcon />{' '}
102
- {localization.columnActionMenuItemSortAsc?.replace(
103
- '{column}',
104
- String(column.Header),
105
- )}
128
+ <ListItemIcon>
129
+ <SortIcon />
130
+ </ListItemIcon>
131
+ <ListItemText>
132
+ {localization.columnActionMenuItemSortAsc?.replace(
133
+ '{column}',
134
+ String(column.Header),
135
+ )}
136
+ </ListItemText>
106
137
  </MenuItem>,
107
138
  <MenuItem
139
+ divider={
140
+ !disableFilters || enableColumnGrouping || !disableColumnHiding
141
+ }
108
142
  key={3}
109
143
  disabled={column.isSorted && column.isSortedDesc}
110
144
  onClick={handleSortDesc}
111
145
  sx={commonMenuItemStyles}
112
146
  >
113
- <SortIcon style={{ transform: 'rotate(180deg) scaleX(-1)' }} />{' '}
114
- {localization.columnActionMenuItemSortDesc?.replace(
115
- '{column}',
116
- String(column.Header),
117
- )}
147
+ <ListItemIcon>
148
+ <SortIcon style={{ transform: 'rotate(180deg) scaleX(-1)' }} />
149
+ </ListItemIcon>
150
+ <ListItemText>
151
+ {localization.columnActionMenuItemSortDesc?.replace(
152
+ '{column}',
153
+ String(column.Header),
154
+ )}
155
+ </ListItemText>
118
156
  </MenuItem>,
119
157
  ]}
120
158
  {!disableFilters &&
121
159
  column.canFilter && [
122
- <Divider key={0} />,
123
160
  <MenuItem
161
+ divider={enableColumnGrouping || !disableColumnHiding}
124
162
  key={1}
125
163
  onClick={handleFilterByColumn}
126
164
  sx={commonMenuItemStyles}
127
165
  >
128
- <FilterListIcon />{' '}
129
- {localization.filterTextFieldPlaceholder?.replace(
130
- '{column}',
131
- String(column.Header),
132
- )}
166
+ <ListItemIcon>
167
+ <FilterListIcon />
168
+ </ListItemIcon>
169
+ <ListItemText>
170
+ {localization.filterTextFieldPlaceholder?.replace(
171
+ '{column}',
172
+ String(column.Header),
173
+ )}
174
+ </ListItemText>
175
+ <IconButton
176
+ onClick={handleOpenFilterModeMenu}
177
+ onMouseEnter={handleOpenFilterModeMenu}
178
+ size="small"
179
+ sx={{ p: 0 }}
180
+ >
181
+ <ArrowRightIcon />
182
+ </IconButton>
133
183
  </MenuItem>,
184
+ <MRT_FilterTypeMenu
185
+ anchorEl={filterMenuAnchorEl}
186
+ column={column}
187
+ key={2}
188
+ setAnchorEl={setFilterMenuAnchorEl}
189
+ onSelect={handleFilterByColumn}
190
+ />,
134
191
  ]}
135
192
  {enableColumnGrouping &&
136
193
  column.canGroupBy && [
137
- <Divider key={1} />,
138
194
  <MenuItem
195
+ divider={!disableColumnHiding}
139
196
  key={2}
140
197
  onClick={handleGroupByColumn}
141
198
  sx={commonMenuItemStyles}
142
199
  >
143
- <DynamicFeedIcon />{' '}
144
- {localization[
145
- column.isGrouped
146
- ? 'columnActionMenuItemUnGroupBy'
147
- : 'columnActionMenuItemGroupBy'
148
- ]?.replace('{column}', String(column.Header))}
200
+ <ListItemIcon>
201
+ <DynamicFeedIcon />
202
+ </ListItemIcon>
203
+ <ListItemText>
204
+ {localization[
205
+ column.isGrouped
206
+ ? 'columnActionMenuItemUnGroupBy'
207
+ : 'columnActionMenuItemGroupBy'
208
+ ]?.replace('{column}', String(column.Header))}
209
+ </ListItemText>
149
210
  </MenuItem>,
150
211
  ]}
151
212
  {!disableColumnHiding && [
152
- <Divider key={0} />,
153
213
  <MenuItem key={1} onClick={handleHideColumn} sx={commonMenuItemStyles}>
154
- <VisibilityOffIcon />{' '}
155
- {localization.columnActionMenuItemHideColumn?.replace(
156
- '{column}',
157
- String(column.Header),
158
- )}
214
+ <ListItemIcon>
215
+ <VisibilityOffIcon />
216
+ </ListItemIcon>
217
+ <ListItemText>
218
+ {localization.columnActionMenuItemHideColumn?.replace(
219
+ '{column}',
220
+ String(column.Header),
221
+ )}
222
+ </ListItemText>
159
223
  </MenuItem>,
160
224
  ]}
161
225
  </Menu>
@@ -0,0 +1,109 @@
1
+ import React, { FC, useMemo } from 'react';
2
+ import { Menu, MenuItem } from '@mui/material';
3
+ import { useMRT } from '../useMRT';
4
+ import { MRT_FilterType, MRT_HeaderGroup } from '..';
5
+
6
+ interface Props {
7
+ anchorEl: HTMLElement | null;
8
+ column: MRT_HeaderGroup;
9
+ setAnchorEl: (anchorEl: HTMLElement | null) => void;
10
+ onSelect?: () => void;
11
+ }
12
+
13
+ export const MRT_FilterTypeMenu: FC<Props> = ({
14
+ anchorEl,
15
+ column,
16
+ onSelect,
17
+ setAnchorEl,
18
+ }) => {
19
+ const { localization, setCurrentFilterTypes, tableInstance } = useMRT();
20
+
21
+ const filterTypes: {
22
+ type: MRT_FilterType;
23
+ label: string;
24
+ divider: boolean;
25
+ }[] = useMemo(
26
+ () => [
27
+ {
28
+ type: 'fuzzy',
29
+ label: localization.filterMenuItemFuzzy,
30
+ divider: false,
31
+ },
32
+ {
33
+ type: 'contains',
34
+ label: localization.filterMenuItemContains,
35
+ divider: true,
36
+ },
37
+ {
38
+ type: 'startsWith',
39
+ label: localization.filterMenuItemStartsWith,
40
+ divider: false,
41
+ },
42
+ {
43
+ type: 'endsWith',
44
+ label: localization.filterMenuItemEndsWith,
45
+ divider: true,
46
+ },
47
+ {
48
+ type: 'equals',
49
+ label: localization.filterMenuItemEquals,
50
+ divider: false,
51
+ },
52
+ {
53
+ type: 'notEquals',
54
+ label: localization.filterMenuItemNotEquals,
55
+ divider: true,
56
+ },
57
+ {
58
+ type: 'empty',
59
+ label: localization.filterMenuItemEmpty,
60
+ divider: false,
61
+ },
62
+ {
63
+ type: 'notEmpty',
64
+ label: localization.filterMenuItemNotEmpty,
65
+ divider: false,
66
+ },
67
+ ],
68
+ [],
69
+ );
70
+
71
+ const handleSelectFilterType = (value: MRT_FilterType) => {
72
+ setAnchorEl(null);
73
+ setCurrentFilterTypes((prev: { [key: string]: MRT_FilterType }) => ({
74
+ ...prev,
75
+ [column.id]: value,
76
+ }));
77
+ if (['empty', 'notEmpty'].includes(value)) {
78
+ column.setFilter(' ');
79
+ }
80
+ onSelect?.();
81
+ };
82
+
83
+ const filterType = tableInstance.state.currentFilterTypes[column.id];
84
+
85
+ return (
86
+ <Menu
87
+ anchorEl={anchorEl}
88
+ anchorOrigin={{ vertical: 'center', horizontal: 'right' }}
89
+ onClose={() => setAnchorEl(null)}
90
+ open={!!anchorEl}
91
+ MenuListProps={{
92
+ dense: tableInstance.state.densePadding,
93
+ disablePadding: true,
94
+ }}
95
+ >
96
+ {filterTypes.map(({ type, label, divider }) => (
97
+ <MenuItem
98
+ divider={divider}
99
+ key={type}
100
+ onClick={() => handleSelectFilterType(type)}
101
+ selected={type === filterType}
102
+ value={type}
103
+ >
104
+ {label}
105
+ </MenuItem>
106
+ ))}
107
+ </Menu>
108
+ );
109
+ };
@@ -1,5 +1,5 @@
1
1
  import React, { FC } from 'react';
2
- import { Menu, MenuItem } from '@mui/material';
2
+ import { ListItemIcon, ListItemText, Menu, MenuItem } from '@mui/material';
3
3
  import { useMRT } from '../useMRT';
4
4
  import { MRT_Row } from '..';
5
5
 
@@ -29,10 +29,17 @@ export const MRT_RowActionMenu: FC<Props> = ({
29
29
  anchorEl={anchorEl}
30
30
  open={!!anchorEl}
31
31
  onClose={() => setAnchorEl(null)}
32
+ MenuListProps={{
33
+ dense: tableInstance.state.densePadding,
34
+ disablePadding: true,
35
+ }}
32
36
  >
33
37
  {enableRowEditing && (
34
- <MenuItem sx={{ display: 'flex', gap: '0.75rem' }} onClick={handleEdit}>
35
- <EditIcon /> {localization.rowActionMenuItemEdit}
38
+ <MenuItem onClick={handleEdit}>
39
+ <ListItemIcon>
40
+ <EditIcon />
41
+ </ListItemIcon>
42
+ <ListItemText>{localization.rowActionMenuItemEdit}</ListItemText>
36
43
  </MenuItem>
37
44
  )}
38
45
  {renderRowActionMenuItems?.(row, tableInstance, () =>
@@ -8,7 +8,7 @@ interface Props {
8
8
  }
9
9
 
10
10
  export const MRT_ShowHideColumnsMenu: FC<Props> = ({ column }) => {
11
- const isParentHeader = (column?.columns?.length ?? 0) > 0;
11
+ const isParentHeader = !!column?.columns?.length;
12
12
 
13
13
  const allChildColumnsVisible =
14
14
  isParentHeader &&