@atlaskit/editor-plugin-block-controls 17.3.9 → 17.3.11

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 (39) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/cjs/blockControlsPlugin.js +2 -3
  3. package/dist/cjs/pm-plugins/decorations-common.js +2 -2
  4. package/dist/cjs/pm-plugins/decorations-drag-handle.js +4 -4
  5. package/dist/cjs/pm-plugins/decorations-drop-target.js +3 -3
  6. package/dist/cjs/pm-plugins/decorations-quick-insert-button.js +2 -2
  7. package/dist/cjs/pm-plugins/main.js +4 -2
  8. package/dist/cjs/ui/block-controls-left-surface.js +21 -7
  9. package/dist/cjs/ui/block-controls-right-surface.js +21 -7
  10. package/dist/cjs/ui/consts.js +13 -5
  11. package/dist/cjs/ui/utils/partition-components-by-persistence.js +65 -0
  12. package/dist/cjs/ui/visibility-container.js +6 -2
  13. package/dist/es2019/blockControlsPlugin.js +2 -3
  14. package/dist/es2019/pm-plugins/decorations-common.js +1 -1
  15. package/dist/es2019/pm-plugins/decorations-drag-handle.js +1 -1
  16. package/dist/es2019/pm-plugins/decorations-drop-target.js +1 -1
  17. package/dist/es2019/pm-plugins/decorations-quick-insert-button.js +1 -1
  18. package/dist/es2019/pm-plugins/main.js +4 -1
  19. package/dist/es2019/ui/block-controls-left-surface.js +22 -7
  20. package/dist/es2019/ui/block-controls-right-surface.js +22 -7
  21. package/dist/es2019/ui/consts.js +10 -4
  22. package/dist/es2019/ui/utils/partition-components-by-persistence.js +48 -0
  23. package/dist/es2019/ui/visibility-container.js +6 -2
  24. package/dist/esm/blockControlsPlugin.js +2 -3
  25. package/dist/esm/pm-plugins/decorations-common.js +1 -1
  26. package/dist/esm/pm-plugins/decorations-drag-handle.js +1 -1
  27. package/dist/esm/pm-plugins/decorations-drop-target.js +1 -1
  28. package/dist/esm/pm-plugins/decorations-quick-insert-button.js +1 -1
  29. package/dist/esm/pm-plugins/main.js +4 -2
  30. package/dist/esm/ui/block-controls-left-surface.js +21 -7
  31. package/dist/esm/ui/block-controls-right-surface.js +21 -7
  32. package/dist/esm/ui/consts.js +12 -4
  33. package/dist/esm/ui/utils/partition-components-by-persistence.js +59 -0
  34. package/dist/esm/ui/visibility-container.js +6 -2
  35. package/dist/types/pm-plugins/main.d.ts +1 -1
  36. package/dist/types/ui/consts.d.ts +0 -1
  37. package/dist/types/ui/utils/partition-components-by-persistence.d.ts +15 -0
  38. package/dist/types/ui/visibility-container.d.ts +2 -1
  39. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @atlaskit/editor-plugin-block-controls
2
2
 
3
+ ## 17.3.11
4
+
5
+ ### Patch Changes
6
+
7
+ - [`0927c3666c010`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0927c3666c010) -
8
+ Upgrade `uuid` from `3.x` to `11.1.1` to remediate GHSA-w5hq-g745-h8pq / SNYK-JS-UUID-16133035.
9
+
10
+ `uuid@11` removed the deep subpath exports (`uuid/v4`, `uuid/v1`, `uuid/v5`) and the default
11
+ export, so all internal call sites were migrated to named imports:
12
+
13
+ ```diff
14
+ -import uuid from 'uuid/v4';
15
+ +import { v4 as uuid } from 'uuid';
16
+
17
+ -import uuid from 'uuid';
18
+ +import { v4 as uuid } from 'uuid';
19
+ ```
20
+
21
+ With the exception of `@atlassian/integrations` (below), this is an internal implementation change
22
+ only - no public API, export, or entrypoint changed. UUID generation behaviour is unchanged
23
+ (`uuid@3`'s default export was already `v4`).
24
+
25
+ `@atlassian/integrations` declares `uuid` as a peer dependency, so its declared range moved from
26
+ `^3.1.0` to `^11.1.1`. That is a peer dependency declaration change, hence `minor` rather than
27
+ `patch` for that package.
28
+
29
+ The following `platform/packages/ai-mate` packages were also touched, but are all `private: true`
30
+ and so are intentionally not listed in the frontmatter above:
31
+ - `@atlassian/csm-assistance-service` - bumped its explicit `uuid` dependency from `npm:^9.0.0` to
32
+ `npm:^11.1.1` (`9.0.1` is also within the advisory's affected range).
33
+ - `@atlassian/csm-guidance-config` - example helper only, migrated to the named `uuid` import.
34
+ - `@atlassian/csm-ui-components` - example helper only, migrated to the named `uuid` import.
35
+
36
+ - Updated dependencies
37
+
38
+ ## 17.3.10
39
+
40
+ ### Patch Changes
41
+
42
+ - [`42ff8dffbdf01`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/42ff8dffbdf01) -
43
+ EDITOR-8771: Buttons registered on the same surface position now stay visible independently of
44
+ eachother: a button that renders without hover (e.g. an AI suggestions icon) no longer
45
+ hides/showstogether with a hover-only button (e.g. Remix) that shares its position.Increase the
46
+ default drag-handle/surface gap for non-resizable, default-sized nodes from 8px to12px, matching
47
+ the gap already used for resizable/breakout nodes, so spacing is consistent acrossnode
48
+ types.Simplify `surfaceNodePositionsEnabled` (which controls whether the "stored" whole-doc
49
+ surface scanruns) to depend only on `platform_editor_block_control_migration`, dropping the
50
+ extra`platform_editor_collapsible_headings` OR-condition now
51
+ that`platform_editor_block_control_right_surface` consumers need the same behavior.
52
+ - Updated dependencies
53
+
3
54
  ## 17.3.9
4
55
 
5
56
  ### Patch Changes
@@ -46,7 +46,6 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
46
46
  var rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
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
- var surfaceNodePositionsEnabled = registryBlockControlsEnabled && (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_collapsible_headings');
50
49
  var legacyBlockControlsEnabled = !registryBlockControlsEnabled;
51
50
  var rightSurfaceEnabled = registryBlockControlsEnabled && (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_right_surface');
52
51
  if (registryBlockControlsEnabled) {
@@ -146,7 +145,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
146
145
  plugin: function plugin(_ref2) {
147
146
  var getIntl = _ref2.getIntl,
148
147
  nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
149
- return (0, _main.createPlugin)(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, surfaceNodePositionsEnabled, rightSurfaceEnabled);
148
+ return (0, _main.createPlugin)(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled);
150
149
  }
151
150
  }];
152
151
  if ((0, _editorExperiment.editorExperiment)('platform_editor_controls', 'variant1')) {
@@ -448,7 +447,7 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
448
447
  isEditing: (_interactionTrackingP = _pmPlugin.interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
449
448
  isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState10 = _main.key.getState(editorState)) === null || _key$getState10 === void 0 ? void 0 : _key$getState10.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
450
449
  };
451
- if (surfaceNodePositionsEnabled) {
450
+ if (registryBlockControlsEnabled) {
452
451
  var _key$getState$surface, _key$getState11;
453
452
  sharedState.surfaceNodePositions = (_key$getState$surface = (_key$getState11 = _main.key.getState(editorState)) === null || _key$getState11 === void 0 ? void 0 : _key$getState11.surfaceNodePositions) !== null && _key$getState$surface !== void 0 ? _key$getState$surface : [];
454
453
  }
@@ -8,7 +8,7 @@ exports.unmountDecorations = exports.getNodeTypeWithLevel = exports.getNodeAncho
8
8
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
9
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
- var _uuid = _interopRequireDefault(require("uuid"));
11
+ var _uuid = require("uuid");
12
12
  var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
13
13
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
14
14
  var _reactRootRegistry = require("./react-root-registry");
@@ -48,7 +48,7 @@ var ObjHash = /*#__PURE__*/function () {
48
48
  return this.caching.get(node);
49
49
  }
50
50
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
51
- var uniqueId = (0, _uuid.default)();
51
+ var uniqueId = (0, _uuid.v4)();
52
52
  this.caching.set(node, uniqueId);
53
53
  return uniqueId;
54
54
  }
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.findHandleDec = exports.findActiveDragHandleNodeDec = exports.emptyParagraphNodeDecorations = exports.dragHandleDecoration = exports.createActiveDragHandleNodeDecoration = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = require("react");
10
- var _uuid = _interopRequireDefault(require("uuid"));
10
+ var _uuid = require("uuid");
11
11
  var _view = require("@atlaskit/editor-prosemirror/view");
12
12
  var _fg = require("@atlaskit/platform-feature-flags/fg");
13
13
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
@@ -62,12 +62,12 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
62
62
  editorState = _ref.editorState;
63
63
  (0, _decorationsCommon.unmountDecorations)(nodeViewPortalProviderAPI, 'data-blocks-drag-handle-container', 'data-blocks-drag-handle-key');
64
64
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
65
- var key = (0, _uuid.default)();
65
+ var key = (0, _uuid.v4)();
66
66
  var widgetSpec = (0, _editorExperiment.editorExperiment)('platform_editor_breakout_resizing', true) ? {
67
67
  side: -1,
68
68
  type: _decorationsCommon.TYPE_HANDLE_DEC,
69
69
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
70
- testid: "".concat(_decorationsCommon.TYPE_HANDLE_DEC, "-").concat((0, _uuid.default)()),
70
+ testid: "".concat(_decorationsCommon.TYPE_HANDLE_DEC, "-").concat((0, _uuid.v4)()),
71
71
  /**
72
72
  * sigh - `marks` influences the position that the widget is drawn (as described on the `side` property).
73
73
  * Exclude 'breakout' on purpose, so the widgets render at the top of the document to avoid z-index issues
@@ -78,7 +78,7 @@ var dragHandleDecoration = exports.dragHandleDecoration = function dragHandleDec
78
78
  side: -1,
79
79
  type: _decorationsCommon.TYPE_HANDLE_DEC,
80
80
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
81
- testid: "".concat(_decorationsCommon.TYPE_HANDLE_DEC, "-").concat((0, _uuid.default)()),
81
+ testid: "".concat(_decorationsCommon.TYPE_HANDLE_DEC, "-").concat((0, _uuid.v4)()),
82
82
  marks: (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? (0, _marks.getMatchingBlockMarks)(editorState, pos, [editorState.schema.marks.alignment, editorState.schema.marks.fontSize]) : []
83
83
  };
84
84
  return _view.Decoration.widget(pos, function (view, getPosUnsafe) {
@@ -9,7 +9,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _react = require("react");
11
11
  var _memoizeOne = _interopRequireDefault(require("memoize-one"));
12
- var _uuid = _interopRequireDefault(require("uuid"));
12
+ var _uuid = require("uuid");
13
13
  var _selection = require("@atlaskit/editor-common/selection");
14
14
  var _utils = require("@atlaskit/editor-common/utils");
15
15
  var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
@@ -100,7 +100,7 @@ var findDropTargetDecs = exports.findDropTargetDecs = function findDropTargetDec
100
100
  };
101
101
  var createDropTargetDecoration = exports.createDropTargetDecoration = function createDropTargetDecoration(pos, props, nodeViewPortalProviderAPI, side, anchorRectCache, isSameLayout) {
102
102
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
103
- var key = (0, _uuid.default)();
103
+ var key = (0, _uuid.v4)();
104
104
  return _view.Decoration.widget(pos, function (_, getPosUnsafe) {
105
105
  var getPos = function getPos() {
106
106
  try {
@@ -139,7 +139,7 @@ var createDropTargetDecoration = exports.createDropTargetDecoration = function c
139
139
  };
140
140
  var createLayoutDropTargetDecoration = exports.createLayoutDropTargetDecoration = function createLayoutDropTargetDecoration(pos, props, nodeViewPortalProviderAPI, anchorRectCache) {
141
141
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
142
- var key = (0, _uuid.default)();
142
+ var key = (0, _uuid.v4)();
143
143
  return _view.Decoration.widget(pos, function (_, getPosUnsafe) {
144
144
  var getPos = function getPos() {
145
145
  try {
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.quickInsertButtonDecoration = exports.findQuickInsertInsertButtonDecoration = exports.findActiveQuickInsertNodeDec = exports.createActiveQuickInsertNodeDecoration = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = require("react");
10
- var _uuid = _interopRequireDefault(require("uuid"));
10
+ var _uuid = require("uuid");
11
11
  var _view = require("@atlaskit/editor-prosemirror/view");
12
12
  var _fg = require("@atlaskit/platform-feature-flags/fg");
13
13
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
@@ -51,7 +51,7 @@ var quickInsertButtonDecoration = exports.quickInsertButtonDecoration = function
51
51
  anchorRectCache = _ref.anchorRectCache,
52
52
  editorState = _ref.editorState;
53
53
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
54
- var key = (0, _uuid.default)();
54
+ var key = (0, _uuid.v4)();
55
55
  var cleanupCallbacks = [];
56
56
  var widgetSpec = (0, _editorExperiment.editorExperiment)('platform_editor_breakout_resizing', true) ? {
57
57
  side: -2,
@@ -890,14 +890,16 @@ var createPlugin = exports.createPlugin = function createPlugin(api, getIntl, no
890
890
  var rightSideControlsEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
891
891
  var quickInsertButtonEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
892
892
  var legacyDragHandleEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true;
893
- var surfaceNodePositionsEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
894
- var rightSurfaceEnabled = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
893
+ var rightSurfaceEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
895
894
  var _getIntl = getIntl(),
896
895
  formatMessage = _getIntl.formatMessage;
897
896
  var isAdvancedLayoutEnabled = (0, _editorExperiment.editorExperiment)('advanced_layouts', true, {
898
897
  exposure: true
899
898
  });
900
899
  var toolbarFlagsEnabled = (0, _toolbarFlagCheck.areToolbarFlagsEnabled)(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
900
+ // Mirrors `registryBlockControlsEnabled` in blockControlsPlugin.tsx: `legacyDragHandleEnabled` is
901
+ // only false once that gate is on.
902
+ var surfaceNodePositionsEnabled = !legacyDragHandleEnabled;
901
903
  var flags = {
902
904
  legacyDragHandleEnabled: legacyDragHandleEnabled,
903
905
  surfaceNodePositionsEnabled: surfaceNodePositionsEnabled,
@@ -14,6 +14,7 @@ var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys"
14
14
  var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
15
15
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
16
16
  var _blockControlsSurfaceContext = require("./block-controls-surface-context");
17
+ var _partitionComponentsByPersistence = require("./utils/partition-components-by-persistence");
17
18
  var _visibilityContainer = require("./visibility-container");
18
19
  var leftSurfaceOuterStyles = null;
19
20
  var leftSurfaceRowStyles = null;
@@ -34,11 +35,11 @@ var BlockControlsLeftSurface = exports.BlockControlsLeftSurface = function Block
34
35
  if (!placement || !(0, _surfaceRenderer.willSurfaceRender)(components, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
35
36
  return null;
36
37
  }
37
- var surface = /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
38
- components: components,
39
- surface: _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE,
40
- surfaceContext: surfaceContext
41
- });
38
+ var _partitionComponentsB = (0, _partitionComponentsByPersistence.partitionComponentsByPersistence)(components, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext),
39
+ hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
40
+ persistentComponents = _partitionComponentsB.persistentComponents;
41
+ var willRenderPersistent = (0, _surfaceRenderer.willSurfaceRender)(persistentComponents, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
42
+ var willRenderHoverOnly = (0, _surfaceRenderer.willSurfaceRender)(hoverOnlyComponents, _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
42
43
  var isSticky = placement.height !== undefined;
43
44
  return /*#__PURE__*/_react.default.createElement("div", {
44
45
  "data-editor-block-controls-surface": true,
@@ -49,10 +50,23 @@ var BlockControlsLeftSurface = exports.BlockControlsLeftSurface = function Block
49
50
  className: (0, _runtime.ax)(["_kqswstnw _1pbyb4wl"])
50
51
  }, /*#__PURE__*/_react.default.createElement("div", {
51
52
  className: (0, _runtime.ax)(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
52
- }, /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
53
+ }, willRenderPersistent && /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
54
+ api: api,
55
+ controlSide: (0, _blockControlsSurfaceContext.getBlockControlsSurfaceControlSide)(surfaceContext.get(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT), (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_controls_reliable_anchor')),
56
+ forceVisibleOnMouseOut: forceVisibleOnMouseOut,
57
+ shouldUseDisplayContents: true
58
+ }, /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
59
+ components: persistentComponents,
60
+ surface: _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE,
61
+ surfaceContext: surfaceContext
62
+ })), willRenderHoverOnly && /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
53
63
  api: api,
54
64
  controlSide: (0, _blockControlsSurfaceContext.getBlockControlsSurfaceControlSide)(surfaceContext.get(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT), (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_controls_reliable_anchor')),
55
65
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
56
66
  shouldUseDisplayContents: true
57
- }, surface)));
67
+ }, /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
68
+ components: hoverOnlyComponents,
69
+ surface: _surfaceKeys.BLOCK_CONTROLS_LEFT_SURFACE,
70
+ surfaceContext: surfaceContext
71
+ }))));
58
72
  };
@@ -11,6 +11,7 @@ var _runtime = require("@compiled/react/runtime");
11
11
  var _react = _interopRequireDefault(require("react"));
12
12
  var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys");
13
13
  var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
14
+ var _partitionComponentsByPersistence = require("./utils/partition-components-by-persistence");
14
15
  var _visibilityContainer = require("./visibility-container");
15
16
  var rightSurfaceOuterStyles = null;
16
17
  var rightSurfaceRowStyles = null;
@@ -31,11 +32,11 @@ var BlockControlsRightSurface = exports.BlockControlsRightSurface = function Blo
31
32
  if (!placement || !(0, _surfaceRenderer.willSurfaceRender)(components, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
32
33
  return null;
33
34
  }
34
- var surface = /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
35
- components: components,
36
- surface: _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE,
37
- surfaceContext: surfaceContext
38
- });
35
+ var _partitionComponentsB = (0, _partitionComponentsByPersistence.partitionComponentsByPersistence)(components, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext),
36
+ hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
37
+ persistentComponents = _partitionComponentsB.persistentComponents;
38
+ var willRenderPersistent = (0, _surfaceRenderer.willSurfaceRender)(persistentComponents, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
39
+ var willRenderHoverOnly = (0, _surfaceRenderer.willSurfaceRender)(hoverOnlyComponents, _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
39
40
  var isSticky = placement.height !== undefined;
40
41
  return /*#__PURE__*/_react.default.createElement("div", {
41
42
  "data-editor-block-controls-surface": true,
@@ -46,10 +47,23 @@ var BlockControlsRightSurface = exports.BlockControlsRightSurface = function Blo
46
47
  className: (0, _runtime.ax)(["_kqswstnw _1pbyb4wl"])
47
48
  }, /*#__PURE__*/_react.default.createElement("div", {
48
49
  className: (0, _runtime.ax)(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
49
- }, /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
50
+ }, willRenderPersistent && /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
51
+ api: api,
52
+ controlSide: "right",
53
+ isPersistent: true,
54
+ shouldUseDisplayContents: true
55
+ }, /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
56
+ components: persistentComponents,
57
+ surface: _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE,
58
+ surfaceContext: surfaceContext
59
+ })), willRenderHoverOnly && /*#__PURE__*/_react.default.createElement(_visibilityContainer.VisibilityContainer, {
50
60
  api: api,
51
61
  controlSide: "right",
52
62
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
53
63
  shouldUseDisplayContents: true
54
- }, surface)));
64
+ }, /*#__PURE__*/_react.default.createElement(_surfaceRenderer.SurfaceRenderer, {
65
+ components: hoverOnlyComponents,
66
+ surface: _surfaceKeys.BLOCK_CONTROLS_RIGHT_SURFACE,
67
+ surfaceContext: surfaceContext
68
+ }))));
55
69
  };
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.topPositionAdjustment = exports.spacingBetweenNodesForPreview = exports.spaceLookupMap = exports.rootElementGap = exports.nodeMargins = exports.getNestedNodeLeftPaddingMargin = exports.dropTargetMarginMap = exports.dragHandleGap = exports.STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER = exports.STICKY_CONTROLS_TOP_MARGIN = exports.QUICK_INSERT_WIDTH = exports.QUICK_INSERT_LEFT_OFFSET = exports.QUICK_INSERT_HEIGHT = exports.QUICK_INSERT_DIMENSIONS = exports.DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_WRAPPED_MEDIA_EMBED_TOP_ADJUSTMENT = exports.DRAG_HANDLE_SYNCED_BLOCK_GAP = exports.DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = exports.DRAG_HANDLE_PARAGRAPH_SMALL_TOP_ADJUSTMENT = exports.DRAG_HANDLE_NARROW_GAP = exports.DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = exports.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = exports.DRAG_HANDLE_MAX_GAP = exports.DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = exports.DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_H6_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H5_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H4_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H3_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H2_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H1_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DEFAULT_GAP = exports.DRAG_HANDLE_BORDER_RADIUS = exports.DEFAULT_COLUMN_DISTRIBUTIONS = exports.BLOCK_CONTROLS_SURFACE_SELECTOR = exports.ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = exports.ACTIVE_QUICK_INSERT_ATTR = exports.ACTIVE_DRAG_HANDLE_FALLBACK_ANCHOR_NAME = exports.ACTIVE_DRAG_HANDLE_ATTR = void 0;
7
+ exports.topPositionAdjustment = exports.spacingBetweenNodesForPreview = exports.spaceLookupMap = exports.rootElementGap = exports.nodeMargins = exports.getNestedNodeLeftPaddingMargin = exports.dropTargetMarginMap = exports.dragHandleGap = exports.STICKY_CONTROLS_TOP_MARGIN_FOR_STICKY_HEADER = exports.STICKY_CONTROLS_TOP_MARGIN = exports.QUICK_INSERT_WIDTH = exports.QUICK_INSERT_LEFT_OFFSET = exports.QUICK_INSERT_HEIGHT = exports.QUICK_INSERT_DIMENSIONS = exports.DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_WRAPPED_MEDIA_EMBED_TOP_ADJUSTMENT = exports.DRAG_HANDLE_SYNCED_BLOCK_GAP = exports.DRAG_HANDLE_PARAGRAPH_TOP_ADJUSTMENT = exports.DRAG_HANDLE_PARAGRAPH_SMALL_TOP_ADJUSTMENT = exports.DRAG_HANDLE_NARROW_GAP = exports.DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = exports.DRAG_HANDLE_MAX_SHIFT_CLICK_DEPTH = exports.DRAG_HANDLE_MAX_GAP = exports.DRAG_HANDLE_LAYOUT_SECTION_TOP_ADJUSTMENT = exports.DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_H6_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H5_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H4_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H3_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H2_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H1_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = exports.DRAG_HANDLE_BORDER_RADIUS = exports.DEFAULT_COLUMN_DISTRIBUTIONS = exports.BLOCK_CONTROLS_SURFACE_SELECTOR = exports.ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = exports.ACTIVE_QUICK_INSERT_ATTR = exports.ACTIVE_DRAG_HANDLE_FALLBACK_ANCHOR_NAME = exports.ACTIVE_DRAG_HANDLE_ATTR = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _styles = require("@atlaskit/editor-common/styles");
@@ -23,11 +23,19 @@ var ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = exports.ACTIVE_QUICK_INSERT_FALLB
23
23
  var DRAG_HANDLE_HEIGHT = exports.DRAG_HANDLE_HEIGHT = 24;
24
24
  var DRAG_HANDLE_BORDER_RADIUS = exports.DRAG_HANDLE_BORDER_RADIUS = 4;
25
25
  var DRAG_HANDLE_ZINDEX = exports.DRAG_HANDLE_ZINDEX = _editorSharedStyles.akRichMediaResizeZIndex + _editorSharedStyles.akEditorUnitZIndex; //place above legacy resizer
26
- var DRAG_HANDLE_DEFAULT_GAP = exports.DRAG_HANDLE_DEFAULT_GAP = 8;
26
+ var LEGACY_DRAG_HANDLE_DEFAULT_GAP = 8;
27
+ var MIGRATED_DRAG_HANDLE_DEFAULT_GAP = 12;
27
28
  var DRAG_HANDLE_NARROW_GAP = exports.DRAG_HANDLE_NARROW_GAP = 4;
28
29
  var DRAG_HANDLE_MAX_GAP = exports.DRAG_HANDLE_MAX_GAP = 12;
29
30
  var DRAG_HANDLE_SYNCED_BLOCK_GAP = exports.DRAG_HANDLE_SYNCED_BLOCK_GAP = 2.5;
30
31
  var DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = exports.DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = _styles.DRAG_HANDLE_WIDTH + DRAG_HANDLE_MAX_GAP;
32
+
33
+ // Non-resizable/default-sized nodes get the same gap as resizable/breakout nodes
34
+ // (DRAG_HANDLE_MAX_GAP) once the registry-backed surfaces are on; kept at the legacy value
35
+ // otherwise to avoid an unrelated visual change for consumers still on the old decoration path.
36
+ var getDragHandleDefaultGap = function getDragHandleDefaultGap() {
37
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? MIGRATED_DRAG_HANDLE_DEFAULT_GAP : LEGACY_DRAG_HANDLE_DEFAULT_GAP;
38
+ };
31
39
  var DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = exports.DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = 4 + 2; // 4px for the divider vertical padding and 2px for the divider height
32
40
  var DRAG_HANDLE_H1_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H1_TOP_ADJUSTMENT = 5;
33
41
  var DRAG_HANDLE_H2_TOP_ADJUSTMENT = exports.DRAG_HANDLE_H2_TOP_ADJUSTMENT = 2;
@@ -78,12 +86,12 @@ var dragHandleGap = exports.dragHandleGap = function dragHandleGap(nodeType, par
78
86
  }
79
87
  }
80
88
  if (nodeType === 'layoutSection') {
81
- return DRAG_HANDLE_DEFAULT_GAP + 20;
89
+ return getDragHandleDefaultGap() + 20;
82
90
  }
83
91
  if (nodeTypeExcludeList.includes(nodeType)) {
84
92
  return DRAG_HANDLE_MAX_GAP;
85
93
  }
86
- return DRAG_HANDLE_DEFAULT_GAP;
94
+ return getDragHandleDefaultGap();
87
95
  };
88
96
 
89
97
  // use for returning gap only for root level elements
@@ -104,7 +112,7 @@ var rootElementGap = exports.rootElementGap = function rootElementGap(nodeType)
104
112
  if (nodeType === 'layoutSection') {
105
113
  return DRAG_HANDLE_MAX_GAP + 12;
106
114
  }
107
- return DRAG_HANDLE_DEFAULT_GAP;
115
+ return getDragHandleDefaultGap();
108
116
  };
109
117
  var getNestedNodeLeftPaddingMargin = exports.getNestedNodeLeftPaddingMargin = function getNestedNodeLeftPaddingMargin(nodeType) {
110
118
  switch (nodeType) {
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.partitionComponentsByPersistence = void 0;
7
+ var _blockControlUiContext = require("@atlaskit/editor-common/block-controls/block-control-ui-context");
8
+ var _surfaceRenderer = require("@atlaskit/editor-ui-control-model/surface-renderer");
9
+ var _createSurfaceContext = require("@atlaskit/editor-ui-control-model/create-surface-context");
10
+ 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; } } }; }
11
+ 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; } }
12
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
+ /**
14
+ * Split registered components into two groups:
15
+ * those that should be rendered persistently and those that should only be rendered on hover.
16
+ */
17
+ var partitionComponentsByPersistence = exports.partitionComponentsByPersistence = function partitionComponentsByPersistence(components, surface, surfaceContext) {
18
+ var _resolveSurface = (0, _surfaceRenderer.resolveSurface)(components, surface),
19
+ childrenMap = _resolveSurface.childrenMap,
20
+ root = _resolveSurface.root,
21
+ topLevelChildren = _resolveSurface.topLevelChildren;
22
+ if (!root || !topLevelChildren || topLevelChildren.length === 0) {
23
+ return {
24
+ hoverOnlyComponents: [],
25
+ persistentComponents: components
26
+ };
27
+ }
28
+ var context = surfaceContext === null || surfaceContext === void 0 ? void 0 : surfaceContext.get(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT);
29
+ var storedSurfaceContext = context ? (0, _createSurfaceContext.createSurfaceContext)(_blockControlUiContext.BLOCK_CONTROL_UI_CONTEXT, {
30
+ activeNode: undefined,
31
+ rootNode: context.targetNode,
32
+ targetNode: context.targetNode
33
+ }) : undefined;
34
+ var isLeaf = function isLeaf(component) {
35
+ var children = childrenMap.get((0, _surfaceRenderer.getComponentIdentity)(component));
36
+ return !children || children.length === 0;
37
+ };
38
+ var persistentComponents = [];
39
+ var hoverOnlyComponents = [];
40
+ var _iterator = _createForOfIteratorHelper(components),
41
+ _step;
42
+ try {
43
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
44
+ var component = _step.value;
45
+ if (!isLeaf(component)) {
46
+ persistentComponents.push(component);
47
+ hoverOnlyComponents.push(component);
48
+ continue;
49
+ }
50
+ if ((0, _surfaceRenderer.willComponentRender)(component, childrenMap, storedSurfaceContext)) {
51
+ persistentComponents.push(component);
52
+ } else {
53
+ hoverOnlyComponents.push(component);
54
+ }
55
+ }
56
+ } catch (err) {
57
+ _iterator.e(err);
58
+ } finally {
59
+ _iterator.f();
60
+ }
61
+ return {
62
+ hoverOnlyComponents: hoverOnlyComponents,
63
+ persistentComponents: persistentComponents
64
+ };
65
+ };
@@ -62,6 +62,7 @@ var VisibilityContainer = exports.VisibilityContainer = function VisibilityConta
62
62
  children = _ref.children,
63
63
  controlSide = _ref.controlSide,
64
64
  forceVisibleOnMouseOut = _ref.forceVisibleOnMouseOut,
65
+ isPersistent = _ref.isPersistent,
65
66
  shouldUseDisplayContents = _ref.shouldUseDisplayContents;
66
67
  var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['typeAhead', 'blockControls', 'editorViewMode', 'userIntent', 'showDiff'], function (states) {
67
68
  var _states$typeAheadStat, _states$blockControls, _states$blockControls2, _states$blockControls3, _states$editorViewMod, _states$userIntentSta, _states$showDiffState, _states$blockControls4;
@@ -99,9 +100,12 @@ var VisibilityContainer = exports.VisibilityContainer = function VisibilityConta
99
100
  // When forceVisibleOnMouseOut is true (e.g. drag handle focused via keyboard Shift+Ctrl+H),
100
101
  // override the mouse-out condition so the control stays visible regardless of mouse position.
101
102
  var shouldHideWhenMouseOut = forceVisibleOnMouseOut ? false : hideOnMouseOut;
102
- var shouldHideImmediate = isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
103
+ // Persistent controls (e.g. an AI suggestion icon on every qualifying node) aren't hover-driven,
104
+ // so none of the hover/typing/mouse-out/diff-review reasons below apply to them — they're never
105
+ // hidden by this container.
106
+ var shouldHideImmediate = !isPersistent && (isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
103
107
  // EDITOR-7926: hide the drag handle while a diff is on screen or a suggestion card is open.
104
- (isDisplayingDiff || userIntent === 'reviewing') && (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden;
108
+ (isDisplayingDiff || userIntent === 'reviewing') && (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden);
105
109
 
106
110
  // Delay hiding the right control in view mode to reduce flickering when moving from block
107
111
  // toward the right-edge button (avoids rapid show/hide as mouse crosses boundaries).
@@ -36,7 +36,6 @@ export const blockControlsPlugin = ({
36
36
  const rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
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
- const surfaceNodePositionsEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_collapsible_headings');
40
39
  const legacyBlockControlsEnabled = !registryBlockControlsEnabled;
41
40
  const rightSurfaceEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_block_control_right_surface');
42
41
  if (registryBlockControlsEnabled) {
@@ -144,7 +143,7 @@ export const blockControlsPlugin = ({
144
143
  plugin: ({
145
144
  getIntl,
146
145
  nodeViewPortalProviderAPI
147
- }) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, surfaceNodePositionsEnabled, rightSurfaceEnabled)
146
+ }) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled)
148
147
  }];
149
148
  if (editorExperiment('platform_editor_controls', 'variant1')) {
150
149
  pmPlugins.push({
@@ -440,7 +439,7 @@ export const blockControlsPlugin = ({
440
439
  isEditing: (_interactionTrackingP = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
441
440
  isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState10 = key.getState(editorState)) === null || _key$getState10 === void 0 ? void 0 : _key$getState10.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
442
441
  };
443
- if (surfaceNodePositionsEnabled) {
442
+ if (registryBlockControlsEnabled) {
444
443
  var _key$getState$surface, _key$getState11;
445
444
  sharedState.surfaceNodePositions = (_key$getState$surface = (_key$getState11 = key.getState(editorState)) === null || _key$getState11 === void 0 ? void 0 : _key$getState11.surfaceNodePositions) !== null && _key$getState$surface !== void 0 ? _key$getState$surface : [];
446
445
  }
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
3
- import uuid from 'uuid';
3
+ import { v4 as uuid } from 'uuid';
4
4
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
5
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
6
  import { unmountFromMountPoint } from './react-root-registry';
@@ -1,6 +1,6 @@
1
1
  import { createElement } from 'react';
2
2
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
3
- import uuid from 'uuid';
3
+ import { v4 as uuid } from 'uuid';
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
6
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -1,7 +1,7 @@
1
1
  import { createElement } from 'react';
2
2
  import memoizeOne from 'memoize-one';
3
3
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
4
- import uuid from 'uuid';
4
+ import { v4 as uuid } from 'uuid';
5
5
  import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
6
6
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
7
7
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
@@ -1,6 +1,6 @@
1
1
  import { createElement } from 'react';
2
2
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
3
- import uuid from 'uuid';
3
+ import { v4 as uuid } from 'uuid';
4
4
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
5
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
6
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -784,7 +784,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
784
784
  isSelectedViaDragHandle: isSelectedViaDragHandleNew
785
785
  };
786
786
  };
787
- export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, legacyDragHandleEnabled = true, surfaceNodePositionsEnabled = false, rightSurfaceEnabled = false) => {
787
+ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, legacyDragHandleEnabled = true, rightSurfaceEnabled = false) => {
788
788
  var _api$uiControlRegistr, _api$uiControlRegistr2, _api$uiControlRegistr3, _api$uiControlRegistr4;
789
789
  const {
790
790
  formatMessage
@@ -793,6 +793,9 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
793
793
  exposure: true
794
794
  });
795
795
  const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
796
+ // Mirrors `registryBlockControlsEnabled` in blockControlsPlugin.tsx: `legacyDragHandleEnabled` is
797
+ // only false once that gate is on.
798
+ const surfaceNodePositionsEnabled = !legacyDragHandleEnabled;
796
799
  const flags = {
797
800
  legacyDragHandleEnabled,
798
801
  surfaceNodePositionsEnabled,
@@ -7,6 +7,7 @@ import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-contr
7
7
  import { SurfaceRenderer, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
8
8
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
9
9
  import { getBlockControlsSurfaceControlSide } from './block-controls-surface-context';
10
+ import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
10
11
  import { VisibilityContainer } from './visibility-container';
11
12
  const leftSurfaceOuterStyles = null;
12
13
  const leftSurfaceRowStyles = null;
@@ -28,11 +29,12 @@ export const BlockControlsLeftSurface = ({
28
29
  if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
29
30
  return null;
30
31
  }
31
- const surface = /*#__PURE__*/React.createElement(SurfaceRenderer, {
32
- components: components,
33
- surface: BLOCK_CONTROLS_LEFT_SURFACE,
34
- surfaceContext: surfaceContext
35
- });
32
+ const {
33
+ hoverOnlyComponents,
34
+ persistentComponents
35
+ } = partitionComponentsByPersistence(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
36
+ const willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
37
+ const willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
36
38
  const isSticky = placement.height !== undefined;
37
39
  return /*#__PURE__*/React.createElement("div", {
38
40
  "data-editor-block-controls-surface": true,
@@ -43,10 +45,23 @@ export const BlockControlsLeftSurface = ({
43
45
  className: ax(["_kqswstnw _1pbyb4wl"])
44
46
  }, /*#__PURE__*/React.createElement("div", {
45
47
  className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
46
- }, /*#__PURE__*/React.createElement(VisibilityContainer, {
48
+ }, willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
49
+ api: api,
50
+ controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
51
+ forceVisibleOnMouseOut: forceVisibleOnMouseOut,
52
+ shouldUseDisplayContents: true
53
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
54
+ components: persistentComponents,
55
+ surface: BLOCK_CONTROLS_LEFT_SURFACE,
56
+ surfaceContext: surfaceContext
57
+ })), willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
47
58
  api: api,
48
59
  controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
49
60
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
50
61
  shouldUseDisplayContents: true
51
- }, surface)));
62
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
63
+ components: hoverOnlyComponents,
64
+ surface: BLOCK_CONTROLS_LEFT_SURFACE,
65
+ surfaceContext: surfaceContext
66
+ }))));
52
67
  };
@@ -4,6 +4,7 @@ import { ax, ix } from "@compiled/react/runtime";
4
4
  import React from 'react';
5
5
  import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
6
6
  import { SurfaceRenderer, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
7
+ import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
7
8
  import { VisibilityContainer } from './visibility-container';
8
9
  const rightSurfaceOuterStyles = null;
9
10
  const rightSurfaceRowStyles = null;
@@ -25,11 +26,12 @@ export const BlockControlsRightSurface = ({
25
26
  if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
26
27
  return null;
27
28
  }
28
- const surface = /*#__PURE__*/React.createElement(SurfaceRenderer, {
29
- components: components,
30
- surface: BLOCK_CONTROLS_RIGHT_SURFACE,
31
- surfaceContext: surfaceContext
32
- });
29
+ const {
30
+ hoverOnlyComponents,
31
+ persistentComponents
32
+ } = partitionComponentsByPersistence(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
33
+ const willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
34
+ const willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
33
35
  const isSticky = placement.height !== undefined;
34
36
  return /*#__PURE__*/React.createElement("div", {
35
37
  "data-editor-block-controls-surface": true,
@@ -40,10 +42,23 @@ export const BlockControlsRightSurface = ({
40
42
  className: ax(["_kqswstnw _1pbyb4wl"])
41
43
  }, /*#__PURE__*/React.createElement("div", {
42
44
  className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
43
- }, /*#__PURE__*/React.createElement(VisibilityContainer, {
45
+ }, willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
46
+ api: api,
47
+ controlSide: "right",
48
+ isPersistent: true,
49
+ shouldUseDisplayContents: true
50
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
51
+ components: persistentComponents,
52
+ surface: BLOCK_CONTROLS_RIGHT_SURFACE,
53
+ surfaceContext: surfaceContext
54
+ })), willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
44
55
  api: api,
45
56
  controlSide: "right",
46
57
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
47
58
  shouldUseDisplayContents: true
48
- }, surface)));
59
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
60
+ components: hoverOnlyComponents,
61
+ surface: BLOCK_CONTROLS_RIGHT_SURFACE,
62
+ surfaceContext: surfaceContext
63
+ }))));
49
64
  };
@@ -13,11 +13,17 @@ export const ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = '--editor-block-controls
13
13
  export const DRAG_HANDLE_HEIGHT = 24;
14
14
  export const DRAG_HANDLE_BORDER_RADIUS = 4;
15
15
  export const DRAG_HANDLE_ZINDEX = akRichMediaResizeZIndex + akEditorUnitZIndex; //place above legacy resizer
16
- export const DRAG_HANDLE_DEFAULT_GAP = 8;
16
+ const LEGACY_DRAG_HANDLE_DEFAULT_GAP = 8;
17
+ const MIGRATED_DRAG_HANDLE_DEFAULT_GAP = 12;
17
18
  export const DRAG_HANDLE_NARROW_GAP = 4;
18
19
  export const DRAG_HANDLE_MAX_GAP = 12;
19
20
  export const DRAG_HANDLE_SYNCED_BLOCK_GAP = 2.5;
20
21
  export const DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = DRAG_HANDLE_WIDTH + DRAG_HANDLE_MAX_GAP;
22
+
23
+ // Non-resizable/default-sized nodes get the same gap as resizable/breakout nodes
24
+ // (DRAG_HANDLE_MAX_GAP) once the registry-backed surfaces are on; kept at the legacy value
25
+ // otherwise to avoid an unrelated visual change for consumers still on the old decoration path.
26
+ const getDragHandleDefaultGap = () => isExperimentEnabled('platform_editor_block_control_migration') ? MIGRATED_DRAG_HANDLE_DEFAULT_GAP : LEGACY_DRAG_HANDLE_DEFAULT_GAP;
21
27
  export const DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = 4 + 2; // 4px for the divider vertical padding and 2px for the divider height
22
28
  export const DRAG_HANDLE_H1_TOP_ADJUSTMENT = 5;
23
29
  export const DRAG_HANDLE_H2_TOP_ADJUSTMENT = 2;
@@ -68,12 +74,12 @@ export const dragHandleGap = (nodeType, parentNodeType) => {
68
74
  }
69
75
  }
70
76
  if (nodeType === 'layoutSection') {
71
- return DRAG_HANDLE_DEFAULT_GAP + 20;
77
+ return getDragHandleDefaultGap() + 20;
72
78
  }
73
79
  if (nodeTypeExcludeList.includes(nodeType)) {
74
80
  return DRAG_HANDLE_MAX_GAP;
75
81
  }
76
- return DRAG_HANDLE_DEFAULT_GAP;
82
+ return getDragHandleDefaultGap();
77
83
  };
78
84
 
79
85
  // use for returning gap only for root level elements
@@ -94,7 +100,7 @@ export const rootElementGap = nodeType => {
94
100
  if (nodeType === 'layoutSection') {
95
101
  return DRAG_HANDLE_MAX_GAP + 12;
96
102
  }
97
- return DRAG_HANDLE_DEFAULT_GAP;
103
+ return getDragHandleDefaultGap();
98
104
  };
99
105
  export const getNestedNodeLeftPaddingMargin = nodeType => {
100
106
  switch (nodeType) {
@@ -0,0 +1,48 @@
1
+ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls/block-control-ui-context';
2
+ import { getComponentIdentity, resolveSurface, willComponentRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
3
+ import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
4
+ /**
5
+ * Split registered components into two groups:
6
+ * those that should be rendered persistently and those that should only be rendered on hover.
7
+ */
8
+ export const partitionComponentsByPersistence = (components, surface, surfaceContext) => {
9
+ const {
10
+ childrenMap,
11
+ root,
12
+ topLevelChildren
13
+ } = resolveSurface(components, surface);
14
+ if (!root || !topLevelChildren || topLevelChildren.length === 0) {
15
+ return {
16
+ hoverOnlyComponents: [],
17
+ persistentComponents: components
18
+ };
19
+ }
20
+ const context = surfaceContext === null || surfaceContext === void 0 ? void 0 : surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT);
21
+ const storedSurfaceContext = context ? createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, {
22
+ activeNode: undefined,
23
+ rootNode: context.targetNode,
24
+ targetNode: context.targetNode
25
+ }) : undefined;
26
+ const isLeaf = component => {
27
+ const children = childrenMap.get(getComponentIdentity(component));
28
+ return !children || children.length === 0;
29
+ };
30
+ const persistentComponents = [];
31
+ const hoverOnlyComponents = [];
32
+ for (const component of components) {
33
+ if (!isLeaf(component)) {
34
+ persistentComponents.push(component);
35
+ hoverOnlyComponents.push(component);
36
+ continue;
37
+ }
38
+ if (willComponentRender(component, childrenMap, storedSurfaceContext)) {
39
+ persistentComponents.push(component);
40
+ } else {
41
+ hoverOnlyComponents.push(component);
42
+ }
43
+ }
44
+ return {
45
+ hoverOnlyComponents,
46
+ persistentComponents
47
+ };
48
+ };
@@ -51,6 +51,7 @@ export const VisibilityContainer = ({
51
51
  children,
52
52
  controlSide,
53
53
  forceVisibleOnMouseOut,
54
+ isPersistent,
54
55
  shouldUseDisplayContents
55
56
  }) => {
56
57
  const {
@@ -90,9 +91,12 @@ export const VisibilityContainer = ({
90
91
  // When forceVisibleOnMouseOut is true (e.g. drag handle focused via keyboard Shift+Ctrl+H),
91
92
  // override the mouse-out condition so the control stays visible regardless of mouse position.
92
93
  const shouldHideWhenMouseOut = forceVisibleOnMouseOut ? false : hideOnMouseOut;
93
- const shouldHideImmediate = isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
94
+ // Persistent controls (e.g. an AI suggestion icon on every qualifying node) aren't hover-driven,
95
+ // so none of the hover/typing/mouse-out/diff-review reasons below apply to them — they're never
96
+ // hidden by this container.
97
+ const shouldHideImmediate = !isPersistent && (isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
94
98
  // EDITOR-7926: hide the drag handle while a diff is on screen or a suggestion card is open.
95
- (isDisplayingDiff || userIntent === 'reviewing') && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden;
99
+ (isDisplayingDiff || userIntent === 'reviewing') && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden);
96
100
 
97
101
  // Delay hiding the right control in view mode to reduce flickering when moving from block
98
102
  // toward the right-edge button (avoids rapid show/hide as mouse crosses boundaries).
@@ -39,7 +39,6 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
39
39
  var rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
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
- var surfaceNodePositionsEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_collapsible_headings');
43
42
  var legacyBlockControlsEnabled = !registryBlockControlsEnabled;
44
43
  var rightSurfaceEnabled = registryBlockControlsEnabled && isExperimentEnabled('platform_editor_block_control_right_surface');
45
44
  if (registryBlockControlsEnabled) {
@@ -139,7 +138,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
139
138
  plugin: function plugin(_ref2) {
140
139
  var getIntl = _ref2.getIntl,
141
140
  nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
142
- return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, surfaceNodePositionsEnabled, rightSurfaceEnabled);
141
+ return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled, rightSurfaceEnabled);
143
142
  }
144
143
  }];
145
144
  if (editorExperiment('platform_editor_controls', 'variant1')) {
@@ -441,7 +440,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
441
440
  isEditing: (_interactionTrackingP = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP === void 0 ? void 0 : _interactionTrackingP.isEditing,
442
441
  isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState10 = key.getState(editorState)) === null || _key$getState10 === void 0 ? void 0 : _key$getState10.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
443
442
  };
444
- if (surfaceNodePositionsEnabled) {
443
+ if (registryBlockControlsEnabled) {
445
444
  var _key$getState$surface, _key$getState11;
446
445
  sharedState.surfaceNodePositions = (_key$getState$surface = (_key$getState11 = key.getState(editorState)) === null || _key$getState11 === void 0 ? void 0 : _key$getState11.surfaceNodePositions) !== null && _key$getState$surface !== void 0 ? _key$getState$surface : [];
447
446
  }
@@ -2,7 +2,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
5
- import uuid from 'uuid';
5
+ import { v4 as uuid } from 'uuid';
6
6
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { unmountFromMountPoint } from './react-root-registry';
@@ -1,7 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { createElement } from 'react';
3
3
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
4
- import uuid from 'uuid';
4
+ import { v4 as uuid } from 'uuid';
5
5
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
6
6
  import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -5,7 +5,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
5
5
  import { createElement } from 'react';
6
6
  import memoizeOne from 'memoize-one';
7
7
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
8
- import uuid from 'uuid';
8
+ import { v4 as uuid } from 'uuid';
9
9
  import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
10
10
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
11
11
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
@@ -1,7 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { createElement } from 'react';
3
3
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
4
- import uuid from 'uuid';
4
+ import { v4 as uuid } from 'uuid';
5
5
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
6
6
  import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -884,14 +884,16 @@ export var createPlugin = function createPlugin(api, getIntl, nodeViewPortalProv
884
884
  var rightSideControlsEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
885
885
  var quickInsertButtonEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
886
886
  var legacyDragHandleEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true;
887
- var surfaceNodePositionsEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
888
- var rightSurfaceEnabled = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
887
+ var rightSurfaceEnabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
889
888
  var _getIntl = getIntl(),
890
889
  formatMessage = _getIntl.formatMessage;
891
890
  var isAdvancedLayoutEnabled = editorExperiment('advanced_layouts', true, {
892
891
  exposure: true
893
892
  });
894
893
  var toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
894
+ // Mirrors `registryBlockControlsEnabled` in blockControlsPlugin.tsx: `legacyDragHandleEnabled` is
895
+ // only false once that gate is on.
896
+ var surfaceNodePositionsEnabled = !legacyDragHandleEnabled;
895
897
  var flags = {
896
898
  legacyDragHandleEnabled: legacyDragHandleEnabled,
897
899
  surfaceNodePositionsEnabled: surfaceNodePositionsEnabled,
@@ -7,6 +7,7 @@ import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-contr
7
7
  import { SurfaceRenderer, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
8
8
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
9
9
  import { getBlockControlsSurfaceControlSide } from './block-controls-surface-context';
10
+ import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
10
11
  import { VisibilityContainer } from './visibility-container';
11
12
  var leftSurfaceOuterStyles = null;
12
13
  var leftSurfaceRowStyles = null;
@@ -27,11 +28,11 @@ export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref) {
27
28
  if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
28
29
  return null;
29
30
  }
30
- var surface = /*#__PURE__*/React.createElement(SurfaceRenderer, {
31
- components: components,
32
- surface: BLOCK_CONTROLS_LEFT_SURFACE,
33
- surfaceContext: surfaceContext
34
- });
31
+ var _partitionComponentsB = partitionComponentsByPersistence(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext),
32
+ hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
33
+ persistentComponents = _partitionComponentsB.persistentComponents;
34
+ var willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
35
+ var willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
35
36
  var isSticky = placement.height !== undefined;
36
37
  return /*#__PURE__*/React.createElement("div", {
37
38
  "data-editor-block-controls-surface": true,
@@ -42,10 +43,23 @@ export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref) {
42
43
  className: ax(["_kqswstnw _1pbyb4wl"])
43
44
  }, /*#__PURE__*/React.createElement("div", {
44
45
  className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
45
- }, /*#__PURE__*/React.createElement(VisibilityContainer, {
46
+ }, willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
47
+ api: api,
48
+ controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
49
+ forceVisibleOnMouseOut: forceVisibleOnMouseOut,
50
+ shouldUseDisplayContents: true
51
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
52
+ components: persistentComponents,
53
+ surface: BLOCK_CONTROLS_LEFT_SURFACE,
54
+ surfaceContext: surfaceContext
55
+ })), willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
46
56
  api: api,
47
57
  controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
48
58
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
49
59
  shouldUseDisplayContents: true
50
- }, surface)));
60
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
61
+ components: hoverOnlyComponents,
62
+ surface: BLOCK_CONTROLS_LEFT_SURFACE,
63
+ surfaceContext: surfaceContext
64
+ }))));
51
65
  };
@@ -4,6 +4,7 @@ import { ax, ix } from "@compiled/react/runtime";
4
4
  import React from 'react';
5
5
  import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
6
6
  import { SurfaceRenderer, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
7
+ import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
7
8
  import { VisibilityContainer } from './visibility-container';
8
9
  var rightSurfaceOuterStyles = null;
9
10
  var rightSurfaceRowStyles = null;
@@ -24,11 +25,11 @@ export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref)
24
25
  if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
25
26
  return null;
26
27
  }
27
- var surface = /*#__PURE__*/React.createElement(SurfaceRenderer, {
28
- components: components,
29
- surface: BLOCK_CONTROLS_RIGHT_SURFACE,
30
- surfaceContext: surfaceContext
31
- });
28
+ var _partitionComponentsB = partitionComponentsByPersistence(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext),
29
+ hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
30
+ persistentComponents = _partitionComponentsB.persistentComponents;
31
+ var willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
32
+ var willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
32
33
  var isSticky = placement.height !== undefined;
33
34
  return /*#__PURE__*/React.createElement("div", {
34
35
  "data-editor-block-controls-surface": true,
@@ -39,10 +40,23 @@ export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref)
39
40
  className: ax(["_kqswstnw _1pbyb4wl"])
40
41
  }, /*#__PURE__*/React.createElement("div", {
41
42
  className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
42
- }, /*#__PURE__*/React.createElement(VisibilityContainer, {
43
+ }, willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
44
+ api: api,
45
+ controlSide: "right",
46
+ isPersistent: true,
47
+ shouldUseDisplayContents: true
48
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
49
+ components: persistentComponents,
50
+ surface: BLOCK_CONTROLS_RIGHT_SURFACE,
51
+ surfaceContext: surfaceContext
52
+ })), willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
43
53
  api: api,
44
54
  controlSide: "right",
45
55
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
46
56
  shouldUseDisplayContents: true
47
- }, surface)));
57
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
58
+ components: hoverOnlyComponents,
59
+ surface: BLOCK_CONTROLS_RIGHT_SURFACE,
60
+ surfaceContext: surfaceContext
61
+ }))));
48
62
  };
@@ -16,11 +16,19 @@ export var ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = '--editor-block-controls-a
16
16
  export var DRAG_HANDLE_HEIGHT = 24;
17
17
  export var DRAG_HANDLE_BORDER_RADIUS = 4;
18
18
  export var DRAG_HANDLE_ZINDEX = akRichMediaResizeZIndex + akEditorUnitZIndex; //place above legacy resizer
19
- export var DRAG_HANDLE_DEFAULT_GAP = 8;
19
+ var LEGACY_DRAG_HANDLE_DEFAULT_GAP = 8;
20
+ var MIGRATED_DRAG_HANDLE_DEFAULT_GAP = 12;
20
21
  export var DRAG_HANDLE_NARROW_GAP = 4;
21
22
  export var DRAG_HANDLE_MAX_GAP = 12;
22
23
  export var DRAG_HANDLE_SYNCED_BLOCK_GAP = 2.5;
23
24
  export var DRAG_HANDLE_MAX_WIDTH_PLUS_GAP = DRAG_HANDLE_WIDTH + DRAG_HANDLE_MAX_GAP;
25
+
26
+ // Non-resizable/default-sized nodes get the same gap as resizable/breakout nodes
27
+ // (DRAG_HANDLE_MAX_GAP) once the registry-backed surfaces are on; kept at the legacy value
28
+ // otherwise to avoid an unrelated visual change for consumers still on the old decoration path.
29
+ var getDragHandleDefaultGap = function getDragHandleDefaultGap() {
30
+ return isExperimentEnabled('platform_editor_block_control_migration') ? MIGRATED_DRAG_HANDLE_DEFAULT_GAP : LEGACY_DRAG_HANDLE_DEFAULT_GAP;
31
+ };
24
32
  export var DRAG_HANDLE_DIVIDER_TOP_ADJUSTMENT = 4 + 2; // 4px for the divider vertical padding and 2px for the divider height
25
33
  export var DRAG_HANDLE_H1_TOP_ADJUSTMENT = 5;
26
34
  export var DRAG_HANDLE_H2_TOP_ADJUSTMENT = 2;
@@ -71,12 +79,12 @@ export var dragHandleGap = function dragHandleGap(nodeType, parentNodeType) {
71
79
  }
72
80
  }
73
81
  if (nodeType === 'layoutSection') {
74
- return DRAG_HANDLE_DEFAULT_GAP + 20;
82
+ return getDragHandleDefaultGap() + 20;
75
83
  }
76
84
  if (nodeTypeExcludeList.includes(nodeType)) {
77
85
  return DRAG_HANDLE_MAX_GAP;
78
86
  }
79
- return DRAG_HANDLE_DEFAULT_GAP;
87
+ return getDragHandleDefaultGap();
80
88
  };
81
89
 
82
90
  // use for returning gap only for root level elements
@@ -97,7 +105,7 @@ export var rootElementGap = function rootElementGap(nodeType) {
97
105
  if (nodeType === 'layoutSection') {
98
106
  return DRAG_HANDLE_MAX_GAP + 12;
99
107
  }
100
- return DRAG_HANDLE_DEFAULT_GAP;
108
+ return getDragHandleDefaultGap();
101
109
  };
102
110
  export var getNestedNodeLeftPaddingMargin = function getNestedNodeLeftPaddingMargin(nodeType) {
103
111
  switch (nodeType) {
@@ -0,0 +1,59 @@
1
+ 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; } } }; }
2
+ 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; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls/block-control-ui-context';
5
+ import { getComponentIdentity, resolveSurface, willComponentRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
6
+ import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
7
+ /**
8
+ * Split registered components into two groups:
9
+ * those that should be rendered persistently and those that should only be rendered on hover.
10
+ */
11
+ export var partitionComponentsByPersistence = function partitionComponentsByPersistence(components, surface, surfaceContext) {
12
+ var _resolveSurface = resolveSurface(components, surface),
13
+ childrenMap = _resolveSurface.childrenMap,
14
+ root = _resolveSurface.root,
15
+ topLevelChildren = _resolveSurface.topLevelChildren;
16
+ if (!root || !topLevelChildren || topLevelChildren.length === 0) {
17
+ return {
18
+ hoverOnlyComponents: [],
19
+ persistentComponents: components
20
+ };
21
+ }
22
+ var context = surfaceContext === null || surfaceContext === void 0 ? void 0 : surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT);
23
+ var storedSurfaceContext = context ? createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, {
24
+ activeNode: undefined,
25
+ rootNode: context.targetNode,
26
+ targetNode: context.targetNode
27
+ }) : undefined;
28
+ var isLeaf = function isLeaf(component) {
29
+ var children = childrenMap.get(getComponentIdentity(component));
30
+ return !children || children.length === 0;
31
+ };
32
+ var persistentComponents = [];
33
+ var hoverOnlyComponents = [];
34
+ var _iterator = _createForOfIteratorHelper(components),
35
+ _step;
36
+ try {
37
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
38
+ var component = _step.value;
39
+ if (!isLeaf(component)) {
40
+ persistentComponents.push(component);
41
+ hoverOnlyComponents.push(component);
42
+ continue;
43
+ }
44
+ if (willComponentRender(component, childrenMap, storedSurfaceContext)) {
45
+ persistentComponents.push(component);
46
+ } else {
47
+ hoverOnlyComponents.push(component);
48
+ }
49
+ }
50
+ } catch (err) {
51
+ _iterator.e(err);
52
+ } finally {
53
+ _iterator.f();
54
+ }
55
+ return {
56
+ hoverOnlyComponents: hoverOnlyComponents,
57
+ persistentComponents: persistentComponents
58
+ };
59
+ };
@@ -51,6 +51,7 @@ export var VisibilityContainer = function VisibilityContainer(_ref) {
51
51
  children = _ref.children,
52
52
  controlSide = _ref.controlSide,
53
53
  forceVisibleOnMouseOut = _ref.forceVisibleOnMouseOut,
54
+ isPersistent = _ref.isPersistent,
54
55
  shouldUseDisplayContents = _ref.shouldUseDisplayContents;
55
56
  var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['typeAhead', 'blockControls', 'editorViewMode', 'userIntent', 'showDiff'], function (states) {
56
57
  var _states$typeAheadStat, _states$blockControls, _states$blockControls2, _states$blockControls3, _states$editorViewMod, _states$userIntentSta, _states$showDiffState, _states$blockControls4;
@@ -88,9 +89,12 @@ export var VisibilityContainer = function VisibilityContainer(_ref) {
88
89
  // When forceVisibleOnMouseOut is true (e.g. drag handle focused via keyboard Shift+Ctrl+H),
89
90
  // override the mouse-out condition so the control stays visible regardless of mouse position.
90
91
  var shouldHideWhenMouseOut = forceVisibleOnMouseOut ? false : hideOnMouseOut;
91
- var shouldHideImmediate = isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
92
+ // Persistent controls (e.g. an AI suggestion icon on every qualifying node) aren't hover-driven,
93
+ // so none of the hover/typing/mouse-out/diff-review reasons below apply to them — they're never
94
+ // hidden by this container.
95
+ var shouldHideImmediate = !isPersistent && (isTypeAheadOpen || isEditing || shouldHideWhenMouseOut || userIntent === 'aiStreaming' ||
92
96
  // EDITOR-7926: hide the drag handle while a diff is on screen or a suggestion card is open.
93
- (isDisplayingDiff || userIntent === 'reviewing') && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden;
97
+ (isDisplayingDiff || userIntent === 'reviewing') && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || sideHidden);
94
98
 
95
99
  // Delay hiding the right control in view mode to reduce flickering when moving from block
96
100
  // toward the right-edge button (avoids rapid show/hide as mouse crosses boundaries).
@@ -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, surfaceNodePositionsEnabled?: 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, rightSurfaceEnabled?: boolean) => SafePlugin<PluginState | {
48
48
  activeDropTargetNode: ActiveDropTargetNode | undefined;
49
49
  activeNode: any;
50
50
  blockMenuOptions: {
@@ -6,7 +6,6 @@ export declare const ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME = "--editor-block-
6
6
  export declare const DRAG_HANDLE_HEIGHT = 24;
7
7
  export declare const DRAG_HANDLE_BORDER_RADIUS = 4;
8
8
  export declare const DRAG_HANDLE_ZINDEX: number;
9
- export declare const DRAG_HANDLE_DEFAULT_GAP = 8;
10
9
  export declare const DRAG_HANDLE_NARROW_GAP = 4;
11
10
  export declare const DRAG_HANDLE_MAX_GAP = 12;
12
11
  export declare const DRAG_HANDLE_SYNCED_BLOCK_GAP = 2.5;
@@ -0,0 +1,15 @@
1
+ import type { RegisterComponent, SurfaceContext } from '@atlaskit/editor-ui-control-model/types';
2
+ type SurfaceIdentifier = {
3
+ key: string;
4
+ type: 'toolbar' | 'menu';
5
+ };
6
+ type PartitionedComponents = {
7
+ hoverOnlyComponents: RegisterComponent[];
8
+ persistentComponents: RegisterComponent[];
9
+ };
10
+ /**
11
+ * Split registered components into two groups:
12
+ * those that should be rendered persistently and those that should only be rendered on hover.
13
+ */
14
+ export declare const partitionComponentsByPersistence: (components: RegisterComponent[], surface: SurfaceIdentifier, surfaceContext: SurfaceContext | undefined) => PartitionedComponents;
15
+ export {};
@@ -11,10 +11,11 @@ interface VisibilityContainerProps {
11
11
  children: React.ReactNode;
12
12
  controlSide?: 'left' | 'right';
13
13
  forceVisibleOnMouseOut?: boolean;
14
+ isPersistent?: boolean;
14
15
  /**
15
16
  * Set when the container should not create its own layout box while its descendants retain theirs.
16
17
  */
17
18
  shouldUseDisplayContents?: boolean;
18
19
  }
19
- export declare const VisibilityContainer: ({ api, children, controlSide, forceVisibleOnMouseOut, shouldUseDisplayContents, }: VisibilityContainerProps) => jsx.JSX.Element;
20
+ export declare const VisibilityContainer: ({ api, children, controlSide, forceVisibleOnMouseOut, isPersistent, shouldUseDisplayContents, }: VisibilityContainerProps) => jsx.JSX.Element;
20
21
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-controls",
3
- "version": "17.3.9",
3
+ "version": "17.3.11",
4
4
  "description": "Block controls plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -34,7 +34,7 @@
34
34
  "@atlaskit/editor-plugin-metrics": "^17.0.0",
35
35
  "@atlaskit/editor-plugin-quick-insert": "^16.2.0",
36
36
  "@atlaskit/editor-plugin-selection": "^16.1.0",
37
- "@atlaskit/editor-plugin-show-diff": "^14.3.0",
37
+ "@atlaskit/editor-plugin-show-diff": "^14.4.0",
38
38
  "@atlaskit/editor-plugin-toolbar": "^13.0.0",
39
39
  "@atlaskit/editor-plugin-type-ahead": "^17.1.0",
40
40
  "@atlaskit/editor-plugin-ui-control-registry": "^10.0.0",
@@ -45,7 +45,7 @@
45
45
  "@atlaskit/editor-tables": "^3.1.0",
46
46
  "@atlaskit/editor-ui-control-model": "^2.9.0",
47
47
  "@atlaskit/icon": "^37.6.0",
48
- "@atlaskit/icon-lab": "^7.7.0",
48
+ "@atlaskit/icon-lab": "^7.8.0",
49
49
  "@atlaskit/link": "^5.1.0",
50
50
  "@atlaskit/platform-feature-experiments": "^0.3.0",
51
51
  "@atlaskit/platform-feature-flags": "^2.2.0",
@@ -64,10 +64,10 @@
64
64
  "bind-event-listener": "^3.0.0",
65
65
  "memoize-one": "^6.0.0",
66
66
  "raf-schd": "^4.0.3",
67
- "uuid": "^3.1.0"
67
+ "uuid": "^11.1.1"
68
68
  },
69
69
  "peerDependencies": {
70
- "@atlaskit/editor-common": "^120.12.0",
70
+ "@atlaskit/editor-common": "^120.13.0",
71
71
  "react": "^18.2.0 || ^19.2.0",
72
72
  "react-dom": "^18.2.0 || ^19.2.0",
73
73
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"