@atlaskit/editor-plugin-block-controls 7.7.2 → 7.7.4

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 (35) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/blockControlsPlugin.js +14 -0
  3. package/dist/cjs/pm-plugins/selection-preservation/editor-commands.js +32 -0
  4. package/dist/cjs/pm-plugins/selection-preservation/plugin-key.js +8 -0
  5. package/dist/cjs/pm-plugins/selection-preservation/pm-plugin.js +116 -0
  6. package/dist/cjs/pm-plugins/selection-preservation/types.js +5 -0
  7. package/dist/cjs/pm-plugins/selection-preservation/utils.js +21 -0
  8. package/dist/cjs/ui/drag-handle.js +155 -62
  9. package/dist/es2019/blockControlsPlugin.js +11 -1
  10. package/dist/es2019/pm-plugins/selection-preservation/editor-commands.js +28 -0
  11. package/dist/es2019/pm-plugins/selection-preservation/plugin-key.js +2 -0
  12. package/dist/es2019/pm-plugins/selection-preservation/pm-plugin.js +110 -0
  13. package/dist/es2019/pm-plugins/selection-preservation/types.js +1 -0
  14. package/dist/es2019/pm-plugins/selection-preservation/utils.js +13 -0
  15. package/dist/es2019/ui/drag-handle.js +128 -33
  16. package/dist/esm/blockControlsPlugin.js +14 -0
  17. package/dist/esm/pm-plugins/selection-preservation/editor-commands.js +26 -0
  18. package/dist/esm/pm-plugins/selection-preservation/plugin-key.js +2 -0
  19. package/dist/esm/pm-plugins/selection-preservation/pm-plugin.js +110 -0
  20. package/dist/esm/pm-plugins/selection-preservation/types.js +1 -0
  21. package/dist/esm/pm-plugins/selection-preservation/utils.js +15 -0
  22. package/dist/esm/ui/drag-handle.js +157 -64
  23. package/dist/types/blockControlsPluginType.d.ts +12 -1
  24. package/dist/types/pm-plugins/selection-preservation/editor-commands.d.ts +13 -0
  25. package/dist/types/pm-plugins/selection-preservation/plugin-key.d.ts +3 -0
  26. package/dist/types/pm-plugins/selection-preservation/pm-plugin.d.ts +26 -0
  27. package/dist/types/pm-plugins/selection-preservation/types.d.ts +7 -0
  28. package/dist/types/pm-plugins/selection-preservation/utils.d.ts +10 -0
  29. package/dist/types-ts4.5/blockControlsPluginType.d.ts +12 -1
  30. package/dist/types-ts4.5/pm-plugins/selection-preservation/editor-commands.d.ts +13 -0
  31. package/dist/types-ts4.5/pm-plugins/selection-preservation/plugin-key.d.ts +3 -0
  32. package/dist/types-ts4.5/pm-plugins/selection-preservation/pm-plugin.d.ts +26 -0
  33. package/dist/types-ts4.5/pm-plugins/selection-preservation/types.d.ts +7 -0
  34. package/dist/types-ts4.5/pm-plugins/selection-preservation/utils.d.ts +10 -0
  35. package/package.json +7 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 7.7.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [`1117e966eee41`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1117e966eee41) -
8
+ [ux] EDITOR-3384 Multiselect expand on doc changes
9
+
10
+ ## 7.7.3
11
+
12
+ ### Patch Changes
13
+
14
+ - [`aa5913a5d4962`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/aa5913a5d4962) -
15
+ [ux] EDITOR-2679 Fix multiselect collapsing issues for drag handle selections and block menu
16
+ - Updated dependencies
17
+
3
18
  ## 7.7.2
4
19
 
5
20
  ### Patch Changes
@@ -20,6 +20,8 @@ var _moveNodeUtils = require("./editor-commands/utils/move-node-utils");
20
20
  var _firstNodeDecPlugin = require("./pm-plugins/first-node-dec-plugin");
21
21
  var _pmPlugin = require("./pm-plugins/interaction-tracking/pm-plugin");
22
22
  var _main = require("./pm-plugins/main");
23
+ var _editorCommands = require("./pm-plugins/selection-preservation/editor-commands");
24
+ var _pmPlugin2 = require("./pm-plugins/selection-preservation/pm-plugin");
23
25
  var _getSelection = require("./pm-plugins/utils/getSelection");
24
26
  var _blockMenu = _interopRequireDefault(require("./ui/block-menu"));
25
27
  var _dragHandleMenu = require("./ui/drag-handle-menu");
@@ -45,6 +47,12 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
45
47
  plugin: _pmPlugin.createInteractionTrackingPlugin
46
48
  });
47
49
  }
50
+ if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
51
+ pmPlugins.push({
52
+ name: 'blockControlsSelectionPreservationPlugin',
53
+ plugin: _pmPlugin2.createSelectionPreservationPlugin
54
+ });
55
+ }
48
56
 
49
57
  // platform_editor_controls note: quick insert rendering fixes
50
58
  if ((0, _toolbarFlagCheck.areToolbarFlagsEnabled)(Boolean(api === null || api === void 0 ? void 0 : api.toolbar))) {
@@ -239,6 +247,12 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
239
247
  },
240
248
  moveNodeWithBlockMenu: function moveNodeWithBlockMenu(direction) {
241
249
  return (0, _moveNodeWithBlockMenu2.moveNodeWithBlockMenu)(api, direction);
250
+ },
251
+ startPreservingSelection: function startPreservingSelection() {
252
+ return _editorCommands.startPreservingSelection;
253
+ },
254
+ stopPreservingSelection: function stopPreservingSelection() {
255
+ return _editorCommands.stopPreservingSelection;
242
256
  }
243
257
  },
244
258
  getSharedState: function getSharedState(editorState) {
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.stopPreservingSelection = exports.startPreservingSelection = void 0;
7
+ var _pluginKey = require("./plugin-key");
8
+ /**
9
+ * Start preserving the selection when a UI interaction requires it
10
+ *
11
+ * e.g., block menu open, drag-and-drop in progress
12
+ */
13
+ var startPreservingSelection = exports.startPreservingSelection = function startPreservingSelection(_ref) {
14
+ var tr = _ref.tr;
15
+ var meta = {
16
+ type: 'startPreserving'
17
+ };
18
+ return tr.setMeta(_pluginKey.selectionPreservationPluginKey, meta);
19
+ };
20
+
21
+ /**
22
+ * Stop preserving the selection when a UI interaction completes
23
+ *
24
+ * e.g., block menu closed, drag-and-drop ended
25
+ */
26
+ var stopPreservingSelection = exports.stopPreservingSelection = function stopPreservingSelection(_ref2) {
27
+ var tr = _ref2.tr;
28
+ var meta = {
29
+ type: 'stopPreserving'
30
+ };
31
+ return tr.setMeta(_pluginKey.selectionPreservationPluginKey, meta);
32
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.selectionPreservationPluginKey = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var selectionPreservationPluginKey = exports.selectionPreservationPluginKey = new _state.PluginKey('selectionPreservationPlugin');
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createSelectionPreservationPlugin = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
10
+ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
11
+ var _state = require("@atlaskit/editor-prosemirror/state");
12
+ var _editorCommands = require("./editor-commands");
13
+ var _pluginKey = require("./plugin-key");
14
+ var _utils = require("./utils");
15
+ 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; }
16
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
+ /**
18
+ * Selection Preservation Plugin for ProseMirror Editor
19
+ *
20
+ * Solves a ProseMirror limitation where TextSelection cannot include positions at node boundaries
21
+ * (like media/images). When a selection spans text + media nodes, subsequent transactions cause
22
+ * ProseMirror to collapse the selection to the nearest inline position, excluding the media node.
23
+ * This is problematic for features like block menus and drag-and-drop that need stable multi-node
24
+ * selections while performing operations.
25
+ *
26
+ * The plugin works in three phases:
27
+ * (1) Explicitly save a selection via startPreservingSelection() when opening block menus or starting drag operations.
28
+ * (2) Map the saved selection through document changes to keep positions valid.
29
+ * (3) Detect when transactions collapse the selection and restore it via appendTransaction().
30
+ *
31
+ * Stops preserving via stopPreservingSelection() when the menu closes or operation completes.
32
+ *
33
+ * Commands: startPreservingSelection() to begin preservation, stopPreservingSelection() to end it.
34
+ *
35
+ * NOTE: Only use when the UI blocks user selection changes. For example: when a block menu overlay
36
+ * is open (editor becomes non-interactive), during drag-and-drop operations (user is mid-drag), or
37
+ * when modal dialogs are active. In these states, any selection changes are from ProseMirror's
38
+ * internal behavior (not user input) and should be prevented. Do not use during normal editing.
39
+ */
40
+ var createSelectionPreservationPlugin = exports.createSelectionPreservationPlugin = function createSelectionPreservationPlugin() {
41
+ return new _safePlugin.SafePlugin({
42
+ key: _pluginKey.selectionPreservationPluginKey,
43
+ state: {
44
+ init: function init() {
45
+ return {
46
+ preservedSelection: undefined
47
+ };
48
+ },
49
+ apply: function apply(tr, pluginState) {
50
+ var meta = (0, _utils.getSelectionPreservationMeta)(tr);
51
+ var newState = _objectSpread({}, pluginState);
52
+ if ((meta === null || meta === void 0 ? void 0 : meta.type) === 'startPreserving') {
53
+ newState.preservedSelection = new _state.TextSelection(tr.selection.$from, tr.selection.$to);
54
+ } else if ((meta === null || meta === void 0 ? void 0 : meta.type) === 'stopPreserving') {
55
+ newState.preservedSelection = undefined;
56
+ }
57
+ if (newState.preservedSelection && tr.docChanged) {
58
+ var from = tr.mapping.map(newState.preservedSelection.from);
59
+ var to = tr.mapping.map(newState.preservedSelection.to);
60
+ if (from < 0 || to > tr.doc.content.size || from >= to) {
61
+ // stop preserving if preserved selection becomes invalid or collapsed to a cursor
62
+ // e.g. after deleting the selection
63
+ newState.preservedSelection = undefined;
64
+ } else {
65
+ var _expandToBlockRange = expandToBlockRange(tr.doc.resolve(from), tr.doc.resolve(to)),
66
+ $from = _expandToBlockRange.$from,
67
+ $to = _expandToBlockRange.$to;
68
+ newState.preservedSelection = new _state.TextSelection($from, $to);
69
+ }
70
+ }
71
+ return newState;
72
+ }
73
+ },
74
+ appendTransaction: function appendTransaction(transactions, _oldState, newState) {
75
+ var pluginState = _pluginKey.selectionPreservationPluginKey.getState(newState);
76
+ var savedSel = pluginState === null || pluginState === void 0 ? void 0 : pluginState.preservedSelection;
77
+ if (!savedSel) {
78
+ return null;
79
+ }
80
+ if ((0, _utils.hasUserSelectionChange)(transactions)) {
81
+ // Auto-stop if user explicitly changes selection
82
+ return (0, _editorCommands.stopPreservingSelection)({
83
+ tr: newState.tr
84
+ });
85
+ }
86
+ var currSel = newState.selection;
87
+ var wasEmptySelection = savedSel.from === savedSel.to;
88
+ var selectionUnchanged = currSel.from === savedSel.from && currSel.to === savedSel.to;
89
+ var selectionInvalid = savedSel.from < 0 || savedSel.to > newState.doc.content.size;
90
+ if (wasEmptySelection || selectionUnchanged || selectionInvalid) {
91
+ return null;
92
+ }
93
+ try {
94
+ return newState.tr.setSelection(_state.TextSelection.create(newState.doc, savedSel.from, savedSel.to));
95
+ } catch (error) {
96
+ (0, _monitoring.logException)(error, {
97
+ location: 'editor-plugin-block-controls/SelectionPreservationPlugin'
98
+ });
99
+ }
100
+ return null;
101
+ }
102
+ });
103
+ };
104
+ var expandToBlockRange = function expandToBlockRange($from, $to) {
105
+ var range = $from.blockRange($to);
106
+ if (!range) {
107
+ return {
108
+ $from: $from,
109
+ $to: $to
110
+ };
111
+ }
112
+ return {
113
+ $from: $from.doc.resolve(range.start),
114
+ $to: $to.doc.resolve(range.end)
115
+ };
116
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.hasUserSelectionChange = exports.getSelectionPreservationMeta = void 0;
7
+ var _pluginKey = require("./plugin-key");
8
+ /**
9
+ * Detects if any of the transactions include user-driven selection changes.
10
+ *
11
+ * @param transactions The list of transactions to check.
12
+ * @returns True if any transaction includes a user-driven selection change, otherwise false.
13
+ */
14
+ var hasUserSelectionChange = exports.hasUserSelectionChange = function hasUserSelectionChange(transactions) {
15
+ return transactions.some(function (tr) {
16
+ return tr.getMeta('pointer') && tr.selectionSet;
17
+ });
18
+ };
19
+ var getSelectionPreservationMeta = exports.getSelectionPreservationMeta = function getSelectionPreservationMeta(tr) {
20
+ return tr.getMeta(_pluginKey.selectionPreservationPluginKey);
21
+ };
@@ -11,6 +11,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
11
11
  var _react = require("react");
12
12
  var _react2 = require("@emotion/react");
13
13
  var _bindEventListener = require("bind-event-listener");
14
+ var _browserApis = require("@atlaskit/browser-apis");
14
15
  var _analytics = require("@atlaskit/editor-common/analytics");
15
16
  var _browser = require("@atlaskit/editor-common/browser");
16
17
  var _hooks = require("@atlaskit/editor-common/hooks");
@@ -34,6 +35,7 @@ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
34
35
  var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
35
36
  var _decorationsCommon = require("../pm-plugins/decorations-common");
36
37
  var _main = require("../pm-plugins/main");
38
+ var _pluginKey = require("../pm-plugins/selection-preservation/plugin-key");
37
39
  var _analytics2 = require("../pm-plugins/utils/analytics");
38
40
  var _dragHandlePositions = require("../pm-plugins/utils/drag-handle-positions");
39
41
  var _getSelection = require("../pm-plugins/utils/getSelection");
@@ -296,18 +298,55 @@ var getNodeMargins = function getNodeMargins(node) {
296
298
  }
297
299
  return _consts2.nodeMargins[nodeTypeName] || _consts2.nodeMargins['default'];
298
300
  };
299
- var DragHandle = exports.DragHandle = function DragHandle(_ref) {
300
- var _api$core3;
301
- var view = _ref.view,
302
- api = _ref.api,
303
- formatMessage = _ref.formatMessage,
304
- getPos = _ref.getPos,
305
- anchorName = _ref.anchorName,
306
- nodeType = _ref.nodeType,
307
- handleOptions = _ref.handleOptions,
308
- _ref$isTopLevelNode = _ref.isTopLevelNode,
309
- isTopLevelNode = _ref$isTopLevelNode === void 0 ? true : _ref$isTopLevelNode,
310
- anchorRectCache = _ref.anchorRectCache;
301
+ var isMultiNodeRange = function isMultiNodeRange(range) {
302
+ if (range.endIndex - range.startIndex <= 1) {
303
+ return false; // At most one child
304
+ }
305
+
306
+ // Count block nodes in the range, return true if more than one
307
+ var blockCount = 0;
308
+ for (var i = range.startIndex; i < range.endIndex; i++) {
309
+ if (range.parent.child(i).isBlock) {
310
+ blockCount++;
311
+ }
312
+ if (blockCount > 1) {
313
+ return true;
314
+ }
315
+ }
316
+ return false;
317
+ };
318
+ var isPosWithinRange = function isPosWithinRange(pos, range) {
319
+ return range.start <= pos && range.end >= pos + 1;
320
+ };
321
+ /**
322
+ * From the current selection and the position of the drag handle being clicked,
323
+ * calculate the expanded block range up to the common ancestor.
324
+ */
325
+ var getExpandedSelectionRange = function getExpandedSelectionRange(_ref) {
326
+ var selection = _ref.selection,
327
+ doc = _ref.doc,
328
+ resolvedStartPos = _ref.resolvedStartPos,
329
+ isShiftPressed = _ref.isShiftPressed;
330
+ // When not pressing shift, expand the current selection
331
+ // When shift selecting upwards, expand from start of node to selection end
332
+ // When shift selecting downwards, expand from selection start to end of node
333
+ var selectUp = resolvedStartPos.pos < selection.from;
334
+ var $from = isShiftPressed && selectUp ? resolvedStartPos : selection.$from;
335
+ var $to = isShiftPressed && !selectUp ? doc.resolve(resolvedStartPos.pos + 1) : selection.$to;
336
+ return $from.blockRange($to);
337
+ };
338
+ var DragHandle = exports.DragHandle = function DragHandle(_ref2) {
339
+ var _api$core4;
340
+ var view = _ref2.view,
341
+ api = _ref2.api,
342
+ formatMessage = _ref2.formatMessage,
343
+ getPos = _ref2.getPos,
344
+ anchorName = _ref2.anchorName,
345
+ nodeType = _ref2.nodeType,
346
+ handleOptions = _ref2.handleOptions,
347
+ _ref2$isTopLevelNode = _ref2.isTopLevelNode,
348
+ isTopLevelNode = _ref2$isTopLevelNode === void 0 ? true : _ref2$isTopLevelNode,
349
+ anchorRectCache = _ref2.anchorRectCache;
311
350
  var buttonRef = (0, _react.useRef)(null);
312
351
  var _useState = (0, _react.useState)(false),
313
352
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
@@ -368,14 +407,68 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
368
407
  }
369
408
  }
370
409
  }, [anchorName, nodeType, view.dom]);
371
- var handleOnClick = (0, _react.useCallback)(function (e) {
410
+ var handleOnClickNew = (0, _react.useCallback)(function (e) {
372
411
  var _api$core;
412
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
413
+ var _api$analytics, _resolvedStartPos$nod, _selectionPreservatio, _api$blockControls, _api$blockControls2;
414
+ var tr = _ref3.tr;
415
+ var startPos = getPos();
416
+ if (startPos === undefined) {
417
+ return tr;
418
+ }
419
+ var resolvedStartPos = tr.doc.resolve(startPos);
420
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
421
+ eventType: _analytics.EVENT_TYPE.UI,
422
+ action: _analytics.ACTION.CLICKED,
423
+ actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
424
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
425
+ attributes: {
426
+ nodeDepth: resolvedStartPos.depth,
427
+ nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
428
+ }
429
+ })(tr);
430
+ var selection = ((_selectionPreservatio = _pluginKey.selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection) || tr.selection;
431
+ var range = getExpandedSelectionRange({
432
+ doc: tr.doc,
433
+ selection: selection,
434
+ resolvedStartPos: resolvedStartPos,
435
+ isShiftPressed: e.shiftKey
436
+ });
437
+
438
+ // Set selection to expanded selection range if it encompases the clicked drag handle
439
+ if (range && isPosWithinRange(startPos, range) && isMultiNodeRange(range)) {
440
+ tr.setSelection(_state.TextSelection.create(tr.doc, Math.min(selection.from, range.start), Math.max(selection.to, range.end)));
441
+ } else {
442
+ // Select the clicked drag handle's node only
443
+ tr = (0, _getSelection.selectNode)(tr, startPos, nodeType, api);
444
+ }
445
+ api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.startPreservingSelection()({
446
+ tr: tr
447
+ });
448
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
449
+ anchorName: anchorName,
450
+ openedViaKeyboard: false,
451
+ triggerByNode: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_synced_block', 'isEnabled', true) ? {
452
+ nodeType: nodeType,
453
+ pos: startPos,
454
+ rootPos: tr.doc.resolve(startPos).before(1)
455
+ } : undefined
456
+ })({
457
+ tr: tr
458
+ });
459
+ tr.setMeta('scrollIntoView', false);
460
+ return tr;
461
+ });
462
+ view.focus();
463
+ }, [api, view, getPos, nodeType, anchorName]);
464
+ var handleOnClick = (0, _react.useCallback)(function (e) {
465
+ var _api$core2;
373
466
  if (!isMultiSelect) {
374
467
  setDragHandleSelected(!dragHandleSelected);
375
468
  }
376
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
377
- var _api$blockControls$sh, _api$analytics;
378
- var tr = _ref2.tr;
469
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref4) {
470
+ var _api$blockControls$sh, _api$analytics2;
471
+ var tr = _ref4.tr;
379
472
  var startPos = getPos();
380
473
  if (startPos === undefined) {
381
474
  return tr;
@@ -404,8 +497,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
404
497
  rootPos: rootPos
405
498
  } : undefined;
406
499
  if (_consts2.BLOCK_MENU_ENABLED && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
407
- var _api$blockControls;
408
- api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu({
500
+ var _api$blockControls3;
501
+ api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.toggleBlockMenu({
409
502
  anchorName: anchorName,
410
503
  triggerByNode: triggerByNode,
411
504
  openedViaKeyboard: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? false : undefined
@@ -414,8 +507,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
414
507
  });
415
508
  e.stopPropagation();
416
509
  } else if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
417
- var _api$blockControls2;
418
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
510
+ var _api$blockControls4;
511
+ api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.toggleBlockMenu({
419
512
  anchorName: anchorName,
420
513
  triggerByNode: triggerByNode,
421
514
  openedViaKeyboard: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? false : undefined
@@ -425,18 +518,18 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
425
518
  e.stopPropagation();
426
519
  }
427
520
  } else if (isTopLevelNode && $anchor.depth <= _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
428
- var _api$blockControls3;
521
+ var _api$blockControls5;
429
522
  var alignAnchorHeadToSel = (0, _selection3.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
430
523
  var selectionWithExpandedHead = (0, _selection3.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
431
524
  tr.setSelection(selectionWithExpandedHead);
432
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.setMultiSelectPositions()({
525
+ api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.setMultiSelectPositions()({
433
526
  tr: tr
434
527
  });
435
528
  }
436
529
  var resolvedMovingNode = tr.doc.resolve(startPos);
437
530
  var maybeNode = resolvedMovingNode.nodeAfter;
438
531
  tr.setMeta('scrollIntoView', false);
439
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
532
+ api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.attachAnalyticsEvent({
440
533
  eventType: _analytics.EVENT_TYPE.UI,
441
534
  action: _analytics.ACTION.CLICKED,
442
535
  actionSubject: _analytics.ACTION_SUBJECT.BUTTON,
@@ -453,10 +546,10 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
453
546
  var handleKeyDown = (0, _react.useCallback)(function (e) {
454
547
  // allow user to use spacebar to select the node
455
548
  if (!e.repeat && e.key === ' ') {
456
- var _api$core2;
549
+ var _api$core3;
457
550
  var startPos = getPos();
458
- api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref3) {
459
- var tr = _ref3.tr;
551
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref5) {
552
+ var tr = _ref5.tr;
460
553
  if (startPos === undefined) {
461
554
  return tr;
462
555
  }
@@ -479,20 +572,20 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
479
572
  // return focus to editor to resume editing from caret position
480
573
  view.focus();
481
574
  }
482
- }, [getPos, api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions, isMultiSelect, view]);
575
+ }, [getPos, api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions, isMultiSelect, view]);
483
576
  var handleKeyDownNew = (0, _react.useCallback)(function (e) {
484
577
  // allow user to use spacebar to select the node
485
578
  if (e.key === 'Enter' || !e.repeat && e.key === ' ') {
486
- var _api$core4;
487
- if (document.activeElement !== buttonRef.current) {
579
+ var _getDocument, _api$core5;
580
+ if (((_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement) !== buttonRef.current) {
488
581
  return;
489
582
  }
490
583
  e.preventDefault();
491
584
  e.stopPropagation();
492
585
  var startPos = getPos();
493
- api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref4) {
494
- var _api$blockControls4, _api$userIntent;
495
- var tr = _ref4.tr;
586
+ api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref6) {
587
+ var _api$blockControls6, _api$userIntent;
588
+ var tr = _ref6.tr;
496
589
  if (startPos === undefined) {
497
590
  return tr;
498
591
  }
@@ -506,7 +599,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
506
599
  pos: startPos,
507
600
  rootPos: rootPos
508
601
  } : undefined;
509
- api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.toggleBlockMenu({
602
+ api === null || api === void 0 || (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 || _api$blockControls6.commands.toggleBlockMenu({
510
603
  anchorName: anchorName,
511
604
  triggerByNode: triggerByNode,
512
605
  openedViaKeyboard: true
@@ -521,11 +614,11 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
521
614
  } else if (e.key === 'Backspace' || e.key === 'Delete') {
522
615
  e.preventDefault();
523
616
  e.stopPropagation();
524
- api === null || api === void 0 || api.core.actions.execute(function (_ref5) {
525
- var _api$blockControls5;
526
- var tr = _ref5.tr;
617
+ api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
618
+ var _api$blockControls7;
619
+ var tr = _ref7.tr;
527
620
  (0, _selection2.deleteSelectedRange)(tr);
528
- api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.toggleBlockMenu({
621
+ api === null || api === void 0 || (_api$blockControls7 = api.blockControls) === null || _api$blockControls7 === void 0 || _api$blockControls7.commands.toggleBlockMenu({
529
622
  closeMenu: true
530
623
  })({
531
624
  tr: tr
@@ -553,21 +646,21 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
553
646
  start: start
554
647
  };
555
648
  },
556
- onGenerateDragPreview: function onGenerateDragPreview(_ref6) {
649
+ onGenerateDragPreview: function onGenerateDragPreview(_ref8) {
557
650
  var _api$blockControls$sh2;
558
- var nativeSetDragImage = _ref6.nativeSetDragImage;
651
+ var nativeSetDragImage = _ref8.nativeSetDragImage;
559
652
  if (isMultiSelect) {
560
- var _api$core5;
561
- api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref7) {
562
- var tr = _ref7.tr;
653
+ var _api$core6;
654
+ api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref9) {
655
+ var tr = _ref9.tr;
563
656
  var handlePos = getPos();
564
657
  if (typeof handlePos !== 'number') {
565
658
  return tr;
566
659
  }
567
660
  var newHandlePosCheck = (0, _getSelection.isHandleCorrelatedToSelection)(view.state, tr.selection, handlePos);
568
661
  if (!tr.selection.empty && newHandlePosCheck) {
569
- var _api$blockControls6;
570
- api === null || api === void 0 || (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 || _api$blockControls6.commands.setMultiSelectPositions()({
662
+ var _api$blockControls8;
663
+ api === null || api === void 0 || (_api$blockControls8 = api.blockControls) === null || _api$blockControls8 === void 0 || _api$blockControls8.commands.setMultiSelectPositions()({
571
664
  tr: tr
572
665
  });
573
666
  } else if ((0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_select_node_on_drag')) {
@@ -637,8 +730,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
637
730
  };
638
731
  }
639
732
  },
640
- render: function render(_ref8) {
641
- var container = _ref8.container;
733
+ render: function render(_ref0) {
734
+ var container = _ref0.container;
642
735
  var dom = view.dom.querySelector("[".concat((0, _domAttrName.getAnchorAttrName)(), "=\"").concat(anchorName, "\"]"));
643
736
  if (!dom) {
644
737
  return;
@@ -670,13 +763,13 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
670
763
  });
671
764
  },
672
765
  onDragStart: function onDragStart() {
673
- var _api$core6;
766
+ var _api$core7;
674
767
  if (start === undefined) {
675
768
  return;
676
769
  }
677
- api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref9) {
678
- var _api$blockControls$sh3, _api$blockControls7, _api$analytics2;
679
- var tr = _ref9.tr;
770
+ api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref1) {
771
+ var _api$blockControls$sh3, _api$blockControls9, _api$analytics3;
772
+ var tr = _ref1.tr;
680
773
  var nodeTypes, hasSelectedMultipleNodes;
681
774
  var resolvedMovingNode = tr.doc.resolve(start);
682
775
  var maybeNode = resolvedMovingNode.nodeAfter;
@@ -689,11 +782,11 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
689
782
  nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
690
783
  hasSelectedMultipleNodes = false;
691
784
  }
692
- api === null || api === void 0 || (_api$blockControls7 = api.blockControls) === null || _api$blockControls7 === void 0 || _api$blockControls7.commands.setNodeDragged(getPos, anchorName, nodeType)({
785
+ api === null || api === void 0 || (_api$blockControls9 = api.blockControls) === null || _api$blockControls9 === void 0 || _api$blockControls9.commands.setNodeDragged(getPos, anchorName, nodeType)({
693
786
  tr: tr
694
787
  });
695
788
  tr.setMeta('scrollIntoView', false);
696
- api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.attachAnalyticsEvent({
789
+ api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.attachAnalyticsEvent({
697
790
  eventType: _analytics.EVENT_TYPE.UI,
698
791
  action: _analytics.ACTION.DRAGGED,
699
792
  actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
@@ -987,7 +1080,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
987
1080
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
988
1081
  ,
989
1082
  style: !(0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? (0, _experiments.editorExperiment)('platform_editor_block_control_optimise_render', true) ? positionStyles : positionStylesOld : {},
990
- onClick: handleOnClick,
1083
+ onClick: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true) ? handleOnClickNew : handleOnClick,
991
1084
  onKeyDown: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true) && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? handleKeyDownNew : handleKeyDown
992
1085
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
993
1086
  ,
@@ -1072,15 +1165,15 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
1072
1165
  var render = isTooltip ? buttonWithTooltip() : renderButton();
1073
1166
  return (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? stickyRender : render;
1074
1167
  };
1075
- var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragHandleWithVisibility(_ref0) {
1076
- var view = _ref0.view,
1077
- api = _ref0.api,
1078
- formatMessage = _ref0.formatMessage,
1079
- getPos = _ref0.getPos,
1080
- anchorName = _ref0.anchorName,
1081
- nodeType = _ref0.nodeType,
1082
- handleOptions = _ref0.handleOptions,
1083
- anchorRectCache = _ref0.anchorRectCache;
1168
+ var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragHandleWithVisibility(_ref10) {
1169
+ var view = _ref10.view,
1170
+ api = _ref10.api,
1171
+ formatMessage = _ref10.formatMessage,
1172
+ getPos = _ref10.getPos,
1173
+ anchorName = _ref10.anchorName,
1174
+ nodeType = _ref10.nodeType,
1175
+ handleOptions = _ref10.handleOptions,
1176
+ anchorRectCache = _ref10.anchorRectCache;
1084
1177
  return (0, _react2.jsx)(_visibilityContainer.VisibilityContainer, {
1085
1178
  api: api
1086
1179
  }, (0, _react2.jsx)(DragHandle, {
@@ -12,6 +12,8 @@ import { canMoveNodeUpOrDown } from './editor-commands/utils/move-node-utils';
12
12
  import { firstNodeDecPlugin } from './pm-plugins/first-node-dec-plugin';
13
13
  import { createInteractionTrackingPlugin, interactionTrackingPluginKey } from './pm-plugins/interaction-tracking/pm-plugin';
14
14
  import { createPlugin, key } from './pm-plugins/main';
15
+ import { startPreservingSelection, stopPreservingSelection } from './pm-plugins/selection-preservation/editor-commands';
16
+ import { createSelectionPreservationPlugin } from './pm-plugins/selection-preservation/pm-plugin';
15
17
  import { selectNode } from './pm-plugins/utils/getSelection';
16
18
  import BlockMenu from './ui/block-menu';
17
19
  import { DragHandleMenu } from './ui/drag-handle-menu';
@@ -34,6 +36,12 @@ export const blockControlsPlugin = ({
34
36
  plugin: createInteractionTrackingPlugin
35
37
  });
36
38
  }
39
+ if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
40
+ pmPlugins.push({
41
+ name: 'blockControlsSelectionPreservationPlugin',
42
+ plugin: createSelectionPreservationPlugin
43
+ });
44
+ }
37
45
 
38
46
  // platform_editor_controls note: quick insert rendering fixes
39
47
  if (areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar))) {
@@ -233,7 +241,9 @@ export const blockControlsPlugin = ({
233
241
  },
234
242
  moveNodeWithBlockMenu: direction => {
235
243
  return moveNodeWithBlockMenu(api, direction);
236
- }
244
+ },
245
+ startPreservingSelection: () => startPreservingSelection,
246
+ stopPreservingSelection: () => stopPreservingSelection
237
247
  },
238
248
  getSharedState(editorState) {
239
249
  var _key$getState$isMenuO, _key$getState, _key$getState$menuTri, _key$getState2, _key$getState$menuTri2, _key$getState3, _key$getState$blockMe, _key$getState4, _key$getState$activeN, _key$getState5, _key$getState$activeD, _key$getState6, _key$getState$isDragg, _key$getState7, _key$getState$isPMDra, _key$getState8, _key$getState$multiSe, _key$getState9, _key$getState$isShift, _key$getState0, _key$getState$lastDra, _key$getState1, _interactionTrackingP, _key$getState$isSelec, _key$getState10;