material-react-table 1.4.3 → 1.5.0-beta.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.
Files changed (43) hide show
  1. package/dist/cjs/index.js +183 -71
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/MaterialReactTable.d.ts +19 -6
  4. package/dist/cjs/types/body/MRT_TableBody.d.ts +5 -0
  5. package/dist/cjs/types/body/MRT_TableBodyCell.d.ts +3 -0
  6. package/dist/cjs/types/body/MRT_TableBodyRow.d.ts +5 -1
  7. package/dist/cjs/types/footer/MRT_TableFooter.d.ts +4 -0
  8. package/dist/cjs/types/footer/MRT_TableFooterRow.d.ts +4 -0
  9. package/dist/cjs/types/head/MRT_TableHead.d.ts +4 -0
  10. package/dist/cjs/types/head/MRT_TableHeadRow.d.ts +4 -0
  11. package/dist/cjs/types/table/MRT_TableRoot.d.ts +12 -5
  12. package/dist/cjs/types/toolbar/MRT_TablePagination.d.ts +1 -1
  13. package/dist/esm/material-react-table.esm.js +179 -67
  14. package/dist/esm/material-react-table.esm.js.map +1 -1
  15. package/dist/esm/types/MaterialReactTable.d.ts +19 -6
  16. package/dist/esm/types/body/MRT_TableBody.d.ts +5 -0
  17. package/dist/esm/types/body/MRT_TableBodyCell.d.ts +3 -0
  18. package/dist/esm/types/body/MRT_TableBodyRow.d.ts +5 -1
  19. package/dist/esm/types/footer/MRT_TableFooter.d.ts +4 -0
  20. package/dist/esm/types/footer/MRT_TableFooterRow.d.ts +4 -0
  21. package/dist/esm/types/head/MRT_TableHead.d.ts +4 -0
  22. package/dist/esm/types/head/MRT_TableHeadRow.d.ts +4 -0
  23. package/dist/esm/types/table/MRT_TableRoot.d.ts +12 -5
  24. package/dist/esm/types/toolbar/MRT_TablePagination.d.ts +1 -1
  25. package/dist/index.d.ts +21 -8
  26. package/locales/ru.esm.js +1 -1
  27. package/locales/ru.js +1 -1
  28. package/package.json +1 -1
  29. package/src/MaterialReactTable.tsx +48 -11
  30. package/src/_locales/ru.ts +1 -1
  31. package/src/body/MRT_TableBody.tsx +42 -13
  32. package/src/body/MRT_TableBodyCell.tsx +17 -1
  33. package/src/body/MRT_TableBodyRow.tsx +24 -3
  34. package/src/column.utils.ts +4 -1
  35. package/src/footer/MRT_TableFooter.tsx +13 -1
  36. package/src/footer/MRT_TableFooterCell.tsx +6 -1
  37. package/src/footer/MRT_TableFooterRow.tsx +27 -4
  38. package/src/head/MRT_TableHead.tsx +13 -1
  39. package/src/head/MRT_TableHeadCell.tsx +2 -2
  40. package/src/head/MRT_TableHeadRow.tsx +26 -4
  41. package/src/table/MRT_Table.tsx +105 -7
  42. package/src/table/MRT_TableRoot.tsx +1 -1
  43. package/src/toolbar/MRT_TablePagination.tsx +2 -2
@@ -3,24 +3,32 @@ import TableRow from '@mui/material/TableRow';
3
3
  import { darken, lighten, useTheme } from '@mui/material/styles';
4
4
  import { Memo_MRT_TableBodyCell, MRT_TableBodyCell } from './MRT_TableBodyCell';
5
5
  import { MRT_TableDetailPanel } from './MRT_TableDetailPanel';
6
- import type { VirtualItem } from '@tanstack/react-virtual';
7
- import type { MRT_Row, MRT_TableInstance } from '..';
6
+ import type { VirtualItem, Virtualizer } from '@tanstack/react-virtual';
7
+ import type { MRT_Cell, MRT_Row, MRT_TableInstance } from '..';
8
8
 
9
9
  interface Props {
10
+ columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
10
11
  measureElement?: (element: HTMLTableRowElement) => void;
11
12
  numRows: number;
12
13
  row: MRT_Row;
13
14
  rowIndex: number;
14
15
  table: MRT_TableInstance;
16
+ virtualColumns?: VirtualItem[];
17
+ virtualPaddingLeft?: number;
18
+ virtualPaddingRight?: number;
15
19
  virtualRow?: VirtualItem;
16
20
  }
17
21
 
18
22
  export const MRT_TableBodyRow: FC<Props> = ({
23
+ columnVirtualizer,
19
24
  measureElement,
20
25
  numRows,
21
26
  row,
22
27
  rowIndex,
23
28
  table,
29
+ virtualColumns,
30
+ virtualPaddingLeft,
31
+ virtualPaddingRight,
24
32
  virtualRow,
25
33
  }) => {
26
34
  const theme = useTheme();
@@ -108,15 +116,25 @@ export const MRT_TableBodyRow: FC<Props> = ({
108
116
  ...draggingBorders,
109
117
  })}
110
118
  >
111
- {row.getVisibleCells().map((cell) => {
119
+ {virtualPaddingLeft ? (
120
+ <td style={{ display: 'flex', width: virtualPaddingLeft }} />
121
+ ) : null}
122
+ {(virtualColumns ?? row.getVisibleCells()).map((cellOrVirtualCell) => {
123
+ const cell = columnVirtualizer
124
+ ? row.getVisibleCells()[(cellOrVirtualCell as VirtualItem).index]
125
+ : (cellOrVirtualCell as MRT_Cell);
112
126
  const props = {
113
127
  cell,
114
128
  enableHover: tableRowProps?.hover !== false,
115
129
  key: cell.id,
130
+ measureElement: columnVirtualizer?.measureElement,
116
131
  numRows,
117
132
  rowIndex,
118
133
  rowRef,
119
134
  table,
135
+ virtualCell: columnVirtualizer
136
+ ? (cellOrVirtualCell as VirtualItem)
137
+ : undefined,
120
138
  };
121
139
  return memoMode === 'cells' &&
122
140
  cell.column.columnDef.columnDefType === 'data' &&
@@ -129,6 +147,9 @@ export const MRT_TableBodyRow: FC<Props> = ({
129
147
  <MRT_TableBodyCell {...props} />
130
148
  );
131
149
  })}
150
+ {virtualPaddingRight ? (
151
+ <td style={{ display: 'flex', width: virtualPaddingRight }} />
152
+ ) : null}
132
153
  </TableRow>
133
154
  {renderDetailPanel && !row.getIsGrouped() && (
134
155
  <MRT_TableDetailPanel
@@ -266,7 +266,10 @@ export const getCommonCellStyles = ({
266
266
  column.getIsPinned() === 'right'
267
267
  ? `${getTotalRight(table, column)}px`
268
268
  : undefined,
269
- transition: `all ${column.getIsResizing() ? 0 : '150ms'} ease-in-out`,
269
+ transition:
270
+ table.options.enableColumnVirtualization || column.getIsResizing()
271
+ ? 'none'
272
+ : `all 150ms ease-in-out`,
270
273
  ...(tableCellProps?.sx instanceof Function
271
274
  ? tableCellProps.sx(theme)
272
275
  : (tableCellProps?.sx as any)),
@@ -2,13 +2,22 @@ import React, { FC } from 'react';
2
2
  import TableFooter from '@mui/material/TableFooter';
3
3
  import { lighten } from '@mui/material/styles';
4
4
  import { MRT_TableFooterRow } from './MRT_TableFooterRow';
5
+ import type { VirtualItem } from '@tanstack/react-virtual';
5
6
  import type { MRT_TableInstance } from '..';
6
7
 
7
8
  interface Props {
8
9
  table: MRT_TableInstance;
10
+ virtualColumns?: VirtualItem[];
11
+ virtualPaddingLeft?: number;
12
+ virtualPaddingRight?: number;
9
13
  }
10
14
 
11
- export const MRT_TableFooter: FC<Props> = ({ table }) => {
15
+ export const MRT_TableFooter: FC<Props> = ({
16
+ table,
17
+ virtualColumns,
18
+ virtualPaddingLeft,
19
+ virtualPaddingRight,
20
+ }) => {
12
21
  const {
13
22
  getFooterGroups,
14
23
  getState,
@@ -48,6 +57,9 @@ export const MRT_TableFooter: FC<Props> = ({ table }) => {
48
57
  footerGroup={footerGroup as any}
49
58
  key={footerGroup.id}
50
59
  table={table}
60
+ virtualColumns={virtualColumns}
61
+ virtualPaddingLeft={virtualPaddingLeft}
62
+ virtualPaddingRight={virtualPaddingRight}
51
63
  />
52
64
  ))}
53
65
  </TableFooter>
@@ -51,7 +51,12 @@ export const MRT_TableFooterCell: FC<Props> = ({ footer, table }) => {
51
51
  : '1.5rem',
52
52
  verticalAlign: 'top',
53
53
  zIndex: column.getIsPinned() && columnDefType !== 'group' ? 2 : 1,
54
- ...getCommonCellStyles({ column, table, theme, tableCellProps }),
54
+ ...getCommonCellStyles({
55
+ column,
56
+ table,
57
+ theme,
58
+ tableCellProps,
59
+ }),
55
60
  })}
56
61
  >
57
62
  <>
@@ -1,14 +1,24 @@
1
1
  import React, { FC } from 'react';
2
2
  import TableRow from '@mui/material/TableRow';
3
3
  import { MRT_TableFooterCell } from './MRT_TableFooterCell';
4
+ import { VirtualItem } from '@tanstack/react-virtual';
4
5
  import type { MRT_Header, MRT_HeaderGroup, MRT_TableInstance } from '..';
5
6
 
6
7
  interface Props {
7
8
  footerGroup: MRT_HeaderGroup;
8
9
  table: MRT_TableInstance;
10
+ virtualColumns?: VirtualItem[];
11
+ virtualPaddingLeft?: number;
12
+ virtualPaddingRight?: number;
9
13
  }
10
14
 
11
- export const MRT_TableFooterRow: FC<Props> = ({ footerGroup, table }) => {
15
+ export const MRT_TableFooterRow: FC<Props> = ({
16
+ footerGroup,
17
+ table,
18
+ virtualColumns,
19
+ virtualPaddingLeft,
20
+ virtualPaddingRight,
21
+ }) => {
12
22
  const {
13
23
  options: { layoutMode, muiTableFooterRowProps },
14
24
  } = table;
@@ -34,14 +44,27 @@ export const MRT_TableFooterRow: FC<Props> = ({ footerGroup, table }) => {
34
44
  {...tableRowProps}
35
45
  sx={(theme) => ({
36
46
  display: layoutMode === 'grid' ? 'flex' : 'table-row',
47
+ width: '100%',
37
48
  ...(tableRowProps?.sx instanceof Function
38
49
  ? tableRowProps?.sx(theme)
39
50
  : (tableRowProps?.sx as any)),
40
51
  })}
41
52
  >
42
- {footerGroup.headers.map((footer: MRT_Header) => (
43
- <MRT_TableFooterCell footer={footer} key={footer.id} table={table} />
44
- ))}
53
+ {virtualPaddingLeft ? (
54
+ <th style={{ display: 'flex', width: virtualPaddingLeft }} />
55
+ ) : null}
56
+ {(virtualColumns ?? footerGroup.headers).map((footerOrVirtualFooter) => {
57
+ const footer = virtualColumns
58
+ ? footerGroup.headers[footerOrVirtualFooter.index]
59
+ : (footerOrVirtualFooter as MRT_Header);
60
+
61
+ return (
62
+ <MRT_TableFooterCell footer={footer} key={footer.id} table={table} />
63
+ );
64
+ })}
65
+ {virtualPaddingRight ? (
66
+ <th style={{ display: 'flex', width: virtualPaddingRight }} />
67
+ ) : null}
45
68
  </TableRow>
46
69
  );
47
70
  };
@@ -1,13 +1,22 @@
1
1
  import React, { FC } from 'react';
2
2
  import TableHead from '@mui/material/TableHead';
3
3
  import { MRT_TableHeadRow } from './MRT_TableHeadRow';
4
+ import type { VirtualItem } from '@tanstack/react-virtual';
4
5
  import type { MRT_TableInstance } from '..';
5
6
 
6
7
  interface Props {
7
8
  table: MRT_TableInstance;
9
+ virtualColumns?: VirtualItem[];
10
+ virtualPaddingLeft?: number;
11
+ virtualPaddingRight?: number;
8
12
  }
9
13
 
10
- export const MRT_TableHead: FC<Props> = ({ table }) => {
14
+ export const MRT_TableHead: FC<Props> = ({
15
+ table,
16
+ virtualColumns,
17
+ virtualPaddingLeft,
18
+ virtualPaddingRight,
19
+ }) => {
11
20
  const {
12
21
  getHeaderGroups,
13
22
  getState,
@@ -41,6 +50,9 @@ export const MRT_TableHead: FC<Props> = ({ table }) => {
41
50
  headerGroup={headerGroup as any}
42
51
  key={headerGroup.id}
43
52
  table={table}
53
+ virtualColumns={virtualColumns}
54
+ virtualPaddingLeft={virtualPaddingLeft}
55
+ virtualPaddingRight={virtualPaddingRight}
44
56
  />
45
57
  ))}
46
58
  </TableHead>
@@ -123,9 +123,9 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
123
123
  align={columnDefType === 'group' ? 'center' : 'left'}
124
124
  colSpan={header.colSpan}
125
125
  onDragEnter={handleDragEnter}
126
- ref={(node) => {
126
+ ref={(node: HTMLTableCellElement) => {
127
127
  if (node) {
128
- tableHeadCellRefs.current[column.id] = node as HTMLTableCellElement;
128
+ tableHeadCellRefs.current[column.id] = node;
129
129
  }
130
130
  }}
131
131
  {...tableCellProps}
@@ -2,14 +2,24 @@ import React, { FC } from 'react';
2
2
  import TableRow from '@mui/material/TableRow';
3
3
  import { alpha, lighten } from '@mui/material/styles';
4
4
  import { MRT_TableHeadCell } from './MRT_TableHeadCell';
5
+ import type { VirtualItem } from '@tanstack/react-virtual';
5
6
  import type { MRT_Header, MRT_HeaderGroup, MRT_TableInstance } from '..';
6
7
 
7
8
  interface Props {
8
9
  headerGroup: MRT_HeaderGroup;
9
10
  table: MRT_TableInstance;
11
+ virtualColumns?: VirtualItem[];
12
+ virtualPaddingLeft?: number;
13
+ virtualPaddingRight?: number;
10
14
  }
11
15
 
12
- export const MRT_TableHeadRow: FC<Props> = ({ headerGroup, table }) => {
16
+ export const MRT_TableHeadRow: FC<Props> = ({
17
+ headerGroup,
18
+ table,
19
+ virtualColumns,
20
+ virtualPaddingLeft,
21
+ virtualPaddingRight,
22
+ }) => {
13
23
  const {
14
24
  options: { layoutMode, muiTableHeadRowProps },
15
25
  } = table;
@@ -32,9 +42,21 @@ export const MRT_TableHeadRow: FC<Props> = ({ headerGroup, table }) => {
32
42
  : (tableRowProps?.sx as any)),
33
43
  })}
34
44
  >
35
- {headerGroup.headers.map((header: MRT_Header) => (
36
- <MRT_TableHeadCell header={header} key={header.id} table={table} />
37
- ))}
45
+ {virtualPaddingLeft ? (
46
+ <th style={{ display: 'flex', width: virtualPaddingLeft }} />
47
+ ) : null}
48
+ {(virtualColumns ?? headerGroup.headers).map((headerOrVirtualHeader) => {
49
+ const header = virtualColumns
50
+ ? headerGroup.headers[headerOrVirtualHeader.index]
51
+ : (headerOrVirtualHeader as MRT_Header);
52
+
53
+ return (
54
+ <MRT_TableHeadCell header={header} key={header.id} table={table} />
55
+ );
56
+ })}
57
+ {virtualPaddingRight ? (
58
+ <th style={{ display: 'flex', width: virtualPaddingRight }} />
59
+ ) : null}
38
60
  </TableRow>
39
61
  );
40
62
  };
@@ -1,4 +1,10 @@
1
- import React, { FC } from 'react';
1
+ import React, { FC, useCallback, useMemo } from 'react';
2
+ import {
3
+ defaultRangeExtractor,
4
+ Range,
5
+ useVirtualizer,
6
+ Virtualizer,
7
+ } from '@tanstack/react-virtual';
2
8
  import Table from '@mui/material/Table';
3
9
  import { MRT_TableHead } from '../head/MRT_TableHead';
4
10
  import { Memo_MRT_TableBody, MRT_TableBody } from '../body/MRT_TableBody';
@@ -13,7 +19,11 @@ export const MRT_Table: FC<Props> = ({ table }) => {
13
19
  const {
14
20
  getState,
15
21
  options: {
22
+ columnVirtualizerInstanceRef,
23
+ columnVirtualizerProps,
16
24
  enableColumnResizing,
25
+ enableColumnVirtualization,
26
+ enablePinning,
17
27
  enableStickyHeader,
18
28
  enableTableFooter,
19
29
  enableTableHead,
@@ -21,33 +31,121 @@ export const MRT_Table: FC<Props> = ({ table }) => {
21
31
  memoMode,
22
32
  muiTableProps,
23
33
  },
34
+ refs: { tableContainerRef },
24
35
  } = table;
25
- const { isFullScreen } = getState();
36
+ const { isFullScreen, columnPinning, columnVisibility } = getState();
26
37
 
27
38
  const tableProps =
28
39
  muiTableProps instanceof Function
29
40
  ? muiTableProps({ table })
30
41
  : muiTableProps;
31
42
 
43
+ const vProps =
44
+ columnVirtualizerProps instanceof Function
45
+ ? columnVirtualizerProps({ table })
46
+ : columnVirtualizerProps;
47
+
48
+ //get first 16 column widths and average them
49
+ const averageColumnWidth = useMemo(() => {
50
+ const columnsWidths =
51
+ table
52
+ .getRowModel()
53
+ .rows[0]?.getCenterVisibleCells()
54
+ ?.slice(0, 16)
55
+ ?.map((cell) => cell.column.getSize() * 1.25) ?? [];
56
+ return columnsWidths.reduce((a, b) => a + b, 0) / columnsWidths.length;
57
+ }, [table.getRowModel().rows, columnPinning, columnVisibility]);
58
+
59
+ const pinnedColumnIndexes = useMemo(
60
+ () =>
61
+ enableColumnVirtualization && enablePinning
62
+ ? [
63
+ ...table.getLeftFlatHeaders().map((h) => h.column.getPinnedIndex()),
64
+ ...table
65
+ .getRightFlatHeaders()
66
+ .map(
67
+ (h) =>
68
+ table.getVisibleFlatColumns().length -
69
+ h.column.getPinnedIndex() -
70
+ 1,
71
+ ),
72
+ ]
73
+ : [],
74
+ [columnPinning, enableColumnVirtualization, enablePinning],
75
+ );
76
+
77
+ const columnVirtualizer:
78
+ | Virtualizer<HTMLDivElement, HTMLTableCellElement>
79
+ | undefined = enableColumnVirtualization
80
+ ? useVirtualizer({
81
+ count: table.getRowModel().rows[0].getVisibleCells().length,
82
+ estimateSize: () => averageColumnWidth,
83
+ getScrollElement: () => tableContainerRef.current,
84
+ horizontal: true,
85
+ measureElement: (element) => element?.getBoundingClientRect().width,
86
+ overscan: 3,
87
+ rangeExtractor: useCallback(
88
+ (range: Range) =>
89
+ [
90
+ ...new Set([
91
+ ...pinnedColumnIndexes,
92
+ ...defaultRangeExtractor(range),
93
+ ]),
94
+ ].sort((a, b) => a - b),
95
+ [pinnedColumnIndexes],
96
+ ),
97
+ ...vProps,
98
+ })
99
+ : undefined;
100
+
101
+ if (columnVirtualizerInstanceRef && columnVirtualizer) {
102
+ columnVirtualizerInstanceRef.current = columnVirtualizer;
103
+ }
104
+
105
+ const virtualColumns = columnVirtualizer
106
+ ? columnVirtualizer.getVirtualItems()
107
+ : undefined;
108
+
109
+ let virtualPaddingLeft: number | undefined;
110
+ let virtualPaddingRight: number | undefined;
111
+
112
+ if (columnVirtualizer && virtualColumns?.length) {
113
+ virtualPaddingLeft = virtualColumns?.length
114
+ ? virtualColumns[0]?.start || 0
115
+ : 0;
116
+ virtualPaddingRight = virtualColumns?.length
117
+ ? columnVirtualizer.getTotalSize() -
118
+ (virtualColumns[virtualColumns.length - 1]?.end || 0)
119
+ : 0;
120
+ }
121
+
122
+ const props = {
123
+ table,
124
+ virtualColumns,
125
+ virtualPaddingLeft,
126
+ virtualPaddingRight,
127
+ };
128
+
32
129
  return (
33
130
  <Table
34
131
  stickyHeader={enableStickyHeader || isFullScreen}
35
132
  {...tableProps}
36
133
  sx={(theme) => ({
37
134
  display: layoutMode === 'grid' ? 'grid' : 'table',
38
- tableLayout: enableColumnResizing ? 'fixed' : 'auto',
135
+ tableLayout:
136
+ layoutMode !== 'grid' && enableColumnResizing ? 'fixed' : undefined,
39
137
  ...(tableProps?.sx instanceof Function
40
138
  ? tableProps.sx(theme)
41
139
  : (tableProps?.sx as any)),
42
140
  })}
43
141
  >
44
- {enableTableHead && <MRT_TableHead table={table} />}
142
+ {enableTableHead && <MRT_TableHead {...props} />}
45
143
  {memoMode === 'table-body' ? (
46
- <Memo_MRT_TableBody table={table} />
144
+ <Memo_MRT_TableBody columnVirtualizer={columnVirtualizer} {...props} />
47
145
  ) : (
48
- <MRT_TableBody table={table} />
146
+ <MRT_TableBody columnVirtualizer={columnVirtualizer} {...props} />
49
147
  )}
50
- {enableTableFooter && <MRT_TableFooter table={table} />}
148
+ {enableTableFooter && <MRT_TableFooter {...props} />}
51
149
  </Table>
52
150
  );
53
151
  };
@@ -239,7 +239,7 @@ export const MRT_TableRoot = <TData extends Record<string, any> = {}>(
239
239
  {},
240
240
  ...getAllLeafColumnDefs(props.columns as MRT_ColumnDef[]).map(
241
241
  (col) => ({
242
- [col.id ?? col.accessorKey ?? '']: null,
242
+ [getColumnId(col)]: null,
243
243
  }),
244
244
  ),
245
245
  ),
@@ -3,13 +3,13 @@ import TablePagination from '@mui/material/TablePagination';
3
3
  import { MRT_TableInstance } from '..';
4
4
 
5
5
  interface Props<TData extends Record<string, any> = {}> {
6
- position: 'top' | 'bottom';
6
+ position?: 'top' | 'bottom';
7
7
  table: MRT_TableInstance<TData>;
8
8
  }
9
9
 
10
10
  export const MRT_TablePagination = <TData extends Record<string, any> = {}>({
11
11
  table,
12
- position,
12
+ position = 'bottom',
13
13
  }: Props<TData>) => {
14
14
  const {
15
15
  getPrePaginationRowModel,