@atlaskit/editor-plugin-layout 10.3.1 → 10.3.3

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 (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/layoutPlugin.js +5 -1
  3. package/dist/cjs/pm-plugins/actions.js +30 -5
  4. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +40 -0
  5. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +39 -0
  6. package/dist/cjs/ui/LayoutColumnMenu/components.js +59 -22
  7. package/dist/cjs/ui/LayoutColumnMenu/index.js +23 -4
  8. package/dist/cjs/ui/LayoutColumnMenu/keys.js +58 -0
  9. package/dist/cjs/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +22 -0
  10. package/dist/cjs/ui/LayoutColumnMenu/verticalAlignIcons.js +18 -0
  11. package/dist/es2019/layoutPlugin.js +7 -3
  12. package/dist/es2019/pm-plugins/actions.js +27 -0
  13. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +35 -0
  14. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +35 -0
  15. package/dist/es2019/ui/LayoutColumnMenu/components.js +54 -18
  16. package/dist/es2019/ui/LayoutColumnMenu/index.js +24 -5
  17. package/dist/es2019/ui/LayoutColumnMenu/keys.js +61 -0
  18. package/dist/es2019/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +14 -0
  19. package/dist/es2019/ui/LayoutColumnMenu/verticalAlignIcons.js +11 -0
  20. package/dist/esm/layoutPlugin.js +7 -3
  21. package/dist/esm/pm-plugins/actions.js +29 -4
  22. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +32 -0
  23. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +32 -0
  24. package/dist/esm/ui/LayoutColumnMenu/components.js +51 -14
  25. package/dist/esm/ui/LayoutColumnMenu/index.js +24 -5
  26. package/dist/esm/ui/LayoutColumnMenu/keys.js +51 -0
  27. package/dist/esm/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +16 -0
  28. package/dist/esm/ui/LayoutColumnMenu/verticalAlignIcons.js +11 -0
  29. package/dist/types/layoutPluginType.d.ts +2 -1
  30. package/dist/types/pm-plugins/actions.d.ts +2 -0
  31. package/dist/types/ui/LayoutColumnMenu/VerticalAlignDropdownItem.d.ts +14 -0
  32. package/dist/types/ui/LayoutColumnMenu/VerticalAlignNestedMenu.d.ts +8 -0
  33. package/dist/types/ui/LayoutColumnMenu/components.d.ts +0 -4
  34. package/dist/types/ui/LayoutColumnMenu/keys.d.ts +13 -0
  35. package/dist/types/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.d.ts +11 -0
  36. package/dist/types/ui/LayoutColumnMenu/verticalAlignIcons.d.ts +5 -0
  37. package/dist/types-ts4.5/layoutPluginType.d.ts +2 -1
  38. package/dist/types-ts4.5/pm-plugins/actions.d.ts +2 -0
  39. package/dist/types-ts4.5/ui/LayoutColumnMenu/VerticalAlignDropdownItem.d.ts +14 -0
  40. package/dist/types-ts4.5/ui/LayoutColumnMenu/VerticalAlignNestedMenu.d.ts +8 -0
  41. package/dist/types-ts4.5/ui/LayoutColumnMenu/components.d.ts +0 -4
  42. package/dist/types-ts4.5/ui/LayoutColumnMenu/keys.d.ts +13 -0
  43. package/dist/types-ts4.5/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.d.ts +11 -0
  44. package/dist/types-ts4.5/ui/LayoutColumnMenu/verticalAlignIcons.d.ts +5 -0
  45. package/package.json +9 -9
@@ -1,25 +1,11 @@
1
1
  import React from 'react';
2
+ import { layoutMessages } from '@atlaskit/editor-common/messages';
2
3
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
3
4
  import { ToolbarMenuContainer } from '@atlaskit/editor-toolbar/toolbar-menu-container';
4
5
  import { createDistributeColumnsDropdownItem } from './DistributeColumnsDropdownItem';
5
- export const LAYOUT_COLUMN_MENU = {
6
- key: 'layout-column-menu',
7
- type: 'menu'
8
- };
9
- const LAYOUT_COLUMN_MENU_SECTION = {
10
- key: 'layout-column-menu-section',
11
- type: 'menu-section'
12
- };
13
- const DISTRIBUTE_COLUMNS_MENU_ITEM = {
14
- key: 'layout-column-menu-distribute-columns-item',
15
- type: 'menu-item'
16
- };
17
- const LAYOUT_COLUMN_MENU_RANK = {
18
- [LAYOUT_COLUMN_MENU_SECTION.key]: 0
19
- };
20
- const LAYOUT_COLUMN_MENU_SECTION_RANK = {
21
- [DISTRIBUTE_COLUMNS_MENU_ITEM.key]: 0
22
- };
6
+ import { DISTRIBUTE_COLUMNS_MENU_ITEM, LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_RANK, LAYOUT_COLUMN_MENU_SECTION, LAYOUT_COLUMN_MENU_SECTION_RANK, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION, VERTICAL_ALIGN_BOTTOM_MENU_ITEM, VERTICAL_ALIGN_MENU, VERTICAL_ALIGN_MENU_RANK, VERTICAL_ALIGN_MENU_SECTION_RANK, VERTICAL_ALIGN_MIDDLE_MENU_ITEM, VERTICAL_ALIGN_TOP_MENU_ITEM } from './keys';
7
+ import { VerticalAlignDropdownItem } from './VerticalAlignDropdownItem';
8
+ import { VerticalAlignNestedMenu } from './VerticalAlignNestedMenu';
23
9
  export const LAYOUT_COLUMN_MENU_FALLBACKS = {
24
10
  'menu-section': ({
25
11
  children
@@ -44,5 +30,55 @@ export const getLayoutColumnMenuComponents = ({
44
30
  ...LAYOUT_COLUMN_MENU_SECTION,
45
31
  rank: LAYOUT_COLUMN_MENU_SECTION_RANK[DISTRIBUTE_COLUMNS_MENU_ITEM.key]
46
32
  }]
33
+ }, {
34
+ ...VERTICAL_ALIGN_MENU,
35
+ component: ({
36
+ children
37
+ }) => /*#__PURE__*/React.createElement(VerticalAlignNestedMenu, {
38
+ api: api
39
+ }, children),
40
+ parents: [{
41
+ ...LAYOUT_COLUMN_MENU_SECTION,
42
+ rank: LAYOUT_COLUMN_MENU_SECTION_RANK[VERTICAL_ALIGN_MENU.key]
43
+ }]
44
+ }, {
45
+ ...LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION,
46
+ parents: [{
47
+ ...VERTICAL_ALIGN_MENU,
48
+ rank: VERTICAL_ALIGN_MENU_RANK[LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key]
49
+ }]
50
+ }, {
51
+ ...VERTICAL_ALIGN_TOP_MENU_ITEM,
52
+ component: () => /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
53
+ api: api,
54
+ label: layoutMessages.alignColumnTop,
55
+ value: "top"
56
+ }),
57
+ parents: [{
58
+ ...LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION,
59
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_TOP_MENU_ITEM.key]
60
+ }]
61
+ }, {
62
+ ...VERTICAL_ALIGN_MIDDLE_MENU_ITEM,
63
+ component: () => /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
64
+ api: api,
65
+ label: layoutMessages.alignColumnMiddle,
66
+ value: "middle"
67
+ }),
68
+ parents: [{
69
+ ...LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION,
70
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_MIDDLE_MENU_ITEM.key]
71
+ }]
72
+ }, {
73
+ ...VERTICAL_ALIGN_BOTTOM_MENU_ITEM,
74
+ component: () => /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
75
+ api: api,
76
+ label: layoutMessages.alignColumnBottom,
77
+ value: "bottom"
78
+ }),
79
+ parents: [{
80
+ ...LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION,
81
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_BOTTOM_MENU_ITEM.key]
82
+ }]
47
83
  }];
48
84
  };
@@ -1,13 +1,14 @@
1
- import React, { useCallback, useEffect } from 'react';
1
+ import React, { useCallback, useContext, useEffect, useRef } from 'react';
2
2
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
3
  import { EditorToolbarProvider } from '@atlaskit/editor-common/toolbar';
4
4
  import { Popup } from '@atlaskit/editor-common/ui';
5
- import { withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
5
+ import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
6
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
8
8
  import { ToolbarDropdownMenuProvider } from '@atlaskit/editor-toolbar';
9
9
  import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model';
10
- import { LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
10
+ import { LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
11
+ import { LAYOUT_COLUMN_MENU } from './keys';
11
12
  const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
12
13
  const LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
13
14
  const getLayoutColumnMenuTarget = (editorView, selectionAnchorPos) => {
@@ -38,17 +39,33 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
38
39
  selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
39
40
  };
40
41
  });
42
+ const setOutsideClickTargetRef = useContext(OutsideClickTargetRefContext);
43
+ const menuRef = useRef(null);
41
44
  const closeLayoutColumnMenu = useCallback(() => {
42
45
  var _api$core, _api$layout;
43
46
  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
47
  isOpen: false
45
48
  }));
46
49
  }, [api]);
50
+ const handleClickOutside = useCallback(event => {
51
+ var _menuRef$current;
52
+ if (event.target instanceof Node && (_menuRef$current = menuRef.current) !== null && _menuRef$current !== void 0 && _menuRef$current.contains(event.target)) {
53
+ return;
54
+ }
55
+ if (event.target instanceof Element && event.target.closest('[data-toolbar-nested-dropdown-menu]')) {
56
+ return;
57
+ }
58
+ closeLayoutColumnMenu();
59
+ }, [closeLayoutColumnMenu]);
47
60
  const handleSetIsOpen = useCallback(isOpen => {
48
61
  if (!isOpen) {
49
62
  closeLayoutColumnMenu();
50
63
  }
51
64
  }, [closeLayoutColumnMenu]);
65
+ const handleMenuRef = useCallback(el => {
66
+ setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 ? void 0 : setOutsideClickTargetRef(el);
67
+ menuRef.current = el;
68
+ }, [setOutsideClickTargetRef]);
52
69
  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 : [];
53
70
  const target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
54
71
  const hasValidTarget = target instanceof HTMLElement;
@@ -70,8 +87,10 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
70
87
  alignY: "top",
71
88
  forcePlacement: true,
72
89
  offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
73
- handleClickOutside: closeLayoutColumnMenu,
90
+ handleClickOutside: handleClickOutside,
74
91
  handleEscapeKeydown: closeLayoutColumnMenu
92
+ }, /*#__PURE__*/React.createElement("div", {
93
+ ref: handleMenuRef
75
94
  }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
76
95
  editorView: editorView
77
96
  }, /*#__PURE__*/React.createElement(ToolbarDropdownMenuProvider, {
@@ -81,5 +100,5 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
81
100
  components: components,
82
101
  fallbacks: LAYOUT_COLUMN_MENU_FALLBACKS,
83
102
  surface: LAYOUT_COLUMN_MENU
84
- }))));
103
+ })))));
85
104
  });
@@ -0,0 +1,61 @@
1
+ // --- Menu surface ---
2
+
3
+ export const LAYOUT_COLUMN_MENU = {
4
+ type: 'menu',
5
+ key: 'layout-column-menu'
6
+ };
7
+
8
+ // --- Sections ---
9
+
10
+ export const LAYOUT_COLUMN_MENU_SECTION = {
11
+ type: 'menu-section',
12
+ key: 'layout-column-menu-section'
13
+ };
14
+ export const LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION = {
15
+ type: 'menu-section',
16
+ key: 'layout-column-vertical-align-menu-section'
17
+ };
18
+ export const LAYOUT_COLUMN_MENU_RANK = {
19
+ [LAYOUT_COLUMN_MENU_SECTION.key]: 100
20
+ };
21
+
22
+ // --- Menus ---
23
+
24
+ export const VERTICAL_ALIGN_MENU = {
25
+ type: 'nested-menu',
26
+ key: 'layout-column-menu-vertical-align-menu'
27
+ };
28
+
29
+ // --- Items ---
30
+
31
+ export const DISTRIBUTE_COLUMNS_MENU_ITEM = {
32
+ type: 'menu-item',
33
+ key: 'layout-column-menu-distribute-columns-item'
34
+ };
35
+ export const VERTICAL_ALIGN_TOP_MENU_ITEM = {
36
+ type: 'menu-item',
37
+ key: 'layout-column-menu-vertical-align-top-item'
38
+ };
39
+ export const VERTICAL_ALIGN_MIDDLE_MENU_ITEM = {
40
+ type: 'menu-item',
41
+ key: 'layout-column-menu-vertical-align-middle-item'
42
+ };
43
+ export const VERTICAL_ALIGN_BOTTOM_MENU_ITEM = {
44
+ type: 'menu-item',
45
+ key: 'layout-column-menu-vertical-align-bottom-item'
46
+ };
47
+
48
+ // --- Item ranks within sections ---
49
+
50
+ export const LAYOUT_COLUMN_MENU_SECTION_RANK = {
51
+ [DISTRIBUTE_COLUMNS_MENU_ITEM.key]: 100,
52
+ [VERTICAL_ALIGN_MENU.key]: 200
53
+ };
54
+ export const VERTICAL_ALIGN_MENU_RANK = {
55
+ [LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key]: 100
56
+ };
57
+ export const VERTICAL_ALIGN_MENU_SECTION_RANK = {
58
+ [VERTICAL_ALIGN_TOP_MENU_ITEM.key]: 100,
59
+ [VERTICAL_ALIGN_MIDDLE_MENU_ITEM.key]: 200,
60
+ [VERTICAL_ALIGN_BOTTOM_MENU_ITEM.key]: 300
61
+ };
@@ -0,0 +1,14 @@
1
+ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
2
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
3
+ export const getCurrentLayoutColumnValign = selection => {
4
+ const selectedColumn = selection instanceof NodeSelection && selection.node.type.name === 'layoutColumn' ? selection.node : undefined;
5
+ const currentValign = selectedColumn === null || selectedColumn === void 0 ? void 0 : selectedColumn.attrs.valign;
6
+ return {
7
+ currentValign,
8
+ selectedColumn
9
+ };
10
+ };
11
+ export const useCurrentLayoutColumnValign = api => useSharedPluginStateWithSelector(api, ['selection'], states => {
12
+ var _states$selectionStat;
13
+ return getCurrentLayoutColumnValign((_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection);
14
+ });
@@ -0,0 +1,11 @@
1
+ // Disable no-re-export here, this is a useful mapping file for icon lookup used in multiple places
2
+ /* eslint-disable @atlaskit/editor/no-re-export */
3
+
4
+ import AlignContentBottomIcon from '@atlaskit/icon-lab/core/align-content-bottom';
5
+ import AlignContentCenterVerticalIcon from '@atlaskit/icon-lab/core/align-content-center-vertical';
6
+ import AlignContentTopIcon from '@atlaskit/icon-lab/core/align-content-top';
7
+ export const VERTICAL_ALIGN_ICONS = {
8
+ top: AlignContentTopIcon,
9
+ middle: AlignContentCenterVerticalIcon,
10
+ bottom: AlignContentBottomIcon
11
+ };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { layoutColumn, layoutColumnWithLocalId, layoutSection, layoutSectionWithLocalId } from '@atlaskit/adf-schema';
2
+ import { layoutColumn, layoutColumnStage0, layoutColumnWithLocalId, layoutSection, layoutSectionWithLocalId } from '@atlaskit/adf-schema';
3
3
  import { layoutSectionWithSingleColumn, layoutSectionWithSingleColumnLocalId } from '@atlaskit/adf-schema/schema';
4
4
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
5
  import { TRANSFORM_STRUCTURE_LAYOUT_MENU_ITEM, TRANSFORM_STRUCTURE_MENU_SECTION, TRANSFORM_STRUCTURE_MENU_SECTION_RANK } from '@atlaskit/editor-common/block-menu';
@@ -10,7 +10,7 @@ import { findParentNode } from '@atlaskit/editor-prosemirror/utils';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
11
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
12
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
- import { createDefaultLayoutSection, createMultiColumnLayoutSection, insertLayoutColumnsWithAnalytics, toggleLayoutColumnMenu } from './pm-plugins/actions';
13
+ import { createDefaultLayoutSection, createMultiColumnLayoutSection, insertLayoutColumnsWithAnalytics, setLayoutColumnValign, toggleLayoutColumnMenu } from './pm-plugins/actions';
14
14
  import { default as createLayoutPlugin } from './pm-plugins/main';
15
15
  import { pluginKey } from './pm-plugins/plugin-key';
16
16
  import { default as createLayoutResizingPlugin } from './pm-plugins/resizing';
@@ -87,7 +87,10 @@ export var layoutPlugin = function layoutPlugin(_ref) {
87
87
  node: editorExperiment('advanced_layouts', true) ? fg('platform_editor_adf_with_localid') ? layoutSectionWithSingleColumnLocalId : layoutSectionWithSingleColumn : fg('platform_editor_adf_with_localid') ? layoutSectionWithLocalId : layoutSection
88
88
  }, {
89
89
  name: 'layoutColumn',
90
- node: fg('platform_editor_adf_with_localid') ? layoutColumnWithLocalId : layoutColumn
90
+ node: expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true) ?
91
+ // `layoutColumnStage0` includes both `valign` and `localId` attrs, so it remains
92
+ // compatible with `platform_editor_adf_with_localid` when both flags are enabled.
93
+ layoutColumnStage0 : fg('platform_editor_adf_with_localid') ? layoutColumnWithLocalId : layoutColumn
91
94
  }];
92
95
  },
93
96
  pmPlugins: function pmPlugins() {
@@ -299,6 +302,7 @@ export var layoutPlugin = function layoutPlugin(_ref) {
299
302
  return pluginKey.getState(editorState);
300
303
  },
301
304
  commands: {
305
+ setLayoutColumnValign: setLayoutColumnValign,
302
306
  toggleLayoutColumnMenu: toggleLayoutColumnMenu
303
307
  }
304
308
  };
@@ -8,6 +8,7 @@ import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
8
8
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
9
9
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
11
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
12
13
  import { EVEN_DISTRIBUTED_COL_WIDTHS } from './consts';
13
14
  import { pluginKey } from './plugin-key';
@@ -539,10 +540,34 @@ var formatLayoutName = function formatLayoutName(layout) {
539
540
  return LAYOUT_TYPE.THREE_WITH_SIDEBARS;
540
541
  }
541
542
  };
542
- export var toggleLayoutColumnMenu = function toggleLayoutColumnMenu(_ref4) {
543
- var isOpen = _ref4.isOpen;
544
- return function (_ref5) {
545
- var tr = _ref5.tr;
543
+ export var setLayoutColumnValign = function setLayoutColumnValign(valign) {
544
+ return function (_ref4) {
545
+ var tr = _ref4.tr;
546
+ if (!expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true)) {
547
+ return null;
548
+ }
549
+ var layoutColumn = tr.doc.type.schema.nodes.layoutColumn;
550
+ var selectedColumn = tr.selection instanceof NodeSelection && tr.selection.node.type === layoutColumn ? {
551
+ node: tr.selection.node,
552
+ pos: tr.selection.from
553
+ } : undefined;
554
+ if (!selectedColumn) {
555
+ return null;
556
+ }
557
+ if (selectedColumn.node.attrs.valign === valign) {
558
+ return null;
559
+ }
560
+ tr.setNodeMarkup(selectedColumn.pos, selectedColumn.node.type, _objectSpread(_objectSpread({}, selectedColumn.node.attrs), {}, {
561
+ valign: valign
562
+ }));
563
+ tr.setMeta('scrollIntoView', false);
564
+ return tr;
565
+ };
566
+ };
567
+ export var toggleLayoutColumnMenu = function toggleLayoutColumnMenu(_ref5) {
568
+ var isOpen = _ref5.isOpen;
569
+ return function (_ref6) {
570
+ var tr = _ref6.tr;
546
571
  tr.setMeta('toggleLayoutColumnMenu', {
547
572
  isOpen: isOpen
548
573
  });
@@ -0,0 +1,32 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
4
+ import { useCurrentLayoutColumnValign } from './useCurrentLayoutColumnValign';
5
+ import { VERTICAL_ALIGN_ICONS } from './verticalAlignIcons';
6
+ export var VerticalAlignDropdownItem = function VerticalAlignDropdownItem(_ref) {
7
+ var api = _ref.api,
8
+ label = _ref.label,
9
+ value = _ref.value;
10
+ var _useIntl = useIntl(),
11
+ formatMessage = _useIntl.formatMessage;
12
+ var _useCurrentLayoutColu = useCurrentLayoutColumnValign(api),
13
+ currentValign = _useCurrentLayoutColu.currentValign,
14
+ selectedColumn = _useCurrentLayoutColu.selectedColumn;
15
+ var Icon = VERTICAL_ALIGN_ICONS[value];
16
+ var onClick = useCallback(function () {
17
+ var _api$core, _api$layout;
18
+ 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.setLayoutColumnValign(value));
19
+ }, [api, value]);
20
+ if (!selectedColumn) {
21
+ return null;
22
+ }
23
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
24
+ elemBefore: /*#__PURE__*/React.createElement(Icon, {
25
+ label: "",
26
+ size: "small"
27
+ }),
28
+ isSelected: currentValign === value,
29
+ onClick: onClick,
30
+ testId: "layout-column-align-".concat(value)
31
+ }, formatMessage(label));
32
+ };
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { layoutMessages } from '@atlaskit/editor-common/messages';
4
+ import { LayoutIcon, NestedDropdownRightIcon, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
5
+ import { useCurrentLayoutColumnValign } from './useCurrentLayoutColumnValign';
6
+ import { VERTICAL_ALIGN_ICONS } from './verticalAlignIcons';
7
+ export var VerticalAlignNestedMenu = function VerticalAlignNestedMenu(_ref) {
8
+ var api = _ref.api,
9
+ children = _ref.children;
10
+ var _useIntl = useIntl(),
11
+ formatMessage = _useIntl.formatMessage;
12
+ var _useCurrentLayoutColu = useCurrentLayoutColumnValign(api),
13
+ currentValign = _useCurrentLayoutColu.currentValign,
14
+ selectedColumn = _useCurrentLayoutColu.selectedColumn;
15
+ var TriggerIcon = currentValign ? VERTICAL_ALIGN_ICONS[currentValign] : LayoutIcon;
16
+ if (!selectedColumn) {
17
+ return null;
18
+ }
19
+ return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
20
+ elemBefore: /*#__PURE__*/React.createElement(TriggerIcon, {
21
+ label: "",
22
+ size: "small"
23
+ }),
24
+ elemAfter: /*#__PURE__*/React.createElement(NestedDropdownRightIcon, {
25
+ label: "",
26
+ size: "small"
27
+ }),
28
+ text: formatMessage(layoutMessages.alignColumn),
29
+ testId: "layout-column-align-menu",
30
+ dropdownTestId: "layout-column-align-dropdown"
31
+ }, children);
32
+ };
@@ -2,23 +2,13 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
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
+ import { layoutMessages } from '@atlaskit/editor-common/messages';
5
6
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
6
7
  import { ToolbarMenuContainer } from '@atlaskit/editor-toolbar/toolbar-menu-container';
7
8
  import { createDistributeColumnsDropdownItem } from './DistributeColumnsDropdownItem';
8
- export var LAYOUT_COLUMN_MENU = {
9
- key: 'layout-column-menu',
10
- type: 'menu'
11
- };
12
- var LAYOUT_COLUMN_MENU_SECTION = {
13
- key: 'layout-column-menu-section',
14
- type: 'menu-section'
15
- };
16
- var DISTRIBUTE_COLUMNS_MENU_ITEM = {
17
- key: 'layout-column-menu-distribute-columns-item',
18
- type: 'menu-item'
19
- };
20
- var LAYOUT_COLUMN_MENU_RANK = _defineProperty({}, LAYOUT_COLUMN_MENU_SECTION.key, 0);
21
- var LAYOUT_COLUMN_MENU_SECTION_RANK = _defineProperty({}, DISTRIBUTE_COLUMNS_MENU_ITEM.key, 0);
9
+ import { DISTRIBUTE_COLUMNS_MENU_ITEM, LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_RANK, LAYOUT_COLUMN_MENU_SECTION, LAYOUT_COLUMN_MENU_SECTION_RANK, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION, VERTICAL_ALIGN_BOTTOM_MENU_ITEM, VERTICAL_ALIGN_MENU, VERTICAL_ALIGN_MENU_RANK, VERTICAL_ALIGN_MENU_SECTION_RANK, VERTICAL_ALIGN_MIDDLE_MENU_ITEM, VERTICAL_ALIGN_TOP_MENU_ITEM } from './keys';
10
+ import { VerticalAlignDropdownItem } from './VerticalAlignDropdownItem';
11
+ import { VerticalAlignNestedMenu } from './VerticalAlignNestedMenu';
22
12
  export var LAYOUT_COLUMN_MENU_FALLBACKS = {
23
13
  'menu-section': function menuSection(_ref) {
24
14
  var children = _ref.children;
@@ -38,5 +28,52 @@ export var getLayoutColumnMenuComponents = function getLayoutColumnMenuComponent
38
28
  parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
39
29
  rank: LAYOUT_COLUMN_MENU_SECTION_RANK[DISTRIBUTE_COLUMNS_MENU_ITEM.key]
40
30
  })]
31
+ }), _objectSpread(_objectSpread({}, VERTICAL_ALIGN_MENU), {}, {
32
+ component: function component(_ref3) {
33
+ var children = _ref3.children;
34
+ return /*#__PURE__*/React.createElement(VerticalAlignNestedMenu, {
35
+ api: api
36
+ }, children);
37
+ },
38
+ parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_MENU_SECTION), {}, {
39
+ rank: LAYOUT_COLUMN_MENU_SECTION_RANK[VERTICAL_ALIGN_MENU.key]
40
+ })]
41
+ }), _objectSpread(_objectSpread({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION), {}, {
42
+ parents: [_objectSpread(_objectSpread({}, VERTICAL_ALIGN_MENU), {}, {
43
+ rank: VERTICAL_ALIGN_MENU_RANK[LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key]
44
+ })]
45
+ }), _objectSpread(_objectSpread({}, VERTICAL_ALIGN_TOP_MENU_ITEM), {}, {
46
+ component: function component() {
47
+ return /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
48
+ api: api,
49
+ label: layoutMessages.alignColumnTop,
50
+ value: "top"
51
+ });
52
+ },
53
+ parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION), {}, {
54
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_TOP_MENU_ITEM.key]
55
+ })]
56
+ }), _objectSpread(_objectSpread({}, VERTICAL_ALIGN_MIDDLE_MENU_ITEM), {}, {
57
+ component: function component() {
58
+ return /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
59
+ api: api,
60
+ label: layoutMessages.alignColumnMiddle,
61
+ value: "middle"
62
+ });
63
+ },
64
+ parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION), {}, {
65
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_MIDDLE_MENU_ITEM.key]
66
+ })]
67
+ }), _objectSpread(_objectSpread({}, VERTICAL_ALIGN_BOTTOM_MENU_ITEM), {}, {
68
+ component: function component() {
69
+ return /*#__PURE__*/React.createElement(VerticalAlignDropdownItem, {
70
+ api: api,
71
+ label: layoutMessages.alignColumnBottom,
72
+ value: "bottom"
73
+ });
74
+ },
75
+ parents: [_objectSpread(_objectSpread({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION), {}, {
76
+ rank: VERTICAL_ALIGN_MENU_SECTION_RANK[VERTICAL_ALIGN_BOTTOM_MENU_ITEM.key]
77
+ })]
41
78
  })];
42
79
  };
@@ -1,13 +1,14 @@
1
- import React, { useCallback, useEffect } from 'react';
1
+ import React, { useCallback, useContext, useEffect, useRef } from 'react';
2
2
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
3
  import { EditorToolbarProvider } from '@atlaskit/editor-common/toolbar';
4
4
  import { Popup } from '@atlaskit/editor-common/ui';
5
- import { withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
5
+ import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
6
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
8
8
  import { ToolbarDropdownMenuProvider } from '@atlaskit/editor-toolbar';
9
9
  import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model';
10
- import { LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
10
+ import { LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
11
+ import { LAYOUT_COLUMN_MENU } from './keys';
11
12
  var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
12
13
  var LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
13
14
  var getLayoutColumnMenuTarget = function getLayoutColumnMenuTarget(editorView, selectionAnchorPos) {
@@ -36,17 +37,33 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
36
37
  }),
37
38
  isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen,
38
39
  selection = _useSharedPluginState.selection;
40
+ var setOutsideClickTargetRef = useContext(OutsideClickTargetRefContext);
41
+ var menuRef = useRef(null);
39
42
  var closeLayoutColumnMenu = useCallback(function () {
40
43
  var _api$core, _api$layout;
41
44
  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
45
  isOpen: false
43
46
  }));
44
47
  }, [api]);
48
+ var handleClickOutside = useCallback(function (event) {
49
+ var _menuRef$current;
50
+ if (event.target instanceof Node && (_menuRef$current = menuRef.current) !== null && _menuRef$current !== void 0 && _menuRef$current.contains(event.target)) {
51
+ return;
52
+ }
53
+ if (event.target instanceof Element && event.target.closest('[data-toolbar-nested-dropdown-menu]')) {
54
+ return;
55
+ }
56
+ closeLayoutColumnMenu();
57
+ }, [closeLayoutColumnMenu]);
45
58
  var handleSetIsOpen = useCallback(function (isOpen) {
46
59
  if (!isOpen) {
47
60
  closeLayoutColumnMenu();
48
61
  }
49
62
  }, [closeLayoutColumnMenu]);
63
+ var handleMenuRef = useCallback(function (el) {
64
+ setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 || setOutsideClickTargetRef(el);
65
+ menuRef.current = el;
66
+ }, [setOutsideClickTargetRef]);
50
67
  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 : [];
51
68
  var target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
52
69
  var hasValidTarget = target instanceof HTMLElement;
@@ -68,8 +85,10 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
68
85
  alignY: "top",
69
86
  forcePlacement: true,
70
87
  offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
71
- handleClickOutside: closeLayoutColumnMenu,
88
+ handleClickOutside: handleClickOutside,
72
89
  handleEscapeKeydown: closeLayoutColumnMenu
90
+ }, /*#__PURE__*/React.createElement("div", {
91
+ ref: handleMenuRef
73
92
  }, /*#__PURE__*/React.createElement(EditorToolbarProvider, {
74
93
  editorView: editorView
75
94
  }, /*#__PURE__*/React.createElement(ToolbarDropdownMenuProvider, {
@@ -79,5 +98,5 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
79
98
  components: components,
80
99
  fallbacks: LAYOUT_COLUMN_MENU_FALLBACKS,
81
100
  surface: LAYOUT_COLUMN_MENU
82
- }))));
101
+ })))));
83
102
  });
@@ -0,0 +1,51 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ // --- Menu surface ---
3
+
4
+ export var LAYOUT_COLUMN_MENU = {
5
+ type: 'menu',
6
+ key: 'layout-column-menu'
7
+ };
8
+
9
+ // --- Sections ---
10
+
11
+ export var LAYOUT_COLUMN_MENU_SECTION = {
12
+ type: 'menu-section',
13
+ key: 'layout-column-menu-section'
14
+ };
15
+ export var LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION = {
16
+ type: 'menu-section',
17
+ key: 'layout-column-vertical-align-menu-section'
18
+ };
19
+ export var LAYOUT_COLUMN_MENU_RANK = _defineProperty({}, LAYOUT_COLUMN_MENU_SECTION.key, 100);
20
+
21
+ // --- Menus ---
22
+
23
+ export var VERTICAL_ALIGN_MENU = {
24
+ type: 'nested-menu',
25
+ key: 'layout-column-menu-vertical-align-menu'
26
+ };
27
+
28
+ // --- Items ---
29
+
30
+ export var DISTRIBUTE_COLUMNS_MENU_ITEM = {
31
+ type: 'menu-item',
32
+ key: 'layout-column-menu-distribute-columns-item'
33
+ };
34
+ export var VERTICAL_ALIGN_TOP_MENU_ITEM = {
35
+ type: 'menu-item',
36
+ key: 'layout-column-menu-vertical-align-top-item'
37
+ };
38
+ export var VERTICAL_ALIGN_MIDDLE_MENU_ITEM = {
39
+ type: 'menu-item',
40
+ key: 'layout-column-menu-vertical-align-middle-item'
41
+ };
42
+ export var VERTICAL_ALIGN_BOTTOM_MENU_ITEM = {
43
+ type: 'menu-item',
44
+ key: 'layout-column-menu-vertical-align-bottom-item'
45
+ };
46
+
47
+ // --- Item ranks within sections ---
48
+
49
+ export var LAYOUT_COLUMN_MENU_SECTION_RANK = _defineProperty(_defineProperty({}, DISTRIBUTE_COLUMNS_MENU_ITEM.key, 100), VERTICAL_ALIGN_MENU.key, 200);
50
+ export var VERTICAL_ALIGN_MENU_RANK = _defineProperty({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key, 100);
51
+ export var VERTICAL_ALIGN_MENU_SECTION_RANK = _defineProperty(_defineProperty(_defineProperty({}, VERTICAL_ALIGN_TOP_MENU_ITEM.key, 100), VERTICAL_ALIGN_MIDDLE_MENU_ITEM.key, 200), VERTICAL_ALIGN_BOTTOM_MENU_ITEM.key, 300);
@@ -0,0 +1,16 @@
1
+ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
2
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
3
+ export var getCurrentLayoutColumnValign = function getCurrentLayoutColumnValign(selection) {
4
+ var selectedColumn = selection instanceof NodeSelection && selection.node.type.name === 'layoutColumn' ? selection.node : undefined;
5
+ var currentValign = selectedColumn === null || selectedColumn === void 0 ? void 0 : selectedColumn.attrs.valign;
6
+ return {
7
+ currentValign: currentValign,
8
+ selectedColumn: selectedColumn
9
+ };
10
+ };
11
+ export var useCurrentLayoutColumnValign = function useCurrentLayoutColumnValign(api) {
12
+ return useSharedPluginStateWithSelector(api, ['selection'], function (states) {
13
+ var _states$selectionStat;
14
+ return getCurrentLayoutColumnValign((_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection);
15
+ });
16
+ };
@@ -0,0 +1,11 @@
1
+ // Disable no-re-export here, this is a useful mapping file for icon lookup used in multiple places
2
+ /* eslint-disable @atlaskit/editor/no-re-export */
3
+
4
+ import AlignContentBottomIcon from '@atlaskit/icon-lab/core/align-content-bottom';
5
+ import AlignContentCenterVerticalIcon from '@atlaskit/icon-lab/core/align-content-center-vertical';
6
+ import AlignContentTopIcon from '@atlaskit/icon-lab/core/align-content-top';
7
+ export var VERTICAL_ALIGN_ICONS = {
8
+ top: AlignContentTopIcon,
9
+ middle: AlignContentCenterVerticalIcon,
10
+ bottom: AlignContentBottomIcon
11
+ };
@@ -9,7 +9,7 @@ import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
9
9
  import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
10
10
  import type { UiControlRegistryPlugin } from '@atlaskit/editor-plugin-ui-control-registry';
11
11
  import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
12
- import type { insertLayoutColumnsWithAnalytics, toggleLayoutColumnMenu } from './pm-plugins/actions';
12
+ import type { insertLayoutColumnsWithAnalytics, setLayoutColumnValign, toggleLayoutColumnMenu } from './pm-plugins/actions';
13
13
  import type { LayoutState } from './pm-plugins/types';
14
14
  import type { LayoutPluginOptions } from './types';
15
15
  export type LayoutPluginDependencies = [
@@ -29,6 +29,7 @@ export type LayoutPlugin = NextEditorPlugin<'layout', {
29
29
  insertLayoutColumns: ReturnType<typeof insertLayoutColumnsWithAnalytics>;
30
30
  };
31
31
  commands: {
32
+ setLayoutColumnValign: typeof setLayoutColumnValign;
32
33
  toggleLayoutColumnMenu: typeof toggleLayoutColumnMenu;
33
34
  };
34
35
  dependencies: LayoutPluginDependencies;