@atlaskit/editor-plugin-block-controls 2.26.4 → 2.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/blockControlsPlugin.js +10 -4
  3. package/dist/cjs/editor-commands/move-node.js +38 -8
  4. package/dist/cjs/pm-plugins/decorations-drop-target.js +11 -5
  5. package/dist/cjs/pm-plugins/main.js +3 -1
  6. package/dist/cjs/pm-plugins/utils/getSelection.js +2 -2
  7. package/dist/cjs/pm-plugins/utils/selection.js +8 -5
  8. package/dist/cjs/pm-plugins/utils/validation.js +2 -1
  9. package/dist/cjs/ui/drag-handle.js +1 -1
  10. package/dist/es2019/blockControlsPlugin.js +10 -5
  11. package/dist/es2019/editor-commands/move-node.js +37 -5
  12. package/dist/es2019/pm-plugins/decorations-drop-target.js +12 -5
  13. package/dist/es2019/pm-plugins/main.js +3 -1
  14. package/dist/es2019/pm-plugins/utils/getSelection.js +1 -1
  15. package/dist/es2019/pm-plugins/utils/selection.js +8 -6
  16. package/dist/es2019/pm-plugins/utils/validation.js +2 -1
  17. package/dist/es2019/ui/drag-handle.js +2 -2
  18. package/dist/esm/blockControlsPlugin.js +10 -4
  19. package/dist/esm/editor-commands/move-node.js +39 -9
  20. package/dist/esm/pm-plugins/decorations-drop-target.js +11 -5
  21. package/dist/esm/pm-plugins/main.js +3 -1
  22. package/dist/esm/pm-plugins/utils/getSelection.js +1 -1
  23. package/dist/esm/pm-plugins/utils/selection.js +8 -5
  24. package/dist/esm/pm-plugins/utils/validation.js +2 -1
  25. package/dist/esm/ui/drag-handle.js +2 -2
  26. package/dist/types/blockControlsPluginType.d.ts +1 -1
  27. package/dist/types/pm-plugins/utils/getSelection.d.ts +1 -1
  28. package/dist/types/pm-plugins/utils/selection.d.ts +2 -2
  29. package/dist/types/pm-plugins/utils/validation.d.ts +1 -1
  30. package/dist/types-ts4.5/blockControlsPluginType.d.ts +1 -1
  31. package/dist/types-ts4.5/pm-plugins/utils/getSelection.d.ts +1 -1
  32. package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +2 -2
  33. package/dist/types-ts4.5/pm-plugins/utils/validation.d.ts +1 -1
  34. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 2.27.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#112996](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/112996)
8
+ [`e76ab95452657`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e76ab95452657) -
9
+ ED-26395: Added tests for canMoveSliceToIndex, and fix drop target showing when first node is p,
10
+ second node table, drop into panel
11
+
12
+ ## 2.27.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [#114097](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/114097)
17
+ [`c767c26ecbc7c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c767c26ecbc7c) -
18
+ [ux] [ED-26269] Support moving multiple nodes with shortcuts
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies
23
+
3
24
  ## 2.26.4
4
25
 
5
26
  ### Patch Changes
@@ -67,16 +67,22 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
67
67
  return tr;
68
68
  };
69
69
  },
70
- setMultiSelectPositions: function setMultiSelectPositions() {
70
+ setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
71
71
  return function (_ref5) {
72
72
  var _api$selection;
73
73
  var tr = _ref5.tr;
74
74
  var _tr$selection = tr.selection,
75
75
  userAnchor = _tr$selection.anchor,
76
76
  userHead = _tr$selection.head;
77
- var _expandSelectionBound = (0, _selection.expandSelectionBounds)(tr.selection.$anchor, tr.selection.$head),
78
- expandedAnchor = _expandSelectionBound.$anchor,
79
- expandedHead = _expandSelectionBound.$head;
77
+ var expandedAnchor, expandedHead;
78
+ if (anchor !== undefined && head !== undefined) {
79
+ expandedAnchor = tr.doc.resolve(anchor);
80
+ expandedHead = tr.doc.resolve(head);
81
+ } else {
82
+ var expandedSelection = (0, _selection.expandSelectionBounds)(tr.selection.$anchor, tr.selection.$head);
83
+ expandedAnchor = expandedSelection.$anchor;
84
+ expandedHead = expandedSelection.$head;
85
+ }
80
86
  api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
81
87
  tr: tr
82
88
  });
@@ -95,7 +95,18 @@ var moveNodeViaShortcut = exports.moveNodeViaShortcut = function moveNodeViaShor
95
95
  if (shouldEnableNestedDndA11y) {
96
96
  isParentNodeOfTypeLayout = !!(0, _utils2.findParentNodeOfType)([state.schema.nodes.layoutSection])(state.selection);
97
97
  }
98
- var currentNodePos = getCurrentNodePos(state);
98
+ var isMultiSelectEnabled = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true);
99
+ var expandedAnchor, expandedHead;
100
+ var pluginState = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
101
+ if (pluginState !== null && pluginState !== void 0 && pluginState.multiSelectDnD) {
102
+ expandedAnchor = pluginState.multiSelectDnD.anchor;
103
+ expandedHead = pluginState.multiSelectDnD.head;
104
+ } else {
105
+ var expandedSelection = (0, _selection.expandSelectionBounds)(selection.$anchor, selection.$head);
106
+ expandedAnchor = expandedSelection.$anchor.pos;
107
+ expandedHead = expandedSelection.$head.pos;
108
+ }
109
+ var currentNodePos = isMultiSelectEnabled ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
99
110
  if (currentNodePos > -1) {
100
111
  var _state$doc$nodeAt;
101
112
  var $pos = state.doc.resolve(currentNodePos);
@@ -206,7 +217,7 @@ var moveNodeViaShortcut = exports.moveNodeViaShortcut = function moveNodeViaShor
206
217
  }
207
218
  } else {
208
219
  var _endOfDoc = $pos.end();
209
- var nodeAfterPos = $pos.posAtIndex($pos.index() + 1);
220
+ var nodeAfterPos = isMultiSelectEnabled ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
210
221
  if (nodeAfterPos > _endOfDoc) {
211
222
  return false;
212
223
  }
@@ -228,6 +239,9 @@ var moveNodeViaShortcut = exports.moveNodeViaShortcut = function moveNodeViaShor
228
239
  var _api$core7;
229
240
  api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref4) {
230
241
  var tr = _ref4.tr;
242
+ api === null || api === void 0 || api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
243
+ tr: tr
244
+ });
231
245
  moveNode(api)(currentNodePos, moveToPos, _analytics.INPUT_METHOD.SHORTCUT, formatMessage)({
232
246
  tr: tr
233
247
  });
@@ -235,7 +249,7 @@ var moveNodeViaShortcut = exports.moveNodeViaShortcut = function moveNodeViaShor
235
249
  return tr;
236
250
  });
237
251
  return true;
238
- } else if (nodeType) {
252
+ } else if (nodeType && !isMultiSelectEnabled) {
239
253
  var _api$core8;
240
254
  // If the node is first/last one, only select the node
241
255
  api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 || _api$core8.actions.execute(function (_ref5) {
@@ -245,6 +259,17 @@ var moveNodeViaShortcut = exports.moveNodeViaShortcut = function moveNodeViaShor
245
259
  return tr;
246
260
  });
247
261
  return true;
262
+ } else if (isMultiSelectEnabled) {
263
+ var _api$core9;
264
+ api === null || api === void 0 || (_api$core9 = api.core) === null || _api$core9 === void 0 || _api$core9.actions.execute(function (_ref6) {
265
+ var tr = _ref6.tr;
266
+ api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
267
+ tr: tr
268
+ });
269
+ tr.scrollIntoView();
270
+ return tr;
271
+ });
272
+ return true;
248
273
  }
249
274
  }
250
275
  return false;
@@ -254,8 +279,9 @@ var moveNode = exports.moveNode = function moveNode(api) {
254
279
  return function (start, to) {
255
280
  var inputMethod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _analytics.INPUT_METHOD.DRAG_AND_DROP;
256
281
  var formatMessage = arguments.length > 3 ? arguments[3] : undefined;
257
- return function (_ref6) {
258
- var tr = _ref6.tr;
282
+ return function (_ref7) {
283
+ var _api$blockControls$co;
284
+ var tr = _ref7.tr;
259
285
  if (!api) {
260
286
  return tr;
261
287
  }
@@ -327,10 +353,14 @@ var moveNode = exports.moveNode = function moveNode(api) {
327
353
  mappedTo = tr.mapping.map(to);
328
354
  tr.insert(mappedTo, _nodeCopy); // insert the content at the new position
329
355
  }
330
- tr = inputMethod === _analytics.INPUT_METHOD.DRAG_AND_DROP ? (0, _getSelection.setCursorPositionAtMovedNode)(tr, mappedTo) : (0, _getSelection.selectNode)(tr, mappedTo, handleNode.type.name);
331
- tr.setMeta(_main.key, {
356
+ var sliceSize = sliceTo - sliceFrom;
357
+ tr = inputMethod === _analytics.INPUT_METHOD.DRAG_AND_DROP ? (0, _getSelection.setCursorPositionAtMovedNode)(tr, mappedTo) : isMultiSelect ? (_api$blockControls$co = api === null || api === void 0 ? void 0 : api.blockControls.commands.setMultiSelectPositions(mappedTo, mappedTo + sliceSize)({
358
+ tr: tr
359
+ })) !== null && _api$blockControls$co !== void 0 ? _api$blockControls$co : tr : (0, _getSelection.selectNode)(tr, mappedTo, handleNode.type.name);
360
+ var currMeta = tr.getMeta(_main.key);
361
+ tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
332
362
  nodeMoved: true
333
- });
363
+ }));
334
364
  api === null || api === void 0 || api.core.actions.focus();
335
365
  var $mappedTo = tr.doc.resolve(mappedTo);
336
366
  var expandAncestor = (0, _utils2.findParentNodeOfTypeClosestToPos)($to, [expand, nestedExpand]);
@@ -8,6 +8,7 @@ exports.findDropTargetDecs = exports.dropTargetDecorations = exports.createLayou
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = require("react");
10
10
  var _uuid = _interopRequireDefault(require("uuid"));
11
+ var _selection = require("@atlaskit/editor-common/selection");
11
12
  var _utils = require("@atlaskit/editor-common/utils");
12
13
  var _view = require("@atlaskit/editor-prosemirror/view");
13
14
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
@@ -166,6 +167,15 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
166
167
  prevNodeStack.push(node);
167
168
  };
168
169
  var isAdvancedLayoutsPreRelease2 = (0, _experiments.editorExperiment)('advanced_layouts', true);
170
+
171
+ // For deciding to show drop targets or not when multiple nodes are selected
172
+ var selection = newState.selection;
173
+ var _expandSelectionBound = (0, _selection.expandSelectionBounds)(selection.$anchor, selection.$head),
174
+ expandedAnchor = _expandSelectionBound.$anchor,
175
+ expandedHead = _expandSelectionBound.$head;
176
+ var selectionFrom = Math.min(expandedAnchor.pos, expandedHead.pos);
177
+ var selectionTo = Math.max(expandedAnchor.pos, expandedHead.pos);
178
+ var handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
169
179
  newState.doc.nodesBetween(docFrom, docTo, function (node, pos, parent, index) {
170
180
  var depth = 0;
171
181
  // drop target deco at the end position
@@ -200,10 +210,6 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
200
210
 
201
211
  // When multi select is on, validate all the nodes in the selection instead of just the handle node
202
212
  if (isMultiSelect) {
203
- var selection = newState.selection;
204
- var selectionFrom = selection.$from.pos;
205
- var selectionTo = selection.$to.pos;
206
- var handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom - 1 && activeNodePos <= selectionTo;
207
213
  var selectionSlice = newState.doc.slice(selectionFrom, selectionTo, false);
208
214
  var selectionSliceChildCount = selectionSlice.content.childCount;
209
215
  var canDropSingleNode = true;
@@ -211,7 +217,7 @@ var dropTargetDecorations = exports.dropTargetDecorations = function dropTargetD
211
217
 
212
218
  // when there is only one node in the slice, use the same logic as when multi select is not on
213
219
  if (selectionSliceChildCount > 1 && handleInsideSelection) {
214
- canDropMultipleNodes = (0, _validation.canMoveSliceToIndex)(selectionSlice, selectionFrom, newState.doc, parent, index, $pos);
220
+ canDropMultipleNodes = (0, _validation.canMoveSliceToIndex)(selectionSlice, selectionFrom, parent, index, $pos);
215
221
  } else {
216
222
  canDropSingleNode = !!(activePMNode && (0, _validation.canMoveNodeToIndex)(parent, index, activePMNode, $pos, node));
217
223
  }
@@ -189,7 +189,9 @@ var newApply = exports.newApply = function newApply(api, formatMessage, tr, curr
189
189
  var resizerMeta = tr.getMeta('is-resizer-resizing');
190
190
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
191
191
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
192
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ? undefined : multiSelectDnD;
192
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ||
193
+ // For move node with shortcut, only reset when the selection changes
194
+ tr.selection.anchor !== multiSelectDnD.textAnchor || tr.selection.head !== multiSelectDnD.textHead ? undefined : multiSelectDnD;
193
195
  }
194
196
  var _getTrMetadata = (0, _transactions.getTrMetadata)(tr),
195
197
  from = _getTrMetadata.from,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setCursorPositionAtMovedNode = exports.selectNode = exports.rootTaskListDepth = exports.rootListDepth = exports.isHandleInSelection = exports.getSelection = exports.getInlineNodePos = void 0;
6
+ exports.setCursorPositionAtMovedNode = exports.selectNode = exports.rootTaskListDepth = exports.rootListDepth = exports.isHandleCorrelatedToSelection = exports.getSelection = exports.getInlineNodePos = void 0;
7
7
  var _selection = require("@atlaskit/editor-common/selection");
8
8
  var _state = require("@atlaskit/editor-prosemirror/state");
9
9
  var _utils = require("@atlaskit/editor-prosemirror/utils");
@@ -100,7 +100,7 @@ var setCursorPositionAtMovedNode = exports.setCursorPositionAtMovedNode = functi
100
100
  * @param handlePos
101
101
  * @returns
102
102
  */
103
- var isHandleInSelection = exports.isHandleInSelection = function isHandleInSelection(state, selection, handlePos) {
103
+ var isHandleCorrelatedToSelection = exports.isHandleCorrelatedToSelection = function isHandleCorrelatedToSelection(state, selection, handlePos) {
104
104
  if (selection.empty) {
105
105
  return false;
106
106
  }
@@ -4,10 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getSelectedSlicePosition = exports.getMultiSelectionIfPosInside = void 0;
7
- var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos) {
8
- var _api$blockControls;
9
- var _ref = ((_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
10
- multiSelectDnD = _ref.multiSelectDnD;
7
+ var _main = require("../main");
8
+ var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos, tr) {
9
+ var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
10
+ var pluginState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
11
+ // With move nodes shortcut, we expand selection and move node within one transaction,
12
+ // Hence we also look for `multiSelectDnD` in transaction meta
13
+ var multiSelectDnD = (_pluginState$multiSel = pluginState === null || pluginState === void 0 ? void 0 : pluginState.multiSelectDnD) !== null && _pluginState$multiSel !== void 0 ? _pluginState$multiSel : tr === null || tr === void 0 || (_tr$getMeta = tr.getMeta(_main.key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
11
14
  if (multiSelectDnD && multiSelectDnD.anchor >= 0 && multiSelectDnD.head >= 0) {
12
15
  var multiFrom = Math.min(multiSelectDnD.anchor, multiSelectDnD.head);
13
16
  var multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
@@ -27,7 +30,7 @@ var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = functi
27
30
  */
28
31
  var getSelectedSlicePosition = exports.getSelectedSlicePosition = function getSelectedSlicePosition(handlePos, tr, api) {
29
32
  var _activeNode$nodeSize;
30
- var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, handlePos),
33
+ var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, handlePos, tr),
31
34
  anchor = _getMultiSelectionIfP.anchor,
32
35
  head = _getMultiSelectionIfP.head;
33
36
  var inSelection = anchor !== undefined && head !== undefined;
@@ -121,8 +121,9 @@ function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNodePos,
121
121
  }
122
122
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
123
123
  }
124
- function canMoveSliceToIndex(slice, sliceFromPos, doc, destParent, indexIntoParent, $destNodePos, destNode) {
124
+ function canMoveSliceToIndex(slice, sliceFromPos, destParent, indexIntoParent, $destNodePos, destNode) {
125
125
  var canMoveNodes = true;
126
+ var doc = $destNodePos.doc;
126
127
  var nodesPos = [];
127
128
  for (var i = 0; i < slice.content.childCount; i++) {
128
129
  var node = slice.content.maybeChild(i);
@@ -401,7 +401,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
401
401
  if (!isMultiSelect || typeof start !== 'number' || !selection) {
402
402
  return;
403
403
  }
404
- setDragHandleSelected((0, _getSelection.isHandleInSelection)(view.state, selection, start));
404
+ setDragHandleSelected((0, _getSelection.isHandleCorrelatedToSelection)(view.state, selection, start));
405
405
  }, [start, selection, view.state]);
406
406
  var helpDescriptors = isTopLevelNode && (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_accessibility') ? [{
407
407
  description: formatMessage(_messages.blockControlsMessages.dragToMove)
@@ -56,7 +56,7 @@ export const blockControlsPlugin = ({
56
56
  });
57
57
  return tr;
58
58
  },
59
- setMultiSelectPositions: () => ({
59
+ setMultiSelectPositions: (anchor, head) => ({
60
60
  tr
61
61
  }) => {
62
62
  var _api$selection;
@@ -64,10 +64,15 @@ export const blockControlsPlugin = ({
64
64
  anchor: userAnchor,
65
65
  head: userHead
66
66
  } = tr.selection;
67
- const {
68
- $anchor: expandedAnchor,
69
- $head: expandedHead
70
- } = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
67
+ let expandedAnchor, expandedHead;
68
+ if (anchor !== undefined && head !== undefined) {
69
+ expandedAnchor = tr.doc.resolve(anchor);
70
+ expandedHead = tr.doc.resolve(head);
71
+ } else {
72
+ const expandedSelection = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
73
+ expandedAnchor = expandedSelection.$anchor;
74
+ expandedHead = expandedSelection.$head;
75
+ }
71
76
  api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
72
77
  tr
73
78
  });
@@ -1,7 +1,7 @@
1
1
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import { expandedState } from '@atlaskit/editor-common/expand';
3
3
  import { blockControlsMessages } from '@atlaskit/editor-common/messages';
4
- import { GapCursorSelection } from '@atlaskit/editor-common/selection';
4
+ import { GapCursorSelection, expandSelectionBounds } from '@atlaskit/editor-common/selection';
5
5
  import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
6
6
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
7
7
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
@@ -92,7 +92,18 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
92
92
  if (shouldEnableNestedDndA11y) {
93
93
  isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
94
94
  }
95
- const currentNodePos = getCurrentNodePos(state);
95
+ const isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
96
+ let expandedAnchor, expandedHead;
97
+ const pluginState = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
98
+ if (pluginState !== null && pluginState !== void 0 && pluginState.multiSelectDnD) {
99
+ expandedAnchor = pluginState.multiSelectDnD.anchor;
100
+ expandedHead = pluginState.multiSelectDnD.head;
101
+ } else {
102
+ const expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
103
+ expandedAnchor = expandedSelection.$anchor.pos;
104
+ expandedHead = expandedSelection.$head.pos;
105
+ }
106
+ const currentNodePos = isMultiSelectEnabled ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
96
107
  if (currentNodePos > -1) {
97
108
  var _state$doc$nodeAt;
98
109
  const $pos = state.doc.resolve(currentNodePos);
@@ -205,7 +216,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
205
216
  }
206
217
  } else {
207
218
  const endOfDoc = $pos.end();
208
- const nodeAfterPos = $pos.posAtIndex($pos.index() + 1);
219
+ const nodeAfterPos = isMultiSelectEnabled ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
209
220
  if (nodeAfterPos > endOfDoc) {
210
221
  return false;
211
222
  }
@@ -228,6 +239,9 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
228
239
  api === null || api === void 0 ? void 0 : (_api$core7 = api.core) === null || _api$core7 === void 0 ? void 0 : _api$core7.actions.execute(({
229
240
  tr
230
241
  }) => {
242
+ api === null || api === void 0 ? void 0 : api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
243
+ tr
244
+ });
231
245
  moveNode(api)(currentNodePos, moveToPos, INPUT_METHOD.SHORTCUT, formatMessage)({
232
246
  tr
233
247
  });
@@ -235,7 +249,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
235
249
  return tr;
236
250
  });
237
251
  return true;
238
- } else if (nodeType) {
252
+ } else if (nodeType && !isMultiSelectEnabled) {
239
253
  var _api$core8;
240
254
  // If the node is first/last one, only select the node
241
255
  api === null || api === void 0 ? void 0 : (_api$core8 = api.core) === null || _api$core8 === void 0 ? void 0 : _api$core8.actions.execute(({
@@ -246,6 +260,18 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
246
260
  return tr;
247
261
  });
248
262
  return true;
263
+ } else if (isMultiSelectEnabled) {
264
+ var _api$core9;
265
+ api === null || api === void 0 ? void 0 : (_api$core9 = api.core) === null || _api$core9 === void 0 ? void 0 : _api$core9.actions.execute(({
266
+ tr
267
+ }) => {
268
+ api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
269
+ tr
270
+ });
271
+ tr.scrollIntoView();
272
+ return tr;
273
+ });
274
+ return true;
249
275
  }
250
276
  }
251
277
  return false;
@@ -254,6 +280,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
254
280
  export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_DROP, formatMessage) => ({
255
281
  tr
256
282
  }) => {
283
+ var _api$blockControls$co2;
257
284
  if (!api) {
258
285
  return tr;
259
286
  }
@@ -326,8 +353,13 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
326
353
  mappedTo = tr.mapping.map(to);
327
354
  tr.insert(mappedTo, nodeCopy); // insert the content at the new position
328
355
  }
329
- tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP ? setCursorPositionAtMovedNode(tr, mappedTo) : selectNode(tr, mappedTo, handleNode.type.name);
356
+ const sliceSize = sliceTo - sliceFrom;
357
+ tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP ? setCursorPositionAtMovedNode(tr, mappedTo) : isMultiSelect ? (_api$blockControls$co2 = api === null || api === void 0 ? void 0 : api.blockControls.commands.setMultiSelectPositions(mappedTo, mappedTo + sliceSize)({
358
+ tr
359
+ })) !== null && _api$blockControls$co2 !== void 0 ? _api$blockControls$co2 : tr : selectNode(tr, mappedTo, handleNode.type.name);
360
+ const currMeta = tr.getMeta(key);
330
361
  tr.setMeta(key, {
362
+ ...currMeta,
331
363
  nodeMoved: true
332
364
  });
333
365
  api === null || api === void 0 ? void 0 : api.core.actions.focus();
@@ -1,5 +1,6 @@
1
1
  import { createElement } from 'react';
2
2
  import uuid from 'uuid';
3
+ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
3
4
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
4
5
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
6
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -153,6 +154,16 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
153
154
  prevNodeStack.push(node);
154
155
  };
155
156
  const isAdvancedLayoutsPreRelease2 = editorExperiment('advanced_layouts', true);
157
+
158
+ // For deciding to show drop targets or not when multiple nodes are selected
159
+ const selection = newState.selection;
160
+ const {
161
+ $anchor: expandedAnchor,
162
+ $head: expandedHead
163
+ } = expandSelectionBounds(selection.$anchor, selection.$head);
164
+ const selectionFrom = Math.min(expandedAnchor.pos, expandedHead.pos);
165
+ const selectionTo = Math.max(expandedAnchor.pos, expandedHead.pos);
166
+ const handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
156
167
  newState.doc.nodesBetween(docFrom, docTo, (node, pos, parent, index) => {
157
168
  let depth = 0;
158
169
  // drop target deco at the end position
@@ -187,10 +198,6 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
187
198
 
188
199
  // When multi select is on, validate all the nodes in the selection instead of just the handle node
189
200
  if (isMultiSelect) {
190
- const selection = newState.selection;
191
- const selectionFrom = selection.$from.pos;
192
- const selectionTo = selection.$to.pos;
193
- const handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom - 1 && activeNodePos <= selectionTo;
194
201
  const selectionSlice = newState.doc.slice(selectionFrom, selectionTo, false);
195
202
  const selectionSliceChildCount = selectionSlice.content.childCount;
196
203
  let canDropSingleNode = true;
@@ -198,7 +205,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
198
205
 
199
206
  // when there is only one node in the slice, use the same logic as when multi select is not on
200
207
  if (selectionSliceChildCount > 1 && handleInsideSelection) {
201
- canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, newState.doc, parent, index, $pos);
208
+ canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, parent, index, $pos);
202
209
  } else {
203
210
  canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $pos, node));
204
211
  }
@@ -189,7 +189,9 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
189
189
  const resizerMeta = tr.getMeta('is-resizer-resizing');
190
190
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
191
191
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
192
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ? undefined : multiSelectDnD;
192
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ||
193
+ // For move node with shortcut, only reset when the selection changes
194
+ tr.selection.anchor !== multiSelectDnD.textAnchor || tr.selection.head !== multiSelectDnD.textHead ? undefined : multiSelectDnD;
193
195
  }
194
196
  const {
195
197
  from,
@@ -96,7 +96,7 @@ export const setCursorPositionAtMovedNode = (tr, start) => {
96
96
  * @param handlePos
97
97
  * @returns
98
98
  */
99
- export const isHandleInSelection = (state, selection, handlePos) => {
99
+ export const isHandleCorrelatedToSelection = (state, selection, handlePos) => {
100
100
  if (selection.empty) {
101
101
  return false;
102
102
  }
@@ -1,8 +1,10 @@
1
- export const getMultiSelectionIfPosInside = (api, pos) => {
2
- var _api$blockControls;
3
- const {
4
- multiSelectDnD
5
- } = ((_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
1
+ import { key } from '../main';
2
+ export const getMultiSelectionIfPosInside = (api, pos, tr) => {
3
+ var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
4
+ const pluginState = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
5
+ // With move nodes shortcut, we expand selection and move node within one transaction,
6
+ // Hence we also look for `multiSelectDnD` in transaction meta
7
+ const multiSelectDnD = (_pluginState$multiSel = pluginState === null || pluginState === void 0 ? void 0 : pluginState.multiSelectDnD) !== null && _pluginState$multiSel !== void 0 ? _pluginState$multiSel : tr === null || tr === void 0 ? void 0 : (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
6
8
  if (multiSelectDnD && multiSelectDnD.anchor >= 0 && multiSelectDnD.head >= 0) {
7
9
  const multiFrom = Math.min(multiSelectDnD.anchor, multiSelectDnD.head);
8
10
  const multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
@@ -25,7 +27,7 @@ export const getSelectedSlicePosition = (handlePos, tr, api) => {
25
27
  const {
26
28
  anchor,
27
29
  head
28
- } = getMultiSelectionIfPosInside(api, handlePos);
30
+ } = getMultiSelectionIfPosInside(api, handlePos, tr);
29
31
  const inSelection = anchor !== undefined && head !== undefined;
30
32
  const from = inSelection ? Math.min(anchor, head) : handlePos;
31
33
  const activeNode = tr.doc.nodeAt(handlePos);
@@ -114,8 +114,9 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
114
114
  }
115
115
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
116
116
  }
117
- export function canMoveSliceToIndex(slice, sliceFromPos, doc, destParent, indexIntoParent, $destNodePos, destNode) {
117
+ export function canMoveSliceToIndex(slice, sliceFromPos, destParent, indexIntoParent, $destNodePos, destNode) {
118
118
  let canMoveNodes = true;
119
+ const doc = $destNodePos.doc;
119
120
  const nodesPos = [];
120
121
  for (let i = 0; i < slice.content.childCount; i++) {
121
122
  const node = slice.content.maybeChild(i);
@@ -24,7 +24,7 @@ import { key } from '../pm-plugins/main';
24
24
  import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
25
25
  import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
26
26
  import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
27
- import { isHandleInSelection, selectNode } from '../pm-plugins/utils/getSelection';
27
+ import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
28
28
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, topPositionAdjustment } from './consts';
29
29
  import { dragPreview } from './drag-preview';
30
30
  const iconWrapperStyles = xcss({
@@ -383,7 +383,7 @@ export const DragHandle = ({
383
383
  if (!isMultiSelect || typeof start !== 'number' || !selection) {
384
384
  return;
385
385
  }
386
- setDragHandleSelected(isHandleInSelection(view.state, selection, start));
386
+ setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
387
387
  }, [start, selection, view.state]);
388
388
  let helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
389
389
  description: formatMessage(blockControlsMessages.dragToMove)
@@ -60,16 +60,22 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
60
60
  return tr;
61
61
  };
62
62
  },
63
- setMultiSelectPositions: function setMultiSelectPositions() {
63
+ setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
64
64
  return function (_ref5) {
65
65
  var _api$selection;
66
66
  var tr = _ref5.tr;
67
67
  var _tr$selection = tr.selection,
68
68
  userAnchor = _tr$selection.anchor,
69
69
  userHead = _tr$selection.head;
70
- var _expandSelectionBound = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head),
71
- expandedAnchor = _expandSelectionBound.$anchor,
72
- expandedHead = _expandSelectionBound.$head;
70
+ var expandedAnchor, expandedHead;
71
+ if (anchor !== undefined && head !== undefined) {
72
+ expandedAnchor = tr.doc.resolve(anchor);
73
+ expandedHead = tr.doc.resolve(head);
74
+ } else {
75
+ var expandedSelection = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
76
+ expandedAnchor = expandedSelection.$anchor;
77
+ expandedHead = expandedSelection.$head;
78
+ }
73
79
  api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
74
80
  tr: tr
75
81
  });
@@ -4,7 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
5
  import { expandedState } from '@atlaskit/editor-common/expand';
6
6
  import { blockControlsMessages } from '@atlaskit/editor-common/messages';
7
- import { GapCursorSelection } from '@atlaskit/editor-common/selection';
7
+ import { GapCursorSelection, expandSelectionBounds } from '@atlaskit/editor-common/selection';
8
8
  import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
9
9
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
10
10
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
@@ -89,7 +89,18 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
89
89
  if (shouldEnableNestedDndA11y) {
90
90
  isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
91
91
  }
92
- var currentNodePos = getCurrentNodePos(state);
92
+ var isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
93
+ var expandedAnchor, expandedHead;
94
+ var pluginState = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
95
+ if (pluginState !== null && pluginState !== void 0 && pluginState.multiSelectDnD) {
96
+ expandedAnchor = pluginState.multiSelectDnD.anchor;
97
+ expandedHead = pluginState.multiSelectDnD.head;
98
+ } else {
99
+ var expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
100
+ expandedAnchor = expandedSelection.$anchor.pos;
101
+ expandedHead = expandedSelection.$head.pos;
102
+ }
103
+ var currentNodePos = isMultiSelectEnabled ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
93
104
  if (currentNodePos > -1) {
94
105
  var _state$doc$nodeAt;
95
106
  var $pos = state.doc.resolve(currentNodePos);
@@ -200,7 +211,7 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
200
211
  }
201
212
  } else {
202
213
  var _endOfDoc = $pos.end();
203
- var nodeAfterPos = $pos.posAtIndex($pos.index() + 1);
214
+ var nodeAfterPos = isMultiSelectEnabled ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
204
215
  if (nodeAfterPos > _endOfDoc) {
205
216
  return false;
206
217
  }
@@ -222,6 +233,9 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
222
233
  var _api$core7;
223
234
  api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref4) {
224
235
  var tr = _ref4.tr;
236
+ api === null || api === void 0 || api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
237
+ tr: tr
238
+ });
225
239
  moveNode(api)(currentNodePos, moveToPos, INPUT_METHOD.SHORTCUT, formatMessage)({
226
240
  tr: tr
227
241
  });
@@ -229,7 +243,7 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
229
243
  return tr;
230
244
  });
231
245
  return true;
232
- } else if (nodeType) {
246
+ } else if (nodeType && !isMultiSelectEnabled) {
233
247
  var _api$core8;
234
248
  // If the node is first/last one, only select the node
235
249
  api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 || _api$core8.actions.execute(function (_ref5) {
@@ -239,6 +253,17 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
239
253
  return tr;
240
254
  });
241
255
  return true;
256
+ } else if (isMultiSelectEnabled) {
257
+ var _api$core9;
258
+ api === null || api === void 0 || (_api$core9 = api.core) === null || _api$core9 === void 0 || _api$core9.actions.execute(function (_ref6) {
259
+ var tr = _ref6.tr;
260
+ api.blockControls.commands.setMultiSelectPositions(expandedAnchor, expandedHead)({
261
+ tr: tr
262
+ });
263
+ tr.scrollIntoView();
264
+ return tr;
265
+ });
266
+ return true;
242
267
  }
243
268
  }
244
269
  return false;
@@ -248,8 +273,9 @@ export var moveNode = function moveNode(api) {
248
273
  return function (start, to) {
249
274
  var inputMethod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : INPUT_METHOD.DRAG_AND_DROP;
250
275
  var formatMessage = arguments.length > 3 ? arguments[3] : undefined;
251
- return function (_ref6) {
252
- var tr = _ref6.tr;
276
+ return function (_ref7) {
277
+ var _api$blockControls$co;
278
+ var tr = _ref7.tr;
253
279
  if (!api) {
254
280
  return tr;
255
281
  }
@@ -321,10 +347,14 @@ export var moveNode = function moveNode(api) {
321
347
  mappedTo = tr.mapping.map(to);
322
348
  tr.insert(mappedTo, _nodeCopy); // insert the content at the new position
323
349
  }
324
- tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP ? setCursorPositionAtMovedNode(tr, mappedTo) : selectNode(tr, mappedTo, handleNode.type.name);
325
- tr.setMeta(key, {
350
+ var sliceSize = sliceTo - sliceFrom;
351
+ tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP ? setCursorPositionAtMovedNode(tr, mappedTo) : isMultiSelect ? (_api$blockControls$co = api === null || api === void 0 ? void 0 : api.blockControls.commands.setMultiSelectPositions(mappedTo, mappedTo + sliceSize)({
352
+ tr: tr
353
+ })) !== null && _api$blockControls$co !== void 0 ? _api$blockControls$co : tr : selectNode(tr, mappedTo, handleNode.type.name);
354
+ var currMeta = tr.getMeta(key);
355
+ tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
326
356
  nodeMoved: true
327
- });
357
+ }));
328
358
  api === null || api === void 0 || api.core.actions.focus();
329
359
  var $mappedTo = tr.doc.resolve(mappedTo);
330
360
  var expandAncestor = findParentNodeOfTypeClosestToPos($to, [expand, nestedExpand]);
@@ -3,6 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import { createElement } from 'react';
5
5
  import uuid from 'uuid';
6
+ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
6
7
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
7
8
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
8
9
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -159,6 +160,15 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
159
160
  prevNodeStack.push(node);
160
161
  };
161
162
  var isAdvancedLayoutsPreRelease2 = editorExperiment('advanced_layouts', true);
163
+
164
+ // For deciding to show drop targets or not when multiple nodes are selected
165
+ var selection = newState.selection;
166
+ var _expandSelectionBound = expandSelectionBounds(selection.$anchor, selection.$head),
167
+ expandedAnchor = _expandSelectionBound.$anchor,
168
+ expandedHead = _expandSelectionBound.$head;
169
+ var selectionFrom = Math.min(expandedAnchor.pos, expandedHead.pos);
170
+ var selectionTo = Math.max(expandedAnchor.pos, expandedHead.pos);
171
+ var handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
162
172
  newState.doc.nodesBetween(docFrom, docTo, function (node, pos, parent, index) {
163
173
  var depth = 0;
164
174
  // drop target deco at the end position
@@ -193,10 +203,6 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
193
203
 
194
204
  // When multi select is on, validate all the nodes in the selection instead of just the handle node
195
205
  if (isMultiSelect) {
196
- var selection = newState.selection;
197
- var selectionFrom = selection.$from.pos;
198
- var selectionTo = selection.$to.pos;
199
- var handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom - 1 && activeNodePos <= selectionTo;
200
206
  var selectionSlice = newState.doc.slice(selectionFrom, selectionTo, false);
201
207
  var selectionSliceChildCount = selectionSlice.content.childCount;
202
208
  var canDropSingleNode = true;
@@ -204,7 +210,7 @@ export var dropTargetDecorations = function dropTargetDecorations(newState, api,
204
210
 
205
211
  // when there is only one node in the slice, use the same logic as when multi select is not on
206
212
  if (selectionSliceChildCount > 1 && handleInsideSelection) {
207
- canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, newState.doc, parent, index, $pos);
213
+ canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, parent, index, $pos);
208
214
  } else {
209
215
  canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $pos, node));
210
216
  }
@@ -182,7 +182,9 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
182
182
  var resizerMeta = tr.getMeta('is-resizer-resizing');
183
183
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
184
184
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
185
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ? undefined : multiSelectDnD;
185
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ||
186
+ // For move node with shortcut, only reset when the selection changes
187
+ tr.selection.anchor !== multiSelectDnD.textAnchor || tr.selection.head !== multiSelectDnD.textHead ? undefined : multiSelectDnD;
186
188
  }
187
189
  var _getTrMetadata = getTrMetadata(tr),
188
190
  from = _getTrMetadata.from,
@@ -94,7 +94,7 @@ export var setCursorPositionAtMovedNode = function setCursorPositionAtMovedNode(
94
94
  * @param handlePos
95
95
  * @returns
96
96
  */
97
- export var isHandleInSelection = function isHandleInSelection(state, selection, handlePos) {
97
+ export var isHandleCorrelatedToSelection = function isHandleCorrelatedToSelection(state, selection, handlePos) {
98
98
  if (selection.empty) {
99
99
  return false;
100
100
  }
@@ -1,7 +1,10 @@
1
- export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos) {
2
- var _api$blockControls;
3
- var _ref = ((_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
4
- multiSelectDnD = _ref.multiSelectDnD;
1
+ import { key } from '../main';
2
+ export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos, tr) {
3
+ var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
4
+ var pluginState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
5
+ // With move nodes shortcut, we expand selection and move node within one transaction,
6
+ // Hence we also look for `multiSelectDnD` in transaction meta
7
+ var multiSelectDnD = (_pluginState$multiSel = pluginState === null || pluginState === void 0 ? void 0 : pluginState.multiSelectDnD) !== null && _pluginState$multiSel !== void 0 ? _pluginState$multiSel : tr === null || tr === void 0 || (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
5
8
  if (multiSelectDnD && multiSelectDnD.anchor >= 0 && multiSelectDnD.head >= 0) {
6
9
  var multiFrom = Math.min(multiSelectDnD.anchor, multiSelectDnD.head);
7
10
  var multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
@@ -21,7 +24,7 @@ export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(
21
24
  */
22
25
  export var getSelectedSlicePosition = function getSelectedSlicePosition(handlePos, tr, api) {
23
26
  var _activeNode$nodeSize;
24
- var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, handlePos),
27
+ var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, handlePos, tr),
25
28
  anchor = _getMultiSelectionIfP.anchor,
26
29
  head = _getMultiSelectionIfP.head;
27
30
  var inSelection = anchor !== undefined && head !== undefined;
@@ -112,8 +112,9 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
112
112
  }
113
113
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
114
114
  }
115
- export function canMoveSliceToIndex(slice, sliceFromPos, doc, destParent, indexIntoParent, $destNodePos, destNode) {
115
+ export function canMoveSliceToIndex(slice, sliceFromPos, destParent, indexIntoParent, $destNodePos, destNode) {
116
116
  var canMoveNodes = true;
117
+ var doc = $destNodePos.doc;
117
118
  var nodesPos = [];
118
119
  for (var i = 0; i < slice.content.childCount; i++) {
119
120
  var node = slice.content.maybeChild(i);
@@ -29,7 +29,7 @@ import { key } from '../pm-plugins/main';
29
29
  import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
30
30
  import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
31
31
  import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
32
- import { isHandleInSelection, selectNode } from '../pm-plugins/utils/getSelection';
32
+ import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
33
33
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, topPositionAdjustment } from './consts';
34
34
  import { dragPreview } from './drag-preview';
35
35
  var iconWrapperStyles = xcss({
@@ -396,7 +396,7 @@ export var DragHandle = function DragHandle(_ref) {
396
396
  if (!isMultiSelect || typeof start !== 'number' || !selection) {
397
397
  return;
398
398
  }
399
- setDragHandleSelected(isHandleInSelection(view.state, selection, start));
399
+ setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
400
400
  }, [start, selection, view.state]);
401
401
  var helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
402
402
  description: formatMessage(blockControlsMessages.dragToMove)
@@ -87,7 +87,7 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
87
87
  moveNode: MoveNode;
88
88
  showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions) => EditorCommand;
89
89
  setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
90
- setMultiSelectPositions: () => EditorCommand;
90
+ setMultiSelectPositions: (anchor?: number, head?: number) => EditorCommand;
91
91
  };
92
92
  }>;
93
93
  export type BlockControlsMeta = {
@@ -14,6 +14,6 @@ export declare const setCursorPositionAtMovedNode: (tr: Transaction, start: numb
14
14
  * @param handlePos
15
15
  * @returns
16
16
  */
17
- export declare const isHandleInSelection: (state: EditorState, selection: Selection, handlePos: number) => boolean;
17
+ export declare const isHandleCorrelatedToSelection: (state: EditorState, selection: Selection, handlePos: number) => boolean;
18
18
  export declare const rootListDepth: (itemPos: ResolvedPos) => number | undefined;
19
19
  export declare const rootTaskListDepth: (taskListPos: ResolvedPos) => number | undefined;
@@ -1,7 +1,7 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ import { type Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { BlockControlsPlugin } from '../../blockControlsPluginType';
4
- export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number) => {
4
+ export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number, tr?: Transaction) => {
5
5
  anchor?: number;
6
6
  head?: number;
7
7
  };
@@ -17,4 +17,4 @@ export declare const transformExpandToNestedExpand: (expandNode: PMNode) => PMNo
17
17
  export declare const transformSliceExpandToNestedExpand: (slice: Slice) => Slice | null;
18
18
  export declare const memoizedTransformExpandToNestedExpand: import("memoize-one").MemoizedFn<(node: PMNode) => PMNode | null>;
19
19
  export declare function canMoveNodeToIndex(destParent: PMNode, indexIntoParent: number, srcNode: PMNode, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
20
- export declare function canMoveSliceToIndex(slice: Slice, sliceFromPos: number, doc: PMNode, destParent: PMNode, indexIntoParent: number, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
20
+ export declare function canMoveSliceToIndex(slice: Slice, sliceFromPos: number, destParent: PMNode, indexIntoParent: number, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
@@ -87,7 +87,7 @@ export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
87
87
  moveNode: MoveNode;
88
88
  showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions) => EditorCommand;
89
89
  setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
90
- setMultiSelectPositions: () => EditorCommand;
90
+ setMultiSelectPositions: (anchor?: number, head?: number) => EditorCommand;
91
91
  };
92
92
  }>;
93
93
  export type BlockControlsMeta = {
@@ -14,6 +14,6 @@ export declare const setCursorPositionAtMovedNode: (tr: Transaction, start: numb
14
14
  * @param handlePos
15
15
  * @returns
16
16
  */
17
- export declare const isHandleInSelection: (state: EditorState, selection: Selection, handlePos: number) => boolean;
17
+ export declare const isHandleCorrelatedToSelection: (state: EditorState, selection: Selection, handlePos: number) => boolean;
18
18
  export declare const rootListDepth: (itemPos: ResolvedPos) => number | undefined;
19
19
  export declare const rootTaskListDepth: (taskListPos: ResolvedPos) => number | undefined;
@@ -1,7 +1,7 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ import { type Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { BlockControlsPlugin } from '../../blockControlsPluginType';
4
- export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number) => {
4
+ export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number, tr?: Transaction) => {
5
5
  anchor?: number;
6
6
  head?: number;
7
7
  };
@@ -17,4 +17,4 @@ export declare const transformExpandToNestedExpand: (expandNode: PMNode) => PMNo
17
17
  export declare const transformSliceExpandToNestedExpand: (slice: Slice) => Slice | null;
18
18
  export declare const memoizedTransformExpandToNestedExpand: import("memoize-one").MemoizedFn<(node: PMNode) => PMNode | null>;
19
19
  export declare function canMoveNodeToIndex(destParent: PMNode, indexIntoParent: number, srcNode: PMNode, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
20
- export declare function canMoveSliceToIndex(slice: Slice, sliceFromPos: number, doc: PMNode, destParent: PMNode, indexIntoParent: number, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
20
+ export declare function canMoveSliceToIndex(slice: Slice, sliceFromPos: number, destParent: PMNode, indexIntoParent: number, $destNodePos: ResolvedPos, destNode?: PMNode): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "2.26.4",
3
+ "version": "2.27.1",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@atlaskit/adf-schema": "^47.2.1",
34
- "@atlaskit/editor-common": "^99.15.0",
34
+ "@atlaskit/editor-common": "^99.16.0",
35
35
  "@atlaskit/editor-plugin-accessibility-utils": "^1.4.0",
36
36
  "@atlaskit/editor-plugin-analytics": "^1.12.0",
37
37
  "@atlaskit/editor-plugin-editor-disabled": "^1.5.0",