@atlaskit/editor-plugin-block-controls 3.1.5 → 3.1.7

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,37 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 3.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [#120533](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/120533)
8
+ [`f1bec731e278f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f1bec731e278f) -
9
+ Adds a `sideEffects` field to ensure this package does not have Compiled styles tree-shaken in the
10
+ future to avoid an accidental regression.
11
+
12
+ This is related to
13
+ https://community.developer.atlassian.com/t/rfc-73-migrating-our-components-to-compiled-css-in-js/85953
14
+
15
+ - [#120887](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/120887)
16
+ [`ab17c525aee48`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ab17c525aee48) -
17
+ Fix multi-select drag previews
18
+ - [#120893](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/120893)
19
+ [`8070e79030a9b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8070e79030a9b) -
20
+ Prevent multi-select layoutColumns from dropping
21
+ - Updated dependencies
22
+
23
+ ## 3.1.6
24
+
25
+ ### Patch Changes
26
+
27
+ - [#120473](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/120473)
28
+ [`6d0a06b4b6689`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6d0a06b4b6689) -
29
+ Put DnD shift-select behind FG
30
+ - [#119967](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/119967)
31
+ [`9c072f388dcaa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9c072f388dcaa) -
32
+ Add check for selection before triggering quick insert, and move selection if not within target
33
+ node
34
+
3
35
  ## 3.1.5
4
36
 
5
37
  ### Patch Changes
@@ -650,7 +650,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
650
650
  return true;
651
651
  }
652
652
  }
653
- if (!event.repeat && event.shiftKey) {
653
+ if (!event.repeat && event.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
654
654
  view.dispatch(view.state.tr.setMeta(key, _objectSpread(_objectSpread({}, view.state.tr.getMeta(key)), {}, {
655
655
  isShiftDown: true
656
656
  })));
@@ -122,6 +122,7 @@ function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNodePos,
122
122
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
123
123
  }
124
124
  function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
125
+ var _slice$content$firstC;
125
126
  var canMoveNodes = true;
126
127
  var doc = $destNodePos.doc;
127
128
  var nodesPos = [];
@@ -130,6 +131,11 @@ function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexI
130
131
  if ($destNodePos.pos < sliceToPos && $destNodePos.pos >= sliceFromPos) {
131
132
  return false;
132
133
  }
134
+
135
+ // Multiple layout columns do not drop correctly.
136
+ if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type.name) === 'layoutColumn' && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_multi_select_patch_1')) {
137
+ return false;
138
+ }
133
139
  for (var i = 0; i < slice.content.childCount; i++) {
134
140
  var node = slice.content.maybeChild(i);
135
141
  if (i === 0) {
@@ -324,6 +324,14 @@ var nodeMargins = exports.nodeMargins = {
324
324
  top: 12,
325
325
  bottom: 0
326
326
  },
327
+ expand: {
328
+ top: 4,
329
+ bottom: 0
330
+ },
331
+ nestedExpand: {
332
+ top: 1,
333
+ bottom: 0
334
+ },
327
335
  default: {
328
336
  top: 0,
329
337
  bottom: 0
@@ -124,8 +124,18 @@ var getNodeSpacingForPreview = function getNodeSpacingForPreview(node) {
124
124
  }
125
125
  return _consts.spacingBetweenNodesForPreview[nodeTypeName] || _consts.spacingBetweenNodesForPreview['default'];
126
126
  };
127
+ var getNodeMargins = function getNodeMargins(node) {
128
+ if (!node) {
129
+ return _consts.nodeMargins['default'];
130
+ }
131
+ var nodeTypeName = node.type.name;
132
+ if (nodeTypeName === 'heading') {
133
+ return _consts.nodeMargins["heading".concat(node.attrs.level)] || _consts.nodeMargins['default'];
134
+ }
135
+ return _consts.nodeMargins[nodeTypeName] || _consts.nodeMargins['default'];
136
+ };
127
137
  var DragHandle = exports.DragHandle = function DragHandle(_ref) {
128
- var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
138
+ var _api$core2, _api$blockControls3, _api$analytics2, _api$core4;
129
139
  var view = _ref.view,
130
140
  api = _ref.api,
131
141
  formatMessage = _ref.formatMessage,
@@ -153,7 +163,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
153
163
  featureFlagsState = _useSharedPluginState.featureFlagsState;
154
164
  var selection = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'selection.selection');
155
165
  var isShiftDown = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'blockControls.isShiftDown');
156
- var multiSelectDnD = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'blockControls.multiSelectDnD');
157
166
  var isLayoutColumn = nodeType === 'layoutColumn';
158
167
  var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
159
168
  exposure: true
@@ -181,13 +190,14 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
181
190
  setDragHandleSelected(!dragHandleSelected);
182
191
  }
183
192
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
184
- var _api$analytics;
193
+ var _api$blockControls$sh, _api$analytics;
185
194
  var tr = _ref2.tr;
186
195
  var startPos = getPos();
187
196
  if (startPos === undefined) {
188
197
  return tr;
189
198
  }
190
- var $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? tr.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : tr.selection.$anchor;
199
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.multiSelectDnD;
200
+ var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
191
201
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
192
202
  tr = (0, _getSelection.selectNode)(tr, startPos, nodeType);
193
203
  if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
@@ -199,7 +209,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
199
209
  });
200
210
  e.stopPropagation();
201
211
  }
202
- } else if (isTopLevelNode && $anchor.depth <= _consts.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
212
+ } else if (isTopLevelNode && $anchor.depth <= _consts.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
203
213
  var _api$blockControls2;
204
214
  var alignAnchorHeadToSel = (0, _selection.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
205
215
  var selectionWithExpandedHead = (0, _selection.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
@@ -224,7 +234,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
224
234
  return tr;
225
235
  });
226
236
  view.focus();
227
- }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType, anchorName]);
237
+ }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : api.blockControls.sharedState, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, view, dragHandleSelected, getPos, isTopLevelNode, nodeType, anchorName]);
228
238
 
229
239
  // TODO - This needs to be investigated further. Drag preview generation is not always working
230
240
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -287,6 +297,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
287
297
  };
288
298
  },
289
299
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
300
+ var _api$blockControls$sh2;
290
301
  var nativeSetDragImage = _ref4.nativeSetDragImage;
291
302
  if (isMultiSelect) {
292
303
  var _api$core5;
@@ -311,9 +322,10 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
311
322
  selection = state.selection;
312
323
  var sliceFrom = selection.from;
313
324
  var sliceTo = selection.to;
314
- if (multiSelectDnD) {
315
- var anchor = multiSelectDnD.anchor,
316
- head = multiSelectDnD.head;
325
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh2 === void 0 ? void 0 : _api$blockControls$sh2.multiSelectDnD;
326
+ if (mSelect) {
327
+ var anchor = mSelect.anchor,
328
+ head = mSelect.head;
317
329
  sliceFrom = Math.min(anchor, head);
318
330
  sliceTo = Math.max(anchor, head);
319
331
  }
@@ -350,12 +362,12 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
350
362
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
351
363
  var currentNodeElement = (0, _utils.findDomRefAtPos)(nodesStartPos[i], domAtPos);
352
364
  var maybeCurrentNode = expandedSlice.content.maybeChild(i);
353
- var currentNodeSpacing = maybeCurrentNode ? _consts.nodeMargins[maybeCurrentNode.type.name].top + _consts.nodeMargins[maybeCurrentNode.type.name].bottom : 0;
365
+ var currentNodeSpacing = maybeCurrentNode ? getNodeMargins(maybeCurrentNode).top + getNodeMargins(maybeCurrentNode).bottom : 0;
354
366
  domElementsHeightBeforeHandle = domElementsHeightBeforeHandle + currentNodeElement.offsetHeight + currentNodeSpacing;
355
367
  } else {
356
368
  // when the node is after the handle, calculate the top margin of the active node
357
369
  var maybeNextNode = expandedSlice.content.maybeChild(i);
358
- activeNodeMarginTop = maybeNextNode ? _consts.nodeMargins[maybeNextNode.type.name].top : 0;
370
+ activeNodeMarginTop = maybeNextNode ? getNodeMargins(maybeNextNode).top : 0;
359
371
  break;
360
372
  }
361
373
  }
@@ -379,7 +391,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
379
391
  } else {
380
392
  var domAtPos = view.domAtPos.bind(view);
381
393
  var previewContent = [];
382
- expandedSlice.content.descendants(function (node, pos, parent, index) {
394
+ expandedSlice.content.descendants(function (node, pos, _parent, _index) {
383
395
  // Get the dom element of the node
384
396
  //eslint-disable-next-line @atlaskit/editor/no-as-casting
385
397
  var nodeDomElement = (0, _utils.findDomRefAtPos)(sliceFrom + pos, domAtPos);
@@ -403,13 +415,14 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
403
415
  return;
404
416
  }
405
417
  api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref7) {
406
- var _api$blockControls5, _api$analytics3;
418
+ var _api$blockControls$sh3, _api$blockControls5, _api$analytics3;
407
419
  var tr = _ref7.tr;
408
420
  var nodeTypes, hasSelectedMultipleNodes;
409
421
  var resolvedMovingNode = tr.doc.resolve(start);
410
422
  var maybeNode = resolvedMovingNode.nodeAfter;
411
- if (multiSelectDnD) {
412
- var attributes = (0, _analytics2.getMultiSelectAnalyticsAttributes)(tr, multiSelectDnD.anchor, multiSelectDnD.head);
423
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh3 === void 0 ? void 0 : _api$blockControls$sh3.multiSelectDnD;
424
+ if (mSelect) {
425
+ var attributes = (0, _analytics2.getMultiSelectAnalyticsAttributes)(tr, mSelect.anchor, mSelect.head);
413
426
  nodeTypes = attributes.nodeTypes;
414
427
  hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
415
428
  } else {
@@ -438,7 +451,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
438
451
  view.focus();
439
452
  }
440
453
  });
441
- }, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
454
+ }, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
442
455
  var macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
443
456
  var calculatePosition = (0, _react.useCallback)(function () {
444
457
  var parentNodeType;
@@ -529,16 +542,18 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
529
542
  setDragHandleSelected((0, _getSelection.isHandleCorrelatedToSelection)(view.state, selection, start));
530
543
  }, [start, selection, view.state, isMultiSelect]);
531
544
  (0, _react.useEffect)(function () {
532
- if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
545
+ var _api$blockControls$sh4;
546
+ if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty || !(0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
533
547
  return;
534
548
  }
535
- var $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? view.state.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : view.state.selection.$anchor;
549
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
550
+ var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
536
551
  if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > _consts.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
537
552
  setDragHandleDisabled(true);
538
553
  } else {
539
554
  setDragHandleDisabled(false);
540
555
  }
541
- }, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
556
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view.state.doc, view.state.selection]);
542
557
  var helpDescriptors = isTopLevelNode && (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_accessibility') ? [{
543
558
  description: formatMessage(_messages.blockControlsMessages.dragToMove)
544
559
  }, {
@@ -155,6 +155,18 @@ var topLevelNodeMarginStyles = (0, _react.css)({
155
155
  }
156
156
  }
157
157
  });
158
+
159
+ // when quick insert is rendered there are 2 widgets before the first block node
160
+ var topLevelNodeMarginWithQuickInsertStyles = (0, _react.css)({
161
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
162
+ '.ProseMirror': {
163
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
164
+ '> .ProseMirror-widget:nth-child(-n + 2) + .ProseMirror-gapcursor + *:not([data-layout-section="true"]), > .ProseMirror-widget:nth-child(-n + 2) + *:not([data-layout-section="true"])': {
165
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
166
+ marginTop: '0 !important'
167
+ }
168
+ }
169
+ });
158
170
  var withDividerInPanelStyleFix = (0, _react.css)((0, _defineProperty2.default)({}, "".concat(dividerBodiedInCustomPanelWithNoIconSelector), {
159
171
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
160
172
  marginTop: '0 !important'
@@ -216,6 +228,6 @@ var blockCardWithoutLayout = (0, _react.css)({
216
228
  });
217
229
  var GlobalStylesWrapper = exports.GlobalStylesWrapper = function GlobalStylesWrapper() {
218
230
  return (0, _react.jsx)(_react.Global, {
219
- styles: [globalStyles(), (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, (0, _experiments.editorExperiment)('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, (0, _experiments.editorExperiment)('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, topLevelNodeMarginStyles, (0, _experiments.editorExperiment)('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
231
+ styles: [globalStyles(), (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, (0, _experiments.editorExperiment)('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, (0, _experiments.editorExperiment)('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? topLevelNodeMarginWithQuickInsertStyles : topLevelNodeMarginStyles, (0, _experiments.editorExperiment)('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
220
232
  });
221
233
  };
@@ -30,7 +30,7 @@ var buttonStyles = (0, _primitives.xcss)({
30
30
  height: "var(--ds-space-300, 24px)",
31
31
  width: "var(--ds-space-300, 24px)",
32
32
  border: 'none',
33
- backgroundColor: 'color.background.neutral',
33
+ backgroundColor: 'color.background.neutral.subtle',
34
34
  borderRadius: '50%',
35
35
  color: 'color.text.accent.gray',
36
36
  zIndex: 'card',
@@ -52,6 +52,18 @@ var containerStaticStyles = (0, _primitives.xcss)({
52
52
 
53
53
  // TODO: Share prop types between DragHandle - generic enough to create a type for block control decoration
54
54
 
55
+ var isSelectionInNode = function isSelectionInNode(start, view) {
56
+ var node = view.state.doc.nodeAt(start);
57
+ if (node === null) {
58
+ return false;
59
+ }
60
+ var endPos = start + node.nodeSize;
61
+ var startPos = start;
62
+ var _view$state$selection = view.state.selection,
63
+ $from = _view$state$selection.$from,
64
+ $to = _view$state$selection.$to;
65
+ return $from.pos >= startPos && endPos >= $to.pos;
66
+ };
55
67
  var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref) {
56
68
  var view = _ref.view,
57
69
  api = _ref.api,
@@ -62,7 +74,9 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
62
74
  rootAnchorName = _ref.rootAnchorName,
63
75
  rootNodeType = _ref.rootNodeType;
64
76
  var macroInteractionUpdates = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'featureFlags.macroInteractionUpdates');
65
- var _useState = (0, _react.useState)({}),
77
+ var _useState = (0, _react.useState)({
78
+ display: 'none'
79
+ }),
66
80
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
67
81
  positionStyles = _useState2[0],
68
82
  setPositionStyles = _useState2[1];
@@ -145,15 +159,23 @@ var TypeAheadControl = exports.TypeAheadControl = function TypeAheadControl(_ref
145
159
  "aria-label": formatMessage(_messages.blockControlsMessages.insert),
146
160
  xcss: [buttonStyles],
147
161
  onClick: function onClick() {
148
- var _api$core, _api$quickInsert;
149
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
150
- var tr = _ref2.tr;
151
- var start = getPos();
152
- if (!start) {
153
- return null;
154
- }
155
- return tr.setSelection(_state.TextSelection.create(tr.doc, start));
156
- });
162
+ var _api$quickInsert;
163
+ // if the selection is not within the node this decoration is rendered at
164
+ // then insert a newline and trigger quick insert
165
+ var start = getPos();
166
+ if (start !== undefined && !isSelectionInNode(start, view)) {
167
+ api.core.actions.execute(function (_ref2) {
168
+ var _tr$doc$nodeAt;
169
+ var tr = _ref2.tr;
170
+ var nodeSize = (_tr$doc$nodeAt = tr.doc.nodeAt(start)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.nodeSize;
171
+ if (nodeSize === undefined) {
172
+ return tr;
173
+ }
174
+ var position = start + nodeSize;
175
+ tr.insert(position, tr.doc.type.schema.nodes.paragraph.create());
176
+ return tr.setSelection(_state.TextSelection.create(tr.doc, position));
177
+ });
178
+ }
157
179
  api === null || api === void 0 || (_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 || _api$quickInsert.actions.openTypeAhead('blockControl');
158
180
  }
159
181
  }, /*#__PURE__*/_react.default.createElement(_add.default, {
@@ -639,7 +639,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
639
639
  return true;
640
640
  }
641
641
  }
642
- if (!event.repeat && event.shiftKey) {
642
+ if (!event.repeat && event.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
643
643
  view.dispatch(view.state.tr.setMeta(key, {
644
644
  ...view.state.tr.getMeta(key),
645
645
  isShiftDown: true
@@ -115,6 +115,7 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
115
115
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
116
116
  }
117
117
  export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
118
+ var _slice$content$firstC;
118
119
  let canMoveNodes = true;
119
120
  const doc = $destNodePos.doc;
120
121
  const nodesPos = [];
@@ -123,6 +124,11 @@ export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent,
123
124
  if ($destNodePos.pos < sliceToPos && $destNodePos.pos >= sliceFromPos) {
124
125
  return false;
125
126
  }
127
+
128
+ // Multiple layout columns do not drop correctly.
129
+ if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type.name) === 'layoutColumn' && fg('platform_editor_elements_dnd_multi_select_patch_1')) {
130
+ return false;
131
+ }
126
132
  for (let i = 0; i < slice.content.childCount; i++) {
127
133
  const node = slice.content.maybeChild(i);
128
134
  if (i === 0) {
@@ -333,6 +333,14 @@ export const nodeMargins = {
333
333
  top: 12,
334
334
  bottom: 0
335
335
  },
336
+ expand: {
337
+ top: 4,
338
+ bottom: 0
339
+ },
340
+ nestedExpand: {
341
+ top: 1,
342
+ bottom: 0
343
+ },
336
344
  default: {
337
345
  top: 0,
338
346
  bottom: 0
@@ -114,6 +114,16 @@ const getNodeSpacingForPreview = node => {
114
114
  }
115
115
  return spacingBetweenNodesForPreview[nodeTypeName] || spacingBetweenNodesForPreview['default'];
116
116
  };
117
+ const getNodeMargins = node => {
118
+ if (!node) {
119
+ return nodeMargins['default'];
120
+ }
121
+ const nodeTypeName = node.type.name;
122
+ if (nodeTypeName === 'heading') {
123
+ return nodeMargins[`heading${node.attrs.level}`] || nodeMargins['default'];
124
+ }
125
+ return nodeMargins[nodeTypeName] || nodeMargins['default'];
126
+ };
117
127
  export const DragHandle = ({
118
128
  view,
119
129
  api,
@@ -124,7 +134,7 @@ export const DragHandle = ({
124
134
  handleOptions,
125
135
  isTopLevelNode = true
126
136
  }) => {
127
- var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
137
+ var _api$core2, _api$blockControls3, _api$analytics2, _api$core4;
128
138
  const start = getPos();
129
139
  const buttonRef = useRef(null);
130
140
  const [blockCardWidth, setBlockCardWidth] = useState(768);
@@ -135,7 +145,6 @@ export const DragHandle = ({
135
145
  } = useSharedPluginState(api, ['featureFlags']);
136
146
  const selection = useSharedPluginStateSelector(api, 'selection.selection');
137
147
  const isShiftDown = useSharedPluginStateSelector(api, 'blockControls.isShiftDown');
138
- const multiSelectDnD = useSharedPluginStateSelector(api, 'blockControls.multiSelectDnD');
139
148
  const isLayoutColumn = nodeType === 'layoutColumn';
140
149
  const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
141
150
  exposure: true
@@ -163,12 +172,13 @@ export const DragHandle = ({
163
172
  api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
164
173
  tr
165
174
  }) => {
166
- var _api$analytics;
175
+ var _api$blockControls$sh, _api$analytics;
167
176
  const startPos = getPos();
168
177
  if (startPos === undefined) {
169
178
  return tr;
170
179
  }
171
- const $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? tr.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : tr.selection.$anchor;
180
+ const mSelect = api === null || api === void 0 ? void 0 : (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.multiSelectDnD;
181
+ const $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
172
182
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
173
183
  tr = selectNode(tr, startPos, nodeType);
174
184
  if (editorExperiment('platform_editor_controls', 'variant1')) {
@@ -180,7 +190,7 @@ export const DragHandle = ({
180
190
  });
181
191
  e.stopPropagation();
182
192
  }
183
- } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
193
+ } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
184
194
  var _api$blockControls2;
185
195
  const alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
186
196
  const selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
@@ -205,7 +215,7 @@ export const DragHandle = ({
205
215
  return tr;
206
216
  });
207
217
  view.focus();
208
- }, [isMultiSelect, api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType, anchorName]);
218
+ }, [isMultiSelect, api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : api.blockControls.sharedState, api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, view, dragHandleSelected, getPos, isTopLevelNode, nodeType, anchorName]);
209
219
 
210
220
  // TODO - This needs to be investigated further. Drag preview generation is not always working
211
221
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -267,6 +277,7 @@ export const DragHandle = ({
267
277
  onGenerateDragPreview: ({
268
278
  nativeSetDragImage
269
279
  }) => {
280
+ var _api$blockControls$sh2;
270
281
  if (isMultiSelect) {
271
282
  var _api$core5;
272
283
  api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(({
@@ -293,11 +304,12 @@ export const DragHandle = ({
293
304
  } = state;
294
305
  let sliceFrom = selection.from;
295
306
  let sliceTo = selection.to;
296
- if (multiSelectDnD) {
307
+ const mSelect = api === null || api === void 0 ? void 0 : (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh2 === void 0 ? void 0 : _api$blockControls$sh2.multiSelectDnD;
308
+ if (mSelect) {
297
309
  const {
298
310
  anchor,
299
311
  head
300
- } = multiSelectDnD;
312
+ } = mSelect;
301
313
  sliceFrom = Math.min(anchor, head);
302
314
  sliceTo = Math.max(anchor, head);
303
315
  }
@@ -334,12 +346,12 @@ export const DragHandle = ({
334
346
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
335
347
  const currentNodeElement = findDomRefAtPos(nodesStartPos[i], domAtPos);
336
348
  const maybeCurrentNode = expandedSlice.content.maybeChild(i);
337
- const currentNodeSpacing = maybeCurrentNode ? nodeMargins[maybeCurrentNode.type.name].top + nodeMargins[maybeCurrentNode.type.name].bottom : 0;
349
+ const currentNodeSpacing = maybeCurrentNode ? getNodeMargins(maybeCurrentNode).top + getNodeMargins(maybeCurrentNode).bottom : 0;
338
350
  domElementsHeightBeforeHandle = domElementsHeightBeforeHandle + currentNodeElement.offsetHeight + currentNodeSpacing;
339
351
  } else {
340
352
  // when the node is after the handle, calculate the top margin of the active node
341
353
  const maybeNextNode = expandedSlice.content.maybeChild(i);
342
- activeNodeMarginTop = maybeNextNode ? nodeMargins[maybeNextNode.type.name].top : 0;
354
+ activeNodeMarginTop = maybeNextNode ? getNodeMargins(maybeNextNode).top : 0;
343
355
  break;
344
356
  }
345
357
  }
@@ -364,7 +376,7 @@ export const DragHandle = ({
364
376
  } else {
365
377
  const domAtPos = view.domAtPos.bind(view);
366
378
  const previewContent = [];
367
- expandedSlice.content.descendants((node, pos, parent, index) => {
379
+ expandedSlice.content.descendants((node, pos, _parent, _index) => {
368
380
  // Get the dom element of the node
369
381
  //eslint-disable-next-line @atlaskit/editor/no-as-casting
370
382
  const nodeDomElement = findDomRefAtPos(sliceFrom + pos, domAtPos);
@@ -390,12 +402,13 @@ export const DragHandle = ({
390
402
  api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(({
391
403
  tr
392
404
  }) => {
393
- var _api$blockControls5, _api$analytics3;
405
+ var _api$blockControls$sh3, _api$blockControls5, _api$analytics3;
394
406
  let nodeTypes, hasSelectedMultipleNodes;
395
407
  const resolvedMovingNode = tr.doc.resolve(start);
396
408
  const maybeNode = resolvedMovingNode.nodeAfter;
397
- if (multiSelectDnD) {
398
- const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
409
+ const mSelect = api === null || api === void 0 ? void 0 : (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh3 === void 0 ? void 0 : _api$blockControls$sh3.multiSelectDnD;
410
+ if (mSelect) {
411
+ const attributes = getMultiSelectAnalyticsAttributes(tr, mSelect.anchor, mSelect.head);
399
412
  nodeTypes = attributes.nodeTypes;
400
413
  hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
401
414
  } else {
@@ -425,7 +438,7 @@ export const DragHandle = ({
425
438
  view.focus();
426
439
  }
427
440
  });
428
- }, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
441
+ }, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
429
442
  const macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
430
443
  const calculatePosition = useCallback(() => {
431
444
  let parentNodeType;
@@ -513,16 +526,18 @@ export const DragHandle = ({
513
526
  setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
514
527
  }, [start, selection, view.state, isMultiSelect]);
515
528
  useEffect(() => {
516
- if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
529
+ var _api$blockControls$sh4;
530
+ if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty || !fg('platform_editor_elements_dnd_shift_click_select')) {
517
531
  return;
518
532
  }
519
- const $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? view.state.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : view.state.selection.$anchor;
533
+ const mSelect = api === null || api === void 0 ? void 0 : (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
534
+ const $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
520
535
  if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
521
536
  setDragHandleDisabled(true);
522
537
  } else {
523
538
  setDragHandleDisabled(false);
524
539
  }
525
- }, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
540
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view.state.doc, view.state.selection]);
526
541
  let helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
527
542
  description: formatMessage(blockControlsMessages.dragToMove)
528
543
  }, {
@@ -178,6 +178,18 @@ const topLevelNodeMarginStyles = css({
178
178
  }
179
179
  }
180
180
  });
181
+
182
+ // when quick insert is rendered there are 2 widgets before the first block node
183
+ const topLevelNodeMarginWithQuickInsertStyles = css({
184
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
185
+ '.ProseMirror': {
186
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
187
+ '> .ProseMirror-widget:nth-child(-n + 2) + .ProseMirror-gapcursor + *:not([data-layout-section="true"]), > .ProseMirror-widget:nth-child(-n + 2) + *:not([data-layout-section="true"])': {
188
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
189
+ marginTop: '0 !important'
190
+ }
191
+ }
192
+ });
181
193
  const withDividerInPanelStyleFix = css({
182
194
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-values
183
195
  [`${dividerBodiedInCustomPanelWithNoIconSelector}`]: {
@@ -260,6 +272,6 @@ const blockCardWithoutLayout = css({
260
272
  });
261
273
  export const GlobalStylesWrapper = () => {
262
274
  return jsx(Global, {
263
- styles: [globalStyles(), fg('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, topLevelNodeMarginStyles, editorExperiment('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
275
+ styles: [globalStyles(), fg('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, editorExperiment('platform_editor_controls', 'variant1') ? topLevelNodeMarginWithQuickInsertStyles : topLevelNodeMarginStyles, editorExperiment('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
264
276
  });
265
277
  };
@@ -19,7 +19,7 @@ const buttonStyles = xcss({
19
19
  height: "var(--ds-space-300, 24px)",
20
20
  width: "var(--ds-space-300, 24px)",
21
21
  border: 'none',
22
- backgroundColor: 'color.background.neutral',
22
+ backgroundColor: 'color.background.neutral.subtle',
23
23
  borderRadius: '50%',
24
24
  color: 'color.text.accent.gray',
25
25
  zIndex: 'card',
@@ -41,6 +41,19 @@ const containerStaticStyles = xcss({
41
41
 
42
42
  // TODO: Share prop types between DragHandle - generic enough to create a type for block control decoration
43
43
 
44
+ const isSelectionInNode = (start, view) => {
45
+ const node = view.state.doc.nodeAt(start);
46
+ if (node === null) {
47
+ return false;
48
+ }
49
+ const endPos = start + node.nodeSize;
50
+ const startPos = start;
51
+ const {
52
+ $from,
53
+ $to
54
+ } = view.state.selection;
55
+ return $from.pos >= startPos && endPos >= $to.pos;
56
+ };
44
57
  export const TypeAheadControl = ({
45
58
  view,
46
59
  api,
@@ -52,7 +65,9 @@ export const TypeAheadControl = ({
52
65
  rootNodeType
53
66
  }) => {
54
67
  const macroInteractionUpdates = useSharedPluginStateSelector(api, 'featureFlags.macroInteractionUpdates');
55
- const [positionStyles, setPositionStyles] = useState({});
68
+ const [positionStyles, setPositionStyles] = useState({
69
+ display: 'none'
70
+ });
56
71
 
57
72
  // Adapted from `src/ui/drag-handle.tsx` as positioning logic is similar
58
73
  // CHANGES - added an offset so quick insert button can be positioned beside drag handle
@@ -132,16 +147,24 @@ export const TypeAheadControl = ({
132
147
  "aria-label": formatMessage(messages.insert),
133
148
  xcss: [buttonStyles],
134
149
  onClick: () => {
135
- var _api$core, _api$quickInsert;
136
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
137
- tr
138
- }) => {
139
- const start = getPos();
140
- if (!start) {
141
- return null;
142
- }
143
- return tr.setSelection(TextSelection.create(tr.doc, start));
144
- });
150
+ var _api$quickInsert;
151
+ // if the selection is not within the node this decoration is rendered at
152
+ // then insert a newline and trigger quick insert
153
+ const start = getPos();
154
+ if (start !== undefined && !isSelectionInNode(start, view)) {
155
+ api.core.actions.execute(({
156
+ tr
157
+ }) => {
158
+ var _tr$doc$nodeAt;
159
+ const nodeSize = (_tr$doc$nodeAt = tr.doc.nodeAt(start)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.nodeSize;
160
+ if (nodeSize === undefined) {
161
+ return tr;
162
+ }
163
+ const position = start + nodeSize;
164
+ tr.insert(position, tr.doc.type.schema.nodes.paragraph.create());
165
+ return tr.setSelection(TextSelection.create(tr.doc, position));
166
+ });
167
+ }
145
168
  api === null || api === void 0 ? void 0 : (_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 ? void 0 : _api$quickInsert.actions.openTypeAhead('blockControl');
146
169
  }
147
170
  }, /*#__PURE__*/React.createElement(EditorAddIcon, {
@@ -643,7 +643,7 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
643
643
  return true;
644
644
  }
645
645
  }
646
- if (!event.repeat && event.shiftKey) {
646
+ if (!event.repeat && event.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
647
647
  view.dispatch(view.state.tr.setMeta(key, _objectSpread(_objectSpread({}, view.state.tr.getMeta(key)), {}, {
648
648
  isShiftDown: true
649
649
  })));
@@ -113,6 +113,7 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
113
113
  return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
114
114
  }
115
115
  export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
116
+ var _slice$content$firstC;
116
117
  var canMoveNodes = true;
117
118
  var doc = $destNodePos.doc;
118
119
  var nodesPos = [];
@@ -121,6 +122,11 @@ export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent,
121
122
  if ($destNodePos.pos < sliceToPos && $destNodePos.pos >= sliceFromPos) {
122
123
  return false;
123
124
  }
125
+
126
+ // Multiple layout columns do not drop correctly.
127
+ if (((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type.name) === 'layoutColumn' && fg('platform_editor_elements_dnd_multi_select_patch_1')) {
128
+ return false;
129
+ }
124
130
  for (var i = 0; i < slice.content.childCount; i++) {
125
131
  var node = slice.content.maybeChild(i);
126
132
  if (i === 0) {
@@ -317,6 +317,14 @@ export var nodeMargins = {
317
317
  top: 12,
318
318
  bottom: 0
319
319
  },
320
+ expand: {
321
+ top: 4,
322
+ bottom: 0
323
+ },
324
+ nestedExpand: {
325
+ top: 1,
326
+ bottom: 0
327
+ },
320
328
  default: {
321
329
  top: 0,
322
330
  bottom: 0
@@ -119,8 +119,18 @@ var getNodeSpacingForPreview = function getNodeSpacingForPreview(node) {
119
119
  }
120
120
  return spacingBetweenNodesForPreview[nodeTypeName] || spacingBetweenNodesForPreview['default'];
121
121
  };
122
+ var getNodeMargins = function getNodeMargins(node) {
123
+ if (!node) {
124
+ return nodeMargins['default'];
125
+ }
126
+ var nodeTypeName = node.type.name;
127
+ if (nodeTypeName === 'heading') {
128
+ return nodeMargins["heading".concat(node.attrs.level)] || nodeMargins['default'];
129
+ }
130
+ return nodeMargins[nodeTypeName] || nodeMargins['default'];
131
+ };
122
132
  export var DragHandle = function DragHandle(_ref) {
123
- var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
133
+ var _api$core2, _api$blockControls3, _api$analytics2, _api$core4;
124
134
  var view = _ref.view,
125
135
  api = _ref.api,
126
136
  formatMessage = _ref.formatMessage,
@@ -148,7 +158,6 @@ export var DragHandle = function DragHandle(_ref) {
148
158
  featureFlagsState = _useSharedPluginState.featureFlagsState;
149
159
  var selection = useSharedPluginStateSelector(api, 'selection.selection');
150
160
  var isShiftDown = useSharedPluginStateSelector(api, 'blockControls.isShiftDown');
151
- var multiSelectDnD = useSharedPluginStateSelector(api, 'blockControls.multiSelectDnD');
152
161
  var isLayoutColumn = nodeType === 'layoutColumn';
153
162
  var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
154
163
  exposure: true
@@ -176,13 +185,14 @@ export var DragHandle = function DragHandle(_ref) {
176
185
  setDragHandleSelected(!dragHandleSelected);
177
186
  }
178
187
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
179
- var _api$analytics;
188
+ var _api$blockControls$sh, _api$analytics;
180
189
  var tr = _ref2.tr;
181
190
  var startPos = getPos();
182
191
  if (startPos === undefined) {
183
192
  return tr;
184
193
  }
185
- var $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? tr.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : tr.selection.$anchor;
194
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.multiSelectDnD;
195
+ var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? tr.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : tr.selection.$anchor;
186
196
  if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
187
197
  tr = selectNode(tr, startPos, nodeType);
188
198
  if (editorExperiment('platform_editor_controls', 'variant1')) {
@@ -194,7 +204,7 @@ export var DragHandle = function DragHandle(_ref) {
194
204
  });
195
205
  e.stopPropagation();
196
206
  }
197
- } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
207
+ } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
198
208
  var _api$blockControls2;
199
209
  var alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
200
210
  var selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
@@ -219,7 +229,7 @@ export var DragHandle = function DragHandle(_ref) {
219
229
  return tr;
220
230
  });
221
231
  view.focus();
222
- }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, view, dragHandleSelected, getPos, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, isTopLevelNode, nodeType, anchorName]);
232
+ }, [isMultiSelect, api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions, api === null || api === void 0 ? void 0 : api.blockControls.sharedState, api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands, api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions, view, dragHandleSelected, getPos, isTopLevelNode, nodeType, anchorName]);
223
233
 
224
234
  // TODO - This needs to be investigated further. Drag preview generation is not always working
225
235
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -282,6 +292,7 @@ export var DragHandle = function DragHandle(_ref) {
282
292
  };
283
293
  },
284
294
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
295
+ var _api$blockControls$sh2;
285
296
  var nativeSetDragImage = _ref4.nativeSetDragImage;
286
297
  if (isMultiSelect) {
287
298
  var _api$core5;
@@ -306,9 +317,10 @@ export var DragHandle = function DragHandle(_ref) {
306
317
  selection = state.selection;
307
318
  var sliceFrom = selection.from;
308
319
  var sliceTo = selection.to;
309
- if (multiSelectDnD) {
310
- var anchor = multiSelectDnD.anchor,
311
- head = multiSelectDnD.head;
320
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh2 === void 0 ? void 0 : _api$blockControls$sh2.multiSelectDnD;
321
+ if (mSelect) {
322
+ var anchor = mSelect.anchor,
323
+ head = mSelect.head;
312
324
  sliceFrom = Math.min(anchor, head);
313
325
  sliceTo = Math.max(anchor, head);
314
326
  }
@@ -345,12 +357,12 @@ export var DragHandle = function DragHandle(_ref) {
345
357
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
346
358
  var currentNodeElement = findDomRefAtPos(nodesStartPos[i], domAtPos);
347
359
  var maybeCurrentNode = expandedSlice.content.maybeChild(i);
348
- var currentNodeSpacing = maybeCurrentNode ? nodeMargins[maybeCurrentNode.type.name].top + nodeMargins[maybeCurrentNode.type.name].bottom : 0;
360
+ var currentNodeSpacing = maybeCurrentNode ? getNodeMargins(maybeCurrentNode).top + getNodeMargins(maybeCurrentNode).bottom : 0;
349
361
  domElementsHeightBeforeHandle = domElementsHeightBeforeHandle + currentNodeElement.offsetHeight + currentNodeSpacing;
350
362
  } else {
351
363
  // when the node is after the handle, calculate the top margin of the active node
352
364
  var maybeNextNode = expandedSlice.content.maybeChild(i);
353
- activeNodeMarginTop = maybeNextNode ? nodeMargins[maybeNextNode.type.name].top : 0;
365
+ activeNodeMarginTop = maybeNextNode ? getNodeMargins(maybeNextNode).top : 0;
354
366
  break;
355
367
  }
356
368
  }
@@ -374,7 +386,7 @@ export var DragHandle = function DragHandle(_ref) {
374
386
  } else {
375
387
  var domAtPos = view.domAtPos.bind(view);
376
388
  var previewContent = [];
377
- expandedSlice.content.descendants(function (node, pos, parent, index) {
389
+ expandedSlice.content.descendants(function (node, pos, _parent, _index) {
378
390
  // Get the dom element of the node
379
391
  //eslint-disable-next-line @atlaskit/editor/no-as-casting
380
392
  var nodeDomElement = findDomRefAtPos(sliceFrom + pos, domAtPos);
@@ -398,13 +410,14 @@ export var DragHandle = function DragHandle(_ref) {
398
410
  return;
399
411
  }
400
412
  api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref7) {
401
- var _api$blockControls5, _api$analytics3;
413
+ var _api$blockControls$sh3, _api$blockControls5, _api$analytics3;
402
414
  var tr = _ref7.tr;
403
415
  var nodeTypes, hasSelectedMultipleNodes;
404
416
  var resolvedMovingNode = tr.doc.resolve(start);
405
417
  var maybeNode = resolvedMovingNode.nodeAfter;
406
- if (multiSelectDnD) {
407
- var attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
418
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh3 === void 0 ? void 0 : _api$blockControls$sh3.multiSelectDnD;
419
+ if (mSelect) {
420
+ var attributes = getMultiSelectAnalyticsAttributes(tr, mSelect.anchor, mSelect.head);
408
421
  nodeTypes = attributes.nodeTypes;
409
422
  hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
410
423
  } else {
@@ -433,7 +446,7 @@ export var DragHandle = function DragHandle(_ref) {
433
446
  view.focus();
434
447
  }
435
448
  });
436
- }, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
449
+ }, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
437
450
  var macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
438
451
  var calculatePosition = useCallback(function () {
439
452
  var parentNodeType;
@@ -524,16 +537,18 @@ export var DragHandle = function DragHandle(_ref) {
524
537
  setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
525
538
  }, [start, selection, view.state, isMultiSelect]);
526
539
  useEffect(function () {
527
- if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
540
+ var _api$blockControls$sh4;
541
+ if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty || !fg('platform_editor_elements_dnd_shift_click_select')) {
528
542
  return;
529
543
  }
530
- var $anchor = (multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) !== undefined ? view.state.doc.resolve(multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor) : view.state.selection.$anchor;
544
+ var mSelect = api === null || api === void 0 || (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.multiSelectDnD;
545
+ var $anchor = (mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) !== undefined ? view.state.doc.resolve(mSelect === null || mSelect === void 0 ? void 0 : mSelect.anchor) : view.state.selection.$anchor;
531
546
  if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
532
547
  setDragHandleDisabled(true);
533
548
  } else {
534
549
  setDragHandleDisabled(false);
535
550
  }
536
- }, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
551
+ }, [api === null || api === void 0 ? void 0 : api.blockControls.sharedState, isMultiSelect, isShiftDown, isTopLevelNode, view.state.doc, view.state.selection]);
537
552
  var helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
538
553
  description: formatMessage(blockControlsMessages.dragToMove)
539
554
  }, {
@@ -148,6 +148,18 @@ var topLevelNodeMarginStyles = css({
148
148
  }
149
149
  }
150
150
  });
151
+
152
+ // when quick insert is rendered there are 2 widgets before the first block node
153
+ var topLevelNodeMarginWithQuickInsertStyles = css({
154
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
155
+ '.ProseMirror': {
156
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
157
+ '> .ProseMirror-widget:nth-child(-n + 2) + .ProseMirror-gapcursor + *:not([data-layout-section="true"]), > .ProseMirror-widget:nth-child(-n + 2) + *:not([data-layout-section="true"])': {
158
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles -- Ignored via go/DSP-18766
159
+ marginTop: '0 !important'
160
+ }
161
+ }
162
+ });
151
163
  var withDividerInPanelStyleFix = css(_defineProperty({}, "".concat(dividerBodiedInCustomPanelWithNoIconSelector), {
152
164
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-important-styles
153
165
  marginTop: '0 !important'
@@ -209,6 +221,6 @@ var blockCardWithoutLayout = css({
209
221
  });
210
222
  export var GlobalStylesWrapper = function GlobalStylesWrapper() {
211
223
  return jsx(Global, {
212
- styles: [globalStyles(), fg('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, topLevelNodeMarginStyles, editorExperiment('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
224
+ styles: [globalStyles(), fg('platform_editor_advanced_layouts_post_fix_patch_1') && globalDnDStyle, editorExperiment('nested-dnd', true) ? extendedHoverZoneNested() : extendedHoverZone(), withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, withRelativePosStyle, editorExperiment('platform_editor_controls', 'variant1') ? topLevelNodeMarginWithQuickInsertStyles : topLevelNodeMarginStyles, editorExperiment('nested-dnd', true) ? withAnchorNameZindexNestedStyle : withAnchorNameZindexStyle,,]
213
225
  });
214
226
  };
@@ -20,7 +20,7 @@ var buttonStyles = xcss({
20
20
  height: "var(--ds-space-300, 24px)",
21
21
  width: "var(--ds-space-300, 24px)",
22
22
  border: 'none',
23
- backgroundColor: 'color.background.neutral',
23
+ backgroundColor: 'color.background.neutral.subtle',
24
24
  borderRadius: '50%',
25
25
  color: 'color.text.accent.gray',
26
26
  zIndex: 'card',
@@ -42,6 +42,18 @@ var containerStaticStyles = xcss({
42
42
 
43
43
  // TODO: Share prop types between DragHandle - generic enough to create a type for block control decoration
44
44
 
45
+ var isSelectionInNode = function isSelectionInNode(start, view) {
46
+ var node = view.state.doc.nodeAt(start);
47
+ if (node === null) {
48
+ return false;
49
+ }
50
+ var endPos = start + node.nodeSize;
51
+ var startPos = start;
52
+ var _view$state$selection = view.state.selection,
53
+ $from = _view$state$selection.$from,
54
+ $to = _view$state$selection.$to;
55
+ return $from.pos >= startPos && endPos >= $to.pos;
56
+ };
45
57
  export var TypeAheadControl = function TypeAheadControl(_ref) {
46
58
  var view = _ref.view,
47
59
  api = _ref.api,
@@ -52,7 +64,9 @@ export var TypeAheadControl = function TypeAheadControl(_ref) {
52
64
  rootAnchorName = _ref.rootAnchorName,
53
65
  rootNodeType = _ref.rootNodeType;
54
66
  var macroInteractionUpdates = useSharedPluginStateSelector(api, 'featureFlags.macroInteractionUpdates');
55
- var _useState = useState({}),
67
+ var _useState = useState({
68
+ display: 'none'
69
+ }),
56
70
  _useState2 = _slicedToArray(_useState, 2),
57
71
  positionStyles = _useState2[0],
58
72
  setPositionStyles = _useState2[1];
@@ -135,15 +149,23 @@ export var TypeAheadControl = function TypeAheadControl(_ref) {
135
149
  "aria-label": formatMessage(messages.insert),
136
150
  xcss: [buttonStyles],
137
151
  onClick: function onClick() {
138
- var _api$core, _api$quickInsert;
139
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
140
- var tr = _ref2.tr;
141
- var start = getPos();
142
- if (!start) {
143
- return null;
144
- }
145
- return tr.setSelection(TextSelection.create(tr.doc, start));
146
- });
152
+ var _api$quickInsert;
153
+ // if the selection is not within the node this decoration is rendered at
154
+ // then insert a newline and trigger quick insert
155
+ var start = getPos();
156
+ if (start !== undefined && !isSelectionInNode(start, view)) {
157
+ api.core.actions.execute(function (_ref2) {
158
+ var _tr$doc$nodeAt;
159
+ var tr = _ref2.tr;
160
+ var nodeSize = (_tr$doc$nodeAt = tr.doc.nodeAt(start)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.nodeSize;
161
+ if (nodeSize === undefined) {
162
+ return tr;
163
+ }
164
+ var position = start + nodeSize;
165
+ tr.insert(position, tr.doc.type.schema.nodes.paragraph.create());
166
+ return tr.setSelection(TextSelection.create(tr.doc, position));
167
+ });
168
+ }
147
169
  api === null || api === void 0 || (_api$quickInsert = api.quickInsert) === null || _api$quickInsert === void 0 || _api$quickInsert.actions.openTypeAhead('blockControl');
148
170
  }
149
171
  }, /*#__PURE__*/React.createElement(EditorAddIcon, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "3.1.5",
3
+ "version": "3.1.7",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -24,14 +24,16 @@
24
24
  ]
25
25
  }
26
26
  },
27
- "sideEffects": false,
27
+ "sideEffects": [
28
+ "*.compiled.css"
29
+ ],
28
30
  "atlaskit:src": "src/index.ts",
29
31
  "af:exports": {
30
32
  ".": "./src/index.ts"
31
33
  },
32
34
  "dependencies": {
33
35
  "@atlaskit/adf-schema": "^47.2.1",
34
- "@atlaskit/editor-common": "^100.2.0",
36
+ "@atlaskit/editor-common": "^100.4.0",
35
37
  "@atlaskit/editor-plugin-accessibility-utils": "^2.0.0",
36
38
  "@atlaskit/editor-plugin-analytics": "^2.0.0",
37
39
  "@atlaskit/editor-plugin-editor-disabled": "^2.0.0",
@@ -46,7 +48,7 @@
46
48
  "@atlaskit/platform-feature-flags": "^1.1.0",
47
49
  "@atlaskit/pragmatic-drag-and-drop": "^1.5.0",
48
50
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
49
- "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^2.0.0",
51
+ "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^2.1.0",
50
52
  "@atlaskit/primitives": "^14.1.0",
51
53
  "@atlaskit/theme": "^17.0.0",
52
54
  "@atlaskit/tmp-editor-statsig": "^3.3.0",
@@ -151,6 +153,12 @@
151
153
  },
152
154
  "platform_editor_disable_drag_handle_nested_tables": {
153
155
  "type": "boolean"
156
+ },
157
+ "platform_editor_elements_dnd_shift_click_select": {
158
+ "type": "boolean"
159
+ },
160
+ "platform_editor_elements_dnd_multi_select_patch_1": {
161
+ "type": "boolean"
154
162
  }
155
163
  }
156
164
  }