@atlaskit/editor-plugin-block-controls 2.21.4 → 2.21.6

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 (62) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/blockControlsPlugin.js +0 -2
  3. package/dist/cjs/editor-commands/move-node.js +2 -5
  4. package/dist/cjs/editor-commands/move-to-layout.js +186 -60
  5. package/dist/cjs/pm-plugins/decorations-anchor.js +1 -6
  6. package/dist/cjs/pm-plugins/decorations-drag-handle.js +1 -4
  7. package/dist/cjs/pm-plugins/decorations-drop-target.js +4 -17
  8. package/dist/cjs/pm-plugins/main.js +6 -15
  9. package/dist/cjs/pm-plugins/utils/check-fragment.js +26 -0
  10. package/dist/cjs/pm-plugins/utils/drag-handle-positions.js +1 -4
  11. package/dist/cjs/pm-plugins/utils/fire-analytics.js +1 -4
  12. package/dist/cjs/pm-plugins/utils/inline-drop-target.js +1 -4
  13. package/dist/cjs/pm-plugins/utils/remove-from-source.js +15 -6
  14. package/dist/cjs/pm-plugins/utils/update-column-widths.js +1 -4
  15. package/dist/cjs/pm-plugins/utils/validation.js +0 -3
  16. package/dist/cjs/ui/drop-target-layout.js +1 -2
  17. package/dist/cjs/ui/drop-target.js +7 -6
  18. package/dist/cjs/ui/inline-drop-target.js +1 -2
  19. package/dist/es2019/blockControlsPlugin.js +0 -2
  20. package/dist/es2019/editor-commands/move-node.js +2 -5
  21. package/dist/es2019/editor-commands/move-to-layout.js +171 -50
  22. package/dist/es2019/pm-plugins/decorations-anchor.js +1 -6
  23. package/dist/es2019/pm-plugins/decorations-drag-handle.js +1 -4
  24. package/dist/es2019/pm-plugins/decorations-drop-target.js +4 -17
  25. package/dist/es2019/pm-plugins/main.js +6 -15
  26. package/dist/es2019/pm-plugins/utils/check-fragment.js +20 -0
  27. package/dist/es2019/pm-plugins/utils/drag-handle-positions.js +1 -4
  28. package/dist/es2019/pm-plugins/utils/fire-analytics.js +1 -4
  29. package/dist/es2019/pm-plugins/utils/inline-drop-target.js +1 -4
  30. package/dist/es2019/pm-plugins/utils/remove-from-source.js +15 -6
  31. package/dist/es2019/pm-plugins/utils/update-column-widths.js +1 -4
  32. package/dist/es2019/pm-plugins/utils/validation.js +0 -3
  33. package/dist/es2019/ui/drop-target-layout.js +1 -2
  34. package/dist/es2019/ui/drop-target.js +7 -6
  35. package/dist/es2019/ui/inline-drop-target.js +1 -2
  36. package/dist/esm/blockControlsPlugin.js +0 -2
  37. package/dist/esm/editor-commands/move-node.js +2 -5
  38. package/dist/esm/editor-commands/move-to-layout.js +187 -61
  39. package/dist/esm/pm-plugins/decorations-anchor.js +1 -6
  40. package/dist/esm/pm-plugins/decorations-drag-handle.js +1 -4
  41. package/dist/esm/pm-plugins/decorations-drop-target.js +4 -17
  42. package/dist/esm/pm-plugins/main.js +6 -15
  43. package/dist/esm/pm-plugins/utils/check-fragment.js +20 -0
  44. package/dist/esm/pm-plugins/utils/drag-handle-positions.js +1 -4
  45. package/dist/esm/pm-plugins/utils/fire-analytics.js +1 -4
  46. package/dist/esm/pm-plugins/utils/inline-drop-target.js +1 -4
  47. package/dist/esm/pm-plugins/utils/remove-from-source.js +15 -6
  48. package/dist/esm/pm-plugins/utils/update-column-widths.js +1 -4
  49. package/dist/esm/pm-plugins/utils/validation.js +0 -3
  50. package/dist/esm/ui/drop-target-layout.js +1 -2
  51. package/dist/esm/ui/drop-target.js +7 -6
  52. package/dist/esm/ui/inline-drop-target.js +1 -2
  53. package/dist/types/pm-plugins/utils/check-fragment.d.ts +9 -0
  54. package/dist/types/pm-plugins/utils/remove-from-source.d.ts +1 -1
  55. package/dist/types-ts4.5/pm-plugins/utils/check-fragment.d.ts +9 -0
  56. package/dist/types-ts4.5/pm-plugins/utils/remove-from-source.d.ts +1 -1
  57. package/package.json +5 -8
  58. package/dist/cjs/pm-plugins/utils/drag-target-debug.js +0 -11
  59. package/dist/es2019/pm-plugins/utils/drag-target-debug.js +0 -5
  60. package/dist/esm/pm-plugins/utils/drag-target-debug.js +0 -5
  61. package/dist/types/pm-plugins/utils/drag-target-debug.d.ts +0 -1
  62. package/dist/types-ts4.5/pm-plugins/utils/drag-target-debug.d.ts +0 -1
@@ -7,16 +7,25 @@ exports.removeFromSource = void 0;
7
7
  var _model = require("@atlaskit/editor-prosemirror/model");
8
8
  var _utils = require("@atlaskit/editor-prosemirror/utils");
9
9
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
10
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
11
+ var _checkFragment = require("./check-fragment");
10
12
  var _consts = require("./consts");
11
13
  var _updateColumnWidths = require("./update-column-widths");
12
- var removeFromSource = exports.removeFromSource = function removeFromSource(tr, $from) {
13
- var sourceNode = $from.nodeAfter;
14
- var sourceParent = $from.parent;
15
- if (!sourceNode) {
14
+ var removeFromSource = exports.removeFromSource = function removeFromSource(tr, $from, to) {
15
+ var _sourceContent, _sourceContent2;
16
+ var sourceContent = $from.nodeAfter;
17
+ var isLayoutColumn = ((_sourceContent = sourceContent) === null || _sourceContent === void 0 ? void 0 : _sourceContent.type.name) === 'layoutColumn';
18
+ var sourceNodeEndPos = $from.pos + (((_sourceContent2 = sourceContent) === null || _sourceContent2 === void 0 ? void 0 : _sourceContent2.nodeSize) || 1);
19
+ if ((0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true)) {
20
+ sourceContent = tr.doc.slice($from.pos, to).content;
21
+ isLayoutColumn = (0, _checkFragment.isFragmentOfType)(sourceContent, 'layoutColumn');
22
+ sourceNodeEndPos = to === undefined ? $from.pos + sourceContent.size : to;
23
+ }
24
+ if (!sourceContent) {
16
25
  return tr;
17
26
  }
18
- var sourceNodeEndPos = $from.pos + sourceNode.nodeSize;
19
- if (sourceNode.type.name === 'layoutColumn') {
27
+ if (isLayoutColumn) {
28
+ var sourceParent = $from.parent;
20
29
  if (sourceParent.childCount === _consts.MIN_LAYOUT_COLUMN) {
21
30
  tr.delete($from.pos + 1, sourceNodeEndPos - 1);
22
31
 
@@ -5,10 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.updateColumnWidths = void 0;
7
7
  var _consts = require("../../ui/consts");
8
- var updateColumnWidths = exports.updateColumnWidths = function updateColumnWidths(tr, layoutNode, layoutNodePos, childCount
9
- // Ignored via go/ees005
10
- // eslint-disable-next-line @typescript-eslint/max-params
11
- ) {
8
+ var updateColumnWidths = exports.updateColumnWidths = function updateColumnWidths(tr, layoutNode, layoutNodePos, childCount) {
12
9
  var newColumnWidth = _consts.DEFAULT_COLUMN_DISTRIBUTIONS[childCount];
13
10
  if (newColumnWidth) {
14
11
  layoutNode.content.forEach(function (node, offset) {
@@ -78,9 +78,6 @@ var memoizedTransformExpandToNestedExpand = exports.memoizedTransformExpandToNes
78
78
  return null;
79
79
  }
80
80
  });
81
-
82
- // Ignored via go/ees005
83
- // eslint-disable-next-line @typescript-eslint/max-params
84
81
  function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNodePos, destNode) {
85
82
  var srcNodeType = srcNode.type;
86
83
  var parentNodeType = destParent === null || destParent === void 0 ? void 0 : destParent.type.name;
@@ -17,7 +17,6 @@ var _colors = require("@atlaskit/theme/colors");
17
17
  var _decorationsCommon = require("../pm-plugins/decorations-common");
18
18
  var _activeAnchorTracker = require("../pm-plugins/utils/active-anchor-tracker");
19
19
  var _anchorUtils = require("../pm-plugins/utils/anchor-utils");
20
- var _dragTargetDebug = require("../pm-plugins/utils/drag-target-debug");
21
20
  var _updateSelection = require("../pm-plugins/utils/update-selection");
22
21
  /**
23
22
  * @jsxRuntime classic
@@ -131,7 +130,7 @@ var DropTargetLayout = exports.DropTargetLayout = function DropTargetLayout(prop
131
130
  ,
132
131
  css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle],
133
132
  "data-testid": "block-ctrl-drop-indicator"
134
- }, isDraggedOver || (0, _dragTargetDebug.isBlocksDragTargetDebug)() ? (0, _react2.jsx)(_box.DropIndicator, {
133
+ }, isDraggedOver ? (0, _react2.jsx)(_box.DropIndicator, {
135
134
  edge: "right",
136
135
  gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px")
137
136
  }) : isActiveAnchor && (0, _react2.jsx)("div", {
@@ -18,7 +18,6 @@ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
18
18
  var _decorationsCommon = require("../pm-plugins/decorations-common");
19
19
  var _activeAnchorTracker = require("../pm-plugins/utils/active-anchor-tracker");
20
20
  var _anchorUtils = require("../pm-plugins/utils/anchor-utils");
21
- var _dragTargetDebug = require("../pm-plugins/utils/drag-target-debug");
22
21
  var _inlineDropTarget = require("../pm-plugins/utils/inline-drop-target");
23
22
  var _consts = require("./consts");
24
23
  var _inlineDropTarget2 = require("./inline-drop-target");
@@ -48,7 +47,11 @@ var styleDropIndicator = (0, _react2.css)({
48
47
  height: '100%',
49
48
  margin: '0 auto',
50
49
  position: 'relative',
51
- width: "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, ", 100%)")
50
+ width: "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, ", 100%)"),
51
+ display: 'none'
52
+ });
53
+ var styleDropIndicatorVisible = (0, _react2.css)({
54
+ display: 'block'
52
55
  });
53
56
  var nestedDropIndicatorStyle = (0, _react2.css)({
54
57
  position: 'relative'
@@ -232,10 +235,8 @@ var DropTarget = exports.DropTarget = function DropTarget(props) {
232
235
  ,
233
236
  style: dynamicStyle,
234
237
  "data-testid": "block-ctrl-drop-target"
235
- },
236
- // 4px gap to clear expand node border
237
- (isDraggedOver || (0, _dragTargetDebug.isBlocksDragTargetDebug)()) && (0, _react2.jsx)("div", {
238
- css: styleDropIndicator,
238
+ }, (0, _react2.jsx)("div", {
239
+ css: [styleDropIndicator, isDraggedOver && styleDropIndicatorVisible],
239
240
  "data-testid": "block-ctrl-drop-indicator"
240
241
  }, (0, _react2.jsx)(_box.DropIndicator, {
241
242
  edge: "bottom"
@@ -17,7 +17,6 @@ var _colors = require("@atlaskit/theme/colors");
17
17
  var _decorationsCommon = require("../pm-plugins/decorations-common");
18
18
  var _activeAnchorTracker = require("../pm-plugins/utils/active-anchor-tracker");
19
19
  var _anchorUtils = require("../pm-plugins/utils/anchor-utils");
20
- var _dragTargetDebug = require("../pm-plugins/utils/drag-target-debug");
21
20
  var _updateSelection = require("../pm-plugins/utils/update-selection");
22
21
  /* eslint-disable @atlaskit/design-system/consistent-css-prop-usage */
23
22
  /* eslint-disable @atlaskit/ui-styling-standard/no-unsafe-values */
@@ -255,7 +254,7 @@ var InlineDropTarget = exports.InlineDropTarget = function InlineDropTarget(_ref
255
254
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
256
255
  ,
257
256
  style: hoverZoneRectStyle
258
- }, isDraggedOver || (0, _dragTargetDebug.isBlocksDragTargetDebug)() ? (0, _react2.jsx)(_box.DropIndicator, {
257
+ }, isDraggedOver ? (0, _react2.jsx)(_box.DropIndicator, {
259
258
  edge: dropIndicatorPos
260
259
  }) : isActiveAnchor && (0, _react2.jsx)("div", {
261
260
  "data-testid": "block-ctrl-drop-hint",
@@ -20,8 +20,6 @@ export const blockControlsPlugin = ({
20
20
  commands: {
21
21
  moveNode: moveNode(api),
22
22
  moveToLayout: moveToLayout(api),
23
- // Ignored via go/ees005
24
- // eslint-disable-next-line @typescript-eslint/max-params
25
23
  showDragHandleAt: (pos, anchorName, nodeType, handleOptions) => ({
26
24
  tr
27
25
  }) => {
@@ -154,10 +154,7 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
154
154
  return false;
155
155
  };
156
156
  };
157
- export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_DROP, formatMessage
158
- // Ignored via go/ees005
159
- // eslint-disable-next-line @typescript-eslint/max-params
160
- ) => ({
157
+ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_DROP, formatMessage) => ({
161
158
  tr
162
159
  }) => {
163
160
  const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
@@ -203,7 +200,7 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
203
200
  if (sourceNode && isDragLayoutColumnToTopLevel($handlePos, $to)) {
204
201
  // need update after we support single column layout.
205
202
  const fragment = Fragment.from(sourceNode.content);
206
- removeFromSource(tr, $handlePos);
203
+ removeFromSource(tr, $handlePos, $handlePos.pos + sourceNode.nodeSize);
207
204
  const mappedTo = tr.mapping.map(to);
208
205
  tr.insert(mappedTo, fragment).setSelection(Selection.near(tr.doc.resolve(mappedTo))).scrollIntoView();
209
206
  return tr;
@@ -1,7 +1,9 @@
1
1
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
- import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+ import { Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
3
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
4
  import { fg } from '@atlaskit/platform-feature-flags';
5
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
6
+ import { isFragmentOfType, containsNodeOfType } from '../pm-plugins/utils/check-fragment';
5
7
  import { maxLayoutColumnSupported } from '../pm-plugins/utils/consts';
6
8
  import { fireInsertLayoutAnalytics, attachMoveNodeAnalytics } from '../pm-plugins/utils/fire-analytics';
7
9
  import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
@@ -33,17 +35,27 @@ const createNewLayout = (schema, layoutContents) => {
33
35
  }
34
36
  return null;
35
37
  };
36
- const moveToExistingLayout = (toLayout, toLayoutPos, sourceNode, from, to, tr, $originalFrom, $originalTo, api
37
- // Ignored via go/ees005
38
- // eslint-disable-next-line @typescript-eslint/max-params
39
- ) => {
38
+ const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr, $originalFrom, $originalTo, api) => {
40
39
  const isSameLayout = isInSameLayout($originalFrom, $originalTo);
40
+ let sourceContentEndPos = -1;
41
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
42
+ if (sourceContent instanceof Fragment) {
43
+ sourceContentEndPos = from + sourceContent.size;
44
+ }
45
+ } else {
46
+ if (sourceContent instanceof PMNode) {
47
+ sourceContentEndPos = from + sourceContent.nodeSize;
48
+ }
49
+ }
50
+ if (sourceContentEndPos === -1) {
51
+ return tr;
52
+ }
41
53
  if (isSameLayout) {
42
54
  var _$originalFrom$nodeAf;
43
55
  // reorder columns
44
- tr.delete(from, from + sourceNode.nodeSize);
56
+ tr.delete(from, sourceContentEndPos);
45
57
  const mappedTo = tr.mapping.map(to);
46
- tr.insert(mappedTo, sourceNode);
58
+ tr.insert(mappedTo, sourceContent);
47
59
  if (!fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
48
60
  tr.setSelection(new NodeSelection(tr.doc.resolve(mappedTo))).scrollIntoView();
49
61
  }
@@ -51,12 +63,12 @@ const moveToExistingLayout = (toLayout, toLayoutPos, sourceNode, from, to, tr, $
51
63
  } else if (toLayout.childCount < maxLayoutColumnSupported()) {
52
64
  var _$originalFrom$nodeAf2;
53
65
  if (fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
54
- removeFromSource(tr, tr.doc.resolve(from));
55
- insertToDestinationNoWidthUpdate(tr, tr.mapping.map(to), sourceNode);
66
+ removeFromSource(tr, tr.doc.resolve(from), sourceContentEndPos);
67
+ insertToDestinationNoWidthUpdate(tr, tr.mapping.map(to), sourceContent);
56
68
  } else {
57
- insertToDestination(tr, to, sourceNode, toLayout, toLayoutPos);
69
+ insertToDestination(tr, to, sourceContent, toLayout, toLayoutPos);
58
70
  const mappedFrom = tr.mapping.map(from);
59
- removeFromSource(tr, tr.doc.resolve(mappedFrom));
71
+ removeFromSource(tr, tr.doc.resolve(mappedFrom), tr.mapping.map(sourceContentEndPos));
60
72
  }
61
73
  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);
62
74
  }
@@ -71,30 +83,57 @@ const moveToExistingLayout = (toLayout, toLayoutPos, sourceNode, from, to, tr, $
71
83
  * @param sourceNode
72
84
  * @returns
73
85
  */
74
- const insertToDestinationNoWidthUpdate = (tr, to, sourceNode) => {
86
+ const insertToDestinationNoWidthUpdate = (tr, to, sourceContent) => {
75
87
  const {
76
88
  layoutColumn
77
89
  } = tr.doc.type.schema.nodes || {};
78
- const content = layoutColumn.createChecked({
79
- width: 0
80
- }, sourceNode.type.name === 'layoutColumn' ? sourceNode.content : sourceNode);
81
- tr.insert(to, content);
90
+ let content = null;
91
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
92
+ if (sourceContent instanceof Fragment) {
93
+ var _sourceFragment$first;
94
+ const sourceFragment = sourceContent;
95
+ content = layoutColumn.createChecked({
96
+ width: 0
97
+ }, isFragmentOfType(sourceFragment, 'layoutColumn') ? (_sourceFragment$first = sourceFragment.firstChild) === null || _sourceFragment$first === void 0 ? void 0 : _sourceFragment$first.content : sourceFragment);
98
+ }
99
+ } else {
100
+ if (sourceContent instanceof PMNode) {
101
+ const sourceNode = sourceContent;
102
+ content = layoutColumn.createChecked({
103
+ width: 0
104
+ }, sourceNode.type.name === 'layoutColumn' ? sourceNode.content : sourceNode);
105
+ }
106
+ }
107
+ if (content) {
108
+ tr.insert(to, content);
109
+ }
82
110
  return tr;
83
111
  };
84
- const insertToDestination = (tr, to, sourceNode, toLayout, toLayoutPos
85
- // Ignored via go/ees005
86
- // eslint-disable-next-line @typescript-eslint/max-params
87
- ) => {
112
+ const insertToDestination = (tr, to, sourceContent, toLayout, toLayoutPos) => {
88
113
  const {
89
114
  newColumnWidth
90
115
  } = updateColumnWidths(tr, toLayout, toLayoutPos, toLayout.childCount + 1) || {};
91
116
  const {
92
117
  layoutColumn
93
118
  } = tr.doc.type.schema.nodes || {};
94
- const content = layoutColumn.createChecked({
95
- width: newColumnWidth
96
- }, sourceNode.type.name === 'layoutColumn' ? sourceNode.content : sourceNode);
97
- tr.insert(to, content);
119
+ let content = null;
120
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
121
+ if (sourceContent instanceof Fragment) {
122
+ var _sourceContent$firstC;
123
+ content = layoutColumn.createChecked({
124
+ width: newColumnWidth
125
+ }, isFragmentOfType(sourceContent, 'layoutColumn') ? (_sourceContent$firstC = sourceContent.firstChild) === null || _sourceContent$firstC === void 0 ? void 0 : _sourceContent$firstC.content : sourceContent);
126
+ }
127
+ } else {
128
+ if (sourceContent instanceof PMNode) {
129
+ content = layoutColumn.createChecked({
130
+ width: newColumnWidth
131
+ }, sourceContent.type.name === 'layoutColumn' ? sourceContent.content : sourceContent);
132
+ }
133
+ }
134
+ if (content) {
135
+ tr.insert(to, content);
136
+ }
98
137
  if (!fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
99
138
  tr.setSelection(new NodeSelection(tr.doc.resolve(to))).scrollIntoView();
100
139
  }
@@ -126,20 +165,103 @@ const canMoveToLayout = (from, to, tr) => {
126
165
  return;
127
166
  }
128
167
  const $from = tr.doc.resolve(from);
168
+ const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
169
+ exposure: true
170
+ });
129
171
 
130
172
  // invalid from position or dragging a layout
131
173
  if (!$from.nodeAfter || $from.nodeAfter.type === layoutSection) {
132
174
  return;
133
175
  }
176
+ let sourceContent = $from.nodeAfter;
177
+ let sourceFrom = from;
178
+ let sourceTo = from + sourceContent.nodeSize;
179
+ if (isMultiSelect) {
180
+ var _tr$selection$$from$n;
181
+ // Selection often starts from the content of the node (e.g. to show text selection properly),
182
+ // so we need to trace back to the start of the node instead
183
+ const 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();
184
+
185
+ // If the handle position sits within the Editor selection, we will move all nodes that sit in that selection
186
+ // handle position is the same as `from` position
187
+ const useSelection = from >= contentStartPos && from <= tr.selection.to;
188
+ if (useSelection) {
189
+ sourceFrom = contentStartPos;
190
+ sourceTo = tr.selection.to;
191
+ sourceContent = tr.doc.slice(sourceFrom, sourceTo).content;
192
+
193
+ // TODO: this might become expensive for large content, consider removing it if check has been done beforehand
194
+ if (containsNodeOfType(sourceContent, 'layoutSection')) {
195
+ return;
196
+ }
197
+ } else {
198
+ sourceContent = Fragment.from($from.nodeAfter);
199
+ }
200
+ }
134
201
  const toNode = $to.nodeAfter;
135
- const fromNode = $from.nodeAfter;
136
202
  return {
137
203
  toNode,
138
- fromNode,
139
- $from,
140
- $to
204
+ $to,
205
+ sourceContent,
206
+ $sourceFrom: tr.doc.resolve(sourceFrom),
207
+ sourceTo
141
208
  };
142
209
  };
210
+ const removeBreakoutMarks = (tr, $from, to) => {
211
+ let fromContentWithoutBreakout = $from.nodeAfter;
212
+ const {
213
+ breakout
214
+ } = tr.doc.type.schema.marks || {};
215
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
216
+ tr.doc.nodesBetween($from.pos, to, (node, pos, parent) => {
217
+ // breakout doesn't exist on nested nodes
218
+ if ((parent === null || parent === void 0 ? void 0 : parent.type.name) === 'doc' && node.marks.some(m => m.type === breakout)) {
219
+ tr.removeNodeMark(pos, breakout);
220
+ }
221
+
222
+ // descending is not needed as breakout doesn't exist on nested nodes
223
+ return false;
224
+ });
225
+ // resolve again the source content after node updated (remove breakout marks)
226
+ fromContentWithoutBreakout = tr.doc.slice($from.pos, to).content;
227
+ } else {
228
+ if (breakout && $from.nodeAfter && $from.nodeAfter.marks.some(m => m.type === breakout)) {
229
+ tr.removeNodeMark($from.pos, breakout);
230
+ // resolve again the source node after node updated (remove breakout marks)
231
+ fromContentWithoutBreakout = tr.doc.resolve($from.pos).nodeAfter;
232
+ }
233
+ }
234
+ return fromContentWithoutBreakout;
235
+ };
236
+ const getBreakoutMode = (content, breakout) => {
237
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
238
+ if (content instanceof PMNode) {
239
+ var _content$marks$find;
240
+ return (_content$marks$find = content.marks.find(m => m.type === breakout)) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs;
241
+ } else if (content instanceof Fragment) {
242
+ // Find the first breakout mode in the fragment
243
+ let firstBreakoutMode;
244
+ for (let i = 0; i < content.childCount; i++) {
245
+ const child = content.child(i);
246
+ const breakoutMark = child.marks.find(m => m.type === breakout);
247
+ if (breakoutMark) {
248
+ firstBreakoutMode = breakoutMark.attrs.mode;
249
+ break;
250
+ }
251
+ }
252
+ return firstBreakoutMode;
253
+ }
254
+ } else {
255
+ // Without multi-select support, we can assume source content is of type PMNode
256
+ if (content instanceof PMNode) {
257
+ var _content$marks$find2;
258
+ return (_content$marks$find2 = content.marks.find(m => m.type === breakout)) === null || _content$marks$find2 === void 0 ? void 0 : _content$marks$find2.attrs.mode;
259
+ }
260
+ }
261
+ };
262
+
263
+ // TODO: As part of platform_editor_element_drag_and_drop_multiselect clean up,
264
+ // source content variable that has type of `PMNode | Fragment` should be updated to `Fragment` only
143
265
  export const moveToLayout = api => (from, to, options) => ({
144
266
  tr
145
267
  }) => {
@@ -149,9 +271,10 @@ export const moveToLayout = api => (from, to, options) => ({
149
271
  }
150
272
  const {
151
273
  toNode,
152
- fromNode,
153
- $from,
154
- $to
274
+ $to,
275
+ sourceContent,
276
+ $sourceFrom,
277
+ sourceTo
155
278
  } = canMove;
156
279
  const {
157
280
  layoutSection,
@@ -160,32 +283,24 @@ export const moveToLayout = api => (from, to, options) => ({
160
283
  const {
161
284
  breakout
162
285
  } = tr.doc.type.schema.marks || {};
163
- let fromNodeWithoutBreakout = fromNode;
164
- const getBreakoutMode = node => {
165
- var _node$marks$find;
166
- return (_node$marks$find = node.marks.find(m => m.type === breakout)) === null || _node$marks$find === void 0 ? void 0 : _node$marks$find.attrs.mode;
167
- };
286
+
168
287
  // get breakout mode from destination node,
169
288
  // if not found, get from source node,
170
- const breakoutMode = getBreakoutMode(toNode) || getBreakoutMode(fromNode);
289
+ const breakoutMode = getBreakoutMode(toNode, breakout) || getBreakoutMode(sourceContent, breakout);
171
290
 
172
- // remove breakout from node;
173
- if (breakout && $from.nodeAfter && $from.nodeAfter.marks.some(m => m.type === breakout)) {
174
- tr.removeNodeMark(from, breakout);
175
- // resolve again the source node after node updated (remove breakout marks)
176
- fromNodeWithoutBreakout = tr.doc.resolve(from).nodeAfter;
177
- }
178
- if (!fromNodeWithoutBreakout) {
291
+ // remove breakout from source content
292
+ let fromContentWithoutBreakout = removeBreakoutMarks(tr, $sourceFrom, sourceTo);
293
+ if (!fromContentWithoutBreakout) {
179
294
  return tr;
180
295
  }
181
296
  if (toNode.type === layoutSection) {
182
297
  const toPos = options !== null && options !== void 0 && options.moveToEnd ? to + toNode.nodeSize - 1 : to + 1;
183
- return moveToExistingLayout(toNode, to, fromNodeWithoutBreakout, from, toPos, tr, $from, $to, api);
298
+ return moveToExistingLayout(toNode, to, fromContentWithoutBreakout, $sourceFrom.pos, toPos, tr, $sourceFrom, $to, api);
184
299
  } else if (toNode.type === layoutColumn) {
185
300
  const toLayout = $to.parent;
186
301
  const toLayoutPos = to - $to.parentOffset - 1;
187
302
  const toPos = options !== null && options !== void 0 && options.moveToEnd ? to + toNode.nodeSize : to;
188
- return moveToExistingLayout(toLayout, toLayoutPos, fromNodeWithoutBreakout, from, toPos, tr, $from, $to, api);
303
+ return moveToExistingLayout(toLayout, toLayoutPos, fromContentWithoutBreakout, $sourceFrom.pos, toPos, tr, $sourceFrom, $to, api);
189
304
  } else {
190
305
  let toNodeWithoutBreakout = toNode;
191
306
 
@@ -195,13 +310,19 @@ export const moveToLayout = api => (from, to, options) => ({
195
310
  // resolve again the source node after node updated (remove breakout marks)
196
311
  toNodeWithoutBreakout = tr.doc.resolve(to).nodeAfter || toNode;
197
312
  }
198
- if (fromNodeWithoutBreakout.type.name === 'layoutColumn') {
199
- fromNodeWithoutBreakout = fromNodeWithoutBreakout.content;
313
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
314
+ if (isFragmentOfType(fromContentWithoutBreakout, 'layoutColumn') && fromContentWithoutBreakout.firstChild) {
315
+ fromContentWithoutBreakout = fromContentWithoutBreakout.firstChild.content;
316
+ }
317
+ } else {
318
+ if (fromContentWithoutBreakout instanceof PMNode && fromContentWithoutBreakout.type.name === 'layoutColumn') {
319
+ fromContentWithoutBreakout = fromContentWithoutBreakout.content;
320
+ }
200
321
  }
201
- const layoutContents = options !== null && options !== void 0 && options.moveToEnd ? [toNodeWithoutBreakout, fromNodeWithoutBreakout] : [fromNodeWithoutBreakout, toNodeWithoutBreakout];
322
+ const layoutContents = options !== null && options !== void 0 && options.moveToEnd ? [toNodeWithoutBreakout, fromContentWithoutBreakout] : [fromContentWithoutBreakout, toNodeWithoutBreakout];
202
323
  const newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
203
324
  if (newLayout) {
204
- tr = removeFromSource(tr, $from);
325
+ tr = removeFromSource(tr, $sourceFrom, sourceTo);
205
326
  const mappedTo = tr.mapping.map(to);
206
327
  tr.delete(mappedTo, mappedTo + toNodeWithoutBreakout.nodeSize).insert(mappedTo, newLayout);
207
328
  if (!fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
@@ -19,10 +19,7 @@ export const shouldDescendIntoNode = node => {
19
19
  }
20
20
  return !IGNORE_NODE_DESCENDANTS.includes(node.type.name);
21
21
  };
22
- const shouldIgnoreNode = (node, ignore_nodes, depth, parent
23
- // Ignored via go/ees005
24
- // eslint-disable-next-line @typescript-eslint/max-params
25
- ) => {
22
+ const shouldIgnoreNode = (node, ignore_nodes, depth, parent) => {
26
23
  const isEmbedCard = node.type.name === 'embedCard';
27
24
  const isMediaSingle = node.type.name === 'mediaSingle';
28
25
  const isFirstTableRow = (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'table' && depth === 1 && node === parent.firstChild && 'tableRow' === node.type.name && editorExperiment('advanced_layouts', true);
@@ -64,8 +61,6 @@ export const nodeDecorations = (newState, from, to) => {
64
61
  const docFrom = from === undefined || from < 0 ? 0 : from;
65
62
  const docTo = to === undefined || to > newState.doc.nodeSize - 2 ? newState.doc.nodeSize - 2 : to;
66
63
  const ignore_nodes = editorExperiment('advanced_layouts', true) ? IGNORE_NODES_NEXT : IGNORE_NODES;
67
- // Ignored via go/ees005
68
- // eslint-disable-next-line @typescript-eslint/max-params
69
64
  newState.doc.nodesBetween(docFrom, docTo, (node, pos, parent, index) => {
70
65
  let depth = 0;
71
66
  let anchorName;
@@ -20,10 +20,7 @@ export const emptyParagraphNodeDecorations = () => {
20
20
  export const findHandleDec = (decorations, from, to) => {
21
21
  return decorations.find(from, to, spec => spec.type === TYPE_HANDLE_DEC);
22
22
  };
23
- export const dragHandleDecoration = (api, formatMessage, pos, anchorName, nodeType, nodeViewPortalProviderAPI, handleOptions
24
- // Ignored via go/ees005
25
- // eslint-disable-next-line @typescript-eslint/max-params
26
- ) => {
23
+ export const dragHandleDecoration = (api, formatMessage, pos, anchorName, nodeType, nodeViewPortalProviderAPI, handleOptions) => {
27
24
  unmountDecorations(nodeViewPortalProviderAPI, 'data-blocks-drag-handle-container', 'data-blocks-drag-handle-key');
28
25
  let unbind;
29
26
  const key = uuid();
@@ -10,7 +10,6 @@ import { DropTarget, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONT
10
10
  import { DropTargetLayout } from '../ui/drop-target-layout';
11
11
  import { getNestedDepth, TYPE_DROP_TARGET_DEC, unmountDecorations } from './decorations-common';
12
12
  import { maxLayoutColumnSupported } from './utils/consts';
13
- import { isBlocksDragTargetDebug } from './utils/drag-target-debug';
14
13
  import { canMoveNodeToIndex, isInSameLayout } from './utils/validation';
15
14
  const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'layoutColumn', 'listItem', 'caption'];
16
15
  const PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
@@ -72,10 +71,7 @@ const getGapAndOffset = (prevNode, nextNode, parentNode) => {
72
71
  export const findDropTargetDecs = (decorations, from, to) => {
73
72
  return decorations.find(from, to, spec => spec.type === TYPE_DROP_TARGET_DEC);
74
73
  };
75
- export const createDropTargetDecoration = (pos, props, nodeViewPortalProviderAPI, side, anchorRectCache, isSameLayout
76
- // Ignored via go/ees005
77
- // eslint-disable-next-line @typescript-eslint/max-params
78
- ) => {
74
+ export const createDropTargetDecoration = (pos, props, nodeViewPortalProviderAPI, side, anchorRectCache, isSameLayout) => {
79
75
  const key = uuid();
80
76
  return Decoration.widget(pos, (_, getPosUnsafe) => {
81
77
  const getPos = () => {
@@ -117,10 +113,7 @@ export const createDropTargetDecoration = (pos, props, nodeViewPortalProviderAPI
117
113
  side
118
114
  });
119
115
  };
120
- export const createLayoutDropTargetDecoration = (pos, props, nodeViewPortalProviderAPI, anchorRectCache
121
- // Ignored via go/ees005
122
- // eslint-disable-next-line @typescript-eslint/max-params
123
- ) => {
116
+ export const createLayoutDropTargetDecoration = (pos, props, nodeViewPortalProviderAPI, anchorRectCache) => {
124
117
  const key = uuid();
125
118
  return Decoration.widget(pos, (_, getPosUnsafe) => {
126
119
  const getPos = () => {
@@ -152,10 +145,7 @@ export const createLayoutDropTargetDecoration = (pos, props, nodeViewPortalProvi
152
145
  type: TYPE_DROP_TARGET_DEC
153
146
  });
154
147
  };
155
- export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPortalProviderAPI, activeNode, anchorRectCache, from, to
156
- // Ignored via go/ees005
157
- // eslint-disable-next-line @typescript-eslint/max-params
158
- ) => {
148
+ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPortalProviderAPI, activeNode, anchorRectCache, from, to) => {
159
149
  unmountDecorations(nodeViewPortalProviderAPI, 'data-blocks-drop-target-container', 'data-blocks-drop-target-key');
160
150
  const decs = [];
161
151
  const POS_END_OF_DOC = newState.doc.nodeSize - 2;
@@ -179,9 +169,6 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
179
169
  prevNodeStack.push(node);
180
170
  };
181
171
  const isAdvancedLayoutsPreRelease2 = editorExperiment('advanced_layouts', true);
182
-
183
- // Ignored via go/ees005
184
- // eslint-disable-next-line @typescript-eslint/max-params
185
172
  newState.doc.nodesBetween(docFrom, docTo, (node, pos, parent, index) => {
186
173
  let depth = 0;
187
174
  // drop target deco at the end position
@@ -216,7 +203,7 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
216
203
  const canDrop = activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $pos, node);
217
204
 
218
205
  //NOTE: This will block drop targets showing for nodes that are valid after transformation (i.e. expand -> nestedExpand)
219
- if (!canDrop && !isBlocksDragTargetDebug()) {
206
+ if (!canDrop) {
220
207
  pushNodeStack(node, depth);
221
208
  return false; //not valid pos, so nested not valid either
222
209
  }
@@ -19,7 +19,6 @@ import { handleMouseOver } from './handle-mouse-over';
19
19
  import { boundKeydownHandler } from './keymap';
20
20
  import { defaultActiveAnchorTracker } from './utils/active-anchor-tracker';
21
21
  import { AnchorRectCache, isAnchorSupported } from './utils/anchor-utils';
22
- import { isBlocksDragTargetDebug } from './utils/drag-target-debug';
23
22
  import { getTrMetadata } from './utils/transactions';
24
23
  export const key = new PluginKey('blockControls');
25
24
  const EDITOR_BLOCKS_DRAG_INIT = 'Editor Blocks Drag Initialization Time';
@@ -114,10 +113,7 @@ const initialState = {
114
113
  isDocSizeLimitEnabled: null,
115
114
  isPMDragging: false
116
115
  };
117
- export const newApply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache
118
- // Ignored via go/ees005
119
- // eslint-disable-next-line @typescript-eslint/max-params
120
- ) => {
116
+ export const newApply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) => {
121
117
  var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging;
122
118
  let {
123
119
  activeNode,
@@ -219,14 +215,14 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
219
215
  const isDropTargetsMissing = ((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && maybeNodeCountChanged && !(meta !== null && meta !== void 0 && meta.nodeMoved);
220
216
 
221
217
  // Remove drop target decorations when dragging stops or they need to be redrawn
222
- if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || isDropTargetsMissing || isBlocksDragTargetDebug()) {
218
+ if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || isDropTargetsMissing) {
223
219
  const dropTargetDecs = findDropTargetDecs(decorations);
224
220
  decorations = decorations.remove(dropTargetDecs);
225
221
  }
226
222
 
227
223
  // Add drop targets when dragging starts or some are missing
228
224
  if (api) {
229
- if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing || isBlocksDragTargetDebug()) {
225
+ if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing) {
230
226
  const decs = dropTargetDecorations(newState, api, formatMessage, nodeViewPortalProviderAPI, latestActiveNode, anchorRectCache);
231
227
  decorations = decorations.add(newState.doc, decs);
232
228
  }
@@ -252,10 +248,7 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
252
248
  isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging
253
249
  };
254
250
  };
255
- export const oldApply = (api, formatMessage, tr, currentState, oldState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache
256
- // Ignored via go/ees005
257
- // eslint-disable-next-line @typescript-eslint/max-params
258
- ) => {
251
+ export const oldApply = (api, formatMessage, tr, currentState, oldState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) => {
259
252
  var _meta$activeNode2, _meta$activeNode$hand2, _meta$activeNode8, _meta$isDragging4, _meta$editorHeight2, _meta$editorWidthLeft2, _meta$editorWidthRigh2, _meta$isPMDragging2;
260
253
  const {
261
254
  isNestedEnabled
@@ -355,7 +348,7 @@ export const oldApply = (api, formatMessage, tr, currentState, oldState, newStat
355
348
  const decs = dragHandleDecoration(api, formatMessage, meta.activeNode.pos, meta.activeNode.anchorName, meta.activeNode.nodeType, nodeViewPortalProviderAPI, meta.activeNode.handleOptions);
356
349
  decorations = decorations.add(newState.doc, [decs]);
357
350
  }
358
- if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || isDropTargetsMissing || isBlocksDragTargetDebug()) {
351
+ if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || isDropTargetsMissing) {
359
352
  // Remove drop target decoration when dragging stops
360
353
  const dropTargetDecs = decorations.find(undefined, undefined, spec => spec.type === 'drop-target-decoration');
361
354
  decorations = decorations.remove(dropTargetDecs);
@@ -371,7 +364,7 @@ export const oldApply = (api, formatMessage, tr, currentState, oldState, newStat
371
364
  if (api) {
372
365
  // Add drop targets when node is being dragged
373
366
  // if the transaction is only for analytics and user is dragging, continue to draw drop targets
374
- if (shouldCreateDropTargets || isBlocksDragTargetDebug()) {
367
+ if (shouldCreateDropTargets) {
375
368
  var _meta$activeNode7;
376
369
  const decs = dropTargetDecorations(newState, api, formatMessage, nodeViewPortalProviderAPI, isNestedEnabled ? (_meta$activeNode7 = meta === null || meta === void 0 ? void 0 : meta.activeNode) !== null && _meta$activeNode7 !== void 0 ? _meta$activeNode7 : mappedActiveNodePos : meta === null || meta === void 0 ? void 0 : meta.activeNode, anchorRectCache);
377
370
  decorations = decorations.add(newState.doc, decs);
@@ -421,8 +414,6 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
421
414
  init() {
422
415
  return initialState;
423
416
  },
424
- // Ignored via go/ees005
425
- // eslint-disable-next-line @typescript-eslint/max-params
426
417
  apply(tr, currentState, oldState, newState) {
427
418
  if (isNestedEnabled) {
428
419
  return newApply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache);