@atlaskit/editor-plugin-table 5.4.18 → 5.4.20

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 (96) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/plugins/table/index.js +1 -0
  3. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +5 -2
  4. package/dist/cjs/plugins/table/nodeviews/table.js +7 -2
  5. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  6. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/consts.js +3 -2
  7. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin.js +38 -14
  8. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/reducer.js +2 -0
  9. package/dist/cjs/plugins/table/ui/DragHandle/HandleIconComponent.js +4 -2
  10. package/dist/cjs/plugins/table/ui/DragHandle/index.js +16 -4
  11. package/dist/cjs/plugins/table/ui/FloatingDragMenu/DragMenu.js +3 -2
  12. package/dist/cjs/plugins/table/ui/FloatingDragMenu/index.js +4 -2
  13. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +6 -3
  14. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/index.js +4 -2
  15. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +5 -3
  16. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +7 -4
  17. package/dist/cjs/plugins/table/utils/drag-menu.js +10 -6
  18. package/dist/es2019/plugins/table/index.js +1 -0
  19. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +5 -2
  20. package/dist/es2019/plugins/table/nodeviews/table.js +7 -2
  21. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  22. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/consts.js +2 -1
  23. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin.js +39 -15
  24. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/reducer.js +5 -0
  25. package/dist/es2019/plugins/table/ui/DragHandle/HandleIconComponent.js +3 -1
  26. package/dist/es2019/plugins/table/ui/DragHandle/index.js +15 -4
  27. package/dist/es2019/plugins/table/ui/FloatingDragMenu/DragMenu.js +3 -2
  28. package/dist/es2019/plugins/table/ui/FloatingDragMenu/index.js +4 -2
  29. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +6 -3
  30. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/index.js +4 -2
  31. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +5 -3
  32. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +7 -4
  33. package/dist/es2019/plugins/table/utils/drag-menu.js +6 -6
  34. package/dist/esm/plugins/table/index.js +1 -0
  35. package/dist/esm/plugins/table/nodeviews/TableComponent.js +5 -2
  36. package/dist/esm/plugins/table/nodeviews/table.js +7 -2
  37. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/actions.js +2 -1
  38. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/consts.js +2 -1
  39. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin.js +39 -15
  40. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/reducer.js +2 -0
  41. package/dist/esm/plugins/table/ui/DragHandle/HandleIconComponent.js +4 -2
  42. package/dist/esm/plugins/table/ui/DragHandle/index.js +16 -4
  43. package/dist/esm/plugins/table/ui/FloatingDragMenu/DragMenu.js +3 -2
  44. package/dist/esm/plugins/table/ui/FloatingDragMenu/index.js +4 -2
  45. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +6 -3
  46. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/index.js +4 -2
  47. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +5 -3
  48. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +7 -4
  49. package/dist/esm/plugins/table/utils/drag-menu.js +10 -6
  50. package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +1 -0
  51. package/dist/types/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +4 -1
  52. package/dist/types/plugins/table/pm-plugins/drag-and-drop/consts.d.ts +1 -0
  53. package/dist/types/plugins/table/pm-plugins/drag-and-drop/plugin.d.ts +2 -1
  54. package/dist/types/plugins/table/pm-plugins/drag-and-drop/types.d.ts +1 -0
  55. package/dist/types/plugins/table/ui/DragHandle/HandleIconComponent.d.ts +1 -0
  56. package/dist/types/plugins/table/ui/DragHandle/index.d.ts +2 -1
  57. package/dist/types/plugins/table/ui/FloatingDragMenu/DragMenu.d.ts +2 -1
  58. package/dist/types/plugins/table/ui/FloatingDragMenu/index.d.ts +2 -1
  59. package/dist/types/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  60. package/dist/types/plugins/table/ui/TableFloatingColumnControls/index.d.ts +1 -0
  61. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +1 -0
  62. package/dist/types/plugins/table/ui/TableFloatingControls/index.d.ts +1 -0
  63. package/dist/types/plugins/table/utils/drag-menu.d.ts +1 -1
  64. package/dist/types-ts4.5/plugins/table/nodeviews/TableComponent.d.ts +1 -0
  65. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/actions.d.ts +4 -1
  66. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/consts.d.ts +1 -0
  67. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/plugin.d.ts +2 -1
  68. package/dist/types-ts4.5/plugins/table/pm-plugins/drag-and-drop/types.d.ts +1 -0
  69. package/dist/types-ts4.5/plugins/table/ui/DragHandle/HandleIconComponent.d.ts +1 -0
  70. package/dist/types-ts4.5/plugins/table/ui/DragHandle/index.d.ts +2 -1
  71. package/dist/types-ts4.5/plugins/table/ui/FloatingDragMenu/DragMenu.d.ts +2 -1
  72. package/dist/types-ts4.5/plugins/table/ui/FloatingDragMenu/index.d.ts +2 -1
  73. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -1
  74. package/dist/types-ts4.5/plugins/table/ui/TableFloatingColumnControls/index.d.ts +1 -0
  75. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +1 -0
  76. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/index.d.ts +1 -0
  77. package/dist/types-ts4.5/plugins/table/utils/drag-menu.d.ts +1 -1
  78. package/package.json +1 -1
  79. package/src/__tests__/unit/pm-plugins/drag-and-drop/plugin.ts +112 -0
  80. package/src/plugins/table/index.tsx +1 -0
  81. package/src/plugins/table/nodeviews/TableComponent.tsx +4 -0
  82. package/src/plugins/table/nodeviews/table.tsx +4 -0
  83. package/src/plugins/table/pm-plugins/drag-and-drop/actions.ts +9 -1
  84. package/src/plugins/table/pm-plugins/drag-and-drop/consts.ts +2 -0
  85. package/src/plugins/table/pm-plugins/drag-and-drop/plugin.ts +49 -17
  86. package/src/plugins/table/pm-plugins/drag-and-drop/reducer.ts +5 -0
  87. package/src/plugins/table/pm-plugins/drag-and-drop/types.ts +1 -0
  88. package/src/plugins/table/ui/DragHandle/HandleIconComponent.tsx +5 -1
  89. package/src/plugins/table/ui/DragHandle/index.tsx +15 -2
  90. package/src/plugins/table/ui/FloatingDragMenu/DragMenu.tsx +3 -1
  91. package/src/plugins/table/ui/FloatingDragMenu/index.tsx +3 -0
  92. package/src/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.tsx +5 -1
  93. package/src/plugins/table/ui/TableFloatingColumnControls/index.tsx +3 -0
  94. package/src/plugins/table/ui/TableFloatingControls/RowControls/DragControls.tsx +5 -2
  95. package/src/plugins/table/ui/TableFloatingControls/index.tsx +6 -1
  96. package/src/plugins/table/utils/drag-menu.ts +6 -6
@@ -0,0 +1,112 @@
1
+ import type { DocBuilder } from '@atlaskit/editor-common/types';
2
+ // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
3
+ import { analyticsPlugin } from '@atlaskit/editor-plugin-analytics';
4
+ import { contentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
5
+ import { featureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
6
+ import { guidelinePlugin } from '@atlaskit/editor-plugin-guideline';
7
+ import { selectionPlugin } from '@atlaskit/editor-plugin-selection';
8
+ import { widthPlugin } from '@atlaskit/editor-plugin-width';
9
+ // eslint-disable-next-line import/no-extraneous-dependencies
10
+ import type { LightEditorPlugin } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
11
+ // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
12
+ import {
13
+ createProsemirrorEditorFactory,
14
+ Preset,
15
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
16
+ // eslint-disable-next-line import/no-extraneous-dependencies -- Removed import for fixing circular dependencies
17
+ import {
18
+ doc,
19
+ p,
20
+ table,
21
+ td,
22
+ tdCursor,
23
+ tdEmpty,
24
+ tr,
25
+ } from '@atlaskit/editor-test-helpers/doc-builder';
26
+
27
+ import tablePlugin from '../../../../plugins/table';
28
+ import { DRAGGABLE_TABLE_NODE_SIZE_LIMIT } from '../../../../plugins/table/pm-plugins/drag-and-drop/consts';
29
+ import { getPluginState } from '../../../../plugins/table/pm-plugins/drag-and-drop/plugin-factory';
30
+ import { pluginKey } from '../../../../plugins/table/pm-plugins/plugin-key';
31
+ import type { PluginConfig } from '../../../../plugins/table/types';
32
+
33
+ const tableOptions = {
34
+ allowNumberColumn: true,
35
+ allowHeaderRow: true,
36
+ allowHeaderColumn: true,
37
+ permittedLayouts: 'all',
38
+ allowColumnResizing: true,
39
+ stickyHeaders: true,
40
+ } as PluginConfig;
41
+
42
+ describe('drag and drop plugin', () => {
43
+ const createEditor = createProsemirrorEditorFactory();
44
+ const editor = (doc: DocBuilder) =>
45
+ createEditor({
46
+ doc,
47
+ attachTo: document.body,
48
+ preset: new Preset<LightEditorPlugin>()
49
+ .add([featureFlagsPlugin, {}])
50
+ .add([analyticsPlugin, {}])
51
+ .add(contentInsertionPlugin)
52
+ .add(widthPlugin)
53
+ .add(guidelinePlugin)
54
+ .add(selectionPlugin)
55
+ .add([
56
+ tablePlugin,
57
+ {
58
+ tableOptions,
59
+ dragAndDropEnabled: true,
60
+ },
61
+ ]),
62
+ pluginKey,
63
+ });
64
+
65
+ describe('when table is not selected', () => {
66
+ it('should reset table canDrag so by default tables are draggable', () => {
67
+ const { editorView } = editor(
68
+ doc(
69
+ p('{<>}Hello World'),
70
+ table()(tr(tdEmpty, tdEmpty), tr(tdEmpty, tdEmpty)),
71
+ ),
72
+ );
73
+
74
+ const { canDrag } = getPluginState(editorView.state);
75
+ expect(canDrag).toBe(true);
76
+ });
77
+ });
78
+
79
+ describe('when table is selected', () => {
80
+ it('should allow items to be draggable if table is within nodeSize limit', () => {
81
+ const { editorView } = editor(
82
+ // The nodeSize of an empty 2x2 is 22 so if i adjust the limit to be 1 under the max (ie. 23), then canDrag should be enabled.
83
+ doc(
84
+ table()(
85
+ tr(tdCursor, tdEmpty),
86
+ tr(
87
+ tdEmpty,
88
+ td()(p('-'.repeat(DRAGGABLE_TABLE_NODE_SIZE_LIMIT - 23))),
89
+ ),
90
+ ),
91
+ ),
92
+ );
93
+
94
+ const { canDrag } = getPluginState(editorView.state);
95
+ expect(canDrag).toBe(true);
96
+ });
97
+
98
+ it('should not allow items to be draggable if table is above nodeSize limit', () => {
99
+ const { editorView } = editor(
100
+ doc(
101
+ table()(
102
+ tr(tdCursor, tdEmpty),
103
+ tr(tdEmpty, td()(p('-'.repeat(DRAGGABLE_TABLE_NODE_SIZE_LIMIT)))),
104
+ ),
105
+ ),
106
+ );
107
+
108
+ const { canDrag } = getPluginState(editorView.state);
109
+ expect(canDrag).toBe(false);
110
+ });
111
+ });
112
+ });
@@ -494,6 +494,7 @@ const tablesPlugin: TablePlugin = ({ config: options, api }) => {
494
494
  direction={dragAndDropState?.dragMenuDirection}
495
495
  index={dragAndDropState?.dragMenuIndex}
496
496
  isOpen={!!dragAndDropState?.isDragMenuOpen && !isResizing}
497
+ canDrag={dragAndDropState?.canDrag}
497
498
  getEditorContainerWidth={defaultGetEditorContainerWidth}
498
499
  />
499
500
  )}
@@ -97,6 +97,7 @@ export interface ComponentProps {
97
97
  isHeaderColumnEnabled: boolean;
98
98
  isMediaFullscreen?: boolean;
99
99
  isDragAndDropEnabled?: boolean;
100
+ canDrag?: boolean;
100
101
  tableActive: boolean;
101
102
  ordering: TableColumnOrdering;
102
103
  isResizing?: boolean;
@@ -470,6 +471,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
470
471
  getPos,
471
472
  pluginInjectionApi,
472
473
  isDragAndDropEnabled,
474
+ canDrag,
473
475
  } = this.props;
474
476
  const { showBeforeShadow, showAfterShadow } = this.state;
475
477
  const node = getNode();
@@ -497,6 +499,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
497
499
  isNumberColumnEnabled={node.attrs.isNumberColumnEnabled}
498
500
  isHeaderRowEnabled={isHeaderRowEnabled}
499
501
  isDragAndDropEnabled={isDragAndDropEnabled}
502
+ canDrag={canDrag}
500
503
  ordering={ordering}
501
504
  isHeaderColumnEnabled={isHeaderColumnEnabled}
502
505
  hasHeaderRow={hasHeaderRow}
@@ -525,6 +528,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
525
528
  headerRowHeight={headerRow ? headerRow.offsetHeight : undefined}
526
529
  stickyHeader={this.state.stickyHeader}
527
530
  getEditorFeatureFlags={this.props.getEditorFeatureFlags}
531
+ canDrag={canDrag}
528
532
  />
529
533
  ) : null;
530
534
 
@@ -27,6 +27,7 @@ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
27
27
  import { TableMap } from '@atlaskit/editor-tables/table-map';
28
28
 
29
29
  import { pluginConfig as getPluginConfig } from '../create-plugin-config';
30
+ import { pluginKey as tableDragAndDropPluginKey } from '../pm-plugins/drag-and-drop';
30
31
  import { getPluginState } from '../pm-plugins/plugin-factory';
31
32
  import { pluginKey } from '../pm-plugins/plugin-key';
32
33
  import { pluginKey as tableResizingPluginKey } from '../pm-plugins/table-resizing';
@@ -206,6 +207,7 @@ export default class TableView extends ReactNodeView<Props> {
206
207
  tableWidthPluginState: tableWidthPluginKey,
207
208
  widthPlugin: fakePluginKey,
208
209
  mediaState: fakeMediaPluginKey,
210
+ tableDragAndDropState: tableDragAndDropPluginKey,
209
211
  }}
210
212
  editorView={props.view}
211
213
  render={(pluginStates) => {
@@ -215,6 +217,7 @@ export default class TableView extends ReactNodeView<Props> {
215
217
  pluginState,
216
218
  // containerWidth,
217
219
  mediaState,
220
+ tableDragAndDropState,
218
221
  } = pluginStates;
219
222
  const containerWidth = props.getEditorContainerWidth();
220
223
 
@@ -250,6 +253,7 @@ export default class TableView extends ReactNodeView<Props> {
250
253
  isHeaderRowEnabled={pluginState!.isHeaderRowEnabled}
251
254
  isHeaderColumnEnabled={pluginState!.isHeaderColumnEnabled}
252
255
  isDragAndDropEnabled={pluginState!.isDragAndDropEnabled}
256
+ canDrag={tableDragAndDropState?.canDrag ?? false}
253
257
  tableActive={tableActive}
254
258
  ordering={pluginState!.ordering as TableColumnOrdering}
255
259
  isResizing={isResizing}
@@ -3,6 +3,7 @@ import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
3
  import type { TableDirection } from '../../types';
4
4
 
5
5
  import type { DropTargetType } from './consts';
6
+ import type { DragAndDropPluginState } from './types';
6
7
 
7
8
  export interface DragAndDropAction<T, D> {
8
9
  type: T;
@@ -13,6 +14,7 @@ export const DragAndDropActionType = {
13
14
  SET_DROP_TARGET: 'SET_DROP_TARGET',
14
15
  CLEAR_DROP_TARGET: 'CLEAR_DROP_TARGET',
15
16
  TOGGLE_DRAG_MENU: 'TOGGLE_DRAG_MENU',
17
+ UPDATE: 'UPDATE',
16
18
  } as const;
17
19
 
18
20
  export type DragAndDropSetDropTargetAction = DragAndDropAction<
@@ -40,8 +42,14 @@ export type DragAndDropToggleDragMenuAction = DragAndDropAction<
40
42
  }
41
43
  >;
42
44
 
45
+ export type DragAndDropUpdateAction = DragAndDropAction<
46
+ typeof DragAndDropActionType.UPDATE,
47
+ Partial<DragAndDropPluginState>
48
+ >;
49
+
43
50
  // NOTE: This should be a Union of all possible actions
44
51
  export type DragAndDropPluginAction =
45
52
  | DragAndDropSetDropTargetAction
46
53
  | DragAndDropClearDropTargetAction
47
- | DragAndDropToggleDragMenuAction;
54
+ | DragAndDropToggleDragMenuAction
55
+ | DragAndDropUpdateAction;
@@ -6,3 +6,5 @@ export const DropTargetType = {
6
6
 
7
7
  export type DropTargetType =
8
8
  (typeof DropTargetType)[keyof typeof DropTargetType];
9
+
10
+ export const DRAGGABLE_TABLE_NODE_SIZE_LIMIT = 20000;
@@ -25,9 +25,10 @@ import {
25
25
  setDropTarget,
26
26
  toggleDragMenu,
27
27
  } from './commands';
28
- import { DropTargetType } from './consts';
28
+ import { DRAGGABLE_TABLE_NODE_SIZE_LIMIT, DropTargetType } from './consts';
29
29
  import { createPluginState, getPluginState } from './plugin-factory';
30
30
  import { pluginKey } from './plugin-key';
31
+ import type { DragAndDropPluginState } from './types';
31
32
  import { getDraggableDataFromEvent } from './utils/monitor';
32
33
 
33
34
  export const createPlugin = (
@@ -42,14 +43,23 @@ export const createPlugin = (
42
43
  isDragMenuOpen: false,
43
44
  dragMenuIndex: 0,
44
45
  isDragging: false,
46
+ canDrag: false,
45
47
  })),
46
48
  key: pluginKey,
47
49
  appendTransaction: (transactions, oldState, newState) => {
48
- const { targetCellPosition: oldTargetCellPosition } =
49
- getTablePluginState(oldState);
50
- const { targetCellPosition: newTargetCellPosition } =
51
- getTablePluginState(newState);
52
- const { isDragMenuOpen, dragMenuIndex } = getPluginState(newState);
50
+ const {
51
+ targetCellPosition: oldTargetCellPosition,
52
+ tableNode: oldTableNode,
53
+ } = getTablePluginState(oldState);
54
+ const {
55
+ targetCellPosition: newTargetCellPosition,
56
+ tableNode: newTableNode,
57
+ } = getTablePluginState(newState);
58
+ const { isDragMenuOpen, dragMenuIndex, canDrag } =
59
+ getPluginState(newState);
60
+
61
+ const stateChanges: Array<Partial<DragAndDropPluginState>> = [];
62
+ const tr = newState.tr;
53
63
 
54
64
  // What's happening here? you asked... In a nutshell;
55
65
  // If the target cell position changes while the drag menu is open then we want to close the drag menu if it has been opened.
@@ -57,15 +67,6 @@ export const createPlugin = (
57
67
  // to check if the new target cell position is pointed at a different cell than what the drag menu was opened on.
58
68
  if (oldTargetCellPosition !== newTargetCellPosition) {
59
69
  if (isDragMenuOpen) {
60
- const tr = newState.tr;
61
- const action = {
62
- type: DragAndDropActionType.TOGGLE_DRAG_MENU,
63
- data: {
64
- isDragMenuOpen: false,
65
- direction: undefined,
66
- },
67
- };
68
-
69
70
  if (newTargetCellPosition !== undefined) {
70
71
  const cells = getCellsInRow(dragMenuIndex)(tr.selection);
71
72
  // ED-20673 check if it is a cell selection,
@@ -78,13 +79,44 @@ export const createPlugin = (
78
79
  cells[0].node !== tr.doc.nodeAt(newTargetCellPosition) &&
79
80
  !isCellSelection
80
81
  ) {
81
- return tr.setMeta(pluginKey, action);
82
+ stateChanges.push({
83
+ isDragMenuOpen: false,
84
+ dragMenuDirection: undefined,
85
+ });
82
86
  } // else NOP
83
87
  } else {
84
- return tr.setMeta(pluginKey, action);
88
+ stateChanges.push({
89
+ isDragMenuOpen: false,
90
+ dragMenuDirection: undefined,
91
+ });
85
92
  }
86
93
  }
87
94
  }
95
+
96
+ if (oldTableNode?.nodeSize !== newTableNode?.nodeSize) {
97
+ const nextCanDrag =
98
+ (newTableNode?.nodeSize ?? 0) < DRAGGABLE_TABLE_NODE_SIZE_LIMIT;
99
+
100
+ if (canDrag !== nextCanDrag) {
101
+ stateChanges.push({
102
+ canDrag: nextCanDrag,
103
+ });
104
+ }
105
+ }
106
+
107
+ if (stateChanges.length) {
108
+ return tr
109
+ .setMeta(pluginKey, {
110
+ type: DragAndDropActionType.UPDATE,
111
+ data: {
112
+ ...stateChanges.reduce(
113
+ (state, cur) => ({ ...state, ...cur }),
114
+ {},
115
+ ),
116
+ },
117
+ })
118
+ .setMeta('addToHistory', false);
119
+ }
88
120
  },
89
121
  view: (editorView: EditorView) => {
90
122
  return {
@@ -31,6 +31,11 @@ export default (
31
31
  dragMenuDirection: action.data.direction,
32
32
  dragMenuIndex: action.data.index,
33
33
  };
34
+ case DragAndDropActionType.UPDATE:
35
+ return {
36
+ ...pluginState,
37
+ ...action.data,
38
+ };
34
39
  default:
35
40
  return pluginState;
36
41
  }
@@ -12,4 +12,5 @@ export interface DragAndDropPluginState {
12
12
  dragMenuDirection?: TableDirection;
13
13
  dragMenuIndex: number;
14
14
  isDragging: boolean;
15
+ canDrag: boolean;
15
16
  }
@@ -7,6 +7,7 @@ import {
7
7
  } from '../icons';
8
8
 
9
9
  type HandleIconProps = {
10
+ canDrag: boolean;
10
11
  hasMergedCells: boolean;
11
12
  direction: 'row' | 'column';
12
13
  isDragMenuOpen: boolean | undefined;
@@ -19,6 +20,7 @@ type HandleIconProps = {
19
20
 
20
21
  export const HandleIconComponent = (props: HandleIconProps) => {
21
22
  const {
23
+ canDrag,
22
24
  direction,
23
25
  isDragMenuOpen,
24
26
  isRowHandleHovered,
@@ -36,7 +38,9 @@ export const HandleIconComponent = (props: HandleIconProps) => {
36
38
  dragMenuDirection === direction &&
37
39
  isCurrentRowOrColumnSelected;
38
40
 
39
- const showNormalHandle = hasMergedCells ? (
41
+ const isDragPossible = canDrag && !hasMergedCells;
42
+
43
+ const showNormalHandle = !isDragPossible ? (
40
44
  <DragHandleDisabledIcon />
41
45
  ) : (
42
46
  <DragHandleIcon />
@@ -32,6 +32,7 @@ type DragHandleProps = {
32
32
  onMouseOut?: MouseEventHandler;
33
33
  onMouseUp?: MouseEventHandler;
34
34
  editorView: EditorView;
35
+ canDrag?: boolean;
35
36
  };
36
37
 
37
38
  export const DragHandle = ({
@@ -46,6 +47,7 @@ export const DragHandle = ({
46
47
  onMouseUp,
47
48
  onClick,
48
49
  editorView,
50
+ canDrag = false,
49
51
  }: DragHandleProps) => {
50
52
  const dragHandleDivRef = useRef<HTMLButtonElement>(null);
51
53
  const [previewContainer, setPreviewContainer] = useState<HTMLElement | null>(
@@ -82,6 +84,7 @@ export const DragHandle = ({
82
84
  );
83
85
 
84
86
  const handleIconProps = {
87
+ canDrag,
85
88
  hasMergedCells,
86
89
  direction,
87
90
  isDragMenuOpen,
@@ -99,7 +102,7 @@ export const DragHandle = ({
99
102
  return draggable({
100
103
  element: dragHandleDivRefCurrent,
101
104
  canDrag: () => {
102
- return !hasMergedCells;
105
+ return canDrag && !hasMergedCells;
103
106
  },
104
107
  getInitialData() {
105
108
  return {
@@ -112,6 +115,15 @@ export const DragHandle = ({
112
115
  setCustomNativeDragPreview({
113
116
  getOffset: ({ container }) => {
114
117
  const rect = container.getBoundingClientRect();
118
+ if (browser.safari) {
119
+ // See: https://product-fabric.atlassian.net/browse/ED-21442
120
+ // We need to ensure that the preview is not overlaying screen content when the snapshot is taken, otherwise
121
+ // safari will composite the screen text elements into the bitmap snapshot. The container is a wrapper which is already
122
+ // positioned fixed at top/left 0.
123
+ // IMPORTANT: we must not exceed more then the width of the container off-screen otherwise not preview will
124
+ // be generated.
125
+ container.style.left = `-${rect.width - 0.0001}px`;
126
+ }
115
127
  if (direction === 'row') {
116
128
  return { x: 16, y: 16 };
117
129
  } else {
@@ -133,6 +145,7 @@ export const DragHandle = ({
133
145
  indexes,
134
146
  editorView.state.selection,
135
147
  hasMergedCells,
148
+ canDrag,
136
149
  ]);
137
150
 
138
151
  return (
@@ -142,7 +155,7 @@ export const DragHandle = ({
142
155
  ClassName.DRAG_HANDLE_BUTTON_CONTAINER,
143
156
  appearance,
144
157
  {
145
- [ClassName.DRAG_HANDLE_DISABLED]: hasMergedCells,
158
+ [ClassName.DRAG_HANDLE_DISABLED]: !canDrag || hasMergedCells,
146
159
  },
147
160
  )}
148
161
  ref={dragHandleDivRef}
@@ -49,6 +49,7 @@ type DragMenuProps = {
49
49
  scrollableElement?: HTMLElement;
50
50
  pluginConfig?: PluginConfig;
51
51
  getEditorContainerWidth: GetEditorContainerWidth;
52
+ canDrag?: boolean;
52
53
  };
53
54
 
54
55
  const groupedDragMenuConfig = [
@@ -119,6 +120,7 @@ export const DragMenu = ({
119
120
  scrollableElement,
120
121
  targetCellPosition,
121
122
  getEditorContainerWidth,
123
+ canDrag,
122
124
  }: DragMenuProps) => {
123
125
  const tableMap = tableNode ? TableMap.get(tableNode) : undefined;
124
126
 
@@ -137,7 +139,7 @@ export const DragMenu = ({
137
139
  const dragMenuConfig = getDragMenuConfig(
138
140
  direction,
139
141
  getEditorContainerWidth,
140
- shouldMoveDisabled,
142
+ !!canDrag && !shouldMoveDisabled,
141
143
  tableMap,
142
144
  index,
143
145
  targetCellPosition,
@@ -25,6 +25,7 @@ export interface Props {
25
25
  index?: number;
26
26
  targetCellPosition?: number;
27
27
  getEditorContainerWidth: GetEditorContainerWidth;
28
+ canDrag?: boolean;
28
29
  }
29
30
 
30
31
  const FloatingDragMenu = ({
@@ -39,6 +40,7 @@ const FloatingDragMenu = ({
39
40
  index,
40
41
  targetCellPosition,
41
42
  getEditorContainerWidth,
43
+ canDrag,
42
44
  }: Props) => {
43
45
  if (
44
46
  !isOpen ||
@@ -86,6 +88,7 @@ const FloatingDragMenu = ({
86
88
  index={index}
87
89
  targetCellPosition={targetCellPosition}
88
90
  getEditorContainerWidth={getEditorContainerWidth}
91
+ canDrag={canDrag}
89
92
  />
90
93
  </Popup>
91
94
  );
@@ -1,6 +1,7 @@
1
1
  import type { MouseEvent } from 'react';
2
2
  import React, { useCallback, useMemo } from 'react';
3
3
 
4
+ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
4
5
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
5
6
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
6
7
  import { CellSelection } from '@atlaskit/editor-tables';
@@ -31,6 +32,7 @@ export interface ColumnControlsProps {
31
32
  colWidths?: (number | undefined)[];
32
33
  hasHeaderColumn?: boolean;
33
34
  isTableHovered?: boolean;
35
+ canDrag?: boolean;
34
36
  }
35
37
 
36
38
  const getSelectedColumns = (selection: Selection) => {
@@ -57,6 +59,7 @@ export const ColumnControls = ({
57
59
  colWidths,
58
60
  hasHeaderColumn,
59
61
  isTableHovered,
62
+ canDrag,
60
63
  }: ColumnControlsProps) => {
61
64
  const widths =
62
65
  colWidths?.map((width) => (width ? `${width - 1}px` : '0px')).join(' ') ??
@@ -203,7 +206,7 @@ export const ColumnControls = ({
203
206
  direction="column"
204
207
  tableLocalId={localId || ''}
205
208
  indexes={colIndexes}
206
- previewWidth={colWidths?.[colIndex!] ?? 48}
209
+ previewWidth={colWidths?.[colIndex!] ?? tableCellMinWidth}
207
210
  previewHeight={previewHeight}
208
211
  appearance={
209
212
  selectedColIndexes.includes(hoveredCell.colIndex!)
@@ -217,6 +220,7 @@ export const ColumnControls = ({
217
220
  onMouseOut={handleMouseOut}
218
221
  onMouseUp={handleMouseUp}
219
222
  editorView={editorView}
223
+ canDrag={canDrag}
220
224
  />
221
225
  </div>
222
226
  )}
@@ -35,6 +35,7 @@ export interface Props {
35
35
  ordering?: TableColumnOrdering;
36
36
  stickyHeader?: RowStickyState;
37
37
  isTableHovered?: boolean;
38
+ canDrag?: boolean;
38
39
  }
39
40
 
40
41
  export const TableFloatingColumnControls: React.FC<Props> = ({
@@ -49,6 +50,7 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
49
50
  selection,
50
51
  isInDanger,
51
52
  isTableHovered,
53
+ canDrag,
52
54
  }) => {
53
55
  const [tableRect, setTableRect] = useState<{ width: number; height: number }>(
54
56
  { width: 0, height: 0 },
@@ -139,6 +141,7 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
139
141
  rowHeights={rowHeights}
140
142
  colWidths={colWidths}
141
143
  hasHeaderColumn={hasHeaderColumn}
144
+ canDrag={canDrag}
142
145
  />
143
146
  {hasDropTargets && (
144
147
  <ColumnDropTargets
@@ -42,6 +42,7 @@ type DragControlsProps = {
42
42
  isInDanger?: boolean;
43
43
  isResizing?: boolean;
44
44
  isTableHovered?: boolean;
45
+ canDrag?: boolean;
45
46
  hoverRows: (rows: number[], danger?: boolean) => void;
46
47
  selectRow: (row: number, expand: boolean) => void;
47
48
  updateCellHoverLocation: (rowIndex: number) => void;
@@ -68,6 +69,7 @@ const DragControlsComponent = ({
68
69
  isInDanger,
69
70
  isResizing,
70
71
  isTableHovered,
72
+ canDrag,
71
73
  hoverRows,
72
74
  selectRow,
73
75
  updateCellHoverLocation,
@@ -188,7 +190,7 @@ const DragControlsComponent = ({
188
190
  data-end-index={endIndex}
189
191
  className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT_WRAPPER}
190
192
  contentEditable={false}
191
- key={index}
193
+ key={`insert-dot-${index}`}
192
194
  >
193
195
  {/* TODO: Disabling first column insert button https://atlassian.slack.com/archives/C05U8HRQM50/p1698363744682219?thread_ts=1698209039.104909&cid=C05U8HRQM50 */}
194
196
  {/* {!hasHeaderRow && index === 0 && (
@@ -204,7 +206,7 @@ const DragControlsComponent = ({
204
206
  </div>
205
207
  {isDragging && (
206
208
  <RowDropTarget
207
- key={index}
209
+ key={`drop-target-${index}`}
208
210
  index={index}
209
211
  localId={currentNodeLocalId}
210
212
  style={{
@@ -248,6 +250,7 @@ const DragControlsComponent = ({
248
250
  onMouseOut={handleMouseOut}
249
251
  onMouseUp={onMouseUp}
250
252
  editorView={editorView}
253
+ canDrag={canDrag}
251
254
  />
252
255
  </div>
253
256
  )}
@@ -29,6 +29,7 @@ export interface Props {
29
29
  isHeaderColumnEnabled?: boolean;
30
30
  isNumberColumnEnabled?: boolean;
31
31
  isDragAndDropEnabled?: boolean;
32
+ canDrag?: boolean;
32
33
  hasHeaderRow?: boolean;
33
34
  headerRowHeight?: number;
34
35
  hoveredRows?: number[];
@@ -106,6 +107,7 @@ export default class TableFloatingControls extends Component<Props, State> {
106
107
  stickyHeader,
107
108
  hoveredCell,
108
109
  isTableHovered,
110
+ canDrag,
109
111
  } = this.props;
110
112
  return (
111
113
  this.state.tableWrapperWidth !== nextState.tableWrapperWidth ||
@@ -123,7 +125,8 @@ export default class TableFloatingControls extends Component<Props, State> {
123
125
  headerRowHeight !== nextProps.headerRowHeight ||
124
126
  stickyHeader !== nextProps.stickyHeader ||
125
127
  hoveredCell !== nextProps.hoveredCell ||
126
- isTableHovered !== nextProps.isTableHovered
128
+ isTableHovered !== nextProps.isTableHovered ||
129
+ canDrag !== nextProps.canDrag
127
130
  );
128
131
  }
129
132
 
@@ -150,6 +153,7 @@ export default class TableFloatingControls extends Component<Props, State> {
150
153
  isDragAndDropEnabled,
151
154
  hoveredCell,
152
155
  isTableHovered,
156
+ canDrag,
153
157
  } = this.props;
154
158
 
155
159
  if (!tableRef) {
@@ -208,6 +212,7 @@ export default class TableFloatingControls extends Component<Props, State> {
208
212
  hoverRows={this.hoverRows}
209
213
  selectRow={this.selectRow}
210
214
  updateCellHoverLocation={this.updateCellHoverLocation}
215
+ canDrag={canDrag}
211
216
  />
212
217
  </>
213
218
  ) : (