material-react-table 0.5.1 → 0.5.4

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 (45) hide show
  1. package/dist/MaterialReactTable.d.ts +15 -9
  2. package/dist/filtersFNs.d.ts +67 -0
  3. package/dist/localization.d.ts +10 -1
  4. package/dist/material-react-table.cjs.development.js +455 -147
  5. package/dist/material-react-table.cjs.development.js.map +1 -1
  6. package/dist/material-react-table.cjs.production.min.js +1 -1
  7. package/dist/material-react-table.cjs.production.min.js.map +1 -1
  8. package/dist/material-react-table.esm.js +457 -149
  9. package/dist/material-react-table.esm.js.map +1 -1
  10. package/dist/menus/MRT_FilterMenu.d.ts +10 -0
  11. package/dist/useMRT.d.ts +13 -14
  12. package/package.json +6 -2
  13. package/src/@types/react-table-config.d.ts +3 -3
  14. package/src/MaterialReactTable.tsx +30 -9
  15. package/src/body/MRT_TableBody.tsx +7 -2
  16. package/src/body/MRT_TableBodyCell.tsx +3 -2
  17. package/src/body/MRT_TableBodyRow.tsx +11 -8
  18. package/src/buttons/MRT_EditActionButtons.tsx +4 -2
  19. package/src/buttons/MRT_ExpandAllButton.tsx +3 -4
  20. package/src/buttons/MRT_ExpandButton.tsx +3 -1
  21. package/src/buttons/MRT_FullScreenToggleButton.tsx +3 -1
  22. package/src/buttons/MRT_ToggleColumnActionMenuButton.tsx +4 -3
  23. package/src/buttons/MRT_ToggleDensePaddingButton.tsx +3 -1
  24. package/src/buttons/MRT_ToggleFiltersButton.tsx +4 -2
  25. package/src/buttons/MRT_ToggleRowActionMenuButton.tsx +17 -11
  26. package/src/buttons/MRT_ToggleSearchButton.tsx +5 -2
  27. package/src/filtersFNs.ts +112 -0
  28. package/src/footer/MRT_TableFooter.tsx +6 -1
  29. package/src/footer/MRT_TableFooterCell.tsx +7 -2
  30. package/src/head/MRT_TableHeadCell.tsx +49 -47
  31. package/src/head/MRT_TableHeadCellActions.tsx +6 -1
  32. package/src/head/MRT_TableHeadRow.tsx +7 -2
  33. package/src/index.tsx +0 -2
  34. package/src/inputs/MRT_EditCellTextField.tsx +3 -1
  35. package/src/inputs/MRT_FilterTextField.tsx +117 -52
  36. package/src/inputs/MRT_SearchTextField.tsx +3 -3
  37. package/src/inputs/MRT_SelectCheckbox.tsx +5 -8
  38. package/src/localization.ts +20 -2
  39. package/src/menus/MRT_ColumnActionMenu.tsx +125 -85
  40. package/src/menus/MRT_FilterMenu.tsx +109 -0
  41. package/src/table/MRT_Table.tsx +7 -2
  42. package/src/table/MRT_TableContainer.tsx +16 -3
  43. package/src/toolbar/MRT_ToolbarBottom.tsx +2 -3
  44. package/src/toolbar/MRT_ToolbarTop.tsx +2 -3
  45. package/src/useMRT.tsx +104 -35
@@ -30,13 +30,11 @@ interface Props {
30
30
 
31
31
  export const MRT_TableHeadCell: FC<Props> = ({ column }) => {
32
32
  const {
33
- densePadding,
34
33
  disableColumnActions,
35
34
  disableFilters,
36
35
  enableColumnResizing,
37
36
  localization,
38
37
  muiTableHeadCellProps,
39
- showFilters,
40
38
  tableInstance,
41
39
  } = useMRT();
42
40
 
@@ -75,69 +73,73 @@ export const MRT_TableHeadCell: FC<Props> = ({ column }) => {
75
73
  column.Header as string,
76
74
  );
77
75
 
76
+ const columnHeader = column.render('Header') as string;
77
+
78
78
  return (
79
79
  <TableCell
80
80
  align={isParentHeader ? 'center' : 'left'}
81
81
  {...tableCellProps}
82
82
  sx={{
83
- ...commonTableHeadCellStyles(densePadding, enableColumnResizing),
83
+ ...commonTableHeadCellStyles(
84
+ tableInstance.state.densePadding,
85
+ enableColumnResizing,
86
+ ),
84
87
  ...tableCellProps?.sx,
85
88
  }}
86
89
  >
87
90
  <Box
88
- sx={{ alignContent: 'space-between', display: 'grid', height: '100%' }}
91
+ sx={{
92
+ alignItems: 'flex-start',
93
+ display: 'flex',
94
+ justifyContent: isParentHeader ? 'center' : 'space-between',
95
+ width: '100%',
96
+ }}
89
97
  >
90
98
  <Box
99
+ {...column.getSortByToggleProps()}
91
100
  sx={{
92
- alignItems: 'flex-start',
101
+ alignItems: 'center',
93
102
  display: 'flex',
94
- justifyContent: isParentHeader ? 'center' : 'space-between',
95
- width: '100%',
103
+ flexWrap: 'nowrap',
104
+ whiteSpace: columnHeader.length < 15 ? 'nowrap' : 'normal',
96
105
  }}
106
+ title={undefined}
97
107
  >
98
- <Box
99
- {...column.getSortByToggleProps()}
100
- sx={{ alignItems: 'center', display: 'flex', flexWrap: 'nowrap' }}
101
- title={undefined}
102
- >
103
- {column.render('Header')}
104
- {!isParentHeader && column.canSort && (
105
- <Tooltip arrow title={sortTooltip}>
106
- <TableSortLabel
107
- aria-label={sortTooltip}
108
- active={column.isSorted}
109
- direction={column.isSortedDesc ? 'desc' : 'asc'}
110
- />
111
- </Tooltip>
112
- )}
113
- </Box>
114
- <Box
115
- sx={{ alignItems: 'center', display: 'flex', flexWrap: 'nowrap' }}
116
- >
117
- {!disableColumnActions && !isParentHeader && (
118
- <MRT_ToggleColumnActionMenuButton column={column} />
119
- )}
120
- {enableColumnResizing && !isParentHeader && (
121
- <Divider
122
- flexItem
123
- orientation="vertical"
124
- onDoubleClick={() => tableInstance.resetResizing()}
125
- {...column.getResizerProps()}
126
- sx={{
127
- borderRightWidth: '2px',
128
- borderRadius: '2px',
129
- maxHeight: '2rem',
130
- }}
108
+ {column.render('Header')}
109
+ {!isParentHeader && column.canSort && (
110
+ <Tooltip arrow title={sortTooltip}>
111
+ <TableSortLabel
112
+ aria-label={sortTooltip}
113
+ active={column.isSorted}
114
+ direction={column.isSortedDesc ? 'desc' : 'asc'}
131
115
  />
132
- )}
133
- </Box>
116
+ </Tooltip>
117
+ )}
118
+ </Box>
119
+ <Box sx={{ alignItems: 'center', display: 'flex', flexWrap: 'nowrap' }}>
120
+ {!disableColumnActions && !isParentHeader && (
121
+ <MRT_ToggleColumnActionMenuButton column={column} />
122
+ )}
123
+ {enableColumnResizing && !isParentHeader && (
124
+ <Divider
125
+ flexItem
126
+ orientation="vertical"
127
+ onDoubleClick={() => tableInstance.resetResizing()}
128
+ {...column.getResizerProps()}
129
+ sx={{
130
+ borderRightWidth: '2px',
131
+ borderRadius: '2px',
132
+ maxHeight: '2rem',
133
+ }}
134
+ />
135
+ )}
134
136
  </Box>
135
- {!disableFilters && column.canFilter && (
136
- <Collapse in={showFilters}>
137
- <MRT_FilterTextField column={column} />
138
- </Collapse>
139
- )}
140
137
  </Box>
138
+ {!disableFilters && column.canFilter && (
139
+ <Collapse in={tableInstance.state.showFilters}>
140
+ <MRT_FilterTextField column={column} />
141
+ </Collapse>
142
+ )}
141
143
  </TableCell>
142
144
  );
143
145
  };
@@ -6,7 +6,12 @@ import { commonTableHeadCellStyles } from './MRT_TableHeadCell';
6
6
  interface Props {}
7
7
 
8
8
  export const MRT_TableHeadCellActions: FC<Props> = () => {
9
- const { densePadding, localization } = useMRT();
9
+ const {
10
+ localization,
11
+ tableInstance: {
12
+ state: { densePadding },
13
+ },
14
+ } = useMRT();
10
15
 
11
16
  return (
12
17
  <TableCell
@@ -18,7 +18,6 @@ interface Props {
18
18
  export const MRT_TableHeadRow: FC<Props> = ({ headerGroup }) => {
19
19
  const {
20
20
  anyRowsCanExpand,
21
- densePadding,
22
21
  disableExpandAll,
23
22
  enableRowActions,
24
23
  enableRowEditing,
@@ -55,7 +54,13 @@ export const MRT_TableHeadRow: FC<Props> = ({ headerGroup }) => {
55
54
  (isParentHeader ? (
56
55
  <MRT_TableSpacerCell />
57
56
  ) : (
58
- <TableCell sx={{...commonTableHeadCellStyles(densePadding)}}>#</TableCell>
57
+ <TableCell
58
+ sx={{
59
+ ...commonTableHeadCellStyles(tableInstance.state.densePadding),
60
+ }}
61
+ >
62
+ #
63
+ </TableCell>
59
64
  ))}
60
65
  {(enableRowActions || enableRowEditing) &&
61
66
  positionActionsColumn === 'first' &&
package/src/index.tsx CHANGED
@@ -1,5 +1,3 @@
1
1
  import MaterialReactTable from './MaterialReactTable';
2
2
  export default MaterialReactTable;
3
3
  export * from './MaterialReactTable';
4
-
5
-
@@ -9,9 +9,11 @@ interface Props {
9
9
 
10
10
  export const MRT_EditCellTextField: FC<Props> = ({ cell }) => {
11
11
  const {
12
- currentEditingRow,
13
12
  muiTableBodyCellEditTextFieldProps,
14
13
  setCurrentEditingRow,
14
+ tableInstance: {
15
+ state: { currentEditingRow },
16
+ },
15
17
  } = useMRT();
16
18
 
17
19
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
@@ -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_FilterMenu } from '../menus/MRT_FilterMenu';
6
14
 
7
15
  interface Props {
8
16
  column: MRT_HeaderGroup;
@@ -11,79 +19,136 @@ 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 showFilterChip = ['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
+ sx: {
89
+ textOverflow: 'ellipsis',
90
+ },
91
+ title: filterPlaceholder,
92
+ }}
93
+ margin="none"
94
+ placeholder={showFilterChip ? '' : filterPlaceholder}
95
+ onChange={(e: ChangeEvent<HTMLInputElement>) => {
96
+ setFilterValue(e.target.value);
97
+ handleChange(e.target.value);
98
+ }}
99
+ onClick={(e) => e.stopPropagation()}
100
+ value={filterValue ?? ''}
101
+ variant="standard"
102
+ InputProps={{
103
+ startAdornment: (
62
104
  <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>
105
+ <Tooltip arrow title="Change Filter Mode">
74
106
  <IconButton
75
- aria-label={localization.filterTextFieldClearButtonTitle}
76
- disabled={filterValue?.length === 0}
77
- onClick={handleClear}
107
+ onClick={handleFilterMenuOpen}
78
108
  size="small"
109
+ sx={{ height: '1.75rem', width: '1.75rem' }}
79
110
  >
80
- <CloseIcon fontSize="small" />
111
+ <FilterListIcon />
81
112
  </IconButton>
82
- </span>
83
- </Tooltip>
84
- </InputAdornment>
85
- ),
86
- }}
87
- />
113
+ </Tooltip>
114
+ {showFilterChip && (
115
+ <Chip onDelete={handleClearFilterChip} label={filterType} />
116
+ )}
117
+ </InputAdornment>
118
+ ),
119
+ endAdornment: !showFilterChip && (
120
+ <InputAdornment position="end">
121
+ <Tooltip
122
+ arrow
123
+ placement="right"
124
+ title={localization.filterTextFieldClearButtonTitle ?? ''}
125
+ >
126
+ <span>
127
+ <IconButton
128
+ aria-label={localization.filterTextFieldClearButtonTitle}
129
+ disabled={filterValue?.length === 0}
130
+ onClick={handleClear}
131
+ size="small"
132
+ sx={{ height: '1.75rem', width: '1.75rem' }}
133
+ >
134
+ <CloseIcon fontSize="small" />
135
+ </IconButton>
136
+ </span>
137
+ </Tooltip>
138
+ </InputAdornment>
139
+ ),
140
+ }}
141
+ {...textFieldProps}
142
+ sx={{
143
+ minWidth: '6rem',
144
+ ...textFieldProps?.sx,
145
+ }}
146
+ />
147
+ <MRT_FilterMenu
148
+ anchorEl={anchorEl}
149
+ column={column}
150
+ setAnchorEl={setAnchorEl}
151
+ />
152
+ </>
88
153
  );
89
154
  };
@@ -8,7 +8,7 @@ interface Props {}
8
8
  export const MRT_SearchTextField: FC<Props> = () => {
9
9
  const {
10
10
  icons: { SearchIcon, CloseIcon },
11
- showSearch,
11
+ idPrefix,
12
12
  localization,
13
13
  muiSearchTextFieldProps,
14
14
  onGlobalFilterChange,
@@ -31,9 +31,9 @@ export const MRT_SearchTextField: FC<Props> = () => {
31
31
  };
32
32
 
33
33
  return (
34
- <Collapse in={showSearch} orientation="horizontal">
34
+ <Collapse in={tableInstance.state.showSearch} orientation="horizontal">
35
35
  <TextField
36
- id="global-search-text-field"
36
+ id={`mrt-${idPrefix}-search-text-field`}
37
37
  placeholder={localization.searchTextFieldPlaceholder}
38
38
  onChange={(event: ChangeEvent<HTMLInputElement>) => {
39
39
  setSearchValue(event.target.value);
@@ -10,13 +10,8 @@ interface Props {
10
10
  }
11
11
 
12
12
  export const MRT_SelectCheckbox: FC<Props> = ({ row, selectAll }) => {
13
- const {
14
- densePadding,
15
- localization,
16
- onRowSelectChange,
17
- onSelectAllChange,
18
- tableInstance,
19
- } = useMRT();
13
+ const { localization, onRowSelectChange, onSelectAllChange, tableInstance } =
14
+ useMRT();
20
15
 
21
16
  const onSelectChange = (event: ChangeEvent<HTMLInputElement>) => {
22
17
  if (selectAll) {
@@ -33,7 +28,9 @@ export const MRT_SelectCheckbox: FC<Props> = ({ row, selectAll }) => {
33
28
  : row?.getToggleRowSelectedProps();
34
29
 
35
30
  return (
36
- <TableCell sx={commonTableBodyButtonCellStyles(densePadding)} >
31
+ <TableCell
32
+ sx={commonTableBodyButtonCellStyles(tableInstance.state.densePadding)}
33
+ >
37
34
  <Tooltip
38
35
  arrow
39
36
  enterDelay={1000}
@@ -11,6 +11,15 @@ export interface MRT_Localization {
11
11
  columnShowHideMenuShowAll: string;
12
12
  expandAllButtonTitle: string;
13
13
  expandButtonTitle: string;
14
+ filterMenuItemContains: string;
15
+ filterMenuItemEmpty: string;
16
+ filterMenuItemEndsWith: string;
17
+ filterMenuItemEquals: string;
18
+ filterMenuItemFuzzy: string;
19
+ filterMenuItemNotEmpty: string;
20
+ filterMenuItemNotEquals: string;
21
+ filterMenuItemStartsWith: string;
22
+ filterMenuTitle: string;
14
23
  filterTextFieldClearButtonTitle: string;
15
24
  filterTextFieldPlaceholder: string;
16
25
  rowActionButtonCancel: string;
@@ -27,9 +36,9 @@ export interface MRT_Localization {
27
36
  toggleFilterButtonTitle: string;
28
37
  toggleFullScreenButtonTitle: string;
29
38
  toggleSearchButtonTitle: string;
30
- toolbarAlertSelectionMessage: string;
31
39
  toolbarAlertGroupedByMessage: string;
32
40
  toolbarAlertGroupedThenByMessage: string;
41
+ toolbarAlertSelectionMessage: string;
33
42
  }
34
43
 
35
44
  export const MRT_DefaultLocalization_EN: MRT_Localization = {
@@ -45,6 +54,15 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
45
54
  columnShowHideMenuShowAll: 'Show all',
46
55
  expandAllButtonTitle: 'Expand all',
47
56
  expandButtonTitle: 'Expand',
57
+ filterMenuItemContains: 'Contains Exact',
58
+ filterMenuItemEmpty: 'Empty',
59
+ filterMenuItemEndsWith: 'Ends With',
60
+ filterMenuItemEquals: 'Equals',
61
+ filterMenuItemFuzzy: 'Fuzzy Match',
62
+ filterMenuItemNotEmpty: 'Not Empty',
63
+ filterMenuItemNotEquals: 'Not Equals',
64
+ filterMenuItemStartsWith: 'Starts With',
65
+ filterMenuTitle: 'Filter Mode',
48
66
  filterTextFieldClearButtonTitle: 'Clear filter',
49
67
  filterTextFieldPlaceholder: 'Filter by {column}',
50
68
  rowActionButtonCancel: 'Cancel',
@@ -61,7 +79,7 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
61
79
  toggleFilterButtonTitle: 'Toggle filters',
62
80
  toggleFullScreenButtonTitle: 'Toggle full screen',
63
81
  toggleSearchButtonTitle: 'Toggle search',
64
- toolbarAlertSelectionMessage: '{selectedCount} of {rowCount} row(s) selected',
65
82
  toolbarAlertGroupedByMessage: 'Grouped by ',
66
83
  toolbarAlertGroupedThenByMessage: ', then by ',
84
+ toolbarAlertSelectionMessage: '{selectedCount} of {rowCount} row(s) selected',
67
85
  };