@atlaskit/editor-plugin-block-controls 2.26.0 → 2.26.2

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 (52) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/editor-commands/move-node.js +79 -43
  3. package/dist/cjs/editor-commands/move-to-layout.js +23 -11
  4. package/dist/cjs/editor-commands/show-drag-handle.js +89 -3
  5. package/dist/cjs/pm-plugins/decorations-anchor.js +5 -10
  6. package/dist/cjs/pm-plugins/decorations-common.js +8 -10
  7. package/dist/cjs/pm-plugins/decorations-drag-handle.js +4 -19
  8. package/dist/cjs/pm-plugins/decorations-drop-target.js +8 -25
  9. package/dist/cjs/pm-plugins/main.js +28 -8
  10. package/dist/cjs/pm-plugins/utils/analytics.js +66 -0
  11. package/dist/cjs/pm-plugins/utils/selection.js +22 -2
  12. package/dist/cjs/ui/drag-handle.js +38 -10
  13. package/dist/es2019/editor-commands/move-node.js +76 -40
  14. package/dist/es2019/editor-commands/move-to-layout.js +23 -11
  15. package/dist/es2019/editor-commands/show-drag-handle.js +88 -3
  16. package/dist/es2019/pm-plugins/decorations-anchor.js +6 -11
  17. package/dist/es2019/pm-plugins/decorations-common.js +7 -9
  18. package/dist/es2019/pm-plugins/decorations-drag-handle.js +10 -25
  19. package/dist/es2019/pm-plugins/decorations-drop-target.js +11 -30
  20. package/dist/es2019/pm-plugins/main.js +24 -6
  21. package/dist/es2019/pm-plugins/utils/{fire-analytics.js → analytics.js} +31 -3
  22. package/dist/es2019/pm-plugins/utils/selection.js +22 -1
  23. package/dist/es2019/ui/drag-handle.js +34 -4
  24. package/dist/esm/editor-commands/move-node.js +80 -44
  25. package/dist/esm/editor-commands/move-to-layout.js +23 -11
  26. package/dist/esm/editor-commands/show-drag-handle.js +88 -2
  27. package/dist/esm/pm-plugins/decorations-anchor.js +6 -11
  28. package/dist/esm/pm-plugins/decorations-common.js +7 -9
  29. package/dist/esm/pm-plugins/decorations-drag-handle.js +4 -19
  30. package/dist/esm/pm-plugins/decorations-drop-target.js +8 -25
  31. package/dist/esm/pm-plugins/main.js +27 -7
  32. package/dist/esm/pm-plugins/utils/{fire-analytics.js → analytics.js} +32 -3
  33. package/dist/esm/pm-plugins/utils/selection.js +21 -1
  34. package/dist/esm/ui/drag-handle.js +37 -5
  35. package/dist/types/blockControlsPluginType.d.ts +1 -0
  36. package/dist/types/editor-commands/move-to-layout.d.ts +1 -0
  37. package/dist/types/editor-commands/show-drag-handle.d.ts +1 -1
  38. package/dist/types/pm-plugins/decorations-common.d.ts +1 -0
  39. package/dist/types/pm-plugins/main.d.ts +1 -0
  40. package/dist/types/pm-plugins/utils/analytics.d.ts +12 -0
  41. package/dist/types/pm-plugins/utils/selection.d.ts +9 -0
  42. package/dist/types-ts4.5/blockControlsPluginType.d.ts +1 -0
  43. package/dist/types-ts4.5/editor-commands/move-to-layout.d.ts +1 -0
  44. package/dist/types-ts4.5/editor-commands/show-drag-handle.d.ts +1 -1
  45. package/dist/types-ts4.5/pm-plugins/decorations-common.d.ts +1 -0
  46. package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -0
  47. package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +12 -0
  48. package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +9 -0
  49. package/package.json +10 -7
  50. package/dist/cjs/pm-plugins/utils/fire-analytics.js +0 -36
  51. package/dist/types/pm-plugins/utils/fire-analytics.d.ts +0 -5
  52. package/dist/types-ts4.5/pm-plugins/utils/fire-analytics.d.ts +0 -5
@@ -21,6 +21,7 @@ import { Box, xcss } from '@atlaskit/primitives';
21
21
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
22
22
  import Tooltip from '@atlaskit/tooltip';
23
23
  import { key } from '../pm-plugins/main';
24
+ import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
24
25
  import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
25
26
  import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
26
27
  import { isHandleInSelection, selectNode } from '../pm-plugins/utils/getSelection';
@@ -246,7 +247,11 @@ export const DragHandle = ({
246
247
  const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
247
248
  exposure: true
248
249
  });
250
+ let nodeTypes, hasSelectedMultipleNodes;
251
+ const resolvedMovingNode = tr.doc.resolve(start);
252
+ const maybeNode = resolvedMovingNode.nodeAfter;
249
253
  if (isMultiSelect) {
254
+ var _tr$getMeta;
250
255
  const handlePos = getPos();
251
256
  if (typeof handlePos !== 'number') {
252
257
  return tr;
@@ -257,12 +262,19 @@ export const DragHandle = ({
257
262
  tr
258
263
  });
259
264
  }
265
+ const multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
266
+ if (multiSelectDnD) {
267
+ const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
268
+ nodeTypes = attributes.nodeTypes;
269
+ hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
270
+ } else {
271
+ nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
272
+ hasSelectedMultipleNodes = false;
273
+ }
260
274
  }
261
275
  api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.setNodeDragged(getPos, anchorName, nodeType)({
262
276
  tr
263
277
  });
264
- const resolvedMovingNode = tr.doc.resolve(start);
265
- const maybeNode = resolvedMovingNode.nodeAfter;
266
278
  tr.setMeta('scrollIntoView', false);
267
279
  api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.attachAnalyticsEvent({
268
280
  eventType: EVENT_TYPE.UI,
@@ -271,7 +283,11 @@ export const DragHandle = ({
271
283
  actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
272
284
  attributes: {
273
285
  nodeDepth: resolvedMovingNode.depth,
274
- nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
286
+ nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || '',
287
+ ...(isMultiSelect && {
288
+ nodeTypes,
289
+ hasSelectedMultipleNodes
290
+ })
275
291
  }
276
292
  })(tr);
277
293
  return tr;
@@ -369,7 +385,21 @@ export const DragHandle = ({
369
385
  }
370
386
  setDragHandleSelected(isHandleInSelection(view.state, selection, start));
371
387
  }, [start, selection, view.state]);
372
- let helpDescriptors = [{
388
+ let helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
389
+ description: formatMessage(blockControlsMessages.dragToMove)
390
+ }, {
391
+ description: formatMessage(blockControlsMessages.moveUp),
392
+ keymap: dragToMoveUp
393
+ }, {
394
+ description: formatMessage(blockControlsMessages.moveDown),
395
+ keymap: dragToMoveDown
396
+ }, {
397
+ description: formatMessage(blockControlsMessages.moveLeft),
398
+ keymap: dragToMoveLeft
399
+ }, {
400
+ description: formatMessage(blockControlsMessages.moveRight),
401
+ keymap: dragToMoveRight
402
+ }] : [{
373
403
  description: formatMessage(blockControlsMessages.dragToMove)
374
404
  }, {
375
405
  description: formatMessage(blockControlsMessages.moveUp),
@@ -14,12 +14,13 @@ import { findTable, isInTable, isTableSelected } from '@atlaskit/editor-tables/u
14
14
  import { fg } from '@atlaskit/platform-feature-flags';
15
15
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
16
16
  import { key } from '../pm-plugins/main';
17
+ import { attachMoveNodeAnalytics, getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
17
18
  import { DIRECTION } from '../pm-plugins/utils/consts';
18
- import { attachMoveNodeAnalytics } from '../pm-plugins/utils/fire-analytics';
19
19
  import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
20
20
  import { selectNode, setCursorPositionAtMovedNode } from '../pm-plugins/utils/getSelection';
21
21
  import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
22
- import { getMultiSelectionIfPosInside } from '../pm-plugins/utils/selection';
22
+ import { getSelectedSlicePosition } from '../pm-plugins/utils/selection';
23
+ import { getInsertLayoutStep, updateSelection } from '../pm-plugins/utils/update-selection';
23
24
  import { canMoveNodeToIndex, isInsideTable, transformSliceExpandToNestedExpand } from '../pm-plugins/utils/validation';
24
25
 
25
26
  /**
@@ -52,7 +53,7 @@ var isDragLayoutColumnToTopLevel = function isDragLayoutColumnToTopLevel($from,
52
53
  *
53
54
  * @returns the start position of a node if the node can be moved, otherwise -1
54
55
  */
55
- var getCurrentNodePos = function getCurrentNodePos(state, isParentNodeOfTypeLayout) {
56
+ var getCurrentNodePos = function getCurrentNodePos(state) {
56
57
  var _activeNode$handleOpt;
57
58
  var selection = state.selection;
58
59
  var _ref = key.getState(state) || {},
@@ -88,27 +89,46 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
88
89
  if (shouldEnableNestedDndA11y) {
89
90
  isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
90
91
  }
91
- var currentNodePos = getCurrentNodePos(state, isParentNodeOfTypeLayout);
92
+ var currentNodePos = getCurrentNodePos(state);
92
93
  if (currentNodePos > -1) {
93
94
  var _state$doc$nodeAt;
94
95
  var $pos = state.doc.resolve(currentNodePos);
96
+ var isTopLevelNode = $pos.depth === 0;
95
97
  var moveToPos = -1;
96
98
  var nodeIndex = $pos.index();
97
99
  var isLayoutColumnSelected = selection instanceof NodeSelection && selection.node.type.name === 'layoutColumn';
98
100
  if (direction === DIRECTION.LEFT && shouldEnableNestedDndA11y) {
99
- if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
100
- var _$pos$nodeBefore, _api$core;
101
- moveToPos = selection.from - (((_$pos$nodeBefore = $pos.nodeBefore) === null || _$pos$nodeBefore === void 0 ? void 0 : _$pos$nodeBefore.nodeSize) || 1);
101
+ if (isTopLevelNode && editorExperiment('advanced_layouts', true) && fg('platform_editor_advanced_layouts_accessibility')) {
102
+ var _api$core, _api$core2;
103
+ var nodeBefore = $pos.nodeBefore;
104
+ if (nodeBefore) {
105
+ moveToPos = currentNodePos - nodeBefore.nodeSize;
106
+ }
107
+ if (moveToPos < 0) {
108
+ return false;
109
+ }
102
110
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
103
111
  var _api$blockControls;
104
112
  var tr = _ref2.tr;
105
113
  api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.moveToLayout(currentNodePos, moveToPos, {
106
- selectMovedNode: true
114
+ moveToEnd: true,
115
+ moveNodeAtCursorPos: true
107
116
  })({
108
117
  tr: tr
109
118
  });
119
+ var insertColumnStep = getInsertLayoutStep(tr);
120
+ var mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
121
+ updateSelection(tr, mappedTo, true);
110
122
  return tr;
111
123
  });
124
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
125
+ return true;
126
+ } else if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
127
+ var _$pos$nodeBefore, _api$core3, _api$blockControls2;
128
+ moveToPos = selection.from - (((_$pos$nodeBefore = $pos.nodeBefore) === null || _$pos$nodeBefore === void 0 ? void 0 : _$pos$nodeBefore.nodeSize) || 1);
129
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.moveToLayout(currentNodePos, moveToPos, {
130
+ selectMovedNode: true
131
+ }));
112
132
  return true;
113
133
  } else {
114
134
  if ($pos.depth < 2 || !isParentNodeOfTypeLayout) {
@@ -122,8 +142,30 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
122
142
  moveToPos = $pos.start() - ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeSize) || 1);
123
143
  }
124
144
  } else if (direction === DIRECTION.RIGHT && shouldEnableNestedDndA11y) {
125
- if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
126
- var _api$core2;
145
+ if (isTopLevelNode && editorExperiment('advanced_layouts', true) && fg('platform_editor_advanced_layouts_accessibility')) {
146
+ var _api$core4, _api$core5;
147
+ var endOfDoc = $pos.end();
148
+ moveToPos = $pos.posAtIndex($pos.index() + 1);
149
+ if (moveToPos >= endOfDoc) {
150
+ return false;
151
+ }
152
+ api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref3) {
153
+ var _api$blockControls3;
154
+ var tr = _ref3.tr;
155
+ api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || (_api$blockControls3 = _api$blockControls3.commands) === null || _api$blockControls3 === void 0 || _api$blockControls3.moveToLayout(currentNodePos, moveToPos, {
156
+ moveNodeAtCursorPos: true
157
+ })({
158
+ tr: tr
159
+ });
160
+ var insertColumnStep = getInsertLayoutStep(tr);
161
+ var mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
162
+ updateSelection(tr, mappedTo);
163
+ return tr;
164
+ });
165
+ api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.focus();
166
+ return true;
167
+ } else if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
168
+ var _api$core6, _api$blockControls4;
127
169
  var _index = $pos.index($pos.depth);
128
170
  var parent = $pos.node($pos.depth);
129
171
  // get the next layoutColumn node
@@ -136,17 +178,10 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
136
178
  }
137
179
  var moveToEnd = _index === parent.childCount - 2;
138
180
  moveToPos = moveToEnd ? $pos.before() : selection.to + ((nextNode === null || nextNode === void 0 ? void 0 : nextNode.nodeSize) || 1);
139
- api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref3) {
140
- var _api$blockControls2;
141
- var tr = _ref3.tr;
142
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.moveToLayout(currentNodePos, moveToPos, {
143
- moveToEnd: moveToEnd,
144
- selectMovedNode: true
145
- })({
146
- tr: tr
147
- });
148
- return tr;
149
- });
181
+ api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.moveToLayout(currentNodePos, moveToPos, {
182
+ moveToEnd: moveToEnd,
183
+ selectMovedNode: true
184
+ }));
150
185
  return true;
151
186
  } else {
152
187
  if ($pos.depth < 2 || !isParentNodeOfTypeLayout) {
@@ -158,15 +193,15 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
158
193
  if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
159
194
  moveToPos = $pos.start() - 1;
160
195
  } else {
161
- var nodeBefore = $pos.depth > 1 && nodeIndex === 0 && shouldEnableNestedDndA11y ? $pos.node($pos.depth) : $pos.nodeBefore;
162
- if (nodeBefore) {
163
- moveToPos = currentNodePos - nodeBefore.nodeSize;
196
+ var _nodeBefore = $pos.depth > 1 && nodeIndex === 0 && shouldEnableNestedDndA11y ? $pos.node($pos.depth) : $pos.nodeBefore;
197
+ if (_nodeBefore) {
198
+ moveToPos = currentNodePos - _nodeBefore.nodeSize;
164
199
  }
165
200
  }
166
201
  } else {
167
- var endOfDoc = $pos.end();
202
+ var _endOfDoc = $pos.end();
168
203
  var nodeAfterPos = $pos.posAtIndex($pos.index() + 1);
169
- if (nodeAfterPos > endOfDoc) {
204
+ if (nodeAfterPos > _endOfDoc) {
170
205
  return false;
171
206
  }
172
207
  if (isLayoutColumnSelected && fg('platform_editor_advanced_layouts_accessibility')) {
@@ -184,8 +219,8 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
184
219
  // only move the node if the destination is at the same depth, not support moving a nested node to a parent node
185
220
  var shouldMoveNode = (shouldEnableNestedDndA11y ? moveToPos > -1 && $pos.depth === state.doc.resolve(moveToPos).depth || nodeType === 'layoutColumn' : moveToPos > -1) || nodeType === 'layoutColumn' && fg('platform_editor_advanced_layouts_accessibility');
186
221
  if (shouldMoveNode) {
187
- var _api$core3;
188
- api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref4) {
222
+ var _api$core7;
223
+ api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref4) {
189
224
  var tr = _ref4.tr;
190
225
  moveNode(api)(currentNodePos, moveToPos, INPUT_METHOD.SHORTCUT, formatMessage)({
191
226
  tr: tr
@@ -195,9 +230,9 @@ export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, fo
195
230
  });
196
231
  return true;
197
232
  } else if (nodeType) {
198
- var _api$core4;
233
+ var _api$core8;
199
234
  // If the node is first/last one, only select the node
200
- api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref5) {
235
+ api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 || _api$core8.actions.execute(function (_ref5) {
201
236
  var tr = _ref5.tr;
202
237
  selectNode(tr, currentNodePos, nodeType);
203
238
  tr.scrollIntoView();
@@ -224,22 +259,21 @@ export var moveNode = function moveNode(api) {
224
259
  }
225
260
  var sliceFrom = start;
226
261
  var sliceTo;
262
+ var mappedTo;
263
+ var sourceNodeTypes, hasSelectedMultipleNodes;
227
264
  var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
228
265
  exposure: true
229
266
  });
230
267
  if (isMultiSelect) {
231
- var _handleNode$nodeSize;
232
- var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, start),
233
- anchor = _getMultiSelectionIfP.anchor,
234
- head = _getMultiSelectionIfP.head;
235
- var inSelection = anchor !== undefined && head !== undefined;
236
- sliceFrom = inSelection ? Math.min(anchor, head) : start;
237
- var handleSize = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
238
- var handleEnd = sliceFrom + handleSize;
239
- sliceTo = inSelection ? Math.max(anchor, head) : handleEnd;
268
+ var slicePosition = getSelectedSlicePosition(start, tr, api);
269
+ sliceFrom = slicePosition.from;
270
+ sliceTo = slicePosition.to;
271
+ var attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
272
+ hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
273
+ sourceNodeTypes = attributes.nodeTypes;
240
274
  } else {
241
- var _handleNode$nodeSize2;
242
- var size = (_handleNode$nodeSize2 = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize2 !== void 0 ? _handleNode$nodeSize2 : 1;
275
+ var _handleNode$nodeSize;
276
+ var size = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
243
277
  sliceTo = sliceFrom + size;
244
278
  }
245
279
  var _tr$doc$type$schema$n = tr.doc.type.schema.nodes,
@@ -247,7 +281,6 @@ export var moveNode = function moveNode(api) {
247
281
  nestedExpand = _tr$doc$type$schema$n.nestedExpand;
248
282
  var $to = tr.doc.resolve(to);
249
283
  var $handlePos = tr.doc.resolve(start);
250
- var mappedTo;
251
284
  if (editorExperiment('nested-dnd', true)) {
252
285
  var nodeCopy = tr.doc.slice(sliceFrom, sliceTo, false); // cut the content
253
286
  var destType = $to.node().type;
@@ -303,7 +336,7 @@ export var moveNode = function moveNode(api) {
303
336
  }
304
337
  }
305
338
  if (editorExperiment('advanced_layouts', true)) {
306
- attachMoveNodeAnalytics(tr, inputMethod, $handlePos.depth, handleNode.type.name, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name, $handlePos.sameParent($mappedTo), api);
339
+ attachMoveNodeAnalytics(tr, inputMethod, $handlePos.depth, handleNode.type.name, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name, $handlePos.sameParent($mappedTo), api, sourceNodeTypes, hasSelectedMultipleNodes);
307
340
  } else {
308
341
  var _api$analytics;
309
342
  api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
@@ -311,13 +344,16 @@ export var moveNode = function moveNode(api) {
311
344
  action: ACTION.MOVED,
312
345
  actionSubject: ACTION_SUBJECT.ELEMENT,
313
346
  actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
314
- attributes: _objectSpread({
347
+ attributes: _objectSpread(_objectSpread({
315
348
  nodeDepth: $handlePos.depth,
316
349
  nodeType: handleNode.type.name,
317
350
  destinationNodeDepth: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth,
318
351
  destinationNodeType: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name
319
352
  }, fg('platform_editor_element_drag_and_drop_ed_23873') && {
320
353
  inputMethod: inputMethod
354
+ }), isMultiSelect && {
355
+ sourceNodeTypes: sourceNodeTypes,
356
+ hasSelectedMultipleNodes: hasSelectedMultipleNodes
321
357
  })
322
358
  })(tr);
323
359
  }
@@ -4,9 +4,9 @@ import { Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
4
4
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
5
  import { fg } from '@atlaskit/platform-feature-flags';
6
6
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
7
+ import { fireInsertLayoutAnalytics, attachMoveNodeAnalytics, getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
7
8
  import { isFragmentOfType, containsNodeOfType } from '../pm-plugins/utils/check-fragment';
8
9
  import { maxLayoutColumnSupported } from '../pm-plugins/utils/consts';
9
- import { fireInsertLayoutAnalytics, attachMoveNodeAnalytics } from '../pm-plugins/utils/fire-analytics';
10
10
  import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
11
11
  import { getMultiSelectionIfPosInside } from '../pm-plugins/utils/selection';
12
12
  import { updateColumnWidths } from '../pm-plugins/utils/update-column-widths';
@@ -41,9 +41,14 @@ var createNewLayout = function createNewLayout(schema, layoutContents) {
41
41
  var moveToExistingLayout = function moveToExistingLayout(toLayout, toLayoutPos, sourceContent, from, to, tr, $originalFrom, $originalTo, api, selectMovedNode) {
42
42
  var isSameLayout = isInSameLayout($originalFrom, $originalTo);
43
43
  var sourceContentEndPos = -1;
44
- if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
44
+ var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
45
+ var sourceNodeTypes, hasSelectedMultipleNodes;
46
+ if (isMultiSelect) {
45
47
  if (sourceContent instanceof Fragment) {
46
48
  sourceContentEndPos = from + sourceContent.size;
49
+ var attributes = getMultiSelectAnalyticsAttributes(tr, from, sourceContentEndPos);
50
+ hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
51
+ sourceNodeTypes = attributes.nodeTypes;
47
52
  }
48
53
  } else {
49
54
  if (sourceContent instanceof PMNode) {
@@ -62,7 +67,7 @@ var moveToExistingLayout = function moveToExistingLayout(toLayout, toLayoutPos,
62
67
  if (!fg('platform_editor_advanced_layouts_post_fix_patch_1') || selectMovedNode) {
63
68
  tr.setSelection(new NodeSelection(tr.doc.resolve(mappedTo))).scrollIntoView();
64
69
  }
65
- attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf === void 0 ? void 0 : _$originalFrom$nodeAf.type.name) || '', 1, 'layoutSection', true, api);
70
+ attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf === void 0 ? void 0 : _$originalFrom$nodeAf.type.name) || '', 1, 'layoutSection', true, api, sourceNodeTypes, hasSelectedMultipleNodes);
66
71
  } else if (toLayout.childCount < maxLayoutColumnSupported()) {
67
72
  var _$originalFrom$nodeAf2;
68
73
  if (fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
@@ -73,7 +78,7 @@ var moveToExistingLayout = function moveToExistingLayout(toLayout, toLayoutPos,
73
78
  var mappedFrom = tr.mapping.map(from);
74
79
  removeFromSource(tr, tr.doc.resolve(mappedFrom), tr.mapping.map(sourceContentEndPos));
75
80
  }
76
- attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf2 = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf2 === void 0 ? void 0 : _$originalFrom$nodeAf2.type.name) || '', 1, 'layoutSection', false, api);
81
+ attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf2 = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf2 === void 0 ? void 0 : _$originalFrom$nodeAf2.type.name) || '', 1, 'layoutSection', false, api, sourceNodeTypes, hasSelectedMultipleNodes);
77
82
  }
78
83
  return tr;
79
84
  };
@@ -156,7 +161,7 @@ var insertToDestination = function insertToDestination(tr, to, sourceContent, to
156
161
  * Check if the node at `from` can be moved to node at `to` to create/expand a layout.
157
162
  * Returns the source and destination nodes and positions if it's a valid move, otherwise, undefined
158
163
  */
159
- var canMoveToLayout = function canMoveToLayout(api, from, to, tr) {
164
+ var canMoveToLayout = function canMoveToLayout(api, from, to, tr, moveNodeAtCursorPos) {
160
165
  if (from === to) {
161
166
  return;
162
167
  }
@@ -187,11 +192,11 @@ var canMoveToLayout = function canMoveToLayout(api, from, to, tr) {
187
192
  var sourceContent = $from.nodeAfter;
188
193
  var sourceFrom = from;
189
194
  var sourceTo = from + sourceContent.nodeSize;
190
- if (isMultiSelect) {
195
+ if (isMultiSelect && !moveNodeAtCursorPos) {
191
196
  var _getMultiSelectionIfP = getMultiSelectionIfPosInside(api, from),
192
197
  anchor = _getMultiSelectionIfP.anchor,
193
198
  head = _getMultiSelectionIfP.head;
194
- if (anchor && head) {
199
+ if (anchor !== undefined && head !== undefined) {
195
200
  sourceFrom = Math.min(anchor, head);
196
201
  sourceTo = Math.max(anchor, head);
197
202
  sourceContent = tr.doc.slice(sourceFrom, sourceTo).content;
@@ -248,7 +253,7 @@ var getBreakoutMode = function getBreakoutMode(content, breakout) {
248
253
  var _content$marks$find;
249
254
  return (_content$marks$find = content.marks.find(function (m) {
250
255
  return m.type === breakout;
251
- })) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs;
256
+ })) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs.mode;
252
257
  } else if (content instanceof Fragment) {
253
258
  // Find the first breakout mode in the fragment
254
259
  var firstBreakoutMode;
@@ -284,7 +289,7 @@ export var moveToLayout = function moveToLayout(api) {
284
289
  if (!api) {
285
290
  return tr;
286
291
  }
287
- var canMove = canMoveToLayout(api, from, to, tr);
292
+ var canMove = canMoveToLayout(api, from, to, tr, options === null || options === void 0 ? void 0 : options.moveNodeAtCursorPos);
288
293
  if (!canMove) {
289
294
  return tr;
290
295
  }
@@ -308,6 +313,7 @@ export var moveToLayout = function moveToLayout(api) {
308
313
  if (!fromContentWithoutBreakout) {
309
314
  return tr;
310
315
  }
316
+ var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
311
317
  if (toNode.type === layoutSection) {
312
318
  var toPos = options !== null && options !== void 0 && options.moveToEnd ? to + toNode.nodeSize - 1 : to + 1;
313
319
  return moveToExistingLayout(toNode, to, fromContentWithoutBreakout, $sourceFrom.pos, toPos, tr, $sourceFrom, $to, api, options === null || options === void 0 ? void 0 : options.selectMovedNode);
@@ -327,7 +333,7 @@ export var moveToLayout = function moveToLayout(api) {
327
333
  // resolve again the source node after node updated (remove breakout marks)
328
334
  toNodeWithoutBreakout = tr.doc.resolve(to).nodeAfter || toNode;
329
335
  }
330
- if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
336
+ if (isMultiSelect) {
331
337
  if (isFragmentOfType(fromContentWithoutBreakout, 'layoutColumn') && fromContentWithoutBreakout.firstChild) {
332
338
  fromContentWithoutBreakout = fromContentWithoutBreakout.firstChild.content;
333
339
  }
@@ -339,6 +345,12 @@ export var moveToLayout = function moveToLayout(api) {
339
345
  var layoutContents = options !== null && options !== void 0 && options.moveToEnd ? [toNodeWithoutBreakout, fromContentWithoutBreakout] : [fromContentWithoutBreakout, toNodeWithoutBreakout];
340
346
  var newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
341
347
  if (newLayout) {
348
+ var sourceNodeTypes, hasSelectedMultipleNodes;
349
+ if (isMultiSelect) {
350
+ var attributes = getMultiSelectAnalyticsAttributes(tr, $sourceFrom.pos, sourceTo);
351
+ hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
352
+ sourceNodeTypes = attributes.nodeTypes;
353
+ }
342
354
  tr = removeFromSource(tr, $sourceFrom, sourceTo);
343
355
  var mappedTo = tr.mapping.map(to);
344
356
  tr.delete(mappedTo, mappedTo + toNodeWithoutBreakout.nodeSize).insert(mappedTo, newLayout);
@@ -348,7 +360,7 @@ export var moveToLayout = function moveToLayout(api) {
348
360
  breakoutMode && tr.setNodeMarkup(mappedTo, newLayout.type, newLayout.attrs, [breakout.create({
349
361
  mode: breakoutMode
350
362
  })]);
351
- fireInsertLayoutAnalytics(tr, api);
363
+ fireInsertLayoutAnalytics(tr, api, sourceNodeTypes, hasSelectedMultipleNodes);
352
364
  }
353
365
  return tr;
354
366
  }
@@ -1,8 +1,11 @@
1
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
1
2
  import { isInTable } from '@atlaskit/editor-tables/utils';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
2
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
3
- import { key } from '../pm-plugins/main';
5
+ import { findNodeDecs } from '../pm-plugins/decorations-anchor';
6
+ import { getDecorations, key } from '../pm-plugins/main';
4
7
  import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
5
- export var showDragHandleAtSelection = function showDragHandleAtSelection(api, shouldFocusParentNode) {
8
+ var showDragHandleAtSelectionOld = function showDragHandleAtSelectionOld(api, shouldFocusParentNode) {
6
9
  return function (state, _, view) {
7
10
  var $from = state.selection.$from;
8
11
  var shouldFocusParentNode;
@@ -62,4 +65,87 @@ export var showDragHandleAtSelection = function showDragHandleAtSelection(api, s
62
65
  }
63
66
  return false;
64
67
  };
68
+ };
69
+ var findParentPosForHandle = function findParentPosForHandle(state) {
70
+ var _activeNode$handleOpt2;
71
+ var $from = state.selection.$from;
72
+ var _ref2 = key.getState(state) || {},
73
+ activeNode = _ref2.activeNode;
74
+
75
+ // if a node handle is already focused, return the parent pos of that node (with focused handle)
76
+ if (activeNode && (_activeNode$handleOpt2 = activeNode.handleOptions) !== null && _activeNode$handleOpt2 !== void 0 && _activeNode$handleOpt2.isFocused) {
77
+ var $activeNodePos = state.doc.resolve(activeNode.pos);
78
+
79
+ // if the handle is at the top level already, do nothing
80
+ if ($activeNodePos.depth === 0) {
81
+ return undefined;
82
+ }
83
+ return $activeNodePos.before();
84
+ }
85
+
86
+ // if we are in second level of nested node, we should focus the node at level 1
87
+ if ($from.depth <= 1) {
88
+ return $from.before(1);
89
+ }
90
+
91
+ // if we are inside a table, we should focus the table's handle
92
+ var parentTableNode = findParentNodeOfType([state.schema.nodes.table])(state.selection);
93
+ if (parentTableNode) {
94
+ return parentTableNode.pos;
95
+ }
96
+
97
+ // else find closest parent node
98
+ return getNestedNodePosition(state);
99
+ };
100
+ var findNextAnchorDecoration = function findNextAnchorDecoration(state) {
101
+ var decorations = getDecorations(state);
102
+ if (!decorations) {
103
+ return undefined;
104
+ }
105
+ var nextHandleNodePos = findParentPosForHandle(state);
106
+ if (nextHandleNodePos === undefined) {
107
+ return undefined;
108
+ }
109
+ var nextHandleNode = state.doc.nodeAt(nextHandleNodePos);
110
+ var nodeDecorations = nextHandleNode && findNodeDecs(decorations, nextHandleNodePos, nextHandleNodePos + nextHandleNode.nodeSize);
111
+ if (!nodeDecorations || nodeDecorations.length === 0) {
112
+ return undefined;
113
+ }
114
+
115
+ // ensure the decoration covers the position of the look up node
116
+ nodeDecorations = nodeDecorations.filter(function (decoration) {
117
+ return decoration.from <= nextHandleNodePos;
118
+ });
119
+ if (nodeDecorations.length === 0) {
120
+ return undefined;
121
+ }
122
+
123
+ // sort the decorations by the position of the node
124
+ // so we can find the closest decoration to the node
125
+ nodeDecorations.sort(function (a, b) {
126
+ if (a.from === b.from) {
127
+ return a.to - b.to;
128
+ }
129
+ return b.from - a.from;
130
+ });
131
+
132
+ // return the closest decoration to the node
133
+ return nodeDecorations[0];
134
+ };
135
+ var showDragHandleAtSelectionNew = function showDragHandleAtSelectionNew(api) {
136
+ return function (state) {
137
+ var decoration = findNextAnchorDecoration(state);
138
+ if (api && decoration) {
139
+ api.core.actions.execute(api.blockControls.commands.showDragHandleAt(decoration.from, decoration.spec.anchorName, decoration.spec.nodeTypeWithLevel, {
140
+ isFocused: true
141
+ }));
142
+ return true;
143
+ }
144
+ return false;
145
+ };
146
+ };
147
+ export var showDragHandleAtSelection = function showDragHandleAtSelection(api) {
148
+ return function (state, dispatch, view) {
149
+ return editorExperiment('nested-dnd', true) && fg('platform_editor_advanced_layouts_a11y') ? showDragHandleAtSelectionNew(api)(state) : showDragHandleAtSelectionOld(api)(state, dispatch, view);
150
+ };
65
151
  };
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
3
  import { fg } from '@atlaskit/platform-feature-flags';
4
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
5
- import { getNestedDepth, getNodeAnchor, TYPE_NODE_DEC } from './decorations-common';
5
+ import { getNestedDepth, getNodeAnchor, getNodeTypeWithLevel, TYPE_NODE_DEC } from './decorations-common';
6
6
  var IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'listItem', 'caption', 'layoutColumn'];
7
7
  var IGNORE_NODES_NEXT = ['tableCell', 'tableHeader', 'tableRow', 'listItem', 'caption'];
8
8
  var IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaSingle'];
@@ -71,11 +71,10 @@ export var nodeDecorations = function nodeDecorations(newState, from, to) {
71
71
  var ignore_nodes = editorExperiment('advanced_layouts', true) ? IGNORE_NODES_NEXT : IGNORE_NODES;
72
72
  newState.doc.nodesBetween(docFrom, docTo, function (node, pos, parent, index) {
73
73
  var depth = 0;
74
- var anchorName;
75
74
  var shouldDescend = shouldDescendIntoNode(node);
76
- anchorName = getNodeAnchor(node);
75
+ var anchorName = getNodeAnchor(node);
76
+ var nodeTypeWithLevel = getNodeTypeWithLevel(node);
77
77
  if (editorExperiment('nested-dnd', true)) {
78
- var _anchorName;
79
78
  // Doesn't descend into a node
80
79
  if (node.isInline) {
81
80
  return false;
@@ -84,19 +83,15 @@ export var nodeDecorations = function nodeDecorations(newState, from, to) {
84
83
  if (shouldIgnoreNode(node, ignore_nodes, depth, parent)) {
85
84
  return shouldDescend; //skip over, don't consider it a valid depth
86
85
  }
87
- anchorName = (_anchorName = anchorName) !== null && _anchorName !== void 0 ? _anchorName : "--node-anchor-".concat(node.type.name, "-").concat(pos);
88
- } else {
89
- var _anchorName2;
90
- anchorName = (_anchorName2 = anchorName) !== null && _anchorName2 !== void 0 ? _anchorName2 : "--node-anchor-".concat(node.type.name, "-").concat(index);
91
86
  }
92
87
  var anchorStyles = "anchor-name: ".concat(anchorName, ";");
93
- var subType = node.attrs.level ? "-".concat(node.attrs.level) : '';
94
88
  decs.push(Decoration.node(pos, pos + node.nodeSize, _defineProperty(_defineProperty(_defineProperty({
95
89
  style: anchorStyles
96
- }, 'data-drag-handler-anchor-name', anchorName), 'data-drag-handler-node-type', node.type.name + subType), 'data-drag-handler-anchor-depth', "".concat(depth)), {
90
+ }, 'data-drag-handler-anchor-name', anchorName), 'data-drag-handler-node-type', nodeTypeWithLevel), 'data-drag-handler-anchor-depth', "".concat(depth)), {
97
91
  type: TYPE_NODE_DEC,
98
92
  anchorName: anchorName,
99
- nodeType: node.type.name
93
+ nodeType: node.type.name,
94
+ nodeTypeWithLevel: nodeTypeWithLevel
100
95
  }));
101
96
  return shouldDescend && depth < getNestedDepth();
102
97
  });
@@ -1,9 +1,7 @@
1
1
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- import ReactDOM from 'react-dom';
5
4
  import uuid from 'uuid';
6
- import { fg } from '@atlaskit/platform-feature-flags';
7
5
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
8
6
  export var TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
9
7
  export var TYPE_HANDLE_DEC = 'drag-handle';
@@ -15,6 +13,10 @@ export var getNodeAnchor = function getNodeAnchor(node) {
15
13
  var handleId = ObjHash.getForNode(node);
16
14
  return "--node-anchor-".concat(node.type.name, "-").concat(handleId);
17
15
  };
16
+ export var getNodeTypeWithLevel = function getNodeTypeWithLevel(node) {
17
+ var subType = node.attrs.level ? "-".concat(node.attrs.level) : '';
18
+ return node.type.name + subType;
19
+ };
18
20
  var ObjHash = /*#__PURE__*/function () {
19
21
  function ObjHash() {
20
22
  _classCallCheck(this, ObjHash);
@@ -37,13 +39,9 @@ export var unmountDecorations = function unmountDecorations(nodeViewPortalProvid
37
39
  // as it was more responsive and causes less re-rendering
38
40
  var decorationsToRemove = document.querySelectorAll("[".concat(selector, "=\"true\"]"));
39
41
  decorationsToRemove.forEach(function (el) {
40
- if (fg('platform_editor_react18_plugin_portalprovider')) {
41
- var nodeKey = el.getAttribute(key);
42
- if (nodeKey) {
43
- nodeViewPortalProviderAPI.remove(nodeKey);
44
- }
45
- } else {
46
- ReactDOM.unmountComponentAtNode(el);
42
+ var nodeKey = el.getAttribute(key);
43
+ if (nodeKey) {
44
+ nodeViewPortalProviderAPI.remove(nodeKey);
47
45
  }
48
46
  });
49
47
  };