@atlaskit/editor-plugin-table 7.5.16 → 7.6.0

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 (39) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/pm-plugins/drag-and-drop/commands-with-analytics.js +36 -1
  3. package/dist/cjs/pm-plugins/drag-and-drop/commands.js +17 -1
  4. package/dist/cjs/pm-plugins/drag-and-drop/plugin.js +8 -2
  5. package/dist/cjs/pm-plugins/drag-and-drop/utils/getDragBehaviour.js +13 -0
  6. package/dist/cjs/pm-plugins/drag-and-drop/utils/monitor.js +11 -4
  7. package/dist/cjs/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.js +31 -6
  8. package/dist/cjs/ui/TableFloatingControls/RowDropTarget/index.js +31 -6
  9. package/dist/es2019/pm-plugins/drag-and-drop/commands-with-analytics.js +34 -1
  10. package/dist/es2019/pm-plugins/drag-and-drop/commands.js +15 -1
  11. package/dist/es2019/pm-plugins/drag-and-drop/plugin.js +9 -3
  12. package/dist/es2019/pm-plugins/drag-and-drop/utils/getDragBehaviour.js +8 -0
  13. package/dist/es2019/pm-plugins/drag-and-drop/utils/monitor.js +9 -4
  14. package/dist/es2019/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.js +27 -3
  15. package/dist/es2019/ui/TableFloatingControls/RowDropTarget/index.js +27 -3
  16. package/dist/esm/pm-plugins/drag-and-drop/commands-with-analytics.js +36 -1
  17. package/dist/esm/pm-plugins/drag-and-drop/commands.js +17 -1
  18. package/dist/esm/pm-plugins/drag-and-drop/plugin.js +9 -3
  19. package/dist/esm/pm-plugins/drag-and-drop/utils/getDragBehaviour.js +7 -0
  20. package/dist/esm/pm-plugins/drag-and-drop/utils/monitor.js +10 -4
  21. package/dist/esm/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.js +31 -6
  22. package/dist/esm/ui/TableFloatingControls/RowDropTarget/index.js +31 -6
  23. package/dist/types/pm-plugins/drag-and-drop/commands-with-analytics.d.ts +1 -0
  24. package/dist/types/pm-plugins/drag-and-drop/commands.d.ts +1 -0
  25. package/dist/types/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +3 -0
  26. package/dist/types/types.d.ts +12 -1
  27. package/dist/types-ts4.5/pm-plugins/drag-and-drop/commands-with-analytics.d.ts +1 -0
  28. package/dist/types-ts4.5/pm-plugins/drag-and-drop/commands.d.ts +1 -0
  29. package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +3 -0
  30. package/dist/types-ts4.5/types.d.ts +12 -1
  31. package/package.json +3 -3
  32. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +56 -1
  33. package/src/pm-plugins/drag-and-drop/commands.ts +31 -2
  34. package/src/pm-plugins/drag-and-drop/plugin.ts +21 -7
  35. package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +12 -0
  36. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +17 -3
  37. package/src/types.ts +13 -1
  38. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +39 -5
  39. package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +40 -5
@@ -5,7 +5,7 @@ import { findCellRectClosestToPos, getSelectionRect } from '@atlaskit/editor-tab
5
5
  import { getSelectedColumnIndexes, getSelectedRowIndexes, getSelectedTableInfo } from '../../utils';
6
6
  import { withEditorAnalyticsAPI } from '../../utils/analytics';
7
7
  import { canMove, getTargetIndex } from '../../utils/drag-menu';
8
- import { clearDropTarget, moveSource } from './commands';
8
+ import { clearDropTarget, cloneSource, moveSource } from './commands';
9
9
  export var clearDropTargetWithAnalytics = function clearDropTargetWithAnalytics(editorAnalyticsAPI) {
10
10
  return function (inputMethod, sourceType, sourceIndexes, status, tr) {
11
11
  return withEditorAnalyticsAPI(function (_ref) {
@@ -95,4 +95,39 @@ export var moveSourceWithAnalyticsViaShortcut = function moveSourceWithAnalytics
95
95
  return moveSourceWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.SHORTCUT, sourceType, selectedIndexes, targetIndex)(state, dispatch);
96
96
  };
97
97
  };
98
+ };
99
+ export var cloneSourceWithAnalytics = function cloneSourceWithAnalytics(editorAnalyticsAPI) {
100
+ return function (inputMethod, sourceType, sourceIndexes, targetIndex, targetDirection, tr) {
101
+ return withEditorAnalyticsAPI(function (_ref3) {
102
+ var selection = _ref3.selection;
103
+ var direction = sourceIndexes[0] > targetIndex ? -1 : 1;
104
+ var _getSelectedTableInfo4 = getSelectedTableInfo(selection),
105
+ totalRowCount = _getSelectedTableInfo4.totalRowCount,
106
+ totalColumnCount = _getSelectedTableInfo4.totalColumnCount;
107
+ return {
108
+ action: sourceType === 'table-row' ? TABLE_ACTION.CLONED_ROW : TABLE_ACTION.CLONED_COLUMN,
109
+ actionSubject: ACTION_SUBJECT.TABLE,
110
+ actionSubjectId: null,
111
+ attributes: {
112
+ inputMethod: inputMethod,
113
+ count: sourceIndexes.length,
114
+ // This identifies the total amount of row/cols the move operation covered. The distance covered should be a representaion
115
+ // of the minimum distance. This will account for large selection being moved causing a large distance travelled value.
116
+ distance: Math.min.apply(Math, _toConsumableArray(sourceIndexes.map(function (v) {
117
+ return Math.abs(targetIndex - v);
118
+ }))) * direction,
119
+ // If a drop doesn't actually change anything then we're going to mark the event as cancelled.
120
+ status: sourceIndexes.includes(targetIndex) ? TABLE_STATUS.CANCELLED : TABLE_STATUS.SUCCESS,
121
+ totalRowCount: totalRowCount,
122
+ totalColumnCount: totalColumnCount
123
+ },
124
+ eventType: EVENT_TYPE.TRACK
125
+ };
126
+ })(editorAnalyticsAPI)(function (state, dispatch) {
127
+ if (dispatch) {
128
+ cloneSource(sourceType, sourceIndexes, targetIndex, targetDirection, tr)(state, dispatch);
129
+ }
130
+ return true;
131
+ });
132
+ };
98
133
  };
@@ -1,5 +1,5 @@
1
1
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
2
- import { moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
2
+ import { cloneColumn, cloneRow, moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
3
3
  import { TableDecorations } from '../../types';
4
4
  import { createColumnInsertLine, createRowInsertLine, updateDecorations } from '../../utils';
5
5
  import { DragAndDropActionType } from './actions';
@@ -112,4 +112,20 @@ export var toggleDragMenu = function toggleDragMenu(isDragMenuOpen, direction, i
112
112
  }, function (tr) {
113
113
  return tr.setMeta('addToHistory', false);
114
114
  });
115
+ };
116
+ export var cloneSource = function cloneSource(sourceType, sourceIndexes, targetIndex, targetDirection, tr) {
117
+ return createCommand(function (state) {
118
+ return {
119
+ type: DragAndDropActionType.CLEAR_DROP_TARGET,
120
+ data: {
121
+ decorationSet: DecorationSet.empty
122
+ }
123
+ };
124
+ }, function (originalTr, state) {
125
+ var nextTr = tr || originalTr;
126
+ var clone = sourceType === 'table-row' ? cloneRow : cloneColumn;
127
+ return clone(state, sourceIndexes, targetIndex, targetDirection, {
128
+ selectAfterClone: true
129
+ })(nextTr);
130
+ });
115
131
  };
@@ -12,7 +12,7 @@ import { pluginKey as tablePluginKey } from '../plugin-key';
12
12
  import { insertColgroupFromNode } from '../table-resizing/utils';
13
13
  import { DragAndDropActionType } from './actions';
14
14
  import { clearDropTarget, setDropTarget, toggleDragMenu } from './commands';
15
- import { clearDropTargetWithAnalytics, moveSourceWithAnalytics } from './commands-with-analytics';
15
+ import { clearDropTargetWithAnalytics, cloneSourceWithAnalytics, moveSourceWithAnalytics } from './commands-with-analytics';
16
16
  import { DropTargetType } from './consts';
17
17
  import { createPluginState, getPluginState } from './plugin-factory';
18
18
  import { pluginKey } from './plugin-key';
@@ -121,7 +121,9 @@ var destroyFn = function destroyFn(editorView, editorAnalyticsAPI) {
121
121
  sourceIndexes = data.sourceIndexes,
122
122
  targetIndex = data.targetIndex,
123
123
  targetAdjustedIndex = data.targetAdjustedIndex,
124
- direction = data.direction;
124
+ targetDirection = data.targetDirection,
125
+ direction = data.direction,
126
+ behaviour = data.behaviour;
125
127
 
126
128
  // When we drop on a target we will know the targets row/col index for certain,
127
129
  if (sourceType === 'table-row') {
@@ -138,7 +140,11 @@ var destroyFn = function destroyFn(editorView, editorAnalyticsAPI) {
138
140
  return;
139
141
  }
140
142
  requestAnimationFrame(function () {
141
- moveSourceWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.DRAG_AND_DROP, sourceType, sourceIndexes, targetAdjustedIndex + (direction === -1 ? 0 : -1), tr)(editorView.state, editorView.dispatch);
143
+ if (behaviour === 'clone') {
144
+ cloneSourceWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.DRAG_AND_DROP, sourceType, sourceIndexes, targetIndex, targetDirection, tr)(editorView.state, editorView.dispatch);
145
+ } else {
146
+ moveSourceWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.DRAG_AND_DROP, sourceType, sourceIndexes, targetAdjustedIndex + (direction === 1 ? -1 : 0), tr)(editorView.state, editorView.dispatch);
147
+ }
142
148
 
143
149
  // force a colgroup update here, otherwise dropped columns don't have
144
150
  // the correct width immediately after the drop
@@ -0,0 +1,7 @@
1
+ import { browser } from '@atlaskit/editor-common/utils';
2
+ export var getDragBehaviour = function getDragBehaviour(_ref) {
3
+ var altKey = _ref.altKey,
4
+ ctrlKey = _ref.ctrlKey;
5
+ var isCloneModifierKeyPressed = browser.mac ? altKey : ctrlKey;
6
+ return isCloneModifierKeyPressed ? 'clone' : 'move';
7
+ };
@@ -1,4 +1,6 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
3
+ import { getDragBehaviour } from './getDragBehaviour';
2
4
  export var getDraggableDataFromEvent = function getDraggableDataFromEvent(_ref) {
3
5
  var _extractClosestEdge;
4
6
  var location = _ref.location,
@@ -36,9 +38,11 @@ export var getDraggableDataFromEvent = function getDraggableDataFromEvent(_ref)
36
38
  // the new target index to be 1 index higher.
37
39
  var targetOffset = targetClosestEdge === 'right' || targetClosestEdge === 'bottom' ? 1 : 0;
38
40
 
39
- // since only consecutive rows/cols can be moved we can assume that if the first index is greater then
40
- // the target index, the then the direction of the DnD is decreasing
41
- var direction = sourceIndexes[0] > targetIndex ? -1 : 1;
41
+ // if the min index is greater then the target index, the then the direction of the DnD is decreasing
42
+ // if the target is within the min/max index then we can assume that no direction exists so it will be 0.
43
+ var srcMin = Math.min.apply(Math, _toConsumableArray(sourceIndexes));
44
+ var srcMax = Math.max.apply(Math, _toConsumableArray(sourceIndexes));
45
+ var direction = targetIndex >= srcMin && targetIndex <= srcMax ? 0 : srcMin >= targetIndex ? -1 : 1;
42
46
  return {
43
47
  sourceType: sourceType,
44
48
  sourceLocalId: sourceLocalId,
@@ -48,6 +52,8 @@ export var getDraggableDataFromEvent = function getDraggableDataFromEvent(_ref)
48
52
  targetIndex: targetIndex,
49
53
  targetAdjustedIndex: targetIndex + targetOffset,
50
54
  targetClosestEdge: targetClosestEdge,
51
- direction: direction
55
+ targetDirection: targetClosestEdge === 'top' || targetClosestEdge === 'left' ? 'start' : 'end',
56
+ direction: direction,
57
+ behaviour: getDragBehaviour(location.current.input)
52
58
  };
53
59
  };
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
3
3
  import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
4
+ import { getDragBehaviour } from '../../../pm-plugins/drag-and-drop/utils/getDragBehaviour';
4
5
  export var ColumnDropTarget = function ColumnDropTarget(_ref) {
5
6
  var index = _ref.index,
6
7
  localId = _ref.localId,
@@ -16,32 +17,56 @@ export var ColumnDropTarget = function ColumnDropTarget(_ref) {
16
17
  element: dropTargetRef.current,
17
18
  canDrop: function canDrop(_ref2) {
18
19
  var _data$indexes, _data$indexes2;
19
- var source = _ref2.source;
20
+ var source = _ref2.source,
21
+ input = _ref2.input;
20
22
  var data = source.data;
23
+ var behaviour = getDragBehaviour(input);
24
+
25
+ // A move drop is limited too where it can go, however a clone can drop can go anywhere.
26
+ var isDropValid = behaviour === 'move' ? ((_data$indexes = data.indexes) === null || _data$indexes === void 0 ? void 0 : _data$indexes.indexOf(index)) === -1 : behaviour === 'clone';
21
27
  return (
22
28
  // Only draggables of row type can be dropped on this target
23
29
  data.type === 'table-column' &&
24
30
  // Only draggables which came from the same table can be dropped on this target
25
31
  data.localId === localId &&
26
32
  // Only draggables which DO NOT include this drop targets index can be dropped
27
- !!((_data$indexes = data.indexes) !== null && _data$indexes !== void 0 && _data$indexes.length) && ((_data$indexes2 = data.indexes) === null || _data$indexes2 === void 0 ? void 0 : _data$indexes2.indexOf(index)) === -1
33
+ !!((_data$indexes2 = data.indexes) !== null && _data$indexes2 !== void 0 && _data$indexes2.length) && isDropValid
28
34
  );
29
35
  },
36
+ getDropEffect: function getDropEffect(_ref3) {
37
+ var input = _ref3.input;
38
+ return getDragBehaviour(input) === 'clone' ? 'copy' : 'move';
39
+ },
30
40
  getIsSticky: function getIsSticky() {
31
41
  return true;
32
42
  },
33
- getData: function getData(_ref3) {
34
- var input = _ref3.input,
35
- element = _ref3.element;
43
+ getData: function getData(_ref4) {
44
+ var _srcData$indexes;
45
+ var source = _ref4.source,
46
+ input = _ref4.input,
47
+ element = _ref4.element;
36
48
  var data = {
37
49
  localId: localId,
38
50
  type: 'table-column',
39
51
  targetIndex: index
40
52
  };
53
+ var srcData = source.data;
54
+ var behaviour = getDragBehaviour(input);
55
+
56
+ // During a move op there's no point in allowing edges to be dropped on which result in no change/move to occur.
57
+ var allowedEdges = behaviour === 'move' ? (_srcData$indexes = srcData.indexes) === null || _srcData$indexes === void 0 ? void 0 : _srcData$indexes.reduce(function (acc, v) {
58
+ if (v - index === -1) {
59
+ acc.shift();
60
+ }
61
+ if (v - index === 1) {
62
+ acc.pop();
63
+ }
64
+ return acc;
65
+ }, ['left', 'right']) : ['left', 'right'];
41
66
  return attachClosestEdge(data, {
42
67
  input: input,
43
68
  element: element,
44
- allowedEdges: ['left', 'right']
69
+ allowedEdges: allowedEdges
45
70
  });
46
71
  }
47
72
  });
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
3
3
  import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
4
+ import { getDragBehaviour } from '../../../pm-plugins/drag-and-drop/utils/getDragBehaviour';
4
5
  var RowDropTarget = function RowDropTarget(_ref) {
5
6
  var index = _ref.index,
6
7
  localId = _ref.localId,
@@ -14,32 +15,56 @@ var RowDropTarget = function RowDropTarget(_ref) {
14
15
  element: dropTargetRef.current,
15
16
  canDrop: function canDrop(_ref2) {
16
17
  var _data$indexes, _data$indexes2;
17
- var source = _ref2.source;
18
+ var source = _ref2.source,
19
+ input = _ref2.input;
18
20
  var data = source.data;
21
+ var behaviour = getDragBehaviour(input);
22
+
23
+ // A move drop is limited too where it can go, however a clone can drop can go anywhere.
24
+ var isDropValid = behaviour === 'move' ? ((_data$indexes = data.indexes) === null || _data$indexes === void 0 ? void 0 : _data$indexes.indexOf(index)) === -1 : behaviour === 'clone';
19
25
  return (
20
26
  // Only draggables of row type can be dropped on this target
21
27
  data.type === 'table-row' &&
22
28
  // Only draggables which came from the same table can be dropped on this target
23
29
  data.localId === localId &&
24
30
  // Only draggables which DO NOT include this drop targets index can be dropped
25
- !!((_data$indexes = data.indexes) !== null && _data$indexes !== void 0 && _data$indexes.length) && ((_data$indexes2 = data.indexes) === null || _data$indexes2 === void 0 ? void 0 : _data$indexes2.indexOf(index)) === -1
31
+ !!((_data$indexes2 = data.indexes) !== null && _data$indexes2 !== void 0 && _data$indexes2.length) && isDropValid
26
32
  );
27
33
  },
34
+ getDropEffect: function getDropEffect(_ref3) {
35
+ var input = _ref3.input;
36
+ return getDragBehaviour(input) === 'clone' ? 'copy' : 'move';
37
+ },
28
38
  getIsSticky: function getIsSticky() {
29
39
  return true;
30
40
  },
31
- getData: function getData(_ref3) {
32
- var input = _ref3.input,
33
- element = _ref3.element;
41
+ getData: function getData(_ref4) {
42
+ var _srcData$indexes;
43
+ var source = _ref4.source,
44
+ input = _ref4.input,
45
+ element = _ref4.element;
34
46
  var data = {
35
47
  localId: localId,
36
48
  type: 'table-row',
37
49
  targetIndex: index
38
50
  };
51
+ var srcData = source.data;
52
+ var behaviour = getDragBehaviour(input);
53
+
54
+ // During a move op there's no point in allowing edges to be dropped on which result in no change/move to occur.
55
+ var allowedEdges = behaviour === 'move' ? (_srcData$indexes = srcData.indexes) === null || _srcData$indexes === void 0 ? void 0 : _srcData$indexes.reduce(function (acc, v) {
56
+ if (v - index === -1) {
57
+ acc.shift();
58
+ }
59
+ if (v - index === 1) {
60
+ acc.pop();
61
+ }
62
+ return acc;
63
+ }, ['top', 'bottom']) : ['top', 'bottom'];
39
64
  return attachClosestEdge(data, {
40
65
  input: input,
41
66
  element: element,
42
- allowedEdges: ['top', 'bottom']
67
+ allowedEdges: allowedEdges
43
68
  });
44
69
  }
45
70
  });
@@ -6,3 +6,4 @@ import type { DraggableData, DraggableType } from '../../types';
6
6
  export declare const clearDropTargetWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP, sourceType: DraggableType, sourceIndexes: number[] | undefined, status: TABLE_STATUS.CANCELLED | TABLE_STATUS.INVALID, tr?: Transaction) => Command;
7
7
  export declare const moveSourceWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP | INPUT_METHOD.SHORTCUT, sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, tr?: Transaction) => Command;
8
8
  export declare const moveSourceWithAnalyticsViaShortcut: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (sourceType: DraggableType, direction: DraggableData['direction']) => Command;
9
+ export declare const cloneSourceWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP | INPUT_METHOD.SHORTCUT, sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, targetDirection: 'start' | 'end', tr?: Transaction) => Command;
@@ -11,3 +11,4 @@ export declare const setDropTarget: (type: DropTargetType, index: number, hasMer
11
11
  export declare const clearDropTarget: (tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
12
12
  export declare const moveSource: (sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
13
13
  export declare const toggleDragMenu: (isDragMenuOpen: boolean | undefined, direction?: TableDirection, index?: number, trigger?: TriggerType) => import("@atlaskit/editor-common/types").Command;
14
+ export declare const cloneSource: (sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, targetDirection: 'start' | 'end', tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
@@ -0,0 +1,3 @@
1
+ import type { Input } from '@atlaskit/pragmatic-drag-and-drop/types';
2
+ import type { DraggableBehaviour } from '../../../types';
3
+ export declare const getDragBehaviour: ({ altKey, ctrlKey, }: Input) => DraggableBehaviour;
@@ -435,6 +435,7 @@ export type TableDirection = 'row' | 'column';
435
435
  * Drag and Drop interfaces
436
436
  */
437
437
  export type DraggableType = 'table-row' | 'table-column';
438
+ export type DraggableBehaviour = 'move' | 'clone';
438
439
  export interface DraggableSourceData extends Record<string, unknown> {
439
440
  type: DraggableType;
440
441
  localId: string;
@@ -454,7 +455,17 @@ export interface DraggableData {
454
455
  targetIndex: number;
455
456
  targetAdjustedIndex: number;
456
457
  targetClosestEdge: Edge;
457
- direction: 1 | -1;
458
+ /**
459
+ * The target direction identifies where relative to the target index is the item being dropped. A value of 'start' would
460
+ * mean that the item is being inserted before the index, and 'end would be after.
461
+ */
462
+ targetDirection: 'start' | 'end';
463
+ /**
464
+ * This represents a hollistic movement direction; a value of 1 means the source->target index would shift in a positive direction.
465
+ * A value of 0 indicates that the target index is inside the the source indexes.
466
+ */
467
+ direction: 1 | -1 | 0;
468
+ behaviour: DraggableBehaviour;
458
469
  }
459
470
  export type HandleTypes = 'hover' | 'selected';
460
471
  export interface MessageDescriptor {
@@ -6,3 +6,4 @@ import type { DraggableData, DraggableType } from '../../types';
6
6
  export declare const clearDropTargetWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP, sourceType: DraggableType, sourceIndexes: number[] | undefined, status: TABLE_STATUS.CANCELLED | TABLE_STATUS.INVALID, tr?: Transaction) => Command;
7
7
  export declare const moveSourceWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP | INPUT_METHOD.SHORTCUT, sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, tr?: Transaction) => Command;
8
8
  export declare const moveSourceWithAnalyticsViaShortcut: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (sourceType: DraggableType, direction: DraggableData['direction']) => Command;
9
+ export declare const cloneSourceWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => (inputMethod: INPUT_METHOD.TABLE_CONTEXT_MENU | INPUT_METHOD.DRAG_AND_DROP | INPUT_METHOD.SHORTCUT, sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, targetDirection: 'start' | 'end', tr?: Transaction) => Command;
@@ -11,3 +11,4 @@ export declare const setDropTarget: (type: DropTargetType, index: number, hasMer
11
11
  export declare const clearDropTarget: (tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
12
12
  export declare const moveSource: (sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
13
13
  export declare const toggleDragMenu: (isDragMenuOpen: boolean | undefined, direction?: TableDirection, index?: number, trigger?: TriggerType) => import("@atlaskit/editor-common/types").Command;
14
+ export declare const cloneSource: (sourceType: DraggableType, sourceIndexes: number[], targetIndex: number, targetDirection: 'start' | 'end', tr?: Transaction) => import("@atlaskit/editor-common/types").Command;
@@ -0,0 +1,3 @@
1
+ import type { Input } from '@atlaskit/pragmatic-drag-and-drop/types';
2
+ import type { DraggableBehaviour } from '../../../types';
3
+ export declare const getDragBehaviour: ({ altKey, ctrlKey, }: Input) => DraggableBehaviour;
@@ -435,6 +435,7 @@ export type TableDirection = 'row' | 'column';
435
435
  * Drag and Drop interfaces
436
436
  */
437
437
  export type DraggableType = 'table-row' | 'table-column';
438
+ export type DraggableBehaviour = 'move' | 'clone';
438
439
  export interface DraggableSourceData extends Record<string, unknown> {
439
440
  type: DraggableType;
440
441
  localId: string;
@@ -454,7 +455,17 @@ export interface DraggableData {
454
455
  targetIndex: number;
455
456
  targetAdjustedIndex: number;
456
457
  targetClosestEdge: Edge;
457
- direction: 1 | -1;
458
+ /**
459
+ * The target direction identifies where relative to the target index is the item being dropped. A value of 'start' would
460
+ * mean that the item is being inserted before the index, and 'end would be after.
461
+ */
462
+ targetDirection: 'start' | 'end';
463
+ /**
464
+ * This represents a hollistic movement direction; a value of 1 means the source->target index would shift in a positive direction.
465
+ * A value of 0 indicates that the target index is inside the the source indexes.
466
+ */
467
+ direction: 1 | -1 | 0;
468
+ behaviour: DraggableBehaviour;
458
469
  }
459
470
  export type HandleTypes = 'hover' | 'selected';
460
471
  export interface MessageDescriptor {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "7.5.16",
3
+ "version": "7.6.0",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@atlaskit/adf-schema": "^35.7.0",
32
32
  "@atlaskit/custom-steps": "^0.0.16",
33
- "@atlaskit/editor-common": "^78.19.0",
33
+ "@atlaskit/editor-common": "^78.20.0",
34
34
  "@atlaskit/editor-palette": "1.5.3",
35
35
  "@atlaskit/editor-plugin-analytics": "^1.0.0",
36
36
  "@atlaskit/editor-plugin-content-insertion": "^1.0.0",
@@ -39,7 +39,7 @@
39
39
  "@atlaskit/editor-plugin-width": "^1.0.0",
40
40
  "@atlaskit/editor-prosemirror": "3.0.0",
41
41
  "@atlaskit/editor-shared-styles": "^2.9.0",
42
- "@atlaskit/editor-tables": "^2.5.0",
42
+ "@atlaskit/editor-tables": "^2.6.0",
43
43
  "@atlaskit/icon": "^22.1.0",
44
44
  "@atlaskit/menu": "^2.1.5",
45
45
  "@atlaskit/platform-feature-flags": "^0.2.1",
@@ -26,7 +26,7 @@ import {
26
26
  import { withEditorAnalyticsAPI } from '../../utils/analytics';
27
27
  import { canMove, getTargetIndex } from '../../utils/drag-menu';
28
28
 
29
- import { clearDropTarget, moveSource } from './commands';
29
+ import { clearDropTarget, cloneSource, moveSource } from './commands';
30
30
 
31
31
  export const clearDropTargetWithAnalytics =
32
32
  (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) =>
@@ -157,3 +157,58 @@ export const moveSourceWithAnalyticsViaShortcut =
157
157
  targetIndex,
158
158
  )(state, dispatch);
159
159
  };
160
+
161
+ export const cloneSourceWithAnalytics =
162
+ (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) =>
163
+ (
164
+ inputMethod:
165
+ | INPUT_METHOD.TABLE_CONTEXT_MENU
166
+ | INPUT_METHOD.DRAG_AND_DROP
167
+ | INPUT_METHOD.SHORTCUT,
168
+ sourceType: DraggableType,
169
+ sourceIndexes: number[],
170
+ targetIndex: number,
171
+ targetDirection: 'start' | 'end',
172
+ tr?: Transaction,
173
+ ) => {
174
+ return withEditorAnalyticsAPI(({ selection }: EditorState) => {
175
+ const direction = sourceIndexes[0] > targetIndex ? -1 : 1;
176
+ const { totalRowCount, totalColumnCount } =
177
+ getSelectedTableInfo(selection);
178
+ return {
179
+ action:
180
+ sourceType === 'table-row'
181
+ ? TABLE_ACTION.CLONED_ROW
182
+ : TABLE_ACTION.CLONED_COLUMN,
183
+ actionSubject: ACTION_SUBJECT.TABLE,
184
+ actionSubjectId: null,
185
+ attributes: {
186
+ inputMethod,
187
+ count: sourceIndexes.length,
188
+ // This identifies the total amount of row/cols the move operation covered. The distance covered should be a representaion
189
+ // of the minimum distance. This will account for large selection being moved causing a large distance travelled value.
190
+ distance:
191
+ Math.min(...sourceIndexes.map((v) => Math.abs(targetIndex - v))) *
192
+ direction,
193
+ // If a drop doesn't actually change anything then we're going to mark the event as cancelled.
194
+ status: sourceIndexes.includes(targetIndex)
195
+ ? TABLE_STATUS.CANCELLED
196
+ : TABLE_STATUS.SUCCESS,
197
+ totalRowCount,
198
+ totalColumnCount,
199
+ },
200
+ eventType: EVENT_TYPE.TRACK,
201
+ };
202
+ })(editorAnalyticsAPI)((state, dispatch) => {
203
+ if (dispatch) {
204
+ cloneSource(
205
+ sourceType,
206
+ sourceIndexes,
207
+ targetIndex,
208
+ targetDirection,
209
+ tr,
210
+ )(state, dispatch);
211
+ }
212
+ return true;
213
+ });
214
+ };
@@ -4,7 +4,12 @@ import type {
4
4
  } from '@atlaskit/editor-prosemirror/state';
5
5
  import type { Decoration } from '@atlaskit/editor-prosemirror/view';
6
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
- import { moveColumn, moveRow } from '@atlaskit/editor-tables/utils';
7
+ import {
8
+ cloneColumn,
9
+ cloneRow,
10
+ moveColumn,
11
+ moveRow,
12
+ } from '@atlaskit/editor-tables/utils';
8
13
 
9
14
  import type { DraggableType, TableDirection } from '../../types';
10
15
  import { TableDecorations } from '../../types';
@@ -59,7 +64,6 @@ export const setDropTarget = (
59
64
  TableDecorations.ROW_INSERT_LINE,
60
65
  );
61
66
  }
62
-
63
67
  return {
64
68
  type: DragAndDropActionType.SET_DROP_TARGET,
65
69
  data: {
@@ -175,3 +179,28 @@ export const toggleDragMenu = (
175
179
  return tr.setMeta('addToHistory', false);
176
180
  },
177
181
  );
182
+
183
+ export const cloneSource = (
184
+ sourceType: DraggableType,
185
+ sourceIndexes: number[],
186
+ targetIndex: number,
187
+ targetDirection: 'start' | 'end',
188
+ tr?: Transaction,
189
+ ) =>
190
+ createCommand(
191
+ (state) => {
192
+ return {
193
+ type: DragAndDropActionType.CLEAR_DROP_TARGET,
194
+ data: {
195
+ decorationSet: DecorationSet.empty,
196
+ },
197
+ };
198
+ },
199
+ (originalTr: Transaction, state) => {
200
+ const nextTr = tr || originalTr;
201
+ const clone = sourceType === 'table-row' ? cloneRow : cloneColumn;
202
+ return clone(state, sourceIndexes, targetIndex, targetDirection, {
203
+ selectAfterClone: true,
204
+ })(nextTr);
205
+ },
206
+ );
@@ -26,6 +26,7 @@ import { DragAndDropActionType } from './actions';
26
26
  import { clearDropTarget, setDropTarget, toggleDragMenu } from './commands';
27
27
  import {
28
28
  clearDropTargetWithAnalytics,
29
+ cloneSourceWithAnalytics,
29
30
  moveSourceWithAnalytics,
30
31
  } from './commands-with-analytics';
31
32
  import { DropTargetType } from './consts';
@@ -172,7 +173,9 @@ const destroyFn = (editorView: EditorView, editorAnalyticsAPI: any) => {
172
173
  sourceIndexes,
173
174
  targetIndex,
174
175
  targetAdjustedIndex,
176
+ targetDirection,
175
177
  direction,
178
+ behaviour,
176
179
  } = data;
177
180
 
178
181
  // When we drop on a target we will know the targets row/col index for certain,
@@ -203,13 +206,24 @@ const destroyFn = (editorView: EditorView, editorAnalyticsAPI: any) => {
203
206
  }
204
207
 
205
208
  requestAnimationFrame(() => {
206
- moveSourceWithAnalytics(editorAnalyticsAPI)(
207
- INPUT_METHOD.DRAG_AND_DROP,
208
- sourceType,
209
- sourceIndexes,
210
- targetAdjustedIndex + (direction === -1 ? 0 : -1),
211
- tr,
212
- )(editorView.state, editorView.dispatch);
209
+ if (behaviour === 'clone') {
210
+ cloneSourceWithAnalytics(editorAnalyticsAPI)(
211
+ INPUT_METHOD.DRAG_AND_DROP,
212
+ sourceType,
213
+ sourceIndexes,
214
+ targetIndex,
215
+ targetDirection,
216
+ tr,
217
+ )(editorView.state, editorView.dispatch);
218
+ } else {
219
+ moveSourceWithAnalytics(editorAnalyticsAPI)(
220
+ INPUT_METHOD.DRAG_AND_DROP,
221
+ sourceType,
222
+ sourceIndexes,
223
+ targetAdjustedIndex + (direction === 1 ? -1 : 0),
224
+ tr,
225
+ )(editorView.state, editorView.dispatch);
226
+ }
213
227
 
214
228
  // force a colgroup update here, otherwise dropped columns don't have
215
229
  // the correct width immediately after the drop
@@ -0,0 +1,12 @@
1
+ import { browser } from '@atlaskit/editor-common/utils';
2
+ import type { Input } from '@atlaskit/pragmatic-drag-and-drop/types';
3
+
4
+ import type { DraggableBehaviour } from '../../../types';
5
+
6
+ export const getDragBehaviour = ({
7
+ altKey,
8
+ ctrlKey,
9
+ }: Input): DraggableBehaviour => {
10
+ const isCloneModifierKeyPressed = browser.mac ? altKey : ctrlKey;
11
+ return isCloneModifierKeyPressed ? 'clone' : 'move';
12
+ };
@@ -8,6 +8,8 @@ import type {
8
8
  DraggableTargetData,
9
9
  } from '../../../types';
10
10
 
11
+ import { getDragBehaviour } from './getDragBehaviour';
12
+
11
13
  export const getDraggableDataFromEvent = ({
12
14
  location,
13
15
  source,
@@ -54,9 +56,16 @@ export const getDraggableDataFromEvent = ({
54
56
  const targetOffset =
55
57
  targetClosestEdge === 'right' || targetClosestEdge === 'bottom' ? 1 : 0;
56
58
 
57
- // since only consecutive rows/cols can be moved we can assume that if the first index is greater then
58
- // the target index, the then the direction of the DnD is decreasing
59
- const direction = sourceIndexes[0] > targetIndex ? -1 : 1;
59
+ // if the min index is greater then the target index, the then the direction of the DnD is decreasing
60
+ // if the target is within the min/max index then we can assume that no direction exists so it will be 0.
61
+ const srcMin = Math.min(...sourceIndexes);
62
+ const srcMax = Math.max(...sourceIndexes);
63
+ const direction =
64
+ targetIndex >= srcMin && targetIndex <= srcMax
65
+ ? 0
66
+ : srcMin >= targetIndex
67
+ ? -1
68
+ : 1;
60
69
 
61
70
  return {
62
71
  sourceType,
@@ -67,6 +76,11 @@ export const getDraggableDataFromEvent = ({
67
76
  targetIndex,
68
77
  targetAdjustedIndex: targetIndex + targetOffset,
69
78
  targetClosestEdge,
79
+ targetDirection:
80
+ targetClosestEdge === 'top' || targetClosestEdge === 'left'
81
+ ? 'start'
82
+ : 'end',
70
83
  direction,
84
+ behaviour: getDragBehaviour(location.current.input),
71
85
  };
72
86
  };