material-react-table 0.27.0 → 0.29.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.
@@ -1,5 +1,12 @@
1
1
  import { FC } from 'react';
2
2
  import type { MRT_Header, MRT_TableInstance } from '..';
3
+ import { MRT_Localization } from '../localization';
4
+ export declare const internalFilterOptions: (localization: MRT_Localization) => {
5
+ option: string;
6
+ symbol: string;
7
+ label: string;
8
+ divider: boolean;
9
+ }[];
3
10
  interface Props {
4
11
  anchorEl: HTMLElement | null;
5
12
  header?: MRT_Header;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
- "version": "0.27.0",
2
+ "version": "0.29.1",
3
3
  "license": "MIT",
4
4
  "name": "material-react-table",
5
- "description": "A fully featured Material UI implementation of TanStack React Table, inspired by material-table and the MUI X DataGrid, written from the ground up in TypeScript.",
5
+ "description": "A fully featured Material UI V5 implementation of TanStack React Table V8, written from the ground up in TypeScript.",
6
6
  "author": "Kevin Vandy",
7
7
  "keywords": [
8
8
  "react-table",
@@ -62,7 +62,7 @@
62
62
  "@emotion/styled": "^11.9.3",
63
63
  "@faker-js/faker": "^7.3.0",
64
64
  "@mui/icons-material": "^5.8.4",
65
- "@mui/material": "^5.9.1",
65
+ "@mui/material": "^5.9.2",
66
66
  "@size-limit/preset-small-lib": "^7.0.8",
67
67
  "@storybook/addon-a11y": "^6.5.9",
68
68
  "@storybook/addon-actions": "^6.5.9",
@@ -101,6 +101,6 @@
101
101
  "dependencies": {
102
102
  "@tanstack/match-sorter-utils": "8.1.1",
103
103
  "@tanstack/react-table": "8.2.6",
104
- "react-virtual": "^2.10.4"
104
+ "@tanstack/react-virtual": "^3.0.0-beta.13"
105
105
  }
106
106
  }
@@ -40,7 +40,7 @@ import type {
40
40
  TableOptions,
41
41
  TableState,
42
42
  } from '@tanstack/react-table';
43
- import type { Options as VirtualizerOptions } from 'react-virtual';
43
+ import type { VirtualizerOptions } from '@tanstack/react-virtual';
44
44
  import { MRT_Localization, MRT_DefaultLocalization_EN } from './localization';
45
45
  import { MRT_Default_Icons, MRT_Icons } from './icons';
46
46
  import { MRT_TableRoot } from './table/MRT_TableRoot';
@@ -225,6 +225,7 @@ export type MRT_ColumnDef<TData extends Record<string, any> = {}> = Omit<
225
225
  enableEditing?: boolean;
226
226
  filterFn?: MRT_FilterFn<TData>;
227
227
  filterSelectOptions?: (string | { text: string; value: string })[];
228
+ filterVariant?: 'text' | 'select' | 'multi-select' | 'range';
228
229
  /**
229
230
  * footer must be a string. If you want custom JSX to render the footer, you can also specify a `Footer` option. (Capital F)
230
231
  */
@@ -302,9 +303,11 @@ export type MRT_ColumnDef<TData extends Record<string, any> = {}> = Omit<
302
303
  | (({
303
304
  table,
304
305
  column,
306
+ rangeFilterIndex,
305
307
  }: {
306
308
  table: MRT_TableInstance<TData>;
307
309
  column: MRT_Column<TData>;
310
+ rangeFilterIndex?: number;
308
311
  }) => TextFieldProps);
309
312
  muiTableHeadCellProps?:
310
313
  | TableCellProps
@@ -341,6 +344,7 @@ export type MRT_DefinedColumnDef<TData extends Record<string, any> = {}> = Omit<
341
344
  'id'
342
345
  > & {
343
346
  id: string;
347
+ _filterFn: MRT_FilterOption;
344
348
  };
345
349
 
346
350
  export type MRT_Column<TData extends Record<string, any> = {}> = Omit<
@@ -607,9 +611,11 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
607
611
  | (({
608
612
  table,
609
613
  column,
614
+ rangeFilterIndex,
610
615
  }: {
611
616
  table: MRT_TableInstance<TData>;
612
617
  column: MRT_Column<TData>;
618
+ rangeFilterIndex?: number;
613
619
  }) => TextFieldProps);
614
620
  muiTableHeadCellProps?:
615
621
  | TableCellProps
@@ -779,7 +785,9 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
779
785
  selectAllMode?: 'all' | 'page';
780
786
  state?: Partial<MRT_TableState<TData>>;
781
787
  tableId?: string;
782
- virtualizerProps?: Partial<VirtualizerOptions<HTMLDivElement>>;
788
+ virtualizerProps?: Partial<
789
+ VirtualizerOptions<HTMLDivElement, HTMLTableRowElement>
790
+ >;
783
791
  };
784
792
 
785
793
  export default <TData extends Record<string, any> = {}>({
@@ -1,5 +1,5 @@
1
1
  import React, { FC, RefObject, useMemo } from 'react';
2
- import { useVirtual } from 'react-virtual';
2
+ import { useVirtualizer, Virtualizer } from '@tanstack/react-virtual';
3
3
  import { TableBody } from '@mui/material';
4
4
  import { MRT_TableBodyRow } from './MRT_TableBodyRow';
5
5
  import { rankGlobalFuzzy } from '../sortingFns';
@@ -60,28 +60,27 @@ export const MRT_TableBody: FC<Props> = ({ table, tableContainerRef }) => {
60
60
  globalFilter,
61
61
  ]);
62
62
 
63
- const rowVirtualizer = enableRowVirtualization
64
- ? useVirtual({
65
- // estimateSize: () => (density === 'compact' ? 25 : 50),
63
+ const rowVirtualizer: Virtualizer = enableRowVirtualization
64
+ ? useVirtualizer({
65
+ estimateSize: () => (density === 'compact' ? 25 : 50),
66
66
  overscan: density === 'compact' ? 30 : 10,
67
- parentRef: tableContainerRef,
68
- size: rows.length,
67
+ getScrollElement: () => tableContainerRef.current as HTMLDivElement,
68
+ count: rows.length,
69
69
  ...virtualizerProps,
70
70
  })
71
71
  : ({} as any);
72
72
 
73
73
  const virtualRows = enableRowVirtualization
74
- ? rowVirtualizer.virtualItems
74
+ ? rowVirtualizer.getVirtualItems()
75
75
  : [];
76
76
 
77
77
  let paddingTop = 0;
78
78
  let paddingBottom = 0;
79
79
  if (enableRowVirtualization) {
80
- paddingTop = virtualRows.length > 0 ? virtualRows[0].start : 0;
81
- paddingBottom =
82
- virtualRows.length > 0
83
- ? rowVirtualizer.totalSize - virtualRows[virtualRows.length - 1].end
84
- : 0;
80
+ paddingTop = !!virtualRows.length ? virtualRows[0].start : 0;
81
+ paddingBottom = !!virtualRows.length
82
+ ? rowVirtualizer.getTotalSize() - virtualRows[virtualRows.length - 1].end
83
+ : 0;
85
84
  }
86
85
 
87
86
  return (
@@ -91,6 +90,7 @@ export const MRT_TableBody: FC<Props> = ({ table, tableContainerRef }) => {
91
90
  <td style={{ height: `${paddingTop}px` }} />
92
91
  </tr>
93
92
  )}
93
+ {/* @ts-ignore */}
94
94
  {(enableRowVirtualization ? virtualRows : rows).map(
95
95
  (rowOrVirtualRow: any, rowIndex: number) => {
96
96
  const row = enableRowVirtualization
@@ -52,6 +52,8 @@ export const prepareColumns = <TData extends Record<string, any> = {}>(
52
52
  if (Object.keys(MRT_FilterFns).includes(currentFilterFns[columnDef.id])) {
53
53
  columnDef.filterFn =
54
54
  MRT_FilterFns[currentFilterFns[columnDef.id]] ?? MRT_FilterFns.fuzzy;
55
+ //@ts-ignore
56
+ columnDef._filterFn = currentFilterFns[columnDef.id];
55
57
  }
56
58
  if (Object.keys(MRT_SortingFns).includes(columnDef.sortingFn as string)) {
57
59
  // @ts-ignore
@@ -123,3 +125,14 @@ export const getDefaultColumnOrderIds = <
123
125
  ),
124
126
  ...getTrailingDisplayColumnIds(props),
125
127
  ].filter(Boolean) as string[];
128
+
129
+ export const getDefaultColumnFilterFn = <
130
+ TData extends Record<string, any> = {},
131
+ >(
132
+ columnDef: MRT_ColumnDef<TData>,
133
+ ): MRT_FilterOption => {
134
+ if (columnDef.filterVariant === 'multi-select') return 'arrIncludesSome';
135
+ if (columnDef.filterVariant === 'select') return 'equals';
136
+ if (columnDef.filterVariant === 'range') return 'betweenInclusive';
137
+ return 'fuzzy';
138
+ };
@@ -19,7 +19,9 @@ export const MRT_TableHeadCellFilterContainer: FC<Props> = ({
19
19
 
20
20
  return (
21
21
  <Collapse in={showColumnFilters} mountOnEnter unmountOnExit>
22
- {currentFilterFns[column.id] === 'between' ? (
22
+ {['between', 'betweenInclusive', 'inNumberRange'].includes(
23
+ currentFilterFns[column.id],
24
+ ) ? (
23
25
  <MRT_FilterRangeFields header={header} table={table} />
24
26
  ) : (
25
27
  <MRT_FilterTextField header={header} table={table} />
@@ -19,6 +19,11 @@ export const MRT_TableHeadCellFilterLabel: FC<Props> = ({ header, table }) => {
19
19
  const { column } = header;
20
20
  const { columnDef } = column;
21
21
 
22
+ const isRangeFilter = [
23
+ 'between',
24
+ 'betweenInclusive',
25
+ 'inNumberRange',
26
+ ].includes(columnDef._filterFn);
22
27
  const currentFilterOption = currentFilterFns?.[header.id];
23
28
  const filterTooltip = localization.filteringByColumn
24
29
  .replace('{column}', String(columnDef.header))
@@ -37,7 +42,7 @@ export const MRT_TableHeadCellFilterLabel: FC<Props> = ({ header, table }) => {
37
42
  `"${
38
43
  Array.isArray(column.getFilterValue())
39
44
  ? (column.getFilterValue() as [string, string]).join(
40
- `" ${localization.and} "`,
45
+ `" ${isRangeFilter ? localization.and : localization.or} "`,
41
46
  )
42
47
  : (column.getFilterValue() as string)
43
48
  }"`,
@@ -48,8 +53,8 @@ export const MRT_TableHeadCellFilterLabel: FC<Props> = ({ header, table }) => {
48
53
  <Grow
49
54
  unmountOnExit
50
55
  in={
51
- (!!column.getFilterValue() && currentFilterOption !== 'between') ||
52
- (currentFilterOption === 'between' && // @ts-ignore
56
+ (!!column.getFilterValue() && isRangeFilter) ||
57
+ (!isRangeFilter && // @ts-ignore
53
58
  (!!column.getFilterValue()?.[0] || !!column.getFilterValue()?.[1]))
54
59
  }
55
60
  >
@@ -11,8 +11,8 @@ interface Props {
11
11
  export const MRT_FilterRangeFields: FC<Props> = ({ header, table }) => {
12
12
  return (
13
13
  <Box sx={{ display: 'grid', gridTemplateColumns: '6fr 6fr', gap: '1rem' }}>
14
- <MRT_FilterTextField header={header} inputIndex={0} table={table} />
15
- <MRT_FilterTextField header={header} inputIndex={1} table={table} />
14
+ <MRT_FilterTextField header={header} rangeFilterIndex={0} table={table} />
15
+ <MRT_FilterTextField header={header} rangeFilterIndex={1} table={table} />
16
16
  </Box>
17
17
  );
18
18
  };
@@ -6,10 +6,13 @@ import React, {
6
6
  useState,
7
7
  } from 'react';
8
8
  import {
9
+ Box,
10
+ Checkbox,
9
11
  Chip,
10
12
  debounce,
11
13
  IconButton,
12
14
  InputAdornment,
15
+ ListItemText,
13
16
  MenuItem,
14
17
  TextField,
15
18
  TextFieldProps,
@@ -20,13 +23,13 @@ import type { MRT_Header, MRT_TableInstance } from '..';
20
23
 
21
24
  interface Props {
22
25
  header: MRT_Header;
23
- inputIndex?: number;
26
+ rangeFilterIndex?: number;
24
27
  table: MRT_TableInstance;
25
28
  }
26
29
 
27
30
  export const MRT_FilterTextField: FC<Props> = ({
28
31
  header,
29
- inputIndex,
32
+ rangeFilterIndex,
30
33
  table,
31
34
  }) => {
32
35
  const {
@@ -45,11 +48,13 @@ export const MRT_FilterTextField: FC<Props> = ({
45
48
  const { columnDef } = column;
46
49
  const { currentFilterFns } = getState();
47
50
 
48
- const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
49
-
50
51
  const mTableHeadCellFilterTextFieldProps =
51
52
  muiTableHeadCellFilterTextFieldProps instanceof Function
52
- ? muiTableHeadCellFilterTextFieldProps({ column, table })
53
+ ? muiTableHeadCellFilterTextFieldProps({
54
+ column,
55
+ table,
56
+ rangeFilterIndex,
57
+ })
53
58
  : muiTableHeadCellFilterTextFieldProps;
54
59
 
55
60
  const mcTableHeadCellFilterTextFieldProps =
@@ -57,6 +62,7 @@ export const MRT_FilterTextField: FC<Props> = ({
57
62
  ? columnDef.muiTableHeadCellFilterTextFieldProps({
58
63
  column,
59
64
  table,
65
+ rangeFilterIndex,
60
66
  })
61
67
  : columnDef.muiTableHeadCellFilterTextFieldProps;
62
68
 
@@ -65,28 +71,73 @@ export const MRT_FilterTextField: FC<Props> = ({
65
71
  ...mcTableHeadCellFilterTextFieldProps,
66
72
  } as TextFieldProps;
67
73
 
68
- const [filterValue, setFilterValue] = useState<string>(() =>
69
- inputIndex !== undefined
70
- ? (column.getFilterValue() as [string, string])?.[inputIndex] ?? ''
74
+ const isRangeFilter =
75
+ columnDef.filterVariant === 'range' || rangeFilterIndex !== undefined;
76
+ const isSelectFilter = columnDef.filterVariant === 'select';
77
+ const isMultiSelectFilter = columnDef.filterVariant === 'multi-select';
78
+ const isTextboxFilter =
79
+ columnDef.filterVariant === 'text' ||
80
+ (!isSelectFilter && !isMultiSelectFilter);
81
+
82
+ const currentFilterOption = currentFilterFns?.[header.id];
83
+ const filterId = `mrt-${tableId}-${header.id}-filter-text-field${
84
+ rangeFilterIndex ?? ''
85
+ }`;
86
+ const filterChipLabel = ['empty', 'notEmpty'].includes(currentFilterOption)
87
+ ? //@ts-ignore
88
+ localization[
89
+ `filter${
90
+ currentFilterOption?.charAt?.(0)?.toUpperCase() +
91
+ currentFilterOption?.slice(1)
92
+ }`
93
+ ]
94
+ : '';
95
+ const filterPlaceholder = !isRangeFilter
96
+ ? localization.filterByColumn?.replace('{column}', String(columnDef.header))
97
+ : rangeFilterIndex === 0
98
+ ? localization.min
99
+ : rangeFilterIndex === 1
100
+ ? localization.max
101
+ : '';
102
+ const allowedColumnFilterOptions =
103
+ columnDef?.columnFilterModeOptions ?? columnFilterModeOptions;
104
+ const showChangeModeButton =
105
+ enableColumnFilterChangeMode &&
106
+ columnDef.enableColumnFilterChangeMode !== false &&
107
+ !rangeFilterIndex &&
108
+ (allowedColumnFilterOptions === undefined ||
109
+ !!allowedColumnFilterOptions?.length);
110
+
111
+ const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
112
+ const [filterValue, setFilterValue] = useState<string | string[]>(() =>
113
+ isMultiSelectFilter
114
+ ? (column.getFilterValue() as string[]) || []
115
+ : isRangeFilter
116
+ ? (column.getFilterValue() as [string, string])?.[
117
+ rangeFilterIndex as number
118
+ ] || []
71
119
  : (column.getFilterValue() as string) ?? '',
72
120
  );
73
121
 
74
122
  const handleChangeDebounced = useCallback(
75
- debounce((event: ChangeEvent<HTMLInputElement>) => {
76
- let value =
77
- textFieldProps.type === 'date'
78
- ? new Date(event.target.value)
79
- : event.target.value;
80
- if (inputIndex !== undefined) {
81
- column.setFilterValue((old: [string, string | Date]) => {
82
- const newFilterValues = old ?? ['', ''];
83
- newFilterValues[inputIndex] = value;
84
- return newFilterValues;
85
- });
86
- } else {
87
- column.setFilterValue(value ?? undefined);
88
- }
89
- }, 200),
123
+ debounce(
124
+ (event: ChangeEvent<HTMLInputElement>) => {
125
+ let value =
126
+ textFieldProps.type === 'date'
127
+ ? new Date(event.target.value)
128
+ : event.target.value;
129
+ if (isRangeFilter) {
130
+ column.setFilterValue((old: [string, string | Date]) => {
131
+ const newFilterValues = old ?? ['', ''];
132
+ newFilterValues[rangeFilterIndex as number] = value;
133
+ return newFilterValues;
134
+ });
135
+ } else {
136
+ column.setFilterValue(value ?? undefined);
137
+ }
138
+ },
139
+ isTextboxFilter ? 200 : 1,
140
+ ),
90
141
  [],
91
142
  );
92
143
 
@@ -95,24 +146,24 @@ export const MRT_FilterTextField: FC<Props> = ({
95
146
  handleChangeDebounced(event);
96
147
  };
97
148
 
98
- const handleFilterMenuOpen = (event: MouseEvent<HTMLElement>) => {
99
- setAnchorEl(event.currentTarget);
100
- };
101
-
102
149
  const handleClear = () => {
103
- setFilterValue('');
104
- if (inputIndex !== undefined) {
150
+ if (isMultiSelectFilter) {
151
+ setFilterValue([]);
152
+ column.setFilterValue([]);
153
+ } else if (isRangeFilter) {
154
+ setFilterValue('');
105
155
  column.setFilterValue((old: [string | undefined, string | undefined]) => {
106
156
  const newFilterValues = old ?? ['', ''];
107
- newFilterValues[inputIndex] = undefined;
157
+ newFilterValues[rangeFilterIndex as number] = undefined;
108
158
  return newFilterValues;
109
159
  });
110
160
  } else {
161
+ setFilterValue('');
111
162
  column.setFilterValue(undefined);
112
163
  }
113
164
  };
114
165
 
115
- const handleClearFilterChip = () => {
166
+ const handleClearEmptyFilterChip = () => {
116
167
  setFilterValue('');
117
168
  column.setFilterValue(undefined);
118
169
  setCurrentFilterFns((prev) => ({
@@ -121,47 +172,14 @@ export const MRT_FilterTextField: FC<Props> = ({
121
172
  }));
122
173
  };
123
174
 
175
+ const handleFilterMenuOpen = (event: MouseEvent<HTMLElement>) => {
176
+ setAnchorEl(event.currentTarget);
177
+ };
178
+
124
179
  if (columnDef.Filter) {
125
180
  return <>{columnDef.Filter?.({ header, table })}</>;
126
181
  }
127
182
 
128
- const filterId = `mrt-${tableId}-${header.id}-filter-text-field${
129
- inputIndex ?? ''
130
- }`;
131
- const currentFilterOption = currentFilterFns?.[header.id];
132
- const isSelectFilter = !!columnDef.filterSelectOptions;
133
- const filterChipLabel = ['empty', 'notEmpty'].includes(currentFilterOption)
134
- ? //@ts-ignore
135
- localization[
136
- `filter${
137
- currentFilterOption?.charAt(0)?.toUpperCase() +
138
- currentFilterOption?.slice(1)
139
- }`
140
- ]
141
- : '';
142
- const filterPlaceholder =
143
- inputIndex === undefined
144
- ? localization.filterByColumn?.replace(
145
- '{column}',
146
- String(columnDef.header),
147
- )
148
- : inputIndex === 0
149
- ? localization.min
150
- : inputIndex === 1
151
- ? localization.max
152
- : '';
153
-
154
- const allowedColumnFilterOptions =
155
- columnDef?.columnFilterModeOptions ?? columnFilterModeOptions;
156
-
157
- const showChangeModeButton =
158
- enableColumnFilterChangeMode &&
159
- columnDef.enableColumnFilterChangeMode !== false &&
160
- !isSelectFilter &&
161
- !inputIndex &&
162
- (allowedColumnFilterOptions === undefined ||
163
- !!allowedColumnFilterOptions?.length);
164
-
165
183
  return (
166
184
  <>
167
185
  <TextField
@@ -200,12 +218,14 @@ export const MRT_FilterTextField: FC<Props> = ({
200
218
  }}
201
219
  margin="none"
202
220
  placeholder={
203
- filterChipLabel || isSelectFilter ? undefined : filterPlaceholder
221
+ filterChipLabel || isSelectFilter || isMultiSelectFilter
222
+ ? undefined
223
+ : filterPlaceholder
204
224
  }
205
225
  onChange={handleChange}
206
226
  onClick={(e: MouseEvent<HTMLInputElement>) => e.stopPropagation()}
207
- select={isSelectFilter}
208
- value={filterValue ?? ''}
227
+ select={isSelectFilter || isMultiSelectFilter}
228
+ value={filterValue}
209
229
  variant="standard"
210
230
  InputProps={{
211
231
  startAdornment: showChangeModeButton ? (
@@ -224,7 +244,7 @@ export const MRT_FilterTextField: FC<Props> = ({
224
244
  </Tooltip>
225
245
  {filterChipLabel && (
226
246
  <Chip
227
- onDelete={handleClearFilterChip}
247
+ onDelete={handleClearEmptyFilterChip}
228
248
  label={filterChipLabel}
229
249
  />
230
250
  )}
@@ -236,7 +256,6 @@ export const MRT_FilterTextField: FC<Props> = ({
236
256
  <InputAdornment position="end">
237
257
  <Tooltip
238
258
  arrow
239
- disableHoverListener={isSelectFilter}
240
259
  placement="right"
241
260
  title={localization.clearFilter ?? ''}
242
261
  >
@@ -258,10 +277,26 @@ export const MRT_FilterTextField: FC<Props> = ({
258
277
  </InputAdornment>
259
278
  ),
260
279
  }}
280
+ SelectProps={{
281
+ displayEmpty: true,
282
+ multiple: isMultiSelectFilter,
283
+ renderValue: isMultiSelectFilter
284
+ ? (selected: any) =>
285
+ !selected?.length ? (
286
+ <Box sx={{ opacity: 0.5 }}>{filterPlaceholder}</Box>
287
+ ) : (
288
+ <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: '2px' }}>
289
+ {(selected as string[])?.map((value) => (
290
+ <Chip key={value} label={value} />
291
+ ))}
292
+ </Box>
293
+ )
294
+ : undefined,
295
+ }}
261
296
  {...textFieldProps}
262
297
  sx={(theme) => ({
263
298
  p: 0,
264
- minWidth: !filterChipLabel ? '8rem' : 'auto',
299
+ minWidth: !filterChipLabel ? '6rem' : 'auto',
265
300
  width: 'calc(100% + 0.5rem)',
266
301
  '& .MuiSelect-icon': {
267
302
  mr: '1.5rem',
@@ -271,24 +306,32 @@ export const MRT_FilterTextField: FC<Props> = ({
271
306
  : (textFieldProps?.sx as any)),
272
307
  })}
273
308
  >
274
- {isSelectFilter && (
275
- <MenuItem divider disabled={!filterValue} value="">
276
- {localization.clearFilter}
309
+ {(isSelectFilter || isMultiSelectFilter) && (
310
+ <MenuItem divider disabled hidden value="">
311
+ <Box sx={{ opacity: 0.5 }}>{filterPlaceholder}</Box>
277
312
  </MenuItem>
278
313
  )}
279
314
  {columnDef?.filterSelectOptions?.map((option) => {
280
- let value;
281
- let text;
282
- if (typeof option === 'string') {
315
+ let value: string;
316
+ let text: string;
317
+ if (typeof option !== 'object') {
283
318
  value = option;
284
319
  text = option;
285
- } else if (typeof option === 'object') {
320
+ } else {
286
321
  value = option.value;
287
322
  text = option.text;
288
323
  }
289
324
  return (
290
325
  <MenuItem key={value} value={value}>
291
- {text}
326
+ {isMultiSelectFilter && (
327
+ <Checkbox
328
+ checked={(
329
+ (column.getFilterValue() ?? []) as string[]
330
+ ).includes(value)}
331
+ sx={{ mr: '0.5rem' }}
332
+ />
333
+ )}
334
+ <ListItemText>{text}</ListItemText>
292
335
  </MenuItem>
293
336
  );
294
337
  })}
@@ -13,6 +13,9 @@ export interface MRT_Localization {
13
13
  edit: string;
14
14
  expand: string;
15
15
  expandAll: string;
16
+ filterArrIncludes: string;
17
+ filterArrIncludesAll: string;
18
+ filterArrIncludesSome: string;
16
19
  filterBetween: string;
17
20
  filterBetweenInclusive: string;
18
21
  filterByColumn: string;
@@ -20,15 +23,20 @@ export interface MRT_Localization {
20
23
  filterEmpty: string;
21
24
  filterEndsWith: string;
22
25
  filterEquals: string;
26
+ filterEqualsString: string;
23
27
  filterFuzzy: string;
24
28
  filterGreaterThan: string;
25
29
  filterGreaterThanOrEqualTo: string;
30
+ filterInNumberRange: string;
31
+ filterIncludesString: string;
32
+ filterIncludesStringSensitive: string;
26
33
  filterLessThan: string;
27
34
  filterLessThanOrEqualTo: string;
28
35
  filterMode: string;
29
36
  filterNotEmpty: string;
30
37
  filterNotEquals: string;
31
38
  filterStartsWith: string;
39
+ filterWeakEquals: string;
32
40
  filteringByColumn: string;
33
41
  grab: string;
34
42
  groupByColumn: string;
@@ -38,6 +46,7 @@ export interface MRT_Localization {
38
46
  max: string;
39
47
  min: string;
40
48
  move: string;
49
+ or: string;
41
50
  pinToLeft: string;
42
51
  pinToRight: string;
43
52
  resetColumnSize: string;
@@ -85,6 +94,9 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
85
94
  edit: 'Edit',
86
95
  expand: 'Expand',
87
96
  expandAll: 'Expand all',
97
+ filterArrIncludes: 'Includes',
98
+ filterArrIncludesAll: 'Includes all',
99
+ filterArrIncludesSome: 'Includes',
88
100
  filterBetween: 'Between',
89
101
  filterBetweenInclusive: 'Between Inclusive',
90
102
  filterByColumn: 'Filter by {column}',
@@ -92,15 +104,20 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
92
104
  filterEmpty: 'Empty',
93
105
  filterEndsWith: 'Ends With',
94
106
  filterEquals: 'Equals',
107
+ filterEqualsString: 'Equals',
95
108
  filterFuzzy: 'Fuzzy',
96
109
  filterGreaterThan: 'Greater Than',
97
110
  filterGreaterThanOrEqualTo: 'Greater Than Or Equal To',
111
+ filterInNumberRange: 'Between',
112
+ filterIncludesString: 'Contains',
113
+ filterIncludesStringSensitive: 'Contains',
98
114
  filterLessThan: 'Less Than',
99
115
  filterLessThanOrEqualTo: 'Less Than Or Equal To',
100
116
  filterMode: 'Filter Mode: {filterType}',
101
117
  filterNotEmpty: 'Not Empty',
102
118
  filterNotEquals: 'Not Equals',
103
119
  filterStartsWith: 'Starts With',
120
+ filterWeakEquals: 'Equals',
104
121
  filteringByColumn: 'Filtering by {column} - {filterType} {filterValue}',
105
122
  grab: 'Grab',
106
123
  groupByColumn: 'Group by {column}',
@@ -110,6 +127,7 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
110
127
  max: 'Max',
111
128
  min: 'Min',
112
129
  move: 'Move',
130
+ or: 'or',
113
131
  pinToLeft: 'Pin to left',
114
132
  pinToRight: 'Pin to right',
115
133
  resetColumnSize: 'Reset column size',