@atlaskit/editor-plugin-block-controls 3.19.4 → 3.19.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 3.19.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#172583](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/172583)
8
+ [`40f387a0c0962`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/40f387a0c0962) -
9
+ Clean up platform_editor_controls_patch_2
10
+ - Updated dependencies
11
+
12
+ ## 3.19.5
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies
17
+
3
18
  ## 3.19.4
4
19
 
5
20
  ### Patch Changes
@@ -59,14 +59,20 @@ var canMoveNodeOrSliceToPos = exports.canMoveNodeOrSliceToPos = function canMove
59
59
  }
60
60
  return true;
61
61
  };
62
- var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = function getActiveDropTargetDecorations(activeDropTargetNode, state, api, formatMessage, nodeViewPortalProviderAPI, activeNode) {
62
+ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = function getActiveDropTargetDecorations(activeDropTargetNode, state, api, existingDecs, formatMessage, nodeViewPortalProviderAPI, activeNode) {
63
63
  if (!(0, _platformFeatureFlags.fg)('platform_editor_block_controls_drop_target_mem_fix')) {
64
64
  (0, _decorationsCommon.unmountDecorations)(nodeViewPortalProviderAPI, 'data-blocks-drop-target-container', 'data-blocks-drop-target-key');
65
65
  }
66
- var decs = [];
66
+ var decsToAdd = [];
67
+ var decsToRemove = existingDecs.filter(function (dec) {
68
+ return !!dec;
69
+ });
67
70
  var activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
68
71
  var $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
69
72
  var $toPos = state.doc.resolve(activeDropTargetNode.pos);
73
+ var existingDecsPos = decsToRemove.map(function (dec) {
74
+ return dec.from;
75
+ });
70
76
  var _findSurroundingNodes = (0, _decorationsFindSurroundingNodes.findSurroundingNodes)(state, $toPos, activeDropTargetNode.nodeTypeName),
71
77
  parent = _findSurroundingNodes.parent,
72
78
  index = _findSurroundingNodes.index,
@@ -81,32 +87,52 @@ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = fu
81
87
  * above the first child and below the last child.
82
88
  */
83
89
  if (isContainerNode(node)) {
90
+ var isEmptyContainer = node.childCount === 0 || node.childCount === 1 && (0, _utils.isEmptyParagraph)(node.firstChild);
91
+
84
92
  // can move to before first child
85
- if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(pos + 1),
86
- // +1 to get the position of the first child
87
- activeNode)) {
88
- decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + 1, {
89
- api: api,
90
- prevNode: undefined,
91
- nextNode: node.firstChild,
92
- parentNode: node,
93
- formatMessage: formatMessage,
94
- dropTargetStyle: 'default'
95
- }, nodeViewPortalProviderAPI, 1));
93
+ var posBeforeFirstChild = pos + 1; // +1 to get the position of the first child
94
+ if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(posBeforeFirstChild), activeNode)) {
95
+ if (existingDecsPos.includes(posBeforeFirstChild)) {
96
+ // if the decoration already exists, we don't add it again.
97
+ decsToRemove = decsToRemove.filter(function (dec) {
98
+ return dec.from !== posBeforeFirstChild;
99
+ });
100
+ } else {
101
+ decsToAdd.push((0, _decorationsDropTarget.createDropTargetDecoration)(posBeforeFirstChild, {
102
+ api: api,
103
+ prevNode: undefined,
104
+ nextNode: node.firstChild,
105
+ parentNode: node,
106
+ formatMessage: formatMessage,
107
+ dropTargetStyle: isEmptyContainer ? 'remainingHeight' : 'default'
108
+ }, nodeViewPortalProviderAPI, 1));
109
+ }
96
110
  }
97
111
 
98
112
  // can move to after last child
99
- if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(pos + node.nodeSize - 1),
100
- // -1 to get the position after last child
101
- activeNode)) {
102
- decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + node.nodeSize - 1, {
103
- api: api,
104
- prevNode: node.lastChild,
105
- nextNode: undefined,
106
- parentNode: node,
107
- formatMessage: formatMessage,
108
- dropTargetStyle: 'default'
109
- }, nodeViewPortalProviderAPI, -1));
113
+ // if the node is empty, we don't show the drop target at the end of the node
114
+ if (!isEmptyContainer) {
115
+ var posAfterLastChild = pos + node.nodeSize - 1; // -1 to get the position after last child
116
+
117
+ if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(posAfterLastChild),
118
+ // -1 to get the position after last child
119
+ activeNode)) {
120
+ if (existingDecsPos.includes(posAfterLastChild)) {
121
+ // if the decoration already exists, we don't add it again.
122
+ decsToRemove = decsToRemove.filter(function (dec) {
123
+ return dec.from !== posAfterLastChild;
124
+ });
125
+ } else {
126
+ decsToAdd.push((0, _decorationsDropTarget.createDropTargetDecoration)(posAfterLastChild, {
127
+ api: api,
128
+ prevNode: node.lastChild,
129
+ nextNode: undefined,
130
+ parentNode: node,
131
+ formatMessage: formatMessage,
132
+ dropTargetStyle: 'remainingHeight'
133
+ }, nodeViewPortalProviderAPI, -1));
134
+ }
135
+ }
110
136
  }
111
137
  }
112
138
 
@@ -118,24 +144,41 @@ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = fu
118
144
  var isInSupportedContainer = ['tableCell', 'tableHeader', 'layoutColumn'].includes((parent === null || parent === void 0 ? void 0 : parent.type.name) || '');
119
145
  var shouldShowFullHeight = isInSupportedContainer && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node && (0, _utils.isEmptyParagraph)(node);
120
146
  if (canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode)) {
121
- decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos, {
122
- api: api,
123
- prevNode: before || undefined,
124
- nextNode: node,
125
- parentNode: parent || undefined,
126
- formatMessage: formatMessage,
127
- dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
128
- }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
147
+ if (existingDecsPos.includes(pos)) {
148
+ // if the decoration already exists, we don't add it again.
149
+ decsToRemove = decsToRemove.filter(function (dec) {
150
+ return dec.from !== pos;
151
+ });
152
+ } else {
153
+ decsToAdd.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos, {
154
+ api: api,
155
+ prevNode: before || undefined,
156
+ nextNode: node,
157
+ parentNode: parent || undefined,
158
+ formatMessage: formatMessage,
159
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
160
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
161
+ }
129
162
  }
130
- if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(pos + node.nodeSize), activeNode)) {
131
- decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(pos + node.nodeSize, {
132
- api: api,
133
- prevNode: node,
134
- nextNode: after || undefined,
135
- parentNode: parent || undefined,
136
- formatMessage: formatMessage,
137
- dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
138
- }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
163
+
164
+ // if the node is a container node, we show the drop target after the node
165
+ var posAfterNode = pos + node.nodeSize;
166
+ if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(posAfterNode), activeNode)) {
167
+ if (existingDecsPos.includes(posAfterNode)) {
168
+ // if the decoration already exists, we don't add it again.
169
+ decsToRemove = decsToRemove.filter(function (dec) {
170
+ return dec.from !== posAfterNode;
171
+ });
172
+ } else {
173
+ decsToAdd.push((0, _decorationsDropTarget.createDropTargetDecoration)(posAfterNode, {
174
+ api: api,
175
+ prevNode: node,
176
+ nextNode: after || undefined,
177
+ parentNode: parent || undefined,
178
+ formatMessage: formatMessage,
179
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
180
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
181
+ }
139
182
  }
140
183
  }
141
184
  var rootNodeWithPos = {
@@ -146,14 +189,21 @@ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = fu
146
189
  // if the current node is not a top level node, we create one for advanced layout drop targets
147
190
  if (depth > 1) {
148
191
  var root = (0, _decorationsFindSurroundingNodes.findSurroundingNodes)(state, state.doc.resolve($toPos.before(2)));
149
- decs.push((0, _decorationsDropTarget.createDropTargetDecoration)(root.pos, {
150
- api: api,
151
- prevNode: root.before || undefined,
152
- nextNode: root.node,
153
- parentNode: state.doc || undefined,
154
- formatMessage: formatMessage,
155
- dropTargetStyle: 'default'
156
- }, nodeViewPortalProviderAPI, 0, undefined, false));
192
+ if (existingDecsPos.includes(root.pos)) {
193
+ // if the decoration already exists, we don't add it again.
194
+ decsToRemove = decsToRemove.filter(function (dec) {
195
+ return dec.from !== root.pos;
196
+ });
197
+ } else {
198
+ decsToAdd.push((0, _decorationsDropTarget.createDropTargetDecoration)(root.pos, {
199
+ api: api,
200
+ prevNode: root.before || undefined,
201
+ nextNode: root.node,
202
+ parentNode: state.doc || undefined,
203
+ formatMessage: formatMessage,
204
+ dropTargetStyle: 'default'
205
+ }, nodeViewPortalProviderAPI, 0, undefined, false));
206
+ }
157
207
  rootNodeWithPos = {
158
208
  node: root.node,
159
209
  pos: root.pos
@@ -167,11 +217,19 @@ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = fu
167
217
  layoutSectionNode.descendants(function (childNode, childPos, parent, index) {
168
218
  if (childNode.type.name === 'layoutColumn' && (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutSection' && index !== 0 // Not the first node
169
219
  ) {
170
- decs.push((0, _decorationsDropTarget.createLayoutDropTargetDecoration)(rootNodeWithPos.pos + childPos + 1, {
171
- api: api,
172
- parent: parent,
173
- formatMessage: formatMessage
174
- }, nodeViewPortalProviderAPI, undefined));
220
+ var currentPos = rootNodeWithPos.pos + childPos + 1;
221
+ if (existingDecsPos.includes(currentPos)) {
222
+ // if the decoration already exists, we don't add it again.
223
+ decsToRemove = decsToRemove.filter(function (dec) {
224
+ return dec.from !== currentPos;
225
+ });
226
+ } else {
227
+ decsToAdd.push((0, _decorationsDropTarget.createLayoutDropTargetDecoration)(rootNodeWithPos.pos + childPos + 1, {
228
+ api: api,
229
+ parent: parent,
230
+ formatMessage: formatMessage
231
+ }, nodeViewPortalProviderAPI, undefined));
232
+ }
175
233
  }
176
234
  return false;
177
235
  });
@@ -179,5 +237,8 @@ var getActiveDropTargetDecorations = exports.getActiveDropTargetDecorations = fu
179
237
  }
180
238
  }
181
239
  _activeAnchorTracker.defaultActiveAnchorTracker.emit((0, _decorationsCommon.getNodeAnchor)(rootNodeWithPos.node));
182
- return decs;
240
+ return {
241
+ decsToAdd: decsToAdd,
242
+ decsToRemove: decsToRemove
243
+ };
183
244
  };
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.findSurroundingNodes = void 0;
7
7
  var IGNORE_NODES = ['tableRow', 'listItem', 'caption', 'media'];
8
8
  var blockLeafNodes = ['blockCard', 'rule'];
9
+ var DISABLE_CHILD_DROP_TARGET = ['orderedList', 'bulletList'];
9
10
 
10
11
  /**
11
12
  * This function returns the surrounding nodes of a given resolved position in the editor.
@@ -33,17 +34,25 @@ var _findSurroundingNodes = exports.findSurroundingNodes = function findSurround
33
34
  before: _before,
34
35
  after: _after,
35
36
  index: _index,
36
- depth: 1
37
+ depth: depth
37
38
  };
38
39
  }
39
40
  var isRootNode = depth === 1;
40
41
  var node = $pos.node(depth);
41
- var isIgnoredNode = IGNORE_NODES.includes(node.type.name);
42
- if (isIgnoredNode && !isRootNode) {
42
+
43
+ // go through the path to find the first node that is not allow child drop target
44
+ // From top to bottom, we check the node types at each depth
45
+ for (var i = 1; i < depth; i++) {
46
+ var _nodeType = $pos.node(i).type.name;
47
+ if (DISABLE_CHILD_DROP_TARGET.includes(_nodeType)) {
48
+ return _findSurroundingNodes(state, state.doc.resolve($pos.before(i + 1)), _nodeType);
49
+ }
50
+ }
51
+ if (IGNORE_NODES.includes(node.type.name) && !isRootNode) {
43
52
  // If the node is an ignored node, we return the surrounding nodes of its parent
44
53
  return _findSurroundingNodes(state, state.doc.resolve($pos.before(depth - 1)));
45
54
  }
46
- var pos = $pos.before(depth);
55
+ var pos = depth > 0 ? $pos.before(depth) : 0;
47
56
  var parent = isRootNode ? state.doc : $pos.node(depth - 1);
48
57
  var index = $pos.index(depth - 1);
49
58
  var before = index > 0 ? parent.child(index - 1) : null;
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.handleMouseDown = void 0;
7
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
7
  var handleMouseDown = exports.handleMouseDown = function handleMouseDown(api) {
9
8
  return function (view, event) {
10
9
  if (!(event.target instanceof HTMLElement)) {
@@ -20,7 +19,7 @@ var handleMouseDown = exports.handleMouseDown = function handleMouseDown(api) {
20
19
  return false;
21
20
  }
22
21
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.showDragHandleAt(rootPos, '', (_rootNode$type$name = rootNode.type.name) !== null && _rootNode$type$name !== void 0 ? _rootNode$type$name : '', undefined, rootPos, '', (_rootNode$type$name2 = rootNode.type.name) !== null && _rootNode$type$name2 !== void 0 ? _rootNode$type$name2 : ''));
23
- } else if ((0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5')) {
22
+ } else {
24
23
  var isDragHandle = event.target.closest('[data-editor-block-ctrl-drag-handle]') !== null;
25
24
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
26
25
  }
@@ -251,8 +251,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
251
251
  menuTriggerBy = currentState.menuTriggerBy,
252
252
  isPMDragging = currentState.isPMDragging,
253
253
  isShiftDown = currentState.isShiftDown,
254
- lastDragCancelled = currentState.lastDragCancelled,
255
- isSelectedViaDragHandle = currentState.isSelectedViaDragHandle;
254
+ lastDragCancelled = currentState.lastDragCancelled;
256
255
  var isActiveNodeDeleted = false;
257
256
  var _getTrMetadata = (0, _transactions.getTrMetadata)(tr),
258
257
  from = _getTrMetadata.from,
@@ -443,12 +442,21 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
443
442
  var currentActiveDropTargetNode = isDragging ? currentState.activeDropTargetNode : undefined;
444
443
  if (api) {
445
444
  if ((0, _expValEquals.expValEquals)('platform_editor_block_controls_perf_optimization', 'isEnabled', true)) {
445
+ // If page is updated while dragging (likely by remote updates), we simply remove the drop targets
446
+ // and add them back when the use interacts with the editor again
447
+ if (isDropTargetsMissing) {
448
+ var oldDropTargetDecs = (0, _decorationsDropTarget.findDropTargetDecs)(decorations);
449
+ decorations = decorations.remove(oldDropTargetDecs);
450
+ }
446
451
  if (meta !== null && meta !== void 0 && meta.activeDropTargetNode) {
447
452
  currentActiveDropTargetNode = meta === null || meta === void 0 ? void 0 : meta.activeDropTargetNode;
448
- var decos = (0, _decorationsDropTargetActive.getActiveDropTargetDecorations)(meta.activeDropTargetNode, newState, api, formatMessage, nodeViewPortalProviderAPI, latestActiveNode);
449
- decorations = decorations.remove((0, _decorationsDropTarget.findDropTargetDecs)(decorations));
450
- if (decos.length > 0) {
451
- decorations = decorations.add(newState.doc, decos);
453
+ var _oldDropTargetDecs = (0, _decorationsDropTarget.findDropTargetDecs)(decorations);
454
+ var _getActiveDropTargetD = (0, _decorationsDropTargetActive.getActiveDropTargetDecorations)(meta.activeDropTargetNode, newState, api, _oldDropTargetDecs, formatMessage, nodeViewPortalProviderAPI, latestActiveNode),
455
+ decsToAdd = _getActiveDropTargetD.decsToAdd,
456
+ decsToRemove = _getActiveDropTargetD.decsToRemove;
457
+ decorations = decorations.remove(decsToRemove);
458
+ if (decsToAdd.length > 0) {
459
+ decorations = decorations.add(newState.doc, decsToAdd);
452
460
  }
453
461
  }
454
462
  } else if (meta !== null && meta !== void 0 && meta.isDragging || isDropTargetsMissing) {
@@ -484,7 +492,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
484
492
  } else if (meta !== null && meta !== void 0 && meta.toggleMenu) {
485
493
  isMenuOpenNew = !isMenuOpen;
486
494
  }
487
- var isSelectedViaDragHandleNew = (meta === null || meta === void 0 ? void 0 : meta.isSelectedViaDragHandle) !== undefined && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5') ? meta === null || meta === void 0 ? void 0 : meta.isSelectedViaDragHandle : isSelectedViaDragHandle;
495
+ var isSelectedViaDragHandle = (meta === null || meta === void 0 ? void 0 : meta.isSelectedViaDragHandle) !== undefined && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (meta === null || meta === void 0 ? void 0 : meta.isSelectedViaDragHandle);
488
496
  return {
489
497
  decorations: decorations,
490
498
  activeNode: newActiveNode,
@@ -501,7 +509,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
501
509
  multiSelectDnD: multiSelectDnD,
502
510
  isShiftDown: (_meta$isShiftDown = meta === null || meta === void 0 ? void 0 : meta.isShiftDown) !== null && _meta$isShiftDown !== void 0 ? _meta$isShiftDown : isShiftDown,
503
511
  lastDragCancelled: (_meta$lastDragCancell = meta === null || meta === void 0 ? void 0 : meta.lastDragCancelled) !== null && _meta$lastDragCancell !== void 0 ? _meta$lastDragCancell : lastDragCancelled,
504
- isSelectedViaDragHandle: isSelectedViaDragHandleNew
512
+ isSelectedViaDragHandle: isSelectedViaDragHandle
505
513
  };
506
514
  };
507
515
  var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, nodeViewPortalProviderAPI) {
@@ -651,7 +659,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
651
659
  (0, _handleMouseOver.handleMouseOver)(view, event, api);
652
660
  return false;
653
661
  },
654
- mousedown: (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_2') ? (0, _handleMouseDown.handleMouseDown)(api) : undefined,
662
+ mousedown: (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _handleMouseDown.handleMouseDown)(api) : undefined,
655
663
  keydown: function keydown(view, event) {
656
664
  if (isMultiSelectEnabled) {
657
665
  if (event.shiftKey && event.ctrlKey) {
@@ -675,11 +683,11 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
675
683
  return true;
676
684
  }
677
685
  }
678
- if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5')) {
686
+ if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
679
687
  var isDragHandle = event.target.closest('[data-editor-block-ctrl-drag-handle="true"]') !== null;
680
688
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
681
689
  }
682
- 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')) {
690
+ if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
683
691
  var _api$blockControls$sh2;
684
692
  if (api !== null && api !== void 0 && (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh2 !== void 0 && _api$blockControls$sh2.isSelectedViaDragHandle) {
685
693
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
@@ -712,11 +720,11 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
712
720
  return true;
713
721
  }
714
722
  }
715
- if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_5')) {
723
+ if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
716
724
  var _isDragHandle = event.target.closest('[data-editor-block-ctrl-drag-handle="true"]') !== null;
717
725
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(_isDragHandle));
718
726
  }
719
- 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')) {
727
+ if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
720
728
  var _api$blockControls$sh3;
721
729
  if (api !== null && api !== void 0 && (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh3 !== void 0 && _api$blockControls$sh3.isSelectedViaDragHandle) {
722
730
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
@@ -609,7 +609,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
609
609
  var node = parentPos !== undefined ? view.state.doc.nodeAt(parentPos) : undefined;
610
610
  var parentNodeType = node === null || node === void 0 ? void 0 : node.type.name;
611
611
  var supportsAnchor = CSS.supports('top', "anchor(".concat(anchorName, " start)")) && CSS.supports('left', "anchor(".concat(anchorName, " start)"));
612
- var safeAnchorName = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_2') ? (0, _anchorName.refreshAnchorName)({
612
+ var safeAnchorName = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _anchorName.refreshAnchorName)({
613
613
  getPos: getPos,
614
614
  view: view,
615
615
  anchorName: anchorName
@@ -655,7 +655,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
655
655
  var node = parentPos !== undefined ? view.state.doc.nodeAt(parentPos) : undefined;
656
656
  var parentNodeType = node === null || node === void 0 ? void 0 : node.type.name;
657
657
  var supportsAnchor = CSS.supports('top', "anchor(".concat(anchorName, " start)")) && CSS.supports('left', "anchor(".concat(anchorName, " start)"));
658
- var safeAnchorName = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') && (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_2') ? (0, _anchorName.refreshAnchorName)({
658
+ var safeAnchorName = (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _anchorName.refreshAnchorName)({
659
659
  getPos: getPos,
660
660
  view: view,
661
661
  anchorName: anchorName
@@ -129,11 +129,11 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
129
129
  // CHANGES - `removed editorExperiment('advanced_layouts', true) && isLayoutColumn` checks as quick insert button will not be positioned for layout column
130
130
  var calculatePosition = (0, _react.useCallback)(function () {
131
131
  var supportsAnchor = CSS.supports('top', "anchor(".concat(rootAnchorName, " start)")) && CSS.supports('left', "anchor(".concat(rootAnchorName, " start)"));
132
- var safeAnchorName = (0, _platformFeatureFlags.fg)('platform_editor_controls_patch_2') ? (0, _anchorName.refreshAnchorName)({
132
+ var safeAnchorName = (0, _anchorName.refreshAnchorName)({
133
133
  getPos: getPos,
134
134
  view: view,
135
135
  anchorName: rootAnchorName
136
- }) : rootAnchorName;
136
+ });
137
137
  var dom = view.dom.querySelector("[data-drag-handler-anchor-name=\"".concat(safeAnchorName, "\"]"));
138
138
  var hasResizer = rootNodeType === 'table' || rootNodeType === 'mediaSingle';
139
139
  var isExtension = rootNodeType === 'extension' || rootNodeType === 'bodiedExtension';
@@ -55,14 +55,16 @@ export const canMoveNodeOrSliceToPos = (state, node, parent, index, $toPos, acti
55
55
  }
56
56
  return true;
57
57
  };
58
- export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api, formatMessage, nodeViewPortalProviderAPI, activeNode) => {
58
+ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api, existingDecs, formatMessage, nodeViewPortalProviderAPI, activeNode) => {
59
59
  if (!fg('platform_editor_block_controls_drop_target_mem_fix')) {
60
60
  unmountDecorations(nodeViewPortalProviderAPI, 'data-blocks-drop-target-container', 'data-blocks-drop-target-key');
61
61
  }
62
- const decs = [];
62
+ const decsToAdd = [];
63
+ let decsToRemove = existingDecs.filter(dec => !!dec);
63
64
  const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
64
65
  const $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
65
66
  const $toPos = state.doc.resolve(activeDropTargetNode.pos);
67
+ const existingDecsPos = decsToRemove.map(dec => dec.from);
66
68
  const {
67
69
  parent,
68
70
  index,
@@ -78,32 +80,48 @@ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api,
78
80
  * above the first child and below the last child.
79
81
  */
80
82
  if (isContainerNode(node)) {
83
+ const isEmptyContainer = node.childCount === 0 || node.childCount === 1 && isEmptyParagraph(node.firstChild);
84
+
81
85
  // can move to before first child
82
- if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(pos + 1),
83
- // +1 to get the position of the first child
84
- activeNode)) {
85
- decs.push(createDropTargetDecoration(pos + 1, {
86
- api,
87
- prevNode: undefined,
88
- nextNode: node.firstChild,
89
- parentNode: node,
90
- formatMessage,
91
- dropTargetStyle: 'default'
92
- }, nodeViewPortalProviderAPI, 1));
86
+ const posBeforeFirstChild = pos + 1; // +1 to get the position of the first child
87
+ if (node.firstChild && canMoveNodeOrSliceToPos(state, node.firstChild, node, 0, state.doc.resolve(posBeforeFirstChild), activeNode)) {
88
+ if (existingDecsPos.includes(posBeforeFirstChild)) {
89
+ // if the decoration already exists, we don't add it again.
90
+ decsToRemove = decsToRemove.filter(dec => dec.from !== posBeforeFirstChild);
91
+ } else {
92
+ decsToAdd.push(createDropTargetDecoration(posBeforeFirstChild, {
93
+ api,
94
+ prevNode: undefined,
95
+ nextNode: node.firstChild,
96
+ parentNode: node,
97
+ formatMessage,
98
+ dropTargetStyle: isEmptyContainer ? 'remainingHeight' : 'default'
99
+ }, nodeViewPortalProviderAPI, 1));
100
+ }
93
101
  }
94
102
 
95
103
  // can move to after last child
96
- if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(pos + node.nodeSize - 1),
97
- // -1 to get the position after last child
98
- activeNode)) {
99
- decs.push(createDropTargetDecoration(pos + node.nodeSize - 1, {
100
- api,
101
- prevNode: node.lastChild,
102
- nextNode: undefined,
103
- parentNode: node,
104
- formatMessage,
105
- dropTargetStyle: 'default'
106
- }, nodeViewPortalProviderAPI, -1));
104
+ // if the node is empty, we don't show the drop target at the end of the node
105
+ if (!isEmptyContainer) {
106
+ const posAfterLastChild = pos + node.nodeSize - 1; // -1 to get the position after last child
107
+
108
+ if (node.lastChild && canMoveNodeOrSliceToPos(state, node.lastChild, node, node.childCount - 1, state.doc.resolve(posAfterLastChild),
109
+ // -1 to get the position after last child
110
+ activeNode)) {
111
+ if (existingDecsPos.includes(posAfterLastChild)) {
112
+ // if the decoration already exists, we don't add it again.
113
+ decsToRemove = decsToRemove.filter(dec => dec.from !== posAfterLastChild);
114
+ } else {
115
+ decsToAdd.push(createDropTargetDecoration(posAfterLastChild, {
116
+ api,
117
+ prevNode: node.lastChild,
118
+ nextNode: undefined,
119
+ parentNode: node,
120
+ formatMessage,
121
+ dropTargetStyle: 'remainingHeight'
122
+ }, nodeViewPortalProviderAPI, -1));
123
+ }
124
+ }
107
125
  }
108
126
  }
109
127
 
@@ -115,24 +133,37 @@ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api,
115
133
  const isInSupportedContainer = ['tableCell', 'tableHeader', 'layoutColumn'].includes((parent === null || parent === void 0 ? void 0 : parent.type.name) || '');
116
134
  const shouldShowFullHeight = isInSupportedContainer && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node && isEmptyParagraph(node);
117
135
  if (canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode)) {
118
- decs.push(createDropTargetDecoration(pos, {
119
- api,
120
- prevNode: before || undefined,
121
- nextNode: node,
122
- parentNode: parent || undefined,
123
- formatMessage,
124
- dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
125
- }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
136
+ if (existingDecsPos.includes(pos)) {
137
+ // if the decoration already exists, we don't add it again.
138
+ decsToRemove = decsToRemove.filter(dec => dec.from !== pos);
139
+ } else {
140
+ decsToAdd.push(createDropTargetDecoration(pos, {
141
+ api,
142
+ prevNode: before || undefined,
143
+ nextNode: node,
144
+ parentNode: parent || undefined,
145
+ formatMessage,
146
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
147
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
148
+ }
126
149
  }
127
- if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(pos + node.nodeSize), activeNode)) {
128
- decs.push(createDropTargetDecoration(pos + node.nodeSize, {
129
- api,
130
- prevNode: node,
131
- nextNode: after || undefined,
132
- parentNode: parent || undefined,
133
- formatMessage,
134
- dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
135
- }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
150
+
151
+ // if the node is a container node, we show the drop target after the node
152
+ const posAfterNode = pos + node.nodeSize;
153
+ if (canMoveNodeOrSliceToPos(state, node, parent, index + 1, state.doc.resolve(posAfterNode), activeNode)) {
154
+ if (existingDecsPos.includes(posAfterNode)) {
155
+ // if the decoration already exists, we don't add it again.
156
+ decsToRemove = decsToRemove.filter(dec => dec.from !== posAfterNode);
157
+ } else {
158
+ decsToAdd.push(createDropTargetDecoration(posAfterNode, {
159
+ api,
160
+ prevNode: node,
161
+ nextNode: after || undefined,
162
+ parentNode: parent || undefined,
163
+ formatMessage,
164
+ dropTargetStyle: shouldShowFullHeight ? 'remainingHeight' : 'default'
165
+ }, nodeViewPortalProviderAPI, -1, undefined, isSameLayout));
166
+ }
136
167
  }
137
168
  }
138
169
  let rootNodeWithPos = {
@@ -143,14 +174,19 @@ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api,
143
174
  // if the current node is not a top level node, we create one for advanced layout drop targets
144
175
  if (depth > 1) {
145
176
  const root = findSurroundingNodes(state, state.doc.resolve($toPos.before(2)));
146
- decs.push(createDropTargetDecoration(root.pos, {
147
- api,
148
- prevNode: root.before || undefined,
149
- nextNode: root.node,
150
- parentNode: state.doc || undefined,
151
- formatMessage,
152
- dropTargetStyle: 'default'
153
- }, nodeViewPortalProviderAPI, 0, undefined, false));
177
+ if (existingDecsPos.includes(root.pos)) {
178
+ // if the decoration already exists, we don't add it again.
179
+ decsToRemove = decsToRemove.filter(dec => dec.from !== root.pos);
180
+ } else {
181
+ decsToAdd.push(createDropTargetDecoration(root.pos, {
182
+ api,
183
+ prevNode: root.before || undefined,
184
+ nextNode: root.node,
185
+ parentNode: state.doc || undefined,
186
+ formatMessage,
187
+ dropTargetStyle: 'default'
188
+ }, nodeViewPortalProviderAPI, 0, undefined, false));
189
+ }
154
190
  rootNodeWithPos = {
155
191
  node: root.node,
156
192
  pos: root.pos
@@ -164,11 +200,17 @@ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api,
164
200
  layoutSectionNode.descendants((childNode, childPos, parent, index) => {
165
201
  if (childNode.type.name === 'layoutColumn' && (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutSection' && index !== 0 // Not the first node
166
202
  ) {
167
- decs.push(createLayoutDropTargetDecoration(rootNodeWithPos.pos + childPos + 1, {
168
- api,
169
- parent,
170
- formatMessage
171
- }, nodeViewPortalProviderAPI, undefined));
203
+ const currentPos = rootNodeWithPos.pos + childPos + 1;
204
+ if (existingDecsPos.includes(currentPos)) {
205
+ // if the decoration already exists, we don't add it again.
206
+ decsToRemove = decsToRemove.filter(dec => dec.from !== currentPos);
207
+ } else {
208
+ decsToAdd.push(createLayoutDropTargetDecoration(rootNodeWithPos.pos + childPos + 1, {
209
+ api,
210
+ parent,
211
+ formatMessage
212
+ }, nodeViewPortalProviderAPI, undefined));
213
+ }
172
214
  }
173
215
  return false;
174
216
  });
@@ -176,5 +218,8 @@ export const getActiveDropTargetDecorations = (activeDropTargetNode, state, api,
176
218
  }
177
219
  }
178
220
  defaultActiveAnchorTracker.emit(getNodeAnchor(rootNodeWithPos.node));
179
- return decs;
221
+ return {
222
+ decsToAdd,
223
+ decsToRemove
224
+ };
180
225
  };