material-react-table 2.0.0-alpha.0 → 2.0.0-alpha.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 (98) hide show
  1. package/dist/cjs/index.js +437 -384
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/body/MRT_TableBodyRow.d.ts +3 -2
  4. package/dist/cjs/types/body/MRT_TableBodyRowPinButton.d.ts +7 -0
  5. package/dist/cjs/types/body/index.d.ts +1 -0
  6. package/dist/cjs/types/buttons/MRT_RowPinButton.d.ts +9 -0
  7. package/dist/cjs/types/buttons/index.d.ts +2 -1
  8. package/dist/cjs/types/column.utils.d.ts +1 -0
  9. package/dist/cjs/types/types.d.ts +15 -9
  10. package/dist/esm/material-react-table.esm.js +433 -383
  11. package/dist/esm/material-react-table.esm.js.map +1 -1
  12. package/dist/esm/types/body/MRT_TableBodyRow.d.ts +3 -2
  13. package/dist/esm/types/body/MRT_TableBodyRowPinButton.d.ts +7 -0
  14. package/dist/esm/types/body/index.d.ts +1 -0
  15. package/dist/esm/types/buttons/MRT_RowPinButton.d.ts +9 -0
  16. package/dist/esm/types/buttons/index.d.ts +2 -1
  17. package/dist/esm/types/column.utils.d.ts +1 -0
  18. package/dist/esm/types/types.d.ts +15 -9
  19. package/dist/index.d.ts +68 -47
  20. package/locales/en.esm.js +1 -0
  21. package/locales/en.esm.js.map +1 -1
  22. package/locales/en.js +1 -0
  23. package/locales/en.js.map +1 -1
  24. package/package.json +9 -9
  25. package/src/body/MRT_TableBody.tsx +178 -74
  26. package/src/body/MRT_TableBodyCell.tsx +23 -21
  27. package/src/body/MRT_TableBodyRow.tsx +104 -16
  28. package/src/body/MRT_TableBodyRowGrabHandle.tsx +5 -4
  29. package/src/body/MRT_TableBodyRowPinButton.tsx +46 -0
  30. package/src/body/MRT_TableDetailPanel.tsx +13 -19
  31. package/src/body/index.ts +2 -1
  32. package/src/buttons/MRT_CopyButton.tsx +14 -20
  33. package/src/buttons/MRT_ExpandAllButton.tsx +5 -7
  34. package/src/buttons/MRT_ExpandButton.tsx +6 -7
  35. package/src/buttons/MRT_GrabHandleButton.tsx +2 -3
  36. package/src/buttons/MRT_RowPinButton.tsx +74 -0
  37. package/src/buttons/MRT_ToggleRowActionMenuButton.tsx +2 -3
  38. package/src/buttons/index.ts +2 -1
  39. package/src/column.utils.ts +11 -5
  40. package/src/footer/MRT_TableFooter.tsx +13 -7
  41. package/src/footer/MRT_TableFooterCell.tsx +7 -20
  42. package/src/footer/MRT_TableFooterRow.tsx +6 -7
  43. package/src/head/MRT_TableHead.tsx +11 -7
  44. package/src/head/MRT_TableHeadCell.tsx +9 -20
  45. package/src/head/MRT_TableHeadCellColumnActionsButton.tsx +10 -18
  46. package/src/head/MRT_TableHeadCellGrabHandle.tsx +6 -13
  47. package/src/head/MRT_TableHeadRow.tsx +6 -7
  48. package/src/hooks/useMRT_DisplayColumns.tsx +13 -0
  49. package/src/hooks/useMRT_TableInstance.ts +6 -0
  50. package/src/hooks/useMRT_TableOptions.ts +6 -2
  51. package/src/inputs/MRT_EditCellTextField.tsx +14 -22
  52. package/src/inputs/MRT_FilterCheckbox.tsx +11 -23
  53. package/src/inputs/MRT_FilterRangeSlider.tsx +6 -23
  54. package/src/inputs/MRT_FilterTextField.tsx +9 -25
  55. package/src/inputs/MRT_GlobalFilterTextField.tsx +4 -4
  56. package/src/inputs/MRT_SelectCheckbox.tsx +31 -17
  57. package/src/locales/en.ts +1 -1
  58. package/src/menus/MRT_RowActionMenu.tsx +11 -12
  59. package/src/modals/MRT_EditRowModal.tsx +5 -13
  60. package/src/table/MRT_Table.tsx +8 -13
  61. package/src/table/MRT_TableContainer.tsx +6 -12
  62. package/src/table/MRT_TablePaper.tsx +9 -13
  63. package/src/toolbar/MRT_BottomToolbar.tsx +14 -20
  64. package/src/toolbar/MRT_LinearProgressBar.tsx +5 -4
  65. package/src/toolbar/MRT_TablePagination.tsx +5 -7
  66. package/src/toolbar/MRT_ToolbarAlertBanner.tsx +8 -11
  67. package/src/toolbar/MRT_TopToolbar.tsx +8 -14
  68. package/src/types.ts +25 -8
  69. package/locales/tr.d.ts +0 -2
  70. package/locales/tr.esm.d.ts +0 -2
  71. package/locales/tr.esm.js +0 -93
  72. package/locales/tr.esm.js.map +0 -1
  73. package/locales/tr.js +0 -97
  74. package/locales/tr.js.map +0 -1
  75. package/locales/uk.d.ts +0 -2
  76. package/locales/uk.esm.d.ts +0 -2
  77. package/locales/uk.esm.js +0 -93
  78. package/locales/uk.esm.js.map +0 -1
  79. package/locales/uk.js +0 -97
  80. package/locales/uk.js.map +0 -1
  81. package/locales/vi.d.ts +0 -2
  82. package/locales/vi.esm.d.ts +0 -2
  83. package/locales/vi.esm.js +0 -93
  84. package/locales/vi.esm.js.map +0 -1
  85. package/locales/vi.js +0 -97
  86. package/locales/vi.js.map +0 -1
  87. package/locales/zh-Hans.d.ts +0 -2
  88. package/locales/zh-Hans.esm.d.ts +0 -2
  89. package/locales/zh-Hans.esm.js +0 -93
  90. package/locales/zh-Hans.esm.js.map +0 -1
  91. package/locales/zh-Hans.js +0 -97
  92. package/locales/zh-Hans.js.map +0 -1
  93. package/locales/zh-Hant.d.ts +0 -2
  94. package/locales/zh-Hant.esm.d.ts +0 -2
  95. package/locales/zh-Hant.esm.js +0 -93
  96. package/locales/zh-Hant.esm.js.map +0 -1
  97. package/locales/zh-Hant.js +0 -97
  98. package/locales/zh-Hant.js.map +0 -1
@@ -9,6 +9,7 @@ import Typography from '@mui/material/Typography';
9
9
  import { Memo_MRT_TableBodyRow, MRT_TableBodyRow } from './MRT_TableBodyRow';
10
10
  import { rankGlobalFuzzy } from '../sortingFns';
11
11
  import { type MRT_Row, type MRT_TableInstance } from '../types';
12
+ import { parseFromValuesOrFunc } from '../column.utils';
12
13
 
13
14
  interface Props<TData extends Record<string, any>> {
14
15
  columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
@@ -26,13 +27,20 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
26
27
  virtualPaddingRight,
27
28
  }: Props<TData>) => {
28
29
  const {
29
- getRowModel,
30
+ getBottomRows,
31
+ getCenterRows,
30
32
  getPrePaginationRowModel,
33
+ getRowModel,
31
34
  getState,
35
+ getIsSomeRowsPinned,
36
+ getTopRows,
32
37
  options: {
33
38
  enableGlobalFilterRankedResults,
34
39
  enablePagination,
40
+ enableRowPinning,
35
41
  enableRowVirtualization,
42
+ enableStickyHeader,
43
+ enableStickyFooter,
36
44
  layoutMode,
37
45
  localization,
38
46
  manualExpanding,
@@ -43,10 +51,11 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
43
51
  memoMode,
44
52
  muiTableBodyProps,
45
53
  renderEmptyRowsFallback,
54
+ rowPinningDisplayMode,
46
55
  rowVirtualizerInstanceRef,
47
56
  rowVirtualizerOptions,
48
57
  },
49
- refs: { tableContainerRef, tablePaperRef },
58
+ refs: { tableContainerRef, tablePaperRef, tableFooterRef, tableHeadRef },
50
59
  } = table;
51
60
  const {
52
61
  columnFilters,
@@ -56,17 +65,21 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
56
65
  globalFilterFn,
57
66
  pagination,
58
67
  sorting,
68
+ rowPinning,
69
+ isFullScreen,
59
70
  } = getState();
60
71
 
61
- const tableBodyProps =
62
- muiTableBodyProps instanceof Function
63
- ? muiTableBodyProps({ table })
64
- : muiTableBodyProps;
72
+ const tableBodyProps = parseFromValuesOrFunc(muiTableBodyProps, { table });
73
+ const rowVirtualizerProps = parseFromValuesOrFunc(rowVirtualizerOptions, {
74
+ table,
75
+ });
65
76
 
66
- const vProps =
67
- rowVirtualizerOptions instanceof Function
68
- ? rowVirtualizerOptions({ table })
69
- : rowVirtualizerOptions;
77
+ const tableHeadHeight =
78
+ ((enableStickyHeader || isFullScreen) &&
79
+ tableHeadRef.current?.clientHeight) ||
80
+ 0;
81
+ const tableFooterHeight =
82
+ (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
70
83
 
71
84
  const shouldRankResults = useMemo(
72
85
  () =>
@@ -92,21 +105,45 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
92
105
  ],
93
106
  );
94
107
 
108
+ const pinnedRowIds = useMemo(
109
+ () =>
110
+ getRowModel()
111
+ .rows.filter((row) => row.getIsPinned())
112
+ .map((r) => r.id),
113
+ [rowPinning, table.getRowModel().rows],
114
+ );
115
+
95
116
  const rows = useMemo(() => {
96
- if (!shouldRankResults) return getRowModel().rows;
97
- const rankedRows = getPrePaginationRowModel().rows.sort((a, b) =>
98
- rankGlobalFuzzy(a, b),
99
- );
100
- if (enablePagination && !manualPagination) {
101
- const start = pagination.pageIndex * pagination.pageSize;
102
- return rankedRows.slice(start, start + pagination.pageSize);
117
+ let rows = [];
118
+ if (!shouldRankResults) {
119
+ rows =
120
+ !enableRowPinning || rowPinningDisplayMode?.includes('sticky')
121
+ ? getRowModel().rows
122
+ : getCenterRows();
123
+ } else {
124
+ rows = getPrePaginationRowModel().rows.sort((a, b) =>
125
+ rankGlobalFuzzy(a, b),
126
+ );
127
+ if (enablePagination && !manualPagination) {
128
+ const start = pagination.pageIndex * pagination.pageSize;
129
+ rows = rows.slice(start, start + pagination.pageSize);
130
+ }
131
+ }
132
+ if (enableRowPinning && rowPinningDisplayMode?.includes('sticky')) {
133
+ rows = [
134
+ ...getTopRows().filter((row) => !pinnedRowIds.includes(row.id)),
135
+ ...rows,
136
+ ...getBottomRows().filter((row) => !pinnedRowIds.includes(row.id)),
137
+ ];
103
138
  }
104
- return rankedRows;
139
+
140
+ return rows;
105
141
  }, [
106
142
  shouldRankResults,
107
143
  shouldRankResults ? getPrePaginationRowModel().rows : getRowModel().rows,
108
144
  pagination.pageIndex,
109
145
  pagination.pageSize,
146
+ rowPinning,
110
147
  ]);
111
148
 
112
149
  const rowVirtualizer:
@@ -123,7 +160,7 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
123
160
  ? (element) => element?.getBoundingClientRect().height
124
161
  : undefined,
125
162
  overscan: 4,
126
- ...vProps,
163
+ ...rowVirtualizerProps,
127
164
  })
128
165
  : undefined;
129
166
 
@@ -136,68 +173,135 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
136
173
  : undefined;
137
174
 
138
175
  return (
139
- <TableBody
140
- {...tableBodyProps}
141
- sx={(theme) => ({
142
- display: layoutMode === 'grid' ? 'grid' : 'table-row-group',
143
- height: rowVirtualizer
144
- ? `${rowVirtualizer.getTotalSize()}px`
145
- : 'inherit',
146
- minHeight: !rows.length ? '100px' : undefined,
147
- position: 'relative',
148
- ...(tableBodyProps?.sx instanceof Function
149
- ? tableBodyProps?.sx(theme)
150
- : (tableBodyProps?.sx as any)),
151
- })}
152
- >
153
- {tableBodyProps?.children ??
154
- (!rows.length ? (
155
- <tr style={{ display: layoutMode === 'grid' ? 'grid' : 'table-row' }}>
156
- <td
157
- colSpan={table.getVisibleLeafColumns().length}
158
- style={{
159
- display: layoutMode === 'grid' ? 'grid' : 'table-cell',
160
- }}
176
+ <>
177
+ {!rowPinningDisplayMode?.includes('sticky') &&
178
+ getIsSomeRowsPinned('top') && (
179
+ <TableBody
180
+ {...tableBodyProps}
181
+ sx={(theme) => ({
182
+ display: layoutMode === 'grid' ? 'grid' : 'table-row-group',
183
+ position: 'sticky',
184
+ top: tableHeadHeight - 1,
185
+ zIndex: 1,
186
+ ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any),
187
+ })}
188
+ >
189
+ {getTopRows().map((row, rowIndex) => {
190
+ const props = {
191
+ columnVirtualizer,
192
+ measureElement: rowVirtualizer?.measureElement,
193
+ numRows: rows.length,
194
+ row,
195
+ rowIndex,
196
+ table,
197
+ virtualColumns,
198
+ virtualPaddingLeft,
199
+ virtualPaddingRight,
200
+ };
201
+ return memoMode === 'rows' ? (
202
+ <Memo_MRT_TableBodyRow key={row.id} {...props} />
203
+ ) : (
204
+ <MRT_TableBodyRow key={row.id} {...props} />
205
+ );
206
+ })}
207
+ </TableBody>
208
+ )}
209
+ <TableBody
210
+ {...tableBodyProps}
211
+ sx={(theme) => ({
212
+ display: layoutMode === 'grid' ? 'grid' : 'table-row-group',
213
+ height: rowVirtualizer
214
+ ? `${rowVirtualizer.getTotalSize()}px`
215
+ : 'inherit',
216
+ minHeight: !rows.length ? '100px' : undefined,
217
+ position: 'relative',
218
+ ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any),
219
+ })}
220
+ >
221
+ {tableBodyProps?.children ??
222
+ (!rows.length ? (
223
+ <tr
224
+ style={{ display: layoutMode === 'grid' ? 'grid' : 'table-row' }}
161
225
  >
162
- {renderEmptyRowsFallback?.({ table }) ?? (
163
- <Typography
164
- sx={{
165
- color: 'text.secondary',
166
- fontStyle: 'italic',
167
- maxWidth: `min(100vw, ${
168
- tablePaperRef.current?.clientWidth ?? 360
169
- }px)`,
170
- py: '2rem',
171
- textAlign: 'center',
172
- width: '100%',
173
- }}
174
- >
175
- {globalFilter || columnFilters.length
176
- ? localization.noResultsFound
177
- : localization.noRecordsToDisplay}
178
- </Typography>
179
- )}
180
- </td>
181
- </tr>
182
- ) : (
183
- <>
184
- {(virtualRows ?? rows).map((rowOrVirtualRow, rowIndex) => {
185
- const row = rowVirtualizer
186
- ? rows[rowOrVirtualRow.index]
187
- : (rowOrVirtualRow as MRT_Row<TData>);
226
+ <td
227
+ colSpan={table.getVisibleLeafColumns().length}
228
+ style={{
229
+ display: layoutMode === 'grid' ? 'grid' : 'table-cell',
230
+ }}
231
+ >
232
+ {renderEmptyRowsFallback?.({ table }) ?? (
233
+ <Typography
234
+ sx={{
235
+ color: 'text.secondary',
236
+ fontStyle: 'italic',
237
+ maxWidth: `min(100vw, ${
238
+ tablePaperRef.current?.clientWidth ?? 360
239
+ }px)`,
240
+ py: '2rem',
241
+ textAlign: 'center',
242
+ width: '100%',
243
+ }}
244
+ >
245
+ {globalFilter || columnFilters.length
246
+ ? localization.noResultsFound
247
+ : localization.noRecordsToDisplay}
248
+ </Typography>
249
+ )}
250
+ </td>
251
+ </tr>
252
+ ) : (
253
+ <>
254
+ {(virtualRows ?? rows).map((rowOrVirtualRow, rowIndex) => {
255
+ const row = rowVirtualizer
256
+ ? rows[rowOrVirtualRow.index]
257
+ : (rowOrVirtualRow as MRT_Row<TData>);
258
+ const props = {
259
+ columnVirtualizer,
260
+ measureElement: rowVirtualizer?.measureElement,
261
+ numRows: rows.length,
262
+ pinnedRowIds,
263
+ row,
264
+ rowIndex: rowVirtualizer ? rowOrVirtualRow.index : rowIndex,
265
+ table,
266
+ virtualColumns,
267
+ virtualPaddingLeft,
268
+ virtualPaddingRight,
269
+ virtualRow: rowVirtualizer
270
+ ? (rowOrVirtualRow as VirtualItem)
271
+ : undefined,
272
+ };
273
+ return memoMode === 'rows' ? (
274
+ <Memo_MRT_TableBodyRow key={row.id} {...props} />
275
+ ) : (
276
+ <MRT_TableBodyRow key={row.id} {...props} />
277
+ );
278
+ })}
279
+ </>
280
+ ))}
281
+ </TableBody>
282
+ {!rowPinningDisplayMode?.includes('sticky') &&
283
+ getIsSomeRowsPinned('bottom') && (
284
+ <TableBody
285
+ {...tableBodyProps}
286
+ sx={(theme) => ({
287
+ display: layoutMode === 'grid' ? 'grid' : 'table-row-group',
288
+ position: 'sticky',
289
+ bottom: tableFooterHeight - 1,
290
+ zIndex: 1,
291
+ ...(parseFromValuesOrFunc(tableBodyProps?.sx, theme) as any),
292
+ })}
293
+ >
294
+ {getBottomRows().map((row, rowIndex) => {
188
295
  const props = {
189
296
  columnVirtualizer,
190
297
  measureElement: rowVirtualizer?.measureElement,
191
298
  numRows: rows.length,
192
299
  row,
193
- rowIndex: rowVirtualizer ? rowOrVirtualRow.index : rowIndex,
300
+ rowIndex,
194
301
  table,
195
302
  virtualColumns,
196
303
  virtualPaddingLeft,
197
304
  virtualPaddingRight,
198
- virtualRow: rowVirtualizer
199
- ? (rowOrVirtualRow as VirtualItem)
200
- : undefined,
201
305
  };
202
306
  return memoMode === 'rows' ? (
203
307
  <Memo_MRT_TableBodyRow key={row.id} {...props} />
@@ -205,9 +309,9 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
205
309
  <MRT_TableBodyRow key={row.id} {...props} />
206
310
  );
207
311
  })}
208
- </>
209
- ))}
210
- </TableBody>
312
+ </TableBody>
313
+ )}
314
+ </>
211
315
  );
212
316
  };
213
317
 
@@ -18,6 +18,7 @@ import {
18
18
  getCommonCellStyles,
19
19
  getIsFirstColumn,
20
20
  getIsLastColumn,
21
+ parseFromValuesOrFunc,
21
22
  } from '../column.utils';
22
23
  import { type VirtualItem } from '@tanstack/react-virtual';
23
24
  import { type MRT_Cell, type MRT_TableInstance } from '../types';
@@ -77,25 +78,27 @@ export const MRT_TableBodyCell = <TData extends Record<string, any>>({
77
78
  const { columnDef } = column;
78
79
  const { columnDefType } = columnDef;
79
80
 
80
- const mTableCellBodyProps =
81
- muiTableBodyCellProps instanceof Function
82
- ? muiTableBodyCellProps({ cell, column, row, table })
83
- : muiTableBodyCellProps;
84
-
85
- const mcTableCellBodyProps =
86
- columnDef.muiTableBodyCellProps instanceof Function
87
- ? columnDef.muiTableBodyCellProps({ cell, column, row, table })
88
- : columnDef.muiTableBodyCellProps;
89
-
90
81
  const tableCellProps = {
91
- ...mTableCellBodyProps,
92
- ...mcTableCellBodyProps,
82
+ ...parseFromValuesOrFunc(muiTableBodyCellProps, {
83
+ cell,
84
+ column,
85
+ row,
86
+ table,
87
+ }),
88
+ ...parseFromValuesOrFunc(columnDef.muiTableBodyCellProps, {
89
+ cell,
90
+ column,
91
+ row,
92
+ table,
93
+ }),
93
94
  };
94
95
 
95
- const skeletonProps =
96
- muiSkeletonProps instanceof Function
97
- ? muiSkeletonProps({ cell, column, row, table })
98
- : muiSkeletonProps;
96
+ const skeletonProps = parseFromValuesOrFunc(muiSkeletonProps, {
97
+ cell,
98
+ column,
99
+ row,
100
+ table,
101
+ });
99
102
 
100
103
  const [skeletonWidth, setSkeletonWidth] = useState(100);
101
104
  useEffect(() => {
@@ -148,10 +151,8 @@ export const MRT_TableBodyCell = <TData extends Record<string, any>>({
148
151
  }, [draggingColumn, draggingRow, hoveredColumn, hoveredRow, rowIndex]);
149
152
 
150
153
  const isEditable =
151
- (enableEditing instanceof Function ? enableEditing(row) : enableEditing) &&
152
- (columnDef.enableEditing instanceof Function
153
- ? columnDef.enableEditing(row)
154
- : columnDef.enableEditing) !== false;
154
+ parseFromValuesOrFunc(enableEditing, row) &&
155
+ parseFromValuesOrFunc(columnDef.enableEditing, row) !== false;
155
156
 
156
157
  const isEditing =
157
158
  isEditable &&
@@ -232,7 +233,8 @@ export const MRT_TableBodyCell = <TData extends Record<string, any>>({
232
233
  }rem`
233
234
  : undefined,
234
235
  textOverflow: columnDefType !== 'display' ? 'ellipsis' : undefined,
235
- whiteSpace: density === 'compact' ? 'nowrap' : 'normal',
236
+ whiteSpace:
237
+ row.getIsPinned() || density === 'compact' ? 'nowrap' : 'normal',
236
238
  zIndex:
237
239
  draggingColumn?.id === column.id ? 2 : column.getIsPinned() ? 1 : 0,
238
240
  '&:hover': {
@@ -1,15 +1,23 @@
1
- import { type DragEvent, memo, useRef } from 'react';
1
+ import { type DragEvent, memo, useRef, useMemo } from 'react';
2
2
  import TableRow from '@mui/material/TableRow';
3
- import { type Theme, alpha, darken, lighten } from '@mui/material/styles';
3
+ import {
4
+ type Theme,
5
+ alpha,
6
+ darken,
7
+ lighten,
8
+ useTheme,
9
+ } from '@mui/material/styles';
4
10
  import { Memo_MRT_TableBodyCell, MRT_TableBodyCell } from './MRT_TableBodyCell';
5
11
  import { MRT_TableDetailPanel } from './MRT_TableDetailPanel';
6
12
  import { type VirtualItem, type Virtualizer } from '@tanstack/react-virtual';
13
+ import { parseFromValuesOrFunc } from '../column.utils';
7
14
  import { type MRT_Cell, type MRT_Row, type MRT_TableInstance } from '../types';
8
15
 
9
16
  interface Props<TData extends Record<string, any>> {
10
17
  columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
11
18
  measureElement?: (element: HTMLTableRowElement) => void;
12
19
  numRows: number;
20
+ pinnedRowIds?: string[];
13
21
  row: MRT_Row<TData>;
14
22
  rowIndex: number;
15
23
  table: MRT_TableInstance<TData>;
@@ -23,6 +31,7 @@ export const MRT_TableBodyRow = <TData extends Record<string, any>>({
23
31
  columnVirtualizer,
24
32
  measureElement,
25
33
  numRows,
34
+ pinnedRowIds,
26
35
  row,
27
36
  rowIndex,
28
37
  table,
@@ -31,24 +40,70 @@ export const MRT_TableBodyRow = <TData extends Record<string, any>>({
31
40
  virtualPaddingRight,
32
41
  virtualRow,
33
42
  }: Props<TData>) => {
43
+ const theme = useTheme();
44
+
34
45
  const {
35
46
  getState,
36
47
  options: {
37
48
  enableRowOrdering,
49
+ enableRowPinning,
50
+ enableStickyFooter,
51
+ enableStickyHeader,
38
52
  layoutMode,
53
+ rowPinningDisplayMode,
39
54
  memoMode,
40
55
  muiTableBodyRowProps,
41
56
  renderDetailPanel,
42
57
  },
58
+ refs: { tableHeadRef, tableFooterRef },
43
59
  setHoveredRow,
44
60
  } = table;
45
- const { draggingColumn, draggingRow, editingCell, editingRow, hoveredRow } =
46
- getState();
61
+ const {
62
+ density,
63
+ draggingColumn,
64
+ draggingRow,
65
+ editingCell,
66
+ editingRow,
67
+ hoveredRow,
68
+ isFullScreen,
69
+ rowPinning,
70
+ } = getState();
71
+
72
+ const isPinned = enableRowPinning && row.getIsPinned();
73
+
74
+ const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, {
75
+ row,
76
+ staticRowIndex: rowIndex,
77
+ table,
78
+ });
79
+
80
+ const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => {
81
+ if (
82
+ !enableRowPinning ||
83
+ !rowPinningDisplayMode?.includes('sticky') ||
84
+ !pinnedRowIds ||
85
+ !row.getIsPinned()
86
+ )
87
+ return [];
88
+ return [
89
+ [...pinnedRowIds].reverse().indexOf(row.id),
90
+ pinnedRowIds.indexOf(row.id),
91
+ ];
92
+ }, [pinnedRowIds, rowPinning]);
93
+
94
+ const tableHeadHeight =
95
+ ((enableStickyHeader || isFullScreen) &&
96
+ tableHeadRef.current?.clientHeight) ||
97
+ 0;
98
+ const tableFooterHeight =
99
+ (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
100
+
101
+ const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme as any);
47
102
 
48
- const tableRowProps =
49
- muiTableBodyRowProps instanceof Function
50
- ? muiTableBodyRowProps({ row, staticRowIndex: rowIndex, table })
51
- : muiTableBodyRowProps;
103
+ const rowHeight =
104
+ // @ts-ignore
105
+ parseInt(tableRowProps?.style?.height ?? sx?.height, 10) ||
106
+ (density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69);
52
107
 
53
108
  const handleDragEnter = (_e: DragEvent) => {
54
109
  if (enableRowOrdering && draggingRow) {
@@ -72,15 +127,50 @@ export const MRT_TableBodyRow = <TData extends Record<string, any>>({
72
127
  }}
73
128
  {...tableRowProps}
74
129
  sx={(theme: Theme) => ({
75
- backgroundColor: lighten(theme.palette.background.default, 0.06),
130
+ backgroundColor: `${lighten(
131
+ theme.palette.background.default,
132
+ 0.06,
133
+ )} !important`,
76
134
  boxSizing: 'border-box',
135
+ bottom:
136
+ bottomPinnedIndex !== undefined && isPinned
137
+ ? `${
138
+ bottomPinnedIndex * rowHeight +
139
+ (enableStickyFooter ? tableFooterHeight - 1 : 0)
140
+ }px`
141
+ : undefined,
77
142
  display: layoutMode === 'grid' ? 'flex' : 'table-row',
78
- opacity:
79
- draggingRow?.id === row.id || hoveredRow?.id === row.id ? 0.5 : 1,
80
- position: virtualRow ? 'absolute' : undefined,
143
+ opacity: isPinned
144
+ ? 0.98
145
+ : draggingRow?.id === row.id || hoveredRow?.id === row.id
146
+ ? 0.5
147
+ : 1,
148
+ position: virtualRow
149
+ ? 'absolute'
150
+ : rowPinningDisplayMode?.includes('sticky') && isPinned
151
+ ? 'sticky'
152
+ : undefined,
81
153
  transition: virtualRow ? 'none' : 'all 150ms ease-in-out',
82
- top: virtualRow ? 0 : undefined,
154
+ top: virtualRow
155
+ ? 0
156
+ : topPinnedIndex !== undefined && isPinned
157
+ ? `${
158
+ topPinnedIndex * rowHeight +
159
+ (enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0)
160
+ }px`
161
+ : undefined,
83
162
  width: '100%',
163
+ zIndex:
164
+ rowPinningDisplayMode?.includes('sticky') && isPinned
165
+ ? 1
166
+ : undefined,
167
+ td: {
168
+ backgroundColor: row.getIsSelected()
169
+ ? alpha(theme.palette.primary.main, 0.2)
170
+ : isPinned
171
+ ? alpha(theme.palette.primary.main, 0.1)
172
+ : undefined,
173
+ },
84
174
  '&:hover td': {
85
175
  backgroundColor:
86
176
  tableRowProps?.hover !== false
@@ -91,9 +181,7 @@ export const MRT_TableBodyRow = <TData extends Record<string, any>>({
91
181
  : `${darken(theme.palette.background.default, 0.05)}`
92
182
  : undefined,
93
183
  },
94
- ...(tableRowProps?.sx instanceof Function
95
- ? tableRowProps.sx(theme)
96
- : (tableRowProps?.sx as any)),
184
+ ...(sx as any),
97
185
  })}
98
186
  style={{
99
187
  transform: virtualRow
@@ -1,6 +1,7 @@
1
1
  import { type DragEvent, type RefObject } from 'react';
2
2
  import { MRT_GrabHandleButton } from '../buttons/MRT_GrabHandleButton';
3
3
  import { type MRT_Row, type MRT_TableInstance } from '../types';
4
+ import { parseFromValuesOrFunc } from '../column.utils';
4
5
 
5
6
  interface Props<TData extends Record<string, any>> {
6
7
  row: MRT_Row<TData>;
@@ -17,10 +18,10 @@ export const MRT_TableBodyRowGrabHandle = <TData extends Record<string, any>>({
17
18
  options: { muiRowDragHandleProps },
18
19
  } = table;
19
20
 
20
- const iconButtonProps =
21
- muiRowDragHandleProps instanceof Function
22
- ? muiRowDragHandleProps({ row, table })
23
- : muiRowDragHandleProps;
21
+ const iconButtonProps = parseFromValuesOrFunc(muiRowDragHandleProps, {
22
+ row,
23
+ table,
24
+ });
24
25
 
25
26
  const handleDragStart = (event: DragEvent<HTMLButtonElement>) => {
26
27
  iconButtonProps?.onDragStart?.(event);
@@ -0,0 +1,46 @@
1
+ import Box from '@mui/material/Box';
2
+ import { MRT_RowPinButton } from '../buttons/MRT_RowPinButton';
3
+ import { parseFromValuesOrFunc } from '../column.utils';
4
+ import { type MRT_Row, type MRT_TableInstance } from '../types';
5
+
6
+ interface Props<TData extends Record<string, any>> {
7
+ row: MRT_Row<TData>;
8
+ table: MRT_TableInstance<TData>;
9
+ }
10
+
11
+ export const MRT_TableBodyRowPinButton = <TData extends Record<string, any>>({
12
+ row,
13
+ table,
14
+ }: Props<TData>) => {
15
+ const {
16
+ getState,
17
+ options: { enableRowPinning, rowPinningDisplayMode },
18
+ } = table;
19
+ const { density } = getState();
20
+
21
+ const canPin = parseFromValuesOrFunc(enableRowPinning, row as any);
22
+
23
+ if (!canPin) return null;
24
+
25
+ if (rowPinningDisplayMode === 'top-and-bottom' && !row.getIsPinned()) {
26
+ return (
27
+ <Box
28
+ sx={{
29
+ display: 'flex',
30
+ flexDirection: density === 'compact' ? 'row' : 'column',
31
+ }}
32
+ >
33
+ <MRT_RowPinButton row={row} table={table} pinningPosition="top" />
34
+ <MRT_RowPinButton row={row} table={table} pinningPosition="bottom" />
35
+ </Box>
36
+ );
37
+ }
38
+
39
+ return (
40
+ <MRT_RowPinButton
41
+ row={row}
42
+ table={table}
43
+ pinningPosition={rowPinningDisplayMode === 'bottom' ? 'bottom' : 'top'}
44
+ />
45
+ );
46
+ };