@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
@@ -30,6 +30,7 @@ var _main = require("../pm-plugins/main");
30
30
  var _analytics2 = require("../pm-plugins/utils/analytics");
31
31
  var _dragHandlePositions = require("../pm-plugins/utils/drag-handle-positions");
32
32
  var _getSelection = require("../pm-plugins/utils/getSelection");
33
+ var _selection = require("../pm-plugins/utils/selection");
33
34
  var _consts = require("./consts");
34
35
  var _dragPreview = require("./drag-preview");
35
36
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -71,6 +72,13 @@ var dragHandleButtonStyles = (0, _react2.css)({
71
72
  },
72
73
  '&:focus': {
73
74
  outline: "2px solid ".concat("var(--ds-border-focused, #388BFF)")
75
+ },
76
+ '&:disabled': {
77
+ color: "var(--ds-icon-disabled, #8993A4)",
78
+ backgroundColor: 'transparent'
79
+ },
80
+ '&:hover:disabled': {
81
+ backgroundColor: "var(--ds-background-disabled, transparent)"
74
82
  }
75
83
  });
76
84
  var dragHandleMultiLineSelectionFixFirefox = (0, _react2.css)({
@@ -117,7 +125,7 @@ var getNodeSpacingForPreview = function getNodeSpacingForPreview(node) {
117
125
  return _consts.spacingBetweenNodesForPreview[nodeTypeName] || _consts.spacingBetweenNodesForPreview['default'];
118
126
  };
119
127
  var DragHandle = exports.DragHandle = function DragHandle(_ref) {
120
- var _api$core2, _api$analytics2, _api$core4;
128
+ var _api$core2, _api$analytics2, _api$blockControls3, _api$core4;
121
129
  var view = _ref.view,
122
130
  api = _ref.api,
123
131
  formatMessage = _ref.formatMessage,
@@ -137,9 +145,15 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
137
145
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
138
146
  dragHandleSelected = _useState4[0],
139
147
  setDragHandleSelected = _useState4[1];
148
+ var _useState5 = (0, _react.useState)(false),
149
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
150
+ dragHandleDisabled = _useState6[0],
151
+ setDragHandleDisabled = _useState6[1];
140
152
  var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['featureFlags']),
141
153
  featureFlagsState = _useSharedPluginState.featureFlagsState;
142
154
  var selection = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'selection.selection');
155
+ var isShiftDown = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'blockControls.isShiftDown');
156
+ var multiSelectDnD = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'blockControls.multiSelectDnD');
143
157
  var isLayoutColumn = nodeType === 'layoutColumn';
144
158
  var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
145
159
  exposure: true
@@ -161,9 +175,11 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
161
175
  }
162
176
  }
163
177
  }, [anchorName, nodeType, view.dom]);
164
- var handleOnClick = (0, _react.useCallback)(function () {
178
+ var handleOnClick = (0, _react.useCallback)(function (e) {
165
179
  var _api$core;
166
- setDragHandleSelected(!dragHandleSelected);
180
+ if (!isMultiSelect) {
181
+ setDragHandleSelected(!dragHandleSelected);
182
+ }
167
183
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
168
184
  var _api$analytics;
169
185
  var tr = _ref2.tr;
@@ -171,7 +187,24 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
171
187
  if (startPos === undefined) {
172
188
  return tr;
173
189
  }
174
- tr = (0, _getSelection.selectNode)(tr, startPos, nodeType);
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;
191
+ if (!isMultiSelect || tr.selection.empty || !e.shiftKey) {
192
+ tr = (0, _getSelection.selectNode)(tr, startPos, nodeType);
193
+ if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
194
+ var _api$blockControls;
195
+ api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu()({
196
+ tr: tr
197
+ });
198
+ }
199
+ } else if (isTopLevelNode && $anchor.depth <= _consts.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey) {
200
+ var _api$blockControls2;
201
+ var alignAnchorHeadToSel = (0, _selection.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
202
+ var selectionWithExpandedHead = (0, _selection.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
203
+ tr.setSelection(selectionWithExpandedHead);
204
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.setMultiSelectPositions()({
205
+ tr: tr
206
+ });
207
+ }
175
208
  var resolvedMovingNode = tr.doc.resolve(startPos);
176
209
  var maybeNode = resolvedMovingNode.nodeAfter;
177
210
  tr.setMeta('scrollIntoView', false);
@@ -188,14 +221,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
188
221
  return tr;
189
222
  });
190
223
  view.focus();
191
- if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
192
- var startPos = getPos();
193
- if (startPos === undefined) {
194
- return false;
195
- }
196
- api === null || api === void 0 || api.core.actions.execute(api.blockControls.commands.toggleBlockMenu());
197
- }
198
- }, [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]);
224
+ }, [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]);
199
225
 
200
226
  // TODO - This needs to be investigated further. Drag preview generation is not always working
201
227
  // as expected with a node selection. This workaround sets the selection to the node on mouseDown,
@@ -215,7 +241,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
215
241
  var handleKeyDown = (0, _react.useCallback)(function (e) {
216
242
  if ((0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873')) {
217
243
  // allow user to use spacebar to select the node
218
-
219
244
  if (!e.repeat && e.key === ' ') {
220
245
  var _api$core3;
221
246
  var startPos = getPos();
@@ -231,9 +256,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
231
256
  var $startPos = tr.doc.resolve(startPos + node.nodeSize);
232
257
  var selection = new _state.TextSelection($startPos);
233
258
  tr.setSelection(selection);
234
- tr.setMeta(_main.key, {
259
+ !isMultiSelect && tr.setMeta(_main.key, {
235
260
  pos: startPos
236
- }); ////WHERE IS THIS USED?
261
+ });
237
262
  return tr;
238
263
  });
239
264
  } else if (![e.altKey, e.ctrlKey, e.shiftKey].some(function (pressed) {
@@ -244,7 +269,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
244
269
  view.focus();
245
270
  }
246
271
  }
247
- }, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, view]);
272
+ }, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, isMultiSelect, view]);
248
273
  (0, _react.useEffect)(function () {
249
274
  var element = buttonRef.current;
250
275
  if (!element) {
@@ -259,7 +284,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
259
284
  };
260
285
  },
261
286
  onGenerateDragPreview: function onGenerateDragPreview(_ref4) {
262
- var _api$blockControls2;
263
287
  var nativeSetDragImage = _ref4.nativeSetDragImage;
264
288
  if (isMultiSelect) {
265
289
  var _api$core5;
@@ -270,8 +294,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
270
294
  return tr;
271
295
  }
272
296
  if (!tr.selection.empty && handlePos >= tr.selection.$from.start() - 1 && handlePos <= tr.selection.to) {
273
- var _api$blockControls;
274
- api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.setMultiSelectPositions()({
297
+ var _api$blockControls4;
298
+ api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.setMultiSelectPositions()({
275
299
  tr: tr
276
300
  });
277
301
  }
@@ -282,8 +306,6 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
282
306
  var state = view.state;
283
307
  var doc = state.doc,
284
308
  selection = state.selection;
285
- var _ref6 = (api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.sharedState.currentState()) || {},
286
- multiSelectDnD = _ref6.multiSelectDnD;
287
309
  var sliceFrom = selection.from;
288
310
  var sliceTo = selection.to;
289
311
  if (multiSelectDnD) {
@@ -293,7 +315,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
293
315
  sliceTo = Math.max(anchor, head);
294
316
  }
295
317
  var expandedSlice = doc.slice(sliceFrom, sliceTo);
296
- var isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos <= sliceTo && expandedSlice.content.childCount > 1;
318
+ var isDraggingMultiLine = isMultiSelect && startPos !== undefined && startPos >= sliceFrom && startPos < sliceTo && expandedSlice.content.childCount > 1;
297
319
  (0, _setCustomNativeDragPreview.setCustomNativeDragPreview)({
298
320
  getOffset: function getOffset() {
299
321
  if (!isDraggingMultiLine) {
@@ -340,8 +362,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
340
362
  };
341
363
  }
342
364
  },
343
- render: function render(_ref7) {
344
- var container = _ref7.container;
365
+ render: function render(_ref6) {
366
+ var container = _ref6.container;
345
367
  var dom = view.dom.querySelector("[data-drag-handler-anchor-name=\"".concat(anchorName, "\"]"));
346
368
  if (!dom) {
347
369
  return;
@@ -377,13 +399,12 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
377
399
  if (start === undefined) {
378
400
  return;
379
401
  }
380
- api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref8) {
381
- var _tr$getMeta, _api$blockControls3, _api$analytics3;
382
- var tr = _ref8.tr;
402
+ api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref7) {
403
+ var _api$blockControls5, _api$analytics3;
404
+ var tr = _ref7.tr;
383
405
  var nodeTypes, hasSelectedMultipleNodes;
384
406
  var resolvedMovingNode = tr.doc.resolve(start);
385
407
  var maybeNode = resolvedMovingNode.nodeAfter;
386
- var multiSelectDnD = (_tr$getMeta = tr.getMeta(_main.key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
387
408
  if (multiSelectDnD) {
388
409
  var attributes = (0, _analytics2.getMultiSelectAnalyticsAttributes)(tr, multiSelectDnD.anchor, multiSelectDnD.head);
389
410
  nodeTypes = attributes.nodeTypes;
@@ -392,7 +413,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
392
413
  nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
393
414
  hasSelectedMultipleNodes = false;
394
415
  }
395
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.setNodeDragged(getPos, anchorName, nodeType)({
416
+ api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.setNodeDragged(getPos, anchorName, nodeType)({
396
417
  tr: tr
397
418
  });
398
419
  tr.setMeta('scrollIntoView', false);
@@ -414,7 +435,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
414
435
  view.focus();
415
436
  }
416
437
  });
417
- }, [anchorName, api, getPos, isMultiSelect, nodeType, start, view]);
438
+ }, [anchorName, api, getPos, isMultiSelect, multiSelectDnD, nodeType, start, view]);
418
439
  var macroInteractionUpdates = featureFlagsState === null || featureFlagsState === void 0 ? void 0 : featureFlagsState.macroInteractionUpdates;
419
440
  var calculatePosition = (0, _react.useCallback)(function () {
420
441
  var parentNodeType;
@@ -457,12 +478,12 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
457
478
  top: (0, _dragHandlePositions.getTopPosition)(dom, nodeType)
458
479
  };
459
480
  }, [anchorName, nodeType, view, blockCardWidth, macroInteractionUpdates, getPos, isLayoutColumn]);
460
- var _useState5 = (0, _react.useState)({
481
+ var _useState7 = (0, _react.useState)({
461
482
  display: 'none'
462
483
  }),
463
- _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
464
- positionStyles = _useState6[0],
465
- setPositionStyles = _useState6[1];
484
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
485
+ positionStyles = _useState8[0],
486
+ setPositionStyles = _useState8[1];
466
487
  (0, _react.useEffect)(function () {
467
488
  var cleanUpTransitionListener;
468
489
  if (nodeType === 'extension' || nodeType === 'embedCard') {
@@ -504,6 +525,17 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
504
525
  }
505
526
  setDragHandleSelected((0, _getSelection.isHandleCorrelatedToSelection)(view.state, selection, start));
506
527
  }, [start, selection, view.state, isMultiSelect]);
528
+ (0, _react.useEffect)(function () {
529
+ if (!isMultiSelect || isShiftDown === undefined || view.state.selection.empty) {
530
+ return;
531
+ }
532
+ 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;
533
+ if (isShiftDown && (!isTopLevelNode || isTopLevelNode && $anchor.depth > _consts.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH)) {
534
+ setDragHandleDisabled(true);
535
+ } else {
536
+ setDragHandleDisabled(false);
537
+ }
538
+ }, [isMultiSelect, isShiftDown, isTopLevelNode, multiSelectDnD === null || multiSelectDnD === void 0 ? void 0 : multiSelectDnD.anchor, view.state.doc, view.state.selection]);
507
539
  var helpDescriptors = isTopLevelNode && (0, _platformFeatureFlags.fg)('platform_editor_advanced_layouts_accessibility') ? [{
508
540
  description: formatMessage(_messages.blockControlsMessages.dragToMove)
509
541
  }, {
@@ -591,6 +623,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
591
623
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
592
624
  ,
593
625
  onDrop: handleOnDrop,
626
+ disabled: dragHandleDisabled,
594
627
  "data-testid": "block-ctrl-drag-handle"
595
628
  }, (0, _react2.jsx)(_primitives.Box, {
596
629
  as: "span",
@@ -598,13 +631,13 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
598
631
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
599
632
  ,
600
633
  onDragStart: handleIconDragStart
601
- }, ' ', (0, _react2.jsx)(_dragHandler.default, {
634
+ }, (0, _react2.jsx)(_dragHandler.default, {
602
635
  label: "",
603
636
  size: "medium"
604
637
  })))
605
638
  );
606
639
  };
607
- return (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') ? (0, _react2.jsx)(_tooltip.default, {
640
+ return !dragHandleDisabled && (0, _platformFeatureFlags.fg)('platform_editor_element_drag_and_drop_ed_23873') ? (0, _react2.jsx)(_tooltip.default, {
608
641
  content: (0, _react2.jsx)(_keymaps.TooltipContentWithMultipleShortcuts, {
609
642
  helpDescriptors: helpDescriptors
610
643
  }),
@@ -5,6 +5,7 @@ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
5
5
  import { moveNode } from './editor-commands/move-node';
6
6
  import { moveToLayout } from './editor-commands/move-to-layout';
7
7
  import { createPlugin, key } from './pm-plugins/main';
8
+ import { selectNode } from './pm-plugins/utils/getSelection';
8
9
  import BlockMenu from './ui/block-menu';
9
10
  import { DragHandleMenu } from './ui/drag-handle-menu';
10
11
  import { GlobalStylesWrapper } from './ui/global-styles';
@@ -79,29 +80,40 @@ export const blockControlsPlugin = ({
79
80
  setMultiSelectPositions: (anchor, head) => ({
80
81
  tr
81
82
  }) => {
82
- var _api$selection;
83
+ var _api$selection, _$to$nodeBefore, _$from$nodeAfter;
83
84
  const {
84
85
  anchor: userAnchor,
85
86
  head: userHead
86
87
  } = tr.selection;
87
- let expandedAnchor, expandedHead;
88
+ let $expandedAnchor, $expandedHead;
88
89
  if (anchor !== undefined && head !== undefined) {
89
- expandedAnchor = tr.doc.resolve(anchor);
90
- expandedHead = tr.doc.resolve(head);
90
+ $expandedAnchor = tr.doc.resolve(anchor);
91
+ $expandedHead = tr.doc.resolve(head);
91
92
  } else {
92
93
  const expandedSelection = expandSelectionBounds(tr.selection.$anchor, tr.selection.$head);
93
- expandedAnchor = expandedSelection.$anchor;
94
- expandedHead = expandedSelection.$head;
94
+ $expandedAnchor = expandedSelection.$anchor;
95
+ $expandedHead = expandedSelection.$head;
95
96
  }
96
- api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.commands.setManualSelection(expandedAnchor.pos, expandedHead.pos)({
97
+ api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.commands.setManualSelection($expandedAnchor.pos, $expandedHead.pos)({
97
98
  tr
98
99
  });
99
- // this is to normalise the selection's boundaries to inline positions, preventing it from collapsing
100
- const expandedNormalisedSel = TextSelection.between(expandedAnchor, expandedHead);
101
- tr.setSelection(expandedNormalisedSel);
100
+ const $from = $expandedAnchor.min($expandedHead);
101
+ const $to = $expandedAnchor.max($expandedHead);
102
+ let expandedNormalisedSel;
103
+ if ($from.nodeAfter === $to.nodeBefore) {
104
+ selectNode(tr, $from.pos, $expandedAnchor.node().type.name);
105
+ expandedNormalisedSel = tr.selection;
106
+ } else if (((_$to$nodeBefore = $to.nodeBefore) === null || _$to$nodeBefore === void 0 ? void 0 : _$to$nodeBefore.type.name) === 'mediaSingle' || ((_$from$nodeAfter = $from.nodeAfter) === null || _$from$nodeAfter === void 0 ? void 0 : _$from$nodeAfter.type.name) === 'mediaSingle') {
107
+ expandedNormalisedSel = new TextSelection($expandedAnchor, $expandedHead);
108
+ tr.setSelection(expandedNormalisedSel);
109
+ } else {
110
+ // this is to normalise the selection's boundaries to inline positions, preventing it from collapsing
111
+ expandedNormalisedSel = TextSelection.between($expandedAnchor, $expandedHead);
112
+ tr.setSelection(expandedNormalisedSel);
113
+ }
102
114
  const multiSelectDnD = {
103
- anchor: expandedAnchor.pos,
104
- head: expandedHead.pos,
115
+ anchor: $expandedAnchor.pos,
116
+ head: $expandedHead.pos,
105
117
  textAnchor: expandedNormalisedSel.anchor,
106
118
  textHead: expandedNormalisedSel.head,
107
119
  userAnchor: userAnchor,
@@ -116,7 +128,7 @@ export const blockControlsPlugin = ({
116
128
  }
117
129
  },
118
130
  getSharedState(editorState) {
119
- var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4, _key$getState$multiSe, _key$getState5;
131
+ var _key$getState$isMenuO, _key$getState, _key$getState$activeN, _key$getState2, _key$getState$isDragg, _key$getState3, _key$getState$isPMDra, _key$getState4, _key$getState$multiSe, _key$getState5, _key$getState$isShift, _key$getState6;
120
132
  if (!editorState) {
121
133
  return undefined;
122
134
  }
@@ -125,7 +137,8 @@ export const blockControlsPlugin = ({
125
137
  activeNode: (_key$getState$activeN = (_key$getState2 = key.getState(editorState)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.activeNode) !== null && _key$getState$activeN !== void 0 ? _key$getState$activeN : undefined,
126
138
  isDragging: (_key$getState$isDragg = (_key$getState3 = key.getState(editorState)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.isDragging) !== null && _key$getState$isDragg !== void 0 ? _key$getState$isDragg : false,
127
139
  isPMDragging: (_key$getState$isPMDra = (_key$getState4 = key.getState(editorState)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.isPMDragging) !== null && _key$getState$isPMDra !== void 0 ? _key$getState$isPMDra : false,
128
- multiSelectDnD: (_key$getState$multiSe = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined
140
+ multiSelectDnD: (_key$getState$multiSe = (_key$getState5 = key.getState(editorState)) === null || _key$getState5 === void 0 ? void 0 : _key$getState5.multiSelectDnD) !== null && _key$getState$multiSe !== void 0 ? _key$getState$multiSe : undefined,
141
+ isShiftDown: (_key$getState$isShift = (_key$getState6 = key.getState(editorState)) === null || _key$getState6 === void 0 ? void 0 : _key$getState6.isShiftDown) !== null && _key$getState$isShift !== void 0 ? _key$getState$isShift : undefined
129
142
  };
130
143
  },
131
144
  contentComponent({
@@ -1,7 +1,7 @@
1
1
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import { expandedState } from '@atlaskit/editor-common/expand';
3
3
  import { blockControlsMessages } from '@atlaskit/editor-common/messages';
4
- import { GapCursorSelection, expandSelectionBounds } from '@atlaskit/editor-common/selection';
4
+ import { expandSelectionBounds, GapCursorSelection } from '@atlaskit/editor-common/selection';
5
5
  import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
6
6
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
7
7
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
@@ -52,19 +52,16 @@ const isDragLayoutColumnToTopLevel = ($from, $to) => {
52
52
  * @returns the start position of a node if the node can be moved, otherwise -1
53
53
  */
54
54
  const getCurrentNodePos = state => {
55
- var _activeNode$handleOpt;
56
55
  const {
57
56
  selection
58
57
  } = state;
59
- const {
60
- activeNode
61
- } = key.getState(state) || {};
62
58
  let currentNodePos = -1;
63
59
 
64
60
  // There are 3 cases when a node can be moved
65
- if (activeNode && (_activeNode$handleOpt = activeNode.handleOptions) !== null && _activeNode$handleOpt !== void 0 && _activeNode$handleOpt.isFocused) {
61
+ const focusedHandle = getFocusedHandle(state);
62
+ if (focusedHandle) {
66
63
  // 1. drag handle of the node is focused
67
- currentNodePos = activeNode.pos;
64
+ currentNodePos = focusedHandle.pos;
68
65
  } else if (isInTable(state)) {
69
66
  if (isTableSelected(selection)) {
70
67
  var _findTable$pos, _findTable;
@@ -82,6 +79,13 @@ const getCurrentNodePos = state => {
82
79
  }
83
80
  return currentNodePos;
84
81
  };
82
+ const getFocusedHandle = state => {
83
+ var _activeNode$handleOpt;
84
+ const {
85
+ activeNode
86
+ } = key.getState(state) || {};
87
+ return activeNode && (_activeNode$handleOpt = activeNode.handleOptions) !== null && _activeNode$handleOpt !== void 0 && _activeNode$handleOpt.isFocused ? activeNode : undefined;
88
+ };
85
89
  export const moveNodeViaShortcut = (api, direction, formatMessage) => {
86
90
  return state => {
87
91
  let isParentNodeOfTypeLayout;
@@ -93,20 +97,14 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
93
97
  isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
94
98
  }
95
99
  const isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
96
- let expandedAnchor, expandedHead;
97
- const pluginState = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
98
- if (pluginState !== null && pluginState !== void 0 && pluginState.multiSelectDnD) {
99
- expandedAnchor = pluginState.multiSelectDnD.anchor;
100
- expandedHead = pluginState.multiSelectDnD.head;
101
- } else {
102
- const expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
103
- expandedAnchor = expandedSelection.$anchor.pos;
104
- expandedHead = expandedSelection.$head.pos;
105
- }
106
- const currentNodePos = isMultiSelectEnabled ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
100
+ const expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
101
+ const expandedAnchor = expandedSelection.$anchor.pos;
102
+ const expandedHead = expandedSelection.$head.pos;
103
+ const currentNodePos = isMultiSelectEnabled && !getFocusedHandle(state) ? Math.min(expandedAnchor, expandedHead) : getCurrentNodePos(state);
107
104
  if (currentNodePos > -1) {
108
105
  var _state$doc$nodeAt;
109
106
  const $pos = state.doc.resolve(currentNodePos);
107
+ const nodeAfterPos = isMultiSelectEnabled && !getFocusedHandle(state) ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
110
108
  const isTopLevelNode = $pos.depth === 0;
111
109
  let moveToPos = -1;
112
110
  const nodeIndex = $pos.index();
@@ -216,7 +214,6 @@ export const moveNodeViaShortcut = (api, direction, formatMessage) => {
216
214
  }
217
215
  } else {
218
216
  const endOfDoc = $pos.end();
219
- const nodeAfterPos = isMultiSelectEnabled ? Math.max(expandedAnchor, expandedHead) : $pos.posAtIndex($pos.index() + 1);
220
217
  if (nodeAfterPos > endOfDoc) {
221
218
  return false;
222
219
  }
@@ -295,8 +292,8 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
295
292
  const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
296
293
  exposure: true
297
294
  });
295
+ const slicePosition = getSelectedSlicePosition(start, tr, api);
298
296
  if (isMultiSelect) {
299
- const slicePosition = getSelectedSlicePosition(start, tr, api);
300
297
  sliceFrom = slicePosition.from;
301
298
  sliceTo = slicePosition.to;
302
299
  const attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
@@ -1,4 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import ReactDOM from 'react-dom';
2
3
  import uuid from 'uuid';
3
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
5
  export const TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
@@ -29,9 +30,6 @@ export const unmountDecorations = (nodeViewPortalProviderAPI, selector, key) =>
29
30
  // as it was more responsive and causes less re-rendering
30
31
  const decorationsToRemove = document.querySelectorAll(`[${selector}="true"]`);
31
32
  decorationsToRemove.forEach(el => {
32
- const nodeKey = el.getAttribute(key);
33
- if (nodeKey) {
34
- nodeViewPortalProviderAPI.remove(nodeKey);
35
- }
33
+ ReactDOM.unmountComponentAtNode(el);
36
34
  });
37
35
  };
@@ -124,6 +124,7 @@ const destroyFn = (api, editorView) => {
124
124
  })(tr);
125
125
  }
126
126
  return tr.setMeta(key, {
127
+ ...tr.getMeta(key),
127
128
  isDragging: false,
128
129
  isPMDragging: false
129
130
  });
@@ -150,7 +151,7 @@ export const getDecorations = state => {
150
151
  return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
151
152
  };
152
153
  export const newApply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) => {
153
- var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$multiSelectDnD;
154
+ var _meta$multiSelectDnD, _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown;
154
155
  let {
155
156
  activeNode,
156
157
  decorations,
@@ -164,7 +165,8 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
164
165
  isDragging,
165
166
  isMenuOpen,
166
167
  // NOT USED
167
- isPMDragging
168
+ isPMDragging,
169
+ isShiftDown
168
170
  } = currentState;
169
171
  let isActiveNodeDeleted = false;
170
172
 
@@ -188,10 +190,9 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
188
190
  const meta = tr.getMeta(key);
189
191
  const resizerMeta = tr.getMeta('is-resizer-resizing');
190
192
  isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
193
+ multiSelectDnD = (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD;
191
194
  if (multiSelectDnD && flags.isMultiSelectEnabled) {
192
- multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false ||
193
- // For move node with shortcut, only reset when the selection changes
194
- tr.selection.anchor !== multiSelectDnD.textAnchor || tr.selection.head !== multiSelectDnD.textHead ? undefined : multiSelectDnD;
195
+ multiSelectDnD = (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false || tr.selection.empty ? undefined : multiSelectDnD;
195
196
  }
196
197
  const {
197
198
  from,
@@ -293,7 +294,8 @@ export const newApply = (api, formatMessage, tr, currentState, newState, flags,
293
294
  isResizerResizing: isResizerResizing,
294
295
  isDocSizeLimitEnabled: initialState.isDocSizeLimitEnabled,
295
296
  isPMDragging: (_meta$isPMDragging = meta === null || meta === void 0 ? void 0 : meta.isPMDragging) !== null && _meta$isPMDragging !== void 0 ? _meta$isPMDragging : isPMDragging,
296
- multiSelectDnD: (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD
297
+ multiSelectDnD,
298
+ isShiftDown: (_meta$isShiftDown = meta === null || meta === void 0 ? void 0 : meta.isShiftDown) !== null && _meta$isShiftDown !== void 0 ? _meta$isShiftDown : isShiftDown
297
299
  };
298
300
  };
299
301
  export const oldApply = (api, formatMessage, tr, currentState, oldState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) => {
@@ -494,6 +496,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
494
496
  const pluginState = key.getState(state);
495
497
  if (pluginState !== null && pluginState !== void 0 && pluginState.isPMDragging) {
496
498
  dispatch(state.tr.setMeta(key, {
499
+ ...state.tr.getMeta(key),
497
500
  isPMDragging: false
498
501
  }));
499
502
  }
@@ -549,6 +552,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
549
552
  }
550
553
  (_anchorRectCache = anchorRectCache) === null || _anchorRectCache === void 0 ? void 0 : _anchorRectCache.setEditorView(view);
551
554
  view.dispatch(view.state.tr.setMeta(key, {
555
+ ...view.state.tr.getMeta(key),
552
556
  isPMDragging: true
553
557
  }));
554
558
  },
@@ -560,6 +564,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
560
564
  } = view;
561
565
  if ((_key$getState3 = key.getState(state)) !== null && _key$getState3 !== void 0 && _key$getState3.isPMDragging) {
562
566
  dispatch(state.tr.setMeta(key, {
567
+ ...state.tr.getMeta(key),
563
568
  isPMDragging: false
564
569
  }));
565
570
  }
@@ -569,28 +574,69 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
569
574
  return false;
570
575
  },
571
576
  keydown(view, event) {
572
- // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
573
- const {
574
- selection,
575
- doc,
576
- tr
577
- } = view.state;
578
- const metaKey = browser.mac ? event.metaKey : event.ctrlKey;
579
- if (event.key === 'ArrowUp' && event.shiftKey && metaKey) {
580
- if (selection instanceof TextSelection || selection instanceof NodeSelection) {
581
- const newSelection = TextSelection.create(doc, selection.head, 1);
582
- view.dispatch(tr.setSelection(newSelection));
583
- return true;
577
+ if (isMultiSelectEnabled) {
578
+ if (event.shiftKey && event.ctrlKey) {
579
+ //prevent holding down key combo from firing repeatedly
580
+ if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
581
+ event.preventDefault();
582
+ return true;
583
+ }
584
584
  }
585
- }
586
- if (event.shiftKey && event.ctrlKey) {
587
- //prevent holding down key combo from firing repeatedly
588
- if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
589
- event.preventDefault();
585
+
586
+ // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
587
+ const {
588
+ selection,
589
+ doc,
590
+ tr
591
+ } = view.state;
592
+ const metaKey = browser.mac ? event.metaKey : event.ctrlKey;
593
+ if (event.key === 'ArrowUp' && event.shiftKey && metaKey) {
594
+ if (selection instanceof TextSelection || selection instanceof NodeSelection) {
595
+ const newSelection = TextSelection.create(doc, selection.head, 1);
596
+ view.dispatch(tr.setSelection(newSelection));
597
+ return true;
598
+ }
599
+ }
600
+ if (!event.repeat && event.shiftKey) {
601
+ view.dispatch(view.state.tr.setMeta(key, {
602
+ ...view.state.tr.getMeta(key),
603
+ isShiftDown: true
604
+ }));
590
605
  return true;
591
606
  }
607
+ return false;
608
+ } else {
609
+ // Command + Shift + ArrowUp to select was broken with the plugin enabled so this manually sets the selection
610
+ const {
611
+ selection,
612
+ doc,
613
+ tr
614
+ } = view.state;
615
+ const metaKey = browser.mac ? event.metaKey : event.ctrlKey;
616
+ if (event.key === 'ArrowUp' && event.shiftKey && metaKey) {
617
+ if (selection instanceof TextSelection || selection instanceof NodeSelection) {
618
+ const newSelection = TextSelection.create(doc, selection.head, 1);
619
+ view.dispatch(tr.setSelection(newSelection));
620
+ return true;
621
+ }
622
+ }
623
+ if (event.shiftKey && event.ctrlKey) {
624
+ //prevent holding down key combo from firing repeatedly
625
+ if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
626
+ event.preventDefault();
627
+ return true;
628
+ }
629
+ }
592
630
  }
593
631
  return false;
632
+ },
633
+ keyup(view, event) {
634
+ if (!event.repeat && event.key === 'Shift') {
635
+ view.dispatch(view.state.tr.setMeta(key, {
636
+ ...view.state.tr.getMeta(key),
637
+ isShiftDown: false
638
+ }));
639
+ }
594
640
  }
595
641
  }
596
642
  },
@@ -616,6 +662,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
616
662
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
617
663
  const editorWidthLeft = editorContentArea.getBoundingClientRect().left;
618
664
  transaction.setMeta(key, {
665
+ ...transaction.getMeta(key),
619
666
  editorWidthLeft,
620
667
  editorWidthRight
621
668
  });
@@ -58,7 +58,7 @@ export const getSelection = (tr, start) => {
58
58
  inlineNodePos,
59
59
  inlineNodeEndPos
60
60
  } = getInlineNodePos(tr, start, nodeSize);
61
- return new TextSelection(tr.doc.resolve(inlineNodeEndPos), tr.doc.resolve(inlineNodePos));
61
+ return new TextSelection(tr.doc.resolve(inlineNodePos), tr.doc.resolve(inlineNodeEndPos));
62
62
  }
63
63
  };
64
64
  export const selectNode = (tr, start, nodeType) => {