@atlaskit/editor-plugin-block-menu 1.0.7 → 1.0.9

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 (35) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/blockMenuPlugin.js +12 -0
  3. package/dist/cjs/editor-commands/transforms/container-transforms.js +86 -3
  4. package/dist/cjs/editor-commands/transforms/utils.js +48 -1
  5. package/dist/cjs/pm-plugins/getIsFormatMenuHidden.js +40 -0
  6. package/dist/cjs/pm-plugins/main.js +13 -3
  7. package/dist/cjs/ui/block-menu-components.js +8 -4
  8. package/dist/cjs/ui/format-menu-section.js +19 -0
  9. package/dist/es2019/blockMenuPlugin.js +13 -1
  10. package/dist/es2019/editor-commands/transforms/container-transforms.js +88 -3
  11. package/dist/es2019/editor-commands/transforms/utils.js +47 -0
  12. package/dist/es2019/pm-plugins/getIsFormatMenuHidden.js +34 -0
  13. package/dist/es2019/pm-plugins/main.js +13 -3
  14. package/dist/es2019/ui/block-menu-components.js +8 -4
  15. package/dist/es2019/ui/format-menu-section.js +13 -0
  16. package/dist/esm/blockMenuPlugin.js +13 -1
  17. package/dist/esm/editor-commands/transforms/container-transforms.js +86 -3
  18. package/dist/esm/editor-commands/transforms/utils.js +47 -0
  19. package/dist/esm/pm-plugins/getIsFormatMenuHidden.js +34 -0
  20. package/dist/esm/pm-plugins/main.js +12 -3
  21. package/dist/esm/ui/block-menu-components.js +8 -4
  22. package/dist/esm/ui/format-menu-section.js +12 -0
  23. package/dist/types/blockMenuPluginType.d.ts +3 -0
  24. package/dist/types/editor-commands/transforms/container-transforms.d.ts +1 -0
  25. package/dist/types/editor-commands/transforms/utils.d.ts +14 -1
  26. package/dist/types/pm-plugins/getIsFormatMenuHidden.d.ts +2 -0
  27. package/dist/types/pm-plugins/main.d.ts +3 -1
  28. package/dist/types/ui/format-menu-section.d.ts +7 -0
  29. package/dist/types-ts4.5/blockMenuPluginType.d.ts +3 -0
  30. package/dist/types-ts4.5/editor-commands/transforms/container-transforms.d.ts +1 -0
  31. package/dist/types-ts4.5/editor-commands/transforms/utils.d.ts +14 -1
  32. package/dist/types-ts4.5/pm-plugins/getIsFormatMenuHidden.d.ts +2 -0
  33. package/dist/types-ts4.5/pm-plugins/main.d.ts +3 -1
  34. package/dist/types-ts4.5/ui/format-menu-section.d.ts +7 -0
  35. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 1.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - [`da23530028aac`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/da23530028aac) -
8
+ [ux] ED-29145 Hide format menu for unsupported and nested nodes
9
+
10
+ ## 1.0.8
11
+
12
+ ### Patch Changes
13
+
14
+ - [`b3e1332c170a6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b3e1332c170a6) -
15
+ Container to container transform with unsupportted content
16
+ - Updated dependencies
17
+
3
18
  ## 1.0.7
4
19
 
5
20
  ### Patch Changes
@@ -40,6 +40,18 @@ var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
40
40
  return (0, _formatNode2.formatNode)(targetType);
41
41
  }
42
42
  },
43
+ getSharedState: function getSharedState(editorState) {
44
+ if (!editorState) {
45
+ return;
46
+ }
47
+ var pluginState = _main.blockMenuPluginKey.getState(editorState);
48
+ if (!pluginState) {
49
+ return;
50
+ }
51
+ return {
52
+ isFormatMenuHidden: pluginState === null || pluginState === void 0 ? void 0 : pluginState.isFormatMenuHidden
53
+ };
54
+ },
43
55
  contentComponent: function contentComponent(_ref2) {
44
56
  var editorView = _ref2.editorView,
45
57
  popupsMountPoint = _ref2.popupsMountPoint,
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.unwrapAndConvertToList = exports.unwrapAndConvertToBlockType = exports.transformToContainer = exports.transformContainerNode = void 0;
7
+ exports.unwrapAndConvertToList = exports.unwrapAndConvertToBlockType = exports.transformToContainer = exports.transformContainerNode = exports.transformBetweenContainerTypes = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _model = require("@atlaskit/editor-prosemirror/model");
10
10
  var _utils = require("./utils");
@@ -84,8 +84,13 @@ var transformContainerNode = exports.transformContainerNode = function transform
84
84
 
85
85
  // Transform between container types
86
86
  if ((0, _utils.isContainerNodeType)(targetNodeType)) {
87
- tr.setNodeMarkup(sourcePos, targetNodeType, targetAttrs);
88
- return tr;
87
+ return transformBetweenContainerTypes({
88
+ tr: tr,
89
+ sourceNode: sourceNode,
90
+ sourcePos: sourcePos,
91
+ targetNodeType: targetNodeType,
92
+ targetAttrs: targetAttrs
93
+ });
89
94
  }
90
95
  return null;
91
96
  };
@@ -241,4 +246,82 @@ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAnd
241
246
  }
242
247
  createListAndAddToContent();
243
248
  return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, _model.Fragment.from(resultContent));
249
+ };
250
+ var transformBetweenContainerTypes = exports.transformBetweenContainerTypes = function transformBetweenContainerTypes(context) {
251
+ var tr = context.tr,
252
+ sourceNode = context.sourceNode,
253
+ sourcePos = context.sourcePos,
254
+ targetNodeType = context.targetNodeType,
255
+ targetAttrs = context.targetAttrs;
256
+
257
+ // Get content validation for target container type
258
+ var isContentSupported = (0, _utils.getContentSupportChecker)(targetNodeType);
259
+
260
+ // Process content and collect splits
261
+ var contentSplits = splitContentAroundUnsupportedBlocks(sourceNode, isContentSupported, targetNodeType, targetAttrs, tr.doc.type.schema);
262
+
263
+ // Replace the original node with the first split
264
+ var insertPos = sourcePos;
265
+ contentSplits.forEach(function (splitNode, index) {
266
+ if (index === 0) {
267
+ // Replace the original node with the first split
268
+ tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, splitNode);
269
+ insertPos = sourcePos + splitNode.nodeSize;
270
+ } else {
271
+ // Insert additional splits after
272
+ tr.insert(insertPos, splitNode);
273
+ insertPos += splitNode.nodeSize;
274
+ }
275
+ });
276
+ return tr;
277
+ };
278
+
279
+ /**
280
+ * Split content around unsupported block nodes, creating separate containers
281
+ * for content before and after each unsupported block
282
+ */
283
+ var splitContentAroundUnsupportedBlocks = function splitContentAroundUnsupportedBlocks(sourceNode, isContentSupported, targetNodeType, targetAttrs, schema) {
284
+ var _sourceNode$attrs3;
285
+ var splits = [];
286
+ var children = sourceNode.content.content;
287
+ var currentContainerContent = [];
288
+
289
+ // Handle expand title - add as first paragraph if source is expand with title
290
+ if (sourceNode.type.name === 'expand' && (_sourceNode$attrs3 = sourceNode.attrs) !== null && _sourceNode$attrs3 !== void 0 && _sourceNode$attrs3.title) {
291
+ var titleParagraph = schema.nodes.paragraph.create({}, schema.text(sourceNode.attrs.title));
292
+ currentContainerContent.push(titleParagraph);
293
+ }
294
+ var flushCurrentContainer = function flushCurrentContainer() {
295
+ if (currentContainerContent.length > 0) {
296
+ var containerNode = targetNodeType.create(targetAttrs, _model.Fragment.fromArray(currentContainerContent));
297
+ splits.push(containerNode);
298
+ currentContainerContent = [];
299
+ }
300
+ };
301
+ children.forEach(function (childNode) {
302
+ if (isContentSupported(childNode)) {
303
+ // Supported content - add to current container
304
+ currentContainerContent.push(childNode);
305
+ } else if ((0, _utils.isBlockNodeForExtraction)(childNode)) {
306
+ // Unsupported block node - flush current container, add block, continue
307
+ flushCurrentContainer();
308
+ splits.push(childNode);
309
+ } else if (childNode.type.name === targetNodeType.name) {
310
+ // Same type of container merge contents
311
+ childNode.content.forEach(function (child) {
312
+ currentContainerContent.push(child);
313
+ });
314
+ } else {
315
+ // Unsupported inline content - convert to paragraph and add to container
316
+ var inlineContent = (0, _utils.convertNodeToInlineContent)(childNode, schema);
317
+ if (inlineContent.length > 0) {
318
+ var paragraph = schema.nodes.paragraph.create({}, _model.Fragment.fromArray(inlineContent));
319
+ currentContainerContent.push(paragraph);
320
+ }
321
+ }
322
+ });
323
+
324
+ // Flush any remaining container content
325
+ flushCurrentContainer();
326
+ return splits;
244
327
  };
@@ -3,7 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isTaskList = exports.isListNodeType = exports.isListNode = exports.isLayoutNodeType = exports.isContainerNodeType = exports.isContainerNode = exports.isBulletOrOrderedList = exports.isBlockNodeType = exports.isBlockNode = exports.getTargetNodeInfo = exports.getSupportedListTypesSet = exports.getSupportedListTypes = void 0;
6
+ exports.isTaskList = exports.isListNodeType = exports.isListNode = exports.isLayoutNodeType = exports.isContainerNodeType = exports.isContainerNode = exports.isBulletOrOrderedList = exports.isBlockNodeType = exports.isBlockNodeForExtraction = exports.isBlockNode = exports.getTargetNodeInfo = exports.getSupportedListTypesSet = exports.getSupportedListTypes = exports.getContentSupportChecker = exports.convertNodeToInlineContent = void 0;
7
+ var _model = require("@atlaskit/editor-prosemirror/model");
7
8
  var getTargetNodeInfo = exports.getTargetNodeInfo = function getTargetNodeInfo(targetType, nodes) {
8
9
  switch (targetType) {
9
10
  case 'heading1':
@@ -127,4 +128,50 @@ var getSupportedListTypesSet = exports.getSupportedListTypesSet = function getSu
127
128
  };
128
129
  var isLayoutNodeType = exports.isLayoutNodeType = function isLayoutNodeType(nodeType) {
129
130
  return nodeType.name === 'layoutSection';
131
+ };
132
+
133
+ /**
134
+ * Check if a node should be extracted as a standalone block node
135
+ * rather than converted to inline content
136
+ */
137
+ var isBlockNodeForExtraction = exports.isBlockNodeForExtraction = function isBlockNodeForExtraction(node) {
138
+ var blockNodesForExtraction = ['table', 'mediaSingle', 'extension', 'bodiedExtension', 'blockCard', 'embedCard'];
139
+ return blockNodesForExtraction.includes(node.type.name);
140
+ };
141
+
142
+ /**
143
+ * Get a function that checks if content is supported in the target container type
144
+ */
145
+ var getContentSupportChecker = exports.getContentSupportChecker = function getContentSupportChecker(targetNodeType) {
146
+ return function (node) {
147
+ // Check if the target container type can contain this node
148
+ try {
149
+ return targetNodeType.validContent(_model.Fragment.from(node));
150
+ } catch (_unused) {
151
+ return false;
152
+ }
153
+ };
154
+ };
155
+
156
+ /**
157
+ * Convert a node to inline content that can be placed in a paragraph
158
+ */
159
+ var convertNodeToInlineContent = exports.convertNodeToInlineContent = function convertNodeToInlineContent(node, schema) {
160
+ // Extract text and inline nodes from any complex node
161
+ var inlineNodes = [];
162
+ node.descendants(function (childNode) {
163
+ if (childNode.isText) {
164
+ inlineNodes.push(childNode);
165
+ } else if (childNode.isInline) {
166
+ inlineNodes.push(childNode);
167
+ }
168
+ return true; // Continue traversing
169
+ });
170
+
171
+ // If no inline content was found but the node has text content,
172
+ // create a text node with the full text content
173
+ if (inlineNodes.length === 0 && node.textContent) {
174
+ return [schema.text(node.textContent)];
175
+ }
176
+ return inlineNodes;
130
177
  };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getIsFormatMenuHidden = void 0;
7
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
8
+ var TOP_LEVEL_NODE_DEPTHS = {
9
+ LIST_TYPE: 2,
10
+ PARAGRAPH_OR_HEADING: 1,
11
+ BLOCKQUOTE: 1,
12
+ BLOCK: 0
13
+ };
14
+ var getIsFormatMenuHidden = exports.getIsFormatMenuHidden = function getIsFormatMenuHidden(tr) {
15
+ var selection = tr.selection;
16
+ var nodes = tr.doc.type.schema.nodes;
17
+ if (selection.from === selection.to || selection.empty || !nodes) {
18
+ return false;
19
+ }
20
+ var content;
21
+ var isTopLevelNode = false;
22
+ var selectedNode = (0, _utils.findSelectedNodeOfType)([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.layoutSection])(selection);
23
+ if (selectedNode) {
24
+ content = selectedNode.node;
25
+ isTopLevelNode = selectedNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCK;
26
+ } else {
27
+ var listTypeOrBlockQuoteNode = (0, _utils.findParentNodeOfType)([nodes.blockquote, nodes.listItem, nodes.taskItem])(selection);
28
+ if (listTypeOrBlockQuoteNode) {
29
+ content = listTypeOrBlockQuoteNode.node;
30
+ isTopLevelNode = listTypeOrBlockQuoteNode.node.type === nodes.blockquote ? listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCKQUOTE : listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.LIST_TYPE;
31
+ } else {
32
+ var paragraphOrHeadingNode = (0, _utils.findParentNodeOfType)([nodes.paragraph, nodes.heading])(selection);
33
+ if (paragraphOrHeadingNode) {
34
+ content = paragraphOrHeadingNode.node;
35
+ isTopLevelNode = paragraphOrHeadingNode.depth === TOP_LEVEL_NODE_DEPTHS.PARAGRAPH_OR_HEADING;
36
+ }
37
+ }
38
+ }
39
+ return !content || !isTopLevelNode;
40
+ };
@@ -1,11 +1,16 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.createPlugin = exports.blockMenuPluginKey = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
7
9
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
8
10
  var _state = require("@atlaskit/editor-prosemirror/state");
11
+ var _getIsFormatMenuHidden = require("./getIsFormatMenuHidden");
12
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
13
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9
14
  var blockMenuPluginKey = exports.blockMenuPluginKey = new _state.PluginKey('blockMenuPlugin');
10
15
 
11
16
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -15,14 +20,19 @@ var createPlugin = exports.createPlugin = function createPlugin() {
15
20
  key: blockMenuPluginKey,
16
21
  state: {
17
22
  init: function init() {
18
- return {};
23
+ return {
24
+ isFormatMenuHidden: false
25
+ };
19
26
  },
20
27
  apply: function apply(tr, currentPluginState) {
21
28
  var meta = tr.getMeta(blockMenuPluginKey);
22
29
  if (meta) {
23
- return meta;
30
+ return _objectSpread(_objectSpread({}, currentPluginState), meta);
24
31
  }
25
- return currentPluginState;
32
+ var isFormatMenuHidden = (0, _getIsFormatMenuHidden.getIsFormatMenuHidden)(tr);
33
+ return _objectSpread(_objectSpread({}, currentPluginState), {}, {
34
+ isFormatMenuHidden: isFormatMenuHidden
35
+ });
26
36
  }
27
37
  }
28
38
  });
@@ -14,6 +14,7 @@ var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-
14
14
  var _copyBlock = _interopRequireDefault(require("./copy-block"));
15
15
  var _copyLink = require("./copy-link");
16
16
  var _deleteButton = require("./delete-button");
17
+ var _formatMenuSection = require("./format-menu-section");
17
18
  var _moveDown = require("./move-down");
18
19
  var _moveUp = require("./move-up");
19
20
  var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
@@ -45,7 +46,7 @@ var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(a
45
46
  }
46
47
  }];
47
48
  };
48
- var getFormatMenuComponents = function getFormatMenuComponents() {
49
+ var getFormatMenuComponents = function getFormatMenuComponents(api) {
49
50
  return [{
50
51
  type: 'block-menu-nested',
51
52
  key: _blockMenu.NESTED_FORMAT_MENU.key,
@@ -91,21 +92,24 @@ var getFormatMenuComponents = function getFormatMenuComponents() {
91
92
  rank: 100,
92
93
  component: function component(_ref3) {
93
94
  var children = _ref3.children;
94
- return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, null, children);
95
+ return /*#__PURE__*/_react.default.createElement(_formatMenuSection.FormatMenuSection, {
96
+ api: api
97
+ }, children);
95
98
  }
96
99
  }];
97
100
  };
98
101
  var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockMenuComponents(_ref4) {
99
102
  var api = _ref4.api,
100
103
  config = _ref4.config;
101
- return [].concat((0, _toConsumableArray2.default)(getFormatMenuComponents()), [{
104
+ return [].concat((0, _toConsumableArray2.default)(getFormatMenuComponents(api)), [{
102
105
  type: 'block-menu-section',
103
106
  key: _blockMenu.COPY_MENU_SECTION.key,
104
107
  rank: _blockMenu.BLOCK_MENU_SECTION_RANK[_blockMenu.COPY_MENU_SECTION.key],
105
108
  component: function component(_ref5) {
109
+ var _api$blockMenu$shared;
106
110
  var children = _ref5.children;
107
111
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
108
- hasSeparator: true
112
+ hasSeparator: !(api !== null && api !== void 0 && (_api$blockMenu$shared = api.blockMenu.sharedState.currentState()) !== null && _api$blockMenu$shared !== void 0 && _api$blockMenu$shared.isFormatMenuHidden)
109
113
  }, children);
110
114
  }
111
115
  }, {
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.FormatMenuSection = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
10
+ var _editorToolbar = require("@atlaskit/editor-toolbar");
11
+ var FormatMenuSection = exports.FormatMenuSection = function FormatMenuSection(_ref) {
12
+ var children = _ref.children,
13
+ api = _ref.api;
14
+ var isFormatMenuHidden = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'blockMenu.isFormatMenuHidden');
15
+ if (isFormatMenuHidden) {
16
+ return null;
17
+ }
18
+ return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, null, children);
19
+ };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { createBlockMenuRegistry } from './editor-actions';
3
3
  import { formatNode } from './editor-commands/formatNode';
4
- import { createPlugin } from './pm-plugins/main';
4
+ import { blockMenuPluginKey, createPlugin } from './pm-plugins/main';
5
5
  import BlockMenu from './ui/block-menu';
6
6
  import { getBlockMenuComponents } from './ui/block-menu-components';
7
7
  export const blockMenuPlugin = ({
@@ -34,6 +34,18 @@ export const blockMenuPlugin = ({
34
34
  return formatNode(targetType);
35
35
  }
36
36
  },
37
+ getSharedState: editorState => {
38
+ if (!editorState) {
39
+ return;
40
+ }
41
+ const pluginState = blockMenuPluginKey.getState(editorState);
42
+ if (!pluginState) {
43
+ return;
44
+ }
45
+ return {
46
+ isFormatMenuHidden: pluginState === null || pluginState === void 0 ? void 0 : pluginState.isFormatMenuHidden
47
+ };
48
+ },
37
49
  contentComponent({
38
50
  editorView,
39
51
  popupsMountPoint,
@@ -1,5 +1,5 @@
1
1
  import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
2
- import { isBlockNodeType, isListNodeType, isContainerNodeType } from './utils';
2
+ import { isBlockNodeType, isListNodeType, isContainerNodeType, isBlockNodeForExtraction, convertNodeToInlineContent, getContentSupportChecker } from './utils';
3
3
  const convertInvalidNodeToValidNodeType = (sourceContent, sourceNodeType, validNodeType, withMarks) => {
4
4
  const validTransformedContent = [];
5
5
  // Headings are not valid inside headings so convert heading nodes to paragraphs
@@ -78,8 +78,13 @@ export const transformContainerNode = ({
78
78
 
79
79
  // Transform between container types
80
80
  if (isContainerNodeType(targetNodeType)) {
81
- tr.setNodeMarkup(sourcePos, targetNodeType, targetAttrs);
82
- return tr;
81
+ return transformBetweenContainerTypes({
82
+ tr,
83
+ sourceNode,
84
+ sourcePos,
85
+ targetNodeType,
86
+ targetAttrs
87
+ });
83
88
  }
84
89
  return null;
85
90
  };
@@ -238,4 +243,84 @@ export const unwrapAndConvertToList = ({
238
243
  }
239
244
  createListAndAddToContent();
240
245
  return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, Fragment.from(resultContent));
246
+ };
247
+ export const transformBetweenContainerTypes = context => {
248
+ const {
249
+ tr,
250
+ sourceNode,
251
+ sourcePos,
252
+ targetNodeType,
253
+ targetAttrs
254
+ } = context;
255
+
256
+ // Get content validation for target container type
257
+ const isContentSupported = getContentSupportChecker(targetNodeType);
258
+
259
+ // Process content and collect splits
260
+ const contentSplits = splitContentAroundUnsupportedBlocks(sourceNode, isContentSupported, targetNodeType, targetAttrs, tr.doc.type.schema);
261
+
262
+ // Replace the original node with the first split
263
+ let insertPos = sourcePos;
264
+ contentSplits.forEach((splitNode, index) => {
265
+ if (index === 0) {
266
+ // Replace the original node with the first split
267
+ tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, splitNode);
268
+ insertPos = sourcePos + splitNode.nodeSize;
269
+ } else {
270
+ // Insert additional splits after
271
+ tr.insert(insertPos, splitNode);
272
+ insertPos += splitNode.nodeSize;
273
+ }
274
+ });
275
+ return tr;
276
+ };
277
+
278
+ /**
279
+ * Split content around unsupported block nodes, creating separate containers
280
+ * for content before and after each unsupported block
281
+ */
282
+ const splitContentAroundUnsupportedBlocks = (sourceNode, isContentSupported, targetNodeType, targetAttrs, schema) => {
283
+ var _sourceNode$attrs3;
284
+ const splits = [];
285
+ const children = sourceNode.content.content;
286
+ let currentContainerContent = [];
287
+
288
+ // Handle expand title - add as first paragraph if source is expand with title
289
+ if (sourceNode.type.name === 'expand' && (_sourceNode$attrs3 = sourceNode.attrs) !== null && _sourceNode$attrs3 !== void 0 && _sourceNode$attrs3.title) {
290
+ const titleParagraph = schema.nodes.paragraph.create({}, schema.text(sourceNode.attrs.title));
291
+ currentContainerContent.push(titleParagraph);
292
+ }
293
+ const flushCurrentContainer = () => {
294
+ if (currentContainerContent.length > 0) {
295
+ const containerNode = targetNodeType.create(targetAttrs, Fragment.fromArray(currentContainerContent));
296
+ splits.push(containerNode);
297
+ currentContainerContent = [];
298
+ }
299
+ };
300
+ children.forEach(childNode => {
301
+ if (isContentSupported(childNode)) {
302
+ // Supported content - add to current container
303
+ currentContainerContent.push(childNode);
304
+ } else if (isBlockNodeForExtraction(childNode)) {
305
+ // Unsupported block node - flush current container, add block, continue
306
+ flushCurrentContainer();
307
+ splits.push(childNode);
308
+ } else if (childNode.type.name === targetNodeType.name) {
309
+ // Same type of container merge contents
310
+ childNode.content.forEach(child => {
311
+ currentContainerContent.push(child);
312
+ });
313
+ } else {
314
+ // Unsupported inline content - convert to paragraph and add to container
315
+ const inlineContent = convertNodeToInlineContent(childNode, schema);
316
+ if (inlineContent.length > 0) {
317
+ const paragraph = schema.nodes.paragraph.create({}, Fragment.fromArray(inlineContent));
318
+ currentContainerContent.push(paragraph);
319
+ }
320
+ }
321
+ });
322
+
323
+ // Flush any remaining container content
324
+ flushCurrentContainer();
325
+ return splits;
241
326
  };
@@ -1,3 +1,4 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
1
2
  export const getTargetNodeInfo = (targetType, nodes) => {
2
3
  switch (targetType) {
3
4
  case 'heading1':
@@ -121,4 +122,50 @@ export const getSupportedListTypesSet = nodes => {
121
122
  };
122
123
  export const isLayoutNodeType = nodeType => {
123
124
  return nodeType.name === 'layoutSection';
125
+ };
126
+
127
+ /**
128
+ * Check if a node should be extracted as a standalone block node
129
+ * rather than converted to inline content
130
+ */
131
+ export const isBlockNodeForExtraction = node => {
132
+ const blockNodesForExtraction = ['table', 'mediaSingle', 'extension', 'bodiedExtension', 'blockCard', 'embedCard'];
133
+ return blockNodesForExtraction.includes(node.type.name);
134
+ };
135
+
136
+ /**
137
+ * Get a function that checks if content is supported in the target container type
138
+ */
139
+ export const getContentSupportChecker = targetNodeType => {
140
+ return node => {
141
+ // Check if the target container type can contain this node
142
+ try {
143
+ return targetNodeType.validContent(Fragment.from(node));
144
+ } catch {
145
+ return false;
146
+ }
147
+ };
148
+ };
149
+
150
+ /**
151
+ * Convert a node to inline content that can be placed in a paragraph
152
+ */
153
+ export const convertNodeToInlineContent = (node, schema) => {
154
+ // Extract text and inline nodes from any complex node
155
+ const inlineNodes = [];
156
+ node.descendants(childNode => {
157
+ if (childNode.isText) {
158
+ inlineNodes.push(childNode);
159
+ } else if (childNode.isInline) {
160
+ inlineNodes.push(childNode);
161
+ }
162
+ return true; // Continue traversing
163
+ });
164
+
165
+ // If no inline content was found but the node has text content,
166
+ // create a text node with the full text content
167
+ if (inlineNodes.length === 0 && node.textContent) {
168
+ return [schema.text(node.textContent)];
169
+ }
170
+ return inlineNodes;
124
171
  };
@@ -0,0 +1,34 @@
1
+ import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
2
+ const TOP_LEVEL_NODE_DEPTHS = {
3
+ LIST_TYPE: 2,
4
+ PARAGRAPH_OR_HEADING: 1,
5
+ BLOCKQUOTE: 1,
6
+ BLOCK: 0
7
+ };
8
+ export const getIsFormatMenuHidden = tr => {
9
+ const selection = tr.selection;
10
+ const nodes = tr.doc.type.schema.nodes;
11
+ if (selection.from === selection.to || selection.empty || !nodes) {
12
+ return false;
13
+ }
14
+ let content;
15
+ let isTopLevelNode = false;
16
+ const selectedNode = findSelectedNodeOfType([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.layoutSection])(selection);
17
+ if (selectedNode) {
18
+ content = selectedNode.node;
19
+ isTopLevelNode = selectedNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCK;
20
+ } else {
21
+ const listTypeOrBlockQuoteNode = findParentNodeOfType([nodes.blockquote, nodes.listItem, nodes.taskItem])(selection);
22
+ if (listTypeOrBlockQuoteNode) {
23
+ content = listTypeOrBlockQuoteNode.node;
24
+ isTopLevelNode = listTypeOrBlockQuoteNode.node.type === nodes.blockquote ? listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCKQUOTE : listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.LIST_TYPE;
25
+ } else {
26
+ const paragraphOrHeadingNode = findParentNodeOfType([nodes.paragraph, nodes.heading])(selection);
27
+ if (paragraphOrHeadingNode) {
28
+ content = paragraphOrHeadingNode.node;
29
+ isTopLevelNode = paragraphOrHeadingNode.depth === TOP_LEVEL_NODE_DEPTHS.PARAGRAPH_OR_HEADING;
30
+ }
31
+ }
32
+ }
33
+ return !content || !isTopLevelNode;
34
+ };
@@ -1,5 +1,6 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
+ import { getIsFormatMenuHidden } from './getIsFormatMenuHidden';
3
4
  export const blockMenuPluginKey = new PluginKey('blockMenuPlugin');
4
5
 
5
6
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -9,14 +10,23 @@ export const createPlugin = () => {
9
10
  key: blockMenuPluginKey,
10
11
  state: {
11
12
  init() {
12
- return {};
13
+ return {
14
+ isFormatMenuHidden: false
15
+ };
13
16
  },
14
17
  apply: (tr, currentPluginState) => {
15
18
  const meta = tr.getMeta(blockMenuPluginKey);
16
19
  if (meta) {
17
- return meta;
20
+ return {
21
+ ...currentPluginState,
22
+ ...meta
23
+ };
18
24
  }
19
- return currentPluginState;
25
+ const isFormatMenuHidden = getIsFormatMenuHidden(tr);
26
+ return {
27
+ ...currentPluginState,
28
+ isFormatMenuHidden
29
+ };
20
30
  }
21
31
  }
22
32
  });
@@ -6,6 +6,7 @@ import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
6
6
  import CopyBlockMenuItem from './copy-block';
7
7
  import { CopyLinkDropdownItem } from './copy-link';
8
8
  import { DeleteDropdownItem } from './delete-button';
9
+ import { FormatMenuSection } from './format-menu-section';
9
10
  import { MoveDownDropdownItem } from './move-down';
10
11
  import { MoveUpDropdownItem } from './move-up';
11
12
  const getMoveUpMoveDownMenuComponents = api => {
@@ -33,7 +34,7 @@ const getMoveUpMoveDownMenuComponents = api => {
33
34
  })
34
35
  }];
35
36
  };
36
- const getFormatMenuComponents = () => {
37
+ const getFormatMenuComponents = api => {
37
38
  return [{
38
39
  type: 'block-menu-nested',
39
40
  key: NESTED_FORMAT_MENU.key,
@@ -80,7 +81,9 @@ const getFormatMenuComponents = () => {
80
81
  component: ({
81
82
  children
82
83
  }) => {
83
- return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, null, children);
84
+ return /*#__PURE__*/React.createElement(FormatMenuSection, {
85
+ api: api
86
+ }, children);
84
87
  }
85
88
  }];
86
89
  };
@@ -88,15 +91,16 @@ export const getBlockMenuComponents = ({
88
91
  api,
89
92
  config
90
93
  }) => {
91
- return [...getFormatMenuComponents(), {
94
+ return [...getFormatMenuComponents(api), {
92
95
  type: 'block-menu-section',
93
96
  key: COPY_MENU_SECTION.key,
94
97
  rank: BLOCK_MENU_SECTION_RANK[COPY_MENU_SECTION.key],
95
98
  component: ({
96
99
  children
97
100
  }) => {
101
+ var _api$blockMenu$shared;
98
102
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
99
- hasSeparator: true
103
+ hasSeparator: !(api !== null && api !== void 0 && (_api$blockMenu$shared = api.blockMenu.sharedState.currentState()) !== null && _api$blockMenu$shared !== void 0 && _api$blockMenu$shared.isFormatMenuHidden)
100
104
  }, children);
101
105
  }
102
106
  }, {
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
4
+ export const FormatMenuSection = ({
5
+ children,
6
+ api
7
+ }) => {
8
+ const isFormatMenuHidden = useSharedPluginStateSelector(api, 'blockMenu.isFormatMenuHidden');
9
+ if (isFormatMenuHidden) {
10
+ return null;
11
+ }
12
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, null, children);
13
+ };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { createBlockMenuRegistry } from './editor-actions';
3
3
  import { formatNode as _formatNode } from './editor-commands/formatNode';
4
- import { createPlugin } from './pm-plugins/main';
4
+ import { blockMenuPluginKey, createPlugin } from './pm-plugins/main';
5
5
  import BlockMenu from './ui/block-menu';
6
6
  import { getBlockMenuComponents } from './ui/block-menu-components';
7
7
  export var blockMenuPlugin = function blockMenuPlugin(_ref) {
@@ -33,6 +33,18 @@ export var blockMenuPlugin = function blockMenuPlugin(_ref) {
33
33
  return _formatNode(targetType);
34
34
  }
35
35
  },
36
+ getSharedState: function getSharedState(editorState) {
37
+ if (!editorState) {
38
+ return;
39
+ }
40
+ var pluginState = blockMenuPluginKey.getState(editorState);
41
+ if (!pluginState) {
42
+ return;
43
+ }
44
+ return {
45
+ isFormatMenuHidden: pluginState === null || pluginState === void 0 ? void 0 : pluginState.isFormatMenuHidden
46
+ };
47
+ },
36
48
  contentComponent: function contentComponent(_ref2) {
37
49
  var editorView = _ref2.editorView,
38
50
  popupsMountPoint = _ref2.popupsMountPoint,
@@ -1,6 +1,6 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
3
- import { isBlockNodeType, isListNodeType, isContainerNodeType } from './utils';
3
+ import { isBlockNodeType, isListNodeType, isContainerNodeType, isBlockNodeForExtraction, convertNodeToInlineContent, getContentSupportChecker } from './utils';
4
4
  var convertInvalidNodeToValidNodeType = function convertInvalidNodeToValidNodeType(sourceContent, sourceNodeType, validNodeType, withMarks) {
5
5
  var validTransformedContent = [];
6
6
  // Headings are not valid inside headings so convert heading nodes to paragraphs
@@ -77,8 +77,13 @@ export var transformContainerNode = function transformContainerNode(_ref2) {
77
77
 
78
78
  // Transform between container types
79
79
  if (isContainerNodeType(targetNodeType)) {
80
- tr.setNodeMarkup(sourcePos, targetNodeType, targetAttrs);
81
- return tr;
80
+ return transformBetweenContainerTypes({
81
+ tr: tr,
82
+ sourceNode: sourceNode,
83
+ sourcePos: sourcePos,
84
+ targetNodeType: targetNodeType,
85
+ targetAttrs: targetAttrs
86
+ });
82
87
  }
83
88
  return null;
84
89
  };
@@ -234,4 +239,82 @@ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
234
239
  }
235
240
  createListAndAddToContent();
236
241
  return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, Fragment.from(resultContent));
242
+ };
243
+ export var transformBetweenContainerTypes = function transformBetweenContainerTypes(context) {
244
+ var tr = context.tr,
245
+ sourceNode = context.sourceNode,
246
+ sourcePos = context.sourcePos,
247
+ targetNodeType = context.targetNodeType,
248
+ targetAttrs = context.targetAttrs;
249
+
250
+ // Get content validation for target container type
251
+ var isContentSupported = getContentSupportChecker(targetNodeType);
252
+
253
+ // Process content and collect splits
254
+ var contentSplits = splitContentAroundUnsupportedBlocks(sourceNode, isContentSupported, targetNodeType, targetAttrs, tr.doc.type.schema);
255
+
256
+ // Replace the original node with the first split
257
+ var insertPos = sourcePos;
258
+ contentSplits.forEach(function (splitNode, index) {
259
+ if (index === 0) {
260
+ // Replace the original node with the first split
261
+ tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, splitNode);
262
+ insertPos = sourcePos + splitNode.nodeSize;
263
+ } else {
264
+ // Insert additional splits after
265
+ tr.insert(insertPos, splitNode);
266
+ insertPos += splitNode.nodeSize;
267
+ }
268
+ });
269
+ return tr;
270
+ };
271
+
272
+ /**
273
+ * Split content around unsupported block nodes, creating separate containers
274
+ * for content before and after each unsupported block
275
+ */
276
+ var splitContentAroundUnsupportedBlocks = function splitContentAroundUnsupportedBlocks(sourceNode, isContentSupported, targetNodeType, targetAttrs, schema) {
277
+ var _sourceNode$attrs3;
278
+ var splits = [];
279
+ var children = sourceNode.content.content;
280
+ var currentContainerContent = [];
281
+
282
+ // Handle expand title - add as first paragraph if source is expand with title
283
+ if (sourceNode.type.name === 'expand' && (_sourceNode$attrs3 = sourceNode.attrs) !== null && _sourceNode$attrs3 !== void 0 && _sourceNode$attrs3.title) {
284
+ var titleParagraph = schema.nodes.paragraph.create({}, schema.text(sourceNode.attrs.title));
285
+ currentContainerContent.push(titleParagraph);
286
+ }
287
+ var flushCurrentContainer = function flushCurrentContainer() {
288
+ if (currentContainerContent.length > 0) {
289
+ var containerNode = targetNodeType.create(targetAttrs, Fragment.fromArray(currentContainerContent));
290
+ splits.push(containerNode);
291
+ currentContainerContent = [];
292
+ }
293
+ };
294
+ children.forEach(function (childNode) {
295
+ if (isContentSupported(childNode)) {
296
+ // Supported content - add to current container
297
+ currentContainerContent.push(childNode);
298
+ } else if (isBlockNodeForExtraction(childNode)) {
299
+ // Unsupported block node - flush current container, add block, continue
300
+ flushCurrentContainer();
301
+ splits.push(childNode);
302
+ } else if (childNode.type.name === targetNodeType.name) {
303
+ // Same type of container merge contents
304
+ childNode.content.forEach(function (child) {
305
+ currentContainerContent.push(child);
306
+ });
307
+ } else {
308
+ // Unsupported inline content - convert to paragraph and add to container
309
+ var inlineContent = convertNodeToInlineContent(childNode, schema);
310
+ if (inlineContent.length > 0) {
311
+ var paragraph = schema.nodes.paragraph.create({}, Fragment.fromArray(inlineContent));
312
+ currentContainerContent.push(paragraph);
313
+ }
314
+ }
315
+ });
316
+
317
+ // Flush any remaining container content
318
+ flushCurrentContainer();
319
+ return splits;
237
320
  };
@@ -1,3 +1,4 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
1
2
  export var getTargetNodeInfo = function getTargetNodeInfo(targetType, nodes) {
2
3
  switch (targetType) {
3
4
  case 'heading1':
@@ -121,4 +122,50 @@ export var getSupportedListTypesSet = function getSupportedListTypesSet(nodes) {
121
122
  };
122
123
  export var isLayoutNodeType = function isLayoutNodeType(nodeType) {
123
124
  return nodeType.name === 'layoutSection';
125
+ };
126
+
127
+ /**
128
+ * Check if a node should be extracted as a standalone block node
129
+ * rather than converted to inline content
130
+ */
131
+ export var isBlockNodeForExtraction = function isBlockNodeForExtraction(node) {
132
+ var blockNodesForExtraction = ['table', 'mediaSingle', 'extension', 'bodiedExtension', 'blockCard', 'embedCard'];
133
+ return blockNodesForExtraction.includes(node.type.name);
134
+ };
135
+
136
+ /**
137
+ * Get a function that checks if content is supported in the target container type
138
+ */
139
+ export var getContentSupportChecker = function getContentSupportChecker(targetNodeType) {
140
+ return function (node) {
141
+ // Check if the target container type can contain this node
142
+ try {
143
+ return targetNodeType.validContent(Fragment.from(node));
144
+ } catch (_unused) {
145
+ return false;
146
+ }
147
+ };
148
+ };
149
+
150
+ /**
151
+ * Convert a node to inline content that can be placed in a paragraph
152
+ */
153
+ export var convertNodeToInlineContent = function convertNodeToInlineContent(node, schema) {
154
+ // Extract text and inline nodes from any complex node
155
+ var inlineNodes = [];
156
+ node.descendants(function (childNode) {
157
+ if (childNode.isText) {
158
+ inlineNodes.push(childNode);
159
+ } else if (childNode.isInline) {
160
+ inlineNodes.push(childNode);
161
+ }
162
+ return true; // Continue traversing
163
+ });
164
+
165
+ // If no inline content was found but the node has text content,
166
+ // create a text node with the full text content
167
+ if (inlineNodes.length === 0 && node.textContent) {
168
+ return [schema.text(node.textContent)];
169
+ }
170
+ return inlineNodes;
124
171
  };
@@ -0,0 +1,34 @@
1
+ import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
2
+ var TOP_LEVEL_NODE_DEPTHS = {
3
+ LIST_TYPE: 2,
4
+ PARAGRAPH_OR_HEADING: 1,
5
+ BLOCKQUOTE: 1,
6
+ BLOCK: 0
7
+ };
8
+ export var getIsFormatMenuHidden = function getIsFormatMenuHidden(tr) {
9
+ var selection = tr.selection;
10
+ var nodes = tr.doc.type.schema.nodes;
11
+ if (selection.from === selection.to || selection.empty || !nodes) {
12
+ return false;
13
+ }
14
+ var content;
15
+ var isTopLevelNode = false;
16
+ var selectedNode = findSelectedNodeOfType([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.layoutSection])(selection);
17
+ if (selectedNode) {
18
+ content = selectedNode.node;
19
+ isTopLevelNode = selectedNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCK;
20
+ } else {
21
+ var listTypeOrBlockQuoteNode = findParentNodeOfType([nodes.blockquote, nodes.listItem, nodes.taskItem])(selection);
22
+ if (listTypeOrBlockQuoteNode) {
23
+ content = listTypeOrBlockQuoteNode.node;
24
+ isTopLevelNode = listTypeOrBlockQuoteNode.node.type === nodes.blockquote ? listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.BLOCKQUOTE : listTypeOrBlockQuoteNode.depth === TOP_LEVEL_NODE_DEPTHS.LIST_TYPE;
25
+ } else {
26
+ var paragraphOrHeadingNode = findParentNodeOfType([nodes.paragraph, nodes.heading])(selection);
27
+ if (paragraphOrHeadingNode) {
28
+ content = paragraphOrHeadingNode.node;
29
+ isTopLevelNode = paragraphOrHeadingNode.depth === TOP_LEVEL_NODE_DEPTHS.PARAGRAPH_OR_HEADING;
30
+ }
31
+ }
32
+ }
33
+ return !content || !isTopLevelNode;
34
+ };
@@ -1,5 +1,9 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
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
+ 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; }
1
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
+ import { getIsFormatMenuHidden } from './getIsFormatMenuHidden';
3
7
  export var blockMenuPluginKey = new PluginKey('blockMenuPlugin');
4
8
 
5
9
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -9,14 +13,19 @@ export var createPlugin = function createPlugin() {
9
13
  key: blockMenuPluginKey,
10
14
  state: {
11
15
  init: function init() {
12
- return {};
16
+ return {
17
+ isFormatMenuHidden: false
18
+ };
13
19
  },
14
20
  apply: function apply(tr, currentPluginState) {
15
21
  var meta = tr.getMeta(blockMenuPluginKey);
16
22
  if (meta) {
17
- return meta;
23
+ return _objectSpread(_objectSpread({}, currentPluginState), meta);
18
24
  }
19
- return currentPluginState;
25
+ var isFormatMenuHidden = getIsFormatMenuHidden(tr);
26
+ return _objectSpread(_objectSpread({}, currentPluginState), {}, {
27
+ isFormatMenuHidden: isFormatMenuHidden
28
+ });
20
29
  }
21
30
  }
22
31
  });
@@ -7,6 +7,7 @@ import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
7
7
  import CopyBlockMenuItem from './copy-block';
8
8
  import { CopyLinkDropdownItem } from './copy-link';
9
9
  import { DeleteDropdownItem } from './delete-button';
10
+ import { FormatMenuSection } from './format-menu-section';
10
11
  import { MoveDownDropdownItem } from './move-down';
11
12
  import { MoveUpDropdownItem } from './move-up';
12
13
  var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(api) {
@@ -38,7 +39,7 @@ var getMoveUpMoveDownMenuComponents = function getMoveUpMoveDownMenuComponents(a
38
39
  }
39
40
  }];
40
41
  };
41
- var getFormatMenuComponents = function getFormatMenuComponents() {
42
+ var getFormatMenuComponents = function getFormatMenuComponents(api) {
42
43
  return [{
43
44
  type: 'block-menu-nested',
44
45
  key: NESTED_FORMAT_MENU.key,
@@ -84,21 +85,24 @@ var getFormatMenuComponents = function getFormatMenuComponents() {
84
85
  rank: 100,
85
86
  component: function component(_ref3) {
86
87
  var children = _ref3.children;
87
- return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, null, children);
88
+ return /*#__PURE__*/React.createElement(FormatMenuSection, {
89
+ api: api
90
+ }, children);
88
91
  }
89
92
  }];
90
93
  };
91
94
  export var getBlockMenuComponents = function getBlockMenuComponents(_ref4) {
92
95
  var api = _ref4.api,
93
96
  config = _ref4.config;
94
- return [].concat(_toConsumableArray(getFormatMenuComponents()), [{
97
+ return [].concat(_toConsumableArray(getFormatMenuComponents(api)), [{
95
98
  type: 'block-menu-section',
96
99
  key: COPY_MENU_SECTION.key,
97
100
  rank: BLOCK_MENU_SECTION_RANK[COPY_MENU_SECTION.key],
98
101
  component: function component(_ref5) {
102
+ var _api$blockMenu$shared;
99
103
  var children = _ref5.children;
100
104
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
101
- hasSeparator: true
105
+ hasSeparator: !(api !== null && api !== void 0 && (_api$blockMenu$shared = api.blockMenu.sharedState.currentState()) !== null && _api$blockMenu$shared !== void 0 && _api$blockMenu$shared.isFormatMenuHidden)
102
106
  }, children);
103
107
  }
104
108
  }, {
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
4
+ export var FormatMenuSection = function FormatMenuSection(_ref) {
5
+ var children = _ref.children,
6
+ api = _ref.api;
7
+ var isFormatMenuHidden = useSharedPluginStateSelector(api, 'blockMenu.isFormatMenuHidden');
8
+ if (isFormatMenuHidden) {
9
+ return null;
10
+ }
11
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, null, children);
12
+ };
@@ -19,6 +19,9 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
19
19
  OptionalPlugin<DecorationsPlugin>
20
20
  ];
21
21
  pluginConfiguration?: BlockMenuPluginOptions;
22
+ sharedState: {
23
+ isFormatMenuHidden?: boolean;
24
+ } | undefined;
22
25
  }>;
23
26
  export type BlockMenuPluginOptions = {
24
27
  /**
@@ -15,3 +15,4 @@ export declare const unwrapAndConvertToBlockType: (context: TransformContext) =>
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
17
  export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction | null;
18
+ export declare const transformBetweenContainerTypes: (context: TransformContext) => import("prosemirror-state").Transaction;
@@ -1,4 +1,4 @@
1
- import type { Node as PMNode, NodeType } from '@atlaskit/editor-prosemirror/model';
1
+ import type { Node as PMNode, NodeType, Schema } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { FormatNodeTargetType } from './types';
3
3
  export declare const getTargetNodeInfo: (targetType: FormatNodeTargetType, nodes: Record<string, NodeType>) => {
4
4
  attrs?: Record<string, unknown>;
@@ -15,3 +15,16 @@ export declare const isTaskList: (nodeType: NodeType) => boolean;
15
15
  export declare const getSupportedListTypes: (nodes: Record<string, NodeType>) => NodeType[];
16
16
  export declare const getSupportedListTypesSet: (nodes: Record<string, NodeType>) => Set<NodeType>;
17
17
  export declare const isLayoutNodeType: (nodeType: NodeType) => boolean;
18
+ /**
19
+ * Check if a node should be extracted as a standalone block node
20
+ * rather than converted to inline content
21
+ */
22
+ export declare const isBlockNodeForExtraction: (node: PMNode) => boolean;
23
+ /**
24
+ * Get a function that checks if content is supported in the target container type
25
+ */
26
+ export declare const getContentSupportChecker: (targetNodeType: NodeType) => ((node: PMNode) => boolean);
27
+ /**
28
+ * Convert a node to inline content that can be placed in a paragraph
29
+ */
30
+ export declare const convertNodeToInlineContent: (node: PMNode, schema: Schema) => PMNode[];
@@ -0,0 +1,2 @@
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getIsFormatMenuHidden: (tr: ReadonlyTransaction) => boolean;
@@ -1,6 +1,8 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  export declare const blockMenuPluginKey: PluginKey<any>;
4
- type BlockMenuPluginState = {};
4
+ type BlockMenuPluginState = {
5
+ isFormatMenuHidden: boolean;
6
+ };
5
7
  export declare const createPlugin: () => SafePlugin<BlockMenuPluginState>;
6
8
  export {};
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
+ export declare const FormatMenuSection: ({ children, api, }: {
5
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
6
+ children: React.ReactNode;
7
+ }) => React.JSX.Element | null;
@@ -19,6 +19,9 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
19
19
  OptionalPlugin<DecorationsPlugin>
20
20
  ];
21
21
  pluginConfiguration?: BlockMenuPluginOptions;
22
+ sharedState: {
23
+ isFormatMenuHidden?: boolean;
24
+ } | undefined;
22
25
  }>;
23
26
  export type BlockMenuPluginOptions = {
24
27
  /**
@@ -15,3 +15,4 @@ export declare const unwrapAndConvertToBlockType: (context: TransformContext) =>
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
17
  export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction | null;
18
+ export declare const transformBetweenContainerTypes: (context: TransformContext) => import("prosemirror-state").Transaction;
@@ -1,4 +1,4 @@
1
- import type { Node as PMNode, NodeType } from '@atlaskit/editor-prosemirror/model';
1
+ import type { Node as PMNode, NodeType, Schema } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { FormatNodeTargetType } from './types';
3
3
  export declare const getTargetNodeInfo: (targetType: FormatNodeTargetType, nodes: Record<string, NodeType>) => {
4
4
  attrs?: Record<string, unknown>;
@@ -15,3 +15,16 @@ export declare const isTaskList: (nodeType: NodeType) => boolean;
15
15
  export declare const getSupportedListTypes: (nodes: Record<string, NodeType>) => NodeType[];
16
16
  export declare const getSupportedListTypesSet: (nodes: Record<string, NodeType>) => Set<NodeType>;
17
17
  export declare const isLayoutNodeType: (nodeType: NodeType) => boolean;
18
+ /**
19
+ * Check if a node should be extracted as a standalone block node
20
+ * rather than converted to inline content
21
+ */
22
+ export declare const isBlockNodeForExtraction: (node: PMNode) => boolean;
23
+ /**
24
+ * Get a function that checks if content is supported in the target container type
25
+ */
26
+ export declare const getContentSupportChecker: (targetNodeType: NodeType) => ((node: PMNode) => boolean);
27
+ /**
28
+ * Convert a node to inline content that can be placed in a paragraph
29
+ */
30
+ export declare const convertNodeToInlineContent: (node: PMNode, schema: Schema) => PMNode[];
@@ -0,0 +1,2 @@
1
+ import type { ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
2
+ export declare const getIsFormatMenuHidden: (tr: ReadonlyTransaction) => boolean;
@@ -1,6 +1,8 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  export declare const blockMenuPluginKey: PluginKey<any>;
4
- type BlockMenuPluginState = {};
4
+ type BlockMenuPluginState = {
5
+ isFormatMenuHidden: boolean;
6
+ };
5
7
  export declare const createPlugin: () => SafePlugin<BlockMenuPluginState>;
6
8
  export {};
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
+ import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
+ export declare const FormatMenuSection: ({ children, api, }: {
5
+ api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
6
+ children: React.ReactNode;
7
+ }) => React.JSX.Element | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -28,7 +28,7 @@
28
28
  "sideEffects": false,
29
29
  "atlaskit:src": "src/index.ts",
30
30
  "dependencies": {
31
- "@atlaskit/css": "^0.13.0",
31
+ "@atlaskit/css": "^0.14.0",
32
32
  "@atlaskit/dropdown-menu": "^16.3.0",
33
33
  "@atlaskit/editor-plugin-block-controls": "^5.0.0",
34
34
  "@atlaskit/editor-plugin-decorations": "^4.0.0",
@@ -41,8 +41,8 @@
41
41
  "@atlaskit/icon": "^28.1.0",
42
42
  "@atlaskit/icon-lab": "^5.7.0",
43
43
  "@atlaskit/platform-feature-flags": "^1.1.0",
44
- "@atlaskit/primitives": "^14.13.0",
45
- "@atlaskit/tokens": "^6.2.0",
44
+ "@atlaskit/primitives": "^14.14.0",
45
+ "@atlaskit/tokens": "^6.3.0",
46
46
  "@babel/runtime": "^7.0.0"
47
47
  },
48
48
  "peerDependencies": {