@atlaskit/editor-plugin-layout 10.2.0 → 10.3.0

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,16 @@
1
1
  # @atlaskit/editor-plugin-layout
2
2
 
3
+ ## 10.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`89a8af72aa2c9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/89a8af72aa2c9) -
8
+ Add reusable toolbar menu container and render the layout column menu in a popup
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+
3
14
  ## 10.2.0
4
15
 
5
16
  ### Minor Changes
@@ -283,9 +283,17 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
283
283
  }
284
284
  }
285
285
  },
286
- contentComponent: function contentComponent() {
287
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _experiments.editorExperiment)('advanced_layouts', true) ? /*#__PURE__*/_react.default.createElement(_globalStyles.GlobalStylesWrapper, null) : null, (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_menu', 'isEnabled', true) ? /*#__PURE__*/_react.default.createElement(_LayoutColumnMenu.LayoutColumnMenu, {
288
- api: api
286
+ contentComponent: function contentComponent(_ref5) {
287
+ var editorView = _ref5.editorView,
288
+ popupsMountPoint = _ref5.popupsMountPoint,
289
+ popupsBoundariesElement = _ref5.popupsBoundariesElement,
290
+ popupsScrollableElement = _ref5.popupsScrollableElement;
291
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _experiments.editorExperiment)('advanced_layouts', true) ? /*#__PURE__*/_react.default.createElement(_globalStyles.GlobalStylesWrapper, null) : null, (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_menu', 'isEnabled', true) && editorView ? /*#__PURE__*/_react.default.createElement(_LayoutColumnMenu.LayoutColumnMenu, {
292
+ api: api,
293
+ editorView: editorView,
294
+ mountTo: popupsMountPoint,
295
+ boundariesElement: popupsBoundariesElement,
296
+ scrollableElement: popupsScrollableElement
289
297
  }) : null);
290
298
  },
291
299
  getSharedState: function getSharedState(editorState) {
@@ -8,6 +8,7 @@ exports.getLayoutColumnMenuComponents = exports.LAYOUT_COLUMN_MENU_FALLBACKS = e
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _editorToolbar = require("@atlaskit/editor-toolbar");
11
+ var _toolbarMenuContainer = require("@atlaskit/editor-toolbar/toolbar-menu-container");
11
12
  var _DistributeColumnsDropdownItem = require("./DistributeColumnsDropdownItem");
12
13
  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; }
13
14
  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; }
@@ -33,7 +34,9 @@ var LAYOUT_COLUMN_MENU_FALLBACKS = exports.LAYOUT_COLUMN_MENU_FALLBACKS = {
33
34
  };
34
35
  var getLayoutColumnMenuComponents = exports.getLayoutColumnMenuComponents = function getLayoutColumnMenuComponents(_ref2) {
35
36
  var api = _ref2.api;
36
- return [_objectSpread({}, LAYOUT_COLUMN_MENU), _objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
37
+ return [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU), {}, {
38
+ component: _toolbarMenuContainer.ToolbarMenuContainer
39
+ }), _objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
37
40
  parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU), {}, {
38
41
  rank: LAYOUT_COLUMN_MENU_RANK[LAYOUT_COLUMN_MENU_SECTION.key]
39
42
  })]
@@ -1,34 +1,91 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.LayoutColumnMenu = void 0;
8
- var _react = _interopRequireDefault(require("react"));
8
+ var _react = _interopRequireWildcard(require("react"));
9
9
  var _hooks = require("@atlaskit/editor-common/hooks");
10
+ var _toolbar = require("@atlaskit/editor-common/toolbar");
11
+ var _ui = require("@atlaskit/editor-common/ui");
12
+ var _uiReact = require("@atlaskit/editor-common/ui-react");
13
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
14
+ var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
15
+ var _editorToolbar = require("@atlaskit/editor-toolbar");
10
16
  var _editorUiControlModel = require("@atlaskit/editor-ui-control-model");
11
17
  var _components = require("./components");
12
- var LayoutColumnMenu = exports.LayoutColumnMenu = function LayoutColumnMenu(_ref) {
18
+ 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
+ var PopupWithListeners = (0, _uiReact.withReactEditorViewOuterListeners)(_ui.Popup);
20
+ var LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
21
+ var getLayoutColumnMenuTarget = function getLayoutColumnMenuTarget(editorView, selectionAnchorPos) {
22
+ if (selectionAnchorPos === undefined) {
23
+ return null;
24
+ }
25
+ var selectionNode = editorView.state.doc.nodeAt(selectionAnchorPos);
26
+ if ((selectionNode === null || selectionNode === void 0 ? void 0 : selectionNode.type.name) !== 'layoutColumn') {
27
+ return null;
28
+ }
29
+ return (0, _utils.findDomRefAtPos)(selectionAnchorPos, editorView.domAtPos.bind(editorView));
30
+ };
31
+ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.memo(function LayoutColumnMenu(_ref) {
13
32
  var _api$uiControlRegistr, _api$uiControlRegistr2;
14
- var api = _ref.api;
15
- var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['layout'], function (states) {
16
- var _states$layoutState$i, _states$layoutState;
33
+ var api = _ref.api,
34
+ editorView = _ref.editorView,
35
+ mountTo = _ref.mountTo,
36
+ boundariesElement = _ref.boundariesElement,
37
+ scrollableElement = _ref.scrollableElement;
38
+ var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['layout', 'selection'], function (states) {
39
+ var _states$layoutState$i, _states$layoutState, _states$selectionStat;
17
40
  return {
18
- isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false
41
+ isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false,
42
+ selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
19
43
  };
20
44
  }),
21
- isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen;
22
- if (!isLayoutColumnMenuOpen) {
23
- return null;
24
- }
45
+ isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen,
46
+ selection = _useSharedPluginState.selection;
47
+ var closeLayoutColumnMenu = (0, _react.useCallback)(function () {
48
+ var _api$core, _api$layout;
49
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.toggleLayoutColumnMenu({
50
+ isOpen: false
51
+ }));
52
+ }, [api]);
53
+ var handleSetIsOpen = (0, _react.useCallback)(function (isOpen) {
54
+ if (!isOpen) {
55
+ closeLayoutColumnMenu();
56
+ }
57
+ }, [closeLayoutColumnMenu]);
25
58
  var components = (_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(_components.LAYOUT_COLUMN_MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
26
- if (components.length === 0) {
59
+ var target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
60
+ var hasValidTarget = target instanceof HTMLElement;
61
+ (0, _react.useEffect)(function () {
62
+ if (isLayoutColumnMenuOpen && (!hasValidTarget || components.length === 0)) {
63
+ closeLayoutColumnMenu();
64
+ }
65
+ }, [closeLayoutColumnMenu, components.length, hasValidTarget, isLayoutColumnMenuOpen]);
66
+ if (!isLayoutColumnMenuOpen || components.length === 0 || !hasValidTarget) {
27
67
  return null;
28
68
  }
29
- return /*#__PURE__*/_react.default.createElement(_editorUiControlModel.SurfaceRenderer, {
69
+ return /*#__PURE__*/_react.default.createElement(PopupWithListeners, {
70
+ target: target,
71
+ mountTo: mountTo,
72
+ boundariesElement: boundariesElement,
73
+ scrollableElement: scrollableElement,
74
+ zIndex: _editorSharedStyles.akEditorFloatingPanelZIndex,
75
+ alignX: "center",
76
+ alignY: "top",
77
+ forcePlacement: true,
78
+ offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
79
+ handleClickOutside: closeLayoutColumnMenu,
80
+ handleEscapeKeydown: closeLayoutColumnMenu
81
+ }, /*#__PURE__*/_react.default.createElement(_toolbar.EditorToolbarProvider, {
82
+ editorView: editorView
83
+ }, /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownMenuProvider, {
84
+ isOpen: isLayoutColumnMenuOpen,
85
+ setIsOpen: handleSetIsOpen
86
+ }, /*#__PURE__*/_react.default.createElement(_editorUiControlModel.SurfaceRenderer, {
30
87
  components: components,
31
88
  fallbacks: _components.LAYOUT_COLUMN_MENU_FALLBACKS,
32
89
  surface: _components.LAYOUT_COLUMN_MENU
33
- });
34
- };
90
+ }))));
91
+ });
@@ -262,9 +262,18 @@ export const layoutPlugin = ({
262
262
  }
263
263
  }
264
264
  },
265
- contentComponent() {
266
- return /*#__PURE__*/React.createElement(React.Fragment, null, editorExperiment('advanced_layouts', true) ? /*#__PURE__*/React.createElement(GlobalStylesWrapper, null) : null, expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true) ? /*#__PURE__*/React.createElement(LayoutColumnMenu, {
267
- api: api
265
+ contentComponent({
266
+ editorView,
267
+ popupsMountPoint,
268
+ popupsBoundariesElement,
269
+ popupsScrollableElement
270
+ }) {
271
+ return /*#__PURE__*/React.createElement(React.Fragment, null, editorExperiment('advanced_layouts', true) ? /*#__PURE__*/React.createElement(GlobalStylesWrapper, null) : null, expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true) && editorView ? /*#__PURE__*/React.createElement(LayoutColumnMenu, {
272
+ api: api,
273
+ editorView: editorView,
274
+ mountTo: popupsMountPoint,
275
+ boundariesElement: popupsBoundariesElement,
276
+ scrollableElement: popupsScrollableElement
268
277
  }) : null);
269
278
  },
270
279
  getSharedState(editorState) {
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
3
+ import { ToolbarMenuContainer } from '@atlaskit/editor-toolbar/toolbar-menu-container';
3
4
  import { createDistributeColumnsDropdownItem } from './DistributeColumnsDropdownItem';
4
5
  export const LAYOUT_COLUMN_MENU = {
5
6
  key: 'layout-column-menu',
@@ -28,7 +29,8 @@ export const getLayoutColumnMenuComponents = ({
28
29
  api
29
30
  }) => {
30
31
  return [{
31
- ...LAYOUT_COLUMN_MENU
32
+ ...LAYOUT_COLUMN_MENU,
33
+ component: ToolbarMenuContainer
32
34
  }, {
33
35
  ...LAYOUT_COLUMN_MENU_SECTION,
34
36
  parents: [{
@@ -1,29 +1,85 @@
1
- import React from 'react';
1
+ import React, { useCallback, useEffect } from 'react';
2
2
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
+ import { EditorToolbarProvider } from '@atlaskit/editor-common/toolbar';
4
+ import { Popup } from '@atlaskit/editor-common/ui';
5
+ import { withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
7
+ import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
8
+ import { ToolbarDropdownMenuProvider } from '@atlaskit/editor-toolbar';
3
9
  import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model';
4
10
  import { LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
5
- export const LayoutColumnMenu = ({
6
- api
7
- }) => {
11
+ const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
12
+ const LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
13
+ const getLayoutColumnMenuTarget = (editorView, selectionAnchorPos) => {
14
+ if (selectionAnchorPos === undefined) {
15
+ return null;
16
+ }
17
+ const selectionNode = editorView.state.doc.nodeAt(selectionAnchorPos);
18
+ if ((selectionNode === null || selectionNode === void 0 ? void 0 : selectionNode.type.name) !== 'layoutColumn') {
19
+ return null;
20
+ }
21
+ return findDomRefAtPos(selectionAnchorPos, editorView.domAtPos.bind(editorView));
22
+ };
23
+ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu({
24
+ api,
25
+ editorView,
26
+ mountTo,
27
+ boundariesElement,
28
+ scrollableElement
29
+ }) {
8
30
  var _api$uiControlRegistr, _api$uiControlRegistr2;
9
31
  const {
10
- isLayoutColumnMenuOpen
11
- } = useSharedPluginStateWithSelector(api, ['layout'], states => {
12
- var _states$layoutState$i, _states$layoutState;
32
+ isLayoutColumnMenuOpen,
33
+ selection
34
+ } = useSharedPluginStateWithSelector(api, ['layout', 'selection'], states => {
35
+ var _states$layoutState$i, _states$layoutState, _states$selectionStat;
13
36
  return {
14
- isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false
37
+ isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false,
38
+ selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
15
39
  };
16
40
  });
17
- if (!isLayoutColumnMenuOpen) {
18
- return null;
19
- }
41
+ const closeLayoutColumnMenu = useCallback(() => {
42
+ var _api$core, _api$layout;
43
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.toggleLayoutColumnMenu({
44
+ isOpen: false
45
+ }));
46
+ }, [api]);
47
+ const handleSetIsOpen = useCallback(isOpen => {
48
+ if (!isOpen) {
49
+ closeLayoutColumnMenu();
50
+ }
51
+ }, [closeLayoutColumnMenu]);
20
52
  const components = (_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(LAYOUT_COLUMN_MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
21
- if (components.length === 0) {
53
+ const target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
54
+ const hasValidTarget = target instanceof HTMLElement;
55
+ useEffect(() => {
56
+ if (isLayoutColumnMenuOpen && (!hasValidTarget || components.length === 0)) {
57
+ closeLayoutColumnMenu();
58
+ }
59
+ }, [closeLayoutColumnMenu, components.length, hasValidTarget, isLayoutColumnMenuOpen]);
60
+ if (!isLayoutColumnMenuOpen || components.length === 0 || !hasValidTarget) {
22
61
  return null;
23
62
  }
24
- return /*#__PURE__*/React.createElement(SurfaceRenderer, {
63
+ return /*#__PURE__*/React.createElement(PopupWithListeners, {
64
+ target: target,
65
+ mountTo: mountTo,
66
+ boundariesElement: boundariesElement,
67
+ scrollableElement: scrollableElement,
68
+ zIndex: akEditorFloatingPanelZIndex,
69
+ alignX: "center",
70
+ alignY: "top",
71
+ forcePlacement: true,
72
+ offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
73
+ handleClickOutside: closeLayoutColumnMenu,
74
+ handleEscapeKeydown: closeLayoutColumnMenu
75
+ }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
76
+ editorView: editorView
77
+ }, /*#__PURE__*/React.createElement(ToolbarDropdownMenuProvider, {
78
+ isOpen: isLayoutColumnMenuOpen,
79
+ setIsOpen: handleSetIsOpen
80
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
25
81
  components: components,
26
82
  fallbacks: LAYOUT_COLUMN_MENU_FALLBACKS,
27
83
  surface: LAYOUT_COLUMN_MENU
28
- });
29
- };
84
+ }))));
85
+ });
@@ -276,9 +276,17 @@ export var layoutPlugin = function layoutPlugin(_ref) {
276
276
  }
277
277
  }
278
278
  },
279
- contentComponent: function contentComponent() {
280
- return /*#__PURE__*/React.createElement(React.Fragment, null, editorExperiment('advanced_layouts', true) ? /*#__PURE__*/React.createElement(GlobalStylesWrapper, null) : null, expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true) ? /*#__PURE__*/React.createElement(LayoutColumnMenu, {
281
- api: api
279
+ contentComponent: function contentComponent(_ref5) {
280
+ var editorView = _ref5.editorView,
281
+ popupsMountPoint = _ref5.popupsMountPoint,
282
+ popupsBoundariesElement = _ref5.popupsBoundariesElement,
283
+ popupsScrollableElement = _ref5.popupsScrollableElement;
284
+ return /*#__PURE__*/React.createElement(React.Fragment, null, editorExperiment('advanced_layouts', true) ? /*#__PURE__*/React.createElement(GlobalStylesWrapper, null) : null, expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true) && editorView ? /*#__PURE__*/React.createElement(LayoutColumnMenu, {
285
+ api: api,
286
+ editorView: editorView,
287
+ mountTo: popupsMountPoint,
288
+ boundariesElement: popupsBoundariesElement,
289
+ scrollableElement: popupsScrollableElement
282
290
  }) : null);
283
291
  },
284
292
  getSharedState: function getSharedState(editorState) {
@@ -3,6 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
3
  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; }
4
4
  import React from 'react';
5
5
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
6
+ import { ToolbarMenuContainer } from '@atlaskit/editor-toolbar/toolbar-menu-container';
6
7
  import { createDistributeColumnsDropdownItem } from './DistributeColumnsDropdownItem';
7
8
  export var LAYOUT_COLUMN_MENU = {
8
9
  key: 'layout-column-menu',
@@ -26,7 +27,9 @@ export var LAYOUT_COLUMN_MENU_FALLBACKS = {
26
27
  };
27
28
  export var getLayoutColumnMenuComponents = function getLayoutColumnMenuComponents(_ref2) {
28
29
  var api = _ref2.api;
29
- return [_objectSpread({}, LAYOUT_COLUMN_MENU), _objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
30
+ return [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU), {}, {
31
+ component: ToolbarMenuContainer
32
+ }), _objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
30
33
  parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU), {}, {
31
34
  rank: LAYOUT_COLUMN_MENU_RANK[LAYOUT_COLUMN_MENU_SECTION.key]
32
35
  })]
@@ -1,27 +1,83 @@
1
- import React from 'react';
1
+ import React, { useCallback, useEffect } from 'react';
2
2
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
+ import { EditorToolbarProvider } from '@atlaskit/editor-common/toolbar';
4
+ import { Popup } from '@atlaskit/editor-common/ui';
5
+ import { withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
+ import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
7
+ import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
8
+ import { ToolbarDropdownMenuProvider } from '@atlaskit/editor-toolbar';
3
9
  import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model';
4
10
  import { LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
5
- export var LayoutColumnMenu = function LayoutColumnMenu(_ref) {
11
+ var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
12
+ var LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
13
+ var getLayoutColumnMenuTarget = function getLayoutColumnMenuTarget(editorView, selectionAnchorPos) {
14
+ if (selectionAnchorPos === undefined) {
15
+ return null;
16
+ }
17
+ var selectionNode = editorView.state.doc.nodeAt(selectionAnchorPos);
18
+ if ((selectionNode === null || selectionNode === void 0 ? void 0 : selectionNode.type.name) !== 'layoutColumn') {
19
+ return null;
20
+ }
21
+ return findDomRefAtPos(selectionAnchorPos, editorView.domAtPos.bind(editorView));
22
+ };
23
+ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(_ref) {
6
24
  var _api$uiControlRegistr, _api$uiControlRegistr2;
7
- var api = _ref.api;
8
- var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['layout'], function (states) {
9
- var _states$layoutState$i, _states$layoutState;
25
+ var api = _ref.api,
26
+ editorView = _ref.editorView,
27
+ mountTo = _ref.mountTo,
28
+ boundariesElement = _ref.boundariesElement,
29
+ scrollableElement = _ref.scrollableElement;
30
+ var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['layout', 'selection'], function (states) {
31
+ var _states$layoutState$i, _states$layoutState, _states$selectionStat;
10
32
  return {
11
- isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false
33
+ isLayoutColumnMenuOpen: (_states$layoutState$i = (_states$layoutState = states.layoutState) === null || _states$layoutState === void 0 ? void 0 : _states$layoutState.isLayoutColumnMenuOpen) !== null && _states$layoutState$i !== void 0 ? _states$layoutState$i : false,
34
+ selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
12
35
  };
13
36
  }),
14
- isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen;
15
- if (!isLayoutColumnMenuOpen) {
16
- return null;
17
- }
37
+ isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen,
38
+ selection = _useSharedPluginState.selection;
39
+ var closeLayoutColumnMenu = useCallback(function () {
40
+ var _api$core, _api$layout;
41
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.toggleLayoutColumnMenu({
42
+ isOpen: false
43
+ }));
44
+ }, [api]);
45
+ var handleSetIsOpen = useCallback(function (isOpen) {
46
+ if (!isOpen) {
47
+ closeLayoutColumnMenu();
48
+ }
49
+ }, [closeLayoutColumnMenu]);
18
50
  var components = (_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(LAYOUT_COLUMN_MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
19
- if (components.length === 0) {
51
+ var target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
52
+ var hasValidTarget = target instanceof HTMLElement;
53
+ useEffect(function () {
54
+ if (isLayoutColumnMenuOpen && (!hasValidTarget || components.length === 0)) {
55
+ closeLayoutColumnMenu();
56
+ }
57
+ }, [closeLayoutColumnMenu, components.length, hasValidTarget, isLayoutColumnMenuOpen]);
58
+ if (!isLayoutColumnMenuOpen || components.length === 0 || !hasValidTarget) {
20
59
  return null;
21
60
  }
22
- return /*#__PURE__*/React.createElement(SurfaceRenderer, {
61
+ return /*#__PURE__*/React.createElement(PopupWithListeners, {
62
+ target: target,
63
+ mountTo: mountTo,
64
+ boundariesElement: boundariesElement,
65
+ scrollableElement: scrollableElement,
66
+ zIndex: akEditorFloatingPanelZIndex,
67
+ alignX: "center",
68
+ alignY: "top",
69
+ forcePlacement: true,
70
+ offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
71
+ handleClickOutside: closeLayoutColumnMenu,
72
+ handleEscapeKeydown: closeLayoutColumnMenu
73
+ }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
74
+ editorView: editorView
75
+ }, /*#__PURE__*/React.createElement(ToolbarDropdownMenuProvider, {
76
+ isOpen: isLayoutColumnMenuOpen,
77
+ setIsOpen: handleSetIsOpen
78
+ }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
23
79
  components: components,
24
80
  fallbacks: LAYOUT_COLUMN_MENU_FALLBACKS,
25
81
  surface: LAYOUT_COLUMN_MENU
26
- });
27
- };
82
+ }))));
83
+ });
@@ -1,8 +1,13 @@
1
1
  import React from 'react';
2
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
4
  import type { LayoutPlugin } from '../../layoutPluginType';
4
5
  type LayoutColumnMenuProps = {
5
6
  api: ExtractInjectionAPI<LayoutPlugin> | undefined;
7
+ boundariesElement?: HTMLElement;
8
+ editorView: EditorView;
9
+ mountTo?: HTMLElement;
10
+ scrollableElement?: HTMLElement;
6
11
  };
7
- export declare const LayoutColumnMenu: ({ api }: LayoutColumnMenuProps) => React.JSX.Element | null;
12
+ export declare const LayoutColumnMenu: React.NamedExoticComponent<LayoutColumnMenuProps>;
8
13
  export {};
@@ -1,8 +1,13 @@
1
1
  import React from 'react';
2
2
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
3
4
  import type { LayoutPlugin } from '../../layoutPluginType';
4
5
  type LayoutColumnMenuProps = {
5
6
  api: ExtractInjectionAPI<LayoutPlugin> | undefined;
7
+ boundariesElement?: HTMLElement;
8
+ editorView: EditorView;
9
+ mountTo?: HTMLElement;
10
+ scrollableElement?: HTMLElement;
6
11
  };
7
- export declare const LayoutColumnMenu: ({ api }: LayoutColumnMenuProps) => React.JSX.Element | null;
12
+ export declare const LayoutColumnMenu: React.NamedExoticComponent<LayoutColumnMenuProps>;
8
13
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-layout",
3
- "version": "10.2.0",
3
+ "version": "10.3.0",
4
4
  "description": "Layout plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -37,13 +37,13 @@
37
37
  "@atlaskit/editor-plugin-editor-disabled": "^10.1.0",
38
38
  "@atlaskit/editor-plugin-guideline": "^10.1.0",
39
39
  "@atlaskit/editor-plugin-interaction": "^19.1.0",
40
- "@atlaskit/editor-plugin-selection": "^10.0.0",
41
- "@atlaskit/editor-plugin-toolbar": "^7.2.0",
42
- "@atlaskit/editor-plugin-ui-control-registry": "^4.0.0",
43
- "@atlaskit/editor-plugin-width": "^11.0.0",
40
+ "@atlaskit/editor-plugin-selection": "^10.1.0",
41
+ "@atlaskit/editor-plugin-toolbar": "^7.3.0",
42
+ "@atlaskit/editor-plugin-ui-control-registry": "^4.1.0",
43
+ "@atlaskit/editor-plugin-width": "^11.1.0",
44
44
  "@atlaskit/editor-prosemirror": "^7.3.0",
45
45
  "@atlaskit/editor-shared-styles": "^3.10.0",
46
- "@atlaskit/editor-toolbar": "^1.2.0",
46
+ "@atlaskit/editor-toolbar": "^1.3.0",
47
47
  "@atlaskit/editor-ui-control-model": "^1.1.0",
48
48
  "@atlaskit/icon": "^34.5.0",
49
49
  "@atlaskit/icon-lab": "^6.9.0",