@atlaskit/editor-plugin-block-controls 17.4.1 → 17.4.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/blockControlsPlugin.js +17 -20
  3. package/dist/cjs/pm-plugins/interaction-tracking/handle-mouse-move.js +5 -2
  4. package/dist/cjs/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  5. package/dist/cjs/pm-plugins/main.js +21 -13
  6. package/dist/cjs/pm-plugins/utils/surface-node-positions.js +5 -2
  7. package/dist/cjs/ui/block-controls-left-surface.js +1 -0
  8. package/dist/cjs/ui/block-controls-left-surfaces.js +6 -1
  9. package/dist/cjs/ui/block-controls-right-surface.js +1 -0
  10. package/dist/cjs/ui/block-controls-right-surfaces.js +6 -1
  11. package/dist/cjs/ui/utils/has-surface-controls.js +15 -0
  12. package/dist/es2019/blockControlsPlugin.js +20 -23
  13. package/dist/es2019/pm-plugins/interaction-tracking/handle-mouse-move.js +3 -2
  14. package/dist/es2019/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  15. package/dist/es2019/pm-plugins/main.js +22 -12
  16. package/dist/es2019/pm-plugins/utils/surface-node-positions.js +5 -2
  17. package/dist/es2019/ui/block-controls-left-surface.js +1 -0
  18. package/dist/es2019/ui/block-controls-left-surfaces.js +6 -1
  19. package/dist/es2019/ui/block-controls-right-surface.js +1 -0
  20. package/dist/es2019/ui/block-controls-right-surfaces.js +6 -1
  21. package/dist/es2019/ui/utils/has-surface-controls.js +5 -0
  22. package/dist/esm/blockControlsPlugin.js +17 -20
  23. package/dist/esm/pm-plugins/interaction-tracking/handle-mouse-move.js +5 -2
  24. package/dist/esm/pm-plugins/interaction-tracking/pm-plugin.js +1 -1
  25. package/dist/esm/pm-plugins/main.js +21 -13
  26. package/dist/esm/pm-plugins/utils/surface-node-positions.js +5 -2
  27. package/dist/esm/ui/block-controls-left-surface.js +1 -0
  28. package/dist/esm/ui/block-controls-left-surfaces.js +6 -1
  29. package/dist/esm/ui/block-controls-right-surface.js +1 -0
  30. package/dist/esm/ui/block-controls-right-surfaces.js +6 -1
  31. package/dist/esm/ui/utils/has-surface-controls.js +9 -0
  32. package/dist/types/pm-plugins/main.d.ts +1 -1
  33. package/dist/types/ui/utils/has-surface-controls.d.ts +6 -0
  34. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 17.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`3531759a623d1`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3531759a623d1) -
8
+ Move the registry-backed right block-control surface and released Remix button under
9
+ `platform_editor_block_control_migration`, while keeping AI Suggestions behind
10
+ `platform_editor_block_control_right_surface`. Avoid legacy widget work and empty-surface
11
+ measurement in the migrated path, and preserve registry controls across hover transitions.
12
+
3
13
  ## 17.4.1
4
14
 
5
15
  ### Patch Changes
@@ -47,9 +47,8 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
47
47
  var quickInsertButtonEnabled = (_config$quickInsertBu = config === null || config === void 0 ? void 0 : config.quickInsertButtonEnabled) !== null && _config$quickInsertBu !== void 0 ? _config$quickInsertBu : true;
48
48
  var registryBlockControlsEnabled = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration');
49
49
  var legacyBlockControlsEnabled = !registryBlockControlsEnabled;
50
- var rightSurfaceEnabled = registryBlockControlsEnabled && (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_right_surface');
51
50
  if (registryBlockControlsEnabled) {
52
- var _api$uiControlRegistr;
51
+ var _api$uiControlRegistr, _api$uiControlRegistr2;
53
52
  api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 || _api$uiControlRegistr.actions.register([_surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, _objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_LEFT_SECTION), {}, {
54
53
  parents: [_objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE), {}, {
55
54
  rank: 100
@@ -61,21 +60,19 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
61
60
  })].concat((0, _toConsumableArray2.default)((0, _blockControlsSurfaceDragHandleRegistration.getBlockControlsSurfaceDragHandleComponents)({
62
61
  api: api
63
62
  }))));
64
- if (rightSurfaceEnabled) {
65
- var _api$uiControlRegistr2;
66
- // The right surface host stays generic: it only registers the toolbar/section/group
67
- // hierarchy. Individual features contribute their own buttons into
68
- // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
69
- api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 || _api$uiControlRegistr2.actions.register([_surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, _objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SECTION), {}, {
70
- parents: [_objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE), {}, {
71
- rank: 100
72
- })]
73
- }), _objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_GROUP), {}, {
74
- parents: [_objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SECTION), {}, {
75
- rank: 100
76
- })]
77
- })]);
78
- }
63
+
64
+ // The right surface host stays generic: it only registers the toolbar/section/group
65
+ // hierarchy. Individual features contribute their own buttons into
66
+ // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
67
+ api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 || _api$uiControlRegistr2.actions.register([_surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, _objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SECTION), {}, {
68
+ parents: [_objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE), {}, {
69
+ rank: 100
70
+ })]
71
+ }), _objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_GROUP), {}, {
72
+ parents: [_objectSpread(_objectSpread({}, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SECTION), {}, {
73
+ rank: 100
74
+ })]
75
+ })]);
79
76
  }
80
77
  return {
81
78
  name: 'blockControls',
@@ -145,7 +142,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
145
142
  plugin: function plugin(_ref2) {
146
143
  var getIntl = _ref2.getIntl,
147
144
  nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
148
- return (0, _main.createPlugin)(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled);
145
+ return (0, _main.createPlugin)(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled);
149
146
  }
150
147
  }];
151
148
  if ((0, _editorExperiment.editorExperiment)('platform_editor_controls', 'variant1')) {
@@ -473,10 +470,10 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
473
470
  }, /*#__PURE__*/_react.default.createElement(_blockControlsLeftSurfaces.BlockControlsLeftSurfaces, {
474
471
  api: api,
475
472
  editorView: editorView
476
- }), rightSurfaceEnabled ? /*#__PURE__*/_react.default.createElement(_blockControlsRightSurfaces.BlockControlsRightSurfaces, {
473
+ }), /*#__PURE__*/_react.default.createElement(_blockControlsRightSurfaces.BlockControlsRightSurfaces, {
477
474
  api: api,
478
475
  editorView: editorView
479
- }) : null) : null);
476
+ })) : null);
480
477
  }
481
478
  };
482
479
  };
@@ -30,7 +30,10 @@ var clearPendingHoverSide = function clearPendingHoverSide(view) {
30
30
  cancelScheduledProcessForView(view);
31
31
  };
32
32
  var BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
33
- var RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
33
+ var LEGACY_RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
34
+ var getRightControlSelector = function getRightControlSelector() {
35
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? "[data-editor-block-controls-side=\"right\"], ".concat(LEGACY_RIGHT_EDGE_SELECTOR) : LEGACY_RIGHT_EDGE_SELECTOR;
36
+ };
34
37
  var LEGACY_LEFT_CONTROL_SELECTOR = '[data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
35
38
  var getLeftControlSelector = function getLeftControlSelector() {
36
39
  return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? "[data-editor-block-ctrl-drag-handle], ".concat(LEGACY_LEFT_CONTROL_SELECTOR) : LEGACY_LEFT_CONTROL_SELECTOR;
@@ -122,7 +125,7 @@ var processHoverSide = function processHoverSide(view, api) {
122
125
 
123
126
  // When hovering over block controls directly, infer side from which control we're over.
124
127
  // This is more reliable than bounds when controls are in portals outside the editor DOM.
125
- var rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(RIGHT_EDGE_SELECTOR);
128
+ var rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(getRightControlSelector());
126
129
  if (rightEdgeElement) {
127
130
  if (state !== null && state !== void 0 && state.isMouseOut && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('cc_maui_remix_button_hover_corridor', 'isEnabled', true)) {
128
131
  (0, _commands.mouseEnter)(view, 'right');
@@ -21,7 +21,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
21
21
  /** Elements that extend the editor hover area (block controls, right-edge button, etc.) */
22
22
  var LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
23
23
  var getBlockControlsHoverAreaSelector = function getBlockControlsHoverAreaSelector() {
24
- return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? "[data-editor-block-ctrl-drag-handle], ".concat(LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR) : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
24
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? "[data-editor-block-controls-surface], [data-editor-block-ctrl-drag-handle], ".concat(LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR) : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
25
25
  };
26
26
  var MOUSE_LEAVE_DEBOUNCE_MS = 200;
27
27
 
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.key = exports.getDecorations = exports.getBlockControlsMeta = exports.createPlugin = exports.apply = void 0;
8
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
9
  var _rafSchd = _interopRequireDefault(require("raf-schd"));
11
10
  var _browserApis = require("@atlaskit/browser-apis");
@@ -444,16 +443,18 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
444
443
  // In view mode with right-side controls, remove any lingering drag handle decorations
445
444
  // (they may carry over from edit mode). Only remove drag handles specifically, not
446
445
  // the remix button decorations (those are managed separately via showInViewMode).
447
- if (isViewMode && rightSideControlsEnabled) {
446
+ if (flags.legacyDragHandleEnabled && isViewMode && rightSideControlsEnabled) {
448
447
  var allHandleDecs = (0, _decorationsDragHandle.findHandleDec)(decorations, 0, newState.doc.content.size);
449
448
  if (allHandleDecs.length > 0) {
450
449
  decorations = decorations.remove(allHandleDecs);
451
450
  }
452
451
  }
453
452
  if (shouldRemoveHandle) {
454
- var _activeNode5, _activeNode6;
455
- var oldHandle = (0, _decorationsDragHandle.findHandleDec)(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
456
- decorations = decorations.remove(oldHandle);
453
+ if (flags.legacyDragHandleEnabled) {
454
+ var _activeNode5, _activeNode6;
455
+ var oldHandle = (0, _decorationsDragHandle.findHandleDec)(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
456
+ decorations = decorations.remove(oldHandle);
457
+ }
457
458
  // When removing the handle, also remove the anchor-marker node decorations
458
459
  // (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
459
460
  // don't linger on nodes that are no longer active.
@@ -461,7 +462,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
461
462
  // after a doc change (e.g. pressing Enter splits a node), DecorationSet.map() can shift the
462
463
  // decoration to a different position, so a point-range search would miss it and leave a stale
463
464
  // attribute on the wrong DOM node.
464
- if ((0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
465
+ if ((flags.legacyDragHandleEnabled || nodeDecorationRegistry.length > 0) && (0, _expValEquals.expValEquals)('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
465
466
  var oldActiveNodeDec = (0, _decorationsDragHandle.findActiveDragHandleNodeDec)(decorations, 0, newState.doc.content.size);
466
467
  decorations = decorations.remove(oldActiveNodeDec);
467
468
  var oldActiveQuickInsertDec = (0, _decorationsQuickInsertButton.findActiveQuickInsertNodeDec)(decorations, 0, newState.doc.content.size);
@@ -592,7 +593,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
592
593
  }
593
594
  }
594
595
  }
595
- if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
596
+ if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined && (quickInsertButtonEnabled || nodeDecorationRegistry.length > 0) &&
596
597
  // platform_editor_controls note: enables quick insert
597
598
  flags.toolbarFlagsEnabled && (!rightSideControlsEnabled || !isViewMode)) {
598
599
  var _latestActiveNode1;
@@ -822,7 +823,7 @@ var _apply = exports.apply = function apply(api, formatMessage, tr, currentState
822
823
  // remove isEmptyDoc check and let decorations render and determine their own visibility
823
824
  // In view mode with right-side controls we render node decorations (right-edge button), not the
824
825
  // handle - so findHandleDec is always empty. Don't clear activeNode in that case.
825
- var hasHandleOrViewModeControls = (0, _decorationsDragHandle.findHandleDec)(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled || !flags.legacyDragHandleEnabled;
826
+ var hasHandleOrViewModeControls = !flags.legacyDragHandleEnabled || isViewMode && rightSideControlsEnabled || (0, _decorationsDragHandle.findHandleDec)(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0;
826
827
  // Keep the registry surface mounted while its Block Menu owns focus.
827
828
  var keepActiveNodeForOpenBlockMenu = !flags.legacyDragHandleEnabled && isMenuOpen && (0, _editorExperiment.editorExperiment)('platform_editor_block_menu', true);
828
829
  newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred && !keepActiveNodeForOpenBlockMenu || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
@@ -890,7 +891,6 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
890
891
  var rightSideControlsEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
891
892
  var quickInsertButtonEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
892
893
  var legacyDragHandleEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true;
893
- var rightSurfaceEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
894
894
  var _getIntl = getIntl(),
895
895
  formatMessage = _getIntl.formatMessage;
896
896
  var isAdvancedLayoutEnabled = (0, _editorExperiment.editorExperiment)('advanced_layouts', true, {
@@ -905,7 +905,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
905
905
  surfaceNodePositionsEnabled: surfaceNodePositionsEnabled,
906
906
  toolbarFlagsEnabled: toolbarFlagsEnabled
907
907
  };
908
- var resolvedSurfaces = surfaceNodePositionsEnabled ? [(0, _surfaceRenderer.resolveSurface)((_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(_surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE)].concat((0, _toConsumableArray2.default)(rightSurfaceEnabled ? [(0, _surfaceRenderer.resolveSurface)((_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(_surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE)] : [])) : [];
908
+ var resolvedSurfaces = surfaceNodePositionsEnabled ? [(0, _surfaceRenderer.resolveSurface)((_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(_surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE), (0, _surfaceRenderer.resolveSurface)((_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(_surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE)] : [];
909
909
  var anchorRectCache;
910
910
  if (!(0, _anchorUtils.isAnchorSupported)()) {
911
911
  anchorRectCache = new _anchorUtils.AnchorRectCache();
@@ -942,7 +942,7 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
942
942
  var decorationSet = (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
943
943
  // In view mode with right-side controls, remove any lingering drag-handle decorations
944
944
  // (created in edit mode) that may not have been cleaned up on mode switch.
945
- if (decorationSet && rightSideControlsEnabled && (api === null || api === void 0 || (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 || (_api$editorViewMode3 = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3 === void 0 ? void 0 : _api$editorViewMode3.mode) === 'view') {
945
+ if (decorationSet && legacyDragHandleEnabled && rightSideControlsEnabled && (api === null || api === void 0 || (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 || (_api$editorViewMode3 = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3 === void 0 ? void 0 : _api$editorViewMode3.mode) === 'view') {
946
946
  var handleDecs = (0, _decorationsDragHandle.findHandleDec)(decorationSet, 0, state.doc.content.size);
947
947
  if (handleDecs.length > 0) {
948
948
  decorationSet = decorationSet.remove(handleDecs);
@@ -1184,10 +1184,15 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
1184
1184
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDragging)) {
1185
1185
  var isResizerResizing = !!dom.querySelector('.is-resizing');
1186
1186
  var transaction = editorView.state.tr;
1187
+ var shouldDispatch = false;
1187
1188
  if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.isResizerResizing) !== isResizerResizing) {
1188
1189
  transaction.setMeta('is-resizer-resizing', isResizerResizing);
1190
+ shouldDispatch = true;
1189
1191
  }
1190
- if (!isResizerResizing) {
1192
+
1193
+ // Registry surfaces have their own ResizeObservers and absolute placement.
1194
+ // Width metadata only drives legacy widget recreation.
1195
+ if (legacyDragHandleEnabled && !isResizerResizing) {
1191
1196
  var _editorContentArea = entries[0].target;
1192
1197
  // Ignored via go/ees005
1193
1198
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -1199,8 +1204,11 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
1199
1204
  editorWidthLeft: editorWidthLeft,
1200
1205
  editorWidthRight: editorWidthRight
1201
1206
  }));
1207
+ shouldDispatch = true;
1208
+ }
1209
+ if (shouldDispatch) {
1210
+ editorView.dispatch(transaction);
1202
1211
  }
1203
- editorView.dispatch(transaction);
1204
1212
  }
1205
1213
  }));
1206
1214
  var shouldObserve = (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? !(0, _anchorUtils.isAnchorSupported)() : true;
@@ -10,6 +10,7 @@ var _blockControlUiContext = require("@atlaskit/editor-common/block-controls/blo
10
10
  var _createSurfaceContext = require("@atlaskit/editor-ui-control-model/create-surface-context");
11
11
  var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
12
12
  var _blockControlsSurfaceContext = require("../../ui/block-controls-surface-context");
13
+ var _hasSurfaceControls = require("../../ui/utils/has-surface-controls");
13
14
  var createSurfaceContextAtPosition = function createSurfaceContextAtPosition(state, position, activeNode) {
14
15
  var blockControlsContext = (0, _blockControlsSurfaceContext.createBlockControlsSurfaceContextForPosition)(state, position, activeNode);
15
16
  return blockControlsContext ? (0, _createSurfaceContext.createSurfaceContext)(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT, blockControlsContext) : undefined;
@@ -33,8 +34,9 @@ var getSurfaceNodePositions = exports.getSurfaceNodePositions = function getSurf
33
34
  var to = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : state.doc.content.size;
34
35
  var surfaces = resolvedSurfaces.flatMap(function (_ref2) {
35
36
  var childrenMap = _ref2.childrenMap,
37
+ components = _ref2.components,
36
38
  root = _ref2.root;
37
- return root ? [{
39
+ return root && (0, _hasSurfaceControls.hasSurfaceControls)(components) ? [{
38
40
  childrenMap: childrenMap,
39
41
  root: root
40
42
  }] : [];
@@ -74,8 +76,9 @@ var updateSurfaceNodePositions = exports.updateSurfaceNodePositions = function u
74
76
  }
75
77
  var surfaces = resolvedSurfaces.flatMap(function (_ref4) {
76
78
  var childrenMap = _ref4.childrenMap,
79
+ components = _ref4.components,
77
80
  root = _ref4.root;
78
- return root ? [{
81
+ return root && (0, _hasSurfaceControls.hasSurfaceControls)(components) ? [{
79
82
  childrenMap: childrenMap,
80
83
  root: root
81
84
  }] : [];
@@ -43,6 +43,7 @@ var BlockControlsLeftSurface = exports.BlockControlsLeftSurface = function Block
43
43
  var isSticky = placement.height !== undefined;
44
44
  return /*#__PURE__*/_react.default.createElement("div", {
45
45
  "data-editor-block-controls-surface": true,
46
+ "data-editor-block-controls-side": "left",
46
47
  "data-testid": source === 'stored' ? 'block-controls-left-surface-stored' : source === 'active' ? 'block-controls-left-surface-active' : 'block-controls-left-surface'
47
48
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
48
49
  ,
@@ -17,12 +17,14 @@ var _blockControlUiContext = require("@atlaskit/editor-common/block-controls/blo
17
17
  var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys");
18
18
  var _hooks = require("@atlaskit/editor-common/hooks");
19
19
  var _createSurfaceContext = require("@atlaskit/editor-ui-control-model/create-surface-context");
20
+ var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
20
21
  var _decorationsCommon = require("../pm-plugins/decorations-common");
21
22
  var _blockControlsLeftSurface = require("./block-controls-left-surface");
22
23
  var _blockControlsSurfaceContext = require("./block-controls-surface-context");
23
24
  var _blockControlsSurfaceTargets = require("./block-controls-surface-targets");
24
25
  var _getNodeContentElement = require("./utils/get-node-content-element");
25
26
  var _getSurfacePlacement = require("./utils/get-surface-placement");
27
+ var _hasSurfaceControls = require("./utils/has-surface-controls");
26
28
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
29
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
28
30
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
@@ -55,12 +57,15 @@ var BlockControlsLeftSurfaces = exports.BlockControlsLeftSurfaces = function Blo
55
57
  return [];
56
58
  }
57
59
  var surfaceContext = (0, _createSurfaceContext.createSurfaceContext)(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT, context);
60
+ if (!(0, _hasSurfaceControls.hasSurfaceControls)(components) || !(0, _surfaceRenderer.willSurfaceRender)(components, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
61
+ return [];
62
+ }
58
63
  return [_objectSpread(_objectSpread({}, target), {}, {
59
64
  blockControlsContext: context,
60
65
  surfaceContext: surfaceContext
61
66
  })];
62
67
  });
63
- }, [activeNode, editorView, targets]);
68
+ }, [activeNode, components, editorView, targets]);
64
69
  var _useState = (0, _react.useState)(new Map()),
65
70
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
66
71
  placements = _useState2[0],
@@ -40,6 +40,7 @@ var BlockControlsRightSurface = exports.BlockControlsRightSurface = function Blo
40
40
  var isSticky = placement.height !== undefined;
41
41
  return /*#__PURE__*/_react.default.createElement("div", {
42
42
  "data-editor-block-controls-surface": true,
43
+ "data-editor-block-controls-side": "right",
43
44
  "data-testid": source === 'stored' ? 'block-controls-right-surface-stored' : source === 'active' ? 'block-controls-right-surface-active' : 'block-controls-right-surface'
44
45
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
45
46
  ,
@@ -17,12 +17,14 @@ var _blockControlUiContext = require("@atlaskit/editor-common/block-controls/blo
17
17
  var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys");
18
18
  var _hooks = require("@atlaskit/editor-common/hooks");
19
19
  var _createSurfaceContext = require("@atlaskit/editor-ui-control-model/create-surface-context");
20
+ var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
20
21
  var _decorationsCommon = require("../pm-plugins/decorations-common");
21
22
  var _blockControlsRightSurface = require("./block-controls-right-surface");
22
23
  var _blockControlsSurfaceContext = require("./block-controls-surface-context");
23
24
  var _blockControlsSurfaceTargets = require("./block-controls-surface-targets");
24
25
  var _getNodeContentElement = require("./utils/get-node-content-element");
25
26
  var _getSurfacePlacement = require("./utils/get-surface-placement");
27
+ var _hasSurfaceControls = require("./utils/has-surface-controls");
26
28
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
29
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
28
30
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
@@ -60,12 +62,15 @@ var BlockControlsRightSurfaces = exports.BlockControlsRightSurfaces = function B
60
62
  return [];
61
63
  }
62
64
  var surfaceContext = (0, _createSurfaceContext.createSurfaceContext)(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT, context);
65
+ if (!(0, _hasSurfaceControls.hasSurfaceControls)(components) || !(0, _surfaceRenderer.willSurfaceRender)(components, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
66
+ return [];
67
+ }
63
68
  return [_objectSpread(_objectSpread({}, target), {}, {
64
69
  blockControlsContext: context,
65
70
  surfaceContext: surfaceContext
66
71
  })];
67
72
  });
68
- }, [activeNode, editorView, targets]);
73
+ }, [activeNode, components, editorView, targets]);
69
74
  var _useState = (0, _react.useState)(new Map()),
70
75
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
71
76
  placements = _useState2[0],
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.hasSurfaceControls = void 0;
7
+ /**
8
+ * Structural toolbar nodes do not render a control by themselves. Treat a surface as populated
9
+ * only once a contributor has registered an interactive descendant.
10
+ */
11
+ var hasSurfaceControls = exports.hasSurfaceControls = function hasSurfaceControls(components) {
12
+ return components.some(function (component) {
13
+ return Boolean(component.component) || component.type === 'button' || component.type === 'menu' || component.type === 'menu-item' || component.type === 'nested-menu';
14
+ });
15
+ };
@@ -37,9 +37,8 @@ export const blockControlsPlugin = ({
37
37
  const quickInsertButtonEnabled = (_config$quickInsertBu = config === null || config === void 0 ? void 0 : config.quickInsertButtonEnabled) !== null && _config$quickInsertBu !== void 0 ? _config$quickInsertBu : true;
38
38
  const registryBlockControlsEnabled = isExperimentEnabled('platform_editor_block_control_migration');
39
39
  const legacyBlockControlsEnabled = !registryBlockControlsEnabled;
40
- const rightSurfaceEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_block_control_right_surface');
41
40
  if (registryBlockControlsEnabled) {
42
- var _api$uiControlRegistr;
41
+ var _api$uiControlRegistr, _api$uiControlRegistr2;
43
42
  api === null || api === void 0 ? void 0 : (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 ? void 0 : _api$uiControlRegistr.actions.register([BLOCK_CONTROLS_LEFT_SURFACE, {
44
43
  ...BLOCK_CONTROLS_LEFT_SECTION,
45
44
  parents: [{
@@ -55,25 +54,23 @@ export const blockControlsPlugin = ({
55
54
  }, ...getBlockControlsSurfaceDragHandleComponents({
56
55
  api
57
56
  })]);
58
- if (rightSurfaceEnabled) {
59
- var _api$uiControlRegistr2;
60
- // The right surface host stays generic: it only registers the toolbar/section/group
61
- // hierarchy. Individual features contribute their own buttons into
62
- // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
63
- api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.register([BLOCK_CONTROLS_RIGHT_SURFACE, {
57
+
58
+ // The right surface host stays generic: it only registers the toolbar/section/group
59
+ // hierarchy. Individual features contribute their own buttons into
60
+ // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
61
+ api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.register([BLOCK_CONTROLS_RIGHT_SURFACE, {
62
+ ...BLOCK_CONTROLS_RIGHT_SECTION,
63
+ parents: [{
64
+ ...BLOCK_CONTROLS_RIGHT_SURFACE,
65
+ rank: 100
66
+ }]
67
+ }, {
68
+ ...BLOCK_CONTROLS_RIGHT_GROUP,
69
+ parents: [{
64
70
  ...BLOCK_CONTROLS_RIGHT_SECTION,
65
- parents: [{
66
- ...BLOCK_CONTROLS_RIGHT_SURFACE,
67
- rank: 100
68
- }]
69
- }, {
70
- ...BLOCK_CONTROLS_RIGHT_GROUP,
71
- parents: [{
72
- ...BLOCK_CONTROLS_RIGHT_SECTION,
73
- rank: 100
74
- }]
75
- }]);
76
- }
71
+ rank: 100
72
+ }]
73
+ }]);
77
74
  }
78
75
  return {
79
76
  name: 'blockControls',
@@ -143,7 +140,7 @@ export const blockControlsPlugin = ({
143
140
  plugin: ({
144
141
  getIntl,
145
142
  nodeViewPortalProviderAPI
146
- }) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled)
143
+ }) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled)
147
144
  }];
148
145
  if (editorExperiment('platform_editor_controls', 'variant1')) {
149
146
  pmPlugins.push({
@@ -466,10 +463,10 @@ export const blockControlsPlugin = ({
466
463
  }, /*#__PURE__*/React.createElement(BlockControlsLeftSurfaces, {
467
464
  api: api,
468
465
  editorView: editorView
469
- }), rightSurfaceEnabled ? /*#__PURE__*/React.createElement(BlockControlsRightSurfaces, {
466
+ }), /*#__PURE__*/React.createElement(BlockControlsRightSurfaces, {
470
467
  api: api,
471
468
  editorView: editorView
472
- }) : null) : null);
469
+ })) : null);
473
470
  }
474
471
  };
475
472
  };
@@ -22,7 +22,8 @@ const clearPendingHoverSide = view => {
22
22
  cancelScheduledProcessForView(view);
23
23
  };
24
24
  const BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
25
- const RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
25
+ const LEGACY_RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
26
+ const getRightControlSelector = () => isExperimentEnabled('platform_editor_block_control_migration') ? `[data-editor-block-controls-side="right"], ${LEGACY_RIGHT_EDGE_SELECTOR}` : LEGACY_RIGHT_EDGE_SELECTOR;
26
27
  const LEGACY_LEFT_CONTROL_SELECTOR = '[data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
27
28
  const getLeftControlSelector = () => isExperimentEnabled('platform_editor_block_control_migration') ? `[data-editor-block-ctrl-drag-handle], ${LEGACY_LEFT_CONTROL_SELECTOR}` : LEGACY_LEFT_CONTROL_SELECTOR;
28
29
 
@@ -101,7 +102,7 @@ const processHoverSide = (view, api) => {
101
102
 
102
103
  // When hovering over block controls directly, infer side from which control we're over.
103
104
  // This is more reliable than bounds when controls are in portals outside the editor DOM.
104
- const rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(RIGHT_EDGE_SELECTOR);
105
+ const rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(getRightControlSelector());
105
106
  if (rightEdgeElement) {
106
107
  if (state !== null && state !== void 0 && state.isMouseOut && expValEqualsNoExposure('cc_maui_remix_button_hover_corridor', 'isEnabled', true)) {
107
108
  mouseEnter(view, 'right');
@@ -11,7 +11,7 @@ import { handleMouseEnter, handleMouseLeave, handleMouseMove } from './handle-mo
11
11
 
12
12
  /** Elements that extend the editor hover area (block controls, right-edge button, etc.) */
13
13
  const LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
14
- const getBlockControlsHoverAreaSelector = () => isExperimentEnabled('platform_editor_block_control_migration') ? `[data-editor-block-ctrl-drag-handle], ${LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR}` : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
14
+ const getBlockControlsHoverAreaSelector = () => isExperimentEnabled('platform_editor_block_control_migration') ? `[data-editor-block-controls-surface], [data-editor-block-ctrl-drag-handle], ${LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR}` : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
15
15
  const MOUSE_LEAVE_DEBOUNCE_MS = 200;
16
16
 
17
17
  /** ClickAreaBlock overlay that wraps the editor content and covers the right margin. */
@@ -432,16 +432,18 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
432
432
  // In view mode with right-side controls, remove any lingering drag handle decorations
433
433
  // (they may carry over from edit mode). Only remove drag handles specifically, not
434
434
  // the remix button decorations (those are managed separately via showInViewMode).
435
- if (isViewMode && rightSideControlsEnabled) {
435
+ if (flags.legacyDragHandleEnabled && isViewMode && rightSideControlsEnabled) {
436
436
  const allHandleDecs = findHandleDec(decorations, 0, newState.doc.content.size);
437
437
  if (allHandleDecs.length > 0) {
438
438
  decorations = decorations.remove(allHandleDecs);
439
439
  }
440
440
  }
441
441
  if (shouldRemoveHandle) {
442
- var _activeNode5, _activeNode6;
443
- const oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
444
- decorations = decorations.remove(oldHandle);
442
+ if (flags.legacyDragHandleEnabled) {
443
+ var _activeNode5, _activeNode6;
444
+ const oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
445
+ decorations = decorations.remove(oldHandle);
446
+ }
445
447
  // When removing the handle, also remove the anchor-marker node decorations
446
448
  // (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
447
449
  // don't linger on nodes that are no longer active.
@@ -449,7 +451,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
449
451
  // after a doc change (e.g. pressing Enter splits a node), DecorationSet.map() can shift the
450
452
  // decoration to a different position, so a point-range search would miss it and leave a stale
451
453
  // attribute on the wrong DOM node.
452
- if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
454
+ if ((flags.legacyDragHandleEnabled || nodeDecorationRegistry.length > 0) && expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
453
455
  const oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, 0, newState.doc.content.size);
454
456
  decorations = decorations.remove(oldActiveNodeDec);
455
457
  const oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, 0, newState.doc.content.size);
@@ -552,7 +554,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
552
554
  }
553
555
  }
554
556
  }
555
- if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
557
+ if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined && (quickInsertButtonEnabled || nodeDecorationRegistry.length > 0) &&
556
558
  // platform_editor_controls note: enables quick insert
557
559
  flags.toolbarFlagsEnabled && (!rightSideControlsEnabled || !isViewMode)) {
558
560
  var _latestActiveNode1;
@@ -721,7 +723,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
721
723
  // remove isEmptyDoc check and let decorations render and determine their own visibility
722
724
  // In view mode with right-side controls we render node decorations (right-edge button), not the
723
725
  // handle - so findHandleDec is always empty. Don't clear activeNode in that case.
724
- const hasHandleOrViewModeControls = findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled || !flags.legacyDragHandleEnabled;
726
+ const hasHandleOrViewModeControls = !flags.legacyDragHandleEnabled || isViewMode && rightSideControlsEnabled || findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0;
725
727
  // Keep the registry surface mounted while its Block Menu owns focus.
726
728
  const keepActiveNodeForOpenBlockMenu = !flags.legacyDragHandleEnabled && isMenuOpen && editorExperiment('platform_editor_block_menu', true);
727
729
  newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred && !keepActiveNodeForOpenBlockMenu || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
@@ -784,7 +786,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
784
786
  isSelectedViaDragHandle: isSelectedViaDragHandleNew
785
787
  };
786
788
  };
787
- export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, legacyDragHandleEnabled = true, rightSurfaceEnabled = false) => {
789
+ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, legacyDragHandleEnabled = true) => {
788
790
  var _api$uiControlRegistr, _api$uiControlRegistr2, _api$uiControlRegistr3, _api$uiControlRegistr4;
789
791
  const {
790
792
  formatMessage
@@ -801,7 +803,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
801
803
  surfaceNodePositionsEnabled,
802
804
  toolbarFlagsEnabled
803
805
  };
804
- const resolvedSurfaces = surfaceNodePositionsEnabled ? [resolveSurface((_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], BLOCK_CONTROLS_LEFT_SURFACE), ...(rightSurfaceEnabled ? [resolveSurface((_api$uiControlRegistr3 = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], BLOCK_CONTROLS_RIGHT_SURFACE)] : [])] : [];
806
+ const resolvedSurfaces = surfaceNodePositionsEnabled ? [resolveSurface((_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], BLOCK_CONTROLS_LEFT_SURFACE), resolveSurface((_api$uiControlRegistr3 = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], BLOCK_CONTROLS_RIGHT_SURFACE)] : [];
805
807
  let anchorRectCache;
806
808
  if (!isAnchorSupported()) {
807
809
  anchorRectCache = new AnchorRectCache();
@@ -837,7 +839,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
837
839
  let decorationSet = (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
838
840
  // In view mode with right-side controls, remove any lingering drag-handle decorations
839
841
  // (created in edit mode) that may not have been cleaned up on mode switch.
840
- if (decorationSet && rightSideControlsEnabled && (api === null || api === void 0 ? void 0 : (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 ? void 0 : (_api$editorViewMode3$ = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3$ === void 0 ? void 0 : _api$editorViewMode3$.mode) === 'view') {
842
+ if (decorationSet && legacyDragHandleEnabled && rightSideControlsEnabled && (api === null || api === void 0 ? void 0 : (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 ? void 0 : (_api$editorViewMode3$ = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3$ === void 0 ? void 0 : _api$editorViewMode3$.mode) === 'view') {
841
843
  const handleDecs = findHandleDec(decorationSet, 0, state.doc.content.size);
842
844
  if (handleDecs.length > 0) {
843
845
  decorationSet = decorationSet.remove(handleDecs);
@@ -1090,10 +1092,15 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
1090
1092
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDragging)) {
1091
1093
  const isResizerResizing = !!dom.querySelector('.is-resizing');
1092
1094
  const transaction = editorView.state.tr;
1095
+ let shouldDispatch = false;
1093
1096
  if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.isResizerResizing) !== isResizerResizing) {
1094
1097
  transaction.setMeta('is-resizer-resizing', isResizerResizing);
1098
+ shouldDispatch = true;
1095
1099
  }
1096
- if (!isResizerResizing) {
1100
+
1101
+ // Registry surfaces have their own ResizeObservers and absolute placement.
1102
+ // Width metadata only drives legacy widget recreation.
1103
+ if (legacyDragHandleEnabled && !isResizerResizing) {
1097
1104
  const editorContentArea = entries[0].target;
1098
1105
  // Ignored via go/ees005
1099
1106
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -1106,8 +1113,11 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
1106
1113
  editorWidthLeft,
1107
1114
  editorWidthRight
1108
1115
  });
1116
+ shouldDispatch = true;
1117
+ }
1118
+ if (shouldDispatch) {
1119
+ editorView.dispatch(transaction);
1109
1120
  }
1110
- editorView.dispatch(transaction);
1111
1121
  }
1112
1122
  }));
1113
1123
  const shouldObserve = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? !isAnchorSupported() : true;
@@ -2,6 +2,7 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
2
2
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
3
3
  import { willComponentRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
4
4
  import { createBlockControlsSurfaceContextForPosition } from '../../ui/block-controls-surface-context';
5
+ import { hasSurfaceControls } from '../../ui/utils/has-surface-controls';
5
6
  const createSurfaceContextAtPosition = (state, position, activeNode) => {
6
7
  const blockControlsContext = createBlockControlsSurfaceContextForPosition(state, position, activeNode);
7
8
  return blockControlsContext ? createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, blockControlsContext) : undefined;
@@ -22,8 +23,9 @@ const willAnySurfaceRenderAt = (surfaces, state, position, activeNode) => {
22
23
  export const getSurfaceNodePositions = (state, resolvedSurfaces, activeNode, from = 0, to = state.doc.content.size) => {
23
24
  const surfaces = resolvedSurfaces.flatMap(({
24
25
  childrenMap,
26
+ components,
25
27
  root
26
- }) => root ? [{
28
+ }) => root && hasSurfaceControls(components) ? [{
27
29
  childrenMap,
28
30
  root
29
31
  }] : []);
@@ -61,8 +63,9 @@ export const updateSurfaceNodePositions = ({
61
63
  }
62
64
  const surfaces = resolvedSurfaces.flatMap(({
63
65
  childrenMap,
66
+ components,
64
67
  root
65
- }) => root ? [{
68
+ }) => root && hasSurfaceControls(components) ? [{
66
69
  childrenMap,
67
70
  root
68
71
  }] : []);
@@ -38,6 +38,7 @@ export const BlockControlsLeftSurface = ({
38
38
  const isSticky = placement.height !== undefined;
39
39
  return /*#__PURE__*/React.createElement("div", {
40
40
  "data-editor-block-controls-surface": true,
41
+ "data-editor-block-controls-side": "left",
41
42
  "data-testid": source === 'stored' ? 'block-controls-left-surface-stored' : source === 'active' ? 'block-controls-left-surface-active' : 'block-controls-left-surface'
42
43
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
43
44
  ,
@@ -7,12 +7,14 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
7
7
  import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
8
8
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
9
9
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
10
+ import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
10
11
  import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
11
12
  import { BlockControlsLeftSurface } from './block-controls-left-surface';
12
13
  import { createBlockControlsSurfaceContext, createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
13
14
  import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
14
15
  import { getNodeContentElement } from './utils/get-node-content-element';
15
16
  import { getAbsoluteSurfacePlacement, getSurfacePlacement } from './utils/get-surface-placement';
17
+ import { hasSurfaceControls } from './utils/has-surface-controls';
16
18
  const EMPTY_SURFACE_POSITIONS = [];
17
19
  const EMPTY_SURFACE_COMPONENTS = [];
18
20
  export const BlockControlsLeftSurfaces = ({
@@ -38,12 +40,15 @@ export const BlockControlsLeftSurfaces = ({
38
40
  return [];
39
41
  }
40
42
  const surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
43
+ if (!hasSurfaceControls(components) || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
44
+ return [];
45
+ }
41
46
  return [{
42
47
  ...target,
43
48
  blockControlsContext: context,
44
49
  surfaceContext
45
50
  }];
46
- }), [activeNode, editorView, targets]);
51
+ }), [activeNode, components, editorView, targets]);
47
52
  const [placements, setPlacements] = useState(new Map());
48
53
  const animationFrameRef = useRef(undefined);
49
54
  useLayoutEffect(() => {
@@ -35,6 +35,7 @@ export const BlockControlsRightSurface = ({
35
35
  const isSticky = placement.height !== undefined;
36
36
  return /*#__PURE__*/React.createElement("div", {
37
37
  "data-editor-block-controls-surface": true,
38
+ "data-editor-block-controls-side": "right",
38
39
  "data-testid": source === 'stored' ? 'block-controls-right-surface-stored' : source === 'active' ? 'block-controls-right-surface-active' : 'block-controls-right-surface'
39
40
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
40
41
  ,
@@ -7,12 +7,14 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
7
7
  import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
8
8
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
9
9
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
10
+ import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
10
11
  import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
11
12
  import { BlockControlsRightSurface } from './block-controls-right-surface';
12
13
  import { createBlockControlsSurfaceContext, createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
13
14
  import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
14
15
  import { getNodeContentElement } from './utils/get-node-content-element';
15
16
  import { getAbsoluteSurfacePlacement, getSurfacePlacement } from './utils/get-surface-placement';
17
+ import { hasSurfaceControls } from './utils/has-surface-controls';
16
18
  const EMPTY_SURFACE_POSITIONS = [];
17
19
  const EMPTY_SURFACE_COMPONENTS = [];
18
20
  /**
@@ -43,12 +45,15 @@ export const BlockControlsRightSurfaces = ({
43
45
  return [];
44
46
  }
45
47
  const surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
48
+ if (!hasSurfaceControls(components) || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
49
+ return [];
50
+ }
46
51
  return [{
47
52
  ...target,
48
53
  blockControlsContext: context,
49
54
  surfaceContext
50
55
  }];
51
- }), [activeNode, editorView, targets]);
56
+ }), [activeNode, components, editorView, targets]);
52
57
  const [placements, setPlacements] = useState(new Map());
53
58
  const animationFrameRef = useRef(undefined);
54
59
  useLayoutEffect(() => {
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Structural toolbar nodes do not render a control by themselves. Treat a surface as populated
3
+ * only once a contributor has registered an interactive descendant.
4
+ */
5
+ export const hasSurfaceControls = components => components.some(component => Boolean(component.component) || component.type === 'button' || component.type === 'menu' || component.type === 'menu-item' || component.type === 'nested-menu');
@@ -40,9 +40,8 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
40
40
  var quickInsertButtonEnabled = (_config$quickInsertBu = config === null || config === void 0 ? void 0 : config.quickInsertButtonEnabled) !== null && _config$quickInsertBu !== void 0 ? _config$quickInsertBu : true;
41
41
  var registryBlockControlsEnabled = isExperimentEnabled('platform_editor_block_control_migration');
42
42
  var legacyBlockControlsEnabled = !registryBlockControlsEnabled;
43
- var rightSurfaceEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_block_control_right_surface');
44
43
  if (registryBlockControlsEnabled) {
45
- var _api$uiControlRegistr;
44
+ var _api$uiControlRegistr, _api$uiControlRegistr2;
46
45
  api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 || _api$uiControlRegistr.actions.register([BLOCK_CONTROLS_LEFT_SURFACE, _objectSpread(_objectSpread({}, BLOCK_CONTROLS_LEFT_SECTION), {}, {
47
46
  parents: [_objectSpread(_objectSpread({}, BLOCK_CONTROLS_LEFT_SURFACE), {}, {
48
47
  rank: 100
@@ -54,21 +53,19 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
54
53
  })].concat(_toConsumableArray(getBlockControlsSurfaceDragHandleComponents({
55
54
  api: api
56
55
  }))));
57
- if (rightSurfaceEnabled) {
58
- var _api$uiControlRegistr2;
59
- // The right surface host stays generic: it only registers the toolbar/section/group
60
- // hierarchy. Individual features contribute their own buttons into
61
- // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
62
- api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 || _api$uiControlRegistr2.actions.register([BLOCK_CONTROLS_RIGHT_SURFACE, _objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SECTION), {}, {
63
- parents: [_objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SURFACE), {}, {
64
- rank: 100
65
- })]
66
- }), _objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_GROUP), {}, {
67
- parents: [_objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SECTION), {}, {
68
- rank: 100
69
- })]
70
- })]);
71
- }
56
+
57
+ // The right surface host stays generic: it only registers the toolbar/section/group
58
+ // hierarchy. Individual features contribute their own buttons into
59
+ // BLOCK_CONTROLS_RIGHT_GROUP from their own plugins, same as the left surface.
60
+ api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 || _api$uiControlRegistr2.actions.register([BLOCK_CONTROLS_RIGHT_SURFACE, _objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SECTION), {}, {
61
+ parents: [_objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SURFACE), {}, {
62
+ rank: 100
63
+ })]
64
+ }), _objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_GROUP), {}, {
65
+ parents: [_objectSpread(_objectSpread({}, BLOCK_CONTROLS_RIGHT_SECTION), {}, {
66
+ rank: 100
67
+ })]
68
+ })]);
72
69
  }
73
70
  return {
74
71
  name: 'blockControls',
@@ -138,7 +135,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
138
135
  plugin: function plugin(_ref2) {
139
136
  var getIntl = _ref2.getIntl,
140
137
  nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
141
- return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled);
138
+ return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled);
142
139
  }
143
140
  }];
144
141
  if (editorExperiment('platform_editor_controls', 'variant1')) {
@@ -466,10 +463,10 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
466
463
  }, /*#__PURE__*/React.createElement(BlockControlsLeftSurfaces, {
467
464
  api: api,
468
465
  editorView: editorView
469
- }), rightSurfaceEnabled ? /*#__PURE__*/React.createElement(BlockControlsRightSurfaces, {
466
+ }), /*#__PURE__*/React.createElement(BlockControlsRightSurfaces, {
470
467
  api: api,
471
468
  editorView: editorView
472
- }) : null) : null);
469
+ })) : null);
473
470
  }
474
471
  };
475
472
  };
@@ -25,7 +25,10 @@ var clearPendingHoverSide = function clearPendingHoverSide(view) {
25
25
  cancelScheduledProcessForView(view);
26
26
  };
27
27
  var BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
28
- var RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
28
+ var LEGACY_RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
29
+ var getRightControlSelector = function getRightControlSelector() {
30
+ return isExperimentEnabled('platform_editor_block_control_migration') ? "[data-editor-block-controls-side=\"right\"], ".concat(LEGACY_RIGHT_EDGE_SELECTOR) : LEGACY_RIGHT_EDGE_SELECTOR;
31
+ };
29
32
  var LEGACY_LEFT_CONTROL_SELECTOR = '[data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
30
33
  var getLeftControlSelector = function getLeftControlSelector() {
31
34
  return isExperimentEnabled('platform_editor_block_control_migration') ? "[data-editor-block-ctrl-drag-handle], ".concat(LEGACY_LEFT_CONTROL_SELECTOR) : LEGACY_LEFT_CONTROL_SELECTOR;
@@ -117,7 +120,7 @@ var processHoverSide = function processHoverSide(view, api) {
117
120
 
118
121
  // When hovering over block controls directly, infer side from which control we're over.
119
122
  // This is more reliable than bounds when controls are in portals outside the editor DOM.
120
- var rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(RIGHT_EDGE_SELECTOR);
123
+ var rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(getRightControlSelector());
121
124
  if (rightEdgeElement) {
122
125
  if (state !== null && state !== void 0 && state.isMouseOut && expValEqualsNoExposure('cc_maui_remix_button_hover_corridor', 'isEnabled', true)) {
123
126
  mouseEnter(view, 'right');
@@ -15,7 +15,7 @@ import { handleMouseEnter, handleMouseLeave, handleMouseMove } from './handle-mo
15
15
  /** Elements that extend the editor hover area (block controls, right-edge button, etc.) */
16
16
  var LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
17
17
  var getBlockControlsHoverAreaSelector = function getBlockControlsHoverAreaSelector() {
18
- return isExperimentEnabled('platform_editor_block_control_migration') ? "[data-editor-block-ctrl-drag-handle], ".concat(LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR) : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
18
+ return isExperimentEnabled('platform_editor_block_control_migration') ? "[data-editor-block-controls-surface], [data-editor-block-ctrl-drag-handle], ".concat(LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR) : LEGACY_BLOCK_CONTROLS_HOVER_AREA_SELECTOR;
19
19
  };
20
20
  var MOUSE_LEAVE_DEBOUNCE_MS = 200;
21
21
 
@@ -1,4 +1,3 @@
1
- import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
2
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
4
3
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
@@ -437,16 +436,18 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
437
436
  // In view mode with right-side controls, remove any lingering drag handle decorations
438
437
  // (they may carry over from edit mode). Only remove drag handles specifically, not
439
438
  // the remix button decorations (those are managed separately via showInViewMode).
440
- if (isViewMode && rightSideControlsEnabled) {
439
+ if (flags.legacyDragHandleEnabled && isViewMode && rightSideControlsEnabled) {
441
440
  var allHandleDecs = findHandleDec(decorations, 0, newState.doc.content.size);
442
441
  if (allHandleDecs.length > 0) {
443
442
  decorations = decorations.remove(allHandleDecs);
444
443
  }
445
444
  }
446
445
  if (shouldRemoveHandle) {
447
- var _activeNode5, _activeNode6;
448
- var oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
449
- decorations = decorations.remove(oldHandle);
446
+ if (flags.legacyDragHandleEnabled) {
447
+ var _activeNode5, _activeNode6;
448
+ var oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
449
+ decorations = decorations.remove(oldHandle);
450
+ }
450
451
  // When removing the handle, also remove the anchor-marker node decorations
451
452
  // (data-active-drag-handle / data-active-quick-insert) so the DOM attributes
452
453
  // don't linger on nodes that are no longer active.
@@ -454,7 +455,7 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
454
455
  // after a doc change (e.g. pressing Enter splits a node), DecorationSet.map() can shift the
455
456
  // decoration to a different position, so a point-range search would miss it and leave a stale
456
457
  // attribute on the wrong DOM node.
457
- if (expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
458
+ if ((flags.legacyDragHandleEnabled || nodeDecorationRegistry.length > 0) && expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
458
459
  var oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, 0, newState.doc.content.size);
459
460
  decorations = decorations.remove(oldActiveNodeDec);
460
461
  var oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, 0, newState.doc.content.size);
@@ -585,7 +586,7 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
585
586
  }
586
587
  }
587
588
  }
588
- if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
589
+ if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined && (quickInsertButtonEnabled || nodeDecorationRegistry.length > 0) &&
589
590
  // platform_editor_controls note: enables quick insert
590
591
  flags.toolbarFlagsEnabled && (!rightSideControlsEnabled || !isViewMode)) {
591
592
  var _latestActiveNode1;
@@ -815,7 +816,7 @@ var _apply = function apply(api, formatMessage, tr, currentState, newState, flag
815
816
  // remove isEmptyDoc check and let decorations render and determine their own visibility
816
817
  // In view mode with right-side controls we render node decorations (right-edge button), not the
817
818
  // handle - so findHandleDec is always empty. Don't clear activeNode in that case.
818
- var hasHandleOrViewModeControls = findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0 || isViewMode && rightSideControlsEnabled || !flags.legacyDragHandleEnabled;
819
+ var hasHandleOrViewModeControls = !flags.legacyDragHandleEnabled || isViewMode && rightSideControlsEnabled || findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0;
819
820
  // Keep the registry surface mounted while its Block Menu owns focus.
820
821
  var keepActiveNodeForOpenBlockMenu = !flags.legacyDragHandleEnabled && isMenuOpen && editorExperiment('platform_editor_block_menu', true);
821
822
  newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred && !keepActiveNodeForOpenBlockMenu || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
@@ -884,7 +885,6 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
884
885
  var rightSideControlsEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
885
886
  var quickInsertButtonEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
886
887
  var legacyDragHandleEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true;
887
- var rightSurfaceEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
888
888
  var _getIntl = getIntl(),
889
889
  formatMessage = _getIntl.formatMessage;
890
890
  var isAdvancedLayoutEnabled = editorExperiment('advanced_layouts', true, {
@@ -899,7 +899,7 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
899
899
  surfaceNodePositionsEnabled: surfaceNodePositionsEnabled,
900
900
  toolbarFlagsEnabled: toolbarFlagsEnabled
901
901
  };
902
- var resolvedSurfaces = surfaceNodePositionsEnabled ? [resolveSurface((_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], BLOCK_CONTROLS_LEFT_SURFACE)].concat(_toConsumableArray(rightSurfaceEnabled ? [resolveSurface((_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], BLOCK_CONTROLS_RIGHT_SURFACE)] : [])) : [];
902
+ var resolvedSurfaces = surfaceNodePositionsEnabled ? [resolveSurface((_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], BLOCK_CONTROLS_LEFT_SURFACE), resolveSurface((_api$uiControlRegistr3 = api === null || api === void 0 || (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], BLOCK_CONTROLS_RIGHT_SURFACE)] : [];
903
903
  var anchorRectCache;
904
904
  if (!isAnchorSupported()) {
905
905
  anchorRectCache = new AnchorRectCache();
@@ -936,7 +936,7 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
936
936
  var decorationSet = (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
937
937
  // In view mode with right-side controls, remove any lingering drag-handle decorations
938
938
  // (created in edit mode) that may not have been cleaned up on mode switch.
939
- if (decorationSet && rightSideControlsEnabled && (api === null || api === void 0 || (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 || (_api$editorViewMode3 = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3 === void 0 ? void 0 : _api$editorViewMode3.mode) === 'view') {
939
+ if (decorationSet && legacyDragHandleEnabled && rightSideControlsEnabled && (api === null || api === void 0 || (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 || (_api$editorViewMode3 = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3 === void 0 ? void 0 : _api$editorViewMode3.mode) === 'view') {
940
940
  var handleDecs = findHandleDec(decorationSet, 0, state.doc.content.size);
941
941
  if (handleDecs.length > 0) {
942
942
  decorationSet = decorationSet.remove(handleDecs);
@@ -1178,10 +1178,15 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
1178
1178
  if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDragging)) {
1179
1179
  var isResizerResizing = !!dom.querySelector('.is-resizing');
1180
1180
  var transaction = editorView.state.tr;
1181
+ var shouldDispatch = false;
1181
1182
  if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.isResizerResizing) !== isResizerResizing) {
1182
1183
  transaction.setMeta('is-resizer-resizing', isResizerResizing);
1184
+ shouldDispatch = true;
1183
1185
  }
1184
- if (!isResizerResizing) {
1186
+
1187
+ // Registry surfaces have their own ResizeObservers and absolute placement.
1188
+ // Width metadata only drives legacy widget recreation.
1189
+ if (legacyDragHandleEnabled && !isResizerResizing) {
1185
1190
  var _editorContentArea = entries[0].target;
1186
1191
  // Ignored via go/ees005
1187
1192
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -1193,8 +1198,11 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
1193
1198
  editorWidthLeft: editorWidthLeft,
1194
1199
  editorWidthRight: editorWidthRight
1195
1200
  }));
1201
+ shouldDispatch = true;
1202
+ }
1203
+ if (shouldDispatch) {
1204
+ editorView.dispatch(transaction);
1196
1205
  }
1197
- editorView.dispatch(transaction);
1198
1206
  }
1199
1207
  }));
1200
1208
  var shouldObserve = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? !isAnchorSupported() : true;
@@ -3,6 +3,7 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
3
3
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
4
4
  import { willComponentRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
5
5
  import { createBlockControlsSurfaceContextForPosition } from '../../ui/block-controls-surface-context';
6
+ import { hasSurfaceControls } from '../../ui/utils/has-surface-controls';
6
7
  var createSurfaceContextAtPosition = function createSurfaceContextAtPosition(state, position, activeNode) {
7
8
  var blockControlsContext = createBlockControlsSurfaceContextForPosition(state, position, activeNode);
8
9
  return blockControlsContext ? createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, blockControlsContext) : undefined;
@@ -26,8 +27,9 @@ export var getSurfaceNodePositions = function getSurfaceNodePositions(state, res
26
27
  var to = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : state.doc.content.size;
27
28
  var surfaces = resolvedSurfaces.flatMap(function (_ref2) {
28
29
  var childrenMap = _ref2.childrenMap,
30
+ components = _ref2.components,
29
31
  root = _ref2.root;
30
- return root ? [{
32
+ return root && hasSurfaceControls(components) ? [{
31
33
  childrenMap: childrenMap,
32
34
  root: root
33
35
  }] : [];
@@ -67,8 +69,9 @@ export var updateSurfaceNodePositions = function updateSurfaceNodePositions(_ref
67
69
  }
68
70
  var surfaces = resolvedSurfaces.flatMap(function (_ref4) {
69
71
  var childrenMap = _ref4.childrenMap,
72
+ components = _ref4.components,
70
73
  root = _ref4.root;
71
- return root ? [{
74
+ return root && hasSurfaceControls(components) ? [{
72
75
  childrenMap: childrenMap,
73
76
  root: root
74
77
  }] : [];
@@ -36,6 +36,7 @@ export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref) {
36
36
  var isSticky = placement.height !== undefined;
37
37
  return /*#__PURE__*/React.createElement("div", {
38
38
  "data-editor-block-controls-surface": true,
39
+ "data-editor-block-controls-side": "left",
39
40
  "data-testid": source === 'stored' ? 'block-controls-left-surface-stored' : source === 'active' ? 'block-controls-left-surface-active' : 'block-controls-left-surface'
40
41
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
41
42
  ,
@@ -14,12 +14,14 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
14
14
  import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
15
15
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
16
16
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
17
+ import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
17
18
  import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
18
19
  import { BlockControlsLeftSurface } from './block-controls-left-surface';
19
20
  import { createBlockControlsSurfaceContext, createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
20
21
  import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
21
22
  import { getNodeContentElement } from './utils/get-node-content-element';
22
23
  import { getAbsoluteSurfacePlacement, getSurfacePlacement } from './utils/get-surface-placement';
24
+ import { hasSurfaceControls } from './utils/has-surface-controls';
23
25
  var EMPTY_SURFACE_POSITIONS = [];
24
26
  var EMPTY_SURFACE_COMPONENTS = [];
25
27
  export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref) {
@@ -46,12 +48,15 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
46
48
  return [];
47
49
  }
48
50
  var surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
51
+ if (!hasSurfaceControls(components) || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
52
+ return [];
53
+ }
49
54
  return [_objectSpread(_objectSpread({}, target), {}, {
50
55
  blockControlsContext: context,
51
56
  surfaceContext: surfaceContext
52
57
  })];
53
58
  });
54
- }, [activeNode, editorView, targets]);
59
+ }, [activeNode, components, editorView, targets]);
55
60
  var _useState = useState(new Map()),
56
61
  _useState2 = _slicedToArray(_useState, 2),
57
62
  placements = _useState2[0],
@@ -33,6 +33,7 @@ export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref)
33
33
  var isSticky = placement.height !== undefined;
34
34
  return /*#__PURE__*/React.createElement("div", {
35
35
  "data-editor-block-controls-surface": true,
36
+ "data-editor-block-controls-side": "right",
36
37
  "data-testid": source === 'stored' ? 'block-controls-right-surface-stored' : source === 'active' ? 'block-controls-right-surface-active' : 'block-controls-right-surface'
37
38
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved from the target node's runtime DOM geometry.
38
39
  ,
@@ -14,12 +14,14 @@ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls
14
14
  import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
15
15
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
16
16
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
17
+ import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
17
18
  import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
18
19
  import { BlockControlsRightSurface } from './block-controls-right-surface';
19
20
  import { createBlockControlsSurfaceContext, createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
20
21
  import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
21
22
  import { getNodeContentElement } from './utils/get-node-content-element';
22
23
  import { getAbsoluteSurfacePlacement, getSurfacePlacement } from './utils/get-surface-placement';
24
+ import { hasSurfaceControls } from './utils/has-surface-controls';
23
25
  var EMPTY_SURFACE_POSITIONS = [];
24
26
  var EMPTY_SURFACE_COMPONENTS = [];
25
27
  /**
@@ -51,12 +53,15 @@ export var BlockControlsRightSurfaces = function BlockControlsRightSurfaces(_ref
51
53
  return [];
52
54
  }
53
55
  var surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
56
+ if (!hasSurfaceControls(components) || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
57
+ return [];
58
+ }
54
59
  return [_objectSpread(_objectSpread({}, target), {}, {
55
60
  blockControlsContext: context,
56
61
  surfaceContext: surfaceContext
57
62
  })];
58
63
  });
59
- }, [activeNode, editorView, targets]);
64
+ }, [activeNode, components, editorView, targets]);
60
65
  var _useState = useState(new Map()),
61
66
  _useState2 = _slicedToArray(_useState, 2),
62
67
  placements = _useState2[0],
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Structural toolbar nodes do not render a control by themselves. Treat a surface as populated
3
+ * only once a contributor has registered an interactive descendant.
4
+ */
5
+ export var hasSurfaceControls = function hasSurfaceControls(components) {
6
+ return components.some(function (component) {
7
+ return Boolean(component.component) || component.type === 'button' || component.type === 'menu' || component.type === 'menu-item' || component.type === 'nested-menu';
8
+ });
9
+ };
@@ -44,7 +44,7 @@ export declare const apply: (api: ExtractInjectionAPI<BlockControlsPlugin> | und
44
44
  multiSelectDnD: MultiSelectDnD | undefined;
45
45
  surfaceNodePositions: number[];
46
46
  };
47
- export declare const createPlugin: (api: ExtractInjectionAPI<BlockControlsPlugin> | undefined, getIntl: () => IntlShape, nodeViewPortalProviderAPI: PortalProviderAPI, nodeDecorationRegistry: NodeDecorationFactory[], rightSideControlsEnabled?: boolean, quickInsertButtonEnabled?: boolean, legacyDragHandleEnabled?: boolean, rightSurfaceEnabled?: boolean) => SafePlugin<PluginState | {
47
+ export declare const createPlugin: (api: ExtractInjectionAPI<BlockControlsPlugin> | undefined, getIntl: () => IntlShape, nodeViewPortalProviderAPI: PortalProviderAPI, nodeDecorationRegistry: NodeDecorationFactory[], rightSideControlsEnabled?: boolean, quickInsertButtonEnabled?: boolean, legacyDragHandleEnabled?: boolean) => SafePlugin<PluginState | {
48
48
  activeDropTargetNode: ActiveDropTargetNode | undefined;
49
49
  activeNode: any;
50
50
  blockMenuOptions: {
@@ -0,0 +1,6 @@
1
+ import type { RegisterComponent } from '@atlaskit/editor-ui-control-model/types';
2
+ /**
3
+ * Structural toolbar nodes do not render a control by themselves. Treat a surface as populated
4
+ * only once a contributor has registered an interactive descendant.
5
+ */
6
+ export declare const hasSurfaceControls: (components: readonly RegisterComponent[]) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "17.4.1",
3
+ "version": "17.4.2",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",