material-react-table 3.0.0-beta.0 → 3.0.0-beta.2
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/dist/index.d.ts +105 -90
- package/dist/index.esm.js +276 -181
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +276 -181
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/components/body/MRT_TableBodyCell.tsx +11 -8
- package/src/components/footer/MRT_TableFooterCell.tsx +10 -7
- package/src/components/head/MRT_TableHeadCell.tsx +12 -8
- package/src/components/inputs/MRT_FilterTextField.tsx +4 -0
- package/src/components/menus/MRT_ActionMenuItem.tsx +1 -0
- package/src/hooks/useMRT_TableOptions.ts +2 -2
- package/src/types.ts +75 -69
- package/src/utils/cell.utils.ts +125 -17
package/package.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "3.0.0-beta.
|
2
|
+
"version": "3.0.0-beta.2",
|
3
3
|
"license": "MIT",
|
4
4
|
"name": "material-react-table",
|
5
5
|
"description": "A fully featured Material UI V6 implementation of TanStack React Table V8, written from the ground up in TypeScript.",
|
@@ -35,11 +35,11 @@
|
|
35
35
|
"size-limit": [
|
36
36
|
{
|
37
37
|
"path": "dist/index.js",
|
38
|
-
"limit": "
|
38
|
+
"limit": "55 KB"
|
39
39
|
},
|
40
40
|
{
|
41
41
|
"path": "dist/index.esm.js",
|
42
|
-
"limit": "
|
42
|
+
"limit": "51 KB"
|
43
43
|
}
|
44
44
|
],
|
45
45
|
"engines": {
|
@@ -78,11 +78,11 @@
|
|
78
78
|
"@storybook/preview-api": "^8.2.9",
|
79
79
|
"@storybook/react": "^8.2.9",
|
80
80
|
"@storybook/react-vite": "^8.2.9",
|
81
|
-
"@types/node": "^22.5.
|
81
|
+
"@types/node": "^22.5.2",
|
82
82
|
"@types/react": "^18.3.5",
|
83
83
|
"@types/react-dom": "^18.3.0",
|
84
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
85
|
-
"@typescript-eslint/parser": "^8.
|
84
|
+
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
85
|
+
"@typescript-eslint/parser": "^8.4.0",
|
86
86
|
"@vitejs/plugin-react": "^4.3.1",
|
87
87
|
"eslint": "^9.9.1",
|
88
88
|
"eslint-plugin-mui-path-imports": "^0.0.15",
|
@@ -18,7 +18,7 @@ import {
|
|
18
18
|
} from '../../types';
|
19
19
|
import {
|
20
20
|
isCellEditable,
|
21
|
-
|
21
|
+
cellKeyboardShortcuts,
|
22
22
|
openEditingCell,
|
23
23
|
} from '../../utils/cell.utils';
|
24
24
|
import { getCommonMRTCellStyles } from '../../utils/style.utils';
|
@@ -58,7 +58,7 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
|
|
58
58
|
enableColumnOrdering,
|
59
59
|
enableColumnPinning,
|
60
60
|
enableGrouping,
|
61
|
-
|
61
|
+
enableKeyboardShortcuts,
|
62
62
|
layoutMode,
|
63
63
|
mrtTheme: { draggingBorderColor },
|
64
64
|
muiSkeletonProps,
|
@@ -232,11 +232,14 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
|
|
232
232
|
}
|
233
233
|
};
|
234
234
|
|
235
|
-
const handleKeyDown = (
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
235
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLTableCellElement>) => {
|
236
|
+
cellKeyboardShortcuts({
|
237
|
+
cell,
|
238
|
+
cellValue: cell.getValue<string>(),
|
239
|
+
event,
|
240
|
+
table,
|
241
|
+
});
|
242
|
+
tableCellProps?.onKeyDown?.(event);
|
240
243
|
};
|
241
244
|
|
242
245
|
return (
|
@@ -244,7 +247,7 @@ export const MRT_TableBodyCell = <TData extends MRT_RowData>({
|
|
244
247
|
align={theme.direction === 'rtl' ? 'right' : 'left'}
|
245
248
|
data-index={staticColumnIndex}
|
246
249
|
data-pinned={!!isColumnPinned || undefined}
|
247
|
-
tabIndex={
|
250
|
+
tabIndex={enableKeyboardShortcuts ? 0 : undefined}
|
248
251
|
{...tableCellProps}
|
249
252
|
onKeyDown={handleKeyDown}
|
250
253
|
onContextMenu={handleContextMenu}
|
@@ -7,7 +7,7 @@ import {
|
|
7
7
|
} from '../../types';
|
8
8
|
import { getCommonMRTCellStyles } from '../../utils/style.utils';
|
9
9
|
import { parseFromValuesOrFunc } from '../../utils/utils';
|
10
|
-
import {
|
10
|
+
import { cellKeyboardShortcuts } from '../../utils/cell.utils';
|
11
11
|
|
12
12
|
export interface MRT_TableFooterCellProps<TData extends MRT_RowData>
|
13
13
|
extends TableCellProps {
|
@@ -28,7 +28,7 @@ export const MRT_TableFooterCell = <TData extends MRT_RowData>({
|
|
28
28
|
options: {
|
29
29
|
enableColumnPinning,
|
30
30
|
muiTableFooterCellProps,
|
31
|
-
|
31
|
+
enableKeyboardShortcuts,
|
32
32
|
},
|
33
33
|
} = table;
|
34
34
|
const { density } = getState();
|
@@ -48,11 +48,13 @@ export const MRT_TableFooterCell = <TData extends MRT_RowData>({
|
|
48
48
|
...rest,
|
49
49
|
};
|
50
50
|
|
51
|
-
const handleKeyDown = (
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLTableCellElement>) => {
|
52
|
+
cellKeyboardShortcuts({
|
53
|
+
event,
|
54
|
+
cellValue: footer.column.columnDef.footer,
|
55
|
+
table,
|
56
|
+
});
|
57
|
+
tableCellProps?.onKeyDown?.(event);
|
56
58
|
};
|
57
59
|
|
58
60
|
return (
|
@@ -67,6 +69,7 @@ export const MRT_TableFooterCell = <TData extends MRT_RowData>({
|
|
67
69
|
colSpan={footer.colSpan}
|
68
70
|
data-index={staticColumnIndex}
|
69
71
|
data-pinned={!!isColumnPinned || undefined}
|
72
|
+
tabIndex={enableKeyboardShortcuts ? 0 : undefined}
|
70
73
|
variant="footer"
|
71
74
|
{...tableCellProps}
|
72
75
|
onKeyDown={handleKeyDown}
|
@@ -17,7 +17,7 @@ import {
|
|
17
17
|
} from '../../types';
|
18
18
|
import { getCommonMRTCellStyles } from '../../utils/style.utils';
|
19
19
|
import { parseFromValuesOrFunc } from '../../utils/utils';
|
20
|
-
import {
|
20
|
+
import { cellKeyboardShortcuts } from '../../utils/cell.utils';
|
21
21
|
|
22
22
|
export interface MRT_TableHeadCellProps<TData extends MRT_RowData>
|
23
23
|
extends TableCellProps {
|
@@ -41,12 +41,12 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
|
|
41
41
|
columnFilterDisplayMode,
|
42
42
|
columnResizeDirection,
|
43
43
|
columnResizeMode,
|
44
|
+
enableKeyboardShortcuts,
|
44
45
|
enableColumnActions,
|
45
46
|
enableColumnDragging,
|
46
47
|
enableColumnOrdering,
|
47
48
|
enableColumnPinning,
|
48
49
|
enableGrouping,
|
49
|
-
enableCellNavigation,
|
50
50
|
enableMultiSort,
|
51
51
|
layoutMode,
|
52
52
|
mrtTheme: { draggingBorderColor },
|
@@ -149,11 +149,15 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
|
|
149
149
|
}
|
150
150
|
};
|
151
151
|
|
152
|
-
const handleKeyDown = (
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
152
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLTableCellElement>) => {
|
153
|
+
cellKeyboardShortcuts({
|
154
|
+
event,
|
155
|
+
cellValue: header.column.columnDef.header,
|
156
|
+
table,
|
157
|
+
header,
|
158
|
+
});
|
159
|
+
|
160
|
+
tableCellProps?.onKeyDown?.(event);
|
157
161
|
};
|
158
162
|
|
159
163
|
const HeaderElement =
|
@@ -194,7 +198,7 @@ export const MRT_TableHeadCell = <TData extends MRT_RowData>({
|
|
194
198
|
}
|
195
199
|
}
|
196
200
|
}}
|
197
|
-
tabIndex={
|
201
|
+
tabIndex={enableKeyboardShortcuts ? 0 : undefined}
|
198
202
|
{...tableCellProps}
|
199
203
|
onKeyDown={handleKeyDown}
|
200
204
|
sx={(theme: Theme) => ({
|
@@ -338,6 +338,10 @@ export const MRT_FilterTextField = <TData extends MRT_RowData>({
|
|
338
338
|
: filterPlaceholder,
|
339
339
|
variant: 'standard',
|
340
340
|
...textFieldProps,
|
341
|
+
onKeyDown: (e) => {
|
342
|
+
e.stopPropagation();
|
343
|
+
textFieldProps.onKeyDown?.(e);
|
344
|
+
},
|
341
345
|
sx: (theme) => ({
|
342
346
|
minWidth: isDateFilter
|
343
347
|
? '160px'
|
@@ -76,7 +76,7 @@ export const useMRT_TableOptions: <TData extends MRT_RowData>(
|
|
76
76
|
enableGlobalFilterRankedResults = true,
|
77
77
|
enableGrouping = false,
|
78
78
|
enableHiding = true,
|
79
|
-
|
79
|
+
enableKeyboardShortcuts = true,
|
80
80
|
enableMultiRowSelection = true,
|
81
81
|
enableMultiSort = true,
|
82
82
|
enablePagination = true,
|
@@ -204,7 +204,7 @@ export const useMRT_TableOptions: <TData extends MRT_RowData>(
|
|
204
204
|
enableGlobalFilterRankedResults,
|
205
205
|
enableGrouping,
|
206
206
|
enableHiding,
|
207
|
-
|
207
|
+
enableKeyboardShortcuts,
|
208
208
|
enableMultiRowSelection,
|
209
209
|
enableMultiSort,
|
210
210
|
enablePagination,
|
package/src/types.ts
CHANGED
@@ -184,9 +184,10 @@ export interface MRT_Localization {
|
|
184
184
|
filterFuzzy: string;
|
185
185
|
filterGreaterThan: string;
|
186
186
|
filterGreaterThanOrEqualTo: string;
|
187
|
-
filterInNumberRange: string;
|
188
187
|
filterIncludesString: string;
|
189
188
|
filterIncludesStringSensitive: string;
|
189
|
+
filteringByColumn: string;
|
190
|
+
filterInNumberRange: string;
|
190
191
|
filterLessThan: string;
|
191
192
|
filterLessThanOrEqualTo: string;
|
192
193
|
filterMode: string;
|
@@ -194,7 +195,6 @@ export interface MRT_Localization {
|
|
194
195
|
filterNotEquals: string;
|
195
196
|
filterStartsWith: string;
|
196
197
|
filterWeakEquals: string;
|
197
|
-
filteringByColumn: string;
|
198
198
|
goToFirstPage: string;
|
199
199
|
goToLastPage: string;
|
200
200
|
goToNextPage: string;
|
@@ -412,6 +412,22 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
412
412
|
| 'id'
|
413
413
|
| 'sortingFn'
|
414
414
|
> {
|
415
|
+
/**
|
416
|
+
* Either an `accessorKey` or a combination of an `accessorFn` and `id` are required for a data column definition.
|
417
|
+
* Specify a function here to point to the correct property in the data object.
|
418
|
+
*
|
419
|
+
* @example accessorFn: (row) => row.username
|
420
|
+
*/
|
421
|
+
accessorFn?: (originalRow: TData) => TValue;
|
422
|
+
/**
|
423
|
+
* Either an `accessorKey` or a combination of an `accessorFn` and `id` are required for a data column definition.
|
424
|
+
* Specify which key in the row this column should use to access the correct data.
|
425
|
+
* Also supports Deep Key Dot Notation.
|
426
|
+
*
|
427
|
+
* @example accessorKey: 'username' //simple
|
428
|
+
* @example accessorKey: 'name.firstName' //deep key dot notation
|
429
|
+
*/
|
430
|
+
accessorKey?: DeepKeys<TData> | (string & {});
|
415
431
|
AggregatedCell?: (props: {
|
416
432
|
cell: MRT_Cell<TData, TValue>;
|
417
433
|
column: MRT_Column<TData, TValue>;
|
@@ -420,6 +436,7 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
420
436
|
staticColumnIndex?: number;
|
421
437
|
staticRowIndex?: number;
|
422
438
|
}) => ReactNode;
|
439
|
+
aggregationFn?: Array<MRT_AggregationFn<TData>> | MRT_AggregationFn<TData>;
|
423
440
|
Cell?: (props: {
|
424
441
|
cell: MRT_Cell<TData, TValue>;
|
425
442
|
column: MRT_Column<TData, TValue>;
|
@@ -430,63 +447,6 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
430
447
|
staticRowIndex?: number;
|
431
448
|
table: MRT_TableInstance<TData>;
|
432
449
|
}) => ReactNode;
|
433
|
-
Edit?: (props: {
|
434
|
-
cell: MRT_Cell<TData, TValue>;
|
435
|
-
column: MRT_Column<TData, TValue>;
|
436
|
-
row: MRT_Row<TData>;
|
437
|
-
table: MRT_TableInstance<TData>;
|
438
|
-
}) => ReactNode;
|
439
|
-
Filter?: (props: {
|
440
|
-
column: MRT_Column<TData, TValue>;
|
441
|
-
header: MRT_Header<TData>;
|
442
|
-
rangeFilterIndex?: number;
|
443
|
-
table: MRT_TableInstance<TData>;
|
444
|
-
}) => ReactNode;
|
445
|
-
Footer?:
|
446
|
-
| ((props: {
|
447
|
-
column: MRT_Column<TData, TValue>;
|
448
|
-
footer: MRT_Header<TData>;
|
449
|
-
table: MRT_TableInstance<TData>;
|
450
|
-
}) => ReactNode)
|
451
|
-
| ReactNode;
|
452
|
-
GroupedCell?: (props: {
|
453
|
-
cell: MRT_Cell<TData, TValue>;
|
454
|
-
column: MRT_Column<TData, TValue>;
|
455
|
-
row: MRT_Row<TData>;
|
456
|
-
table: MRT_TableInstance<TData>;
|
457
|
-
staticColumnIndex?: number;
|
458
|
-
staticRowIndex?: number;
|
459
|
-
}) => ReactNode;
|
460
|
-
Header?:
|
461
|
-
| ((props: {
|
462
|
-
column: MRT_Column<TData, TValue>;
|
463
|
-
header: MRT_Header<TData>;
|
464
|
-
table: MRT_TableInstance<TData>;
|
465
|
-
}) => ReactNode)
|
466
|
-
| ReactNode;
|
467
|
-
PlaceholderCell?: (props: {
|
468
|
-
cell: MRT_Cell<TData, TValue>;
|
469
|
-
column: MRT_Column<TData, TValue>;
|
470
|
-
row: MRT_Row<TData>;
|
471
|
-
table: MRT_TableInstance<TData>;
|
472
|
-
}) => ReactNode;
|
473
|
-
/**
|
474
|
-
* Either an `accessorKey` or a combination of an `accessorFn` and `id` are required for a data column definition.
|
475
|
-
* Specify a function here to point to the correct property in the data object.
|
476
|
-
*
|
477
|
-
* @example accessorFn: (row) => row.username
|
478
|
-
*/
|
479
|
-
accessorFn?: (originalRow: TData) => TValue;
|
480
|
-
/**
|
481
|
-
* Either an `accessorKey` or a combination of an `accessorFn` and `id` are required for a data column definition.
|
482
|
-
* Specify which key in the row this column should use to access the correct data.
|
483
|
-
* Also supports Deep Key Dot Notation.
|
484
|
-
*
|
485
|
-
* @example accessorKey: 'username' //simple
|
486
|
-
* @example accessorKey: 'name.firstName' //deep key dot notation
|
487
|
-
*/
|
488
|
-
accessorKey?: DeepKeys<TData> | (string & {});
|
489
|
-
aggregationFn?: Array<MRT_AggregationFn<TData>> | MRT_AggregationFn<TData>;
|
490
450
|
/**
|
491
451
|
* Specify what type of column this is. Either `data`, `display`, or `group`. Defaults to `data`.
|
492
452
|
* Leave this blank if you are just creating a normal data column.
|
@@ -500,6 +460,12 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
500
460
|
LiteralUnion<string & MRT_FilterOption>
|
501
461
|
> | null;
|
502
462
|
columns?: MRT_ColumnDef<TData, TValue>[];
|
463
|
+
Edit?: (props: {
|
464
|
+
cell: MRT_Cell<TData, TValue>;
|
465
|
+
column: MRT_Column<TData, TValue>;
|
466
|
+
row: MRT_Row<TData>;
|
467
|
+
table: MRT_TableInstance<TData>;
|
468
|
+
}) => ReactNode;
|
503
469
|
editSelectOptions?:
|
504
470
|
| ((props: {
|
505
471
|
cell: MRT_Cell<TData, TValue>;
|
@@ -519,6 +485,12 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
519
485
|
enableColumnOrdering?: boolean;
|
520
486
|
enableEditing?: ((row: MRT_Row<TData>) => boolean) | boolean;
|
521
487
|
enableFilterMatchHighlighting?: boolean;
|
488
|
+
Filter?: (props: {
|
489
|
+
column: MRT_Column<TData, TValue>;
|
490
|
+
header: MRT_Header<TData>;
|
491
|
+
rangeFilterIndex?: number;
|
492
|
+
table: MRT_TableInstance<TData>;
|
493
|
+
}) => ReactNode;
|
522
494
|
filterFn?: MRT_FilterFn<TData>;
|
523
495
|
filterSelectOptions?: DropdownOption[];
|
524
496
|
filterVariant?:
|
@@ -539,6 +511,21 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
539
511
|
* footer must be a string. If you want custom JSX to render the footer, you can also specify a `Footer` option. (Capital F)
|
540
512
|
*/
|
541
513
|
footer?: string;
|
514
|
+
Footer?:
|
515
|
+
| ((props: {
|
516
|
+
column: MRT_Column<TData, TValue>;
|
517
|
+
footer: MRT_Header<TData>;
|
518
|
+
table: MRT_TableInstance<TData>;
|
519
|
+
}) => ReactNode)
|
520
|
+
| ReactNode;
|
521
|
+
GroupedCell?: (props: {
|
522
|
+
cell: MRT_Cell<TData, TValue>;
|
523
|
+
column: MRT_Column<TData, TValue>;
|
524
|
+
row: MRT_Row<TData>;
|
525
|
+
table: MRT_TableInstance<TData>;
|
526
|
+
staticColumnIndex?: number;
|
527
|
+
staticRowIndex?: number;
|
528
|
+
}) => ReactNode;
|
542
529
|
/**
|
543
530
|
* If `layoutMode` is `'grid'` or `'grid-no-grow'`, you can specify the flex grow value for individual columns to still grow and take up remaining space, or set to `false`/0 to not grow.
|
544
531
|
*/
|
@@ -547,6 +534,13 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
547
534
|
* header must be a string. If you want custom JSX to render the header, you can also specify a `Header` option. (Capital H)
|
548
535
|
*/
|
549
536
|
header: string;
|
537
|
+
Header?:
|
538
|
+
| ((props: {
|
539
|
+
column: MRT_Column<TData, TValue>;
|
540
|
+
header: MRT_Header<TData>;
|
541
|
+
table: MRT_TableInstance<TData>;
|
542
|
+
}) => ReactNode)
|
543
|
+
| ReactNode;
|
550
544
|
/**
|
551
545
|
* Either an `accessorKey` or a combination of an `accessorFn` and `id` are required for a data column definition.
|
552
546
|
*
|
@@ -651,6 +645,12 @@ export interface MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown>
|
|
651
645
|
table: MRT_TableInstance<TData>;
|
652
646
|
}) => TableCellProps)
|
653
647
|
| TableCellProps;
|
648
|
+
PlaceholderCell?: (props: {
|
649
|
+
cell: MRT_Cell<TData, TValue>;
|
650
|
+
column: MRT_Column<TData, TValue>;
|
651
|
+
row: MRT_Row<TData>;
|
652
|
+
table: MRT_TableInstance<TData>;
|
653
|
+
}) => ReactNode;
|
654
654
|
renderCellActionMenuItems?: (props: {
|
655
655
|
cell: MRT_Cell<TData>;
|
656
656
|
closeMenu: () => void;
|
@@ -813,12 +813,6 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
813
813
|
columnFilterModeOptions?: Array<
|
814
814
|
LiteralUnion<string & MRT_FilterOption>
|
815
815
|
> | null;
|
816
|
-
columnVirtualizerInstanceRef?: MutableRefObject<MRT_ColumnVirtualizer | null>;
|
817
|
-
columnVirtualizerOptions?:
|
818
|
-
| ((props: {
|
819
|
-
table: MRT_TableInstance<TData>;
|
820
|
-
}) => Partial<VirtualizerOptions<HTMLDivElement, HTMLTableCellElement>>)
|
821
|
-
| Partial<VirtualizerOptions<HTMLDivElement, HTMLTableCellElement>>;
|
822
816
|
/**
|
823
817
|
* The columns to display in the table. `accessorKey`s or `accessorFn`s must match keys in the `data` table option.
|
824
818
|
*
|
@@ -830,6 +824,12 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
830
824
|
* @link https://www.material-react-table.com/docs/api/column-options
|
831
825
|
*/
|
832
826
|
columns: MRT_ColumnDef<TData, any>[];
|
827
|
+
columnVirtualizerInstanceRef?: MutableRefObject<MRT_ColumnVirtualizer | null>;
|
828
|
+
columnVirtualizerOptions?:
|
829
|
+
| ((props: {
|
830
|
+
table: MRT_TableInstance<TData>;
|
831
|
+
}) => Partial<VirtualizerOptions<HTMLDivElement, HTMLTableCellElement>>)
|
832
|
+
| Partial<VirtualizerOptions<HTMLDivElement, HTMLTableCellElement>>;
|
833
833
|
createDisplayMode?: 'custom' | 'modal' | 'row';
|
834
834
|
/**
|
835
835
|
* Pass your data as an array of objects. Objects can theoretically be any shape, but it's best to keep them consistent.
|
@@ -870,7 +870,7 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
870
870
|
enableFullScreenToggle?: boolean;
|
871
871
|
enableGlobalFilterModes?: boolean;
|
872
872
|
enableGlobalFilterRankedResults?: boolean;
|
873
|
-
|
873
|
+
enableKeyboardShortcuts?: boolean;
|
874
874
|
enablePagination?: boolean;
|
875
875
|
enableRowActions?: boolean;
|
876
876
|
enableRowDragging?: boolean;
|
@@ -1099,9 +1099,6 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
1099
1099
|
table: MRT_TableInstance<TData>;
|
1100
1100
|
}) => CheckboxProps | RadioProps)
|
1101
1101
|
| (CheckboxProps | RadioProps);
|
1102
|
-
/**
|
1103
|
-
* @deprecated Specify this in the `defaultColumn` table option instead if you want to apply to all columns.
|
1104
|
-
*/
|
1105
1102
|
muiSkeletonProps?:
|
1106
1103
|
| ((props: {
|
1107
1104
|
cell: MRT_Cell<TData>;
|
@@ -1236,6 +1233,9 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
1236
1233
|
renderCaption?:
|
1237
1234
|
| ((props: { table: MRT_TableInstance<TData> }) => ReactNode)
|
1238
1235
|
| ReactNode;
|
1236
|
+
/**
|
1237
|
+
* @deprecated Specify this in the `defaultColumn` table option instead if you want to apply to all columns.
|
1238
|
+
*/
|
1239
1239
|
renderCellActionMenuItems?: (props: {
|
1240
1240
|
cell: MRT_Cell<TData>;
|
1241
1241
|
closeMenu: () => void;
|
@@ -1246,12 +1246,18 @@ export interface MRT_TableOptions<TData extends MRT_RowData>
|
|
1246
1246
|
staticRowIndex?: number;
|
1247
1247
|
table: MRT_TableInstance<TData>;
|
1248
1248
|
}) => ReactNode[];
|
1249
|
+
/**
|
1250
|
+
* @deprecated Specify this in the `defaultColumn` table option instead if you want to apply to all columns.
|
1251
|
+
*/
|
1249
1252
|
renderColumnActionsMenuItems?: (props: {
|
1250
1253
|
closeMenu: () => void;
|
1251
1254
|
column: MRT_Column<TData>;
|
1252
1255
|
internalColumnMenuItems: ReactNode[];
|
1253
1256
|
table: MRT_TableInstance<TData>;
|
1254
1257
|
}) => ReactNode[];
|
1258
|
+
/**
|
1259
|
+
* @deprecated Specify this in the `defaultColumn` table option instead if you want to apply to all columns.
|
1260
|
+
*/
|
1255
1261
|
renderColumnFilterModeMenuItems?: (props: {
|
1256
1262
|
column: MRT_Column<TData>;
|
1257
1263
|
internalFilterOptions: MRT_InternalFilterOption[];
|
package/src/utils/cell.utils.ts
CHANGED
@@ -1,10 +1,22 @@
|
|
1
1
|
import {
|
2
|
+
MRT_Header,
|
2
3
|
type MRT_Cell,
|
3
4
|
type MRT_RowData,
|
4
5
|
type MRT_TableInstance,
|
5
6
|
} from '../types';
|
7
|
+
import {
|
8
|
+
getMRT_RowSelectionHandler,
|
9
|
+
getMRT_SelectAllHandler,
|
10
|
+
} from './row.utils';
|
6
11
|
import { parseFromValuesOrFunc } from './utils';
|
7
12
|
|
13
|
+
const isWinCtrlMacMeta = (event: React.KeyboardEvent<HTMLTableCellElement>) => {
|
14
|
+
return (
|
15
|
+
(event.ctrlKey && navigator.platform.toLowerCase().includes('win')) ||
|
16
|
+
(event.metaKey && navigator.platform.toLowerCase().includes('mac'))
|
17
|
+
);
|
18
|
+
};
|
19
|
+
|
8
20
|
export const isCellEditable = <TData extends MRT_RowData>({
|
9
21
|
cell,
|
10
22
|
table,
|
@@ -49,20 +61,99 @@ export const openEditingCell = <TData extends MRT_RowData>({
|
|
49
61
|
}
|
50
62
|
};
|
51
63
|
|
52
|
-
export const
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
64
|
+
export const cellKeyboardShortcuts = <TData extends MRT_RowData = MRT_RowData>({
|
65
|
+
cell,
|
66
|
+
cellElements,
|
67
|
+
cellValue,
|
68
|
+
containerElement,
|
69
|
+
event,
|
70
|
+
header,
|
71
|
+
parentElement,
|
72
|
+
table,
|
73
|
+
}: {
|
74
|
+
cell?: MRT_Cell<TData>;
|
75
|
+
header?: MRT_Header<TData>;
|
76
|
+
cellElements?: Array<HTMLTableCellElement>;
|
77
|
+
cellValue?: string;
|
78
|
+
containerElement?: HTMLTableElement;
|
79
|
+
event: React.KeyboardEvent<HTMLTableCellElement>;
|
80
|
+
parentElement?: HTMLTableRowElement;
|
81
|
+
table: MRT_TableInstance<TData>;
|
82
|
+
}) => {
|
83
|
+
if (!table.options.enableKeyboardShortcuts) return;
|
84
|
+
const currentCell = event.currentTarget;
|
85
|
+
|
86
|
+
if (cellValue && isWinCtrlMacMeta(event) && event.key === 'c') {
|
87
|
+
navigator.clipboard.writeText(cellValue);
|
88
|
+
} else if (['Enter', ' '].includes(event.key)) {
|
89
|
+
if (cell?.column?.id === 'mrt-row-select') {
|
90
|
+
event.preventDefault();
|
91
|
+
getMRT_RowSelectionHandler({
|
92
|
+
row: cell.row,
|
93
|
+
table,
|
94
|
+
//@ts-ignore
|
95
|
+
staticRowIndex: +event.target.getAttribute('data-index'),
|
96
|
+
})(event as any);
|
97
|
+
} else if (
|
98
|
+
header?.column?.id === 'mrt-row-select' &&
|
99
|
+
table.options.enableSelectAll
|
100
|
+
) {
|
101
|
+
event.preventDefault();
|
102
|
+
getMRT_SelectAllHandler({
|
103
|
+
table,
|
104
|
+
})(event as any);
|
105
|
+
} else if (
|
106
|
+
cell?.column?.id === 'mrt-row-expand' &&
|
107
|
+
(cell.row.getCanExpand() ||
|
108
|
+
table.options.renderDetailPanel?.({ row: cell.row, table }))
|
109
|
+
) {
|
110
|
+
event.preventDefault();
|
111
|
+
cell.row.toggleExpanded();
|
112
|
+
} else if (
|
113
|
+
header?.column?.id === 'mrt-row-expand' &&
|
114
|
+
table.options.enableExpandAll
|
115
|
+
) {
|
116
|
+
event.preventDefault();
|
117
|
+
table.toggleAllRowsExpanded();
|
118
|
+
} else if (cell?.column.id === 'mrt-row-pin') {
|
119
|
+
event.preventDefault();
|
120
|
+
cell.row.getIsPinned()
|
121
|
+
? cell.row.pin(false)
|
122
|
+
: cell.row.pin(
|
123
|
+
table.options.rowPinningDisplayMode?.includes('bottom')
|
124
|
+
? 'bottom'
|
125
|
+
: 'top',
|
126
|
+
);
|
127
|
+
} else if (header && isWinCtrlMacMeta(event)) {
|
128
|
+
const actionsButton = currentCell.querySelector(
|
129
|
+
`button[aria-label="${table.options.localization.columnActions}"]`,
|
130
|
+
);
|
131
|
+
if (actionsButton) {
|
132
|
+
(actionsButton as HTMLButtonElement).click();
|
133
|
+
}
|
134
|
+
} else if (header?.column?.getCanSort()) {
|
135
|
+
event.preventDefault();
|
136
|
+
header.column.toggleSorting();
|
137
|
+
}
|
138
|
+
} else if (
|
139
|
+
[
|
140
|
+
'ArrowRight',
|
141
|
+
'ArrowLeft',
|
142
|
+
'ArrowUp',
|
143
|
+
'ArrowDown',
|
144
|
+
'Home',
|
145
|
+
'End',
|
146
|
+
'PageUp',
|
147
|
+
'PageDown',
|
148
|
+
].includes(event.key)
|
59
149
|
) {
|
60
|
-
|
61
|
-
const currentCell = e.currentTarget;
|
62
|
-
const currentRow = currentCell.closest('tr');
|
150
|
+
event.preventDefault();
|
63
151
|
|
64
|
-
const
|
65
|
-
const
|
152
|
+
const currentRow = parentElement || currentCell.closest('tr');
|
153
|
+
const tableElement = containerElement || currentCell.closest('table');
|
154
|
+
const allCells =
|
155
|
+
cellElements ||
|
156
|
+
Array.from(tableElement?.querySelectorAll('th, td') || []);
|
66
157
|
const currentCellIndex = allCells.indexOf(currentCell);
|
67
158
|
|
68
159
|
const currentIndex = parseInt(
|
@@ -76,14 +167,25 @@ export const cellNavigation = (
|
|
76
167
|
rowIndex === 'c'
|
77
168
|
? currentRow
|
78
169
|
: rowIndex === 'f'
|
79
|
-
?
|
80
|
-
:
|
170
|
+
? tableElement?.querySelector('tr')
|
171
|
+
: tableElement?.lastElementChild?.lastElementChild;
|
81
172
|
const rowCells = Array.from(row?.children || []);
|
82
173
|
const targetCell =
|
83
174
|
edge === 'f' ? rowCells[0] : rowCells[rowCells.length - 1];
|
84
175
|
return targetCell as HTMLElement;
|
85
176
|
};
|
86
177
|
|
178
|
+
//page up/down first or last cell in column
|
179
|
+
const findBottomTopCell = (columnIndex: number, edge: 'b' | 't') => {
|
180
|
+
const row =
|
181
|
+
edge === 't'
|
182
|
+
? tableElement?.querySelector('tr')
|
183
|
+
: tableElement?.lastElementChild?.lastElementChild;
|
184
|
+
const rowCells = Array.from(row?.children || []);
|
185
|
+
const targetCell = rowCells[columnIndex];
|
186
|
+
return targetCell as HTMLElement;
|
187
|
+
};
|
188
|
+
|
87
189
|
const findAdjacentCell = (
|
88
190
|
columnIndex: number,
|
89
191
|
searchDirection: 'f' | 'b',
|
@@ -97,7 +199,7 @@ export const cellNavigation = (
|
|
97
199
|
) as HTMLElement | undefined;
|
98
200
|
};
|
99
201
|
|
100
|
-
switch (
|
202
|
+
switch (event.key) {
|
101
203
|
case 'ArrowRight':
|
102
204
|
nextCell = findAdjacentCell(currentIndex + 1, 'f');
|
103
205
|
break;
|
@@ -111,10 +213,16 @@ export const cellNavigation = (
|
|
111
213
|
nextCell = findAdjacentCell(currentIndex, 'f');
|
112
214
|
break;
|
113
215
|
case 'Home':
|
114
|
-
nextCell = findEdgeCell(
|
216
|
+
nextCell = findEdgeCell(isWinCtrlMacMeta(event) ? 'f' : 'c', 'f');
|
115
217
|
break;
|
116
218
|
case 'End':
|
117
|
-
nextCell = findEdgeCell(
|
219
|
+
nextCell = findEdgeCell(isWinCtrlMacMeta(event) ? 'l' : 'c', 'l');
|
220
|
+
break;
|
221
|
+
case 'PageUp':
|
222
|
+
nextCell = findBottomTopCell(currentIndex, 't');
|
223
|
+
break;
|
224
|
+
case 'PageDown':
|
225
|
+
nextCell = findBottomTopCell(currentIndex, 'b');
|
118
226
|
break;
|
119
227
|
}
|
120
228
|
|