material-react-table 0.23.4 → 0.24.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  import { FC } from 'react';
2
2
  import { MRT_TableInstance } from '..';
3
3
  interface Props {
4
- alignTo: 'bottom' | 'top';
4
+ isTopToolbar: boolean;
5
5
  table: MRT_TableInstance;
6
6
  }
7
7
  export declare const MRT_LinearProgressBar: FC<Props>;
package/dist/utils.d.ts CHANGED
@@ -4,7 +4,7 @@ export declare const getAllLeafColumnDefs: <TData extends Record<string, any> =
4
4
  export declare const prepareColumns: <TData extends Record<string, any> = {}>(columnDefs: MRT_ColumnDef<TData>[], currentFilterFns: {
5
5
  [key: string]: "between" | "contains" | "empty" | "endsWith" | "equals" | "fuzzy" | "greaterThan" | "lessThan" | "notEmpty" | "notEquals" | "startsWith" | "includesString" | "includesStringSensitive" | "equalsString" | "arrIncludes" | "arrIncludesAll" | "arrIncludesSome" | "weakEquals" | "inNumberRange";
6
6
  }) => MRT_DefinedColumnDef<TData>[];
7
- export declare const reorderColumn: <TData extends Record<string, any> = {}>(movingColumn: MRT_Column<TData>, receivingColumn: MRT_Column<TData>, columnOrder: ColumnOrderState) => ColumnOrderState;
7
+ export declare const reorderColumn: <TData extends Record<string, any> = {}>(draggedColumn: MRT_Column<TData>, targetColumn: MRT_Column<TData>, columnOrder: ColumnOrderState) => ColumnOrderState;
8
8
  export declare const getLeadingDisplayColumnIds: <TData extends Record<string, any> = {}>(props: MaterialReactTableProps<TData>) => string[];
9
9
  export declare const getTrailingDisplayColumnIds: <TData extends Record<string, any> = {}>(props: MaterialReactTableProps<TData>) => (string | false | undefined)[];
10
10
  export declare const getDefaultColumnOrderIds: <TData extends Record<string, any> = {}>(props: MaterialReactTableProps<TData>) => string[];
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.23.4",
2
+ "version": "0.24.1",
3
3
  "license": "MIT",
4
4
  "name": "material-react-table",
5
5
  "description": "A fully featured Material UI implementation of TanStack React Table, inspired by material-table and the MUI X DataGrid, written from the ground up in TypeScript.",
@@ -1,12 +1,13 @@
1
1
  import React, {
2
2
  ChangeEvent,
3
3
  Dispatch,
4
+ DragEvent,
4
5
  FC,
5
6
  FocusEvent,
6
7
  ReactNode,
7
8
  SetStateAction,
8
9
  } from 'react';
9
- import {
10
+ import type {
10
11
  AlertProps,
11
12
  ButtonProps,
12
13
  CheckboxProps,
@@ -25,7 +26,7 @@ import {
25
26
  TextFieldProps,
26
27
  ToolbarProps,
27
28
  } from '@mui/material';
28
- import {
29
+ import type {
29
30
  Cell,
30
31
  Column,
31
32
  ColumnDef,
@@ -39,7 +40,7 @@ import {
39
40
  TableOptions,
40
41
  TableState,
41
42
  } from '@tanstack/react-table';
42
- import { Options as VirtualizerOptions } from 'react-virtual';
43
+ import type { Options as VirtualizerOptions } from 'react-virtual';
43
44
  import { MRT_Localization, MRT_DefaultLocalization_EN } from './localization';
44
45
  import { MRT_Default_Icons, MRT_Icons } from './icons';
45
46
  import { MRT_TableRoot } from './table/MRT_TableRoot';
@@ -107,6 +108,7 @@ export type MRT_TableInstance<TData extends Record<string, any> = {}> = Omit<
107
108
  localization: MRT_Localization;
108
109
  };
109
110
  setCurrentDraggingColumn: Dispatch<SetStateAction<MRT_Column<TData> | null>>;
111
+ setCurrentDraggingRow: Dispatch<SetStateAction<MRT_Row<TData> | null>>;
110
112
  setCurrentEditingCell: Dispatch<SetStateAction<MRT_Cell | null>>;
111
113
  setCurrentEditingRow: Dispatch<SetStateAction<MRT_Row | null>>;
112
114
  setCurrentFilterFns: Dispatch<
@@ -116,6 +118,7 @@ export type MRT_TableInstance<TData extends Record<string, any> = {}> = Omit<
116
118
  >;
117
119
  setCurrentGlobalFilterFn: Dispatch<SetStateAction<MRT_FilterOption>>;
118
120
  setCurrentHoveredColumn: Dispatch<SetStateAction<MRT_Column<TData> | null>>;
121
+ setCurrentHoveredRow: Dispatch<SetStateAction<MRT_Row | null>>;
119
122
  setDensity: Dispatch<SetStateAction<'comfortable' | 'compact' | 'spacious'>>;
120
123
  setIsFullScreen: Dispatch<SetStateAction<boolean>>;
121
124
  setShowAlertBanner: Dispatch<SetStateAction<boolean>>;
@@ -126,11 +129,13 @@ export type MRT_TableInstance<TData extends Record<string, any> = {}> = Omit<
126
129
  export type MRT_TableState<TData extends Record<string, any> = {}> =
127
130
  TableState & {
128
131
  currentDraggingColumn: MRT_Column<TData> | null;
132
+ currentDraggingRow: MRT_Row<TData> | null;
129
133
  currentEditingCell: MRT_Cell<TData> | null;
130
134
  currentEditingRow: MRT_Row<TData> | null;
131
135
  currentFilterFns: Record<string, MRT_FilterOption>;
132
136
  currentGlobalFilterFn: Record<string, MRT_FilterOption>;
133
137
  currentHoveredColumn: MRT_Column<TData> | null;
138
+ currentHoveredRow: MRT_Row<TData> | null;
134
139
  density: 'comfortable' | 'compact' | 'spacious';
135
140
  isFullScreen: boolean;
136
141
  isLoading: boolean;
@@ -226,6 +231,7 @@ export type MRT_ColumnDef<TData extends Record<string, any> = {}> = Omit<
226
231
  columns?: MRT_ColumnDef<TData>[];
227
232
  enableClickToCopy?: boolean;
228
233
  enableColumnActions?: boolean;
234
+ enableColumnDragging?: boolean;
229
235
  enableColumnFilterChangeMode?: boolean;
230
236
  enableColumnOrdering?: boolean;
231
237
  enableEditing?: boolean;
@@ -295,6 +301,15 @@ export type MRT_ColumnDef<TData extends Record<string, any> = {}> = Omit<
295
301
  table: MRT_TableInstance<TData>;
296
302
  column: MRT_Column<TData>;
297
303
  }) => IconButtonProps);
304
+ muiTableHeadCellDragHandleProps?:
305
+ | IconButtonProps
306
+ | (({
307
+ table,
308
+ column,
309
+ }: {
310
+ table: MRT_TableInstance<TData>;
311
+ column: MRT_Column<TData>;
312
+ }) => IconButtonProps);
298
313
  muiTableHeadCellFilterTextFieldProps?:
299
314
  | TextFieldProps
300
315
  | (({
@@ -368,12 +383,11 @@ export type MRT_HeaderGroup<TData extends Record<string, any> = {}> = Omit<
368
383
 
369
384
  export type MRT_Row<TData extends Record<string, any> = {}> = Omit<
370
385
  Row<TData>,
371
- 'getVisibleCells' | 'getAllCells' | 'subRows' | 'original' | '_valuesCache'
386
+ 'getVisibleCells' | 'getAllCells' | 'subRows' | '_valuesCache'
372
387
  > & {
373
388
  getAllCells: () => MRT_Cell<TData>[];
374
389
  getVisibleCells: () => MRT_Cell<TData>[];
375
390
  subRows?: MRT_Row<TData>[];
376
- original: TData;
377
391
  _valuesCache?: TData;
378
392
  };
379
393
 
@@ -397,11 +411,21 @@ export type MRT_FilterFn<TData extends Record<string, any> = {}> =
397
411
  | FilterFn<TData>
398
412
  | MRT_FilterOption;
399
413
 
414
+ /**
415
+ * `columns` and `data` props are the only required props, but there are over 150 other optional props.
416
+ *
417
+ * See more info on creating columns and data on the official docs site:
418
+ * @link https://www.material-react-table.com/docs/usage
419
+ *
420
+ * See the full props list on the official docs site:
421
+ * @link https://www.material-react-table.com/docs/api/props
422
+ */
400
423
  export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
401
424
  MRT_TableOptions<TData> & {
402
425
  editingMode?: 'table' | 'row' | 'cell';
403
426
  enableClickToCopy?: boolean;
404
427
  enableColumnActions?: boolean;
428
+ enableColumnDragging?: boolean;
405
429
  enableColumnFilterChangeMode?: boolean;
406
430
  enableColumnOrdering?: boolean;
407
431
  enableDensityToggle?: boolean;
@@ -412,7 +436,9 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
412
436
  enableGlobalFilterRankedResults?: boolean;
413
437
  enablePagination?: boolean;
414
438
  enableRowActions?: boolean;
439
+ enableRowDragging?: boolean;
415
440
  enableRowNumbers?: boolean;
441
+ enableRowOrdering?: boolean;
416
442
  enableRowVirtualization?: boolean;
417
443
  enableSelectAll?: boolean;
418
444
  enableStickyHeader?: boolean;
@@ -439,8 +465,10 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
439
465
  muiLinearProgressProps?:
440
466
  | LinearProgressProps
441
467
  | (({
468
+ isTopToolbar,
442
469
  table,
443
470
  }: {
471
+ isTopToolbar: boolean;
444
472
  table: MRT_TableInstance<TData>;
445
473
  }) => LinearProgressProps);
446
474
  muiSearchTextFieldProps?:
@@ -494,6 +522,15 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
494
522
  table: MRT_TableInstance<TData>;
495
523
  cell: MRT_Cell<TData>;
496
524
  }) => SkeletonProps);
525
+ muiTableBodyRowDragHandleProps?:
526
+ | IconButtonProps
527
+ | (({
528
+ table,
529
+ row,
530
+ }: {
531
+ table: MRT_TableInstance<TData>;
532
+ row: MRT_Row<TData>;
533
+ }) => IconButtonProps);
497
534
  muiTableBodyProps?:
498
535
  | TableBodyProps
499
536
  | (({ table }: { table: MRT_TableInstance<TData> }) => TableBodyProps);
@@ -552,6 +589,15 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
552
589
  table: MRT_TableInstance<TData>;
553
590
  column: MRT_Column<TData>;
554
591
  }) => IconButtonProps);
592
+ muiTableHeadCellDragHandleProps?:
593
+ | IconButtonProps
594
+ | (({
595
+ table,
596
+ column,
597
+ }: {
598
+ table: MRT_TableInstance<TData>;
599
+ column: MRT_Column<TData>;
600
+ }) => IconButtonProps);
555
601
  muiTableHeadCellFilterTextFieldProps?:
556
602
  | TextFieldProps
557
603
  | (({
@@ -622,12 +668,23 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
622
668
  cell: MRT_Cell<TData>;
623
669
  table: MRT_TableInstance<TData>;
624
670
  }) => void;
671
+ onColumnDrop?: ({
672
+ event,
673
+ draggedColumn,
674
+ targetColumn,
675
+ }: {
676
+ event: DragEvent<HTMLButtonElement>;
677
+ draggedColumn: MRT_Column<TData>;
678
+ targetColumn: MRT_Column<TData> | null;
679
+ }) => void;
625
680
  onCurrentDraggingColumnChange?: OnChangeFn<MRT_Column<TData> | null>;
681
+ onCurrentDraggingRowChange?: OnChangeFn<MRT_Row<TData> | null>;
626
682
  onCurrentEditingCellChange?: OnChangeFn<MRT_Cell<TData> | null>;
627
683
  onCurrentEditingRowChange?: OnChangeFn<MRT_Row<TData> | null>;
628
684
  onCurrentFilterFnsChange?: OnChangeFn<{ [key: string]: MRT_FilterOption }>;
629
685
  onCurrentGlobalFilterFnChange?: OnChangeFn<MRT_FilterOption>;
630
686
  onCurrentHoveredColumnChange?: OnChangeFn<MRT_Column<TData> | null>;
687
+ onCurrentHoveredRowChange?: OnChangeFn<MRT_Row<TData> | null>;
631
688
  onEditRowSubmit?: ({
632
689
  row,
633
690
  table,
@@ -637,6 +694,15 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
637
694
  }) => Promise<void> | void;
638
695
  onDensityChange?: OnChangeFn<boolean>;
639
696
  onIsFullScreenChange?: OnChangeFn<boolean>;
697
+ onRowDrop?: ({
698
+ event,
699
+ draggedRow,
700
+ targetRow,
701
+ }: {
702
+ event: DragEvent<HTMLButtonElement>;
703
+ draggedRow: MRT_Row<TData>;
704
+ targetRow: MRT_Row<TData> | null;
705
+ }) => void;
640
706
  onShowAlertBannerChange?: OnChangeFn<boolean>;
641
707
  onShowFiltersChange?: OnChangeFn<boolean>;
642
708
  onShowGlobalFilterChange?: OnChangeFn<boolean>;
@@ -709,15 +775,6 @@ export type MaterialReactTableProps<TData extends Record<string, any> = {}> =
709
775
  virtualizerProps?: Partial<VirtualizerOptions<HTMLDivElement>>;
710
776
  };
711
777
 
712
- /**
713
- * `columns` and `data` props are the only required props, but there are over 150 other optional props.
714
- *
715
- * See more info on creating columns and data on the official docs site:
716
- * @link https://www.material-react-table.com/docs/usage
717
- *
718
- * See the full props list on the official docs site:
719
- * @link https://www.material-react-table.com/docs/api/props
720
- */
721
778
  export default <TData extends Record<string, any> = {}>({
722
779
  autoResetExpanded = false,
723
780
  columnResizeMode = 'onEnd',
@@ -1,4 +1,4 @@
1
- import React, { DragEvent, FC, MouseEvent, useMemo } from 'react';
1
+ import React, { DragEvent, FC, MouseEvent, RefObject, useMemo } from 'react';
2
2
  import {
3
3
  alpha,
4
4
  darken,
@@ -10,11 +10,13 @@ import {
10
10
  import { MRT_EditCellTextField } from '../inputs/MRT_EditCellTextField';
11
11
  import { MRT_CopyButton } from '../buttons/MRT_CopyButton';
12
12
  import type { MRT_Cell, MRT_TableInstance } from '..';
13
+ import { MRT_TableBodyRowGrabHandle } from './MRT_TableBodyRowGrabHandle';
13
14
 
14
15
  interface Props {
15
16
  cell: MRT_Cell;
16
17
  enableHover?: boolean;
17
18
  rowIndex: number;
19
+ rowRef: RefObject<HTMLTableRowElement>;
18
20
  table: MRT_TableInstance;
19
21
  }
20
22
 
@@ -22,6 +24,7 @@ export const MRT_TableBodyCell: FC<Props> = ({
22
24
  cell,
23
25
  enableHover,
24
26
  rowIndex,
27
+ rowRef,
25
28
  table,
26
29
  }) => {
27
30
  const theme = useTheme();
@@ -30,6 +33,7 @@ export const MRT_TableBodyCell: FC<Props> = ({
30
33
  options: {
31
34
  editingMode,
32
35
  enableClickToCopy,
36
+ enableColumnOrdering,
33
37
  enableEditing,
34
38
  enableRowNumbers,
35
39
  muiTableBodyCellProps,
@@ -124,7 +128,7 @@ export const MRT_TableBodyCell: FC<Props> = ({
124
128
  };
125
129
 
126
130
  const handleDragEnter = (_e: DragEvent) => {
127
- if (currentDraggingColumn) {
131
+ if (enableColumnOrdering && currentDraggingColumn) {
128
132
  setCurrentHoveredColumn(columnDefType === 'data' ? column : null);
129
133
  }
130
134
  };
@@ -140,6 +144,10 @@ export const MRT_TableBodyCell: FC<Props> = ({
140
144
  ? {
141
145
  borderLeft: draggingBorder,
142
146
  borderRight: draggingBorder,
147
+ borderBottom:
148
+ row.index === table.getRowModel().rows.length - 1
149
+ ? draggingBorder
150
+ : undefined,
143
151
  }
144
152
  : undefined;
145
153
 
@@ -181,7 +189,7 @@ export const MRT_TableBodyCell: FC<Props> = ({
181
189
  ? '1rem 1.25rem'
182
190
  : '1.5rem',
183
191
  pl:
184
- column.id === 'mrt-expand'
192
+ column.id === 'mrt-row-expand'
185
193
  ? `${
186
194
  row.depth +
187
195
  (density === 'compact'
@@ -233,6 +241,12 @@ export const MRT_TableBodyCell: FC<Props> = ({
233
241
  rowNumberMode === 'static' &&
234
242
  column.id === 'mrt-row-numbers' ? (
235
243
  rowIndex + 1
244
+ ) : column.id === 'mrt-row-drag' ? (
245
+ <MRT_TableBodyRowGrabHandle
246
+ cell={cell}
247
+ rowRef={rowRef}
248
+ table={table}
249
+ />
236
250
  ) : columnDefType === 'display' ? (
237
251
  columnDef.Cell?.({ cell, table })
238
252
  ) : isEditing ? (
@@ -1,5 +1,5 @@
1
- import React, { FC } from 'react';
2
- import { darken, lighten, TableRow } from '@mui/material';
1
+ import React, { DragEvent, FC, useRef } from 'react';
2
+ import { darken, lighten, TableRow, useTheme } from '@mui/material';
3
3
  import { MRT_TableBodyCell } from './MRT_TableBodyCell';
4
4
  import { MRT_TableDetailPanel } from './MRT_TableDetailPanel';
5
5
  import type { MRT_Row, MRT_TableInstance } from '..';
@@ -11,24 +11,56 @@ interface Props {
11
11
  }
12
12
 
13
13
  export const MRT_TableBodyRow: FC<Props> = ({ row, rowIndex, table }) => {
14
+ const theme = useTheme();
14
15
  const {
15
16
  getIsSomeColumnsPinned,
16
- options: { muiTableBodyRowProps, renderDetailPanel },
17
+ getState,
18
+ options: { enableRowOrdering, muiTableBodyRowProps, renderDetailPanel },
19
+ setCurrentHoveredRow,
17
20
  } = table;
21
+ const { currentDraggingRow, currentHoveredRow } = getState();
18
22
 
19
23
  const tableRowProps =
20
24
  muiTableBodyRowProps instanceof Function
21
25
  ? muiTableBodyRowProps({ row, table })
22
26
  : muiTableBodyRowProps;
23
27
 
28
+ const handleDragEnter = (_e: DragEvent) => {
29
+ if (enableRowOrdering && currentDraggingRow) {
30
+ setCurrentHoveredRow(row);
31
+ }
32
+ };
33
+
34
+ const rowRef = useRef<HTMLTableRowElement>(null);
35
+
36
+ const draggingBorder =
37
+ currentDraggingRow?.id === row.id
38
+ ? `1px dashed ${theme.palette.divider}`
39
+ : currentHoveredRow?.id === row.id
40
+ ? `2px dashed ${theme.palette.primary.main}`
41
+ : undefined;
42
+
43
+ const draggingBorders = draggingBorder
44
+ ? {
45
+ border: draggingBorder,
46
+ }
47
+ : undefined;
48
+
24
49
  return (
25
50
  <>
26
51
  <TableRow
52
+ onDragEnter={handleDragEnter}
27
53
  hover
28
54
  selected={row.getIsSelected()}
55
+ ref={rowRef}
29
56
  {...tableRowProps}
30
57
  sx={(theme) => ({
31
58
  backgroundColor: lighten(theme.palette.background.default, 0.06),
59
+ opacity:
60
+ currentDraggingRow?.id === row.id ||
61
+ currentHoveredRow?.id === row.id
62
+ ? 0.5
63
+ : 1,
32
64
  transition: 'all 0.2s ease-in-out',
33
65
  '&:hover td': {
34
66
  backgroundColor:
@@ -39,6 +71,7 @@ export const MRT_TableBodyRow: FC<Props> = ({ row, rowIndex, table }) => {
39
71
  : undefined,
40
72
  },
41
73
  ...(tableRowProps?.sx as any),
74
+ ...draggingBorders,
42
75
  })}
43
76
  >
44
77
  {row?.getVisibleCells()?.map?.((cell) => (
@@ -47,6 +80,7 @@ export const MRT_TableBodyRow: FC<Props> = ({ row, rowIndex, table }) => {
47
80
  key={cell.id}
48
81
  enableHover={tableRowProps?.hover !== false}
49
82
  rowIndex={rowIndex}
83
+ rowRef={rowRef}
50
84
  table={table}
51
85
  />
52
86
  ))}
@@ -0,0 +1,48 @@
1
+ import React, { DragEvent, FC, RefObject } from 'react';
2
+ import { MRT_Cell, MRT_TableInstance } from '..';
3
+ import { MRT_GrabHandleButton } from '../buttons/MRT_GrabHandleButton';
4
+
5
+ interface Props {
6
+ cell: MRT_Cell;
7
+ rowRef: RefObject<HTMLTableRowElement>;
8
+ table: MRT_TableInstance;
9
+ }
10
+
11
+ export const MRT_TableBodyRowGrabHandle: FC<Props> = ({
12
+ cell,
13
+ rowRef,
14
+ table,
15
+ }) => {
16
+ const {
17
+ options: { muiTableBodyRowDragHandleProps, onRowDrop },
18
+ } = table;
19
+
20
+ const iconButtonProps =
21
+ muiTableBodyRowDragHandleProps instanceof Function
22
+ ? muiTableBodyRowDragHandleProps({ row: cell.row, table })
23
+ : muiTableBodyRowDragHandleProps;
24
+
25
+ const handleDragStart = (e: DragEvent<HTMLButtonElement>) => {
26
+ e.dataTransfer.setDragImage(rowRef.current as HTMLElement, 0, 0);
27
+ table.setCurrentDraggingRow(cell.row as any);
28
+ };
29
+
30
+ const handleDragEnd = (event: DragEvent<HTMLButtonElement>) => {
31
+ onRowDrop?.({
32
+ event,
33
+ draggedRow: table.getState().currentDraggingRow as any,
34
+ targetRow: table.getState().currentHoveredRow as any,
35
+ });
36
+ table.setCurrentDraggingRow(null);
37
+ table.setCurrentHoveredRow(null);
38
+ };
39
+
40
+ return (
41
+ <MRT_GrabHandleButton
42
+ iconButtonProps={iconButtonProps}
43
+ onDragStart={handleDragStart}
44
+ onDragEnd={handleDragEnd}
45
+ table={table}
46
+ />
47
+ );
48
+ };
@@ -1,16 +1,18 @@
1
- import { IconButton, Tooltip } from '@mui/material';
1
+ import { IconButton, IconButtonProps, Tooltip } from '@mui/material';
2
2
  import React, { DragEventHandler, FC } from 'react';
3
3
  import { MRT_TableInstance } from '..';
4
4
 
5
5
  interface Props {
6
- handleDragStart: DragEventHandler<HTMLButtonElement>;
7
- handleDragEnd: DragEventHandler<HTMLButtonElement>;
6
+ iconButtonProps?: IconButtonProps;
7
+ onDragStart: DragEventHandler<HTMLButtonElement>;
8
+ onDragEnd: DragEventHandler<HTMLButtonElement>;
8
9
  table: MRT_TableInstance;
9
10
  }
10
11
 
11
12
  export const MRT_GrabHandleButton: FC<Props> = ({
12
- handleDragStart,
13
- handleDragEnd,
13
+ iconButtonProps,
14
+ onDragEnd,
15
+ onDragStart,
14
16
  table,
15
17
  }) => {
16
18
  const {
@@ -26,14 +28,15 @@ export const MRT_GrabHandleButton: FC<Props> = ({
26
28
  enterDelay={1000}
27
29
  enterNextDelay={1000}
28
30
  placement="top"
29
- title={localization.grab}
31
+ title={localization.move}
30
32
  >
31
33
  <IconButton
32
34
  disableRipple
33
35
  draggable="true"
34
- onDragStart={handleDragStart}
35
- onDragEnd={handleDragEnd}
36
+ onDragStart={onDragStart}
37
+ onDragEnd={onDragEnd}
36
38
  size="small"
39
+ {...iconButtonProps}
37
40
  sx={{
38
41
  cursor: 'grab',
39
42
  m: 0,
@@ -47,6 +50,7 @@ export const MRT_GrabHandleButton: FC<Props> = ({
47
50
  '&:active': {
48
51
  cursor: 'grabbing',
49
52
  },
53
+ ...iconButtonProps?.sx,
50
54
  }}
51
55
  >
52
56
  <DragHandleIcon />
@@ -1,12 +1,11 @@
1
1
  import React, { DragEvent, FC, ReactNode } from 'react';
2
2
  import { Box, TableCell, Theme, alpha, lighten, useTheme } from '@mui/material';
3
+ import { MRT_TableHeadCellColumnActionsButton } from './MRT_TableHeadCellColumnActionsButton';
3
4
  import { MRT_TableHeadCellFilterContainer } from './MRT_TableHeadCellFilterContainer';
4
5
  import { MRT_TableHeadCellFilterLabel } from './MRT_TableHeadCellFilterLabel';
5
- import { MRT_GrabHandleButton } from '../buttons/MRT_GrabHandleButton';
6
+ import { MRT_TableHeadCellGrabHandle } from './MRT_TableHeadCellGrabHandle';
6
7
  import { MRT_TableHeadCellResizeHandle } from './MRT_TableHeadCellResizeHandle';
7
8
  import { MRT_TableHeadCellSortLabel } from './MRT_TableHeadCellSortLabel';
8
- import { MRT_TableHeadCellColumnActionsButton } from './MRT_TableHeadCellColumnActionsButton';
9
- import { reorderColumn } from '../utils';
10
9
  import type { MRT_Header, MRT_TableInstance } from '..';
11
10
 
12
11
  interface Props {
@@ -20,18 +19,16 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
20
19
  getState,
21
20
  options: {
22
21
  enableColumnActions,
22
+ enableColumnDragging,
23
23
  enableColumnOrdering,
24
24
  enableColumnResizing,
25
25
  enableGrouping,
26
26
  enableMultiSort,
27
27
  muiTableHeadCellProps,
28
28
  },
29
- setColumnOrder,
30
- setCurrentDraggingColumn,
31
29
  setCurrentHoveredColumn,
32
30
  } = table;
33
- const { columnOrder, density, currentDraggingColumn, currentHoveredColumn } =
34
- getState();
31
+ const { density, currentDraggingColumn, currentHoveredColumn } = getState();
35
32
  const { column } = header;
36
33
  const { columnDef } = column;
37
34
  const { columnDefType } = columnDef;
@@ -75,30 +72,14 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
75
72
  );
76
73
  };
77
74
 
78
- const tableHeadCellRef = React.useRef<HTMLElement>(null);
79
-
80
- const handleDragStart = (e: DragEvent<HTMLButtonElement>) => {
81
- setCurrentDraggingColumn(column);
82
- e.dataTransfer.setDragImage(tableHeadCellRef.current as HTMLElement, 0, 0);
83
- };
84
-
85
- const handleDragEnd = (_e: DragEvent<HTMLButtonElement>) => {
86
- setCurrentDraggingColumn(null);
87
- setCurrentHoveredColumn(null);
88
- if (
89
- currentHoveredColumn &&
90
- currentHoveredColumn?.id !== currentDraggingColumn?.id
91
- ) {
92
- setColumnOrder(reorderColumn(column, currentHoveredColumn, columnOrder));
93
- }
94
- };
95
-
96
75
  const handleDragEnter = (_e: DragEvent) => {
97
- if (currentDraggingColumn) {
76
+ if (enableColumnOrdering && currentDraggingColumn) {
98
77
  setCurrentHoveredColumn(columnDefType === 'data' ? column : null);
99
78
  }
100
79
  };
101
80
 
81
+ const tableHeadCellRef = React.useRef<HTMLTableCellElement>(null);
82
+
102
83
  const draggingBorder =
103
84
  currentDraggingColumn?.id === column.id
104
85
  ? `1px dashed ${theme.palette.divider}`
@@ -223,13 +204,15 @@ export const MRT_TableHeadCell: FC<Props> = ({ header, table }) => {
223
204
  </Box>
224
205
  <Box sx={{ whiteSpace: 'nowrap' }}>
225
206
  {columnDefType === 'data' &&
226
- ((enableColumnOrdering &&
227
- columnDef.enableColumnOrdering !== false) ||
207
+ ((enableColumnDragging &&
208
+ columnDef.enableColumnDragging !== false) ||
209
+ (enableColumnOrdering &&
210
+ columnDef.enableColumnOrdering !== false) ||
228
211
  (enableGrouping && columnDef.enableGrouping !== false)) && (
229
- <MRT_GrabHandleButton
230
- handleDragStart={handleDragStart}
231
- handleDragEnd={handleDragEnd}
212
+ <MRT_TableHeadCellGrabHandle
213
+ column={column}
232
214
  table={table}
215
+ tableHeadCellRef={tableHeadCellRef}
233
216
  />
234
217
  )}
235
218
  {(enableColumnActions || columnDef.enableColumnActions) &&
@@ -0,0 +1,77 @@
1
+ import React, { DragEvent, FC, RefObject } from 'react';
2
+ import { MRT_GrabHandleButton } from '../buttons/MRT_GrabHandleButton';
3
+ import { reorderColumn } from '../utils';
4
+ import type { MRT_Column, MRT_TableInstance } from '..';
5
+
6
+ interface Props {
7
+ column: MRT_Column;
8
+ table: MRT_TableInstance;
9
+ tableHeadCellRef: RefObject<HTMLTableCellElement>;
10
+ }
11
+
12
+ export const MRT_TableHeadCellGrabHandle: FC<Props> = ({
13
+ column,
14
+ table,
15
+ tableHeadCellRef,
16
+ }) => {
17
+ const {
18
+ getState,
19
+ options: {
20
+ enableColumnOrdering,
21
+ muiTableHeadCellDragHandleProps,
22
+ onColumnDrop,
23
+ },
24
+ setColumnOrder,
25
+ setCurrentDraggingColumn,
26
+ setCurrentHoveredColumn,
27
+ } = table;
28
+ const { columnDef } = column;
29
+ const { currentHoveredColumn, currentDraggingColumn, columnOrder } =
30
+ getState();
31
+
32
+ const mIconButtonProps =
33
+ muiTableHeadCellDragHandleProps instanceof Function
34
+ ? muiTableHeadCellDragHandleProps({ column, table })
35
+ : muiTableHeadCellDragHandleProps;
36
+
37
+ const mcIconButtonProps =
38
+ columnDef.muiTableHeadCellDragHandleProps instanceof Function
39
+ ? columnDef.muiTableHeadCellDragHandleProps({ column, table })
40
+ : columnDef.muiTableHeadCellDragHandleProps;
41
+
42
+ const iconButtonProps = {
43
+ ...mIconButtonProps,
44
+ ...mcIconButtonProps,
45
+ };
46
+
47
+ const handleDragStart = (e: DragEvent<HTMLButtonElement>) => {
48
+ setCurrentDraggingColumn(column);
49
+ e.dataTransfer.setDragImage(tableHeadCellRef.current as HTMLElement, 0, 0);
50
+ };
51
+
52
+ const handleDragEnd = (event: DragEvent<HTMLButtonElement>) => {
53
+ onColumnDrop?.({
54
+ event,
55
+ draggedColumn: column,
56
+ targetColumn: currentHoveredColumn,
57
+ });
58
+ if (
59
+ enableColumnOrdering &&
60
+ currentHoveredColumn &&
61
+ currentHoveredColumn?.id !== currentDraggingColumn?.id
62
+ ) {
63
+ setColumnOrder(reorderColumn(column, currentHoveredColumn, columnOrder));
64
+ }
65
+ setCurrentDraggingColumn(null);
66
+ setCurrentHoveredColumn(null);
67
+ };
68
+
69
+ return (
70
+ <MRT_GrabHandleButton
71
+ iconButtonProps={iconButtonProps}
72
+ onDragStart={handleDragStart}
73
+ onDragEnd={handleDragEnd}
74
+ table={table}
75
+ />
76
+ );
77
+ };