@atlaskit/editor-plugin-block-menu 5.2.27 → 6.0.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,23 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 6.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [`4da819b186eaf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4da819b186eaf) -
8
+ EDITOR-3911 selection preservation key handling
9
+ - [`2f000c01bd8ac`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2f000c01bd8ac) -
10
+ Retain block marks for text -> text transforms
11
+ - Updated dependencies
12
+
13
+ ## 5.2.28
14
+
15
+ ### Patch Changes
16
+
17
+ - [`8c62a0141a5fa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8c62a0141a5fa) -
18
+ [ux] Fixes contextual transform options for direct children of top level nodes.
19
+ - Updated dependencies
20
+
3
21
  ## 5.2.27
4
22
 
5
23
  ### Patch Changes
@@ -28,7 +28,9 @@ var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
28
28
  pmPlugins: function pmPlugins() {
29
29
  return [{
30
30
  name: 'blockMenuPlugin',
31
- plugin: _main.createPlugin
31
+ plugin: function plugin() {
32
+ return (0, _main.createPlugin)(api);
33
+ }
32
34
  }];
33
35
  },
34
36
  actions: {
@@ -9,13 +9,19 @@ var _model = require("@atlaskit/editor-prosemirror/model");
9
9
  var _transform = require("../editor-commands/transform-node-utils/transform");
10
10
  var _types = require("../editor-commands/transform-node-utils/types");
11
11
  var _utils = require("../editor-commands/transform-node-utils/utils");
12
- var canParentContainNodeType = exports.canParentContainNodeType = function canParentContainNodeType(schema, parentNode, nodeTypeName, nodeTypeAttrs) {
13
- var adjustedNodeTypeName = (0, _utils.getTargetNodeTypeNameInContext)(nodeTypeName, true);
12
+ var canParentContainNodeType = exports.canParentContainNodeType = function canParentContainNodeType(schema, selectedNodeTypeName, parentNode, nodeTypeName, nodeTypeAttrs) {
13
+ var adjustedNodeTypeName = parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock' ? nodeTypeName : (0, _utils.getTargetNodeTypeNameInContext)(nodeTypeName, true);
14
14
  if (!adjustedNodeTypeName) {
15
15
  return false;
16
16
  }
17
17
  var nodeType = schema.nodes[adjustedNodeTypeName];
18
- return parentNode.type.validContent(_model.Fragment.from(nodeType.createAndFill(nodeTypeAttrs)));
18
+ var content = null;
19
+ var nodesThatCantBeNestedInNestedExpand = ['blockCard', 'embedCard', 'table'];
20
+ if (nodesThatCantBeNestedInNestedExpand.includes(selectedNodeTypeName) && (adjustedNodeTypeName === 'expand' || adjustedNodeTypeName === 'nestedExpand')) {
21
+ var table = schema.nodes[selectedNodeTypeName];
22
+ content = table.createAndFill();
23
+ }
24
+ return parentNode.type.validContent(_model.Fragment.from(nodeType.createAndFill(nodeTypeAttrs, content)));
19
25
  };
20
26
  var isHeadingToHeadingTransformEnabled = function isHeadingToHeadingTransformEnabled(selectedNode, targetNodeTypeAttrs) {
21
27
  var _selectedNode$attrs;
@@ -38,7 +44,7 @@ var isTransformEnabledForNode = function isTransformEnabledForNode(node, targetN
38
44
  if (selectedNodeTypeName === 'heading' && targetNodeTypeName === 'heading') {
39
45
  return isHeadingToHeadingTransformEnabled(node, targetNodeTypeAttrs);
40
46
  }
41
- if (isNested && !canParentContainNodeType(schema, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
47
+ if (isNested && !canParentContainNodeType(schema, selectedNodeTypeName, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
42
48
  return false;
43
49
  }
44
50
  return true;
@@ -7,8 +7,9 @@ exports.flattenStep = void 0;
7
7
  var flattenStep = exports.flattenStep = function flattenStep(nodes, context) {
8
8
  var schema = context.schema,
9
9
  targetNodeTypeName = context.targetNodeTypeName;
10
+ var paragraph = schema.nodes.paragraph;
10
11
  var targetNodeType = schema.nodes[targetNodeTypeName];
11
- if (!targetNodeType) {
12
+ if (!targetNodeType || !paragraph) {
12
13
  return nodes;
13
14
  }
14
15
 
@@ -26,6 +27,6 @@ var flattenStep = exports.flattenStep = function flattenStep(nodes, context) {
26
27
  if (!isValidWithin) {
27
28
  return node;
28
29
  }
29
- return schema.nodes.paragraph.create({}, node.content);
30
+ return paragraph.create({}, node.content, node.marks);
30
31
  });
31
32
  };
@@ -42,7 +42,7 @@ var applyTargetTextTypeStep = exports.applyTargetTextTypeStep = function applyTa
42
42
  // Convert textblock nodes (paragraphs, headings) to heading with specified level
43
43
  return headingType.create({
44
44
  level: headingLevel
45
- }, node.content);
45
+ }, node.content, node.marks);
46
46
  }
47
47
  // Non-textblock nodes are left unchanged
48
48
  return node;
@@ -7,7 +7,7 @@ exports.createPlugin = exports.blockMenuPluginKey = void 0;
7
7
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
8
8
  var _state = require("@atlaskit/editor-prosemirror/state");
9
9
  var blockMenuPluginKey = exports.blockMenuPluginKey = new _state.PluginKey('blockMenuPlugin');
10
- var createPlugin = exports.createPlugin = function createPlugin() {
10
+ var createPlugin = exports.createPlugin = function createPlugin(api) {
11
11
  return new _safePlugin.SafePlugin({
12
12
  key: blockMenuPluginKey,
13
13
  state: {
@@ -23,6 +23,26 @@ var createPlugin = exports.createPlugin = function createPlugin() {
23
23
  showFlag: (_meta$showFlag = meta === null || meta === void 0 ? void 0 : meta.showFlag) !== null && _meta$showFlag !== void 0 ? _meta$showFlag : currentPluginState.showFlag
24
24
  };
25
25
  }
26
+ },
27
+ props: {
28
+ handleKeyDown: function handleKeyDown(_editorView, event) {
29
+ var _api$userIntent;
30
+ var blockMenuOpen = (api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'blockMenuOpen';
31
+
32
+ // Exit early and do nothing when block menu is closed
33
+ if (!blockMenuOpen) {
34
+ return false;
35
+ }
36
+
37
+ // Block further handling of key events when block menu is open
38
+ // Except for backspace/delete/copy/cut/paste which should be handled by the selection preservation plugin
39
+ var key = event.key.toLowerCase();
40
+ var isMetaCtrl = event.metaKey || event.ctrlKey;
41
+ var isBackspaceDelete = ['backspace', 'delete'].includes(key);
42
+ var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
43
+ var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete;
44
+ return suppressNativeHandling;
45
+ }
26
46
  }
27
47
  });
28
48
  };
@@ -16,7 +16,6 @@ var _css = require("@atlaskit/css");
16
16
  var _analytics = require("@atlaskit/editor-common/analytics");
17
17
  var _errorBoundary = require("@atlaskit/editor-common/error-boundary");
18
18
  var _hooks = require("@atlaskit/editor-common/hooks");
19
- var _selection = require("@atlaskit/editor-common/selection");
20
19
  var _styles = require("@atlaskit/editor-common/styles");
21
20
  var _ui = require("@atlaskit/editor-common/ui");
22
21
  var _uiMenu = require("@atlaskit/editor-common/ui-menu");
@@ -185,25 +184,20 @@ var BlockMenu = function BlockMenu(_ref4) {
185
184
  if (!isMenuOpen) {
186
185
  return null;
187
186
  }
188
- var handleBackspaceDeleteKeydown = function handleBackspaceDeleteKeydown(event) {
189
- // Pevents delete/backspace keypress being handled by editor, avoids double deletions
190
- event === null || event === void 0 || event.preventDefault();
191
- event === null || event === void 0 || event.stopPropagation();
192
- api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
193
- var _api$blockControls, _api$blockControls2;
194
- var tr = _ref6.tr;
195
- (0, _selection.deleteSelectedRange)(tr, api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection);
196
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
197
- closeMenu: true
198
- })({
199
- tr: tr
200
- });
201
- if (editorView && !editorView.hasFocus()) {
202
- // if focus is outside editor, e.g. in block menu popup, then refocus editor after delete
203
- editorView.focus();
204
- }
205
- return tr;
206
- });
187
+ var handleKeyDown = function handleKeyDown(event) {
188
+ var _api$core, _api$blockControls;
189
+ // When the editor view has focus, the keydown will be handled by the
190
+ // selection preservation plugin exit early to avoid double handling
191
+ if (!editorView || editorView !== null && editorView !== void 0 && editorView.hasFocus()) {
192
+ return;
193
+ }
194
+
195
+ // Necessary to prevent the editor from handling the delete natively
196
+ if (['backspace', 'delete'].includes(event.key.toLowerCase())) {
197
+ event.preventDefault();
198
+ event.stopPropagation();
199
+ }
200
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.handleKeyDownWithPreservedSelection(event));
207
201
  };
208
202
  var handleClickOutside = function handleClickOutside(e) {
209
203
  // check if the clicked element was another drag handle, if so don't close the menu
@@ -213,10 +207,10 @@ var BlockMenu = function BlockMenu(_ref4) {
213
207
  closeMenu();
214
208
  };
215
209
  var closeMenu = function closeMenu() {
216
- api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
217
- var _api$blockControls3, _api$userIntent3;
218
- var tr = _ref7.tr;
219
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.toggleBlockMenu({
210
+ api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
211
+ var _api$blockControls2, _api$userIntent3;
212
+ var tr = _ref6.tr;
213
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
220
214
  closeMenu: true
221
215
  })({
222
216
  tr: tr
@@ -249,7 +243,7 @@ var BlockMenu = function BlockMenu(_ref4) {
249
243
  alignY: 'start',
250
244
  handleClickOutside: handleClickOutside,
251
245
  handleEscapeKeydown: closeMenu,
252
- handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
246
+ handleKeyDown: handleKeyDown,
253
247
  mountTo: mountTo,
254
248
  boundariesElement: boundariesElement,
255
249
  scrollableElement: scrollableElement,
@@ -22,7 +22,7 @@ export const blockMenuPlugin = ({
22
22
  pmPlugins() {
23
23
  return [{
24
24
  name: 'blockMenuPlugin',
25
- plugin: createPlugin
25
+ plugin: () => createPlugin(api)
26
26
  }];
27
27
  },
28
28
  actions: {
@@ -3,13 +3,19 @@ import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
3
  import { isTransformDisabledBasedOnStepsConfig } from '../editor-commands/transform-node-utils/transform';
4
4
  import { toNodeTypeValue } from '../editor-commands/transform-node-utils/types';
5
5
  import { getBlockNodesInRange, getTargetNodeTypeNameInContext } from '../editor-commands/transform-node-utils/utils';
6
- export const canParentContainNodeType = (schema, parentNode, nodeTypeName, nodeTypeAttrs) => {
7
- const adjustedNodeTypeName = getTargetNodeTypeNameInContext(nodeTypeName, true);
6
+ export const canParentContainNodeType = (schema, selectedNodeTypeName, parentNode, nodeTypeName, nodeTypeAttrs) => {
7
+ const adjustedNodeTypeName = parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock' ? nodeTypeName : getTargetNodeTypeNameInContext(nodeTypeName, true);
8
8
  if (!adjustedNodeTypeName) {
9
9
  return false;
10
10
  }
11
11
  const nodeType = schema.nodes[adjustedNodeTypeName];
12
- return parentNode.type.validContent(Fragment.from(nodeType.createAndFill(nodeTypeAttrs)));
12
+ let content = null;
13
+ const nodesThatCantBeNestedInNestedExpand = ['blockCard', 'embedCard', 'table'];
14
+ if (nodesThatCantBeNestedInNestedExpand.includes(selectedNodeTypeName) && (adjustedNodeTypeName === 'expand' || adjustedNodeTypeName === 'nestedExpand')) {
15
+ const table = schema.nodes[selectedNodeTypeName];
16
+ content = table.createAndFill();
17
+ }
18
+ return parentNode.type.validContent(Fragment.from(nodeType.createAndFill(nodeTypeAttrs, content)));
13
19
  };
14
20
  const isHeadingToHeadingTransformEnabled = (selectedNode, targetNodeTypeAttrs) => {
15
21
  var _selectedNode$attrs;
@@ -32,7 +38,7 @@ const isTransformEnabledForNode = (node, targetNodeTypeName, targetNodeTypeAttrs
32
38
  if (selectedNodeTypeName === 'heading' && targetNodeTypeName === 'heading') {
33
39
  return isHeadingToHeadingTransformEnabled(node, targetNodeTypeAttrs);
34
40
  }
35
- if (isNested && !canParentContainNodeType(schema, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
41
+ if (isNested && !canParentContainNodeType(schema, selectedNodeTypeName, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
36
42
  return false;
37
43
  }
38
44
  return true;
@@ -3,8 +3,11 @@ export const flattenStep = (nodes, context) => {
3
3
  schema,
4
4
  targetNodeTypeName
5
5
  } = context;
6
+ const {
7
+ paragraph
8
+ } = schema.nodes;
6
9
  const targetNodeType = schema.nodes[targetNodeTypeName];
7
- if (!targetNodeType) {
10
+ if (!targetNodeType || !paragraph) {
8
11
  return nodes;
9
12
  }
10
13
 
@@ -20,6 +23,6 @@ export const flattenStep = (nodes, context) => {
20
23
  if (!isValidWithin) {
21
24
  return node;
22
25
  }
23
- return schema.nodes.paragraph.create({}, node.content);
26
+ return paragraph.create({}, node.content, node.marks);
24
27
  });
25
28
  };
@@ -38,7 +38,7 @@ export const applyTargetTextTypeStep = (nodes, context) => {
38
38
  // Convert textblock nodes (paragraphs, headings) to heading with specified level
39
39
  return headingType.create({
40
40
  level: headingLevel
41
- }, node.content);
41
+ }, node.content, node.marks);
42
42
  }
43
43
  // Non-textblock nodes are left unchanged
44
44
  return node;
@@ -1,7 +1,7 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  export const blockMenuPluginKey = new PluginKey('blockMenuPlugin');
4
- export const createPlugin = () => {
4
+ export const createPlugin = api => {
5
5
  return new SafePlugin({
6
6
  key: blockMenuPluginKey,
7
7
  state: {
@@ -17,6 +17,26 @@ export const createPlugin = () => {
17
17
  showFlag: (_meta$showFlag = meta === null || meta === void 0 ? void 0 : meta.showFlag) !== null && _meta$showFlag !== void 0 ? _meta$showFlag : currentPluginState.showFlag
18
18
  };
19
19
  }
20
+ },
21
+ props: {
22
+ handleKeyDown: (_editorView, event) => {
23
+ var _api$userIntent, _api$userIntent$share;
24
+ const blockMenuOpen = (api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : (_api$userIntent$share = _api$userIntent.sharedState.currentState()) === null || _api$userIntent$share === void 0 ? void 0 : _api$userIntent$share.currentUserIntent) === 'blockMenuOpen';
25
+
26
+ // Exit early and do nothing when block menu is closed
27
+ if (!blockMenuOpen) {
28
+ return false;
29
+ }
30
+
31
+ // Block further handling of key events when block menu is open
32
+ // Except for backspace/delete/copy/cut/paste which should be handled by the selection preservation plugin
33
+ const key = event.key.toLowerCase();
34
+ const isMetaCtrl = event.metaKey || event.ctrlKey;
35
+ const isBackspaceDelete = ['backspace', 'delete'].includes(key);
36
+ const isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
37
+ const suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete;
38
+ return suppressNativeHandling;
39
+ }
20
40
  }
21
41
  });
22
42
  };
@@ -7,7 +7,6 @@ import { cx } from '@atlaskit/css';
7
7
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
8
8
  import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
9
9
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
10
- import { deleteSelectedRange } from '@atlaskit/editor-common/selection';
11
10
  import { DRAG_HANDLE_SELECTOR, DRAG_HANDLE_WIDTH } from '@atlaskit/editor-common/styles';
12
11
  import { Popup } from '@atlaskit/editor-common/ui';
13
12
  import { ArrowKeyNavigationProvider, ArrowKeyNavigationType } from '@atlaskit/editor-common/ui-menu';
@@ -174,26 +173,20 @@ const BlockMenu = ({
174
173
  if (!isMenuOpen) {
175
174
  return null;
176
175
  }
177
- const handleBackspaceDeleteKeydown = event => {
178
- // Pevents delete/backspace keypress being handled by editor, avoids double deletions
179
- event === null || event === void 0 ? void 0 : event.preventDefault();
180
- event === null || event === void 0 ? void 0 : event.stopPropagation();
181
- api === null || api === void 0 ? void 0 : api.core.actions.execute(({
182
- tr
183
- }) => {
184
- var _api$blockControls, _api$blockControls$sh, _api$blockControls2;
185
- deleteSelectedRange(tr, api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$sh = _api$blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection);
186
- api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.toggleBlockMenu({
187
- closeMenu: true
188
- })({
189
- tr
190
- });
191
- if (editorView && !editorView.hasFocus()) {
192
- // if focus is outside editor, e.g. in block menu popup, then refocus editor after delete
193
- editorView.focus();
194
- }
195
- return tr;
196
- });
176
+ const handleKeyDown = event => {
177
+ var _api$core, _api$blockControls, _api$blockControls$co;
178
+ // When the editor view has focus, the keydown will be handled by the
179
+ // selection preservation plugin exit early to avoid double handling
180
+ if (!editorView || editorView !== null && editorView !== void 0 && editorView.hasFocus()) {
181
+ return;
182
+ }
183
+
184
+ // Necessary to prevent the editor from handling the delete natively
185
+ if (['backspace', 'delete'].includes(event.key.toLowerCase())) {
186
+ event.preventDefault();
187
+ event.stopPropagation();
188
+ }
189
+ 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$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.handleKeyDownWithPreservedSelection(event));
197
190
  };
198
191
  const handleClickOutside = e => {
199
192
  // check if the clicked element was another drag handle, if so don't close the menu
@@ -206,8 +199,8 @@ const BlockMenu = ({
206
199
  api === null || api === void 0 ? void 0 : api.core.actions.execute(({
207
200
  tr
208
201
  }) => {
209
- var _api$blockControls3, _api$userIntent3;
210
- api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.toggleBlockMenu({
202
+ var _api$blockControls2, _api$userIntent3;
203
+ api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.toggleBlockMenu({
211
204
  closeMenu: true
212
205
  })({
213
206
  tr
@@ -240,7 +233,7 @@ const BlockMenu = ({
240
233
  alignY: 'start',
241
234
  handleClickOutside: handleClickOutside,
242
235
  handleEscapeKeydown: closeMenu,
243
- handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
236
+ handleKeyDown: handleKeyDown,
244
237
  mountTo: mountTo,
245
238
  boundariesElement: boundariesElement,
246
239
  scrollableElement: scrollableElement,
@@ -21,7 +21,9 @@ export var blockMenuPlugin = function blockMenuPlugin(_ref) {
21
21
  pmPlugins: function pmPlugins() {
22
22
  return [{
23
23
  name: 'blockMenuPlugin',
24
- plugin: createPlugin
24
+ plugin: function plugin() {
25
+ return createPlugin(api);
26
+ }
25
27
  }];
26
28
  },
27
29
  actions: {
@@ -3,13 +3,19 @@ import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
3
  import { isTransformDisabledBasedOnStepsConfig } from '../editor-commands/transform-node-utils/transform';
4
4
  import { toNodeTypeValue } from '../editor-commands/transform-node-utils/types';
5
5
  import { getBlockNodesInRange, getTargetNodeTypeNameInContext } from '../editor-commands/transform-node-utils/utils';
6
- export var canParentContainNodeType = function canParentContainNodeType(schema, parentNode, nodeTypeName, nodeTypeAttrs) {
7
- var adjustedNodeTypeName = getTargetNodeTypeNameInContext(nodeTypeName, true);
6
+ export var canParentContainNodeType = function canParentContainNodeType(schema, selectedNodeTypeName, parentNode, nodeTypeName, nodeTypeAttrs) {
7
+ var adjustedNodeTypeName = parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock' ? nodeTypeName : getTargetNodeTypeNameInContext(nodeTypeName, true);
8
8
  if (!adjustedNodeTypeName) {
9
9
  return false;
10
10
  }
11
11
  var nodeType = schema.nodes[adjustedNodeTypeName];
12
- return parentNode.type.validContent(Fragment.from(nodeType.createAndFill(nodeTypeAttrs)));
12
+ var content = null;
13
+ var nodesThatCantBeNestedInNestedExpand = ['blockCard', 'embedCard', 'table'];
14
+ if (nodesThatCantBeNestedInNestedExpand.includes(selectedNodeTypeName) && (adjustedNodeTypeName === 'expand' || adjustedNodeTypeName === 'nestedExpand')) {
15
+ var table = schema.nodes[selectedNodeTypeName];
16
+ content = table.createAndFill();
17
+ }
18
+ return parentNode.type.validContent(Fragment.from(nodeType.createAndFill(nodeTypeAttrs, content)));
13
19
  };
14
20
  var isHeadingToHeadingTransformEnabled = function isHeadingToHeadingTransformEnabled(selectedNode, targetNodeTypeAttrs) {
15
21
  var _selectedNode$attrs;
@@ -32,7 +38,7 @@ var isTransformEnabledForNode = function isTransformEnabledForNode(node, targetN
32
38
  if (selectedNodeTypeName === 'heading' && targetNodeTypeName === 'heading') {
33
39
  return isHeadingToHeadingTransformEnabled(node, targetNodeTypeAttrs);
34
40
  }
35
- if (isNested && !canParentContainNodeType(schema, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
41
+ if (isNested && !canParentContainNodeType(schema, selectedNodeTypeName, parent, targetNodeTypeName, targetNodeTypeAttrs)) {
36
42
  return false;
37
43
  }
38
44
  return true;
@@ -1,8 +1,9 @@
1
1
  export var flattenStep = function flattenStep(nodes, context) {
2
2
  var schema = context.schema,
3
3
  targetNodeTypeName = context.targetNodeTypeName;
4
+ var paragraph = schema.nodes.paragraph;
4
5
  var targetNodeType = schema.nodes[targetNodeTypeName];
5
- if (!targetNodeType) {
6
+ if (!targetNodeType || !paragraph) {
6
7
  return nodes;
7
8
  }
8
9
 
@@ -20,6 +21,6 @@ export var flattenStep = function flattenStep(nodes, context) {
20
21
  if (!isValidWithin) {
21
22
  return node;
22
23
  }
23
- return schema.nodes.paragraph.create({}, node.content);
24
+ return paragraph.create({}, node.content, node.marks);
24
25
  });
25
26
  };
@@ -36,7 +36,7 @@ export var applyTargetTextTypeStep = function applyTargetTextTypeStep(nodes, con
36
36
  // Convert textblock nodes (paragraphs, headings) to heading with specified level
37
37
  return headingType.create({
38
38
  level: headingLevel
39
- }, node.content);
39
+ }, node.content, node.marks);
40
40
  }
41
41
  // Non-textblock nodes are left unchanged
42
42
  return node;
@@ -1,7 +1,7 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  export var blockMenuPluginKey = new PluginKey('blockMenuPlugin');
4
- export var createPlugin = function createPlugin() {
4
+ export var createPlugin = function createPlugin(api) {
5
5
  return new SafePlugin({
6
6
  key: blockMenuPluginKey,
7
7
  state: {
@@ -17,6 +17,26 @@ export var createPlugin = function createPlugin() {
17
17
  showFlag: (_meta$showFlag = meta === null || meta === void 0 ? void 0 : meta.showFlag) !== null && _meta$showFlag !== void 0 ? _meta$showFlag : currentPluginState.showFlag
18
18
  };
19
19
  }
20
+ },
21
+ props: {
22
+ handleKeyDown: function handleKeyDown(_editorView, event) {
23
+ var _api$userIntent;
24
+ var blockMenuOpen = (api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'blockMenuOpen';
25
+
26
+ // Exit early and do nothing when block menu is closed
27
+ if (!blockMenuOpen) {
28
+ return false;
29
+ }
30
+
31
+ // Block further handling of key events when block menu is open
32
+ // Except for backspace/delete/copy/cut/paste which should be handled by the selection preservation plugin
33
+ var key = event.key.toLowerCase();
34
+ var isMetaCtrl = event.metaKey || event.ctrlKey;
35
+ var isBackspaceDelete = ['backspace', 'delete'].includes(key);
36
+ var isCopyCutPaste = isMetaCtrl && ['c', 'x', 'v'].includes(key);
37
+ var suppressNativeHandling = !isCopyCutPaste && !isBackspaceDelete;
38
+ return suppressNativeHandling;
39
+ }
20
40
  }
21
41
  });
22
42
  };
@@ -8,7 +8,6 @@ import { cx } from '@atlaskit/css';
8
8
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
9
9
  import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
10
10
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
11
- import { deleteSelectedRange } from '@atlaskit/editor-common/selection';
12
11
  import { DRAG_HANDLE_SELECTOR, DRAG_HANDLE_WIDTH } from '@atlaskit/editor-common/styles';
13
12
  import { Popup } from '@atlaskit/editor-common/ui';
14
13
  import { ArrowKeyNavigationProvider, ArrowKeyNavigationType } from '@atlaskit/editor-common/ui-menu';
@@ -176,25 +175,20 @@ var BlockMenu = function BlockMenu(_ref4) {
176
175
  if (!isMenuOpen) {
177
176
  return null;
178
177
  }
179
- var handleBackspaceDeleteKeydown = function handleBackspaceDeleteKeydown(event) {
180
- // Pevents delete/backspace keypress being handled by editor, avoids double deletions
181
- event === null || event === void 0 || event.preventDefault();
182
- event === null || event === void 0 || event.stopPropagation();
183
- api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
184
- var _api$blockControls, _api$blockControls2;
185
- var tr = _ref6.tr;
186
- deleteSelectedRange(tr, api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection);
187
- api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
188
- closeMenu: true
189
- })({
190
- tr: tr
191
- });
192
- if (editorView && !editorView.hasFocus()) {
193
- // if focus is outside editor, e.g. in block menu popup, then refocus editor after delete
194
- editorView.focus();
195
- }
196
- return tr;
197
- });
178
+ var handleKeyDown = function handleKeyDown(event) {
179
+ var _api$core, _api$blockControls;
180
+ // When the editor view has focus, the keydown will be handled by the
181
+ // selection preservation plugin exit early to avoid double handling
182
+ if (!editorView || editorView !== null && editorView !== void 0 && editorView.hasFocus()) {
183
+ return;
184
+ }
185
+
186
+ // Necessary to prevent the editor from handling the delete natively
187
+ if (['backspace', 'delete'].includes(event.key.toLowerCase())) {
188
+ event.preventDefault();
189
+ event.stopPropagation();
190
+ }
191
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.handleKeyDownWithPreservedSelection(event));
198
192
  };
199
193
  var handleClickOutside = function handleClickOutside(e) {
200
194
  // check if the clicked element was another drag handle, if so don't close the menu
@@ -204,10 +198,10 @@ var BlockMenu = function BlockMenu(_ref4) {
204
198
  closeMenu();
205
199
  };
206
200
  var closeMenu = function closeMenu() {
207
- api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
208
- var _api$blockControls3, _api$userIntent3;
209
- var tr = _ref7.tr;
210
- api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.toggleBlockMenu({
201
+ api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
202
+ var _api$blockControls2, _api$userIntent3;
203
+ var tr = _ref6.tr;
204
+ api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.toggleBlockMenu({
211
205
  closeMenu: true
212
206
  })({
213
207
  tr: tr
@@ -240,7 +234,7 @@ var BlockMenu = function BlockMenu(_ref4) {
240
234
  alignY: 'start',
241
235
  handleClickOutside: handleClickOutside,
242
236
  handleEscapeKeydown: closeMenu,
243
- handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
237
+ handleKeyDown: handleKeyDown,
244
238
  mountTo: mountTo,
245
239
  boundariesElement: boundariesElement,
246
240
  scrollableElement: scrollableElement,
@@ -6,6 +6,6 @@ type TransformDisabledArgs = {
6
6
  targetNodeTypeAttrs?: Record<string, unknown>;
7
7
  targetNodeTypeName: string;
8
8
  };
9
- export declare const canParentContainNodeType: (schema: Schema, parentNode: PMNode, nodeTypeName: NodeTypeName, nodeTypeAttrs?: Record<string, unknown>) => boolean;
9
+ export declare const canParentContainNodeType: (schema: Schema, selectedNodeTypeName: NodeTypeName, parentNode: PMNode, nodeTypeName: NodeTypeName, nodeTypeAttrs?: Record<string, unknown>) => boolean;
10
10
  export declare const isTransformToTargetDisabled: ({ selection, targetNodeTypeName, targetNodeTypeAttrs, }: TransformDisabledArgs) => boolean;
11
11
  export {};
@@ -1,9 +1,10 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
3
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
- import type { FLAG_ID } from '../blockMenuPluginType';
4
+ import type { BlockMenuPlugin, FLAG_ID } from '../blockMenuPluginType';
4
5
  export declare const blockMenuPluginKey: PluginKey<any>;
5
6
  type BlockMenuPluginState = {
6
7
  showFlag: FLAG_ID | false;
7
8
  };
8
- export declare const createPlugin: () => SafePlugin<BlockMenuPluginState>;
9
+ export declare const createPlugin: (api: ExtractInjectionAPI<BlockMenuPlugin> | undefined) => SafePlugin<BlockMenuPluginState>;
9
10
  export {};
@@ -6,6 +6,6 @@ type TransformDisabledArgs = {
6
6
  targetNodeTypeAttrs?: Record<string, unknown>;
7
7
  targetNodeTypeName: string;
8
8
  };
9
- export declare const canParentContainNodeType: (schema: Schema, parentNode: PMNode, nodeTypeName: NodeTypeName, nodeTypeAttrs?: Record<string, unknown>) => boolean;
9
+ export declare const canParentContainNodeType: (schema: Schema, selectedNodeTypeName: NodeTypeName, parentNode: PMNode, nodeTypeName: NodeTypeName, nodeTypeAttrs?: Record<string, unknown>) => boolean;
10
10
  export declare const isTransformToTargetDisabled: ({ selection, targetNodeTypeName, targetNodeTypeAttrs, }: TransformDisabledArgs) => boolean;
11
11
  export {};
@@ -1,9 +1,10 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
3
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
- import type { FLAG_ID } from '../blockMenuPluginType';
4
+ import type { BlockMenuPlugin, FLAG_ID } from '../blockMenuPluginType';
4
5
  export declare const blockMenuPluginKey: PluginKey<any>;
5
6
  type BlockMenuPluginState = {
6
7
  showFlag: FLAG_ID | false;
7
8
  };
8
- export declare const createPlugin: () => SafePlugin<BlockMenuPluginState>;
9
+ export declare const createPlugin: (api: ExtractInjectionAPI<BlockMenuPlugin> | undefined) => SafePlugin<BlockMenuPluginState>;
9
10
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "5.2.27",
3
+ "version": "6.0.0",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -30,11 +30,11 @@
30
30
  "dependencies": {
31
31
  "@atlaskit/css": "^0.19.0",
32
32
  "@atlaskit/dropdown-menu": "^16.3.0",
33
- "@atlaskit/editor-plugin-analytics": "^6.2.0",
34
- "@atlaskit/editor-plugin-block-controls": "^7.18.0",
35
- "@atlaskit/editor-plugin-decorations": "^6.1.0",
36
- "@atlaskit/editor-plugin-selection": "^6.1.0",
37
- "@atlaskit/editor-plugin-user-intent": "^4.0.0",
33
+ "@atlaskit/editor-plugin-analytics": "^7.0.0",
34
+ "@atlaskit/editor-plugin-block-controls": "^8.0.0",
35
+ "@atlaskit/editor-plugin-decorations": "^7.0.0",
36
+ "@atlaskit/editor-plugin-selection": "^7.0.0",
37
+ "@atlaskit/editor-plugin-user-intent": "^5.0.0",
38
38
  "@atlaskit/editor-prosemirror": "^7.2.0",
39
39
  "@atlaskit/editor-shared-styles": "^3.10.0",
40
40
  "@atlaskit/editor-tables": "^2.9.0",
@@ -49,7 +49,7 @@
49
49
  "@babel/runtime": "^7.0.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@atlaskit/editor-common": "^110.50.0",
52
+ "@atlaskit/editor-common": "^111.0.0",
53
53
  "react": "^18.2.0",
54
54
  "react-intl-next": "npm:react-intl@^5.18.1"
55
55
  },