@atlaskit/editor-plugin-block-controls 9.0.33 → 9.1.1

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 (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/blockControlsPlugin.js +30 -11
  3. package/dist/cjs/pm-plugins/decorations-drag-handle.js +1 -2
  4. package/dist/cjs/pm-plugins/decorations-quick-insert-button.js +1 -2
  5. package/dist/cjs/pm-plugins/handle-mouse-over.js +3 -3
  6. package/dist/cjs/pm-plugins/interaction-tracking/handle-mouse-move.js +2 -2
  7. package/dist/cjs/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  8. package/dist/cjs/pm-plugins/main.js +3 -4
  9. package/dist/cjs/pm-plugins/utils/expand-and-update-selection.js +69 -0
  10. package/dist/cjs/ui/drag-handle.js +50 -101
  11. package/dist/cjs/ui/visibility-container.js +1 -1
  12. package/dist/es2019/blockControlsPlugin.js +20 -1
  13. package/dist/es2019/pm-plugins/decorations-drag-handle.js +1 -2
  14. package/dist/es2019/pm-plugins/decorations-quick-insert-button.js +1 -2
  15. package/dist/es2019/pm-plugins/handle-mouse-over.js +3 -3
  16. package/dist/es2019/pm-plugins/interaction-tracking/handle-mouse-move.js +2 -2
  17. package/dist/es2019/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  18. package/dist/es2019/pm-plugins/main.js +3 -4
  19. package/dist/es2019/pm-plugins/utils/expand-and-update-selection.js +65 -0
  20. package/dist/es2019/ui/drag-handle.js +9 -62
  21. package/dist/es2019/ui/visibility-container.js +1 -1
  22. package/dist/esm/blockControlsPlugin.js +30 -11
  23. package/dist/esm/pm-plugins/decorations-drag-handle.js +1 -2
  24. package/dist/esm/pm-plugins/decorations-quick-insert-button.js +1 -2
  25. package/dist/esm/pm-plugins/handle-mouse-over.js +3 -3
  26. package/dist/esm/pm-plugins/interaction-tracking/handle-mouse-move.js +2 -2
  27. package/dist/esm/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  28. package/dist/esm/pm-plugins/main.js +3 -4
  29. package/dist/esm/pm-plugins/utils/expand-and-update-selection.js +63 -0
  30. package/dist/esm/ui/drag-handle.js +46 -97
  31. package/dist/esm/ui/visibility-container.js +1 -1
  32. package/dist/types/blockControlsPluginType.d.ts +14 -0
  33. package/dist/types/pm-plugins/utils/expand-and-update-selection.d.ts +20 -0
  34. package/dist/types/ui/consts.d.ts +1 -1
  35. package/dist/types-ts4.5/blockControlsPluginType.d.ts +14 -0
  36. package/dist/types-ts4.5/pm-plugins/utils/expand-and-update-selection.d.ts +20 -0
  37. package/dist/types-ts4.5/ui/consts.d.ts +1 -1
  38. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 9.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ef40f467da8e6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ef40f467da8e6) -
8
+ Fix drag handle not appearing in last layout column and remix button not showing correctly when
9
+ confluence_remix_button_right_side_block_fg is enabled. Layout column drag handles now always show
10
+ regardless of hover side, remix button correctly shows on right-side hover only, and layoutSection
11
+ is always remixable regardless of content.
12
+ - Updated dependencies
13
+
14
+ ## 9.1.0
15
+
16
+ ### Minor Changes
17
+
18
+ - [`81e6d01a5d2b5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/81e6d01a5d2b5) -
19
+ Expose expandAndUpdateSelection as a plugin command so other plugins can update the ProseMirror
20
+ selection using the same block-control click logic
21
+
3
22
  ## 9.0.33
4
23
 
5
24
  ### Patch Changes
@@ -24,6 +24,7 @@ var _main = require("./pm-plugins/main");
24
24
  var _editorCommands = require("./pm-plugins/selection-preservation/editor-commands");
25
25
  var _pluginKey = require("./pm-plugins/selection-preservation/plugin-key");
26
26
  var _pmPlugin2 = require("./pm-plugins/selection-preservation/pm-plugin");
27
+ var _expandAndUpdateSelection2 = require("./pm-plugins/utils/expand-and-update-selection");
27
28
  var _getSelection = require("./pm-plugins/utils/getSelection");
28
29
  var _globalStyles = require("./ui/global-styles");
29
30
  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; }
@@ -84,11 +85,29 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
84
85
  return pmPlugins;
85
86
  },
86
87
  commands: {
88
+ expandAndUpdateSelection: function expandAndUpdateSelection(_ref3) {
89
+ var startPos = _ref3.startPos,
90
+ selection = _ref3.selection,
91
+ isShiftPressed = _ref3.isShiftPressed,
92
+ nodeType = _ref3.nodeType;
93
+ return function (_ref4) {
94
+ var tr = _ref4.tr;
95
+ (0, _expandAndUpdateSelection2.expandAndUpdateSelection)({
96
+ tr: tr,
97
+ selection: selection,
98
+ startPos: startPos,
99
+ isShiftPressed: isShiftPressed,
100
+ nodeType: nodeType,
101
+ api: api
102
+ });
103
+ return tr;
104
+ };
105
+ },
87
106
  moveNode: (0, _moveNode.moveNode)(api),
88
107
  moveToLayout: (0, _moveToLayout.moveToLayout)(api),
89
108
  showDragHandleAt: function showDragHandleAt(pos, anchorName, nodeType, handleOptions, rootPos, rootAnchorName, rootNodeType) {
90
- return function (_ref3) {
91
- var tr = _ref3.tr;
109
+ return function (_ref5) {
110
+ var tr = _ref5.tr;
92
111
  var currMeta = tr.getMeta(_main.key);
93
112
  tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
94
113
  activeNode: {
@@ -105,9 +124,9 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
105
124
  };
106
125
  },
107
126
  toggleBlockMenu: function toggleBlockMenu(options) {
108
- return function (_ref4) {
127
+ return function (_ref6) {
109
128
  var _api$userIntent, _api$blockControls, _options$anchorName, _api$blockControls2;
110
- var tr = _ref4.tr;
129
+ var tr = _ref6.tr;
111
130
  if (!(0, _experiments.editorExperiment)('platform_editor_block_menu', true)) {
112
131
  return tr;
113
132
  }
@@ -212,9 +231,9 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
212
231
  };
213
232
  },
214
233
  setNodeDragged: function setNodeDragged(getPos, anchorName, nodeType) {
215
- return function (_ref5) {
234
+ return function (_ref7) {
216
235
  var _api$userIntent6;
217
- var tr = _ref5.tr;
236
+ var tr = _ref7.tr;
218
237
  var pos = getPos();
219
238
  if (pos === undefined) {
220
239
  return tr;
@@ -244,9 +263,9 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
244
263
  };
245
264
  },
246
265
  setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
247
- return function (_ref6) {
266
+ return function (_ref8) {
248
267
  var _api$selection, _$to$nodeBefore, _$from$nodeAfter;
249
- var tr = _ref6.tr;
268
+ var tr = _ref8.tr;
250
269
  var _tr$selection = tr.selection,
251
270
  userAnchor = _tr$selection.anchor,
252
271
  userHead = _tr$selection.head;
@@ -292,8 +311,8 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
292
311
  };
293
312
  },
294
313
  setSelectedViaDragHandle: function setSelectedViaDragHandle(isSelectedViaDragHandle) {
295
- return function (_ref7) {
296
- var tr = _ref7.tr;
314
+ return function (_ref9) {
315
+ var tr = _ref9.tr;
297
316
  var currMeta = tr.getMeta(_main.key);
298
317
  return tr.setMeta(_main.key, _objectSpread(_objectSpread({}, currMeta), {}, {
299
318
  isSelectedViaDragHandle: isSelectedViaDragHandle
@@ -337,7 +356,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
337
356
  if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
338
357
  var _interactionTrackingP2, _interactionTrackingP3, _interactionTrackingP4;
339
358
  sharedState.isMouseOut = (_interactionTrackingP2 = (_interactionTrackingP3 = _pmPlugin.interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP3 === void 0 ? void 0 : _interactionTrackingP3.isMouseOut) !== null && _interactionTrackingP2 !== void 0 ? _interactionTrackingP2 : false;
340
- // rightSideControlsEnabled is the single source of truth (confluence_remix_icon_right_side from preset)
359
+ // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
341
360
  sharedState.rightSideControlsEnabled = rightSideControlsEnabled;
342
361
  sharedState.hoverSide = rightSideControlsEnabled ? (_interactionTrackingP4 = _pmPlugin.interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP4 === void 0 ? void 0 : _interactionTrackingP4.hoverSide : undefined;
343
362
  }
@@ -13,7 +13,6 @@ var _uuid = _interopRequireDefault(require("uuid"));
13
13
  var _view = require("@atlaskit/editor-prosemirror/view");
14
14
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
15
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
16
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
17
16
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
18
17
  var _dragHandle = require("../ui/drag-handle");
19
18
  var _decorationsCommon = require("./decorations-common");
@@ -86,7 +85,7 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
86
85
  var element = document.createElement('span');
87
86
  // inline decoration causes focus issues when refocusing Editor into first line
88
87
  element.style.display = 'block';
89
- if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)) {
88
+ if ((0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')) {
90
89
  element.setAttribute('data-blocks-decorator-widget', 'true');
91
90
  }
92
91
  element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
@@ -10,7 +10,6 @@ var _uuid = _interopRequireDefault(require("uuid"));
10
10
  var _view = require("@atlaskit/editor-prosemirror/view");
11
11
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
12
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
13
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
14
13
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
15
14
  var _quickInsertButton = require("../ui/quick-insert-button");
16
15
  var _marks = require("./utils/marks");
@@ -76,7 +75,7 @@ var quickInsertButtonDecoration = exports.quickInsertButtonDecoration = function
76
75
  element.style.clear = 'unset';
77
76
  element.contentEditable = 'false';
78
77
  element.setAttribute('data-blocks-quick-insert-container', 'true');
79
- if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)) {
78
+ if ((0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')) {
80
79
  element.setAttribute('data-blocks-quick-insert-button', 'true');
81
80
  }
82
81
  element.setAttribute('data-testid', 'block-ctrl-quick-insert-button');
@@ -9,8 +9,8 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
9
9
  var _memoizeOne = _interopRequireDefault(require("memoize-one"));
10
10
  var _selection = require("@atlaskit/editor-common/selection");
11
11
  var _toolbarFlagCheck = require("@atlaskit/editor-common/toolbar-flag-check");
12
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
13
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
13
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
14
14
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
15
15
  var _domAttrName = require("../ui/utils/dom-attr-name");
16
16
  var _decorationsAnchor = require("./decorations-anchor");
@@ -63,7 +63,7 @@ var handleMouseOver = exports.handleMouseOver = function handleMouseOver(view, e
63
63
  // We shouldn't be firing mouse over transactions when the editor is disabled,
64
64
  // except in view mode when right-side controls are enabled (show controls on block hover)
65
65
  var rightSideControlsEnabled = (_api$blockControls$sh = api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.rightSideControlsEnabled) !== null && _api$blockControls$sh !== void 0 ? _api$blockControls$sh : false;
66
- if (editorDisabled && (!isViewMode || !(rightSideControlsEnabled && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)))) {
66
+ if (editorDisabled && (!isViewMode || !(rightSideControlsEnabled && (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')))) {
67
67
  return false;
68
68
  }
69
69
 
@@ -91,7 +91,7 @@ var handleMouseOver = exports.handleMouseOver = function handleMouseOver(view, e
91
91
 
92
92
  // When hovering over the right-edge button (rendered in a portal outside the block), resolve the
93
93
  // block from the container's anchor so activeNode stays set and the button remains visible.
94
- if (!rootElement && rightSideControlsEnabled && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)) {
94
+ if (!rootElement && rightSideControlsEnabled && (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')) {
95
95
  var rightEdgeContainer = target === null || target === void 0 ? void 0 : target.closest('[data-blocks-right-edge-button-container]');
96
96
  if (rightEdgeContainer) {
97
97
  var anchor = rightEdgeContainer.getAttribute('data-blocks-right-edge-button-anchor');
@@ -27,7 +27,7 @@ var RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
27
27
 
28
28
  /**
29
29
  * Process hover position and set left/right side. Only invoked when right-side controls are
30
- * enabled (confluence_remix_icon_right_side); handleMouseMove returns early otherwise.
30
+ * enabled (confluence_remix_button_right_side_block_fg); handleMouseMove returns early otherwise.
31
31
  */
32
32
  var processHoverSide = function processHoverSide(view) {
33
33
  var event = pendingByView.get(view);
@@ -88,7 +88,7 @@ var handleMouseMove = exports.handleMouseMove = function handleMouseMove(view, e
88
88
  (0, _commands.stopEditing)(view);
89
89
  }
90
90
 
91
- // Only track hover side when right-side controls are enabled (single source: confluence_remix_icon_right_side via config)
91
+ // Only track hover side when right-side controls are enabled (single source: confluence_remix_button_right_side_block_fg via config)
92
92
  if (!rightSideControlsEnabled) {
93
93
  return false;
94
94
  }
@@ -72,7 +72,7 @@ var createInteractionTrackingPlugin = exports.createInteractionTrackingPlugin =
72
72
  },
73
73
  view: (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? function (view) {
74
74
  var editorContentArea = view.dom.closest('.ak-editor-content-area');
75
- // rightSideControlsEnabled is the single source of truth (confluence_remix_icon_right_side from preset)
75
+ // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
76
76
 
77
77
  var unbindMouseEnter;
78
78
  var unbindMouseLeave;
@@ -23,7 +23,6 @@ var _element = require("@atlaskit/pragmatic-drag-and-drop-auto-scroll/element");
23
23
  var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
24
24
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
25
25
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
26
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
27
26
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
28
27
  var _domAttrName = require("../ui/utils/dom-attr-name");
29
28
  var _decorationsAnchor = require("./decorations-anchor");
@@ -469,7 +468,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
469
468
  _iterator.f();
470
469
  }
471
470
  }
472
- if (rightSideControlsEnabled && isViewMode && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)) {
471
+ if (rightSideControlsEnabled && isViewMode && (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')) {
473
472
  var _iterator2 = _createForOfIteratorHelper(nodeDecorationRegistry),
474
473
  _step2;
475
474
  try {
@@ -651,7 +650,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
651
650
  } finally {
652
651
  _iterator5.f();
653
652
  }
654
- } else if (isViewMode && rightSideControlsEnabled && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true)) {
653
+ } else if (isViewMode && rightSideControlsEnabled && (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg')) {
655
654
  // Remove view-mode right-side decorations when no active node
656
655
  var _iterator6 = _createForOfIteratorHelper(nodeDecorationRegistry),
657
656
  _step6;
@@ -813,7 +812,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
813
812
  var isDisabled = api === null || api === void 0 || (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 || (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled === void 0 ? void 0 : _api$editorDisabled.editorDisabled;
814
813
  if (isDisabled) {
815
814
  var _api$editorViewMode2;
816
- var remixRightSideEnabled = rightSideControlsEnabled && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true);
815
+ var remixRightSideEnabled = rightSideControlsEnabled && (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg');
817
816
  // Hide decorations when disabled, except in view mode when right-side controls are enabled
818
817
  if (!remixRightSideEnabled || (api === null || api === void 0 || (_api$editorViewMode2 = api.editorViewMode) === null || _api$editorViewMode2 === void 0 || (_api$editorViewMode2 = _api$editorViewMode2.sharedState.currentState()) === null || _api$editorViewMode2 === void 0 ? void 0 : _api$editorViewMode2.mode) !== 'view') {
819
818
  return;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.expandAndUpdateSelection = void 0;
7
+ var _selection = require("@atlaskit/editor-common/selection");
8
+ var _state = require("@atlaskit/editor-prosemirror/state");
9
+ var _utils = require("@atlaskit/editor-tables/utils");
10
+ var _getSelection = require("./getSelection");
11
+ var _selection2 = require("./selection");
12
+ var isPosWithinRange = function isPosWithinRange(pos, range) {
13
+ return range.start <= pos && range.end >= pos + 1;
14
+ };
15
+ /**
16
+ * Expands the current selection to encompass the full block range
17
+ * starting from the given resolved position.
18
+ */
19
+ var getExpandedSelectionRange = function getExpandedSelectionRange(_ref) {
20
+ var selection = _ref.selection,
21
+ doc = _ref.doc,
22
+ resolvedStartPos = _ref.resolvedStartPos,
23
+ isShiftPressed = _ref.isShiftPressed;
24
+ // When not pressing shift, expand the current selection
25
+ // When shift selecting upwards, expand from start of node to selection end
26
+ // When shift selecting downwards, expand from selection start to end of node
27
+ var selectUp = resolvedStartPos.pos < selection.from;
28
+ var $from = isShiftPressed && selectUp ? resolvedStartPos : selection.$from;
29
+ var $to = isShiftPressed && !selectUp ? doc.resolve(resolvedStartPos.pos + 1) : selection.$to;
30
+ var adjusted = isShiftPressed ? {
31
+ $from: $from,
32
+ $to: $to
33
+ } : (0, _selection2.adjustSelectionBoundsForEdgePositions)($from, $to);
34
+ return (0, _selection.expandToBlockRange)(adjusted.$from, adjusted.$to);
35
+ };
36
+ /**
37
+ * Updates the transaction's selection based on the clicked drag handle position.
38
+ *
39
+ * - If the clicked handle is within an existing multi-block selection range, the selection
40
+ * is expanded to cover both the existing range and the clicked node's range.
41
+ * - For tables, a table cell selection is used.
42
+ * - Otherwise, selects the single node at the clicked handle position.
43
+ */
44
+ var expandAndUpdateSelection = exports.expandAndUpdateSelection = function expandAndUpdateSelection(_ref2) {
45
+ var tr = _ref2.tr,
46
+ selection = _ref2.selection,
47
+ startPos = _ref2.startPos,
48
+ isShiftPressed = _ref2.isShiftPressed,
49
+ nodeType = _ref2.nodeType,
50
+ api = _ref2.api;
51
+ var resolvedStartPos = tr.doc.resolve(startPos);
52
+ var expandedRange = getExpandedSelectionRange({
53
+ doc: tr.doc,
54
+ selection: selection,
55
+ resolvedStartPos: resolvedStartPos,
56
+ isShiftPressed: isShiftPressed
57
+ });
58
+
59
+ // Set selection to expanded selection range if it encompasses the clicked drag handle
60
+ if (expandedRange.range && isPosWithinRange(startPos, expandedRange.range) && (0, _selection.isMultiBlockRange)(expandedRange.range)) {
61
+ // Then create a selection from the start of the first node to the end of the last node
62
+ tr.setSelection(_state.TextSelection.create(tr.doc, Math.min(selection.from, expandedRange.$from.pos), Math.max(selection.to, expandedRange.$to.pos)));
63
+ } else if (nodeType === 'table') {
64
+ (0, _utils.selectTableClosestToPos)(tr, tr.doc.resolve(startPos + 1));
65
+ } else {
66
+ // Select the clicked drag handle's node only
67
+ (0, _getSelection.selectNode)(tr, startPos, nodeType, api);
68
+ }
69
+ };
@@ -17,12 +17,10 @@ var _browser = require("@atlaskit/editor-common/browser");
17
17
  var _hooks = require("@atlaskit/editor-common/hooks");
18
18
  var _keymaps = require("@atlaskit/editor-common/keymaps");
19
19
  var _messages = require("@atlaskit/editor-common/messages");
20
- var _selection = require("@atlaskit/editor-common/selection");
21
20
  var _styles = require("@atlaskit/editor-common/styles");
22
21
  var _state = require("@atlaskit/editor-prosemirror/state");
23
22
  var _utils = require("@atlaskit/editor-prosemirror/utils");
24
23
  var _consts = require("@atlaskit/editor-shared-styles/consts");
25
- var _utils2 = require("@atlaskit/editor-tables/utils");
26
24
  var _dragHandleVertical = _interopRequireDefault(require("@atlaskit/icon/core/drag-handle-vertical"));
27
25
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
28
26
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
@@ -37,8 +35,9 @@ var _main = require("../pm-plugins/main");
37
35
  var _pluginKey = require("../pm-plugins/selection-preservation/plugin-key");
38
36
  var _analytics2 = require("../pm-plugins/utils/analytics");
39
37
  var _dragHandlePositions = require("../pm-plugins/utils/drag-handle-positions");
38
+ var _expandAndUpdateSelection = require("../pm-plugins/utils/expand-and-update-selection");
40
39
  var _getSelection = require("../pm-plugins/utils/getSelection");
41
- var _selection2 = require("../pm-plugins/utils/selection");
40
+ var _selection = require("../pm-plugins/utils/selection");
42
41
  var _consts2 = require("./consts");
43
42
  var _dragHandleNestedIcon = require("./drag-handle-nested-icon");
44
43
  var _dragPreview = require("./drag-preview");
@@ -340,73 +339,18 @@ var getNodeMargins = function getNodeMargins(node) {
340
339
  }
341
340
  return _consts2.nodeMargins[nodeTypeName] || _consts2.nodeMargins['default'];
342
341
  };
343
- var isPosWithinRange = function isPosWithinRange(pos, range) {
344
- return range.start <= pos && range.end >= pos + 1;
345
- };
346
- /**
347
- * From the current selection and the position of the drag handle being clicked,
348
- * calculate the expanded block range up to the common ancestor.
349
- */
350
- var getExpandedSelectionRange = function getExpandedSelectionRange(_ref) {
351
- var selection = _ref.selection,
352
- doc = _ref.doc,
353
- resolvedStartPos = _ref.resolvedStartPos,
354
- isShiftPressed = _ref.isShiftPressed;
355
- // When not pressing shift, expand the current selection
356
- // When shift selecting upwards, expand from start of node to selection end
357
- // When shift selecting downwards, expand from selection start to end of node
358
- var selectUp = resolvedStartPos.pos < selection.from;
359
- var $from = isShiftPressed && selectUp ? resolvedStartPos : selection.$from;
360
- var $to = isShiftPressed && !selectUp ? doc.resolve(resolvedStartPos.pos + 1) : selection.$to;
361
- var adjusted = isShiftPressed ? {
362
- $from: $from,
363
- $to: $to
364
- } : (0, _selection2.adjustSelectionBoundsForEdgePositions)($from, $to);
365
- return (0, _selection.expandToBlockRange)(adjusted.$from, adjusted.$to);
366
- };
367
- /**
368
- * Updates the transaction with preserved selection logic.
369
- * Sets selection to expanded selection range if it encompasses the clicked drag handle,
370
- * otherwise selects the clicked drag handle's node only.
371
- */
372
- var expandAndUpdateSelection = function expandAndUpdateSelection(_ref2) {
373
- var tr = _ref2.tr,
374
- selection = _ref2.selection,
375
- startPos = _ref2.startPos,
376
- isShiftPressed = _ref2.isShiftPressed,
377
- nodeType = _ref2.nodeType,
378
- api = _ref2.api;
379
- var resolvedStartPos = tr.doc.resolve(startPos);
380
- var expandedRange = getExpandedSelectionRange({
381
- doc: tr.doc,
382
- selection: selection,
383
- resolvedStartPos: resolvedStartPos,
384
- isShiftPressed: isShiftPressed
385
- });
386
-
387
- // Set selection to expanded selection range if it encompases the clicked drag handle
388
- if (expandedRange.range && isPosWithinRange(startPos, expandedRange.range) && (0, _selection.isMultiBlockRange)(expandedRange.range)) {
389
- // Then create a selection from the start of the first node to the end of the last node
390
- tr.setSelection(_state.TextSelection.create(tr.doc, Math.min(selection.from, expandedRange.$from.pos), Math.max(selection.to, expandedRange.$to.pos)));
391
- } else if (nodeType === 'table') {
392
- (0, _utils2.selectTableClosestToPos)(tr, tr.doc.resolve(startPos + 1));
393
- } else {
394
- // Select the clicked drag handle's node only
395
- (0, _getSelection.selectNode)(tr, startPos, nodeType, api);
396
- }
397
- };
398
- var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
342
+ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
399
343
  var _api$core4;
400
- var view = _ref3.view,
401
- api = _ref3.api,
402
- formatMessage = _ref3.formatMessage,
403
- getPos = _ref3.getPos,
404
- anchorName = _ref3.anchorName,
405
- nodeType = _ref3.nodeType,
406
- handleOptions = _ref3.handleOptions,
407
- _ref3$isTopLevelNode = _ref3.isTopLevelNode,
408
- isTopLevelNode = _ref3$isTopLevelNode === void 0 ? true : _ref3$isTopLevelNode,
409
- anchorRectCache = _ref3.anchorRectCache;
344
+ var view = _ref.view,
345
+ api = _ref.api,
346
+ formatMessage = _ref.formatMessage,
347
+ getPos = _ref.getPos,
348
+ anchorName = _ref.anchorName,
349
+ nodeType = _ref.nodeType,
350
+ handleOptions = _ref.handleOptions,
351
+ _ref$isTopLevelNode = _ref.isTopLevelNode,
352
+ isTopLevelNode = _ref$isTopLevelNode === void 0 ? true : _ref$isTopLevelNode,
353
+ anchorRectCache = _ref.anchorRectCache;
410
354
  var buttonRef = (0, _react.useRef)(null);
411
355
  var mouseDownRef = (0, _react.useRef)(false);
412
356
  var _useState = (0, _react.useState)(false),
@@ -521,9 +465,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
521
465
  }, []);
522
466
  var handleOnClickNew = (0, _react.useCallback)(function (e) {
523
467
  var _api$core;
524
- api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref4) {
468
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
525
469
  var _selectionPreservatio, _api$analytics, _resolvedStartPos$nod, _api$blockControls, _api$blockControls2;
526
- var tr = _ref4.tr;
470
+ var tr = _ref2.tr;
527
471
  var startPos = getPos();
528
472
  if (startPos === undefined) {
529
473
  return tr;
@@ -540,7 +484,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
540
484
  nodeType: ((_resolvedStartPos$nod = resolvedStartPos.nodeAfter) === null || _resolvedStartPos$nod === void 0 ? void 0 : _resolvedStartPos$nod.type.name) || ''
541
485
  }
542
486
  })(tr);
543
- expandAndUpdateSelection({
487
+ (0, _expandAndUpdateSelection.expandAndUpdateSelection)({
544
488
  tr: tr,
545
489
  selection: selection,
546
490
  startPos: startPos,
@@ -572,9 +516,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
572
516
  if (!isMultiSelect) {
573
517
  setDragHandleSelected(!dragHandleSelected);
574
518
  }
575
- api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref5) {
519
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref3) {
576
520
  var _api$blockControls$sh, _api$analytics2;
577
- var tr = _ref5.tr;
521
+ var tr = _ref3.tr;
578
522
  var startPos = getPos();
579
523
  if (startPos === undefined) {
580
524
  return tr;
@@ -585,8 +529,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
585
529
  tr = (0, _getSelection.selectNode)(tr, startPos, nodeType, api);
586
530
  } else if (isTopLevelNodeValue && $anchor.depth <= _consts2.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH && e.shiftKey && (0, _platformFeatureFlags.fg)('platform_editor_elements_dnd_shift_click_select')) {
587
531
  var _api$blockControls3;
588
- var alignAnchorHeadToSel = (0, _selection2.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
589
- var selectionWithExpandedHead = (0, _selection2.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
532
+ var alignAnchorHeadToSel = (0, _selection.alignAnchorHeadInDirectionOfPos)(tr.selection, startPos);
533
+ var selectionWithExpandedHead = (0, _selection.expandSelectionHeadToNodeAtPos)(alignAnchorHeadToSel, startPos);
590
534
  tr.setSelection(selectionWithExpandedHead);
591
535
  api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.setMultiSelectPositions()({
592
536
  tr: tr
@@ -614,8 +558,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
614
558
  if (!e.repeat && e.key === ' ') {
615
559
  var _api$core3;
616
560
  var startPos = getPos();
617
- api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref6) {
618
- var tr = _ref6.tr;
561
+ api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref4) {
562
+ var tr = _ref4.tr;
619
563
  if (startPos === undefined) {
620
564
  return tr;
621
565
  }
@@ -649,14 +593,14 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
649
593
  e.preventDefault();
650
594
  e.stopPropagation();
651
595
  var startPos = getPos();
652
- api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref7) {
596
+ api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(function (_ref5) {
653
597
  var _selectionPreservatio2, _api$blockControls4, _api$blockControls5, _api$userIntent;
654
- var tr = _ref7.tr;
598
+ var tr = _ref5.tr;
655
599
  if (startPos === undefined) {
656
600
  return tr;
657
601
  }
658
602
  var selection = ((_selectionPreservatio2 = _pluginKey.selectionPreservationPluginKey.getState(view.state)) === null || _selectionPreservatio2 === void 0 ? void 0 : _selectionPreservatio2.preservedSelection) || tr.selection;
659
- expandAndUpdateSelection({
603
+ (0, _expandAndUpdateSelection.expandAndUpdateSelection)({
660
604
  tr: tr,
661
605
  selection: selection,
662
606
  startPos: startPos,
@@ -707,13 +651,13 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
707
651
  start: start
708
652
  };
709
653
  },
710
- onGenerateDragPreview: function onGenerateDragPreview(_ref8) {
654
+ onGenerateDragPreview: function onGenerateDragPreview(_ref6) {
711
655
  var _api$blockControls$sh2;
712
- var nativeSetDragImage = _ref8.nativeSetDragImage;
656
+ var nativeSetDragImage = _ref6.nativeSetDragImage;
713
657
  if (isMultiSelect) {
714
658
  var _api$core6;
715
- api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref9) {
716
- var tr = _ref9.tr;
659
+ api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(function (_ref7) {
660
+ var tr = _ref7.tr;
717
661
  var handlePos = getPos();
718
662
  if (typeof handlePos !== 'number') {
719
663
  return tr;
@@ -791,8 +735,8 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
791
735
  };
792
736
  }
793
737
  },
794
- render: function render(_ref0) {
795
- var container = _ref0.container;
738
+ render: function render(_ref8) {
739
+ var container = _ref8.container;
796
740
  var dom = view.dom.querySelector("[".concat((0, _domAttrName.getAnchorAttrName)(), "=\"").concat(anchorName, "\"]"));
797
741
  if (!dom) {
798
742
  return;
@@ -828,9 +772,9 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
828
772
  if (start === undefined) {
829
773
  return;
830
774
  }
831
- api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref1) {
775
+ api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref9) {
832
776
  var _api$blockControls$sh3, _api$blockControls7, _api$analytics3;
833
- var tr = _ref1.tr;
777
+ var tr = _ref9.tr;
834
778
  var nodeTypes, hasSelectedMultipleNodes;
835
779
  var resolvedMovingNode = tr.doc.resolve(start);
836
780
  var maybeNode = resolvedMovingNode.nodeAfter;
@@ -1150,7 +1094,7 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1150
1094
  onDrop: handleOnDrop,
1151
1095
  disabled: dragHandleDisabled,
1152
1096
  "data-editor-block-ctrl-drag-handle": true,
1153
- "data-blocks-drag-handle": (0, _expValEqualsNoExposure.expValEqualsNoExposure)('confluence_remix_icon_right_side', 'isEnabled', true) || undefined,
1097
+ "data-blocks-drag-handle": (0, _platformFeatureFlags.fg)('confluence_remix_button_right_side_block_fg') || undefined,
1154
1098
  "data-testid": "block-ctrl-drag-handle",
1155
1099
  "aria-label": dragHandleAriaLabel,
1156
1100
  onBlur: (0, _experiments.editorExperiment)('platform_editor_block_menu', true) ? function () {
@@ -1235,25 +1179,30 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref3) {
1235
1179
  var render = isTooltip ? buttonWithTooltip() : renderButton();
1236
1180
  return (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? stickyRender : render;
1237
1181
  };
1238
- var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragHandleWithVisibility(_ref10) {
1239
- var view = _ref10.view,
1240
- api = _ref10.api,
1241
- formatMessage = _ref10.formatMessage,
1242
- getPos = _ref10.getPos,
1243
- anchorName = _ref10.anchorName,
1244
- nodeType = _ref10.nodeType,
1245
- handleOptions = _ref10.handleOptions,
1246
- isTopLevelNode = _ref10.isTopLevelNode,
1247
- anchorRectCache = _ref10.anchorRectCache;
1182
+ var DragHandleWithVisibility = exports.DragHandleWithVisibility = function DragHandleWithVisibility(_ref0) {
1183
+ var view = _ref0.view,
1184
+ api = _ref0.api,
1185
+ formatMessage = _ref0.formatMessage,
1186
+ getPos = _ref0.getPos,
1187
+ anchorName = _ref0.anchorName,
1188
+ nodeType = _ref0.nodeType,
1189
+ handleOptions = _ref0.handleOptions,
1190
+ isTopLevelNode = _ref0.isTopLevelNode,
1191
+ anchorRectCache = _ref0.anchorRectCache;
1248
1192
  var rightSideControlsEnabled = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls'], function (states) {
1249
1193
  var _states$blockControls2, _states$blockControls3;
1250
1194
  return {
1251
1195
  rightSideControlsEnabled: (_states$blockControls2 = (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.rightSideControlsEnabled) !== null && _states$blockControls2 !== void 0 ? _states$blockControls2 : false
1252
1196
  };
1253
1197
  }).rightSideControlsEnabled;
1198
+ // Layout column drag handles sit at the top-centre of each column, not on a left/right edge.
1199
+ // Don't restrict by hoverSide for layout columns — the drag handle should always be visible
1200
+ // when hovering anywhere over the column, regardless of which side of the layoutSection the
1201
+ // column is on. (The right-side remix button is a separate node decoration and is unaffected.)
1202
+ var isLayoutColumn = nodeType === 'layoutColumn';
1254
1203
  return (0, _react2.jsx)(_visibilityContainer.VisibilityContainer, {
1255
1204
  api: api,
1256
- controlSide: rightSideControlsEnabled ? 'left' : undefined
1205
+ controlSide: rightSideControlsEnabled && !isLayoutColumn ? 'left' : undefined
1257
1206
  }, (0, _react2.jsx)(DragHandle, {
1258
1207
  view: view,
1259
1208
  api: api,
@@ -74,7 +74,7 @@ var VisibilityContainer = exports.VisibilityContainer = function VisibilityConta
74
74
  userIntent = _useSharedPluginState.userIntent,
75
75
  rightSideControlsEnabled = _useSharedPluginState.rightSideControlsEnabled;
76
76
  var isViewMode = editorViewMode === 'view';
77
- // rightSideControlsEnabled is the single source of truth (confluence_remix_icon_right_side from preset)
77
+ // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
78
78
  var shouldRestrictBySide = rightSideControlsEnabled && controlSide !== undefined && !isViewMode;
79
79
  // Only restrict by side when hoverSide is known (after mousemove). When undefined, show both
80
80
  // controls so drag handle is visible on load and for keyboard-only users.
@@ -16,6 +16,7 @@ import { createPlugin, key } from './pm-plugins/main';
16
16
  import { startPreservingSelection, stopPreservingSelection } from './pm-plugins/selection-preservation/editor-commands';
17
17
  import { selectionPreservationPluginKey } from './pm-plugins/selection-preservation/plugin-key';
18
18
  import { createSelectionPreservationPlugin } from './pm-plugins/selection-preservation/pm-plugin';
19
+ import { expandAndUpdateSelection } from './pm-plugins/utils/expand-and-update-selection';
19
20
  import { selectNode } from './pm-plugins/utils/getSelection';
20
21
  import { GlobalStylesWrapper } from './ui/global-styles';
21
22
  export const blockControlsPlugin = ({
@@ -70,6 +71,24 @@ export const blockControlsPlugin = ({
70
71
  return pmPlugins;
71
72
  },
72
73
  commands: {
74
+ expandAndUpdateSelection: ({
75
+ startPos,
76
+ selection,
77
+ isShiftPressed,
78
+ nodeType
79
+ }) => ({
80
+ tr
81
+ }) => {
82
+ expandAndUpdateSelection({
83
+ tr,
84
+ selection,
85
+ startPos,
86
+ isShiftPressed,
87
+ nodeType,
88
+ api: api
89
+ });
90
+ return tr;
91
+ },
73
92
  moveNode: moveNode(api),
74
93
  moveToLayout: moveToLayout(api),
75
94
  showDragHandleAt: (pos, anchorName, nodeType, handleOptions, rootPos, rootAnchorName, rootNodeType) => ({
@@ -320,7 +339,7 @@ export const blockControlsPlugin = ({
320
339
  if (editorExperiment('platform_editor_controls', 'variant1')) {
321
340
  var _interactionTrackingP2, _interactionTrackingP3, _interactionTrackingP4;
322
341
  sharedState.isMouseOut = (_interactionTrackingP2 = (_interactionTrackingP3 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP3 === void 0 ? void 0 : _interactionTrackingP3.isMouseOut) !== null && _interactionTrackingP2 !== void 0 ? _interactionTrackingP2 : false;
323
- // rightSideControlsEnabled is the single source of truth (confluence_remix_icon_right_side from preset)
342
+ // rightSideControlsEnabled is the single source of truth (confluence_remix_button_right_side_block_fg from preset)
324
343
  sharedState.rightSideControlsEnabled = rightSideControlsEnabled;
325
344
  sharedState.hoverSide = rightSideControlsEnabled ? (_interactionTrackingP4 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP4 === void 0 ? void 0 : _interactionTrackingP4.hoverSide : undefined;
326
345
  }