@atlaskit/editor-plugin-block-controls 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/blockControlsPlugin.js +27 -14
  3. package/dist/cjs/editor-commands/move-node.js +15 -18
  4. package/dist/cjs/pm-plugins/decorations-common.js +2 -4
  5. package/dist/cjs/pm-plugins/main.js +73 -34
  6. package/dist/cjs/pm-plugins/utils/getSelection.js +1 -1
  7. package/dist/cjs/pm-plugins/utils/selection.js +34 -4
  8. package/dist/cjs/ui/consts.js +9 -1
  9. package/dist/cjs/ui/drag-handle.js +69 -36
  10. package/dist/es2019/blockControlsPlugin.js +27 -14
  11. package/dist/es2019/editor-commands/move-node.js +17 -20
  12. package/dist/es2019/pm-plugins/decorations-common.js +2 -4
  13. package/dist/es2019/pm-plugins/main.js +70 -23
  14. package/dist/es2019/pm-plugins/utils/getSelection.js +1 -1
  15. package/dist/es2019/pm-plugins/utils/selection.js +33 -3
  16. package/dist/es2019/ui/consts.js +8 -0
  17. package/dist/es2019/ui/drag-handle.js +59 -30
  18. package/dist/esm/blockControlsPlugin.js +27 -14
  19. package/dist/esm/editor-commands/move-node.js +16 -19
  20. package/dist/esm/pm-plugins/decorations-common.js +2 -4
  21. package/dist/esm/pm-plugins/main.js +71 -32
  22. package/dist/esm/pm-plugins/utils/getSelection.js +1 -1
  23. package/dist/esm/pm-plugins/utils/selection.js +33 -3
  24. package/dist/esm/ui/consts.js +8 -0
  25. package/dist/esm/ui/drag-handle.js +70 -37
  26. package/dist/types/blockControlsPluginType.d.ts +2 -0
  27. package/dist/types/pm-plugins/main.d.ts +2 -1
  28. package/dist/types/pm-plugins/utils/selection.d.ts +13 -1
  29. package/dist/types/ui/consts.d.ts +7 -0
  30. package/dist/types-ts4.5/blockControlsPluginType.d.ts +2 -0
  31. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
  32. package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +13 -1
  33. package/dist/types-ts4.5/ui/consts.d.ts +7 -0
  34. package/package.json +4 -4
@@ -121,10 +121,10 @@ var destroyFn = function destroyFn(api, editorView) {
121
121
  })
122
122
  })(tr);
123
123
  }
124
- return tr.setMeta(key, {
124
+ return tr.setMeta(key, _objectSpread(_objectSpread({}, tr.getMeta(key)), {}, {
125
125
  isDragging: false,
126
126
  isPMDragging: false
127
- });
127
+ }));
128
128
  });
129
129
  }
130
130
  }));
@@ -148,7 +148,7 @@ export var getDecorations = function getDecorations(state) {
148
148
  return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
149
149
  };
150
150
  export var newApply = function newApply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
151
- var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$multiSelectDnD;
151
+ var _meta$multiSelectDnD, _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown;
152
152
  var activeNode = currentState.activeNode,
153
153
  decorations = currentState.decorations,
154
154
  isResizerResizing = currentState.isResizerResizing,
@@ -158,7 +158,8 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
158
158
  editorWidthRight = currentState.editorWidthRight,
159
159
  isDragging = currentState.isDragging,
160
160
  isMenuOpen = currentState.isMenuOpen,
161
- isPMDragging = currentState.isPMDragging;
161
+ isPMDragging = currentState.isPMDragging,
162
+ isShiftDown = currentState.isShiftDown;
162
163
  var isActiveNodeDeleted = false;
163
164
 
164
165
  // When steps exist, remap existing decorations, activeNode and multi select positions
@@ -181,10 +182,9 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
181
182
  var meta = tr.getMeta(key);
182
183
  var resizerMeta = tr.getMeta('is-resizer-resizing');
183
184
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
185
+ multiSelectDnD = (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD;
184
186
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
185
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ||
186
- // For move node with shortcut, only reset when the selection changes
187
- tr.selection.anchor !== multiSelectDnD.textAnchor || tr.selection.head !== multiSelectDnD.textHead ? undefined : multiSelectDnD;
187
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || tr.selection.empty ? undefined : multiSelectDnD;
188
188
  }
189
189
  var _getTrMetadata = getTrMetadata(tr),
190
190
  from = _getTrMetadata.from,
@@ -287,7 +287,8 @@ export var newApply = function newApply(api, formatMessage, tr, currentState, ne
287
287
  isResizerResizing: isResizerResizing,
288
288
  isDocSizeLimitEnabled: initialState.isDocSizeLimitEnabled,
289
289
  isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging,
290
- multiSelectDnD: (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD
290
+ multiSelectDnD: multiSelectDnD,
291
+ isShiftDown: (_meta$isShiftDown = meta === null || meta === void 0 ? void 0 : meta.isShiftDown) !== null && _meta$isShiftDown !== void 0 ? _meta$isShiftDown : isShiftDown
291
292
  };
292
293
  };
293
294
  export var oldApply = function oldApply(api, formatMessage, tr, currentState, oldState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) {
@@ -503,9 +504,9 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
503
504
  dragging = view.dragging;
504
505
  var pluginState = key.getState(state);
505
506
  if (pluginState !== null && pluginState !== void 0 && pluginState.isPMDragging) {
506
- dispatch(state.tr.setMeta(key, {
507
+ dispatch(state.tr.setMeta(key, _objectSpread(_objectSpread({}, state.tr.getMeta(key)), {}, {
507
508
  isPMDragging: false
508
- }));
509
+ })));
509
510
  }
510
511
  if (!(event.target instanceof HTMLElement) || !(pluginState !== null && pluginState !== void 0 && pluginState.activeNode)) {
511
512
  return false;
@@ -558,18 +559,18 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
558
559
  defaultActiveAnchorTracker.reset();
559
560
  }
560
561
  (_anchorRectCache = anchorRectCache) === null || _anchorRectCache === void 0 || _anchorRectCache.setEditorView(view);
561
- view.dispatch(view.state.tr.setMeta(key, {
562
+ view.dispatch(view.state.tr.setMeta(key, _objectSpread(_objectSpread({}, view.state.tr.getMeta(key)), {}, {
562
563
  isPMDragging: true
563
- }));
564
+ })));
564
565
  },
565
566
  dragend: function dragend(view) {
566
567
  var _key$getState3;
567
568
  var state = view.state,
568
569
  dispatch = view.dispatch;
569
570
  if ((_key$getState3 = key.getState(state)) !== null && _key$getState3 !== void 0 && _key$getState3.isPMDragging) {
570
- dispatch(state.tr.setMeta(key, {
571
+ dispatch(state.tr.setMeta(key, _objectSpread(_objectSpread({}, state.tr.getMeta(key)), {}, {
571
572
  isPMDragging: false
572
- }));
573
+ })));
573
574
  }
574
575
  },
575
576
  mouseover: function mouseover(view, event) {
@@ -577,27 +578,65 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
577
578
  return false;
578
579
  },
579
580
  keydown: function keydown(view, event) {
580
- // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
581
- var _view$state = view.state,
582
- selection = _view$state.selection,
583
- doc = _view$state.doc,
584
- tr = _view$state.tr;
585
- var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
586
- if (event.key === 'ArrowUp' && event.shiftKey && metaKey) {
587
- if (selection instanceof TextSelection || selection instanceof NodeSelection) {
588
- var newSelection = TextSelection.create(doc, selection.head, 1);
589
- view.dispatch(tr.setSelection(newSelection));
590
- return true;
581
+ if (isMultiSelectEnabled) {
582
+ if (event.shiftKey && event.ctrlKey) {
583
+ //prevent holding down key combo from firing repeatedly
584
+ if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
585
+ event.preventDefault();
586
+ return true;
587
+ }
591
588
  }
592
- }
593
- if (event.shiftKey && event.ctrlKey) {
594
- //prevent holding down key combo from firing repeatedly
595
- if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
596
- event.preventDefault();
589
+
590
+ // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
591
+ var _view$state = view.state,
592
+ selection = _view$state.selection,
593
+ doc = _view$state.doc,
594
+ tr = _view$state.tr;
595
+ var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
596
+ if (event.key === 'ArrowUp' && event.shiftKey && metaKey) {
597
+ if (selection instanceof TextSelection || selection instanceof NodeSelection) {
598
+ var newSelection = TextSelection.create(doc, selection.head, 1);
599
+ view.dispatch(tr.setSelection(newSelection));
600
+ return true;
601
+ }
602
+ }
603
+ if (!event.repeat && event.shiftKey) {
604
+ view.dispatch(view.state.tr.setMeta(key, _objectSpread(_objectSpread({}, view.state.tr.getMeta(key)), {}, {
605
+ isShiftDown: true
606
+ })));
597
607
  return true;
598
608
  }
609
+ return false;
610
+ } else {
611
+ // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
612
+ var _view$state2 = view.state,
613
+ _selection = _view$state2.selection,
614
+ _doc = _view$state2.doc,
615
+ _tr = _view$state2.tr;
616
+ var _metaKey = browser.mac ? event.metaKey : event.ctrlKey;
617
+ if (event.key === 'ArrowUp' && event.shiftKey && _metaKey) {
618
+ if (_selection instanceof TextSelection || _selection instanceof NodeSelection) {
619
+ var _newSelection = TextSelection.create(_doc, _selection.head, 1);
620
+ view.dispatch(_tr.setSelection(_newSelection));
621
+ return true;
622
+ }
623
+ }
624
+ if (event.shiftKey && event.ctrlKey) {
625
+ //prevent holding down key combo from firing repeatedly
626
+ if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
627
+ event.preventDefault();
628
+ return true;
629
+ }
630
+ }
599
631
  }
600
632
  return false;
633
+ },
634
+ keyup: function keyup(view, event) {
635
+ if (!event.repeat && event.key === 'Shift') {
636
+ view.dispatch(view.state.tr.setMeta(key, _objectSpread(_objectSpread({}, view.state.tr.getMeta(key)), {}, {
637
+ isShiftDown: false
638
+ })));
639
+ }
601
640
  }
602
641
  }
603
642
  },
@@ -622,10 +661,10 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
622
661
  // Ignored via go/ees005
623
662
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
624
663
  var editorWidthLeft = _editorContentArea.getBoundingClientRect().left;
625
- transaction.setMeta(key, {
664
+ transaction.setMeta(key, _objectSpread(_objectSpread({}, transaction.getMeta(key)), {}, {
626
665
  editorWidthLeft: editorWidthLeft,
627
666
  editorWidthRight: editorWidthRight
628
- });
667
+ }));
629
668
  }
630
669
  editorView.dispatch(transaction);
631
670
  }
@@ -57,7 +57,7 @@ export var getSelection = function getSelection(tr, start) {
57
57
  var _getInlineNodePos = getInlineNodePos(tr, start, nodeSize),
58
58
  inlineNodePos = _getInlineNodePos.inlineNodePos,
59
59
  inlineNodeEndPos = _getInlineNodePos.inlineNodeEndPos;
60
- return new TextSelection(tr.doc.resolve(inlineNodeEndPos), tr.doc.resolve(inlineNodePos));
60
+ return new TextSelection(tr.doc.resolve(inlineNodePos), tr.doc.resolve(inlineNodeEndPos));
61
61
  }
62
62
  };
63
63
  export var selectNode = function selectNode(tr, start, nodeType) {
@@ -1,3 +1,4 @@
1
+ import { TextSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
1
2
  import { key } from '../main';
2
3
  export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(api, pos, tr) {
3
4
  var _api$blockControls, _pluginState$multiSel, _tr$getMeta;
@@ -10,7 +11,7 @@ export var getMultiSelectionIfPosInside = function getMultiSelectionIfPosInside(
10
11
  var multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
11
12
 
12
13
  // We subtract one as the handle position is before the node
13
- return pos >= multiFrom - 1 && pos <= multiTo ? {
14
+ return pos >= multiFrom - 1 && pos < multiTo ? {
14
15
  anchor: multiSelectDnD.anchor,
15
16
  head: multiSelectDnD.head
16
17
  } : {};
@@ -28,12 +29,41 @@ export var getSelectedSlicePosition = function getSelectedSlicePosition(handlePo
28
29
  anchor = _getMultiSelectionIfP.anchor,
29
30
  head = _getMultiSelectionIfP.head;
30
31
  var inSelection = anchor !== undefined && head !== undefined;
31
- var from = inSelection ? Math.min(anchor, head) : handlePos;
32
+ var from = inSelection ? Math.min(anchor || 0, head || 0) : handlePos;
32
33
  var activeNode = tr.doc.nodeAt(handlePos);
33
34
  var activeNodeEndPos = handlePos + ((_activeNode$nodeSize = activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeSize) !== null && _activeNode$nodeSize !== void 0 ? _activeNode$nodeSize : 1);
34
- var to = inSelection ? Math.max(anchor, head) : activeNodeEndPos;
35
+ var to = inSelection ? Math.max(anchor || 0, head || 0) : activeNodeEndPos;
35
36
  return {
36
37
  from: from,
37
38
  to: to
38
39
  };
40
+ };
41
+
42
+ /**
43
+ * Takes a position and expands the selection to encompass the node at that position. Ignores empty or out of range selections.
44
+ * Ignores positions that are in text blocks (i.e. not start of a node)
45
+ * @returns TextSelection if expanded, otherwise returns Selection that was passed in.
46
+ */
47
+ export var expandSelectionHeadToNodeAtPos = function expandSelectionHeadToNodeAtPos(selection, nodePos) {
48
+ var doc = selection.$anchor.doc;
49
+ if (nodePos < 0 || nodePos > doc.nodeSize - 2 || selection.empty) {
50
+ return selection;
51
+ }
52
+ var $pos = doc.resolve(nodePos);
53
+ var node = $pos.nodeAfter;
54
+ if ($pos.node().isTextblock || !node) {
55
+ return selection;
56
+ }
57
+ var $newHead = nodePos < selection.anchor ? $pos : doc.resolve(node.nodeSize + nodePos);
58
+ var textSelection = new TextSelection(selection.$anchor, $newHead);
59
+ return textSelection;
60
+ };
61
+
62
+ /**
63
+ * This swaps the anchor/head for NodeSelections when its anchor > pos.
64
+ * This is because NodeSelection always has an anchor at the start of the node,
65
+ * which may not align with the existing selection.
66
+ */
67
+ export var alignAnchorHeadInDirectionOfPos = function alignAnchorHeadInDirectionOfPos(selection, pos) {
68
+ return selection instanceof NodeSelection && Math.max(pos, selection.anchor) === selection.anchor ? new TextSelection(selection.$head, selection.$anchor) : selection;
39
69
  };
@@ -20,6 +20,14 @@ export var DRAG_HANDLE_H5_TOP_ADJUSTMENT = 3;
20
20
  export var DRAG_HANDLE_H6_TOP_ADJUSTMENT = 3;
21
21
  export var DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = 8;
22
22
  export var DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
23
+
24
+ /** We only want to shift-select nodes that are at the top level of a document.
25
+ * This is because funky things happen when selecting inside of tableCells, but we
26
+ * also want to avoid heavily nested cases to descope potential corner cases.
27
+ * Various top level nodes have their selection 'from' at depths other than 0,
28
+ * so we allow for some leniency to capture them all. e.g. Table is depth 3.
29
+ */
30
+ export var DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
23
31
  var nodeTypeExcludeList = ['embedCard', 'mediaSingle', 'table'];
24
32
  export var dragHandleGap = function dragHandleGap(nodeType, parentNodeType) {
25
33
  if (nodeType === 'layoutSection' && fg('platform_editor_advanced_layouts_post_fix_patch_2')) {
@@ -30,7 +30,8 @@ import { key } from '../pm-plugins/main';
30
30
  import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
31
31
  import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
32
32
  import { isHandleCorrelatedToSelection, selectNode } from '../pm-plugins/utils/getSelection';
33
- import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, topPositionAdjustment } from './consts';
33
+ import { alignAnchorHeadInDirectionOfPos, expandSelectionHeadToNodeAtPos } from '../pm-plugins/utils/selection';
34
+ import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, nodeMargins, spacingBetweenNodesForPreview, topPositionAdjustment } from './consts';
34
35
  import { dragPreview } from './drag-preview';
35
36
  var iconWrapperStyles = xcss({
36
37
  display: 'flex',
@@ -66,6 +67,13 @@ var dragHandleButtonStyles = css({
66
67
  },
67
68
  '&:focus': {
68
69
  outline: "2px solid ".concat("var(--ds-border-focused, #388BFF)")
70
+ },
71
+ '&:disabled': {
72
+ color: "var(--ds-icon-disabled, #8993A4)",
73
+ backgroundColor: 'transparent'
74
+ },
75
+ '&:hover:disabled': {
76
+ backgroundColor: "var(--ds-background-disabled, transparent)"
69
77
  }
70
78
  });
71
79
  var dragHandleMultiLineSelectionFixFirefox = css({
@@ -112,7 +120,7 @@ var getNodeSpacingForPreview = function getNodeSpacingForPreview(node) {
112
120
  return spacingBetweenNodesForPreview[nodeTypeName] || spacingBetweenNodesForPreview['default'];
113
121
  };
114
122
  export var DragHandle = function DragHandle(_ref) {
115
- var _api$core2, _api$analytics2, _api$core4;
123
+ var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
116
124
  var view = _ref.view,
117
125
  api = _ref.api,
118
126
  formatMessage = _ref.formatMessage,
@@ -132,9 +140,15 @@ export var DragHandle = function DragHandle(_ref) {
132
140
  _useState4 = _slicedToArray(_useState3, 2),
133
141
  dragHandleSelected = _useState4[0],
134
142
  setDragHandleSelected = _useState4[1];
143
+ var _useState5 = useState(false),
144
+ _useState6 = _slicedToArray(_useState5, 2),
145
+ dragHandleDisabled = _useState6[0],
146
+ setDragHandleDisabled = _useState6[1];
135
147
  var _useSharedPluginState = useSharedPluginState(api, ['featureFlags']),
136
148
  featureFlagsState = _useSharedPluginState.featureFlagsState;
137
149
  var selection = useSharedPluginStateSelector(api, 'selection.selection');
150
+ var isShiftDown = useSharedPluginStateSelector(api, 'blockControls.isShiftDown');
151
+ var multiSelectDnD = useSharedPluginStateSelector(api, 'blockControls.multiSelectDnD');
138
152
  var isLayoutColumn = nodeType === 'layoutColumn';
139
153
  var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
140
154
  exposure: true
@@ -156,9 +170,11 @@ export var DragHandle = function DragHandle(_ref) {
156
170
  }
157
171
  }
158
172
  }, [anchorName, nodeType, view.dom]);
159
- var handleOnClick = useCallback(function () {
173
+ var handleOnClick = useCallback(function (e) {
160
174
  var _api$core;
161
- setDragHandleSelected(!dragHandleSelected);
175
+ if (!isMultiSelect) {
176
+ setDragHandleSelected(!dragHandleSelected);
177
+ }
162
178
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
163
179
  var _api$analytics;
164
180
  var tr = _ref2.tr;
@@ -166,7 +182,24 @@ export var DragHandle = function DragHandle(_ref) {
166
182
  if (startPos === undefined) {
167
183
  return tr;
168
184
  }
169
- tr = selectNode(tr, startPos, nodeType);
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;
186
+ if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
187
+ tr = selectNode(tr, startPos, nodeType);
188
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
189
+ var _api$blockControls;
190
+ api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu()({
191
+ tr: tr
192
+ });
193
+ }
194
+ } else if (isTopLevelNode && $anchor.depth <= DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
195
+ var _api$blockControls2;
196
+ var alignAnchorHeadToSel = alignAnchorHeadInDirectionOfPos(tr.selection, startPos);
197
+ var selectionWithExpandedHead = expandSelectionHeadToNodeAtPos(alignAnchorHeadToSel, startPos);
198
+ tr.setSelection(selectionWithExpandedHead);
199
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.setMultiSelectPositions()({
200
+ tr: tr
201
+ });
202
+ }
170
203
  var resolvedMovingNode = tr.doc.resolve(startPos);
171
204
  var maybeNode = resolvedMovingNode.nodeAfter;
172
205
  tr.setMeta('scrollIntoView', false);
@@ -183,14 +216,7 @@ export var DragHandle = function DragHandle(_ref) {
183
216
  return tr;
184
217
  });
185
218
  view.focus();
186
- if (editorExperiment('platform_editor_controls', 'variant1')) {
187
- var startPos = getPos();
188
- if (startPos === undefined) {
189
- return false;
190
- }
191
- api === null || api === void 0 || api.core.actions.execute(api.blockControls.commands.toggleBlockMenu());
192
- }
193
- }, [dragHandleSelected, 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 ? void 0 : api.blockControls.commands, view, getPos, nodeType]);
219
+ }, [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]);
194
220
 
195
221
  // TODO - This needs to be investigated further. Drag preview generation is not always working
196
222
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -210,7 +236,6 @@ export var DragHandle = function DragHandle(_ref) {
210
236
  var handleKeyDown = useCallback(function (e) {
211
237
  if (fg('platform_editor_element_drag_and_drop_ed_23873')) {
212
238
  // allow user to use spacebar to select the node
213
-
214
239
  if (!e.repeat && e.key === ' ') {
215
240
  var _api$core3;
216
241
  var startPos = getPos();
@@ -226,9 +251,9 @@ export var DragHandle = function DragHandle(_ref) {
226
251
  var $startPos = tr.doc.resolve(startPos + node.nodeSize);
227
252
  var selection = new TextSelection($startPos);
228
253
  tr.setSelection(selection);
229
- tr.setMeta(key, {
254
+ !isMultiSelect && tr.setMeta(key, {
230
255
  pos: startPos
231
- }); ////WHERE IS THIS USED?
256
+ });
232
257
  return tr;
233
258
  });
234
259
  } else if (![e.altKey, e.ctrlKey, e.shiftKey].some(function (pressed) {
@@ -239,7 +264,7 @@ export var DragHandle = function DragHandle(_ref) {
239
264
  view.focus();
240
265
  }
241
266
  }
242
- }, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, view]);
267
+ }, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, isMultiSelect, view]);
243
268
  useEffect(function () {
244
269
  var element = buttonRef.current;
245
270
  if (!element) {
@@ -254,7 +279,6 @@ export var DragHandle = function DragHandle(_ref) {
254
279
  };
255
280
  },
256
281
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
257
- var _api$blockControls2;
258
282
  var nativeSetDragImage = _ref4.nativeSetDragImage;
259
283
  if (isMultiSelect) {
260
284
  var _api$core5;
@@ -265,8 +289,8 @@ export var DragHandle = function DragHandle(_ref) {
265
289
  return tr;
266
290
  }
267
291
  if (!tr.selection.empty && handlePos >= tr.selection.$from.start() - 1 && handlePos <= tr.selection.to) {
268
- var _api$blockControls;
269
- api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.setMultiSelectPositions()({
292
+ var _api$blockControls4;
293
+ api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.setMultiSelectPositions()({
270
294
  tr: tr
271
295
  });
272
296
  }
@@ -277,8 +301,6 @@ export var DragHandle = function DragHandle(_ref) {
277
301
  var state = view.state;
278
302
  var doc = state.doc,
279
303
  selection = state.selection;
280
- var _ref6 = (api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.sharedState.currentState()) || {},
281
- multiSelectDnD = _ref6.multiSelectDnD;
282
304
  var sliceFrom = selection.from;
283
305
  var sliceTo = selection.to;
284
306
  if (multiSelectDnD) {
@@ -288,7 +310,7 @@ export var DragHandle = function DragHandle(_ref) {
288
310
  sliceTo = Math.max(anchor, head);
289
311
  }
290
312
  var expandedSlice = doc.slice(sliceFrom, sliceTo);
291
- var isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos <= sliceTo && expandedSlice.content.childCount > 1;
313
+ var isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos < sliceTo && expandedSlice.content.childCount > 1;
292
314
  setCustomNativeDragPreview({
293
315
  getOffset: function getOffset() {
294
316
  if (!isDraggingMultiLine) {
@@ -335,8 +357,8 @@ export var DragHandle = function DragHandle(_ref) {
335
357
  };
336
358
  }
337
359
  },
338
- render: function render(_ref7) {
339
- var container = _ref7.container;
360
+ render: function render(_ref6) {
361
+ var container = _ref6.container;
340
362
  var dom = view.dom.querySelector("[data-drag-handler-anchor-name=\"".concat(anchorName, "\"]"));
341
363
  if (!dom) {
342
364
  return;
@@ -372,13 +394,12 @@ export var DragHandle = function DragHandle(_ref) {
372
394
  if (start === undefined) {
373
395
  return;
374
396
  }
375
- api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref8) {
376
- var _tr$getMeta, _api$blockControls3, _api$analytics3;
377
- var tr = _ref8.tr;
397
+ api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref7) {
398
+ var _api$blockControls5, _api$analytics3;
399
+ var tr = _ref7.tr;
378
400
  var nodeTypes, hasSelectedMultipleNodes;
379
401
  var resolvedMovingNode = tr.doc.resolve(start);
380
402
  var maybeNode = resolvedMovingNode.nodeAfter;
381
- var multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
382
403
  if (multiSelectDnD) {
383
404
  var attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
384
405
  nodeTypes = attributes.nodeTypes;
@@ -387,7 +408,7 @@ export var DragHandle = function DragHandle(_ref) {
387
408
  nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
388
409
  hasSelectedMultipleNodes = false;
389
410
  }
390
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.setNodeDragged(getPos, anchorName, nodeType)({
411
+ api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.setNodeDragged(getPos, anchorName, nodeType)({
391
412
  tr: tr
392
413
  });
393
414
  tr.setMeta('scrollIntoView', false);
@@ -409,7 +430,7 @@ export var DragHandle = function DragHandle(_ref) {
409
430
  view.focus();
410
431
  }
411
432
  });
412
- }, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
433
+ }, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
413
434
  var macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
414
435
  var calculatePosition = useCallback(function () {
415
436
  var parentNodeType;
@@ -452,12 +473,12 @@ export var DragHandle = function DragHandle(_ref) {
452
473
  top: getTopPosition(dom, nodeType)
453
474
  };
454
475
  }, [anchorName, nodeType, view, blockCardWidth, macroInteractionUpdates, getPos, isLayoutColumn]);
455
- var _useState5 = useState({
476
+ var _useState7 = useState({
456
477
  display: 'none'
457
478
  }),
458
- _useState6 = _slicedToArray(_useState5, 2),
459
- positionStyles = _useState6[0],
460
- setPositionStyles = _useState6[1];
479
+ _useState8 = _slicedToArray(_useState7, 2),
480
+ positionStyles = _useState8[0],
481
+ setPositionStyles = _useState8[1];
461
482
  useEffect(function () {
462
483
  var cleanUpTransitionListener;
463
484
  if (nodeType === 'extension' || nodeType === 'embedCard') {
@@ -499,6 +520,17 @@ export var DragHandle = function DragHandle(_ref) {
499
520
  }
500
521
  setDragHandleSelected(isHandleCorrelatedToSelection(view.state, selection, start));
501
522
  }, [start, selection, view.state, isMultiSelect]);
523
+ useEffect(function () {
524
+ if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
525
+ return;
526
+ }
527
+ 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;
528
+ if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
529
+ setDragHandleDisabled(true);
530
+ } else {
531
+ setDragHandleDisabled(false);
532
+ }
533
+ }, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
502
534
  var helpDescriptors = isTopLevelNode && fg('platform_editor_advanced_layouts_accessibility') ? [{
503
535
  description: formatMessage(blockControlsMessages.dragToMove)
504
536
  }, {
@@ -586,6 +618,7 @@ export var DragHandle = function DragHandle(_ref) {
586
618
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
587
619
  ,
588
620
  onDrop: handleOnDrop,
621
+ disabled: dragHandleDisabled,
589
622
  "data-testid": "block-ctrl-drag-handle"
590
623
  }, jsx(Box, {
591
624
  as: "span",
@@ -593,13 +626,13 @@ export var DragHandle = function DragHandle(_ref) {
593
626
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
594
627
  ,
595
628
  onDragStart: handleIconDragStart
596
- }, ' ', jsx(DragHandlerIcon, {
629
+ }, jsx(DragHandlerIcon, {
597
630
  label: "",
598
631
  size: "medium"
599
632
  })))
600
633
  );
601
634
  };
602
- return fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
635
+ return !dragHandleDisabled && fg('platform_editor_element_drag_and_drop_ed_23873') ? jsx(Tooltip, {
603
636
  content: jsx(TooltipContentWithMultipleShortcuts, {
604
637
  helpDescriptors: helpDescriptors
605
638
  }),
@@ -42,6 +42,7 @@ export interface PluginState {
42
42
  */
43
43
  isPMDragging: boolean;
44
44
  multiSelectDnD?: MultiSelectDnD;
45
+ isShiftDown?: boolean;
45
46
  }
46
47
  export type ReleaseHiddenDecoration = () => boolean | undefined;
47
48
  export type BlockControlsSharedState = {
@@ -50,6 +51,7 @@ export type BlockControlsSharedState = {
50
51
  isDragging: boolean;
51
52
  isPMDragging: boolean;
52
53
  multiSelectDnD?: MultiSelectDnD;
54
+ isShiftDown?: boolean;
53
55
  } | undefined;
54
56
  export type HandleOptions = {
55
57
  isFocused: boolean;
@@ -24,7 +24,8 @@ export declare const newApply: (api: ExtractInjectionAPI<BlockControlsPlugin> |
24
24
  isResizerResizing: boolean;
25
25
  isDocSizeLimitEnabled: boolean | null;
26
26
  isPMDragging: any;
27
- multiSelectDnD: any;
27
+ multiSelectDnD: import("../blockControlsPluginType").MultiSelectDnD | undefined;
28
+ isShiftDown: any;
28
29
  };
29
30
  export declare const oldApply: (api: ExtractInjectionAPI<BlockControlsPlugin> | undefined, formatMessage: IntlShape['formatMessage'], tr: ReadonlyTransaction, currentState: PluginState, oldState: EditorState, newState: EditorState, flags: FlagType, nodeViewPortalProviderAPI: PortalProviderAPI, anchorRectCache?: AnchorRectCache) => {
30
31
  decorations: DecorationSet;
@@ -1,5 +1,5 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
- import { type Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ import { type Transaction, type Selection } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { BlockControlsPlugin } from '../../blockControlsPluginType';
4
4
  export declare const getMultiSelectionIfPosInside: (api: ExtractInjectionAPI<BlockControlsPlugin>, pos: number, tr?: Transaction) => {
5
5
  anchor?: number;
@@ -13,3 +13,15 @@ export declare const getSelectedSlicePosition: (handlePos: number, tr: Transacti
13
13
  from: number;
14
14
  to: number;
15
15
  };
16
+ /**
17
+ * Takes a position and expands the selection to encompass the node at that position. Ignores empty or out of range selections.
18
+ * Ignores positions that are in text blocks (i.e. not start of a node)
19
+ * @returns TextSelection if expanded, otherwise returns Selection that was passed in.
20
+ */
21
+ export declare const expandSelectionHeadToNodeAtPos: (selection: Selection, nodePos: number) => Selection;
22
+ /**
23
+ * This swaps the anchor/head for NodeSelections when its anchor > pos.
24
+ * This is because NodeSelection always has an anchor at the start of the node,
25
+ * which may not align with the existing selection.
26
+ */
27
+ export declare const alignAnchorHeadInDirectionOfPos: (selection: Selection, pos: number) => Selection;
@@ -15,6 +15,13 @@ export declare const DRAG_HANDLE_H5_TOP_ADJUSTMENT = 3;
15
15
  export declare const DRAG_HANDLE_H6_TOP_ADJUSTMENT = 3;
16
16
  export declare const DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = 8;
17
17
  export declare const DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = 2;
18
+ /** We only want to shift-select nodes that are at the top level of a document.
19
+ * This is because funky things happen when selecting inside of tableCells, but we
20
+ * also want to avoid heavily nested cases to descope potential corner cases.
21
+ * Various top level nodes have their selection 'from' at depths other than 0,
22
+ * so we allow for some leniency to capture them all. e.g. Table is depth 3.
23
+ */
24
+ export declare const DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = 3;
18
25
  export declare const dragHandleGap: (nodeType: string, parentNodeType?: string) => number;
19
26
  export declare const getNestedNodeLeftPaddingMargin: (nodeType?: string) => "8px" | "16px" | "20px" | "24px" | "28px" | "40px";
20
27
  export declare const topPositionAdjustment: (nodeType: string) => number;
@@ -42,6 +42,7 @@ export interface PluginState {
42
42
  */
43
43
  isPMDragging: boolean;
44
44
  multiSelectDnD?: MultiSelectDnD;
45
+ isShiftDown?: boolean;
45
46
  }
46
47
  export type ReleaseHiddenDecoration = () => boolean | undefined;
47
48
  export type BlockControlsSharedState = {
@@ -50,6 +51,7 @@ export type BlockControlsSharedState = {
50
51
  isDragging: boolean;
51
52
  isPMDragging: boolean;
52
53
  multiSelectDnD?: MultiSelectDnD;
54
+ isShiftDown?: boolean;
53
55
  } | undefined;
54
56
  export type HandleOptions = {
55
57
  isFocused: boolean;
@@ -24,7 +24,8 @@ export declare const newApply: (api: ExtractInjectionAPI<BlockControlsPlugin> |
24
24
  isResizerResizing: boolean;
25
25
  isDocSizeLimitEnabled: boolean | null;
26
26
  isPMDragging: any;
27
- multiSelectDnD: any;
27
+ multiSelectDnD: import("../blockControlsPluginType").MultiSelectDnD | undefined;
28
+ isShiftDown: any;
28
29
  };
29
30
  export declare const oldApply: (api: ExtractInjectionAPI<BlockControlsPlugin> | undefined, formatMessage: IntlShape['formatMessage'], tr: ReadonlyTransaction, currentState: PluginState, oldState: EditorState, newState: EditorState, flags: FlagType, nodeViewPortalProviderAPI: PortalProviderAPI, anchorRectCache?: AnchorRectCache) => {
30
31
  decorations: DecorationSet;