@atlaskit/editor-plugin-block-controls 3.16.2 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 3.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#166327](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/166327)
8
+ [`56ba43df67f02`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/56ba43df67f02) -
9
+ ED-28157 implment reduced drop target logic
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 3.16.2
4
16
 
5
17
  ### Patch Changes
@@ -182,7 +182,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
182
182
  }
183
183
  },
184
184
  getSharedState: function getSharedState(editorState) {
185
- var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$activeN, _key$getState3, _key$getState$isDragg, _key$getState4, _key$getState$isPMDra, _key$getState5, _key$getState$multiSe, _key$getState6, _key$getState$isShift, _key$getState7, _key$getState$lastDra, _key$getState8, _interactionTrackingP, _key$getState$isSelec, _key$getState9;
185
+ var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$activeN, _key$getState3, _key$getState$activeD, _key$getState4, _key$getState$isDragg, _key$getState5, _key$getState$isPMDra, _key$getState6, _key$getState$multiSe, _key$getState7, _key$getState$isShift, _key$getState8, _key$getState$lastDra, _key$getState9, _interactionTrackingP, _key$getState$isSelec, _key$getState0;
186
186
  if (!editorState) {
187
187
  return undefined;
188
188
  }
@@ -190,13 +190,14 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
190
190
  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,
191
191
  menuTriggerBy: (_key$getState$menuTri = (_key$getState2 = _main.key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.menuTriggerBy) !== null && _key$getState$menuTri !== void 0 ? _key$getState$menuTri : undefined,
192
192
  activeNode: (_key$getState$activeN = (_key$getState3 = _main.key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
193
- isDragging: (_key$getState$isDragg = (_key$getState4 = _main.key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
194
- isPMDragging: (_key$getState$isPMDra = (_key$getState5 = _main.key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
195
- multiSelectDnD: (_key$getState$multiSe = (_key$getState6 = _main.key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
196
- isShiftDown: (_key$getState$isShift = (_key$getState7 = _main.key.getState(editorState)) === null || _key$getState7 === void 0 ? void 0 : _key$getState7.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined,
197
- lastDragCancelled: (_key$getState$lastDra = (_key$getState8 = _main.key.getState(editorState)) === null || _key$getState8 === void 0 ? void 0 : _key$getState8.lastDragCancelled) !== null && _key$getState$lastDra !== void 0 ? _key$getState$lastDra : false,
193
+ activeDropTargetNode: (_key$getState$activeD = (_key$getState4 = _main.key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.activeDropTargetNode) !== null && _key$getState$activeD !== void 0 ? _key$getState$activeD : undefined,
194
+ isDragging: (_key$getState$isDragg = (_key$getState5 = _main.key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
195
+ isPMDragging: (_key$getState$isPMDra = (_key$getState6 = _main.key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
196
+ multiSelectDnD: (_key$getState$multiSe = (_key$getState7 = _main.key.getState(editorState)) === null || _key$getState7 === void 0 ? void 0 : _key$getState7.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
197
+ isShiftDown: (_key$getState$isShift = (_key$getState8 = _main.key.getState(editorState)) === null || _key$getState8 === void 0 ? void 0 : _key$getState8.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined,
198
+ lastDragCancelled: (_key$getState$lastDra = (_key$getState9 = _main.key.getState(editorState)) === null || _key$getState9 === void 0 ? void 0 : _key$getState9.lastDragCancelled) !== null && _key$getState$lastDra !== void 0 ? _key$getState$lastDra : false,
198
199
  isEditing: (_interactionTrackingP = _pmPlugin.interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
199
- isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState9 = _main.key.getState(editorState)) === null || _key$getState9 === void 0 ? void 0 : _key$getState9.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
200
+ isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState0 = _main.key.getState(editorState)) === null || _key$getState0 === void 0 ? void 0 : _key$getState0.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
200
201
  };
201
202
  },
202
203
  contentComponent: function contentComponent(_ref8) {
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getActiveDropTargetDecorations = exports.canMoveNodeOrSliceToPos = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
8
+ var _utils = require("@atlaskit/editor-common/utils");
9
+ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
10
+ var _decorationsCommon = require("./decorations-common");
11
+ var _decorationsDropTarget = require("./decorations-drop-target");
12
+ var _decorationsFindSurroundingNodes = require("./decorations-find-surrounding-nodes");
13
+ var _activeAnchorTracker = require("./utils/active-anchor-tracker");
14
+ var _validation = require("./utils/validation");
15
+ /**
16
+ * List of parent node types that can have child nodes
17
+ */
18
+ var PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
19
+
20
+ /**
21
+ * List of node types that does not allow drop targets at before or after the node.
22
+ */
23
+ var NODE_WITH_NO_PARENT_POS = ['tableCell', 'tableHeader', 'layoutColumn'];
24
+ var isContainerNode = function isContainerNode(node) {
25
+ return PARENT_WITH_END_DROP_TARGET.includes(node.type.name);
26
+ };
27
+ var canMoveNodeOrSliceToPos = exports.canMoveNodeOrSliceToPos = function canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode) {
28
+ // For deciding to show drop targets or not when multiple nodes are selected
29
+ var selection = state.selection;
30
+ var _expandSelectionBound = (0, _selection.expandSelectionBounds)(selection.$anchor, selection.$head),
31
+ expandedAnchor = _expandSelectionBound.$anchor,
32
+ expandedHead = _expandSelectionBound.$head;
33
+ var selectionFrom = Math.min(expandedAnchor.pos, expandedHead.pos);
34
+ var selectionTo = Math.max(expandedAnchor.pos, expandedHead.pos);
35
+ var activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
36
+ var $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
37
+ var activePMNode = $activeNodePos && $activeNodePos.nodeAfter;
38
+ var handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
39
+ if ((0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true)) {
40
+ var selectionSlice = state.doc.slice(selectionFrom, selectionTo, false);
41
+ var selectionSliceChildCount = selectionSlice.content.childCount;
42
+ var canDropSingleNode = true;
43
+ var canDropMultipleNodes = true;
44
+
45
+ // when there is only one node in the slice, use the same logic as when multi select is not on
46
+ if (selectionSliceChildCount > 1 && handleInsideSelection) {
47
+ canDropMultipleNodes = (0, _validation.canMoveSliceToIndex)(selectionSlice, selectionFrom, selectionTo, parent, index, $toPos);
48
+ } else {
49
+ canDropSingleNode = !!(activePMNode && (0, _validation.canMoveNodeToIndex)(parent, index, activePMNode, $toPos, node));
50
+ }
51
+ if (!canDropMultipleNodes || !canDropSingleNode) {
52
+ return false;
53
+ }
54
+ } else {
55
+ var canDrop = activePMNode && (0, _validation.canMoveNodeToIndex)(parent, index, activePMNode, $toPos, node);
56
+ return canDrop;
57
+ }
58
+ return true;
59
+ };
60
+ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = function getActiveDropTargetDecorations(activeDropTargetNode, state, api, formatMessage, nodeViewPortalProviderAPI, activeNode) {
61
+ (0, _decorationsCommon.unmountDecorations)(nodeViewPortalProviderAPI, 'data-blocks-drop-target-container', 'data-blocks-drop-target-key');
62
+ var decs = [];
63
+ var activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
64
+ var $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
65
+ var $toPos = state.doc.resolve(activeDropTargetNode.pos);
66
+ var _findSurroundingNodes = (0, _decorationsFindSurroundingNodes.findSurroundingNodes)(state, $toPos, activeDropTargetNode.nodeTypeName),
67
+ parent = _findSurroundingNodes.parent,
68
+ index = _findSurroundingNodes.index,
69
+ node = _findSurroundingNodes.node,
70
+ pos = _findSurroundingNodes.pos,
71
+ before = _findSurroundingNodes.before,
72
+ after = _findSurroundingNodes.after,
73
+ depth = _findSurroundingNodes.depth;
74
+
75
+ /**
76
+ * If the current node is a container node, we show the drop targets
77
+ * above the first child and below the last child.
78
+ */
79
+ if (isContainerNode(node)) {
80
+ // can move to before first child
81
+ if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(pos + 1),
82
+ // +1 to get the position of the first child
83
+ activeNode)) {
84
+ decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + 1, {
85
+ api: api,
86
+ prevNode: undefined,
87
+ nextNode: node.firstChild,
88
+ parentNode: node,
89
+ formatMessage: formatMessage,
90
+ dropTargetStyle: 'default'
91
+ }, nodeViewPortalProviderAPI, 1));
92
+ }
93
+
94
+ // can move to after last child
95
+ if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(pos + node.nodeSize - 1),
96
+ // -1 to get the position after last child
97
+ activeNode)) {
98
+ decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + node.nodeSize - 1, {
99
+ api: api,
100
+ prevNode: node.lastChild,
101
+ nextNode: undefined,
102
+ parentNode: node,
103
+ formatMessage: formatMessage,
104
+ dropTargetStyle: 'default'
105
+ }, nodeViewPortalProviderAPI, -1));
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Create drop target before and after the current node
111
+ */
112
+ if (!NODE_WITH_NO_PARENT_POS.includes(node.type.name)) {
113
+ var isSameLayout = $activeNodePos && (0, _validation.isInSameLayout)($activeNodePos, $toPos);
114
+ var isInSupportedContainer = ['tableCell', 'tableHeader', 'layoutColumn'].includes((parent === null || parent === void 0 ? void 0 : parent.type.name) || '');
115
+ var shouldShowFullHeight = isInSupportedContainer && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node && (0, _utils.isEmptyParagraph)(node);
116
+ if (canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode)) {
117
+ decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos, {
118
+ api: api,
119
+ prevNode: before || undefined,
120
+ nextNode: node,
121
+ parentNode: parent || undefined,
122
+ formatMessage: formatMessage,
123
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
124
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
125
+ }
126
+ if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(pos + node.nodeSize), activeNode)) {
127
+ decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + node.nodeSize, {
128
+ api: api,
129
+ prevNode: node,
130
+ nextNode: after || undefined,
131
+ parentNode: parent || undefined,
132
+ formatMessage: formatMessage,
133
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
134
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
135
+ }
136
+ }
137
+
138
+ // if the current node is not a top level node, we create one for advanced layout drop targets
139
+ if (depth > 1) {
140
+ var root = (0, _decorationsFindSurroundingNodes.findSurroundingNodes)(state, state.doc.resolve($toPos.before(2)));
141
+ decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(root.pos, {
142
+ api: api,
143
+ prevNode: root.before || undefined,
144
+ nextNode: root.node,
145
+ parentNode: state.doc || undefined,
146
+ formatMessage: formatMessage,
147
+ dropTargetStyle: 'default'
148
+ }, nodeViewPortalProviderAPI, 0, undefined, false));
149
+ _activeAnchorTracker.defaultActiveAnchorTracker.emit((0, _decorationsCommon.getNodeAnchor)(root.node));
150
+ } else {
151
+ _activeAnchorTracker.defaultActiveAnchorTracker.emit((0, _decorationsCommon.getNodeAnchor)(node));
152
+ }
153
+ return decs;
154
+ };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.findSurroundingNodes = void 0;
7
+ var IGNORE_NODES = ['tableRow', 'listItem', 'caption', 'media'];
8
+ var blockLeafNodes = ['blockCard', 'rule'];
9
+
10
+ /**
11
+ * This function returns the surrounding nodes of a given resolved position in the editor.
12
+ * It provides the position, node, parent, before and after nodes, index, and depth.
13
+ * @param state current editor state
14
+ * @param $pos a resolved position in the editor state.
15
+ * @returns {SurroundingNodes} An object containing the surrounding nodes information.
16
+ * @example
17
+ * const surroundingNodes = findSurroundingNodes(state, $pos);
18
+ */
19
+ var _findSurroundingNodes = exports.findSurroundingNodes = function findSurroundingNodes(state, $pos, nodeType) {
20
+ var depth = $pos.depth;
21
+
22
+ // special cases like hr rule here
23
+ if (blockLeafNodes.includes(nodeType || '') || $pos.pos === 0) {
24
+ var _parent = $pos.node(depth);
25
+ var _node = $pos.nodeAfter;
26
+ var _index = $pos.index();
27
+ var _before = _index > 0 ? _parent.child(_index - 1) : null;
28
+ var _after = _index < _parent.childCount - 1 ? _parent.child(_index + 1) : null;
29
+ return {
30
+ pos: $pos.pos,
31
+ node: _node,
32
+ parent: _parent,
33
+ before: _before,
34
+ after: _after,
35
+ index: _index,
36
+ depth: 1
37
+ };
38
+ }
39
+ var isRootNode = depth === 1;
40
+ var node = $pos.node(depth);
41
+ var isIgnoredNode = IGNORE_NODES.includes(node.type.name);
42
+ if (isIgnoredNode && !isRootNode) {
43
+ // If the node is an ignored node, we return the surrounding nodes of its parent
44
+ return _findSurroundingNodes(state, state.doc.resolve($pos.before(depth - 1)));
45
+ }
46
+ var pos = $pos.before(depth);
47
+ var parent = isRootNode ? state.doc : $pos.node(depth - 1);
48
+ var index = $pos.index(depth - 1);
49
+ var before = index > 0 ? parent.child(index - 1) : null;
50
+ var after = index < parent.childCount - 1 ? parent.child(index + 1) : null;
51
+ return {
52
+ pos: pos,
53
+ node: node,
54
+ parent: parent,
55
+ before: before,
56
+ after: after,
57
+ index: index,
58
+ depth: depth
59
+ };
60
+ };
@@ -14,16 +14,18 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
14
14
  var _ui = require("@atlaskit/editor-common/ui");
15
15
  var _utils = require("@atlaskit/editor-common/utils");
16
16
  var _state = require("@atlaskit/editor-prosemirror/state");
17
- var _view2 = require("@atlaskit/editor-prosemirror/view");
17
+ var _view = require("@atlaskit/editor-prosemirror/view");
18
18
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
19
19
  var _element = require("@atlaskit/pragmatic-drag-and-drop-auto-scroll/element");
20
20
  var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
21
21
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
22
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
22
23
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
23
24
  var _consts = require("../ui/consts");
24
25
  var _decorationsAnchor = require("./decorations-anchor");
25
26
  var _decorationsDragHandle = require("./decorations-drag-handle");
26
27
  var _decorationsDropTarget = require("./decorations-drop-target");
28
+ var _decorationsDropTargetActive = require("./decorations-drop-target-active");
27
29
  var _decorationsQuickInsertButton = require("./decorations-quick-insert-button");
28
30
  var _handleMouseDown = require("./handle-mouse-down");
29
31
  var _handleMouseOver = require("./handle-mouse-over");
@@ -206,7 +208,7 @@ var destroyFn = function destroyFn(api, editorView) {
206
208
  return _combine.combine.apply(void 0, cleanupFn);
207
209
  };
208
210
  var initialState = {
209
- decorations: _view2.DecorationSet.empty,
211
+ decorations: _view.DecorationSet.empty,
210
212
  activeNode: undefined,
211
213
  isDragging: false,
212
214
  isMenuOpen: false,
@@ -238,7 +240,7 @@ var getDecorationAtPos = function getDecorationAtPos(decorations, pos, to) {
238
240
  return nodeDecAtActivePos;
239
241
  };
240
242
  var _apply = exports.apply = function apply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
241
- var _meta$multiSelectDnD, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging, _meta$isDragging2, _meta$toggleMenu, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown, _meta$lastDragCancell;
243
+ var _meta$multiSelectDnD, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging2, _meta$isDragging3, _meta$toggleMenu, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown, _meta$lastDragCancell;
242
244
  var activeNode = currentState.activeNode,
243
245
  decorations = currentState.decorations,
244
246
  isResizerResizing = currentState.isResizerResizing,
@@ -307,7 +309,15 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
307
309
  var hasJustFinishedResizing = resizerMeta === false;
308
310
  multiSelectDnD = (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD;
309
311
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
310
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || tr.selection.empty ? undefined : multiSelectDnD;
312
+ var _meta$isDragging;
313
+ if (((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && (0, _expValEquals.expValEquals)('platform_editor_block_controls_perf_optimization', 'isEnabled', true)) {
314
+ // When dragging, we want to keep the multiSelectDnD object unless both document and selection
315
+ // has changed, in which case we want to reset it.
316
+ var shouldResetMultiSelectDnD = tr.docChanged && tr.selectionSet && tr.selection.empty;
317
+ multiSelectDnD = shouldResetMultiSelectDnD ? undefined : multiSelectDnD;
318
+ } else {
319
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || tr.selection.empty ? undefined : multiSelectDnD;
320
+ }
311
321
  }
312
322
  var maybeNodeCountChanged = !isAllText && numReplaceSteps > 0;
313
323
  var latestActiveNode;
@@ -322,7 +332,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
322
332
  }
323
333
 
324
334
  // Re-create node decorations
325
- var isDecSetEmpty = decorations === _view2.DecorationSet.empty;
335
+ var isDecSetEmpty = decorations === _view.DecorationSet.empty;
326
336
  var isNodeDecsMissing = isDecSetEmpty || maybeNodeCountChanged || (0, _experiments.editorExperiment)('platform_editor_breakout_resizing', true) && hasJustFinishedResizing;
327
337
  var shouldRedrawNodeDecs = !isResizerResizing && (isNodeDecsMissing || (meta === null || meta === void 0 ? void 0 : meta.isDragging));
328
338
  var isActiveNodeModified = false;
@@ -425,17 +435,26 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
425
435
  }
426
436
 
427
437
  // Drop targets may be missing when the node count is being changed during a drag
428
- var 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);
438
+ var isDropTargetsMissing = ((_meta$isDragging2 = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging2 !== void 0 ? _meta$isDragging2 : isDragging) && maybeNodeCountChanged && !(meta !== null && meta !== void 0 && meta.nodeMoved);
429
439
 
430
440
  // Remove drop target decorations when dragging stops or they need to be redrawn
431
441
  if ((meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || isDropTargetsMissing) {
432
442
  var dropTargetDecs = (0, _decorationsDropTarget.findDropTargetDecs)(decorations);
433
443
  decorations = decorations.remove(dropTargetDecs);
434
444
  }
435
-
436
- // Add drop targets when dragging starts or some are missing
445
+ var currentActiveDropTargetNode = isDragging ? currentState.activeDropTargetNode : undefined;
437
446
  if (api) {
438
- if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing) {
447
+ if ((0, _expValEquals.expValEquals)('platform_editor_block_controls_perf_optimization', 'isEnabled', true)) {
448
+ if (meta !== null && meta !== void 0 && meta.activeDropTargetNode) {
449
+ currentActiveDropTargetNode = meta === null || meta === void 0 ? void 0 : meta.activeDropTargetNode;
450
+ var decos = (0, _decorationsDropTargetActive.getActiveDropTargetDecorations)(meta.activeDropTargetNode, newState, api, formatMessage, nodeViewPortalProviderAPI, latestActiveNode);
451
+ decorations = decorations.remove((0, _decorationsDropTarget.findDropTargetDecs)(decorations));
452
+ if (decos.length > 0) {
453
+ decorations = decorations.add(newState.doc, decos);
454
+ }
455
+ }
456
+ } else if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing) {
457
+ // Add drop targets when dragging starts or some are missing
439
458
  var decs = (0, _decorationsDropTarget.dropTargetDecorations)(newState, api, formatMessage, nodeViewPortalProviderAPI, latestActiveNode, anchorRectCache);
440
459
  decorations = decorations.add(newState.doc, decs);
441
460
  }
@@ -471,7 +490,8 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
471
490
  return {
472
491
  decorations: decorations,
473
492
  activeNode: newActiveNode,
474
- isDragging: (_meta$isDragging2 = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging2 !== void 0 ? _meta$isDragging2 : isDragging,
493
+ activeDropTargetNode: currentActiveDropTargetNode,
494
+ isDragging: (_meta$isDragging3 = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging3 !== void 0 ? _meta$isDragging3 : isDragging,
475
495
  isMenuOpen: isMenuOpenNew,
476
496
  menuTriggerBy: (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (meta === null || meta === void 0 || (_meta$toggleMenu = meta.toggleMenu) === null || _meta$toggleMenu === void 0 ? void 0 : _meta$toggleMenu.anchorName) || menuTriggerBy : undefined,
477
497
  editorHeight: (_meta$editorHeight = meta === null || meta === void 0 ? void 0 : meta.editorHeight) !== null && _meta$editorHeight !== void 0 ? _meta$editorHeight : editorHeight,
@@ -570,8 +590,25 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
570
590
  }
571
591
  return false;
572
592
  },
573
- dragenter: function dragenter(_view, event) {
574
- if (isAdvancedLayoutEnabled) {
593
+ dragenter: function dragenter(view, event) {
594
+ if (isHTMLElement(event.target) && (0, _expValEquals.expValEquals)('platform_editor_block_controls_perf_optimization', 'isEnabled', true)) {
595
+ var targetElement = event.target.closest('[data-prosemirror-node-name]');
596
+ if (targetElement) {
597
+ var _api$blockControls$sh;
598
+ var nodeTypeName = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('data-prosemirror-node-name');
599
+ var pos = view.posAtDOM(targetElement, -1);
600
+ var currentActiveDropTargetNode = api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.activeDropTargetNode;
601
+ if ((currentActiveDropTargetNode === null || currentActiveDropTargetNode === void 0 ? void 0 : currentActiveDropTargetNode.pos) !== pos || (currentActiveDropTargetNode === null || currentActiveDropTargetNode === void 0 ? void 0 : currentActiveDropTargetNode.nodeTypeName) !== nodeTypeName) {
602
+ var activeDropTargetNode = {
603
+ pos: pos,
604
+ nodeTypeName: nodeTypeName
605
+ };
606
+ view.dispatch(view.state.tr.setMeta(key, {
607
+ activeDropTargetNode: activeDropTargetNode
608
+ }));
609
+ }
610
+ }
611
+ } else if (isAdvancedLayoutEnabled) {
575
612
  if (isHTMLElement(event.target)) {
576
613
  var closestParentElement = event.target.closest('[data-drag-handler-anchor-depth="0"]');
577
614
  if (closestParentElement) {
@@ -645,8 +682,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
645
682
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
646
683
  }
647
684
  if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5')) {
648
- var _api$blockControls$sh;
649
- if (api !== null && api !== void 0 && (_api$blockControls$sh = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh !== void 0 && _api$blockControls$sh.isSelectedViaDragHandle) {
685
+ var _api$blockControls$sh2;
686
+ if (api !== null && api !== void 0 && (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh2 !== void 0 && _api$blockControls$sh2.isSelectedViaDragHandle) {
650
687
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
651
688
  }
652
689
  }
@@ -682,8 +719,8 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
682
719
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(_isDragHandle));
683
720
  }
684
721
  if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5')) {
685
- var _api$blockControls$sh2;
686
- if (api !== null && api !== void 0 && (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh2 !== void 0 && _api$blockControls$sh2.isSelectedViaDragHandle) {
722
+ var _api$blockControls$sh3;
723
+ if (api !== null && api !== void 0 && (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh3 !== void 0 && _api$blockControls$sh3.isSelectedViaDragHandle) {
687
724
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
688
725
  }
689
726
  }
@@ -173,7 +173,7 @@ export const blockControlsPlugin = ({
173
173
  }
174
174
  },
175
175
  getSharedState(editorState) {
176
- var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$activeN, _key$getState3, _key$getState$isDragg, _key$getState4, _key$getState$isPMDra, _key$getState5, _key$getState$multiSe, _key$getState6, _key$getState$isShift, _key$getState7, _key$getState$lastDra, _key$getState8, _interactionTrackingP, _key$getState$isSelec, _key$getState9;
176
+ var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$activeN, _key$getState3, _key$getState$activeD, _key$getState4, _key$getState$isDragg, _key$getState5, _key$getState$isPMDra, _key$getState6, _key$getState$multiSe, _key$getState7, _key$getState$isShift, _key$getState8, _key$getState$lastDra, _key$getState9, _interactionTrackingP, _key$getState$isSelec, _key$getState0;
177
177
  if (!editorState) {
178
178
  return undefined;
179
179
  }
@@ -181,13 +181,14 @@ export const blockControlsPlugin = ({
181
181
  isMenuOpen: (_key$getState$isMenuO = (_key$getState = key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.isMenuOpen) !== null && _key$getState$isMenuO !== void 0 ? _key$getState$isMenuO : false,
182
182
  menuTriggerBy: (_key$getState$menuTri = (_key$getState2 = key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.menuTriggerBy) !== null && _key$getState$menuTri !== void 0 ? _key$getState$menuTri : undefined,
183
183
  activeNode: (_key$getState$activeN = (_key$getState3 = key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
184
- isDragging: (_key$getState$isDragg = (_key$getState4 = key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
185
- isPMDragging: (_key$getState$isPMDra = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
186
- multiSelectDnD: (_key$getState$multiSe = (_key$getState6 = key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
187
- isShiftDown: (_key$getState$isShift = (_key$getState7 = key.getState(editorState)) === null || _key$getState7 === void 0 ? void 0 : _key$getState7.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined,
188
- lastDragCancelled: (_key$getState$lastDra = (_key$getState8 = key.getState(editorState)) === null || _key$getState8 === void 0 ? void 0 : _key$getState8.lastDragCancelled) !== null && _key$getState$lastDra !== void 0 ? _key$getState$lastDra : false,
184
+ activeDropTargetNode: (_key$getState$activeD = (_key$getState4 = key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.activeDropTargetNode) !== null && _key$getState$activeD !== void 0 ? _key$getState$activeD : undefined,
185
+ isDragging: (_key$getState$isDragg = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
186
+ isPMDragging: (_key$getState$isPMDra = (_key$getState6 = key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
187
+ multiSelectDnD: (_key$getState$multiSe = (_key$getState7 = key.getState(editorState)) === null || _key$getState7 === void 0 ? void 0 : _key$getState7.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
188
+ isShiftDown: (_key$getState$isShift = (_key$getState8 = key.getState(editorState)) === null || _key$getState8 === void 0 ? void 0 : _key$getState8.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined,
189
+ lastDragCancelled: (_key$getState$lastDra = (_key$getState9 = key.getState(editorState)) === null || _key$getState9 === void 0 ? void 0 : _key$getState9.lastDragCancelled) !== null && _key$getState$lastDra !== void 0 ? _key$getState$lastDra : false,
189
190
  isEditing: (_interactionTrackingP = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
190
- isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState9 = key.getState(editorState)) === null || _key$getState9 === void 0 ? void 0 : _key$getState9.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
191
+ isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState0 = key.getState(editorState)) === null || _key$getState0 === void 0 ? void 0 : _key$getState0.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
191
192
  };
192
193
  },
193
194
  contentComponent({
@@ -0,0 +1,151 @@
1
+ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
2
+ import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
3
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
+ import { getNodeAnchor, unmountDecorations } from './decorations-common';
5
+ import { createDropTargetDecoration } from './decorations-drop-target';
6
+ import { findSurroundingNodes } from './decorations-find-surrounding-nodes';
7
+ import { defaultActiveAnchorTracker } from './utils/active-anchor-tracker';
8
+ import { canMoveNodeToIndex, canMoveSliceToIndex, isInSameLayout } from './utils/validation';
9
+
10
+ /**
11
+ * List of parent node types that can have child nodes
12
+ */
13
+ const PARENT_WITH_END_DROP_TARGET = ['tableCell', 'tableHeader', 'panel', 'layoutColumn', 'expand', 'nestedExpand', 'bodiedExtension'];
14
+
15
+ /**
16
+ * List of node types that does not allow drop targets at before or after the node.
17
+ */
18
+ const NODE_WITH_NO_PARENT_POS = ['tableCell', 'tableHeader', 'layoutColumn'];
19
+ const isContainerNode = node => {
20
+ return PARENT_WITH_END_DROP_TARGET.includes(node.type.name);
21
+ };
22
+ export const canMoveNodeOrSliceToPos = (state, node, parent, index, $toPos, activeNode) => {
23
+ // For deciding to show drop targets or not when multiple nodes are selected
24
+ const selection = state.selection;
25
+ const {
26
+ $anchor: expandedAnchor,
27
+ $head: expandedHead
28
+ } = expandSelectionBounds(selection.$anchor, selection.$head);
29
+ const selectionFrom = Math.min(expandedAnchor.pos, expandedHead.pos);
30
+ const selectionTo = Math.max(expandedAnchor.pos, expandedHead.pos);
31
+ const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
32
+ const $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
33
+ const activePMNode = $activeNodePos && $activeNodePos.nodeAfter;
34
+ const handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
35
+ if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
36
+ const selectionSlice = state.doc.slice(selectionFrom, selectionTo, false);
37
+ const selectionSliceChildCount = selectionSlice.content.childCount;
38
+ let canDropSingleNode = true;
39
+ let canDropMultipleNodes = true;
40
+
41
+ // when there is only one node in the slice, use the same logic as when multi select is not on
42
+ if (selectionSliceChildCount > 1 && handleInsideSelection) {
43
+ canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, selectionTo, parent, index, $toPos);
44
+ } else {
45
+ canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $toPos, node));
46
+ }
47
+ if (!canDropMultipleNodes || !canDropSingleNode) {
48
+ return false;
49
+ }
50
+ } else {
51
+ const canDrop = activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $toPos, node);
52
+ return canDrop;
53
+ }
54
+ return true;
55
+ };
56
+ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api, formatMessage, nodeViewPortalProviderAPI, activeNode) => {
57
+ unmountDecorations(nodeViewPortalProviderAPI, 'data-blocks-drop-target-container', 'data-blocks-drop-target-key');
58
+ const decs = [];
59
+ const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
60
+ const $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
61
+ const $toPos = state.doc.resolve(activeDropTargetNode.pos);
62
+ const {
63
+ parent,
64
+ index,
65
+ node,
66
+ pos,
67
+ before,
68
+ after,
69
+ depth
70
+ } = findSurroundingNodes(state, $toPos, activeDropTargetNode.nodeTypeName);
71
+
72
+ /**
73
+ * If the current node is a container node, we show the drop targets
74
+ * above the first child and below the last child.
75
+ */
76
+ if (isContainerNode(node)) {
77
+ // can move to before first child
78
+ if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(pos + 1),
79
+ // +1 to get the position of the first child
80
+ activeNode)) {
81
+ decs.push(createDropTargetDecoration(pos + 1, {
82
+ api,
83
+ prevNode: undefined,
84
+ nextNode: node.firstChild,
85
+ parentNode: node,
86
+ formatMessage,
87
+ dropTargetStyle: 'default'
88
+ }, nodeViewPortalProviderAPI, 1));
89
+ }
90
+
91
+ // can move to after last child
92
+ if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(pos + node.nodeSize - 1),
93
+ // -1 to get the position after last child
94
+ activeNode)) {
95
+ decs.push(createDropTargetDecoration(pos + node.nodeSize - 1, {
96
+ api,
97
+ prevNode: node.lastChild,
98
+ nextNode: undefined,
99
+ parentNode: node,
100
+ formatMessage,
101
+ dropTargetStyle: 'default'
102
+ }, nodeViewPortalProviderAPI, -1));
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Create drop target before and after the current node
108
+ */
109
+ if (!NODE_WITH_NO_PARENT_POS.includes(node.type.name)) {
110
+ const isSameLayout = $activeNodePos && isInSameLayout($activeNodePos, $toPos);
111
+ const isInSupportedContainer = ['tableCell', 'tableHeader', 'layoutColumn'].includes((parent === null || parent === void 0 ? void 0 : parent.type.name) || '');
112
+ const shouldShowFullHeight = isInSupportedContainer && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node && isEmptyParagraph(node);
113
+ if (canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode)) {
114
+ decs.push(createDropTargetDecoration(pos, {
115
+ api,
116
+ prevNode: before || undefined,
117
+ nextNode: node,
118
+ parentNode: parent || undefined,
119
+ formatMessage,
120
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
121
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
122
+ }
123
+ if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(pos + node.nodeSize), activeNode)) {
124
+ decs.push(createDropTargetDecoration(pos + node.nodeSize, {
125
+ api,
126
+ prevNode: node,
127
+ nextNode: after || undefined,
128
+ parentNode: parent || undefined,
129
+ formatMessage,
130
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
131
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
132
+ }
133
+ }
134
+
135
+ // if the current node is not a top level node, we create one for advanced layout drop targets
136
+ if (depth > 1) {
137
+ const root = findSurroundingNodes(state, state.doc.resolve($toPos.before(2)));
138
+ decs.push(createDropTargetDecoration(root.pos, {
139
+ api,
140
+ prevNode: root.before || undefined,
141
+ nextNode: root.node,
142
+ parentNode: state.doc || undefined,
143
+ formatMessage,
144
+ dropTargetStyle: 'default'
145
+ }, nodeViewPortalProviderAPI, 0, undefined, false));
146
+ defaultActiveAnchorTracker.emit(getNodeAnchor(root.node));
147
+ } else {
148
+ defaultActiveAnchorTracker.emit(getNodeAnchor(node));
149
+ }
150
+ return decs;
151
+ };