material-react-table 2.11.1 → 2.11.3

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 (30) hide show
  1. package/dist/index.d.ts +18 -20
  2. package/dist/index.esm.js +104 -125
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +104 -129
  5. package/dist/index.js.map +1 -1
  6. package/package.json +21 -21
  7. package/src/components/body/MRT_TableBody.tsx +1 -1
  8. package/src/components/body/MRT_TableBodyCell.tsx +4 -6
  9. package/src/components/body/MRT_TableBodyCellValue.tsx +5 -4
  10. package/src/components/body/MRT_TableBodyRow.tsx +5 -7
  11. package/src/components/body/MRT_TableDetailPanel.tsx +2 -4
  12. package/src/components/footer/MRT_TableFooterRow.tsx +6 -3
  13. package/src/components/head/MRT_TableHeadCell.tsx +2 -3
  14. package/src/components/head/MRT_TableHeadRow.tsx +7 -3
  15. package/src/components/inputs/MRT_SelectCheckbox.tsx +12 -20
  16. package/src/components/menus/MRT_CellActionMenu.tsx +1 -5
  17. package/src/components/menus/MRT_ColumnActionMenu.tsx +1 -5
  18. package/src/components/menus/MRT_FilterOptionMenu.tsx +1 -5
  19. package/src/components/menus/MRT_RowActionMenu.tsx +1 -5
  20. package/src/components/menus/MRT_ShowHideColumnsMenu.tsx +1 -5
  21. package/src/components/menus/MRT_ShowHideColumnsMenuItems.tsx +3 -2
  22. package/src/components/table/MRT_TableLoadingOverlay.tsx +8 -8
  23. package/src/components/table/MRT_TablePaper.tsx +2 -2
  24. package/src/components/toolbar/MRT_ToolbarAlertBanner.tsx +6 -6
  25. package/src/hooks/useMRT_Rows.ts +1 -2
  26. package/src/hooks/useMRT_TableOptions.ts +4 -0
  27. package/src/types.ts +15 -13
  28. package/src/utils/column.utils.ts +0 -48
  29. package/src/utils/row.utils.ts +59 -24
  30. package/src/utils/style.utils.ts +24 -26
@@ -7,6 +7,7 @@ import Chip from '@mui/material/Chip';
7
7
  import Collapse from '@mui/material/Collapse';
8
8
  import Stack from '@mui/material/Stack';
9
9
  import { type MRT_RowData, type MRT_TableInstance } from '../../types';
10
+ import { getMRT_SelectAllHandler } from '../../utils/row.utils';
10
11
  import { parseFromValuesOrFunc } from '../../utils/utils';
11
12
  import { MRT_SelectCheckbox } from '../inputs/MRT_SelectCheckbox';
12
13
 
@@ -36,7 +37,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
36
37
  renderToolbarAlertBannerContent,
37
38
  rowCount,
38
39
  },
39
- refs: { lastSelectedRowId, tablePaperRef },
40
+ refs: { tablePaperRef },
40
41
  } = table;
41
42
  const { density, grouping, rowSelection, showAlertBanner } = getState();
42
43
 
@@ -51,7 +52,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
51
52
  table,
52
53
  });
53
54
 
54
- const totalRowCount = rowCount ?? getPrePaginationRowModel().rows.length;
55
+ const totalRowCount = rowCount ?? getPrePaginationRowModel().flatRows.length;
55
56
 
56
57
  const selectedRowCount = useMemo(
57
58
  () =>
@@ -67,10 +68,9 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
67
68
  ?.replace('{selectedCount}', selectedRowCount.toLocaleString())
68
69
  ?.replace('{rowCount}', totalRowCount.toString())}
69
70
  <Button
70
- onClick={() => {
71
- table.toggleAllRowsSelected(false);
72
- lastSelectedRowId.current = null;
73
- }}
71
+ onClick={(event) =>
72
+ getMRT_SelectAllHandler({ table })(event, false, true)
73
+ }
74
74
  size="small"
75
75
  sx={{ p: '2px' }}
76
76
  >
@@ -8,7 +8,6 @@ import { getMRT_Rows } from '../utils/row.utils';
8
8
 
9
9
  export const useMRT_Rows = <TData extends MRT_RowData>(
10
10
  table: MRT_TableInstance<TData>,
11
- pinnedRowIds: string[] = [],
12
11
  ): MRT_Row<TData>[] => {
13
12
  const {
14
13
  getRowModel,
@@ -25,7 +24,7 @@ export const useMRT_Rows = <TData extends MRT_RowData>(
25
24
  } = getState();
26
25
 
27
26
  const rows = useMemo(
28
- () => getMRT_Rows(table, pinnedRowIds),
27
+ () => getMRT_Rows(table),
29
28
  [
30
29
  creatingRow,
31
30
  data,
@@ -21,6 +21,7 @@ import {
21
21
  type MRT_RowData,
22
22
  type MRT_TableOptions,
23
23
  } from '../types';
24
+ import { getMRTTheme } from '../utils/style.utils';
24
25
 
25
26
  export const MRT_DefaultColumn = {
26
27
  filterVariant: 'text',
@@ -96,6 +97,7 @@ export const useMRT_TableOptions: <TData extends MRT_RowData>(
96
97
  manualGrouping,
97
98
  manualPagination,
98
99
  manualSorting,
100
+ mrtTheme,
99
101
  paginationDisplayMode = 'default',
100
102
  positionActionsColumn = 'first',
101
103
  positionCreatingRow = 'top',
@@ -120,6 +122,7 @@ export const useMRT_TableOptions: <TData extends MRT_RowData>(
120
122
  }),
121
123
  [localization],
122
124
  );
125
+ mrtTheme = useMemo(() => getMRTTheme(mrtTheme, theme), [mrtTheme, theme]);
123
126
  aggregationFns = useMemo(
124
127
  () => ({ ...MRT_AggregationFns, ...aggregationFns }),
125
128
  [],
@@ -241,6 +244,7 @@ export const useMRT_TableOptions: <TData extends MRT_RowData>(
241
244
  manualGrouping,
242
245
  manualPagination,
243
246
  manualSorting,
247
+ mrtTheme,
244
248
  paginationDisplayMode,
245
249
  positionActionsColumn,
246
250
  positionCreatingRow,
package/src/types.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import {
2
- type CSSProperties,
3
2
  type Dispatch,
4
3
  type MutableRefObject,
5
4
  type ReactNode,
@@ -257,12 +256,12 @@ export interface MRT_Localization {
257
256
  }
258
257
 
259
258
  export interface MRT_Theme {
260
- baseBackgroundColor?: CSSProperties['backgroundColor'];
261
- draggingBorderColor?: CSSProperties['borderColor'];
262
- matchHighlightColor?: CSSProperties['backgroundColor'];
263
- menuBackgroundColor?: CSSProperties['backgroundColor'];
264
- pinnedRowBackgroundColor?: CSSProperties['backgroundColor'];
265
- selectedRowBackgroundColor?: CSSProperties['backgroundColor'];
259
+ baseBackgroundColor: string;
260
+ draggingBorderColor: string;
261
+ matchHighlightColor: string;
262
+ menuBackgroundColor: string;
263
+ pinnedRowBackgroundColor: string;
264
+ selectedRowBackgroundColor: string;
266
265
  }
267
266
 
268
267
  export interface MRT_RowModel<TData extends MRT_RowData> {
@@ -348,11 +347,14 @@ export type MRT_TableInstance<TData extends MRT_RowData> = Omit<
348
347
  setShowToolbarDropZone: Dispatch<SetStateAction<boolean>>;
349
348
  };
350
349
 
351
- export type MRT_DefinedTableOptions<TData extends MRT_RowData> =
352
- MRT_TableOptions<TData> & {
353
- icons: MRT_Icons;
354
- localization: MRT_Localization;
355
- };
350
+ export type MRT_DefinedTableOptions<TData extends MRT_RowData> = Omit<
351
+ MRT_TableOptions<TData>,
352
+ 'icons' | 'localization' | 'mrtTheme'
353
+ > & {
354
+ icons: MRT_Icons;
355
+ localization: MRT_Localization;
356
+ mrtTheme: Required<MRT_Theme>;
357
+ };
356
358
 
357
359
  export type MRT_StatefulTableOptions<TData extends MRT_RowData> =
358
360
  MRT_DefinedTableOptions<TData> & {
@@ -914,7 +916,7 @@ export type MRT_TableOptions<TData extends MRT_RowData> = Omit<
914
916
  * @link https://www.material-react-table.com/docs/guides/memoize-components
915
917
  */
916
918
  memoMode?: 'cells' | 'rows' | 'table-body';
917
- mrtTheme?: ((theme: Theme) => MRT_Theme) | MRT_Theme;
919
+ mrtTheme?: ((theme: Theme) => Partial<MRT_Theme>) | Partial<MRT_Theme>;
918
920
  muiBottomToolbarProps?:
919
921
  | ((props: { table: MRT_TableInstance<TData> }) => BoxProps)
920
922
  | BoxProps;
@@ -7,7 +7,6 @@ import {
7
7
  type MRT_DefinedTableOptions,
8
8
  type MRT_FilterOption,
9
9
  type MRT_RowData,
10
- type MRT_TableInstance,
11
10
  } from '../types';
12
11
 
13
12
  export const getColumnId = <TData extends MRT_RowData>(
@@ -122,50 +121,3 @@ export const getDefaultColumnFilterFn = <TData extends MRT_RowData>(
122
121
  return 'equals';
123
122
  return 'fuzzy';
124
123
  };
125
-
126
- export const getIsFirstColumn = <TData extends MRT_RowData>(
127
- column: MRT_Column<TData>,
128
- table: MRT_TableInstance<TData>,
129
- ) => {
130
- const leftColumns = table.getLeftVisibleLeafColumns();
131
- return leftColumns.length
132
- ? leftColumns[0].id === column.id
133
- : table.getVisibleLeafColumns()[0].id === column.id;
134
- };
135
-
136
- export const getIsLastColumn = <TData extends MRT_RowData>(
137
- column: MRT_Column<TData>,
138
- table: MRT_TableInstance<TData>,
139
- ) => {
140
- const rightColumns = table.getRightVisibleLeafColumns();
141
- const columns = table.getVisibleLeafColumns();
142
- return rightColumns.length
143
- ? rightColumns[rightColumns.length - 1].id === column.id
144
- : columns[columns.length - 1].id === column.id;
145
- };
146
-
147
- export const getIsLastLeftPinnedColumn = <TData extends MRT_RowData>(
148
- table: MRT_TableInstance<TData>,
149
- column: MRT_Column<TData>,
150
- ) => {
151
- return (
152
- column.getIsPinned() === 'left' &&
153
- table.getLeftLeafHeaders().length - 1 === column.getPinnedIndex()
154
- );
155
- };
156
-
157
- export const getIsFirstRightPinnedColumn = <TData extends MRT_RowData>(
158
- column: MRT_Column<TData>,
159
- ) => {
160
- return column.getIsPinned() === 'right' && column.getPinnedIndex() === 0;
161
- };
162
-
163
- export const getTotalRight = <TData extends MRT_RowData>(
164
- table: MRT_TableInstance<TData>,
165
- column: MRT_Column<TData>,
166
- ) => {
167
- return table
168
- .getRightLeafHeaders()
169
- .slice(column.getPinnedIndex() + 1)
170
- .reduce((acc, col) => acc + col.getSize(), 0);
171
- };
@@ -9,11 +9,9 @@ import { parseFromValuesOrFunc } from './utils';
9
9
 
10
10
  export const getMRT_Rows = <TData extends MRT_RowData>(
11
11
  table: MRT_TableInstance<TData>,
12
- pinnedRowIds: string[] = [],
13
12
  all?: boolean,
14
13
  ): MRT_Row<TData>[] => {
15
14
  const {
16
- getBottomRows,
17
15
  getCenterRows,
18
16
  getPrePaginationRowModel,
19
17
  getRowModel,
@@ -41,6 +39,7 @@ export const getMRT_Rows = <TData extends MRT_RowData>(
41
39
  : getRowModel().rows
42
40
  : getCenterRows();
43
41
  } else {
42
+ // fuzzy ranking adjustments
44
43
  rows = getPrePaginationRowModel().rows.sort((a, b) =>
45
44
  rankGlobalFuzzy(a, b),
46
45
  );
@@ -48,14 +47,23 @@ export const getMRT_Rows = <TData extends MRT_RowData>(
48
47
  const start = pagination.pageIndex * pagination.pageSize;
49
48
  rows = rows.slice(start, start + pagination.pageSize);
50
49
  }
50
+ if (enableRowPinning && !rowPinningDisplayMode?.includes('sticky')) {
51
+ // "re-center-ize" the rows (no top or bottom pinned rows unless sticky)
52
+ rows = rows.filter((row) => !row.getIsPinned());
53
+ }
51
54
  }
55
+ // row pinning adjustments
52
56
  if (enableRowPinning && rowPinningDisplayMode?.includes('sticky')) {
57
+ const centerPinnedRowIds = rows
58
+ .filter((row) => row.getIsPinned())
59
+ .map((r) => r.id);
60
+
53
61
  rows = [
54
- ...getTopRows().filter((row) => !pinnedRowIds.includes(row.id)),
62
+ ...getTopRows().filter((row) => !centerPinnedRowIds.includes(row.id)),
55
63
  ...rows,
56
- ...getBottomRows().filter((row) => !pinnedRowIds.includes(row.id)),
57
64
  ];
58
65
  }
66
+ // blank inserted creating row adjustments
59
67
  if (
60
68
  positionCreatingRow !== undefined &&
61
69
  creatingRow &&
@@ -135,22 +143,24 @@ export const getIsRowSelected = <TData extends MRT_RowData>({
135
143
  };
136
144
 
137
145
  export const getMRT_RowSelectionHandler =
138
- () =>
139
146
  <TData extends MRT_RowData>({
140
- event,
141
147
  row,
142
148
  staticRowIndex = 0,
143
149
  table,
144
150
  }: {
145
- event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLTableRowElement>;
146
151
  row: MRT_Row<TData>;
147
152
  staticRowIndex?: number;
148
153
  table: MRT_TableInstance<TData>;
149
- }) => {
154
+ }) =>
155
+ (
156
+ event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLTableRowElement>,
157
+ value?: boolean,
158
+ ) => {
150
159
  const {
151
160
  getState,
152
161
  options: {
153
162
  enableBatchRowSelection,
163
+ enableMultiRowSelection,
154
164
  enableRowPinning,
155
165
  manualPagination,
156
166
  rowPinningDisplayMode,
@@ -163,21 +173,21 @@ export const getMRT_RowSelectionHandler =
163
173
 
164
174
  const paginationOffset = manualPagination ? 0 : pageSize * pageIndex;
165
175
 
166
- const isCurrentRowChecked = getIsRowSelected({ row, table });
167
-
168
- const isStickySelection =
169
- enableRowPinning && rowPinningDisplayMode?.includes('select');
176
+ const wasCurrentRowChecked = getIsRowSelected({ row, table });
170
177
 
171
178
  // toggle selection of this row
172
- row.getToggleSelectedHandler()(event);
179
+ row.toggleSelected(value ?? !wasCurrentRowChecked);
180
+
181
+ const changedRowIds = new Set<string>([row.id]);
173
182
 
174
183
  // if shift key is pressed, select all rows between last selected and this one
175
184
  if (
176
185
  enableBatchRowSelection &&
186
+ enableMultiRowSelection &&
177
187
  (event as any).nativeEvent.shiftKey &&
178
188
  lastSelectedRowId.current !== null
179
189
  ) {
180
- const rows = getMRT_Rows(table, undefined, true);
190
+ const rows = getMRT_Rows(table, true);
181
191
 
182
192
  const lastIndex = rows.findIndex(
183
193
  (r) => r.id === lastSelectedRowId.current,
@@ -197,9 +207,10 @@ export const getMRT_RowSelectionHandler =
197
207
 
198
208
  // toggle selection of all rows between last selected and this one
199
209
  // but only if the last selected row is not the same as the current one
200
- if (isCurrentRowChecked !== isLastIndexChecked) {
210
+ if (wasCurrentRowChecked !== isLastIndexChecked) {
201
211
  for (let i = start; i <= end; i++) {
202
- rows[i].toggleSelected(!isCurrentRowChecked);
212
+ rows[i].toggleSelected(!wasCurrentRowChecked);
213
+ changedRowIds.add(rows[i].id);
203
214
  }
204
215
  }
205
216
  }
@@ -213,13 +224,37 @@ export const getMRT_RowSelectionHandler =
213
224
  row.subRows?.forEach((r) => r.toggleSelected(false));
214
225
  }
215
226
 
216
- if (isStickySelection) {
217
- row.pin(
218
- !row.getIsPinned() && isCurrentRowChecked
219
- ? rowPinningDisplayMode?.includes('bottom')
220
- ? 'bottom'
221
- : 'top'
222
- : false,
223
- );
227
+ if (enableRowPinning && rowPinningDisplayMode?.includes('select')) {
228
+ changedRowIds.forEach((rowId) => {
229
+ const rowToTogglePin = table.getRow(rowId);
230
+ rowToTogglePin.pin(
231
+ !wasCurrentRowChecked //was not previously pinned or selected
232
+ ? rowPinningDisplayMode?.includes('bottom')
233
+ ? 'bottom'
234
+ : 'top'
235
+ : false,
236
+ );
237
+ });
238
+ }
239
+ };
240
+
241
+ export const getMRT_SelectAllHandler =
242
+ <TData extends MRT_RowData>({ table }: { table: MRT_TableInstance<TData> }) =>
243
+ (
244
+ event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>,
245
+ value?: boolean,
246
+ forceAll?: boolean,
247
+ ) => {
248
+ const {
249
+ options: { enableRowPinning, rowPinningDisplayMode, selectAllMode },
250
+ refs: { lastSelectedRowId },
251
+ } = table;
252
+
253
+ selectAllMode === 'all' || forceAll
254
+ ? table.toggleAllRowsSelected(value ?? (event as any).target.checked)
255
+ : table.toggleAllPageRowsSelected(value ?? (event as any).target.checked);
256
+ if (enableRowPinning && rowPinningDisplayMode?.includes('select')) {
257
+ table.setRowPinning({ bottom: [], top: [] });
224
258
  }
259
+ lastSelectedRowId.current = null;
225
260
  };
@@ -8,37 +8,34 @@ import {
8
8
  type MRT_Header,
9
9
  type MRT_RowData,
10
10
  type MRT_TableInstance,
11
+ type MRT_TableOptions,
12
+ type MRT_Theme,
11
13
  } from '../types';
12
- import {
13
- getIsFirstRightPinnedColumn,
14
- getIsLastLeftPinnedColumn,
15
- getTotalRight,
16
- } from '../utils/column.utils';
17
14
  import { parseFromValuesOrFunc } from './utils';
18
15
 
19
16
  export const parseCSSVarId = (id: string) => id.replace(/[^a-zA-Z0-9]/g, '_');
20
17
 
21
18
  export const getMRTTheme = <TData extends MRT_RowData>(
22
- table: MRT_TableInstance<TData>,
23
- theme: Theme,
24
- ) => {
25
- const themeOverrides = parseFromValuesOrFunc(table.options.mrtTheme, theme);
19
+ mrtTheme: MRT_TableOptions<TData>['mrtTheme'],
20
+ muiTheme: Theme,
21
+ ): MRT_Theme => {
22
+ const mrtThemeOverrides = parseFromValuesOrFunc(mrtTheme, muiTheme);
26
23
  const baseBackgroundColor =
27
- themeOverrides?.baseBackgroundColor ??
28
- (theme.palette.mode === 'dark'
29
- ? lighten(theme.palette.background.default, 0.05)
30
- : theme.palette.background.default);
24
+ mrtThemeOverrides?.baseBackgroundColor ??
25
+ (muiTheme.palette.mode === 'dark'
26
+ ? lighten(muiTheme.palette.background.default, 0.05)
27
+ : muiTheme.palette.background.default);
31
28
  return {
32
29
  baseBackgroundColor,
33
- draggingBorderColor: theme.palette.primary.main,
30
+ draggingBorderColor: muiTheme.palette.primary.main,
34
31
  matchHighlightColor:
35
- theme.palette.mode === 'dark'
36
- ? darken(theme.palette.warning.dark, 0.25)
37
- : lighten(theme.palette.warning.light, 0.5),
32
+ muiTheme.palette.mode === 'dark'
33
+ ? darken(muiTheme.palette.warning.dark, 0.25)
34
+ : lighten(muiTheme.palette.warning.light, 0.5),
38
35
  menuBackgroundColor: lighten(baseBackgroundColor, 0.07),
39
- pinnedRowBackgroundColor: alpha(theme.palette.primary.main, 0.1),
40
- selectedRowBackgroundColor: alpha(theme.palette.primary.main, 0.2),
41
- ...themeOverrides,
36
+ pinnedRowBackgroundColor: alpha(muiTheme.palette.primary.main, 0.1),
37
+ selectedRowBackgroundColor: alpha(muiTheme.palette.primary.main, 0.2),
38
+ ...mrtThemeOverrides,
42
39
  };
43
40
  };
44
41
 
@@ -61,7 +58,9 @@ export const getCommonPinnedCellStyles = <TData extends MRT_RowData>({
61
58
  table: MRT_TableInstance<TData>;
62
59
  theme: Theme;
63
60
  }) => {
64
- const { baseBackgroundColor } = getMRTTheme(table, theme);
61
+ const { baseBackgroundColor } = table.options.mrtTheme;
62
+ const isPinned = column?.getIsPinned();
63
+
65
64
  return {
66
65
  '&[data-pinned="true"]': {
67
66
  '&:before': {
@@ -73,9 +72,9 @@ export const getCommonPinnedCellStyles = <TData extends MRT_RowData>({
73
72
  0.97,
74
73
  ),
75
74
  boxShadow: column
76
- ? getIsLastLeftPinnedColumn(table, column)
75
+ ? isPinned === 'left' && column.getIsLastColumn(isPinned)
77
76
  ? `-4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
78
- : getIsFirstRightPinnedColumn(column)
77
+ : isPinned === 'right' && column.getIsFirstColumn(isPinned)
79
78
  ? `4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
80
79
  : undefined
81
80
  : undefined,
@@ -141,7 +140,7 @@ export const getCommonMRTCellStyles = <TData extends MRT_RowData>({
141
140
  position: 'sticky',
142
141
  right:
143
142
  isColumnPinned === 'right'
144
- ? `${getTotalRight(table, column)}px`
143
+ ? `${column.getAfter('right')}px`
145
144
  : undefined,
146
145
  }
147
146
  : {};
@@ -179,13 +178,12 @@ export const getCommonMRTCellStyles = <TData extends MRT_RowData>({
179
178
 
180
179
  export const getCommonToolbarStyles = <TData extends MRT_RowData>({
181
180
  table,
182
- theme,
183
181
  }: {
184
182
  table: MRT_TableInstance<TData>;
185
183
  theme: Theme;
186
184
  }) => ({
187
185
  alignItems: 'flex-start',
188
- backgroundColor: getMRTTheme(table, theme).baseBackgroundColor,
186
+ backgroundColor: table.options.mrtTheme.baseBackgroundColor,
189
187
  display: 'grid',
190
188
  flexWrap: 'wrap-reverse',
191
189
  minHeight: '3.5rem',