@atlaskit/editor-plugin-block-controls 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 2.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#151024](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/151024)
8
+ [`73afcf51ef0da`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/73afcf51ef0da) -
9
+ ED-20516 Set selection at end of node after drop instead of selecting entire moved node
10
+ - Updated dependencies
11
+
12
+ ## 2.2.1
13
+
14
+ ### Patch Changes
15
+
16
+ - [#150591](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/150591)
17
+ [`13337452246bc`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/13337452246bc) -
18
+ support a11y to move various node types with shortcut
19
+
3
20
  ## 2.2.0
4
21
 
5
22
  ### Minor Changes
@@ -18,6 +18,7 @@ var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
18
18
  var _consts = require("../consts");
19
19
  var _main = require("../pm-plugins/main");
20
20
  var _utils4 = require("../utils");
21
+ var _getSelection = require("../utils/getSelection");
21
22
  var _validation = require("../utils/validation");
22
23
  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; }
23
24
  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; }
@@ -69,8 +70,8 @@ var getCurrentNodePos = function getCurrentNodePos(state, isParentNodeOfTypeLayo
69
70
  // 2. caret cursor is inside the node
70
71
  // 3. the start of the selection is inside the node
71
72
  currentNodePos = selection.$from.before(1);
72
- if ((0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_a11y')) {
73
- currentNodePos = selection.$from.depth > (isParentNodeOfTypeLayout ? 2 : 1) ? selection.$from.before(selection.$from.depth) : selection.$from.before(1);
73
+ if (selection.$from.depth > 0 && (0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_a11y')) {
74
+ currentNodePos = (0, _utils4.getNestedNodePosition)(state);
74
75
  }
75
76
  }
76
77
  return currentNodePos;
@@ -189,7 +190,7 @@ var moveNode = exports.moveNode = function moveNode(api) {
189
190
  mappedTo = tr.mapping.map(to);
190
191
  tr.insert(mappedTo, _nodeCopy); // insert the content at the new position
191
192
  }
192
- tr = (0, _utils4.selectNode)(tr, mappedTo, node.type.name);
193
+ tr = inputMethod === _analytics.INPUT_METHOD.DRAG_AND_DROP && (0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_fix_patch_2') ? (0, _getSelection.setCursorPositionAtMovedNode)(tr, mappedTo) : (0, _utils4.selectNode)(tr, mappedTo, node.type.name);
193
194
  tr.setMeta(_main.key, {
194
195
  nodeMoved: true
195
196
  });
@@ -7,6 +7,7 @@ exports.showDragHandleAtSelection = void 0;
7
7
  var _utils = require("@atlaskit/editor-tables/utils");
8
8
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
9
9
  var _main = require("../pm-plugins/main");
10
+ var _utils2 = require("../utils");
10
11
  var showDragHandleAtSelection = exports.showDragHandleAtSelection = function showDragHandleAtSelection(api, shouldFocusParentNode) {
11
12
  return function (state, _, view) {
12
13
  var $from = state.selection.$from;
@@ -18,13 +19,21 @@ var showDragHandleAtSelection = exports.showDragHandleAtSelection = function sho
18
19
 
19
20
  // if the node is already focused, pressing the keymap second times should focus the parent node
20
21
  shouldFocusParentNode = activeNode && ((_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused);
21
- var parentPos = (0, _utils.isInTable)(state) ? $from.before(1) : shouldFocusParentNode ? $from.start($from.depth - 1) : $from.start();
22
+ var parentPos = (0, _utils.isInTable)(state) ? $from.before(1) : shouldFocusParentNode ? $from.before(1) : (0, _utils2.getNestedNodePosition)(state) + 1;
22
23
  var parentElement = view === null || view === void 0 || (_view$domAtPos = view.domAtPos(parentPos, 0)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
23
24
  if (parentElement) {
24
25
  var anchorName = parentElement.getAttribute('data-drag-handler-anchor-name');
25
26
  var nodeType = parentElement.getAttribute('data-drag-handler-node-type');
27
+ if (!anchorName || !nodeType) {
28
+ // for nodes like panel and mediaSingle, the drag handle decoration is not applied to the dom node at the node position but to the parent node
29
+ var closestParentElement = parentElement.closest('[data-drag-handler-anchor-name]');
30
+ if (closestParentElement) {
31
+ anchorName = closestParentElement.getAttribute('data-drag-handler-anchor-name');
32
+ nodeType = closestParentElement.getAttribute('data-drag-handler-node-type');
33
+ }
34
+ }
26
35
  if (api && anchorName && nodeType) {
27
- api.core.actions.execute(api.blockControls.commands.showDragHandleAt($from.before(), anchorName, nodeType, {
36
+ api.core.actions.execute(api.blockControls.commands.showDragHandleAt(parentPos - 1, anchorName, nodeType, {
28
37
  isFocused: true
29
38
  }));
30
39
  return true;
@@ -16,7 +16,6 @@ var _hooks = require("@atlaskit/editor-common/hooks");
16
16
  var _keymaps = require("@atlaskit/editor-common/keymaps");
17
17
  var _messages = require("@atlaskit/editor-common/messages");
18
18
  var _state = require("@atlaskit/editor-prosemirror/state");
19
- var _utils = require("@atlaskit/editor-prosemirror/utils");
20
19
  var _dragHandler = _interopRequireDefault(require("@atlaskit/icon/glyph/drag-handler"));
21
20
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
22
21
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
@@ -24,7 +23,7 @@ var _setCustomNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/ele
24
23
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
25
24
  var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
26
25
  var _main = require("../pm-plugins/main");
27
- var _utils2 = require("../utils");
26
+ var _utils = require("../utils");
28
27
  var _dragHandlePositions = require("../utils/drag-handle-positions");
29
28
  var _consts = require("./consts");
30
29
  var _dragPreview = require("./drag-preview");
@@ -120,7 +119,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
120
119
  if (startPos === undefined) {
121
120
  return tr;
122
121
  }
123
- tr = (0, _utils2.selectNode)(tr, startPos, nodeType);
122
+ tr = (0, _utils.selectNode)(tr, startPos, nodeType);
124
123
  var resolvedMovingNode = tr.doc.resolve(startPos);
125
124
  var maybeNode = resolvedMovingNode.nodeAfter;
126
125
  tr.setMeta('scrollIntoView', false);
@@ -379,7 +378,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
379
378
  }];
380
379
  var isParentNodeOfTypeLayout;
381
380
  if (!isTopLevelNode && handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused && (0, _platformFeatureFlags.fg)('platform_editor_element_dnd_nested_a11y')) {
382
- isParentNodeOfTypeLayout = nodeType === 'layoutSection' || !!(0, _utils.findParentNodeOfType)([view.state.schema.nodes.layoutSection])(view.state.selection);
381
+ isParentNodeOfTypeLayout = nodeType === 'layoutSection' || view.state.doc.resolve((0, _utils.getNestedNodePosition)(view.state)).node().type.name === 'layoutColumn';
383
382
  if (isParentNodeOfTypeLayout) {
384
383
  helpDescriptors = [].concat((0, _toConsumableArray2.default)(helpDescriptors), [{
385
384
  description: formatMessage(_messages.blockControlsMessages.moveLeft),
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getNestedNodePosition = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
9
+ var getNestedNodePosition = exports.getNestedNodePosition = function getNestedNodePosition(state) {
10
+ var selection = state.selection;
11
+ var nestedNodePos = selection.$from.before(1);
12
+ if (selection instanceof _state.TextSelection) {
13
+ nestedNodePos = selection.$from.before();
14
+ var $pos = state.doc.resolve(nestedNodePos);
15
+ if ($pos.depth < 1) {
16
+ return nestedNodePos;
17
+ }
18
+ var parentNodeOfSpecificTypes = (0, _utils.findParentNodeOfType)([state.schema.nodes.bulletList, state.schema.nodes.orderedList, state.schema.nodes.blockquote, state.schema.nodes.taskList])(state.selection);
19
+ if (parentNodeOfSpecificTypes) {
20
+ var parentNodeType = parentNodeOfSpecificTypes.node.type.name;
21
+ nestedNodePos = ['bulletList', 'orderedList'].includes(parentNodeType) ? $pos.before($pos.depth - 1) : ['blockquote', 'taskList'].includes(parentNodeType) ? $pos.before() : nestedNodePos;
22
+ }
23
+ } else {
24
+ nestedNodePos = selection.$from.pos;
25
+ }
26
+ return nestedNodePos;
27
+ };
@@ -3,9 +3,32 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.selectNode = exports.getSelection = void 0;
6
+ exports.setCursorPositionAtMovedNode = exports.selectNode = exports.getSelection = exports.getInlineNodePos = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
7
8
  var _state = require("@atlaskit/editor-prosemirror/state");
8
9
  var _utils = require("@atlaskit/editor-tables/utils");
10
+ var getInlineNodePos = exports.getInlineNodePos = function getInlineNodePos(tr, start, nodeSize) {
11
+ var $startPos = tr.doc.resolve(start);
12
+ // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
13
+ // Find the first inline node in the node
14
+ var inlineNodePos = start;
15
+ var foundInlineNode = false;
16
+ var inlineNodeEndPos = 0;
17
+ tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, function (n, pos) {
18
+ if (n.isInline) {
19
+ inlineNodeEndPos = pos + n.nodeSize;
20
+ }
21
+ if (n.isInline && !foundInlineNode) {
22
+ inlineNodePos = pos;
23
+ foundInlineNode = true;
24
+ }
25
+ return true;
26
+ });
27
+ return {
28
+ inlineNodePos: inlineNodePos,
29
+ inlineNodeEndPos: inlineNodeEndPos
30
+ };
31
+ };
9
32
  var getSelection = exports.getSelection = function getSelection(tr, start) {
10
33
  var node = tr.doc.nodeAt(start);
11
34
  var isNodeSelection = node && _state.NodeSelection.isSelectable(node);
@@ -25,21 +48,9 @@ var getSelection = exports.getSelection = function getSelection(tr, start) {
25
48
  nodeName === 'mediaGroup') {
26
49
  return new _state.NodeSelection($startPos);
27
50
  } else {
28
- // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
29
- // Find the first inline node in the node
30
- var inlineNodePos = start;
31
- var foundInlineNode = false;
32
- var inlineNodeEndPos = 0;
33
- tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, function (n, pos) {
34
- if (n.isInline) {
35
- inlineNodeEndPos = pos + n.nodeSize;
36
- }
37
- if (n.isInline && !foundInlineNode) {
38
- inlineNodePos = pos;
39
- foundInlineNode = true;
40
- }
41
- return true;
42
- });
51
+ var _getInlineNodePos = getInlineNodePos(tr, start, nodeSize),
52
+ inlineNodePos = _getInlineNodePos.inlineNodePos,
53
+ inlineNodeEndPos = _getInlineNodePos.inlineNodeEndPos;
43
54
  return new _state.TextSelection(tr.doc.resolve(inlineNodeEndPos), tr.doc.resolve(inlineNodePos));
44
55
  }
45
56
  };
@@ -51,4 +62,20 @@ var selectNode = exports.selectNode = function selectNode(tr, start, nodeType) {
51
62
  tr.setSelection(getSelection(tr, start));
52
63
  }
53
64
  return tr;
65
+ };
66
+ var setCursorPositionAtMovedNode = exports.setCursorPositionAtMovedNode = function setCursorPositionAtMovedNode(tr, start) {
67
+ var node = tr.doc.nodeAt(start);
68
+ var isNodeSelection = node && _state.NodeSelection.isSelectable(node);
69
+ var nodeSize = node ? node.nodeSize : 1;
70
+ var selection;
71
+ // decisionList node is not selectable, but we want to select the whole node not just text
72
+ if (isNodeSelection || (node === null || node === void 0 ? void 0 : node.type.name) === 'decisionList') {
73
+ selection = new _selection.GapCursorSelection(tr.doc.resolve(start + node.nodeSize), _selection.Side.RIGHT);
74
+ } else {
75
+ var _getInlineNodePos2 = getInlineNodePos(tr, start, nodeSize),
76
+ inlineNodeEndPos = _getInlineNodePos2.inlineNodeEndPos;
77
+ selection = new _state.TextSelection(tr.doc.resolve(inlineNodeEndPos));
78
+ }
79
+ tr.setSelection(selection);
80
+ return tr;
54
81
  };
@@ -3,6 +3,18 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "getInlineNodePos", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _getSelection.getInlineNodePos;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "getNestedNodePosition", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _getNestedNodePosition.getNestedNodePosition;
16
+ }
17
+ });
6
18
  Object.defineProperty(exports, "getSelection", {
7
19
  enumerable: true,
8
20
  get: function get() {
@@ -15,4 +27,11 @@ Object.defineProperty(exports, "selectNode", {
15
27
  return _getSelection.selectNode;
16
28
  }
17
29
  });
18
- var _getSelection = require("./getSelection");
30
+ Object.defineProperty(exports, "setCursorPositionAtMovedNode", {
31
+ enumerable: true,
32
+ get: function get() {
33
+ return _getSelection.setCursorPositionAtMovedNode;
34
+ }
35
+ });
36
+ var _getSelection = require("./getSelection");
37
+ var _getNestedNodePosition = require("./getNestedNodePosition");
@@ -9,7 +9,8 @@ import { fg } from '@atlaskit/platform-feature-flags';
9
9
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
10
10
  import { DIRECTION } from '../consts';
11
11
  import { key } from '../pm-plugins/main';
12
- import { selectNode } from '../utils';
12
+ import { getNestedNodePosition, selectNode } from '../utils';
13
+ import { setCursorPositionAtMovedNode } from '../utils/getSelection';
13
14
  import { canMoveNodeToIndex, isInsideTable, transformSliceExpandToNestedExpand } from '../utils/validation';
14
15
 
15
16
  /**
@@ -64,8 +65,8 @@ const getCurrentNodePos = (state, isParentNodeOfTypeLayout) => {
64
65
  // 2. caret cursor is inside the node
65
66
  // 3. the start of the selection is inside the node
66
67
  currentNodePos = selection.$from.before(1);
67
- if (fg('platform_editor_element_dnd_nested_a11y')) {
68
- currentNodePos = selection.$from.depth > (isParentNodeOfTypeLayout ? 2 : 1) ? selection.$from.before(selection.$from.depth) : selection.$from.before(1);
68
+ if (selection.$from.depth > 0 && fg('platform_editor_element_dnd_nested_a11y')) {
69
+ currentNodePos = getNestedNodePosition(state);
69
70
  }
70
71
  }
71
72
  return currentNodePos;
@@ -183,7 +184,7 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
183
184
  mappedTo = tr.mapping.map(to);
184
185
  tr.insert(mappedTo, nodeCopy); // insert the content at the new position
185
186
  }
186
- tr = selectNode(tr, mappedTo, node.type.name);
187
+ tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP && fg('platform_editor_element_dnd_nested_fix_patch_2') ? setCursorPositionAtMovedNode(tr, mappedTo) : selectNode(tr, mappedTo, node.type.name);
187
188
  tr.setMeta(key, {
188
189
  nodeMoved: true
189
190
  });
@@ -1,6 +1,7 @@
1
1
  import { isInTable } from '@atlaskit/editor-tables/utils';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { key } from '../pm-plugins/main';
4
+ import { getNestedNodePosition } from '../utils';
4
5
  export const showDragHandleAtSelection = (api, shouldFocusParentNode) => (state, _, view) => {
5
6
  const {
6
7
  $from
@@ -14,13 +15,21 @@ export const showDragHandleAtSelection = (api, shouldFocusParentNode) => (state,
14
15
 
15
16
  // if the node is already focused, pressing the keymap second times should focus the parent node
16
17
  shouldFocusParentNode = activeNode && ((_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused);
17
- const parentPos = isInTable(state) ? $from.before(1) : shouldFocusParentNode ? $from.start($from.depth - 1) : $from.start();
18
+ const parentPos = isInTable(state) ? $from.before(1) : shouldFocusParentNode ? $from.before(1) : getNestedNodePosition(state) + 1;
18
19
  const parentElement = view === null || view === void 0 ? void 0 : (_view$domAtPos = view.domAtPos(parentPos, 0)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
19
20
  if (parentElement) {
20
- const anchorName = parentElement.getAttribute('data-drag-handler-anchor-name');
21
- const nodeType = parentElement.getAttribute('data-drag-handler-node-type');
21
+ let anchorName = parentElement.getAttribute('data-drag-handler-anchor-name');
22
+ let nodeType = parentElement.getAttribute('data-drag-handler-node-type');
23
+ if (!anchorName || !nodeType) {
24
+ // for nodes like panel and mediaSingle, the drag handle decoration is not applied to the dom node at the node position but to the parent node
25
+ const closestParentElement = parentElement.closest('[data-drag-handler-anchor-name]');
26
+ if (closestParentElement) {
27
+ anchorName = closestParentElement.getAttribute('data-drag-handler-anchor-name');
28
+ nodeType = closestParentElement.getAttribute('data-drag-handler-node-type');
29
+ }
30
+ }
22
31
  if (api && anchorName && nodeType) {
23
- api.core.actions.execute(api.blockControls.commands.showDragHandleAt($from.before(), anchorName, nodeType, {
32
+ api.core.actions.execute(api.blockControls.commands.showDragHandleAt(parentPos - 1, anchorName, nodeType, {
24
33
  isFocused: true
25
34
  }));
26
35
  return true;
@@ -12,7 +12,6 @@ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
12
12
  import { dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, getAriaKeyshortcuts, TooltipContentWithMultipleShortcuts } from '@atlaskit/editor-common/keymaps';
13
13
  import { blockControlsMessages } from '@atlaskit/editor-common/messages';
14
14
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
15
- import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
16
15
  import DragHandlerIcon from '@atlaskit/icon/glyph/drag-handler';
17
16
  import { fg } from '@atlaskit/platform-feature-flags';
18
17
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
@@ -20,7 +19,7 @@ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/el
20
19
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
21
20
  import Tooltip from '@atlaskit/tooltip';
22
21
  import { key } from '../pm-plugins/main';
23
- import { selectNode } from '../utils';
22
+ import { getNestedNodePosition, selectNode } from '../utils';
24
23
  import { getLeftPosition, getTopPosition } from '../utils/drag-handle-positions';
25
24
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, topPositionAdjustment } from './consts';
26
25
  import { dragPreview } from './drag-preview';
@@ -362,7 +361,7 @@ const DragHandleInternal = ({
362
361
  }];
363
362
  let isParentNodeOfTypeLayout;
364
363
  if (!isTopLevelNode && handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused && fg('platform_editor_element_dnd_nested_a11y')) {
365
- isParentNodeOfTypeLayout = nodeType === 'layoutSection' || !!findParentNodeOfType([view.state.schema.nodes.layoutSection])(view.state.selection);
364
+ isParentNodeOfTypeLayout = nodeType === 'layoutSection' || view.state.doc.resolve(getNestedNodePosition(view.state)).node().type.name === 'layoutColumn';
366
365
  if (isParentNodeOfTypeLayout) {
367
366
  helpDescriptors = [...helpDescriptors, {
368
367
  description: formatMessage(blockControlsMessages.moveLeft),
@@ -0,0 +1,23 @@
1
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
+ export const getNestedNodePosition = state => {
4
+ const {
5
+ selection
6
+ } = state;
7
+ let nestedNodePos = selection.$from.before(1);
8
+ if (selection instanceof TextSelection) {
9
+ nestedNodePos = selection.$from.before();
10
+ const $pos = state.doc.resolve(nestedNodePos);
11
+ if ($pos.depth < 1) {
12
+ return nestedNodePos;
13
+ }
14
+ const parentNodeOfSpecificTypes = findParentNodeOfType([state.schema.nodes.bulletList, state.schema.nodes.orderedList, state.schema.nodes.blockquote, state.schema.nodes.taskList])(state.selection);
15
+ if (parentNodeOfSpecificTypes) {
16
+ const parentNodeType = parentNodeOfSpecificTypes.node.type.name;
17
+ nestedNodePos = ['bulletList', 'orderedList'].includes(parentNodeType) ? $pos.before($pos.depth - 1) : ['blockquote', 'taskList'].includes(parentNodeType) ? $pos.before() : nestedNodePos;
18
+ }
19
+ } else {
20
+ nestedNodePos = selection.$from.pos;
21
+ }
22
+ return nestedNodePos;
23
+ };
@@ -1,5 +1,28 @@
1
+ import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
1
2
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
2
3
  import { selectTableClosestToPos } from '@atlaskit/editor-tables/utils';
4
+ export const getInlineNodePos = (tr, start, nodeSize) => {
5
+ const $startPos = tr.doc.resolve(start);
6
+ // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
7
+ // Find the first inline node in the node
8
+ let inlineNodePos = start;
9
+ let foundInlineNode = false;
10
+ let inlineNodeEndPos = 0;
11
+ tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, (n, pos) => {
12
+ if (n.isInline) {
13
+ inlineNodeEndPos = pos + n.nodeSize;
14
+ }
15
+ if (n.isInline && !foundInlineNode) {
16
+ inlineNodePos = pos;
17
+ foundInlineNode = true;
18
+ }
19
+ return true;
20
+ });
21
+ return {
22
+ inlineNodePos,
23
+ inlineNodeEndPos
24
+ };
25
+ };
3
26
  export const getSelection = (tr, start) => {
4
27
  const node = tr.doc.nodeAt(start);
5
28
  const isNodeSelection = node && NodeSelection.isSelectable(node);
@@ -19,21 +42,10 @@ export const getSelection = (tr, start) => {
19
42
  nodeName === 'mediaGroup') {
20
43
  return new NodeSelection($startPos);
21
44
  } else {
22
- // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
23
- // Find the first inline node in the node
24
- let inlineNodePos = start;
25
- let foundInlineNode = false;
26
- let inlineNodeEndPos = 0;
27
- tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, (n, pos) => {
28
- if (n.isInline) {
29
- inlineNodeEndPos = pos + n.nodeSize;
30
- }
31
- if (n.isInline && !foundInlineNode) {
32
- inlineNodePos = pos;
33
- foundInlineNode = true;
34
- }
35
- return true;
36
- });
45
+ const {
46
+ inlineNodePos,
47
+ inlineNodeEndPos
48
+ } = getInlineNodePos(tr, start, nodeSize);
37
49
  return new TextSelection(tr.doc.resolve(inlineNodeEndPos), tr.doc.resolve(inlineNodePos));
38
50
  }
39
51
  };
@@ -45,4 +57,21 @@ export const selectNode = (tr, start, nodeType) => {
45
57
  tr.setSelection(getSelection(tr, start));
46
58
  }
47
59
  return tr;
60
+ };
61
+ export const setCursorPositionAtMovedNode = (tr, start) => {
62
+ const node = tr.doc.nodeAt(start);
63
+ const isNodeSelection = node && NodeSelection.isSelectable(node);
64
+ const nodeSize = node ? node.nodeSize : 1;
65
+ let selection;
66
+ // decisionList node is not selectable, but we want to select the whole node not just text
67
+ if (isNodeSelection || (node === null || node === void 0 ? void 0 : node.type.name) === 'decisionList') {
68
+ selection = new GapCursorSelection(tr.doc.resolve(start + node.nodeSize), Side.RIGHT);
69
+ } else {
70
+ const {
71
+ inlineNodeEndPos
72
+ } = getInlineNodePos(tr, start, nodeSize);
73
+ selection = new TextSelection(tr.doc.resolve(inlineNodeEndPos));
74
+ }
75
+ tr.setSelection(selection);
76
+ return tr;
48
77
  };
@@ -1 +1,2 @@
1
- export { getSelection, selectNode } from './getSelection';
1
+ export { getInlineNodePos, getSelection, selectNode, setCursorPositionAtMovedNode } from './getSelection';
2
+ export { getNestedNodePosition } from './getNestedNodePosition';
@@ -12,7 +12,8 @@ import { fg } from '@atlaskit/platform-feature-flags';
12
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
13
  import { DIRECTION } from '../consts';
14
14
  import { key } from '../pm-plugins/main';
15
- import { selectNode } from '../utils';
15
+ import { getNestedNodePosition, selectNode } from '../utils';
16
+ import { setCursorPositionAtMovedNode } from '../utils/getSelection';
16
17
  import { canMoveNodeToIndex, isInsideTable, transformSliceExpandToNestedExpand } from '../utils/validation';
17
18
 
18
19
  /**
@@ -63,8 +64,8 @@ var getCurrentNodePos = function getCurrentNodePos(state, isParentNodeOfTypeLayo
63
64
  // 2. caret cursor is inside the node
64
65
  // 3. the start of the selection is inside the node
65
66
  currentNodePos = selection.$from.before(1);
66
- if (fg('platform_editor_element_dnd_nested_a11y')) {
67
- currentNodePos = selection.$from.depth > (isParentNodeOfTypeLayout ? 2 : 1) ? selection.$from.before(selection.$from.depth) : selection.$from.before(1);
67
+ if (selection.$from.depth > 0 && fg('platform_editor_element_dnd_nested_a11y')) {
68
+ currentNodePos = getNestedNodePosition(state);
68
69
  }
69
70
  }
70
71
  return currentNodePos;
@@ -183,7 +184,7 @@ export var moveNode = function moveNode(api) {
183
184
  mappedTo = tr.mapping.map(to);
184
185
  tr.insert(mappedTo, _nodeCopy); // insert the content at the new position
185
186
  }
186
- tr = selectNode(tr, mappedTo, node.type.name);
187
+ tr = inputMethod === INPUT_METHOD.DRAG_AND_DROP && fg('platform_editor_element_dnd_nested_fix_patch_2') ? setCursorPositionAtMovedNode(tr, mappedTo) : selectNode(tr, mappedTo, node.type.name);
187
188
  tr.setMeta(key, {
188
189
  nodeMoved: true
189
190
  });
@@ -1,6 +1,7 @@
1
1
  import { isInTable } from '@atlaskit/editor-tables/utils';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { key } from '../pm-plugins/main';
4
+ import { getNestedNodePosition } from '../utils';
4
5
  export var showDragHandleAtSelection = function showDragHandleAtSelection(api, shouldFocusParentNode) {
5
6
  return function (state, _, view) {
6
7
  var $from = state.selection.$from;
@@ -12,13 +13,21 @@ export var showDragHandleAtSelection = function showDragHandleAtSelection(api, s
12
13
 
13
14
  // if the node is already focused, pressing the keymap second times should focus the parent node
14
15
  shouldFocusParentNode = activeNode && ((_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused);
15
- var parentPos = isInTable(state) ? $from.before(1) : shouldFocusParentNode ? $from.start($from.depth - 1) : $from.start();
16
+ var parentPos = isInTable(state) ? $from.before(1) : shouldFocusParentNode ? $from.before(1) : getNestedNodePosition(state) + 1;
16
17
  var parentElement = view === null || view === void 0 || (_view$domAtPos = view.domAtPos(parentPos, 0)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
17
18
  if (parentElement) {
18
19
  var anchorName = parentElement.getAttribute('data-drag-handler-anchor-name');
19
20
  var nodeType = parentElement.getAttribute('data-drag-handler-node-type');
21
+ if (!anchorName || !nodeType) {
22
+ // for nodes like panel and mediaSingle, the drag handle decoration is not applied to the dom node at the node position but to the parent node
23
+ var closestParentElement = parentElement.closest('[data-drag-handler-anchor-name]');
24
+ if (closestParentElement) {
25
+ anchorName = closestParentElement.getAttribute('data-drag-handler-anchor-name');
26
+ nodeType = closestParentElement.getAttribute('data-drag-handler-node-type');
27
+ }
28
+ }
20
29
  if (api && anchorName && nodeType) {
21
- api.core.actions.execute(api.blockControls.commands.showDragHandleAt($from.before(), anchorName, nodeType, {
30
+ api.core.actions.execute(api.blockControls.commands.showDragHandleAt(parentPos - 1, anchorName, nodeType, {
22
31
  isFocused: true
23
32
  }));
24
33
  return true;
@@ -14,7 +14,6 @@ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
14
14
  import { dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, getAriaKeyshortcuts, TooltipContentWithMultipleShortcuts } from '@atlaskit/editor-common/keymaps';
15
15
  import { blockControlsMessages } from '@atlaskit/editor-common/messages';
16
16
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
17
- import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
18
17
  import DragHandlerIcon from '@atlaskit/icon/glyph/drag-handler';
19
18
  import { fg } from '@atlaskit/platform-feature-flags';
20
19
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
@@ -22,7 +21,7 @@ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/el
22
21
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
23
22
  import Tooltip from '@atlaskit/tooltip';
24
23
  import { key } from '../pm-plugins/main';
25
- import { selectNode } from '../utils';
24
+ import { getNestedNodePosition, selectNode } from '../utils';
26
25
  import { getLeftPosition, getTopPosition } from '../utils/drag-handle-positions';
27
26
  import { DRAG_HANDLE_BORDER_RADIUS, DRAG_HANDLE_HEIGHT, DRAG_HANDLE_WIDTH, DRAG_HANDLE_ZINDEX, dragHandleGap, topPositionAdjustment } from './consts';
28
27
  import { dragPreview } from './drag-preview';
@@ -370,7 +369,7 @@ var DragHandleInternal = function DragHandleInternal(_ref) {
370
369
  }];
371
370
  var isParentNodeOfTypeLayout;
372
371
  if (!isTopLevelNode && handleOptions !== null && handleOptions !== void 0 && handleOptions.isFocused && fg('platform_editor_element_dnd_nested_a11y')) {
373
- isParentNodeOfTypeLayout = nodeType === 'layoutSection' || !!findParentNodeOfType([view.state.schema.nodes.layoutSection])(view.state.selection);
372
+ isParentNodeOfTypeLayout = nodeType === 'layoutSection' || view.state.doc.resolve(getNestedNodePosition(view.state)).node().type.name === 'layoutColumn';
374
373
  if (isParentNodeOfTypeLayout) {
375
374
  helpDescriptors = [].concat(_toConsumableArray(helpDescriptors), [{
376
375
  description: formatMessage(blockControlsMessages.moveLeft),
@@ -0,0 +1,21 @@
1
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
+ export var getNestedNodePosition = function getNestedNodePosition(state) {
4
+ var selection = state.selection;
5
+ var nestedNodePos = selection.$from.before(1);
6
+ if (selection instanceof TextSelection) {
7
+ nestedNodePos = selection.$from.before();
8
+ var $pos = state.doc.resolve(nestedNodePos);
9
+ if ($pos.depth < 1) {
10
+ return nestedNodePos;
11
+ }
12
+ var parentNodeOfSpecificTypes = findParentNodeOfType([state.schema.nodes.bulletList, state.schema.nodes.orderedList, state.schema.nodes.blockquote, state.schema.nodes.taskList])(state.selection);
13
+ if (parentNodeOfSpecificTypes) {
14
+ var parentNodeType = parentNodeOfSpecificTypes.node.type.name;
15
+ nestedNodePos = ['bulletList', 'orderedList'].includes(parentNodeType) ? $pos.before($pos.depth - 1) : ['blockquote', 'taskList'].includes(parentNodeType) ? $pos.before() : nestedNodePos;
16
+ }
17
+ } else {
18
+ nestedNodePos = selection.$from.pos;
19
+ }
20
+ return nestedNodePos;
21
+ };
@@ -1,5 +1,28 @@
1
+ import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
1
2
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
2
3
  import { selectTableClosestToPos } from '@atlaskit/editor-tables/utils';
4
+ export var getInlineNodePos = function getInlineNodePos(tr, start, nodeSize) {
5
+ var $startPos = tr.doc.resolve(start);
6
+ // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
7
+ // Find the first inline node in the node
8
+ var inlineNodePos = start;
9
+ var foundInlineNode = false;
10
+ var inlineNodeEndPos = 0;
11
+ tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, function (n, pos) {
12
+ if (n.isInline) {
13
+ inlineNodeEndPos = pos + n.nodeSize;
14
+ }
15
+ if (n.isInline && !foundInlineNode) {
16
+ inlineNodePos = pos;
17
+ foundInlineNode = true;
18
+ }
19
+ return true;
20
+ });
21
+ return {
22
+ inlineNodePos: inlineNodePos,
23
+ inlineNodeEndPos: inlineNodeEndPos
24
+ };
25
+ };
3
26
  export var getSelection = function getSelection(tr, start) {
4
27
  var node = tr.doc.nodeAt(start);
5
28
  var isNodeSelection = node && NodeSelection.isSelectable(node);
@@ -19,21 +42,9 @@ export var getSelection = function getSelection(tr, start) {
19
42
  nodeName === 'mediaGroup') {
20
43
  return new NodeSelection($startPos);
21
44
  } else {
22
- // To trigger the annotation floating toolbar for non-selectable node, we need to select inline nodes
23
- // Find the first inline node in the node
24
- var inlineNodePos = start;
25
- var foundInlineNode = false;
26
- var inlineNodeEndPos = 0;
27
- tr.doc.nodesBetween($startPos.pos, $startPos.pos + nodeSize, function (n, pos) {
28
- if (n.isInline) {
29
- inlineNodeEndPos = pos + n.nodeSize;
30
- }
31
- if (n.isInline && !foundInlineNode) {
32
- inlineNodePos = pos;
33
- foundInlineNode = true;
34
- }
35
- return true;
36
- });
45
+ var _getInlineNodePos = getInlineNodePos(tr, start, nodeSize),
46
+ inlineNodePos = _getInlineNodePos.inlineNodePos,
47
+ inlineNodeEndPos = _getInlineNodePos.inlineNodeEndPos;
37
48
  return new TextSelection(tr.doc.resolve(inlineNodeEndPos), tr.doc.resolve(inlineNodePos));
38
49
  }
39
50
  };
@@ -45,4 +56,20 @@ export var selectNode = function selectNode(tr, start, nodeType) {
45
56
  tr.setSelection(getSelection(tr, start));
46
57
  }
47
58
  return tr;
59
+ };
60
+ export var setCursorPositionAtMovedNode = function setCursorPositionAtMovedNode(tr, start) {
61
+ var node = tr.doc.nodeAt(start);
62
+ var isNodeSelection = node && NodeSelection.isSelectable(node);
63
+ var nodeSize = node ? node.nodeSize : 1;
64
+ var selection;
65
+ // decisionList node is not selectable, but we want to select the whole node not just text
66
+ if (isNodeSelection || (node === null || node === void 0 ? void 0 : node.type.name) === 'decisionList') {
67
+ selection = new GapCursorSelection(tr.doc.resolve(start + node.nodeSize), Side.RIGHT);
68
+ } else {
69
+ var _getInlineNodePos2 = getInlineNodePos(tr, start, nodeSize),
70
+ inlineNodeEndPos = _getInlineNodePos2.inlineNodeEndPos;
71
+ selection = new TextSelection(tr.doc.resolve(inlineNodeEndPos));
72
+ }
73
+ tr.setSelection(selection);
74
+ return tr;
48
75
  };
@@ -1 +1,2 @@
1
- export { getSelection, selectNode } from './getSelection';
1
+ export { getInlineNodePos, getSelection, selectNode, setCursorPositionAtMovedNode } from './getSelection';
2
+ export { getNestedNodePosition } from './getNestedNodePosition';
@@ -0,0 +1,2 @@
1
+ import { type EditorState } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getNestedNodePosition: (state: EditorState) => number;
@@ -1,3 +1,8 @@
1
1
  import { NodeSelection, TextSelection, type Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getInlineNodePos: (tr: Transaction, start: number, nodeSize: number) => {
3
+ inlineNodePos: number;
4
+ inlineNodeEndPos: number;
5
+ };
2
6
  export declare const getSelection: (tr: Transaction, start: number) => NodeSelection | TextSelection;
3
7
  export declare const selectNode: (tr: Transaction, start: number, nodeType: string) => Transaction;
8
+ export declare const setCursorPositionAtMovedNode: (tr: Transaction, start: number) => Transaction;
@@ -1 +1,2 @@
1
- export { getSelection, selectNode } from './getSelection';
1
+ export { getInlineNodePos, getSelection, selectNode, setCursorPositionAtMovedNode, } from './getSelection';
2
+ export { getNestedNodePosition } from './getNestedNodePosition';
@@ -0,0 +1,2 @@
1
+ import { type EditorState } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getNestedNodePosition: (state: EditorState) => number;
@@ -1,3 +1,8 @@
1
1
  import { NodeSelection, TextSelection, type Transaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getInlineNodePos: (tr: Transaction, start: number, nodeSize: number) => {
3
+ inlineNodePos: number;
4
+ inlineNodeEndPos: number;
5
+ };
2
6
  export declare const getSelection: (tr: Transaction, start: number) => NodeSelection | TextSelection;
3
7
  export declare const selectNode: (tr: Transaction, start: number, nodeType: string) => Transaction;
8
+ export declare const setCursorPositionAtMovedNode: (tr: Transaction, start: number) => Transaction;
@@ -1 +1,2 @@
1
- export { getSelection, selectNode } from './getSelection';
1
+ export { getInlineNodePos, getSelection, selectNode, setCursorPositionAtMovedNode, } from './getSelection';
2
+ export { getNestedNodePosition } from './getNestedNodePosition';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@atlaskit/adf-schema": "^40.9.0",
34
- "@atlaskit/editor-common": "^93.1.0",
34
+ "@atlaskit/editor-common": "^93.2.0",
35
35
  "@atlaskit/editor-plugin-accessibility-utils": "^1.2.0",
36
36
  "@atlaskit/editor-plugin-analytics": "^1.8.0",
37
37
  "@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
@@ -41,14 +41,14 @@
41
41
  "@atlaskit/editor-prosemirror": "6.0.0",
42
42
  "@atlaskit/editor-shared-styles": "^3.0.0",
43
43
  "@atlaskit/editor-tables": "^2.8.0",
44
- "@atlaskit/icon": "^22.20.0",
44
+ "@atlaskit/icon": "^22.22.0",
45
45
  "@atlaskit/platform-feature-flags": "^0.3.0",
46
- "@atlaskit/pragmatic-drag-and-drop": "^1.3.0",
46
+ "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
47
47
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.4.0",
48
48
  "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^1.1.0",
49
49
  "@atlaskit/primitives": "^12.2.0",
50
50
  "@atlaskit/theme": "^13.0.0",
51
- "@atlaskit/tmp-editor-statsig": "^2.2.0",
51
+ "@atlaskit/tmp-editor-statsig": "^2.3.0",
52
52
  "@atlaskit/tokens": "^2.0.0",
53
53
  "@atlaskit/tooltip": "^18.8.0",
54
54
  "@babel/runtime": "^7.0.0",