@atlaskit/editor-plugin-layout 11.0.3 → 11.1.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/layoutPlugin.js +22 -6
  3. package/dist/cjs/nodeviews/index.js +49 -1
  4. package/dist/cjs/pm-plugins/actions.js +30 -10
  5. package/dist/cjs/pm-plugins/keymap.js +31 -0
  6. package/dist/cjs/pm-plugins/main.js +90 -21
  7. package/dist/cjs/pm-plugins/resizing.js +29 -4
  8. package/dist/cjs/pm-plugins/utils/layout-column-selection.js +36 -12
  9. package/dist/cjs/ui/LayoutColumnMenu/DeleteColumnDropdownItem.js +25 -5
  10. package/dist/cjs/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +7 -1
  11. package/dist/cjs/ui/LayoutColumnMenu/index.js +51 -4
  12. package/dist/cjs/ui/LayoutSSRReactContextsProvider.js +34 -0
  13. package/dist/cjs/ui/global-styles.js +11 -1
  14. package/dist/es2019/layoutPlugin.js +21 -7
  15. package/dist/es2019/nodeviews/index.js +49 -1
  16. package/dist/es2019/pm-plugins/actions.js +26 -11
  17. package/dist/es2019/pm-plugins/keymap.js +26 -0
  18. package/dist/es2019/pm-plugins/main.js +97 -25
  19. package/dist/es2019/pm-plugins/resizing.js +37 -7
  20. package/dist/es2019/pm-plugins/utils/layout-column-selection.js +33 -8
  21. package/dist/es2019/ui/LayoutColumnMenu/DeleteColumnDropdownItem.js +26 -6
  22. package/dist/es2019/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +8 -2
  23. package/dist/es2019/ui/LayoutColumnMenu/index.js +52 -5
  24. package/dist/es2019/ui/LayoutSSRReactContextsProvider.js +28 -0
  25. package/dist/es2019/ui/global-styles.js +9 -1
  26. package/dist/esm/layoutPlugin.js +23 -7
  27. package/dist/esm/nodeviews/index.js +49 -1
  28. package/dist/esm/pm-plugins/actions.js +30 -10
  29. package/dist/esm/pm-plugins/keymap.js +25 -0
  30. package/dist/esm/pm-plugins/main.js +90 -21
  31. package/dist/esm/pm-plugins/resizing.js +29 -4
  32. package/dist/esm/pm-plugins/utils/layout-column-selection.js +35 -11
  33. package/dist/esm/ui/LayoutColumnMenu/DeleteColumnDropdownItem.js +26 -6
  34. package/dist/esm/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +8 -2
  35. package/dist/esm/ui/LayoutColumnMenu/index.js +52 -5
  36. package/dist/esm/ui/LayoutSSRReactContextsProvider.js +27 -0
  37. package/dist/esm/ui/global-styles.js +11 -1
  38. package/dist/types/layoutPluginType.d.ts +5 -7
  39. package/dist/types/nodeviews/index.d.ts +5 -0
  40. package/dist/types/pm-plugins/actions.d.ts +8 -4
  41. package/dist/types/pm-plugins/keymap.d.ts +10 -0
  42. package/dist/types/pm-plugins/resizing.d.ts +2 -1
  43. package/dist/types/pm-plugins/types.d.ts +2 -0
  44. package/dist/types/pm-plugins/utils/layout-column-selection.d.ts +1 -0
  45. package/dist/types/ui/LayoutSSRReactContextsProvider.d.ts +19 -0
  46. package/dist/types-ts4.5/layoutPluginType.d.ts +5 -7
  47. package/dist/types-ts4.5/nodeviews/index.d.ts +5 -0
  48. package/dist/types-ts4.5/pm-plugins/actions.d.ts +8 -4
  49. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +10 -0
  50. package/dist/types-ts4.5/pm-plugins/resizing.d.ts +2 -1
  51. package/dist/types-ts4.5/pm-plugins/types.d.ts +2 -0
  52. package/dist/types-ts4.5/pm-plugins/utils/layout-column-selection.d.ts +1 -0
  53. package/dist/types-ts4.5/ui/LayoutSSRReactContextsProvider.d.ts +19 -0
  54. package/package.json +5 -5
@@ -1,7 +1,9 @@
1
- import React, { useCallback, useEffect, useMemo } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
2
+ import { bind } from 'bind-event-listener';
2
3
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
4
  import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
4
5
  import { Popup } from '@atlaskit/editor-common/ui';
6
+ import { ArrowKeyNavigationProvider, ArrowKeyNavigationType } from '@atlaskit/editor-common/ui-menu';
5
7
  import { withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
8
  import { UserIntentPopupWrapper } from '@atlaskit/editor-common/user-intent';
7
9
  import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
@@ -13,6 +15,7 @@ import { LAYOUT_COLUMN_MENU } from './keys';
13
15
  var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
14
16
  var LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 4];
15
17
  var TOOLBAR_MENU_SELECTOR = '[data-toolbar-component="menu"]';
18
+ var NESTED_DROPDOWN_MENU_SELECTOR = '[data-toolbar-nested-dropdown-menu]';
16
19
 
17
20
  /**
18
21
  * Returns the drag handle button for the selected layout column.
@@ -30,6 +33,9 @@ var getLayoutColumnMenuTarget = function getLayoutColumnMenuTarget(editorView, s
30
33
  var dragHandleContainer = (_columnDomRef$parentE = columnDomRef.parentElement) === null || _columnDomRef$parentE === void 0 ? void 0 : _columnDomRef$parentE.querySelector(':scope > [data-blocks-drag-handle-container]');
31
34
  return dragHandleContainer === null || dragHandleContainer === void 0 ? void 0 : dragHandleContainer.querySelector(DRAG_HANDLE_SELECTOR);
32
35
  };
36
+ var focusTrap = {
37
+ initialFocus: undefined
38
+ };
33
39
  export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(_ref) {
34
40
  var _api$uiControlRegistr, _api$uiControlRegistr2;
35
41
  var api = _ref.api,
@@ -38,15 +44,17 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
38
44
  boundariesElement = _ref.boundariesElement,
39
45
  scrollableElement = _ref.scrollableElement;
40
46
  var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['layout', 'selection'], function (states) {
41
- var _states$layoutState$i, _states$layoutState, _states$layoutState2, _states$selectionStat;
47
+ var _states$layoutState$i, _states$layoutState, _states$layoutState2, _states$layoutState$l, _states$layoutState3, _states$selectionStat;
42
48
  return {
43
49
  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,
44
50
  layoutColumnMenuAnchorPos: (_states$layoutState2 = states.layoutState) === null || _states$layoutState2 === void 0 ? void 0 : _states$layoutState2.layoutColumnMenuAnchorPos,
51
+ openedViaKeyboard: (_states$layoutState$l = (_states$layoutState3 = states.layoutState) === null || _states$layoutState3 === void 0 ? void 0 : _states$layoutState3.layoutColumnMenuOpenedViaKeyboard) !== null && _states$layoutState$l !== void 0 ? _states$layoutState$l : false,
45
52
  selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection
46
53
  };
47
54
  }),
48
55
  isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen,
49
56
  layoutColumnMenuAnchorPos = _useSharedPluginState.layoutColumnMenuAnchorPos,
57
+ openedViaKeyboard = _useSharedPluginState.openedViaKeyboard,
50
58
  selection = _useSharedPluginState.selection;
51
59
  var closeLayoutColumnMenu = useCallback(function () {
52
60
  var _api$core, _api$layout;
@@ -55,7 +63,7 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
55
63
  }));
56
64
  }, [api]);
57
65
  var handleClickOutside = useCallback(function (event) {
58
- if (event.target instanceof Element && (event.target.closest(TOOLBAR_MENU_SELECTOR) || event.target.closest('[data-toolbar-nested-dropdown-menu]'))) {
66
+ if (event.target instanceof Element && (event.target.closest(TOOLBAR_MENU_SELECTOR) || event.target.closest(NESTED_DROPDOWN_MENU_SELECTOR))) {
59
67
  return;
60
68
  }
61
69
 
@@ -72,6 +80,38 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
72
80
  closeLayoutColumnMenu();
73
81
  }
74
82
  }, [closeLayoutColumnMenu]);
83
+ var handleArrowKeyNavigationClose = useCallback(function (event) {
84
+ event.preventDefault();
85
+ closeLayoutColumnMenu();
86
+ }, [closeLayoutColumnMenu]);
87
+ var shouldDisableArrowKeyNavigation = useCallback(function (event) {
88
+ if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') {
89
+ return false;
90
+ }
91
+ var target = event.target;
92
+ if (!(target instanceof HTMLElement)) {
93
+ return false;
94
+ }
95
+ return target.closest(NESTED_DROPDOWN_MENU_SELECTOR) !== null;
96
+ }, []);
97
+ var menuWrapperRef = useRef(null);
98
+ var handleMenuKeyDown = useCallback(function (event) {
99
+ // Keep menu keyboard events scoped to the menu while preserving Escape and
100
+ // ArrowUp/ArrowDown handling from Popup and ArrowKeyNavigationProvider.
101
+ if (event.key !== 'Escape' && event.key !== 'ArrowUp' && event.key !== 'ArrowDown') {
102
+ event.stopPropagation();
103
+ }
104
+ }, []);
105
+ useEffect(function () {
106
+ var menuWrapper = menuWrapperRef.current;
107
+ if (!isLayoutColumnMenuOpen || !menuWrapper) {
108
+ return;
109
+ }
110
+ return bind(menuWrapper, {
111
+ type: 'keydown',
112
+ listener: handleMenuKeyDown
113
+ });
114
+ }, [handleMenuKeyDown, isLayoutColumnMenuOpen]);
75
115
  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 : [];
76
116
  var target = useMemo(function () {
77
117
  return isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection, layoutColumnMenuAnchorPos) : null;
@@ -96,16 +136,23 @@ export var LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu(
96
136
  stick: true,
97
137
  offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
98
138
  handleClickOutside: handleClickOutside,
99
- handleEscapeKeydown: closeLayoutColumnMenu
139
+ handleEscapeKeydown: closeLayoutColumnMenu,
140
+ focusTrap: openedViaKeyboard ? focusTrap : undefined
141
+ }, /*#__PURE__*/React.createElement("div", {
142
+ ref: menuWrapperRef
100
143
  }, /*#__PURE__*/React.createElement(UserIntentPopupWrapper, {
101
144
  api: api,
102
145
  userIntent: "layoutColumnMenuPopupOpen"
103
146
  }, /*#__PURE__*/React.createElement(ToolbarDropdownMenuProvider, {
104
147
  isOpen: isLayoutColumnMenuOpen,
105
148
  setIsOpen: handleSetIsOpen
149
+ }, /*#__PURE__*/React.createElement(ArrowKeyNavigationProvider, {
150
+ type: ArrowKeyNavigationType.MENU,
151
+ handleClose: handleArrowKeyNavigationClose,
152
+ disableArrowKeyNavigation: shouldDisableArrowKeyNavigation
106
153
  }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
107
154
  components: components,
108
155
  fallbacks: LAYOUT_COLUMN_MENU_FALLBACKS,
109
156
  surface: LAYOUT_COLUMN_MENU
110
- }))));
157
+ }))))));
111
158
  });
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import { RawIntlProvider } from 'react-intl';
3
+ import { isSSR, isSSRStreaming } from '@atlaskit/editor-common/core-utils';
4
+ /**
5
+ * Wraps the layout section nodeview children with the editor's actual
6
+ * IntlProvider during SSR streaming (renderToStaticMarkup). This ensures any
7
+ * descendants that call `useIntl()` (e.g. `BreakoutResizer`'s ARIA labels)
8
+ * have a valid intl context and do not throw during the static render pass.
9
+ *
10
+ * Outside of SSR streaming this is a no-op passthrough.
11
+ *
12
+ * Follows the same pattern as `MediaSSRReactContextsProvider` and
13
+ * `SyncBlockSSRReactContextsProvider`.
14
+ */
15
+ export function LayoutSSRReactContextsProvider(_ref) {
16
+ var children = _ref.children,
17
+ intl = _ref.intl;
18
+ if (!isSSRStreaming() || !isSSR()) {
19
+ return children;
20
+ }
21
+ if (!intl) {
22
+ return children;
23
+ }
24
+ return /*#__PURE__*/React.createElement(RawIntlProvider, {
25
+ value: intl
26
+ }, children);
27
+ }
@@ -11,6 +11,13 @@ import { useIntl } from 'react-intl';
11
11
  import { layoutMessages as messages } from '@atlaskit/editor-common/messages';
12
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
13
  var PLACEHOLDER_SELECTOR = '.ProseMirror-focused .layoutSectionView-content-wrap.selected [data-layout-column] > [data-layout-content] > p:only-child:has(.ProseMirror-trailingBreak:only-child)';
14
+ var layoutColumnDangerPreviewStyle = css({
15
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766
16
+ '.ProseMirror [data-layout-column].layout-column-danger-preview': {
17
+ backgroundColor: "var(--ds-background-danger, #FFECEB)",
18
+ boxShadow: "inset 0 0 0 2px ".concat("var(--ds-border-danger, #E2483D)")
19
+ }
20
+ });
14
21
  var getPlaceholderStyle = function getPlaceholderStyle(message) {
15
22
  if (editorExperiment('platform_editor_controls', 'variant1')) {
16
23
  return css(_defineProperty({}, "".concat(PLACEHOLDER_SELECTOR), {
@@ -48,7 +55,10 @@ export var GlobalStylesWrapper = function GlobalStylesWrapper() {
48
55
  var placeholderText = editorExperiment('platform_editor_controls', 'variant1') ? messages.controlslayoutPlaceholder : messages.layoutPlaceholder;
49
56
  return getPlaceholderStyle(formatMessage(placeholderText));
50
57
  }, [formatMessage]);
58
+ var globalStyles = useMemo(function () {
59
+ return [placeholderStyle, layoutColumnDangerPreviewStyle];
60
+ }, [placeholderStyle]);
51
61
  return jsx(Global, {
52
- styles: placeholderStyle
62
+ styles: globalStyles
53
63
  });
54
64
  };
@@ -12,7 +12,7 @@ import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
12
12
  import type { UiControlRegistryPlugin } from '@atlaskit/editor-plugin-ui-control-registry';
13
13
  import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
14
14
  import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
15
- import type { DistributeLayoutColumnsOptions, InsertLayoutColumnsInputMethod, InsertLayoutColumnSide } from './pm-plugins/actions';
15
+ import type { DistributeLayoutColumnsOptions, InsertLayoutColumnSide, InsertLayoutColumnsInputMethod, LayoutColumnActionInputMethod, ToggleLayoutColumnMenuOptions } from './pm-plugins/actions';
16
16
  import type { LayoutState } from './pm-plugins/types';
17
17
  import type { LayoutPluginOptions } from './types';
18
18
  export type LayoutPluginDependencies = [
@@ -34,14 +34,12 @@ export type LayoutPlugin = NextEditorPlugin<'layout', {
34
34
  insertLayoutColumns: (inputMethod: InsertLayoutColumnsInputMethod) => Command;
35
35
  };
36
36
  commands: {
37
- deleteLayoutColumn: EditorCommand;
37
+ deleteLayoutColumn: (inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
38
38
  distributeLayoutColumns: (options?: DistributeLayoutColumnsOptions) => EditorCommand;
39
- insertLayoutColumn: (side: InsertLayoutColumnSide) => EditorCommand;
39
+ insertLayoutColumn: (side: InsertLayoutColumnSide, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
40
+ setLayoutColumnDangerPreview: (show: boolean) => EditorCommand;
40
41
  setLayoutColumnValign: (valign: Valign) => EditorCommand;
41
- toggleLayoutColumnMenu: (options: {
42
- anchorPos?: number;
43
- isOpen?: boolean;
44
- }) => EditorCommand;
42
+ toggleLayoutColumnMenu: (options: ToggleLayoutColumnMenuOptions) => EditorCommand;
45
43
  };
46
44
  dependencies: LayoutPluginDependencies;
47
45
  pluginConfiguration: LayoutPluginOptions | undefined;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { IntlShape } from 'react-intl';
2
3
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
4
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
4
5
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
@@ -10,6 +11,7 @@ import type { LayoutPluginOptions } from '../types';
10
11
  type LayoutSectionViewProps = {
11
12
  eventDispatcher: EventDispatcher;
12
13
  getPos: getPosHandlerNode;
14
+ intl?: IntlShape;
13
15
  node: PMNode;
14
16
  options: LayoutPluginOptions;
15
17
  pluginInjectionApi?: ExtractInjectionAPI<LayoutPlugin>;
@@ -24,6 +26,7 @@ export declare class LayoutSectionView extends ReactNodeView<LayoutSectionViewPr
24
26
  options: LayoutPluginOptions;
25
27
  layoutDOM?: HTMLElement;
26
28
  isEmpty?: boolean;
29
+ private intl?;
27
30
  /**
28
31
  * constructor
29
32
  * @param props
@@ -34,11 +37,13 @@ export declare class LayoutSectionView extends ReactNodeView<LayoutSectionViewPr
34
37
  * @param props.eventDispatcher
35
38
  * @param props.pluginInjectionApi
36
39
  * @param props.options
40
+ * @param props.intl
37
41
  * @example
38
42
  */
39
43
  constructor(props: {
40
44
  eventDispatcher: EventDispatcher;
41
45
  getPos: getPosHandlerNode;
46
+ intl?: IntlShape;
42
47
  node: PMNode;
43
48
  options: LayoutPluginOptions;
44
49
  pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>;
@@ -37,20 +37,24 @@ export type LayoutColumnInsertMeta = {
37
37
  side: InsertLayoutColumnSide;
38
38
  };
39
39
  type LayoutPluginAPI = ExtractInjectionAPI<LayoutPlugin> | undefined;
40
+ export type LayoutColumnActionInputMethod = INPUT_METHOD.LAYOUT_COLUMN_MENU | INPUT_METHOD.KEYBOARD;
40
41
  /**
41
42
  * Returns the active maximum layout column count for the current advanced layouts experiment state.
42
43
  */
43
44
  export declare function getEffectiveMaxLayoutColumns(): number;
44
- export declare const insertLayoutColumn: (side: InsertLayoutColumnSide, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
45
+ export declare const insertLayoutColumn: (side: InsertLayoutColumnSide, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
45
46
  export declare const setLayoutColumnValign: (valign: Valign, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
46
47
  export type DistributeLayoutColumnsOptions = {
47
48
  inputMethod?: INPUT_METHOD.LAYOUT_COLUMN_MENU | INPUT_METHOD.FLOATING_TB;
48
49
  target?: 'selectedColumns' | 'allColumns';
49
50
  };
50
51
  export declare const distributeLayoutColumns: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => ({ inputMethod, target, }?: DistributeLayoutColumnsOptions) => EditorCommand;
51
- export declare const toggleLayoutColumnMenu: ({ anchorPos, isOpen }: {
52
+ export type ToggleLayoutColumnMenuOptions = {
52
53
  anchorPos?: number;
53
54
  isOpen?: boolean;
54
- }) => EditorCommand;
55
- export declare const deleteLayoutColumn: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
55
+ openedViaKeyboard?: boolean;
56
+ };
57
+ export declare const toggleLayoutColumnMenu: ({ anchorPos, isOpen, openedViaKeyboard }: ToggleLayoutColumnMenuOptions) => EditorCommand;
58
+ export declare const setLayoutColumnDangerPreview: (show: boolean) => EditorCommand;
59
+ export declare const deleteLayoutColumn: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
56
60
  export {};
@@ -0,0 +1,10 @@
1
+ import type { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { LayoutPlugin } from '../layoutPluginType';
4
+ /**
5
+ * Creates shortcut handlers for layout column actions.
6
+ */
7
+ declare function keymapPlugin({ api }: {
8
+ api: ExtractInjectionAPI<LayoutPlugin> | undefined;
9
+ }): SafePlugin;
10
+ export default keymapPlugin;
@@ -1,3 +1,4 @@
1
+ import type { IntlShape } from 'react-intl';
1
2
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
2
3
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
@@ -6,5 +7,5 @@ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
7
  import type { LayoutPlugin } from '../layoutPluginType';
7
8
  import type { LayoutPluginOptions } from '../types';
8
9
  export declare const pluginKey: PluginKey;
9
- declare const _default: (options: LayoutPluginOptions, pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher) => SafePlugin<undefined>;
10
+ declare const _default: (options: LayoutPluginOptions, pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher, intl?: IntlShape) => SafePlugin<undefined>;
10
11
  export default _default;
@@ -4,9 +4,11 @@ export type LayoutState = {
4
4
  addSidebarLayouts: boolean;
5
5
  allowBreakout: boolean;
6
6
  allowSingleColumnLayout: boolean;
7
+ dangerPreviewLayoutColumnPositions: number[] | undefined;
7
8
  isLayoutColumnMenuOpen: boolean;
8
9
  isResizing: boolean;
9
10
  layoutColumnMenuAnchorPos: number | undefined;
11
+ layoutColumnMenuOpenedViaKeyboard: boolean;
10
12
  pos: number | null;
11
13
  selectedLayout: PresetLayout | undefined;
12
14
  };
@@ -13,6 +13,7 @@ export type SelectedLayoutColumns = {
13
13
  startIndex: number;
14
14
  };
15
15
  export declare const getSelectedLayoutColumnsFromSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
16
+ export declare const getLayoutColumnsFromContentSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
16
17
  export declare const getAllLayoutColumnsFromSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
17
18
  export declare const getLayoutColumnValign: (layoutColumn: PMNode | undefined) => Valign | undefined;
18
19
  export declare const getLayoutColumnMenuAnchorPos: (selection: Selection, anchorPosFromHandle?: number) => number | undefined;
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type IntlShape } from 'react-intl';
3
+ interface Props {
4
+ children: ReactNode;
5
+ intl: IntlShape | undefined;
6
+ }
7
+ /**
8
+ * Wraps the layout section nodeview children with the editor's actual
9
+ * IntlProvider during SSR streaming (renderToStaticMarkup). This ensures any
10
+ * descendants that call `useIntl()` (e.g. `BreakoutResizer`'s ARIA labels)
11
+ * have a valid intl context and do not throw during the static render pass.
12
+ *
13
+ * Outside of SSR streaming this is a no-op passthrough.
14
+ *
15
+ * Follows the same pattern as `MediaSSRReactContextsProvider` and
16
+ * `SyncBlockSSRReactContextsProvider`.
17
+ */
18
+ export declare function LayoutSSRReactContextsProvider({ children, intl }: Props): ReactNode;
19
+ export {};
@@ -12,7 +12,7 @@ import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
12
12
  import type { UiControlRegistryPlugin } from '@atlaskit/editor-plugin-ui-control-registry';
13
13
  import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
14
14
  import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
15
- import type { DistributeLayoutColumnsOptions, InsertLayoutColumnsInputMethod, InsertLayoutColumnSide } from './pm-plugins/actions';
15
+ import type { DistributeLayoutColumnsOptions, InsertLayoutColumnSide, InsertLayoutColumnsInputMethod, LayoutColumnActionInputMethod, ToggleLayoutColumnMenuOptions } from './pm-plugins/actions';
16
16
  import type { LayoutState } from './pm-plugins/types';
17
17
  import type { LayoutPluginOptions } from './types';
18
18
  export type LayoutPluginDependencies = [
@@ -34,14 +34,12 @@ export type LayoutPlugin = NextEditorPlugin<'layout', {
34
34
  insertLayoutColumns: (inputMethod: InsertLayoutColumnsInputMethod) => Command;
35
35
  };
36
36
  commands: {
37
- deleteLayoutColumn: EditorCommand;
37
+ deleteLayoutColumn: (inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
38
38
  distributeLayoutColumns: (options?: DistributeLayoutColumnsOptions) => EditorCommand;
39
- insertLayoutColumn: (side: InsertLayoutColumnSide) => EditorCommand;
39
+ insertLayoutColumn: (side: InsertLayoutColumnSide, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
40
+ setLayoutColumnDangerPreview: (show: boolean) => EditorCommand;
40
41
  setLayoutColumnValign: (valign: Valign) => EditorCommand;
41
- toggleLayoutColumnMenu: (options: {
42
- anchorPos?: number;
43
- isOpen?: boolean;
44
- }) => EditorCommand;
42
+ toggleLayoutColumnMenu: (options: ToggleLayoutColumnMenuOptions) => EditorCommand;
45
43
  };
46
44
  dependencies: LayoutPluginDependencies;
47
45
  pluginConfiguration: LayoutPluginOptions | undefined;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { IntlShape } from 'react-intl';
2
3
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
4
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
4
5
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
@@ -10,6 +11,7 @@ import type { LayoutPluginOptions } from '../types';
10
11
  type LayoutSectionViewProps = {
11
12
  eventDispatcher: EventDispatcher;
12
13
  getPos: getPosHandlerNode;
14
+ intl?: IntlShape;
13
15
  node: PMNode;
14
16
  options: LayoutPluginOptions;
15
17
  pluginInjectionApi?: ExtractInjectionAPI<LayoutPlugin>;
@@ -24,6 +26,7 @@ export declare class LayoutSectionView extends ReactNodeView<LayoutSectionViewPr
24
26
  options: LayoutPluginOptions;
25
27
  layoutDOM?: HTMLElement;
26
28
  isEmpty?: boolean;
29
+ private intl?;
27
30
  /**
28
31
  * constructor
29
32
  * @param props
@@ -34,11 +37,13 @@ export declare class LayoutSectionView extends ReactNodeView<LayoutSectionViewPr
34
37
  * @param props.eventDispatcher
35
38
  * @param props.pluginInjectionApi
36
39
  * @param props.options
40
+ * @param props.intl
37
41
  * @example
38
42
  */
39
43
  constructor(props: {
40
44
  eventDispatcher: EventDispatcher;
41
45
  getPos: getPosHandlerNode;
46
+ intl?: IntlShape;
42
47
  node: PMNode;
43
48
  options: LayoutPluginOptions;
44
49
  pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>;
@@ -37,20 +37,24 @@ export type LayoutColumnInsertMeta = {
37
37
  side: InsertLayoutColumnSide;
38
38
  };
39
39
  type LayoutPluginAPI = ExtractInjectionAPI<LayoutPlugin> | undefined;
40
+ export type LayoutColumnActionInputMethod = INPUT_METHOD.LAYOUT_COLUMN_MENU | INPUT_METHOD.KEYBOARD;
40
41
  /**
41
42
  * Returns the active maximum layout column count for the current advanced layouts experiment state.
42
43
  */
43
44
  export declare function getEffectiveMaxLayoutColumns(): number;
44
- export declare const insertLayoutColumn: (side: InsertLayoutColumnSide, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
45
+ export declare const insertLayoutColumn: (side: InsertLayoutColumnSide, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
45
46
  export declare const setLayoutColumnValign: (valign: Valign, editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
46
47
  export type DistributeLayoutColumnsOptions = {
47
48
  inputMethod?: INPUT_METHOD.LAYOUT_COLUMN_MENU | INPUT_METHOD.FLOATING_TB;
48
49
  target?: 'selectedColumns' | 'allColumns';
49
50
  };
50
51
  export declare const distributeLayoutColumns: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => ({ inputMethod, target, }?: DistributeLayoutColumnsOptions) => EditorCommand;
51
- export declare const toggleLayoutColumnMenu: ({ anchorPos, isOpen }: {
52
+ export type ToggleLayoutColumnMenuOptions = {
52
53
  anchorPos?: number;
53
54
  isOpen?: boolean;
54
- }) => EditorCommand;
55
- export declare const deleteLayoutColumn: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI) => EditorCommand;
55
+ openedViaKeyboard?: boolean;
56
+ };
57
+ export declare const toggleLayoutColumnMenu: ({ anchorPos, isOpen, openedViaKeyboard }: ToggleLayoutColumnMenuOptions) => EditorCommand;
58
+ export declare const setLayoutColumnDangerPreview: (show: boolean) => EditorCommand;
59
+ export declare const deleteLayoutColumn: (editorAnalyticsAPI?: EditorAnalyticsAPI, api?: LayoutPluginAPI, inputMethod?: LayoutColumnActionInputMethod) => EditorCommand;
56
60
  export {};
@@ -0,0 +1,10 @@
1
+ import type { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { LayoutPlugin } from '../layoutPluginType';
4
+ /**
5
+ * Creates shortcut handlers for layout column actions.
6
+ */
7
+ declare function keymapPlugin({ api }: {
8
+ api: ExtractInjectionAPI<LayoutPlugin> | undefined;
9
+ }): SafePlugin;
10
+ export default keymapPlugin;
@@ -1,3 +1,4 @@
1
+ import type { IntlShape } from 'react-intl';
1
2
  import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
2
3
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
3
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
@@ -6,5 +7,5 @@ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
7
  import type { LayoutPlugin } from '../layoutPluginType';
7
8
  import type { LayoutPluginOptions } from '../types';
8
9
  export declare const pluginKey: PluginKey;
9
- declare const _default: (options: LayoutPluginOptions, pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher) => SafePlugin<undefined>;
10
+ declare const _default: (options: LayoutPluginOptions, pluginInjectionApi: ExtractInjectionAPI<LayoutPlugin>, portalProviderAPI: PortalProviderAPI, eventDispatcher: EventDispatcher, intl?: IntlShape) => SafePlugin<undefined>;
10
11
  export default _default;
@@ -4,9 +4,11 @@ export type LayoutState = {
4
4
  addSidebarLayouts: boolean;
5
5
  allowBreakout: boolean;
6
6
  allowSingleColumnLayout: boolean;
7
+ dangerPreviewLayoutColumnPositions: number[] | undefined;
7
8
  isLayoutColumnMenuOpen: boolean;
8
9
  isResizing: boolean;
9
10
  layoutColumnMenuAnchorPos: number | undefined;
11
+ layoutColumnMenuOpenedViaKeyboard: boolean;
10
12
  pos: number | null;
11
13
  selectedLayout: PresetLayout | undefined;
12
14
  };
@@ -13,6 +13,7 @@ export type SelectedLayoutColumns = {
13
13
  startIndex: number;
14
14
  };
15
15
  export declare const getSelectedLayoutColumnsFromSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
16
+ export declare const getLayoutColumnsFromContentSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
16
17
  export declare const getAllLayoutColumnsFromSelection: (selection: Selection) => SelectedLayoutColumns | undefined;
17
18
  export declare const getLayoutColumnValign: (layoutColumn: PMNode | undefined) => Valign | undefined;
18
19
  export declare const getLayoutColumnMenuAnchorPos: (selection: Selection, anchorPosFromHandle?: number) => number | undefined;
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type IntlShape } from 'react-intl';
3
+ interface Props {
4
+ children: ReactNode;
5
+ intl: IntlShape | undefined;
6
+ }
7
+ /**
8
+ * Wraps the layout section nodeview children with the editor's actual
9
+ * IntlProvider during SSR streaming (renderToStaticMarkup). This ensures any
10
+ * descendants that call `useIntl()` (e.g. `BreakoutResizer`'s ARIA labels)
11
+ * have a valid intl context and do not throw during the static render pass.
12
+ *
13
+ * Outside of SSR streaming this is a no-op passthrough.
14
+ *
15
+ * Follows the same pattern as `MediaSSRReactContextsProvider` and
16
+ * `SyncBlockSSRReactContextsProvider`.
17
+ */
18
+ export declare function LayoutSSRReactContextsProvider({ children, intl }: Props): ReactNode;
19
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-layout",
3
- "version": "11.0.3",
3
+ "version": "11.1.0",
4
4
  "description": "Layout plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -32,7 +32,7 @@
32
32
  "@atlaskit/adf-schema": "^52.16.0",
33
33
  "@atlaskit/css": "^0.19.0",
34
34
  "@atlaskit/editor-plugin-analytics": "^11.0.0",
35
- "@atlaskit/editor-plugin-block-controls": "^12.0.0",
35
+ "@atlaskit/editor-plugin-block-controls": "^12.1.0",
36
36
  "@atlaskit/editor-plugin-block-menu": "^10.1.0",
37
37
  "@atlaskit/editor-plugin-decorations": "^11.0.0",
38
38
  "@atlaskit/editor-plugin-editor-disabled": "^11.0.0",
@@ -50,14 +50,14 @@
50
50
  "@atlaskit/icon": "^35.4.0",
51
51
  "@atlaskit/icon-lab": "^6.13.0",
52
52
  "@atlaskit/platform-feature-flags": "^1.1.0",
53
- "@atlaskit/tmp-editor-statsig": "^89.0.0",
54
- "@atlaskit/tokens": "^13.1.0",
53
+ "@atlaskit/tmp-editor-statsig": "^89.4.0",
54
+ "@atlaskit/tokens": "^13.3.0",
55
55
  "@babel/runtime": "^7.0.0",
56
56
  "@emotion/react": "^11.7.1",
57
57
  "bind-event-listener": "^3.0.0"
58
58
  },
59
59
  "peerDependencies": {
60
- "@atlaskit/editor-common": "^115.3.0",
60
+ "@atlaskit/editor-common": "^115.7.0",
61
61
  "react": "^18.2.0",
62
62
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
63
63
  },