@atlaskit/editor-plugin-block-controls 2.26.4 → 2.27.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 2.27.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#114097](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/114097)
8
+ [`c767c26ecbc7c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c767c26ecbc7c) -
9
+ [ux] [ED-26269] Support moving multiple nodes with shortcuts
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 2.26.4
4
16
 
5
17
  ### 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]);
@@ -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,
@@ -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;
@@ -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();
@@ -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,
@@ -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);
@@ -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]);
@@ -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,
@@ -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;
@@ -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 = {
@@ -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
  };
@@ -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 = {
@@ -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
  };
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.0",
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",