@atlaskit/editor-plugin-block-controls 2.23.1 → 2.25.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 (31) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/blockControlsPlugin.js +44 -5
  3. package/dist/cjs/editor-commands/move-node.js +13 -10
  4. package/dist/cjs/editor-commands/move-to-layout.js +12 -13
  5. package/dist/cjs/pm-plugins/main.js +44 -14
  6. package/dist/cjs/pm-plugins/utils/getSelection.js +58 -3
  7. package/dist/cjs/pm-plugins/utils/selection.js +22 -0
  8. package/dist/cjs/ui/drag-handle.js +26 -21
  9. package/dist/es2019/blockControlsPlugin.js +42 -2
  10. package/dist/es2019/editor-commands/move-node.js +14 -10
  11. package/dist/es2019/editor-commands/move-to-layout.js +13 -13
  12. package/dist/es2019/pm-plugins/main.js +40 -9
  13. package/dist/es2019/pm-plugins/utils/getSelection.js +55 -0
  14. package/dist/es2019/pm-plugins/utils/selection.js +17 -0
  15. package/dist/es2019/ui/drag-handle.js +27 -22
  16. package/dist/esm/blockControlsPlugin.js +44 -5
  17. package/dist/esm/editor-commands/move-node.js +13 -10
  18. package/dist/esm/editor-commands/move-to-layout.js +12 -13
  19. package/dist/esm/pm-plugins/main.js +44 -14
  20. package/dist/esm/pm-plugins/utils/getSelection.js +55 -0
  21. package/dist/esm/pm-plugins/utils/selection.js +16 -0
  22. package/dist/esm/ui/drag-handle.js +27 -22
  23. package/dist/types/blockControlsPluginType.d.ts +14 -1
  24. package/dist/types/pm-plugins/main.d.ts +2 -0
  25. package/dist/types/pm-plugins/utils/getSelection.d.ts +12 -1
  26. package/dist/types/pm-plugins/utils/selection.d.ts +6 -0
  27. package/dist/types-ts4.5/blockControlsPluginType.d.ts +14 -1
  28. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -0
  29. package/dist/types-ts4.5/pm-plugins/utils/getSelection.d.ts +12 -1
  30. package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +6 -0
  31. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 2.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#107342](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/107342)
8
+ [`ec6b838ab9935`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/ec6b838ab9935) -
9
+ [ux] Set drag handle selection state based on Editor selection
10
+
11
+ ## 2.24.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#111465](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/111465)
16
+ [`c0cbae02ded12`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c0cbae02ded12) -
17
+ [ux] Expand existing multi-node selection when dragging handle
18
+
19
+ ### Patch Changes
20
+
21
+ - [#109402](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/109402)
22
+ [`a8c334f52bb60`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/a8c334f52bb60) -
23
+ Fix multi-select bug when dragging onto the handle replaces text
24
+ - Updated dependencies
25
+
3
26
  ## 2.23.1
4
27
 
5
28
  ### Patch Changes
@@ -5,12 +5,17 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.blockControlsPlugin = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
9
  var _react = _interopRequireDefault(require("react"));
10
+ var _selection = require("@atlaskit/editor-common/selection");
11
+ var _state = require("@atlaskit/editor-prosemirror/state");
9
12
  var _moveNode = require("./editor-commands/move-node");
10
13
  var _moveToLayout = require("./editor-commands/move-to-layout");
11
14
  var _main = require("./pm-plugins/main");
12
15
  var _dragHandleMenu = require("./ui/drag-handle-menu");
13
16
  var _globalStyles = require("./ui/global-styles");
17
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
+ 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) { (0, _defineProperty2.default)(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; }
14
19
  var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPlugin(_ref) {
15
20
  var api = _ref.api;
16
21
  return {
@@ -31,14 +36,15 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
31
36
  showDragHandleAt: function showDragHandleAt(pos, anchorName, nodeType, handleOptions) {
32
37
  return function (_ref3) {
33
38
  var tr = _ref3.tr;
34
- tr.setMeta(_main.key, {
39
+ var currMeta = tr.getMeta(_main.key);
40
+ tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
35
41
  activeNode: {
36
42
  pos: pos,
37
43
  anchorName: anchorName,
38
44
  nodeType: nodeType,
39
45
  handleOptions: handleOptions
40
46
  }
41
- });
47
+ }));
42
48
  return tr;
43
49
  };
44
50
  },
@@ -49,20 +55,52 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
49
55
  if (pos === undefined) {
50
56
  return tr;
51
57
  }
52
- tr.setMeta(_main.key, {
58
+ var currMeta = tr.getMeta(_main.key);
59
+ tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
53
60
  isDragging: true,
54
61
  activeNode: {
55
62
  pos: pos,
56
63
  anchorName: anchorName,
57
64
  nodeType: nodeType
58
65
  }
66
+ }));
67
+ return tr;
68
+ };
69
+ },
70
+ setMultiSelectPositions: function setMultiSelectPositions() {
71
+ return function (_ref5) {
72
+ var _api$selection;
73
+ var tr = _ref5.tr;
74
+ var _tr$selection = tr.selection,
75
+ userAnchor = _tr$selection.anchor,
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;
80
+ api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
81
+ tr: tr
59
82
  });
83
+ // this is to normalise the selection's boundaries to inline positions, preventing it from collapsing
84
+ var expandedNormalisedSel = _state.TextSelection.between(expandedAnchor, expandedHead);
85
+ tr.setSelection(expandedNormalisedSel);
86
+ var multiSelectDnD = {
87
+ anchor: expandedAnchor.pos,
88
+ head: expandedHead.pos,
89
+ textAnchor: expandedNormalisedSel.anchor,
90
+ textHead: expandedNormalisedSel.head,
91
+ userAnchor: userAnchor,
92
+ userHead: userHead
93
+ };
94
+ var currMeta = tr.getMeta(_main.key);
95
+ tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
96
+ multiSelectDnD: multiSelectDnD
97
+ }));
60
98
  return tr;
61
99
  };
62
100
  }
63
101
  },
64
102
  getSharedState: function getSharedState(editorState) {
65
- var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4;
103
+ var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4, _key$getState$multiSe, _key$getState5;
66
104
  if (!editorState) {
67
105
  return undefined;
68
106
  }
@@ -70,7 +108,8 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
70
108
  isMenuOpen: (_key$getState$isMenuO = (_key$getState = _main.key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.isMenuOpen) !== null && _key$getState$isMenuO !== void 0 ? _key$getState$isMenuO : false,
71
109
  activeNode: (_key$getState$activeN = (_key$getState2 = _main.key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
72
110
  isDragging: (_key$getState$isDragg = (_key$getState3 = _main.key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
73
- isPMDragging: (_key$getState$isPMDra = (_key$getState4 = _main.key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false
111
+ isPMDragging: (_key$getState$isPMDra = (_key$getState4 = _main.key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
112
+ multiSelectDnD: (_key$getState$multiSe = (_key$getState5 = _main.key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined
74
113
  };
75
114
  },
76
115
  contentComponent: function contentComponent() {
@@ -24,6 +24,7 @@ var _fireAnalytics = require("../pm-plugins/utils/fire-analytics");
24
24
  var _getNestedNodePosition = require("../pm-plugins/utils/getNestedNodePosition");
25
25
  var _getSelection = require("../pm-plugins/utils/getSelection");
26
26
  var _removeFromSource = require("../pm-plugins/utils/remove-from-source");
27
+ var _selection2 = require("../pm-plugins/utils/selection");
27
28
  var _validation = require("../pm-plugins/utils/validation");
28
29
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
29
30
  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) { (0, _defineProperty2.default)(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; }
@@ -220,26 +221,28 @@ var moveNode = exports.moveNode = function moveNode(api) {
220
221
  var formatMessage = arguments.length > 3 ? arguments[3] : undefined;
221
222
  return function (_ref6) {
222
223
  var tr = _ref6.tr;
223
- var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
224
- exposure: true
225
- });
226
- var selection = tr.selection;
227
- var selectionFrom = selection.$from.pos;
228
- var selectionTo = selection.$to.pos;
224
+ if (!api) {
225
+ return tr;
226
+ }
229
227
  var handleNode = tr.doc.nodeAt(start);
230
228
  if (!handleNode) {
231
229
  return tr;
232
230
  }
233
231
  var sliceFrom = start;
234
232
  var sliceTo;
233
+ var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
234
+ exposure: true
235
+ });
235
236
  if (isMultiSelect) {
236
237
  var _handleNode$nodeSize;
237
- // //If the handle position sits within the Editor selection, we will move all nodes that sit in that selection
238
- var useSelection = sliceFrom >= selectionFrom - 1 && sliceFrom <= selectionTo;
239
- sliceFrom = useSelection ? selectionFrom : start;
238
+ var _getMultiSelectionIfP = (0, _selection2.getMultiSelectionIfPosInside)(api, start),
239
+ anchor = _getMultiSelectionIfP.anchor,
240
+ head = _getMultiSelectionIfP.head;
241
+ var inSelection = anchor !== undefined && head !== undefined;
242
+ sliceFrom = inSelection ? Math.min(anchor, head) : start;
240
243
  var handleSize = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
241
244
  var handleEnd = sliceFrom + handleSize;
242
- sliceTo = useSelection ? selectionTo : handleEnd;
245
+ sliceTo = inSelection ? Math.max(anchor, head) : handleEnd;
243
246
  } else {
244
247
  var _handleNode$nodeSize2;
245
248
  var size = (_handleNode$nodeSize2 = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize2 !== void 0 ? _handleNode$nodeSize2 : 1;
@@ -14,6 +14,7 @@ var _checkFragment = require("../pm-plugins/utils/check-fragment");
14
14
  var _consts = require("../pm-plugins/utils/consts");
15
15
  var _fireAnalytics = require("../pm-plugins/utils/fire-analytics");
16
16
  var _removeFromSource = require("../pm-plugins/utils/remove-from-source");
17
+ var _selection = require("../pm-plugins/utils/selection");
17
18
  var _updateColumnWidths = require("../pm-plugins/utils/update-column-widths");
18
19
  var _validation = require("../pm-plugins/utils/validation");
19
20
  var _consts2 = require("../ui/consts");
@@ -161,7 +162,7 @@ var insertToDestination = function insertToDestination(tr, to, sourceContent, to
161
162
  * Check if the node at `from` can be moved to node at `to` to create/expand a layout.
162
163
  * Returns the source and destination nodes and positions if it's a valid move, otherwise, undefined
163
164
  */
164
- var canMoveToLayout = function canMoveToLayout(from, to, tr) {
165
+ var canMoveToLayout = function canMoveToLayout(api, from, to, tr) {
165
166
  if (from === to) {
166
167
  return;
167
168
  }
@@ -193,17 +194,12 @@ var canMoveToLayout = function canMoveToLayout(from, to, tr) {
193
194
  var sourceFrom = from;
194
195
  var sourceTo = from + sourceContent.nodeSize;
195
196
  if (isMultiSelect) {
196
- var _tr$selection$$from$n;
197
- // Selection often starts from the content of the node (e.g. to show text selection properly),
198
- // so we need to trace back to the start of the node instead
199
- var contentStartPos = tr.selection.$from.nodeAfter && ((_tr$selection$$from$n = tr.selection.$from.nodeAfter) === null || _tr$selection$$from$n === void 0 ? void 0 : _tr$selection$$from$n.type.name) !== 'text' ? tr.selection.$from.pos : tr.selection.$from.before();
200
-
201
- // If the handle position sits within the Editor selection, we will move all nodes that sit in that selection
202
- // handle position is the same as `from` position
203
- var useSelection = from >= contentStartPos && from <= tr.selection.to;
204
- if (useSelection) {
205
- sourceFrom = contentStartPos;
206
- sourceTo = tr.selection.to;
197
+ var _getMultiSelectionIfP = (0, _selection.getMultiSelectionIfPosInside)(api, from),
198
+ anchor = _getMultiSelectionIfP.anchor,
199
+ head = _getMultiSelectionIfP.head;
200
+ if (anchor && head) {
201
+ sourceFrom = Math.min(anchor, head);
202
+ sourceTo = Math.max(anchor, head);
207
203
  sourceContent = tr.doc.slice(sourceFrom, sourceTo).content;
208
204
 
209
205
  // TODO: this might become expensive for large content, consider removing it if check has been done beforehand
@@ -291,7 +287,10 @@ var moveToLayout = exports.moveToLayout = function moveToLayout(api) {
291
287
  return function (from, to, options) {
292
288
  return function (_ref7) {
293
289
  var tr = _ref7.tr;
294
- var canMove = canMoveToLayout(from, to, tr);
290
+ if (!api) {
291
+ return tr;
292
+ }
293
+ var canMove = canMoveToLayout(api, from, to, tr);
295
294
  if (!canMove) {
296
295
  return tr;
297
296
  }
@@ -78,8 +78,24 @@ var destroyFn = function destroyFn(api, editorView) {
78
78
  }
79
79
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
80
80
  var tr = _ref3.tr;
81
- var _ref4 = source.data,
82
- start = _ref4.start;
81
+ if ((0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true)) {
82
+ var _api$blockControls, _api$selection;
83
+ var _ref4 = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
84
+ multiSelectDnD = _ref4.multiSelectDnD;
85
+ // Restore the users initial Editor selection when the drop completes
86
+ if (multiSelectDnD) {
87
+ // If the TextSelection between the drag start and end has changed, the document has changed, and we should not reapply the last selection
88
+ var expandedSelectionUnchanged = multiSelectDnD.textAnchor === tr.selection.anchor && multiSelectDnD.textHead === tr.selection.head;
89
+ if (expandedSelectionUnchanged) {
90
+ tr.setSelection(_state.TextSelection.create(tr.doc, multiSelectDnD.userAnchor, multiSelectDnD.userHead));
91
+ }
92
+ }
93
+ api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || _api$selection.commands.clearManualSelection()({
94
+ tr: tr
95
+ });
96
+ }
97
+ var _ref5 = source.data,
98
+ start = _ref5.start;
83
99
  // if no drop targets are rendered, assume that drop is invalid
84
100
  if (location.current.dropTargets.length === 0) {
85
101
  var _api$analytics2;
@@ -115,13 +131,15 @@ var initialState = {
115
131
  editorWidthRight: 0,
116
132
  isResizerResizing: false,
117
133
  isDocSizeLimitEnabled: null,
118
- isPMDragging: false
134
+ isPMDragging: false,
135
+ multiSelectDnD: undefined
119
136
  };
120
137
  var newApply = exports.newApply = function newApply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
121
- var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
138
+ var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$multiSelectDnD;
122
139
  var activeNode = currentState.activeNode,
123
140
  decorations = currentState.decorations,
124
- isResizerResizing = currentState.isResizerResizing;
141
+ isResizerResizing = currentState.isResizerResizing,
142
+ multiSelectDnD = currentState.multiSelectDnD;
125
143
  var editorHeight = currentState.editorHeight,
126
144
  editorWidthLeft = currentState.editorWidthLeft,
127
145
  editorWidthRight = currentState.editorWidthRight,
@@ -130,7 +148,7 @@ var newApply = exports.newApply = function newApply(api, formatMessage, tr, curr
130
148
  isPMDragging = currentState.isPMDragging;
131
149
  var isActiveNodeDeleted = false;
132
150
 
133
- // Remap existing decorations and activeNode when steps exist
151
+ // When steps exist, remap existing decorations, activeNode and multi select positions
134
152
  if (tr.docChanged) {
135
153
  decorations = decorations.map(tr.mapping, tr.doc);
136
154
  if (activeNode) {
@@ -142,10 +160,17 @@ var newApply = exports.newApply = function newApply(api, formatMessage, tr, curr
142
160
  nodeType: activeNode.nodeType
143
161
  };
144
162
  }
163
+ if (multiSelectDnD && flags.isMultiSelectEnabled) {
164
+ multiSelectDnD.anchor = tr.mapping.map(multiSelectDnD.anchor);
165
+ multiSelectDnD.head = tr.mapping.map(multiSelectDnD.head);
166
+ }
145
167
  }
146
168
  var meta = tr.getMeta(key);
147
169
  var resizerMeta = tr.getMeta('is-resizer-resizing');
148
170
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
171
+ if (multiSelectDnD && flags.isMultiSelectEnabled) {
172
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ? undefined : multiSelectDnD;
173
+ }
149
174
  var _getTrMetadata = (0, _transactions.getTrMetadata)(tr),
150
175
  from = _getTrMetadata.from,
151
176
  to = _getTrMetadata.to,
@@ -245,7 +270,8 @@ var newApply = exports.newApply = function newApply(api, formatMessage, tr, curr
245
270
  editorWidthRight: (_meta$editorWidthRigh = meta === null || meta === void 0 ? void 0 : meta.editorWidthRight) !== null && _meta$editorWidthRigh !== void 0 ? _meta$editorWidthRigh : editorWidthRight,
246
271
  isResizerResizing: isResizerResizing,
247
272
  isDocSizeLimitEnabled: initialState.isDocSizeLimitEnabled,
248
- isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging
273
+ isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging,
274
+ multiSelectDnD: (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD
249
275
  };
250
276
  };
251
277
  var oldApply = exports.oldApply = function oldApply(api, formatMessage, tr, currentState, oldState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
@@ -289,8 +315,8 @@ var oldApply = exports.oldApply = function oldApply(api, formatMessage, tr, curr
289
315
  }
290
316
  var decsLength = isNestedEnabled ? decorations.find(undefined, undefined, function (spec) {
291
317
  return spec.type === 'node-decoration';
292
- }).length : decorations.find().filter(function (_ref5) {
293
- var spec = _ref5.spec;
318
+ }).length : decorations.find().filter(function (_ref6) {
319
+ var spec = _ref6.spec;
294
320
  return spec.type !== 'drag-handle';
295
321
  }).length;
296
322
  var isDecsMissing = false;
@@ -328,7 +354,7 @@ var oldApply = exports.oldApply = function oldApply(api, formatMessage, tr, curr
328
354
  var newNodeDecs = (0, _decorationsAnchor.nodeDecorations)(newState);
329
355
  decorations = decorations.add(newState.doc, (0, _toConsumableArray2.default)(newNodeDecs));
330
356
  if (activeNode && !(meta !== null && meta !== void 0 && meta.nodeMoved) && !isDecsMissing) {
331
- var _meta$activeNode$pos, _meta$activeNode3, _ref6, _meta$activeNode$anch, _meta$activeNode4, _decAtPos$spec, _ref7, _meta$activeNode$node, _meta$activeNode5, _decAtPos$spec2, _meta$activeNode6;
357
+ var _meta$activeNode$pos, _meta$activeNode3, _ref7, _meta$activeNode$anch, _meta$activeNode4, _decAtPos$spec, _ref8, _meta$activeNode$node, _meta$activeNode5, _decAtPos$spec2, _meta$activeNode6;
332
358
  var mappedPosisiton = tr.mapping.map(activeNode.pos);
333
359
  var prevMappedPos = oldState.tr.mapping.map(activeNode.pos);
334
360
 
@@ -347,7 +373,7 @@ var oldApply = exports.oldApply = function oldApply(api, formatMessage, tr, curr
347
373
  var decAtPos = newNodeDecs.find(function (dec) {
348
374
  return dec.from === mappedPosisiton;
349
375
  });
350
- var draghandleDec = (0, _decorationsDragHandle.dragHandleDecoration)(api, formatMessage, (_meta$activeNode$pos = meta === null || meta === void 0 || (_meta$activeNode3 = meta.activeNode) === null || _meta$activeNode3 === void 0 ? void 0 : _meta$activeNode3.pos) !== null && _meta$activeNode$pos !== void 0 ? _meta$activeNode$pos : mappedPosisiton, (_ref6 = (_meta$activeNode$anch = meta === null || meta === void 0 || (_meta$activeNode4 = meta.activeNode) === null || _meta$activeNode4 === void 0 ? void 0 : _meta$activeNode4.anchorName) !== null && _meta$activeNode$anch !== void 0 ? _meta$activeNode$anch : decAtPos === null || decAtPos === void 0 || (_decAtPos$spec = decAtPos.spec) === null || _decAtPos$spec === void 0 ? void 0 : _decAtPos$spec.anchorName) !== null && _ref6 !== void 0 ? _ref6 : activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName, (_ref7 = (_meta$activeNode$node = meta === null || meta === void 0 || (_meta$activeNode5 = meta.activeNode) === null || _meta$activeNode5 === void 0 ? void 0 : _meta$activeNode5.nodeType) !== null && _meta$activeNode$node !== void 0 ? _meta$activeNode$node : decAtPos === null || decAtPos === void 0 || (_decAtPos$spec2 = decAtPos.spec) === null || _decAtPos$spec2 === void 0 ? void 0 : _decAtPos$spec2.nodeType) !== null && _ref7 !== void 0 ? _ref7 : activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType, nodeViewPortalProviderAPI, meta === null || meta === void 0 || (_meta$activeNode6 = meta.activeNode) === null || _meta$activeNode6 === void 0 ? void 0 : _meta$activeNode6.handleOptions);
376
+ var draghandleDec = (0, _decorationsDragHandle.dragHandleDecoration)(api, formatMessage, (_meta$activeNode$pos = meta === null || meta === void 0 || (_meta$activeNode3 = meta.activeNode) === null || _meta$activeNode3 === void 0 ? void 0 : _meta$activeNode3.pos) !== null && _meta$activeNode$pos !== void 0 ? _meta$activeNode$pos : mappedPosisiton, (_ref7 = (_meta$activeNode$anch = meta === null || meta === void 0 || (_meta$activeNode4 = meta.activeNode) === null || _meta$activeNode4 === void 0 ? void 0 : _meta$activeNode4.anchorName) !== null && _meta$activeNode$anch !== void 0 ? _meta$activeNode$anch : decAtPos === null || decAtPos === void 0 || (_decAtPos$spec = decAtPos.spec) === null || _decAtPos$spec === void 0 ? void 0 : _decAtPos$spec.anchorName) !== null && _ref7 !== void 0 ? _ref7 : activeNode === null || activeNode === void 0 ? void 0 : activeNode.anchorName, (_ref8 = (_meta$activeNode$node = meta === null || meta === void 0 || (_meta$activeNode5 = meta.activeNode) === null || _meta$activeNode5 === void 0 ? void 0 : _meta$activeNode5.nodeType) !== null && _meta$activeNode$node !== void 0 ? _meta$activeNode$node : decAtPos === null || decAtPos === void 0 || (_decAtPos$spec2 = decAtPos.spec) === null || _decAtPos$spec2 === void 0 ? void 0 : _decAtPos$spec2.nodeType) !== null && _ref8 !== void 0 ? _ref8 : activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType, nodeViewPortalProviderAPI, meta === null || meta === void 0 || (_meta$activeNode6 = meta.activeNode) === null || _meta$activeNode6 === void 0 ? void 0 : _meta$activeNode6.handleOptions);
351
377
  decorations = decorations.add(newState.doc, [draghandleDec]);
352
378
  }
353
379
  }
@@ -419,8 +445,10 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
419
445
  var isAdvancedLayoutEnabled = (0, _experiments.editorExperiment)('advanced_layouts', true, {
420
446
  exposure: true
421
447
  });
448
+ var isMultiSelectEnabled = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true);
422
449
  var flags = {
423
- isNestedEnabled: isNestedEnabled
450
+ isNestedEnabled: isNestedEnabled,
451
+ isMultiSelectEnabled: isMultiSelectEnabled
424
452
  };
425
453
  var anchorRectCache;
426
454
  if (!(0, _anchorUtils.isAnchorSupported)()) {
@@ -483,8 +511,10 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
483
511
  var domPos = Math.max(view.posAtDOM(nodeElement, 0) - 1, 0);
484
512
  var nodeTarget = state.doc.nodeAt(domPos);
485
513
  var isSameNode = !!(nodeTarget && draggable !== null && draggable !== void 0 && draggable.eq(nodeTarget));
486
- if (isSameNode) {
487
- // Prevent the default drop behavior if the position is within the activeNode
514
+ var isInSelection = domPos >= state.selection.$from.pos && domPos < state.selection.$to.pos;
515
+
516
+ // Prevent the default drop behavior if the position is within the activeNode or Editor selection
517
+ if (isSameNode || isInSelection && isMultiSelectEnabled) {
488
518
  event.preventDefault();
489
519
  return true;
490
520
  }
@@ -3,10 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setCursorPositionAtMovedNode = exports.selectNode = exports.getSelection = exports.getInlineNodePos = void 0;
6
+ exports.setCursorPositionAtMovedNode = exports.selectNode = exports.rootTaskListDepth = exports.rootListDepth = exports.isHandleInSelection = 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
- var _utils = require("@atlaskit/editor-tables/utils");
9
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
10
+ var _utils2 = require("@atlaskit/editor-tables/utils");
10
11
  var getInlineNodePos = exports.getInlineNodePos = function getInlineNodePos(tr, start, nodeSize) {
11
12
  var $startPos = tr.doc.resolve(start);
12
13
  // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
@@ -68,7 +69,7 @@ var getSelection = exports.getSelection = function getSelection(tr, start) {
68
69
  var selectNode = exports.selectNode = function selectNode(tr, start, nodeType) {
69
70
  // For table, we need to do cell selection instead of node selection
70
71
  if (nodeType === 'table') {
71
- tr = (0, _utils.selectTableClosestToPos)(tr, tr.doc.resolve(start + 1));
72
+ tr = (0, _utils2.selectTableClosestToPos)(tr, tr.doc.resolve(start + 1));
72
73
  } else {
73
74
  tr.setSelection(getSelection(tr, start));
74
75
  }
@@ -90,4 +91,58 @@ var setCursorPositionAtMovedNode = exports.setCursorPositionAtMovedNode = functi
90
91
  }
91
92
  tr.setSelection(selection);
92
93
  return tr;
94
+ };
95
+
96
+ /**
97
+ * Checks if handle position is with the selection or corresponds to a (partially) selected node
98
+ * @param state
99
+ * @param selection
100
+ * @param handlePos
101
+ * @returns
102
+ */
103
+ var isHandleInSelection = exports.isHandleInSelection = function isHandleInSelection(state, selection, handlePos) {
104
+ if (selection.empty) {
105
+ return false;
106
+ }
107
+ var $selectionFrom = selection.$from;
108
+ var selectionFrom = $selectionFrom.pos;
109
+ var nodeStart = $selectionFrom.depth ? $selectionFrom.before() : selectionFrom;
110
+ var $resolvedNodePos = state.doc.resolve(nodeStart);
111
+ if (['tableRow', 'tableCell', 'tableHeader'].includes($resolvedNodePos.node().type.name)) {
112
+ var parentNodeFindRes = (0, _utils.findParentNodeOfType)(state.schema.nodes['table'])(selection);
113
+ var tablePos = parentNodeFindRes === null || parentNodeFindRes === void 0 ? void 0 : parentNodeFindRes.pos;
114
+ nodeStart = typeof tablePos === 'undefined' ? nodeStart : tablePos;
115
+ } else if (['listItem'].includes($resolvedNodePos.node().type.name)) {
116
+ nodeStart = $resolvedNodePos.before(rootListDepth($resolvedNodePos));
117
+ } else if (['taskList'].includes($resolvedNodePos.node().type.name)) {
118
+ var listdepth = rootTaskListDepth($resolvedNodePos);
119
+ nodeStart = $resolvedNodePos.before(listdepth);
120
+ } else if (['blockquote'].includes($resolvedNodePos.node().type.name)) {
121
+ nodeStart = $resolvedNodePos.before();
122
+ }
123
+ return Boolean(handlePos < selection.$to.pos && handlePos >= nodeStart);
124
+ };
125
+ var rootListDepth = exports.rootListDepth = function rootListDepth(itemPos) {
126
+ var depth;
127
+ for (var i = itemPos.depth; i > 1; i -= 2) {
128
+ var node = itemPos.node(i);
129
+ if (node.type.name === 'listItem') {
130
+ depth = i - 1;
131
+ } else {
132
+ break;
133
+ }
134
+ }
135
+ return depth;
136
+ };
137
+ var rootTaskListDepth = exports.rootTaskListDepth = function rootTaskListDepth(taskListPos) {
138
+ var depth;
139
+ for (var i = taskListPos.depth; i > 0; i--) {
140
+ var node = taskListPos.node(i);
141
+ if (node.type.name === 'taskList' || node.type.name === 'taskItem') {
142
+ depth = i;
143
+ } else {
144
+ break;
145
+ }
146
+ }
147
+ return depth;
93
148
  };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getMultiSelectionIfPosInside = void 0;
7
+ var getMultiSelectionIfPosInside = exports.getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos) {
8
+ var _api$blockControls;
9
+ var _ref = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
10
+ multiSelectDnD = _ref.multiSelectDnD;
11
+ if (multiSelectDnD && multiSelectDnD.anchor >= 0 && multiSelectDnD.head >= 0) {
12
+ var multiFrom = Math.min(multiSelectDnD.anchor, multiSelectDnD.head);
13
+ var multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
14
+
15
+ // We subtract one as the handle position is before the node
16
+ return pos >= multiFrom - 1 && pos <= multiTo ? {
17
+ anchor: multiSelectDnD.anchor,
18
+ head: multiSelectDnD.head
19
+ } : {};
20
+ }
21
+ return {};
22
+ };
@@ -15,6 +15,7 @@ var _browser = require("@atlaskit/editor-common/browser");
15
15
  var _hooks = require("@atlaskit/editor-common/hooks");
16
16
  var _keymaps = require("@atlaskit/editor-common/keymaps");
17
17
  var _messages = require("@atlaskit/editor-common/messages");
18
+ var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
18
19
  var _state = require("@atlaskit/editor-prosemirror/state");
19
20
  var _dragHandler = _interopRequireDefault(require("@atlaskit/icon/glyph/drag-handler"));
20
21
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
@@ -128,6 +129,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
128
129
  setDragHandleSelected = _useState4[1];
129
130
  var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['featureFlags']),
130
131
  featureFlagsState = _useSharedPluginState.featureFlagsState;
132
+ var selection = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'selection.selection');
131
133
  var isLayoutColumn = nodeType === 'layoutColumn';
132
134
  (0, _react.useEffect)(function () {
133
135
  // blockCard/datasource width is rendered correctly after this decoraton does. We need to observe for changes.
@@ -256,39 +258,27 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
256
258
  return;
257
259
  }
258
260
  api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref6) {
259
- var _api$blockControls, _api$analytics3;
261
+ var _api$blockControls2, _api$analytics3;
260
262
  var tr = _ref6.tr;
261
263
  var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
262
264
  exposure: true
263
265
  });
264
- var selectionStart = start;
265
266
  if (isMultiSelect) {
266
- var selection = tr.selection;
267
- var selectionFrom = selection.$from.pos;
268
- var selectionTo = selection.$to.pos;
269
- var $selectionFrom = tr.doc.resolve(selectionFrom);
270
- var $selectionTo = tr.doc.resolve(selectionTo);
271
- selectionStart = $selectionFrom.start();
272
- var selectionEnd = $selectionTo.end();
273
267
  var handlePos = getPos();
274
268
  if (typeof handlePos !== 'number') {
275
269
  return tr;
276
270
  }
277
- var posBeforeNode = $selectionFrom.pos ? $selectionFrom.start() - 1 : $selectionFrom.pos;
278
- var shouldExpandSelection = handlePos >= posBeforeNode && handlePos <= selectionEnd;
279
- if (shouldExpandSelection) {
280
- //TODO: What happens if not a text selection?
281
- var newSelection = _state.TextSelection.create(tr.doc, selectionStart, selectionEnd);
282
- tr.setSelection(newSelection);
283
- } else {
284
- var _$selectionFrom = tr.doc.resolve(handlePos + 1);
285
- (0, _getSelection.selectNode)(tr, handlePos, _$selectionFrom.node().type.name);
271
+ if (!tr.selection.empty && handlePos >= tr.selection.$from.start() - 1 && handlePos <= tr.selection.to) {
272
+ var _api$blockControls;
273
+ api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.setMultiSelectPositions()({
274
+ tr: tr
275
+ });
286
276
  }
287
277
  }
288
- api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.setNodeDragged(getPos, anchorName, nodeType)({
278
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.setNodeDragged(getPos, anchorName, nodeType)({
289
279
  tr: tr
290
280
  });
291
- var resolvedMovingNode = tr.doc.resolve(selectionStart);
281
+ var resolvedMovingNode = tr.doc.resolve(start);
292
282
  var maybeNode = resolvedMovingNode.nodeAfter;
293
283
  tr.setMeta('scrollIntoView', false);
294
284
  api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.attachAnalyticsEvent({
@@ -390,6 +380,15 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
390
380
  };
391
381
  }
392
382
  }, [buttonRef, handleOptions === null || handleOptions === void 0 ? void 0 : handleOptions.isFocused, view]);
383
+ (0, _react.useEffect)(function () {
384
+ var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
385
+ exposure: true
386
+ });
387
+ if (!isMultiSelect || typeof start !== 'number' || !selection) {
388
+ return;
389
+ }
390
+ setDragHandleSelected((0, _getSelection.isHandleInSelection)(view.state, selection, start));
391
+ }, [start, selection, view.state]);
393
392
  var helpDescriptors = [{
394
393
  description: formatMessage(_messages.blockControlsMessages.dragToMove)
395
394
  }, {
@@ -436,6 +435,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
436
435
  var message = helpDescriptors.map(function (descriptor) {
437
436
  return descriptor.keymap ? [descriptor.description, (0, _keymaps.getAriaKeyshortcuts)(descriptor.keymap)] : [descriptor.description];
438
437
  }).join('. ');
438
+ var handleOnDrop = function handleOnDrop(event) {
439
+ (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true) && event.stopPropagation();
440
+ };
439
441
  var renderButton = function renderButton() {
440
442
  return (
441
443
  // eslint-disable-next-line @atlaskit/design-system/no-html-button
@@ -451,7 +453,10 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
451
453
  style: positionStyles,
452
454
  onClick: handleOnClick,
453
455
  onMouseDown: handleMouseDown,
454
- onKeyDown: handleKeyDown,
456
+ onKeyDown: handleKeyDown
457
+ // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
458
+ ,
459
+ onDrop: handleOnDrop,
455
460
  "data-testid": "block-ctrl-drag-handle"
456
461
  }, (0, _react2.jsx)(_primitives.Box, {
457
462
  as: "span",