material-react-table 0.30.1 → 0.31.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.
@@ -0,0 +1,7 @@
1
+ import { FC } from 'react';
2
+ import { MRT_TableInstance } from '..';
3
+ interface Props {
4
+ table: MRT_TableInstance;
5
+ }
6
+ export declare const MRT_ToolbarDropZone: FC<Props>;
7
+ export {};
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.30.1",
2
+ "version": "0.31.1",
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.",
@@ -49,11 +49,11 @@
49
49
  "size-limit": [
50
50
  {
51
51
  "path": "dist/material-react-table.cjs.production.min.js",
52
- "limit": "40 KB"
52
+ "limit": "50 KB"
53
53
  },
54
54
  {
55
55
  "path": "dist/material-react-table.esm.js",
56
- "limit": "40 KB"
56
+ "limit": "50 KB"
57
57
  }
58
58
  ],
59
59
  "devDependencies": {
@@ -82,9 +82,6 @@
82
82
  "react": "^18.2.0",
83
83
  "react-dom": "^18.2.0",
84
84
  "react-is": "^18.2.0",
85
- "rollup-plugin-commonjs": "^10.1.0",
86
- "rollup-plugin-node-resolve": "^5.2.0",
87
- "rollup-plugin-peer-deps-external": "^2.2.4",
88
85
  "size-limit": "^7.0.8",
89
86
  "storybook-dark-mode": "^1.1.0",
90
87
  "tsdx": "^0.14.1",
@@ -100,7 +97,7 @@
100
97
  },
101
98
  "dependencies": {
102
99
  "@tanstack/match-sorter-utils": "8.1.1",
103
- "@tanstack/react-table": "8.4.0",
100
+ "@tanstack/react-table": "8.5.2",
104
101
  "@tanstack/react-virtual": "^3.0.0-beta.13"
105
102
  }
106
103
  }
@@ -104,8 +104,12 @@ export type MRT_TableInstance<TData extends Record<string, any> = {}> = Omit<
104
104
  }>
105
105
  >;
106
106
  setCurrentGlobalFilterFn: Dispatch<SetStateAction<MRT_FilterOption>>;
107
- setCurrentHoveredColumn: Dispatch<SetStateAction<MRT_Column<TData> | null>>;
108
- setCurrentHoveredRow: Dispatch<SetStateAction<MRT_Row | null>>;
107
+ setCurrentHoveredColumn: Dispatch<
108
+ SetStateAction<MRT_Column<TData> | { id: string } | null>
109
+ >;
110
+ setCurrentHoveredRow: Dispatch<
111
+ SetStateAction<MRT_Row<TData> | { id: string } | null>
112
+ >;
109
113
  setDensity: Dispatch<SetStateAction<'comfortable' | 'compact' | 'spacious'>>;
110
114
  setIsFullScreen: Dispatch<SetStateAction<boolean>>;
111
115
  setShowAlertBanner: Dispatch<SetStateAction<boolean>>;
@@ -121,8 +125,8 @@ export type MRT_TableState<TData extends Record<string, any> = {}> =
121
125
  currentEditingRow: MRT_Row<TData> | null;
122
126
  currentFilterFns: Record<string, MRT_FilterOption>;
123
127
  currentGlobalFilterFn: Record<string, MRT_FilterOption>;
124
- currentHoveredColumn: MRT_Column<TData> | null;
125
- currentHoveredRow: MRT_Row<TData> | null;
128
+ currentHoveredColumn: MRT_Column<TData> | { id: string } | null;
129
+ currentHoveredRow: MRT_Row<TData> | { id: string } | null;
126
130
  density: 'comfortable' | 'compact' | 'spacious';
127
131
  isFullScreen: boolean;
128
132
  isLoading: boolean;
@@ -390,13 +394,17 @@ export type MRT_Cell<TData extends Record<string, any> = {}> = Omit<
390
394
  row: MRT_Row<TData>;
391
395
  };
392
396
 
393
- export type MRT_SortingOption = keyof typeof MRT_SortingFns;
397
+ export type MRT_SortingOption = LiteralUnion<
398
+ string & keyof typeof MRT_SortingFns
399
+ >;
394
400
 
395
401
  export type MRT_SortingFn<TData extends Record<string, any> = {}> =
396
402
  | SortingFn<TData>
397
403
  | MRT_SortingOption;
398
404
 
399
- export type MRT_FilterOption = keyof typeof MRT_FilterFns;
405
+ export type MRT_FilterOption = LiteralUnion<
406
+ string & keyof typeof MRT_FilterFns
407
+ >;
400
408
 
401
409
  export type MRT_FilterFn<TData extends Record<string, any> = {}> =
402
410
  | FilterFn<TData>
@@ -685,7 +693,7 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
685
693
  }: {
686
694
  event: DragEvent<HTMLButtonElement>;
687
695
  draggedColumn: MRT_Column<TData>;
688
- targetColumn: MRT_Column<TData> | null;
696
+ targetColumn: MRT_Column<TData> | { id: string } | null;
689
697
  }) => void;
690
698
  onCurrentDraggingColumnChange?: OnChangeFn<MRT_Column<TData> | null>;
691
699
  onCurrentDraggingRowChange?: OnChangeFn<MRT_Row<TData> | null>;
@@ -711,7 +719,7 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
711
719
  }: {
712
720
  event: DragEvent<HTMLButtonElement>;
713
721
  draggedRow: MRT_Row<TData>;
714
- targetRow: MRT_Row<TData> | null;
722
+ targetRow: MRT_Row<TData> | { id: string } | null;
715
723
  }) => void;
716
724
  onShowAlertBannerChange?: OnChangeFn<boolean>;
717
725
  onShowFiltersChange?: OnChangeFn<boolean>;
@@ -721,7 +729,8 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
721
729
  positionExpandColumn?: 'first' | 'last';
722
730
  positionGlobalFilter?: 'left' | 'right';
723
731
  positionPagination?: 'bottom' | 'top' | 'both';
724
- positionToolbarAlertBanner?: 'bottom' | 'top';
732
+ positionToolbarAlertBanner?: 'bottom' | 'top' | 'none';
733
+ positionToolbarDropZone?: 'bottom' | 'top' | 'none' | 'both';
725
734
  renderDetailPanel?: ({
726
735
  row,
727
736
  table,
@@ -829,6 +838,7 @@ export default <TData extends Record<string, any> = {}>({
829
838
  positionGlobalFilter = 'right',
830
839
  positionPagination = 'bottom',
831
840
  positionToolbarAlertBanner = 'top',
841
+ positionToolbarDropZone = 'top',
832
842
  rowNumberMode = 'original',
833
843
  selectAllMode = 'all',
834
844
  ...rest
@@ -872,6 +882,7 @@ export default <TData extends Record<string, any> = {}>({
872
882
  positionGlobalFilter={positionGlobalFilter}
873
883
  positionPagination={positionPagination}
874
884
  positionToolbarAlertBanner={positionToolbarAlertBanner}
885
+ positionToolbarDropZone={positionToolbarDropZone}
875
886
  rowNumberMode={rowNumberMode}
876
887
  selectAllMode={selectAllMode}
877
888
  {...rest}
@@ -35,6 +35,7 @@ export const MRT_TableBodyCell: FC<Props> = ({
35
35
  enableClickToCopy,
36
36
  enableColumnOrdering,
37
37
  enableEditing,
38
+ enableGrouping,
38
39
  enablePagination,
39
40
  enableRowNumbers,
40
41
  muiTableBodyCellProps,
@@ -129,6 +130,9 @@ export const MRT_TableBodyCell: FC<Props> = ({
129
130
  };
130
131
 
131
132
  const handleDragEnter = (_e: DragEvent) => {
133
+ if (enableGrouping && currentHoveredColumn?.id === 'drop-zone') {
134
+ setCurrentHoveredColumn(null);
135
+ }
132
136
  if (enableColumnOrdering && currentDraggingColumn) {
133
137
  setCurrentHoveredColumn(
134
138
  columnDef.enableColumnOrdering !== false ? column : null,
@@ -51,6 +51,7 @@ export const prepareColumns = <TData extends Record<string, any> = {}>(
51
51
  } else if (columnDef.columnDefType === 'data') {
52
52
  if (Object.keys(MRT_FilterFns).includes(currentFilterFns[columnDef.id])) {
53
53
  columnDef.filterFn =
54
+ // @ts-ignore
54
55
  MRT_FilterFns[currentFilterFns[columnDef.id]] ?? MRT_FilterFns.fuzzy;
55
56
  //@ts-ignore
56
57
  columnDef._filterFn = currentFilterFns[columnDef.id];
@@ -28,7 +28,12 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
28
28
  },
29
29
  setCurrentHoveredColumn,
30
30
  } = table;
31
- const { density, currentDraggingColumn, currentHoveredColumn } = getState();
31
+ const {
32
+ density,
33
+ currentDraggingColumn,
34
+ currentHoveredColumn,
35
+ showColumnFilters,
36
+ } = getState();
32
37
  const { column } = header;
33
38
  const { columnDef } = column;
34
39
  const { columnDefType } = columnDef;
@@ -66,6 +71,9 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
66
71
  };
67
72
 
68
73
  const handleDragEnter = (_e: DragEvent) => {
74
+ if (enableGrouping && currentHoveredColumn?.id === 'drop-zone') {
75
+ setCurrentHoveredColumn(null);
76
+ }
69
77
  if (enableColumnOrdering && currentDraggingColumn) {
70
78
  setCurrentHoveredColumn(
71
79
  columnDef.enableColumnOrdering !== false ? column : null,
@@ -136,7 +144,12 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
136
144
  : columnDefType === 'display'
137
145
  ? '1rem 1.25rem'
138
146
  : '1.5rem',
139
- pb: columnDefType === 'display' ? 0 : undefined,
147
+ pb:
148
+ columnDefType === 'display'
149
+ ? 0
150
+ : showColumnFilters || density === 'compact'
151
+ ? '0.4rem'
152
+ : '0.6rem',
140
153
  position:
141
154
  column.getIsPinned() && columnDefType !== 'group'
142
155
  ? 'sticky'
@@ -55,12 +55,16 @@ export const MRT_TableHeadCellGrabHandle: FC<Props> = ({
55
55
  draggedColumn: column,
56
56
  targetColumn: currentHoveredColumn,
57
57
  });
58
- if (
58
+ if (currentHoveredColumn?.id === 'drop-zone') {
59
+ column.toggleGrouping();
60
+ } else if (
59
61
  enableColumnOrdering &&
60
62
  currentHoveredColumn &&
61
63
  currentHoveredColumn?.id !== currentDraggingColumn?.id
62
64
  ) {
63
- setColumnOrder(reorderColumn(column, currentHoveredColumn, columnOrder));
65
+ setColumnOrder(
66
+ reorderColumn(column, currentHoveredColumn as MRT_Column, columnOrder),
67
+ );
64
68
  }
65
69
  setCurrentDraggingColumn(null);
66
70
  setCurrentHoveredColumn(null);
@@ -250,7 +250,7 @@ export const MRT_FilterTextField: FC<Props> = ({
250
250
  )}
251
251
  </InputAdornment>
252
252
  ) : (
253
- <FilterListIcon />
253
+ <FilterListIcon style={{ marginRight: '4px' }} />
254
254
  ),
255
255
  endAdornment: !filterChipLabel && (
256
256
  <InputAdornment position="end">
@@ -297,7 +297,7 @@ export const MRT_FilterTextField: FC<Props> = ({
297
297
  sx={(theme) => ({
298
298
  p: 0,
299
299
  minWidth: !filterChipLabel ? '6rem' : 'auto',
300
- width: 'calc(100% + 0.5rem)',
300
+ width: '100%',
301
301
  '& .MuiSelect-icon': {
302
302
  mr: '1.5rem',
303
303
  },
@@ -311,30 +311,32 @@ export const MRT_FilterTextField: FC<Props> = ({
311
311
  <Box sx={{ opacity: 0.5 }}>{filterPlaceholder}</Box>
312
312
  </MenuItem>
313
313
  )}
314
- {columnDef?.filterSelectOptions?.map((option) => {
315
- let value: string;
316
- let text: string;
317
- if (typeof option !== 'object') {
318
- value = option;
319
- text = option;
320
- } else {
321
- value = option.value;
322
- text = option.text;
323
- }
324
- return (
325
- <MenuItem key={value} value={value}>
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>
335
- </MenuItem>
336
- );
337
- })}
314
+ {columnDef?.filterSelectOptions?.map(
315
+ (option: string | { text: string; value: string }) => {
316
+ let value: string;
317
+ let text: string;
318
+ if (typeof option !== 'object') {
319
+ value = option;
320
+ text = option;
321
+ } else {
322
+ value = option.value;
323
+ text = option.text;
324
+ }
325
+ return (
326
+ <MenuItem key={value} value={value}>
327
+ {isMultiSelectFilter && (
328
+ <Checkbox
329
+ checked={(
330
+ (column.getFilterValue() ?? []) as string[]
331
+ ).includes(value)}
332
+ sx={{ mr: '0.5rem' }}
333
+ />
334
+ )}
335
+ <ListItemText>{text}</ListItemText>
336
+ </MenuItem>
337
+ );
338
+ },
339
+ )}
338
340
  </TextField>
339
341
  <MRT_FilterOptionMenu
340
342
  anchorEl={anchorEl}
@@ -86,7 +86,7 @@ export const MRT_GlobalFilterTextField: FC<Props> = ({ table }) => {
86
86
  </Tooltip>
87
87
  </InputAdornment>
88
88
  ) : (
89
- <SearchIcon />
89
+ <SearchIcon style={{ marginRight: '4px' }} />
90
90
  ),
91
91
  endAdornment: (
92
92
  <InputAdornment position="end">
@@ -10,6 +10,7 @@ export interface MRT_Localization {
10
10
  clickToCopy: string;
11
11
  columnActions: string;
12
12
  copiedToClipboard: string;
13
+ dropToGroupBy: string;
13
14
  edit: string;
14
15
  expand: string;
15
16
  expandAll: string;
@@ -91,6 +92,7 @@ export const MRT_DefaultLocalization_EN: MRT_Localization = {
91
92
  clickToCopy: 'Click to copy',
92
93
  columnActions: 'Column Actions',
93
94
  copiedToClipboard: 'Copied to clipboard',
95
+ dropToGroupBy: 'Drop to group by {column}',
94
96
  edit: 'Edit',
95
97
  expand: 'Expand',
96
98
  expandAll: 'Expand all',
@@ -80,12 +80,12 @@ export const MRT_TableRoot = <TData extends Record<string, any> = {}>(
80
80
  useState<MRT_Cell<TData> | null>(initialState.currentEditingCell ?? null);
81
81
  const [currentEditingRow, setCurrentEditingRow] =
82
82
  useState<MRT_Row<TData> | null>(initialState.currentEditingRow ?? null);
83
- const [currentHoveredColumn, setCurrentHoveredColumn] =
84
- useState<MRT_Column<TData> | null>(
85
- initialState.currentHoveredColumn ?? null,
86
- );
87
- const [currentHoveredRow, setCurrentHoveredRow] =
88
- useState<MRT_Row<TData> | null>(initialState.currentHoveredRow ?? null);
83
+ const [currentHoveredColumn, setCurrentHoveredColumn] = useState<
84
+ MRT_Column<TData> | { id: string } | null
85
+ >(initialState.currentHoveredColumn ?? null);
86
+ const [currentHoveredRow, setCurrentHoveredRow] = useState<
87
+ MRT_Row<TData> | { id: string } | null
88
+ >(initialState.currentHoveredRow ?? null);
89
89
  const [density, setDensity] = useState(
90
90
  initialState?.density ?? 'comfortable',
91
91
  );
@@ -248,12 +248,14 @@ export const MRT_TableRoot = <TData extends Record<string, any> = {}>(
248
248
  getPaginationRowModel: getPaginationRowModel(),
249
249
  getSortedRowModel: getSortedRowModel(),
250
250
  onColumnOrderChange: setColumnOrder,
251
+ getSubRows: (row) => row?.subRows,
251
252
  ...props,
252
253
  //@ts-ignore
253
254
  columns: columnDefs,
254
255
  data,
255
- getSubRows: (row) => row?.subRows,
256
+
256
257
  globalFilterFn:
258
+ //@ts-ignore
257
259
  MRT_FilterFns[currentGlobalFilterFn] ?? MRT_FilterFns.fuzzy,
258
260
  initialState,
259
261
  state: {
@@ -5,6 +5,7 @@ import { MRT_ToolbarAlertBanner } from './MRT_ToolbarAlertBanner';
5
5
  import { MRT_LinearProgressBar } from './MRT_LinearProgressBar';
6
6
  import { commonToolbarStyles } from './MRT_ToolbarTop';
7
7
  import { MRT_TableInstance } from '..';
8
+ import { MRT_ToolbarDropZone } from './MRT_ToolbarDropZone';
8
9
 
9
10
  interface Props {
10
11
  table: MRT_TableInstance;
@@ -18,6 +19,7 @@ export const MRT_ToolbarBottom: FC<Props> = ({ table }) => {
18
19
  muiTableToolbarBottomProps,
19
20
  positionPagination,
20
21
  positionToolbarAlertBanner,
22
+ positionToolbarDropZone,
21
23
  renderToolbarBottomCustomActions,
22
24
  tableId,
23
25
  },
@@ -56,6 +58,9 @@ export const MRT_ToolbarBottom: FC<Props> = ({ table }) => {
56
58
  {positionToolbarAlertBanner === 'bottom' && (
57
59
  <MRT_ToolbarAlertBanner table={table} />
58
60
  )}
61
+ {['both', 'bottom'].includes(positionToolbarDropZone ?? '') && (
62
+ <MRT_ToolbarDropZone table={table} />
63
+ )}
59
64
  <Box
60
65
  sx={{
61
66
  display: 'flex',
@@ -0,0 +1,54 @@
1
+ import React, { DragEvent, FC } from 'react';
2
+ import { alpha, Box, Fade, Typography } from '@mui/material';
3
+ import { MRT_TableInstance } from '..';
4
+
5
+ interface Props {
6
+ table: MRT_TableInstance;
7
+ }
8
+
9
+ export const MRT_ToolbarDropZone: FC<Props> = ({ table }) => {
10
+ const {
11
+ getState,
12
+ options: { enableGrouping, localization },
13
+ setCurrentHoveredColumn,
14
+ } = table;
15
+
16
+ const { currentDraggingColumn, currentHoveredColumn } = getState();
17
+
18
+ const handleDragEnter = (_event: DragEvent<HTMLDivElement>) => {
19
+ setCurrentHoveredColumn({ id: 'drop-zone' });
20
+ };
21
+
22
+ return (
23
+ <Fade
24
+ unmountOnExit
25
+ mountOnEnter
26
+ in={!!enableGrouping && !!currentDraggingColumn}
27
+ >
28
+ <Box
29
+ sx={(theme) => ({
30
+ alignItems: 'center',
31
+ backgroundColor: alpha(
32
+ theme.palette.info.main,
33
+ currentHoveredColumn?.id === 'drop-zone' ? 0.2 : 0.1,
34
+ ),
35
+ border: `dashed ${theme.palette.info.main} 2px`,
36
+ display: 'flex',
37
+ justifyContent: 'center',
38
+ height: 'calc(100% - 4px)',
39
+ position: 'absolute',
40
+ width: 'calc(100% - 4px)',
41
+ zIndex: 2,
42
+ })}
43
+ onDragEnter={handleDragEnter}
44
+ >
45
+ <Typography>
46
+ {localization.dropToGroupBy.replace(
47
+ '{column}',
48
+ currentDraggingColumn?.columnDef?.header ?? '',
49
+ )}
50
+ </Typography>
51
+ </Box>
52
+ </Fade>
53
+ );
54
+ };
@@ -6,6 +6,7 @@ import { MRT_TableInstance } from '..';
6
6
  import { MRT_TablePagination } from './MRT_TablePagination';
7
7
  import { MRT_ToolbarAlertBanner } from './MRT_ToolbarAlertBanner';
8
8
  import { MRT_ToolbarInternalButtons } from './MRT_ToolbarInternalButtons';
9
+ import { MRT_ToolbarDropZone } from './MRT_ToolbarDropZone';
9
10
 
10
11
  export const commonToolbarStyles = ({ theme }: { theme: Theme }) => ({
11
12
  alignItems: 'flex-start',
@@ -34,6 +35,7 @@ export const MRT_ToolbarTop: FC<Props> = ({ table }) => {
34
35
  positionGlobalFilter,
35
36
  positionPagination,
36
37
  positionToolbarAlertBanner,
38
+ positionToolbarDropZone,
37
39
  renderToolbarTopCustomActions,
38
40
  tableId,
39
41
  },
@@ -73,6 +75,9 @@ export const MRT_ToolbarTop: FC<Props> = ({ table }) => {
73
75
  table={table}
74
76
  />
75
77
  )}
78
+ {['both', 'top'].includes(positionToolbarDropZone ?? '') && (
79
+ <MRT_ToolbarDropZone table={table} />
80
+ )}
76
81
  <Box
77
82
  sx={{
78
83
  alignItems: 'flex-start',