material-react-table 2.4.1 → 2.5.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.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.4.1",
2
+ "version": "2.5.0",
3
3
  "license": "MIT",
4
4
  "name": "material-react-table",
5
5
  "description": "A fully featured Material UI V5 implementation of TanStack React Table V8, written from the ground up in TypeScript.",
@@ -11,7 +11,6 @@ import Skeleton from '@mui/material/Skeleton';
11
11
  import TableCell, { type TableCellProps } from '@mui/material/TableCell';
12
12
  import { useTheme } from '@mui/material/styles';
13
13
  import { MRT_TableBodyCellValue } from './MRT_TableBodyCellValue';
14
- import { MRT_TableBodyRowGrabHandle } from './MRT_TableBodyRowGrabHandle';
15
14
  import { MRT_CopyButton } from '../buttons/MRT_CopyButton';
16
15
  import {
17
16
  getIsFirstColumn,
@@ -58,11 +57,9 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
58
57
  enableColumnOrdering,
59
58
  enableEditing,
60
59
  enableGrouping,
61
- enableRowNumbers,
62
60
  layoutMode,
63
61
  muiSkeletonProps,
64
62
  muiTableBodyCellProps,
65
- rowNumberDisplayMode,
66
63
  },
67
64
  refs: { editInputRefs },
68
65
  setEditingCell,
@@ -210,6 +207,11 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
210
207
  }
211
208
  };
212
209
 
210
+ const cellValueProps = {
211
+ cell,
212
+ table,
213
+ };
214
+
213
215
  return (
214
216
  <TableCell
215
217
  data-index={virtualColumnIndex}
@@ -286,25 +288,18 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
286
288
  width={skeletonWidth}
287
289
  {...skeletonProps}
288
290
  />
289
- ) : enableRowNumbers &&
290
- rowNumberDisplayMode === 'static' &&
291
- column.id === 'mrt-row-numbers' ? (
292
- rowIndex + 1
293
- ) : column.id === 'mrt-row-drag' ? (
294
- <MRT_TableBodyRowGrabHandle
295
- row={row}
296
- rowRef={rowRef}
297
- table={table}
298
- />
299
291
  ) : columnDefType === 'display' &&
300
- (column.id === 'mrt-row-select' ||
301
- column.id === 'mrt-row-expand' ||
292
+ (['mrt-row-expand', 'mrt-row-numbers', 'mrt-row-select'].includes(
293
+ column.id,
294
+ ) ||
302
295
  !row.getIsGrouped()) ? (
303
296
  columnDef.Cell?.({
304
297
  cell,
305
298
  column,
306
299
  renderedCellValue: cell.renderValue() as any,
307
300
  row,
301
+ rowRef,
302
+ staticRowIndex: rowIndex,
308
303
  table,
309
304
  })
310
305
  ) : isCreating || isEditing ? (
@@ -312,10 +307,10 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
312
307
  ) : (enableClickToCopy || columnDef.enableClickToCopy) &&
313
308
  columnDef.enableClickToCopy !== false ? (
314
309
  <MRT_CopyButton cell={cell} table={table}>
315
- <MRT_TableBodyCellValue cell={cell} table={table} />
310
+ <MRT_TableBodyCellValue {...cellValueProps} />
316
311
  </MRT_CopyButton>
317
312
  ) : (
318
- <MRT_TableBodyCellValue cell={cell} table={table} />
313
+ <MRT_TableBodyCellValue {...cellValueProps} />
319
314
  )}
320
315
  {cell.getIsGrouped() && !columnDef.GroupedCell && (
321
316
  <> ({row.subRows?.length})</>
@@ -1,4 +1,4 @@
1
- import { type ReactNode } from 'react';
1
+ import { type ReactNode, type RefObject } from 'react';
2
2
  import Box from '@mui/material/Box';
3
3
  import { getMRTTheme } from '../style.utils';
4
4
  import {
@@ -12,11 +12,15 @@ const allowedTypes = ['string', 'number'];
12
12
 
13
13
  interface Props<TData extends MRT_RowData> {
14
14
  cell: MRT_Cell<TData>;
15
+ rowRef?: RefObject<HTMLTableRowElement>;
16
+ staticRowIndex?: number;
15
17
  table: MRT_TableInstance<TData>;
16
18
  }
17
19
 
18
20
  export const MRT_TableBodyCellValue = <TData extends MRT_RowData>({
19
21
  cell,
22
+ rowRef,
23
+ staticRowIndex,
20
24
  table,
21
25
  }: Props<TData>) => {
22
26
  const {
@@ -108,6 +112,8 @@ export const MRT_TableBodyCellValue = <TData extends MRT_RowData>({
108
112
  column,
109
113
  renderedCellValue,
110
114
  row,
115
+ rowRef,
116
+ staticRowIndex,
111
117
  table,
112
118
  });
113
119
  }
@@ -1,4 +1,6 @@
1
- import { type RefObject, useMemo } from 'react';
1
+ import { type ReactNode, type RefObject, useMemo } from 'react';
2
+ import Stack from '@mui/material/Stack';
3
+ import Tooltip from '@mui/material/Tooltip';
2
4
  import { MRT_TableBodyRowGrabHandle } from '../body';
3
5
  import { MRT_TableBodyRowPinButton } from '../body/MRT_TableBodyRowPinButton';
4
6
  import { MRT_ExpandAllButton } from '../buttons/MRT_ExpandAllButton';
@@ -63,6 +65,7 @@ export const useMRT_DisplayColumns = <TData extends MRT_RowData>(
63
65
  tableOptions.enableRowOrdering,
64
66
  tableOptions.enableRowSelection,
65
67
  tableOptions.enableSelectAll,
68
+ tableOptions.groupedColumnMode,
66
69
  tableOptions.localization,
67
70
  tableOptions.positionActionsColumn,
68
71
  tableOptions.renderDetailPanel,
@@ -158,11 +161,60 @@ function makeRowExpandColumn<TData extends MRT_RowData>(
158
161
  showExpandColumn(tableOptions, tableOptions.state?.grouping ?? grouping)
159
162
  ) {
160
163
  return {
161
- Cell: ({ row, table }) => <MRT_ExpandButton row={row} table={table} />,
164
+ Cell: ({ cell, column, row, table }) => {
165
+ const expandButtonProps = { row, table };
166
+ const subRowsLength = row.subRows?.length;
167
+ if (
168
+ tableOptions.groupedColumnMode === 'remove' &&
169
+ row.groupingColumnId
170
+ ) {
171
+ return (
172
+ <Stack alignItems="center" flexDirection="row" gap="0.25rem">
173
+ <MRT_ExpandButton {...expandButtonProps} />
174
+ <Tooltip
175
+ enterDelay={1000}
176
+ enterNextDelay={1000}
177
+ placement="right"
178
+ title={table.getColumn(row.groupingColumnId).columnDef.header}
179
+ >
180
+ <span>{row.groupingValue as ReactNode}</span>
181
+ </Tooltip>
182
+ {!!subRowsLength && <span>({subRowsLength})</span>}
183
+ </Stack>
184
+ );
185
+ } else {
186
+ return (
187
+ <>
188
+ <MRT_ExpandButton {...expandButtonProps} />
189
+ {column.columnDef.GroupedCell?.({ cell, column, row, table })}
190
+ </>
191
+ );
192
+ }
193
+ },
162
194
  Header: tableOptions.enableExpandAll
163
- ? ({ table }) => <MRT_ExpandAllButton table={table} />
195
+ ? ({ table }) => {
196
+ return (
197
+ <>
198
+ <MRT_ExpandAllButton table={table} />
199
+ {tableOptions.groupedColumnMode === 'remove' &&
200
+ grouping
201
+ .map(
202
+ (groupedColumnId) =>
203
+ table.getColumn(groupedColumnId).columnDef.header,
204
+ )
205
+ .join(', ')}
206
+ </>
207
+ );
208
+ }
164
209
  : undefined,
165
- ...defaultDisplayColumnProps(tableOptions, id, 'expand'),
210
+ ...defaultDisplayColumnProps(
211
+ tableOptions,
212
+ id,
213
+ 'expand',
214
+ tableOptions.groupedColumnMode === 'remove'
215
+ ? tableOptions?.defaultColumn?.size
216
+ : 60,
217
+ ),
166
218
  };
167
219
  }
168
220
  return null;
@@ -175,7 +227,13 @@ function makeRowSelectColumn<TData extends MRT_RowData>(
175
227
  const id: MRT_DisplayColumnIds = 'mrt-row-select';
176
228
  if (order.includes(id)) {
177
229
  return {
178
- Cell: ({ row, table }) => <MRT_SelectCheckbox row={row} table={table} />,
230
+ Cell: ({ row, staticRowIndex, table }) => (
231
+ <MRT_SelectCheckbox
232
+ row={row}
233
+ staticRowIndex={staticRowIndex}
234
+ table={table}
235
+ />
236
+ ),
179
237
  Header:
180
238
  tableOptions.enableSelectAll && tableOptions.enableMultiRowSelection
181
239
  ? ({ table }) => <MRT_SelectCheckbox selectAll table={table} />
@@ -193,7 +251,10 @@ function makeRowNumbersColumn<TData extends MRT_RowData>(
193
251
  const id: MRT_DisplayColumnIds = 'mrt-row-numbers';
194
252
  if (order.includes(id) || tableOptions.enableRowNumbers)
195
253
  return {
196
- Cell: ({ row }) => row.index + 1,
254
+ Cell: ({ row, staticRowIndex }) =>
255
+ ((tableOptions.rowNumberDisplayMode === 'static'
256
+ ? staticRowIndex
257
+ : row.index) ?? 0) + 1,
197
258
  Header: () => tableOptions.localization.rowNumber,
198
259
  ...defaultDisplayColumnProps(tableOptions, id, 'rowNumbers'),
199
260
  };
@@ -465,6 +465,8 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
465
465
  />
466
466
  ) : (
467
467
  <TextField
468
+ select={isSelectFilter || isMultiSelectFilter}
469
+ {...commonTextFieldProps}
468
470
  SelectProps={{
469
471
  displayEmpty: true,
470
472
  multiple: isMultiSelectFilter,
@@ -488,10 +490,9 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
488
490
  </Box>
489
491
  )
490
492
  : undefined,
493
+ ...commonTextFieldProps.SelectProps,
491
494
  }}
492
495
  onChange={handleTextFieldChange}
493
- select={isSelectFilter || isMultiSelectFilter}
494
- {...commonTextFieldProps}
495
496
  value={filterValue ?? ''}
496
497
  >
497
498
  {(isSelectFilter || isMultiSelectFilter) && [
@@ -1,4 +1,4 @@
1
- import { type MouseEvent } from 'react';
1
+ import { type ChangeEvent, type MouseEvent } from 'react';
2
2
  import Checkbox, { type CheckboxProps } from '@mui/material/Checkbox';
3
3
  import Radio, { type RadioProps } from '@mui/material/Radio';
4
4
  import Tooltip from '@mui/material/Tooltip';
@@ -13,12 +13,14 @@ import {
13
13
  interface Props<TData extends MRT_RowData> extends CheckboxProps {
14
14
  row?: MRT_Row<TData>;
15
15
  selectAll?: boolean;
16
+ staticRowIndex?: number;
16
17
  table: MRT_TableInstance<TData>;
17
18
  }
18
19
 
19
20
  export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
20
21
  row,
21
22
  selectAll,
23
+ staticRowIndex,
22
24
  table,
23
25
  ...rest
24
26
  }: Props<TData>) => {
@@ -39,18 +41,56 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
39
41
  const checkboxProps = {
40
42
  ...(!row
41
43
  ? parseFromValuesOrFunc(muiSelectAllCheckboxProps, { table })
42
- : parseFromValuesOrFunc(muiSelectCheckboxProps, { row, table })),
44
+ : parseFromValuesOrFunc(muiSelectCheckboxProps, {
45
+ row,
46
+ staticRowIndex,
47
+ table,
48
+ })),
43
49
  ...rest,
44
50
  };
45
51
 
52
+ const isStickySelection =
53
+ enableRowPinning && rowPinningDisplayMode?.includes('select');
54
+
46
55
  const allRowsSelected = selectAll
47
56
  ? selectAllMode === 'page'
48
57
  ? table.getIsAllPageRowsSelected()
49
58
  : table.getIsAllRowsSelected()
50
59
  : undefined;
51
60
 
61
+ const onSelectionChange = (
62
+ event: ChangeEvent<HTMLInputElement>,
63
+ row: MRT_Row<TData>,
64
+ ) => {
65
+ if (row.getIsAllSubRowsSelected()) {
66
+ row.subRows?.forEach((r) => r.toggleSelected(false));
67
+ }
68
+ row.getToggleSelectedHandler()(event);
69
+
70
+ if (isStickySelection) {
71
+ row.pin(
72
+ !row.getIsPinned() && event.target.checked
73
+ ? rowPinningDisplayMode?.includes('bottom')
74
+ ? 'bottom'
75
+ : 'top'
76
+ : false,
77
+ );
78
+ }
79
+ };
80
+
81
+ const onSelectAllChange = (event: ChangeEvent<HTMLInputElement>) => {
82
+ selectAllMode === 'all'
83
+ ? table.getToggleAllRowsSelectedHandler()(event)
84
+ : table.getToggleAllPageRowsSelectedHandler()(event);
85
+ if (isStickySelection) {
86
+ table.setRowPinning({ bottom: [], top: [] });
87
+ }
88
+ };
89
+
52
90
  const commonProps = {
53
- checked: selectAll ? allRowsSelected : row?.getIsSelected(),
91
+ checked: selectAll
92
+ ? allRowsSelected
93
+ : row?.getIsSelected() || row?.getIsAllSubRowsSelected(),
54
94
  disabled:
55
95
  isLoading || (row && !row.getCanSelect()) || row?.id === 'mrt-row-create',
56
96
  inputProps: {
@@ -60,24 +100,7 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
60
100
  },
61
101
  onChange: (event) => {
62
102
  event.stopPropagation();
63
- row
64
- ? row.getToggleSelectedHandler()(event)
65
- : selectAllMode === 'all'
66
- ? table.getToggleAllRowsSelectedHandler()(event)
67
- : table.getToggleAllPageRowsSelectedHandler()(event);
68
- if (enableRowPinning && rowPinningDisplayMode?.includes('select')) {
69
- if (row) {
70
- row.pin(
71
- !row.getIsPinned() && event.target.checked
72
- ? rowPinningDisplayMode?.includes('bottom')
73
- ? 'bottom'
74
- : 'top'
75
- : false,
76
- );
77
- } else {
78
- table.setRowPinning({ bottom: [], top: [] });
79
- }
80
- }
103
+ row ? onSelectionChange(event, row) : onSelectAllChange(event);
81
104
  },
82
105
  size: (density === 'compact' ? 'small' : 'medium') as 'medium' | 'small',
83
106
  ...checkboxProps,
@@ -89,8 +89,9 @@ export const MRT_ShowHideColumnsMenuItems = <TData extends MRT_RowData>({
89
89
  }
90
90
  };
91
91
 
92
- if (!columnDef.header || columnDef.visibleInShowHideMenu === false)
92
+ if (!columnDef.header || columnDef.visibleInShowHideMenu === false) {
93
93
  return null;
94
+ }
94
95
 
95
96
  return (
96
97
  <>
@@ -36,11 +36,23 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
36
36
  const { isFullScreen, showGlobalFilter } = getState();
37
37
 
38
38
  const isMobile = useMediaQuery('(max-width:720px)');
39
+ const isTablet = useMediaQuery('(max-width:1024px)');
39
40
 
40
41
  const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table });
41
42
 
42
43
  const stackAlertBanner =
43
- isMobile || !!renderTopToolbarCustomActions || showGlobalFilter;
44
+ isMobile ||
45
+ !!renderTopToolbarCustomActions ||
46
+ (showGlobalFilter && isTablet);
47
+
48
+ const globalFilterProps = {
49
+ sx: !isTablet
50
+ ? {
51
+ zIndex: 2,
52
+ }
53
+ : undefined,
54
+ table,
55
+ };
44
56
 
45
57
  return (
46
58
  <Box
@@ -83,7 +95,7 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
83
95
  }}
84
96
  >
85
97
  {enableGlobalFilter && positionGlobalFilter === 'left' && (
86
- <MRT_GlobalFilterTextField table={table} />
98
+ <MRT_GlobalFilterTextField {...globalFilterProps} />
87
99
  )}
88
100
  {renderTopToolbarCustomActions?.({ table }) ?? <span />}
89
101
  {enableToolbarInternalActions ? (
@@ -97,14 +109,14 @@ export const MRT_TopToolbar = <TData extends MRT_RowData>({
97
109
  }}
98
110
  >
99
111
  {enableGlobalFilter && positionGlobalFilter === 'right' && (
100
- <MRT_GlobalFilterTextField table={table} />
112
+ <MRT_GlobalFilterTextField {...globalFilterProps} />
101
113
  )}
102
114
  <MRT_ToolbarInternalButtons table={table} />
103
115
  </Box>
104
116
  ) : (
105
117
  enableGlobalFilter &&
106
118
  positionGlobalFilter === 'right' && (
107
- <MRT_GlobalFilterTextField table={table} />
119
+ <MRT_GlobalFilterTextField {...globalFilterProps} />
108
120
  )
109
121
  )}
110
122
  </Box>
package/src/types.ts CHANGED
@@ -385,6 +385,7 @@ export type MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown> = Omit<
385
385
  renderedCellValue: ReactNode;
386
386
  row: MRT_Row<TData>;
387
387
  rowRef?: RefObject<HTMLTableRowElement>;
388
+ staticRowIndex?: number;
388
389
  table: MRT_TableInstance<TData>;
389
390
  }) => ReactNode;
390
391
  Edit?: (props: {
@@ -674,10 +675,19 @@ export type MRT_HeaderGroup<TData extends MRT_RowData> = Omit<
674
675
 
675
676
  export type MRT_Row<TData extends MRT_RowData> = Omit<
676
677
  Row<TData>,
677
- '_valuesCache' | 'getAllCells' | 'getVisibleCells' | 'subRows'
678
+ | '_valuesCache'
679
+ | 'getAllCells'
680
+ | 'getParentRow'
681
+ | 'getParentRows'
682
+ | 'getRow'
683
+ | 'getVisibleCells'
684
+ | 'subRows'
678
685
  > & {
679
686
  _valuesCache: Record<LiteralUnion<string & DeepKeys<TData>>, any>;
680
687
  getAllCells: () => MRT_Cell<TData>[];
688
+ getParentRow: () => MRT_Row<TData> | null;
689
+ getParentRows: () => MRT_Row<TData>[];
690
+ getRow: () => MRT_Row<TData>;
681
691
  getVisibleCells: () => MRT_Cell<TData>[];
682
692
  subRows?: MRT_Row<TData>[];
683
693
  };
@@ -996,6 +1006,7 @@ export type MRT_TableOptions<TData extends MRT_RowData> = Omit<
996
1006
  muiSelectCheckboxProps?:
997
1007
  | ((props: {
998
1008
  row: MRT_Row<TData>;
1009
+ staticRowIndex?: number;
999
1010
  table: MRT_TableInstance<TData>;
1000
1011
  }) => CheckboxProps | RadioProps)
1001
1012
  | (CheckboxProps | RadioProps);