@atlaskit/editor-plugin-block-menu 20.0.2 → 20.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 20.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [`981dd11bb4ed2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/981dd11bb4ed2) -
8
+ Add opt-in target visibility handling to editor popups, and use it to hide the Jira description
9
+ block menu while its originating node is outside the visible viewport. The popup reappears when
10
+ its target returns, preserving an open nested menu, behind the
11
+ `platform_editor_popup_target_visibility` experiment.
12
+ - Updated dependencies
13
+
14
+ ## 20.0.3
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+
3
20
  ## 20.0.2
4
21
 
5
22
  ### Patch Changes
@@ -10,11 +10,14 @@ var _reactIntl = require("react-intl");
10
10
  var _messages = require("@atlaskit/editor-common/messages");
11
11
  var _editorToolbar = require("@atlaskit/editor-toolbar");
12
12
  var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
13
+ var _blockMenuTargetVisibilityContext = require("../block-menu-target-visibility-context");
13
14
  var FallbackNestedMenu = function FallbackNestedMenu(_ref) {
14
15
  var children = _ref.children;
15
16
  var _useIntl = (0, _reactIntl.useIntl)(),
16
17
  formatMessage = _useIntl.formatMessage;
18
+ var targetVisible = (0, _blockMenuTargetVisibilityContext.useBlockMenuTargetVisibility)();
17
19
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
20
+ isPopupVisible: targetVisible,
18
21
  elemBefore: undefined,
19
22
  elemAfter: /*#__PURE__*/_react.default.createElement(_chevronRight.default, {
20
23
  label: "",
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useBlockMenuTargetVisibility = exports.BlockMenuTargetVisibilityProvider = void 0;
7
+ var _react = require("react");
8
+ var BlockMenuTargetVisibilityContext = /*#__PURE__*/(0, _react.createContext)(undefined);
9
+ var BlockMenuTargetVisibilityProvider = exports.BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
10
+ var useBlockMenuTargetVisibility = exports.useBlockMenuTargetVisibility = function useBlockMenuTargetVisibility() {
11
+ return (0, _react.useContext)(BlockMenuTargetVisibilityContext);
12
+ };
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", {
9
9
  exports.default = void 0;
10
10
  require("./block-menu.compiled.css");
11
11
  var _runtime = require("@compiled/react/runtime");
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
12
13
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
14
  var _react = _interopRequireWildcard(require("react"));
14
15
  var _reactIntl = require("react-intl");
@@ -30,7 +31,10 @@ var _redo = require("@atlaskit/prosemirror-history/redo");
30
31
  var _undo = require("@atlaskit/prosemirror-history/undo");
31
32
  var _blockMenuProvider = require("./block-menu-provider");
32
33
  var _BlockMenuRenderer = require("./block-menu-renderer/BlockMenuRenderer");
34
+ var _blockMenuTargetVisibilityContext = require("./block-menu-target-visibility-context");
33
35
  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); }
36
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
37
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
34
38
  var styles = {
35
39
  base: "_2rko12b0 _bfhk1bhr _16qs130s",
36
40
  maxWidthStyles: "_p12fnklw",
@@ -180,17 +184,20 @@ var BlockMenu = function BlockMenu(_ref5) {
180
184
  mountTo = _ref5.mountTo,
181
185
  boundariesElement = _ref5.boundariesElement,
182
186
  scrollableElement = _ref5.scrollableElement;
187
+ var isPopupTargetVisibilityEnabled = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_popup_target_visibility');
183
188
  var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls', 'userIntent'], function (states) {
184
- var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
189
+ var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5;
185
190
  return {
186
191
  menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
187
- isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
188
- isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
192
+ menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
193
+ isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
194
+ isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
189
195
  currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
190
- openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 || (_states$blockControls4 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.openedViaKeyboard
196
+ openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 || (_states$blockControls5 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
191
197
  };
192
198
  }),
193
199
  menuTriggerBy = _useSharedPluginState.menuTriggerBy,
200
+ menuTriggerByNode = _useSharedPluginState.menuTriggerByNode,
194
201
  isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
195
202
  isMenuOpen = _useSharedPluginState.isMenuOpen,
196
203
  currentUserIntent = _useSharedPluginState.currentUserIntent,
@@ -228,6 +235,8 @@ var BlockMenu = function BlockMenu(_ref5) {
228
235
  anchoredToRef.current = menuTriggerBy;
229
236
  }
230
237
  var targetHandleRef = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(_styles.DRAG_HANDLE_SELECTOR);
238
+ var menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
239
+ var visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
231
240
  var closeMenu = _react.default.useCallback(function () {
232
241
  api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
233
242
  var _api$blockControls, _api$userIntent2;
@@ -257,19 +266,71 @@ var BlockMenu = function BlockMenu(_ref5) {
257
266
  _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
258
267
  menuHeight = _React$useState4[0],
259
268
  setMenuHeight = _React$useState4[1];
269
+ var _React$useState5 = _react.default.useState({
270
+ isVisible: undefined,
271
+ restoreFocusTo: null
272
+ }),
273
+ _React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
274
+ targetVisibility = _React$useState6[0],
275
+ setTargetVisibility = _React$useState6[1];
276
+ var targetVisible = targetVisibility.isVisible,
277
+ restoreFocusTo = targetVisibility.restoreFocusTo;
278
+ // CSS visibility can move focus to the document body. Preserve the active menu item so the
279
+ // existing focus-loss guard does not close the menus during a temporary scroll transition.
280
+ var handleTargetVisibilityChanged = _react.default.useCallback(function (isVisible) {
281
+ var _popupRef$current;
282
+ if (isVisible) {
283
+ setTargetVisibility(function (current) {
284
+ return {
285
+ isVisible: true,
286
+ restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
287
+ };
288
+ });
289
+ return;
290
+ }
291
+
292
+ // Capture focus before scheduling the state update so the updater stays pure.
293
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
294
+ var activeElement = document.activeElement;
295
+ var isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(_styles.NESTED_DROPDOWN_MENU) !== null);
296
+ setTargetVisibility({
297
+ isVisible: false,
298
+ restoreFocusTo: isFocusInMenu ? activeElement : null
299
+ });
300
+ }, []);
301
+ _react.default.useLayoutEffect(function () {
302
+ if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
303
+ return;
304
+ }
305
+ var _restoreFocusTo$owner = restoreFocusTo.ownerDocument,
306
+ activeElement = _restoreFocusTo$owner.activeElement,
307
+ body = _restoreFocusTo$owner.body,
308
+ documentElement = _restoreFocusTo$owner.documentElement;
309
+ var focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
310
+ if (restoreFocusTo.isConnected && focusWasLost) {
311
+ restoreFocusTo.focus({
312
+ preventScroll: true
313
+ });
314
+ }
315
+ setTargetVisibility(function (current) {
316
+ return _objectSpread(_objectSpread({}, current), {}, {
317
+ restoreFocusTo: null
318
+ });
319
+ });
320
+ }, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
260
321
  var targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
261
322
  _react.default.useLayoutEffect(function () {
262
- var _popupRef$current;
323
+ var _popupRef$current2;
263
324
  if (!isMenuOpen) {
264
325
  return;
265
326
  }
266
327
  onDropdownOpenChanged(true);
267
- setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
328
+ setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
268
329
  }, [isMenuOpen, onDropdownOpenChanged]);
269
330
 
270
331
  // Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
271
332
  // dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
272
- var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
333
+ var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
273
334
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
274
335
  document.activeElement === targetHandleRef || popupRef.current && (
275
336
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
@@ -340,6 +401,10 @@ var BlockMenu = function BlockMenu(_ref5) {
340
401
  if (!(targetHandleRef instanceof HTMLElement)) {
341
402
  return null;
342
403
  }
404
+ var blockMenuContent = /*#__PURE__*/_react.default.createElement(BlockMenuContent, {
405
+ api: api,
406
+ setRef: setRef
407
+ });
343
408
  return /*#__PURE__*/_react.default.createElement(_errorBoundary.ErrorBoundary, {
344
409
  component: _analytics.ACTION_SUBJECT.BLOCK_MENU,
345
410
  dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
@@ -354,11 +419,14 @@ var BlockMenu = function BlockMenu(_ref5) {
354
419
  boundariesElement: boundariesElement,
355
420
  scrollableElement: scrollableElement,
356
421
  target: targetHandleRef,
422
+ visibilityTarget: visibilityTarget,
357
423
  zIndex: _editorSharedStyles.akEditorFloatingOverlapPanelZIndex,
358
424
  fitWidth: DEFAULT_MENU_WIDTH,
359
425
  fitHeight: menuHeight,
360
426
  preventOverflow: true,
361
- stick: true
427
+ stick: true,
428
+ hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
429
+ onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
362
430
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
363
431
  ,
364
432
  offset: [_styles.DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
@@ -367,10 +435,9 @@ var BlockMenu = function BlockMenu(_ref5) {
367
435
  {
368
436
  initialFocus: undefined
369
437
  } : undefined
370
- }, /*#__PURE__*/_react.default.createElement(BlockMenuContent, {
371
- api: api,
372
- setRef: setRef
373
- })));
438
+ }, isPopupTargetVisibilityEnabled ? /*#__PURE__*/_react.default.createElement(_blockMenuTargetVisibilityContext.BlockMenuTargetVisibilityProvider, {
439
+ value: targetVisible
440
+ }, blockMenuContent) : blockMenuContent));
374
441
  };
375
442
 
376
443
  // eslint-disable-next-line @typescript-eslint/no-restricted-types
@@ -14,6 +14,7 @@ var _editorToolbar = require("@atlaskit/editor-toolbar");
14
14
  var _changes = _interopRequireDefault(require("@atlaskit/icon/core/changes"));
15
15
  var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
16
16
  var _fg = require("@atlaskit/platform-feature-flags/fg");
17
+ var _blockMenuTargetVisibilityContext = require("./block-menu-target-visibility-context");
17
18
  var _consts = require("./consts");
18
19
  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); }
19
20
  var BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
@@ -25,6 +26,7 @@ var FormatMenuComponent = exports.FormatMenuComponent = function FormatMenuCompo
25
26
  children = _ref.children;
26
27
  var _useIntl = (0, _reactIntl.useIntl)(),
27
28
  formatMessage = _useIntl.formatMessage;
29
+ var targetVisible = (0, _blockMenuTargetVisibilityContext.useBlockMenuTargetVisibility)();
28
30
  var formatMenuLabel = _messages.blockMenuMessages.changeFormat;
29
31
  var handleClick = (0, _react.useCallback)(function () {
30
32
  api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
@@ -43,6 +45,7 @@ var FormatMenuComponent = exports.FormatMenuComponent = function FormatMenuCompo
43
45
  });
44
46
  }, [api]);
45
47
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
48
+ isPopupVisible: targetVisible,
46
49
  text: formatMessage(formatMenuLabel),
47
50
  elemBefore: /*#__PURE__*/_react.default.createElement(_changes.default, {
48
51
  label: "",
@@ -3,13 +3,16 @@ import { useIntl } from 'react-intl';
3
3
  import { blockMenuMessages } from '@atlaskit/editor-common/messages';
4
4
  import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
5
5
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
6
+ import { useBlockMenuTargetVisibility } from '../block-menu-target-visibility-context';
6
7
  const FallbackNestedMenu = ({
7
8
  children
8
9
  }) => {
9
10
  const {
10
11
  formatMessage
11
12
  } = useIntl();
13
+ const targetVisible = useBlockMenuTargetVisibility();
12
14
  return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
15
+ isPopupVisible: targetVisible,
13
16
  elemBefore: undefined,
14
17
  elemAfter: /*#__PURE__*/React.createElement(ChevronRightIcon, {
15
18
  label: "",
@@ -0,0 +1,4 @@
1
+ import { createContext, useContext } from 'react';
2
+ const BlockMenuTargetVisibilityContext = /*#__PURE__*/createContext(undefined);
3
+ export const BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
4
+ export const useBlockMenuTargetVisibility = () => useContext(BlockMenuTargetVisibilityContext);
@@ -21,6 +21,7 @@ import { redo } from '@atlaskit/prosemirror-history/redo';
21
21
  import { undo } from '@atlaskit/prosemirror-history/undo';
22
22
  import { useBlockMenu } from './block-menu-provider';
23
23
  import { BlockMenuRenderer } from './block-menu-renderer/BlockMenuRenderer';
24
+ import { BlockMenuTargetVisibilityProvider } from './block-menu-target-visibility-context';
24
25
  const styles = {
25
26
  base: "_2rko12b0 _bfhk1bhr _16qs130s",
26
27
  maxWidthStyles: "_p12fnklw",
@@ -168,20 +169,23 @@ const BlockMenu = ({
168
169
  scrollableElement
169
170
  }) => {
170
171
  var _openMenuHandleRef$cu, _editorView$dom, _ref2, _api$analytics2;
172
+ const isPopupTargetVisibilityEnabled = isExperimentEnabled('platform_editor_popup_target_visibility');
171
173
  const {
172
174
  menuTriggerBy,
175
+ menuTriggerByNode,
173
176
  isSelectedViaDragHandle,
174
177
  isMenuOpen,
175
178
  currentUserIntent,
176
179
  openedViaKeyboard
177
180
  } = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], states => {
178
- var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4, _states$blockControls5;
181
+ var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5, _states$blockControls6;
179
182
  return {
180
183
  menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
181
- isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
182
- isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
184
+ menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
185
+ isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
186
+ isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
183
187
  currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
184
- openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : (_states$blockControls5 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
188
+ openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 ? void 0 : (_states$blockControls6 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls6 === void 0 ? void 0 : _states$blockControls6.openedViaKeyboard
185
189
  };
186
190
  });
187
191
  const {
@@ -213,6 +217,8 @@ const BlockMenu = ({
213
217
  anchoredToRef.current = menuTriggerBy;
214
218
  }
215
219
  const targetHandleRef = isExperimentEnabled('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 ? void 0 : (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
220
+ const menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
221
+ const visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
216
222
  const closeMenu = React.useCallback(() => {
217
223
  api === null || api === void 0 ? void 0 : api.core.actions.execute(({
218
224
  tr
@@ -240,19 +246,68 @@ const BlockMenu = ({
240
246
  const prevIsMenuOpenRef = useRef(false);
241
247
  const popupRef = useRef(undefined);
242
248
  const [menuHeight, setMenuHeight] = React.useState(0);
249
+ const [targetVisibility, setTargetVisibility] = React.useState({
250
+ isVisible: undefined,
251
+ restoreFocusTo: null
252
+ });
253
+ const {
254
+ isVisible: targetVisible,
255
+ restoreFocusTo
256
+ } = targetVisibility;
257
+ // CSS visibility can move focus to the document body. Preserve the active menu item so the
258
+ // existing focus-loss guard does not close the menus during a temporary scroll transition.
259
+ const handleTargetVisibilityChanged = React.useCallback(isVisible => {
260
+ var _popupRef$current;
261
+ if (isVisible) {
262
+ setTargetVisibility(current => ({
263
+ isVisible: true,
264
+ restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
265
+ }));
266
+ return;
267
+ }
268
+
269
+ // Capture focus before scheduling the state update so the updater stays pure.
270
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
271
+ const activeElement = document.activeElement;
272
+ const isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(NESTED_DROPDOWN_MENU) !== null);
273
+ setTargetVisibility({
274
+ isVisible: false,
275
+ restoreFocusTo: isFocusInMenu ? activeElement : null
276
+ });
277
+ }, []);
278
+ React.useLayoutEffect(() => {
279
+ if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
280
+ return;
281
+ }
282
+ const {
283
+ activeElement,
284
+ body,
285
+ documentElement
286
+ } = restoreFocusTo.ownerDocument;
287
+ const focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
288
+ if (restoreFocusTo.isConnected && focusWasLost) {
289
+ restoreFocusTo.focus({
290
+ preventScroll: true
291
+ });
292
+ }
293
+ setTargetVisibility(current => ({
294
+ ...current,
295
+ restoreFocusTo: null
296
+ }));
297
+ }, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
243
298
  const targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
244
299
  React.useLayoutEffect(() => {
245
- var _popupRef$current;
300
+ var _popupRef$current2;
246
301
  if (!isMenuOpen) {
247
302
  return;
248
303
  }
249
304
  onDropdownOpenChanged(true);
250
- setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
305
+ setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
251
306
  }, [isMenuOpen, onDropdownOpenChanged]);
252
307
 
253
308
  // Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
254
309
  // dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
255
- const hasFocus = (_ref2 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
310
+ const hasFocus = (_ref2 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
256
311
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
257
312
  document.activeElement === targetHandleRef || popupRef.current && (
258
313
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
@@ -323,6 +378,10 @@ const BlockMenu = ({
323
378
  if (!(targetHandleRef instanceof HTMLElement)) {
324
379
  return null;
325
380
  }
381
+ const blockMenuContent = /*#__PURE__*/React.createElement(BlockMenuContent, {
382
+ api: api,
383
+ setRef: setRef
384
+ });
326
385
  return /*#__PURE__*/React.createElement(ErrorBoundary, {
327
386
  component: ACTION_SUBJECT.BLOCK_MENU,
328
387
  dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
@@ -337,11 +396,14 @@ const BlockMenu = ({
337
396
  boundariesElement: boundariesElement,
338
397
  scrollableElement: scrollableElement,
339
398
  target: targetHandleRef,
399
+ visibilityTarget: visibilityTarget,
340
400
  zIndex: akEditorFloatingOverlapPanelZIndex,
341
401
  fitWidth: DEFAULT_MENU_WIDTH,
342
402
  fitHeight: menuHeight,
343
403
  preventOverflow: true,
344
- stick: true
404
+ stick: true,
405
+ hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
406
+ onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
345
407
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
346
408
  ,
347
409
  offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
@@ -350,10 +412,9 @@ const BlockMenu = ({
350
412
  {
351
413
  initialFocus: undefined
352
414
  } : undefined
353
- }, /*#__PURE__*/React.createElement(BlockMenuContent, {
354
- api: api,
355
- setRef: setRef
356
- })));
415
+ }, isPopupTargetVisibilityEnabled ? /*#__PURE__*/React.createElement(BlockMenuTargetVisibilityProvider, {
416
+ value: targetVisible
417
+ }, blockMenuContent) : blockMenuContent));
357
418
  };
358
419
 
359
420
  // eslint-disable-next-line @typescript-eslint/no-restricted-types
@@ -6,6 +6,7 @@ import { ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
6
6
  import ChangesIcon from '@atlaskit/icon/core/changes';
7
7
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
8
8
  import { fg } from '@atlaskit/platform-feature-flags/fg';
9
+ import { useBlockMenuTargetVisibility } from './block-menu-target-visibility-context';
9
10
  import { BLOCK_MENU_ITEM_NAME } from './consts';
10
11
  const BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
11
12
  const shouldIgnoreBlockMenuTransformSpotlightCloseEvent = event => event.target instanceof Element && event.target.closest(BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR) !== null;
@@ -16,6 +17,7 @@ export const FormatMenuComponent = ({
16
17
  const {
17
18
  formatMessage
18
19
  } = useIntl();
20
+ const targetVisible = useBlockMenuTargetVisibility();
19
21
  const formatMenuLabel = blockMenuMessages.changeFormat;
20
22
  const handleClick = useCallback(() => {
21
23
  api === null || api === void 0 ? void 0 : api.core.actions.execute(({
@@ -35,6 +37,7 @@ export const FormatMenuComponent = ({
35
37
  });
36
38
  }, [api]);
37
39
  return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
40
+ isPopupVisible: targetVisible,
38
41
  text: formatMessage(formatMenuLabel),
39
42
  elemBefore: /*#__PURE__*/React.createElement(ChangesIcon, {
40
43
  label: "",
@@ -3,11 +3,14 @@ import { useIntl } from 'react-intl';
3
3
  import { blockMenuMessages } from '@atlaskit/editor-common/messages';
4
4
  import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
5
5
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
6
+ import { useBlockMenuTargetVisibility } from '../block-menu-target-visibility-context';
6
7
  var FallbackNestedMenu = function FallbackNestedMenu(_ref) {
7
8
  var children = _ref.children;
8
9
  var _useIntl = useIntl(),
9
10
  formatMessage = _useIntl.formatMessage;
11
+ var targetVisible = useBlockMenuTargetVisibility();
10
12
  return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
13
+ isPopupVisible: targetVisible,
11
14
  elemBefore: undefined,
12
15
  elemAfter: /*#__PURE__*/React.createElement(ChevronRightIcon, {
13
16
  label: "",
@@ -0,0 +1,6 @@
1
+ import { createContext, useContext } from 'react';
2
+ var BlockMenuTargetVisibilityContext = /*#__PURE__*/createContext(undefined);
3
+ export var BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
4
+ export var useBlockMenuTargetVisibility = function useBlockMenuTargetVisibility() {
5
+ return useContext(BlockMenuTargetVisibilityContext);
6
+ };
@@ -1,7 +1,10 @@
1
1
  /* block-menu.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
3
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
4
  import "./block-menu.compiled.css";
4
5
  import { ax, ix } from "@compiled/react/runtime";
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
8
  import React, { useContext, useEffect, useRef } from 'react';
6
9
  import { injectIntl } from 'react-intl';
7
10
  import { cx } from '@atlaskit/css';
@@ -22,6 +25,7 @@ import { redo } from '@atlaskit/prosemirror-history/redo';
22
25
  import { undo } from '@atlaskit/prosemirror-history/undo';
23
26
  import { useBlockMenu } from './block-menu-provider';
24
27
  import { BlockMenuRenderer } from './block-menu-renderer/BlockMenuRenderer';
28
+ import { BlockMenuTargetVisibilityProvider } from './block-menu-target-visibility-context';
25
29
  var styles = {
26
30
  base: "_2rko12b0 _bfhk1bhr _16qs130s",
27
31
  maxWidthStyles: "_p12fnklw",
@@ -171,17 +175,20 @@ var BlockMenu = function BlockMenu(_ref5) {
171
175
  mountTo = _ref5.mountTo,
172
176
  boundariesElement = _ref5.boundariesElement,
173
177
  scrollableElement = _ref5.scrollableElement;
178
+ var isPopupTargetVisibilityEnabled = isExperimentEnabled('platform_editor_popup_target_visibility');
174
179
  var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], function (states) {
175
- var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
180
+ var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5;
176
181
  return {
177
182
  menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
178
- isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
179
- isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
183
+ menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
184
+ isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
185
+ isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
180
186
  currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
181
- openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 || (_states$blockControls4 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.openedViaKeyboard
187
+ openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 || (_states$blockControls5 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
182
188
  };
183
189
  }),
184
190
  menuTriggerBy = _useSharedPluginState.menuTriggerBy,
191
+ menuTriggerByNode = _useSharedPluginState.menuTriggerByNode,
185
192
  isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
186
193
  isMenuOpen = _useSharedPluginState.isMenuOpen,
187
194
  currentUserIntent = _useSharedPluginState.currentUserIntent,
@@ -219,6 +226,8 @@ var BlockMenu = function BlockMenu(_ref5) {
219
226
  anchoredToRef.current = menuTriggerBy;
220
227
  }
221
228
  var targetHandleRef = isExperimentEnabled('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
229
+ var menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
230
+ var visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
222
231
  var closeMenu = React.useCallback(function () {
223
232
  api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
224
233
  var _api$blockControls, _api$userIntent2;
@@ -248,19 +257,71 @@ var BlockMenu = function BlockMenu(_ref5) {
248
257
  _React$useState4 = _slicedToArray(_React$useState3, 2),
249
258
  menuHeight = _React$useState4[0],
250
259
  setMenuHeight = _React$useState4[1];
260
+ var _React$useState5 = React.useState({
261
+ isVisible: undefined,
262
+ restoreFocusTo: null
263
+ }),
264
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
265
+ targetVisibility = _React$useState6[0],
266
+ setTargetVisibility = _React$useState6[1];
267
+ var targetVisible = targetVisibility.isVisible,
268
+ restoreFocusTo = targetVisibility.restoreFocusTo;
269
+ // CSS visibility can move focus to the document body. Preserve the active menu item so the
270
+ // existing focus-loss guard does not close the menus during a temporary scroll transition.
271
+ var handleTargetVisibilityChanged = React.useCallback(function (isVisible) {
272
+ var _popupRef$current;
273
+ if (isVisible) {
274
+ setTargetVisibility(function (current) {
275
+ return {
276
+ isVisible: true,
277
+ restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
278
+ };
279
+ });
280
+ return;
281
+ }
282
+
283
+ // Capture focus before scheduling the state update so the updater stays pure.
284
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
285
+ var activeElement = document.activeElement;
286
+ var isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(NESTED_DROPDOWN_MENU) !== null);
287
+ setTargetVisibility({
288
+ isVisible: false,
289
+ restoreFocusTo: isFocusInMenu ? activeElement : null
290
+ });
291
+ }, []);
292
+ React.useLayoutEffect(function () {
293
+ if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
294
+ return;
295
+ }
296
+ var _restoreFocusTo$owner = restoreFocusTo.ownerDocument,
297
+ activeElement = _restoreFocusTo$owner.activeElement,
298
+ body = _restoreFocusTo$owner.body,
299
+ documentElement = _restoreFocusTo$owner.documentElement;
300
+ var focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
301
+ if (restoreFocusTo.isConnected && focusWasLost) {
302
+ restoreFocusTo.focus({
303
+ preventScroll: true
304
+ });
305
+ }
306
+ setTargetVisibility(function (current) {
307
+ return _objectSpread(_objectSpread({}, current), {}, {
308
+ restoreFocusTo: null
309
+ });
310
+ });
311
+ }, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
251
312
  var targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
252
313
  React.useLayoutEffect(function () {
253
- var _popupRef$current;
314
+ var _popupRef$current2;
254
315
  if (!isMenuOpen) {
255
316
  return;
256
317
  }
257
318
  onDropdownOpenChanged(true);
258
- setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
319
+ setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
259
320
  }, [isMenuOpen, onDropdownOpenChanged]);
260
321
 
261
322
  // Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
262
323
  // dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
263
- var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
324
+ var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
264
325
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
265
326
  document.activeElement === targetHandleRef || popupRef.current && (
266
327
  // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
@@ -331,6 +392,10 @@ var BlockMenu = function BlockMenu(_ref5) {
331
392
  if (!(targetHandleRef instanceof HTMLElement)) {
332
393
  return null;
333
394
  }
395
+ var blockMenuContent = /*#__PURE__*/React.createElement(BlockMenuContent, {
396
+ api: api,
397
+ setRef: setRef
398
+ });
334
399
  return /*#__PURE__*/React.createElement(ErrorBoundary, {
335
400
  component: ACTION_SUBJECT.BLOCK_MENU,
336
401
  dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
@@ -345,11 +410,14 @@ var BlockMenu = function BlockMenu(_ref5) {
345
410
  boundariesElement: boundariesElement,
346
411
  scrollableElement: scrollableElement,
347
412
  target: targetHandleRef,
413
+ visibilityTarget: visibilityTarget,
348
414
  zIndex: akEditorFloatingOverlapPanelZIndex,
349
415
  fitWidth: DEFAULT_MENU_WIDTH,
350
416
  fitHeight: menuHeight,
351
417
  preventOverflow: true,
352
- stick: true
418
+ stick: true,
419
+ hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
420
+ onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
353
421
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
354
422
  ,
355
423
  offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
@@ -358,10 +426,9 @@ var BlockMenu = function BlockMenu(_ref5) {
358
426
  {
359
427
  initialFocus: undefined
360
428
  } : undefined
361
- }, /*#__PURE__*/React.createElement(BlockMenuContent, {
362
- api: api,
363
- setRef: setRef
364
- })));
429
+ }, isPopupTargetVisibilityEnabled ? /*#__PURE__*/React.createElement(BlockMenuTargetVisibilityProvider, {
430
+ value: targetVisible
431
+ }, blockMenuContent) : blockMenuContent));
365
432
  };
366
433
 
367
434
  // eslint-disable-next-line @typescript-eslint/no-restricted-types
@@ -6,6 +6,7 @@ import { ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
6
6
  import ChangesIcon from '@atlaskit/icon/core/changes';
7
7
  import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
8
8
  import { fg } from '@atlaskit/platform-feature-flags/fg';
9
+ import { useBlockMenuTargetVisibility } from './block-menu-target-visibility-context';
9
10
  import { BLOCK_MENU_ITEM_NAME } from './consts';
10
11
  var BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
11
12
  var shouldIgnoreBlockMenuTransformSpotlightCloseEvent = function shouldIgnoreBlockMenuTransformSpotlightCloseEvent(event) {
@@ -16,6 +17,7 @@ export var FormatMenuComponent = function FormatMenuComponent(_ref) {
16
17
  children = _ref.children;
17
18
  var _useIntl = useIntl(),
18
19
  formatMessage = _useIntl.formatMessage;
20
+ var targetVisible = useBlockMenuTargetVisibility();
19
21
  var formatMenuLabel = blockMenuMessages.changeFormat;
20
22
  var handleClick = useCallback(function () {
21
23
  api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
@@ -34,6 +36,7 @@ export var FormatMenuComponent = function FormatMenuComponent(_ref) {
34
36
  });
35
37
  }, [api]);
36
38
  return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
39
+ isPopupVisible: targetVisible,
37
40
  text: formatMessage(formatMenuLabel),
38
41
  elemBefore: /*#__PURE__*/React.createElement(ChangesIcon, {
39
42
  label: "",
@@ -0,0 +1,3 @@
1
+ import { type Provider } from 'react';
2
+ export declare const BlockMenuTargetVisibilityProvider: Provider<boolean | undefined>;
3
+ export declare const useBlockMenuTargetVisibility: () => boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "20.0.2",
3
+ "version": "20.0.4",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -35,21 +35,21 @@
35
35
  "@atlaskit/editor-prosemirror": "^9.0.0",
36
36
  "@atlaskit/editor-shared-styles": "^4.3.0",
37
37
  "@atlaskit/editor-tables": "^3.2.0",
38
- "@atlaskit/editor-toolbar": "^2.7.0",
38
+ "@atlaskit/editor-toolbar": "^2.8.0",
39
39
  "@atlaskit/flag": "^19.0.0",
40
40
  "@atlaskit/icon": "^38.0.0",
41
41
  "@atlaskit/platform-feature-experiments": "^0.3.0",
42
42
  "@atlaskit/platform-feature-flags": "^2.2.0",
43
43
  "@atlaskit/primitives": "^22.5.0",
44
44
  "@atlaskit/prosemirror-history": "^1.2.0",
45
- "@atlaskit/tmp-editor-statsig": "^207.0.0",
45
+ "@atlaskit/tmp-editor-statsig": "^208.0.0",
46
46
  "@atlaskit/tokens": "^20.0.0",
47
47
  "@babel/runtime": "^7.0.0",
48
48
  "bind-event-listener": "^3.0.0",
49
49
  "memoize-one": "^6.0.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@atlaskit/editor-common": "^125.2.0",
52
+ "@atlaskit/editor-common": "^125.3.0",
53
53
  "react": "^18.2.0 || ^19.2.0",
54
54
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
55
55
  },