@atlaskit/editor-plugin-block-menu 3.2.0 → 3.2.2

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 (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/blockMenuPlugin.js +5 -2
  3. package/dist/cjs/editor-commands/formatNode.js +48 -1
  4. package/dist/cjs/editor-commands/transforms/container-transforms.js +15 -4
  5. package/dist/cjs/editor-commands/transforms/layout-transforms.js +29 -18
  6. package/dist/cjs/editor-commands/transforms/utils.js +20 -1
  7. package/dist/cjs/ui/block-menu-components.js +5 -14
  8. package/dist/cjs/ui/block-menu-provider.js +40 -0
  9. package/dist/cjs/ui/block-menu.js +14 -4
  10. package/dist/cjs/ui/copy-block.js +11 -3
  11. package/dist/cjs/ui/copy-section.js +7 -0
  12. package/dist/cjs/ui/delete-section.js +23 -0
  13. package/dist/cjs/ui/format-menu-nested.js +28 -0
  14. package/dist/cjs/ui/utils/checkIsFormatMenuHidden.js +35 -1
  15. package/dist/es2019/blockMenuPlugin.js +5 -2
  16. package/dist/es2019/editor-commands/formatNode.js +53 -2
  17. package/dist/es2019/editor-commands/transforms/container-transforms.js +18 -5
  18. package/dist/es2019/editor-commands/transforms/layout-transforms.js +22 -11
  19. package/dist/es2019/editor-commands/transforms/utils.js +13 -0
  20. package/dist/es2019/ui/block-menu-components.js +6 -15
  21. package/dist/es2019/ui/block-menu-provider.js +31 -0
  22. package/dist/es2019/ui/block-menu.js +15 -4
  23. package/dist/es2019/ui/copy-block.js +9 -3
  24. package/dist/es2019/ui/copy-section.js +7 -0
  25. package/dist/es2019/ui/delete-section.js +17 -0
  26. package/dist/es2019/ui/format-menu-nested.js +23 -0
  27. package/dist/es2019/ui/utils/checkIsFormatMenuHidden.js +35 -1
  28. package/dist/esm/blockMenuPlugin.js +5 -2
  29. package/dist/esm/editor-commands/formatNode.js +49 -2
  30. package/dist/esm/editor-commands/transforms/container-transforms.js +16 -5
  31. package/dist/esm/editor-commands/transforms/layout-transforms.js +28 -17
  32. package/dist/esm/editor-commands/transforms/utils.js +18 -0
  33. package/dist/esm/ui/block-menu-components.js +6 -15
  34. package/dist/esm/ui/block-menu-provider.js +32 -0
  35. package/dist/esm/ui/block-menu.js +14 -4
  36. package/dist/esm/ui/copy-block.js +11 -3
  37. package/dist/esm/ui/copy-section.js +7 -0
  38. package/dist/esm/ui/delete-section.js +16 -0
  39. package/dist/esm/ui/format-menu-nested.js +21 -0
  40. package/dist/esm/ui/utils/checkIsFormatMenuHidden.js +35 -1
  41. package/dist/types/editor-commands/transforms/layout-transforms.d.ts +3 -0
  42. package/dist/types/editor-commands/transforms/utils.d.ts +2 -1
  43. package/dist/types/ui/block-menu-components.d.ts +1 -2
  44. package/dist/types/ui/block-menu-provider.d.ts +18 -0
  45. package/dist/types/ui/block-menu.d.ts +1 -1
  46. package/dist/types/ui/copy-section.d.ts +1 -1
  47. package/dist/types/ui/delete-section.d.ts +7 -0
  48. package/dist/types/ui/format-menu-nested.d.ts +4 -0
  49. package/dist/types-ts4.5/editor-commands/transforms/layout-transforms.d.ts +3 -0
  50. package/dist/types-ts4.5/editor-commands/transforms/utils.d.ts +2 -1
  51. package/dist/types-ts4.5/ui/block-menu-components.d.ts +1 -2
  52. package/dist/types-ts4.5/ui/block-menu-provider.d.ts +18 -0
  53. package/dist/types-ts4.5/ui/block-menu.d.ts +1 -1
  54. package/dist/types-ts4.5/ui/copy-section.d.ts +1 -1
  55. package/dist/types-ts4.5/ui/delete-section.d.ts +7 -0
  56. package/dist/types-ts4.5/ui/format-menu-nested.d.ts +4 -0
  57. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 3.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`0cde512c00691`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0cde512c00691) -
8
+ [ux] When resized node it transformed to another resized node, the width should be preserved.
9
+ - [`245e047a2f6e9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/245e047a2f6e9) -
10
+ [ux] Change `Format` option text to `Turn into` in block menu
11
+ - Updated dependencies
12
+
13
+ ## 3.2.1
14
+
15
+ ### Patch Changes
16
+
17
+ - [`7958282e36bdf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7958282e36bdf) -
18
+ [ux] ED-29222: Show block menu on empty line
19
+ - Updated dependencies
20
+
3
21
  ## 3.2.0
4
22
 
5
23
  ### Minor Changes
@@ -11,6 +11,7 @@ var _formatNode2 = require("./editor-commands/formatNode");
11
11
  var _main = require("./pm-plugins/main");
12
12
  var _blockMenu = _interopRequireDefault(require("./ui/block-menu"));
13
13
  var _blockMenuComponents = require("./ui/block-menu-components");
14
+ var _blockMenuProvider = require("./ui/block-menu-provider");
14
15
  var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
15
16
  var api = _ref.api,
16
17
  config = _ref.config;
@@ -59,13 +60,15 @@ var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
59
60
  popupsMountPoint = _ref2.popupsMountPoint,
60
61
  popupsBoundariesElement = _ref2.popupsBoundariesElement,
61
62
  popupsScrollableElement = _ref2.popupsScrollableElement;
62
- return /*#__PURE__*/_react.default.createElement(_blockMenu.default, {
63
+ return /*#__PURE__*/_react.default.createElement(_blockMenuProvider.BlockMenuProvider, {
64
+ api: api
65
+ }, /*#__PURE__*/_react.default.createElement(_blockMenu.default, {
63
66
  editorView: editorView,
64
67
  api: api,
65
68
  mountTo: popupsMountPoint,
66
69
  boundariesElement: popupsBoundariesElement,
67
70
  scrollableElement: popupsScrollableElement
68
- });
71
+ }));
69
72
  }
70
73
  };
71
74
  };
@@ -5,7 +5,48 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.formatNode = void 0;
7
7
  var _utils = require("@atlaskit/editor-prosemirror/utils");
8
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
9
+ var _layoutTransforms = require("./transforms/layout-transforms");
8
10
  var _transformNodeToTargetType = require("./transforms/transformNodeToTargetType");
11
+ /**
12
+ * Handles formatting when selection is empty by inserting a new target node
13
+ */
14
+ var formatNodeWhenSelectionEmpty = function formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema) {
15
+ var _pmSafeInsert;
16
+ var nodes = schema.nodes;
17
+ var paragraph = nodes.paragraph;
18
+ // if not using the ' ' here, the safeInsert from editor-common will fail to insert the heading
19
+ // and the pmSafeInsert introduce an issue that after inserting heading, and click on the handle, selection will go to top of the doc
20
+ // as an workaround, use the spaceTextNode here
21
+ var spaceTextNode = schema.text(' ');
22
+ var targetNode;
23
+ if (targetType.startsWith('heading')) {
24
+ var levelString = targetType.slice(-1);
25
+ var level = parseInt(levelString, 10);
26
+ if (isNaN(level) || level < 1 || level > 6) {
27
+ return null;
28
+ }
29
+ targetNode = nodes.heading.createAndFill({
30
+ level: level
31
+ }, spaceTextNode);
32
+ } else if (targetType === 'paragraph') {
33
+ targetNode = nodes.paragraph.createAndFill({}, spaceTextNode);
34
+ } else if (targetType === 'layoutSection') {
35
+ var contentAsParagraph = paragraph.createAndFill({}, spaceTextNode);
36
+ if (contentAsParagraph) {
37
+ targetNode = (0, _layoutTransforms.createDefaultLayoutSection)(schema, contentAsParagraph);
38
+ }
39
+ } else {
40
+ var targetNodeType = nodes[targetType];
41
+ targetNode = targetNodeType.createAndFill();
42
+ }
43
+ if (!targetNode) {
44
+ return tr;
45
+ }
46
+ tr = (_pmSafeInsert = (0, _utils.safeInsert)(targetNode, nodePos)(tr)) !== null && _pmSafeInsert !== void 0 ? _pmSafeInsert : tr;
47
+ return tr;
48
+ };
49
+
9
50
  /**
10
51
  * Formats the current node or selection to the specified target type
11
52
  * @param targetType - The target node type to convert to
@@ -14,12 +55,18 @@ var formatNode = exports.formatNode = function formatNode(targetType) {
14
55
  return function (_ref) {
15
56
  var tr = _ref.tr;
16
57
  var selection = tr.selection;
17
- var nodes = tr.doc.type.schema.nodes;
58
+ var schema = tr.doc.type.schema;
59
+ var nodes = schema.nodes;
18
60
 
19
61
  // Find the node to format from the current selection
20
62
  var nodeToFormat;
21
63
  var nodePos = selection.from;
22
64
 
65
+ // when selection is empty, we insert a empty target node
66
+ if (selection.empty && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true)) {
67
+ return formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema);
68
+ }
69
+
23
70
  // Try to find the current node from selection
24
71
  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);
25
72
  if (selectedNode) {
@@ -35,9 +35,11 @@ var transformToContainer = exports.transformToContainer = function transformToCo
35
35
  var schema = tr.doc.type.schema;
36
36
  var content = selection.content().content;
37
37
  var transformedContent = content;
38
+ var marks = [];
38
39
  if (sourceNode.type === schema.nodes.codeBlock) {
39
40
  var paragraphNodes = (0, _utils2.convertCodeBlockContentToParagraphs)(sourceNode, schema);
40
41
  transformedContent = _model.Fragment.fromArray(paragraphNodes);
42
+ marks = (0, _utils2.getMarksWithBreakout)(sourceNode, targetNodeType);
41
43
  }
42
44
  if (targetNodeType === schema.nodes.blockquote) {
43
45
  transformedContent = convertInvalidNodeToValidNodeType(transformedContent, schema.nodes.heading, schema.nodes.paragraph, true);
@@ -49,7 +51,7 @@ var transformToContainer = exports.transformToContainer = function transformToCo
49
51
  if (sourceNode.type === schema.nodes.paragraph || sourceNode.type === schema.nodes.heading) {
50
52
  transformedContent = (0, _utils2.filterMarksForTargetNodeType)(transformedContent, targetNodeType);
51
53
  }
52
- var newNode = targetNodeType.createAndFill(targetAttrs, transformedContent);
54
+ var newNode = targetNodeType.createAndFill(targetAttrs, transformedContent, marks);
53
55
  if (!newNode) {
54
56
  return null;
55
57
  }
@@ -175,7 +177,8 @@ var unwrapAndConvertToBlockType = exports.unwrapAndConvertToBlockType = function
175
177
  var codeBlockContent = sourceChildren.map(function (node) {
176
178
  return node.content.textBetween(0, node.content.size, '\n');
177
179
  }).join('\n');
178
- transformedContent = [codeBlock.createChecked({}, schema.text(codeBlockContent))];
180
+ var marks = (0, _utils2.getMarksWithBreakout)(sourceNode, targetNodeType);
181
+ transformedContent = [codeBlock.createChecked({}, schema.text(codeBlockContent), marks)];
179
182
  }
180
183
  var slice = new _model.Slice(_model.Fragment.fromArray(transformedContent), 0, 0);
181
184
  tr.replaceRange(rangeStart, rangeStart + sourceNode.nodeSize, slice);
@@ -272,6 +275,12 @@ var transformBetweenContainerTypes = exports.transformBetweenContainerTypes = fu
272
275
  // Special handling for codeBlock target
273
276
  if (targetNodeType.name === 'codeBlock') {
274
277
  var _contentSplits = splitContentForCodeBlock(sourceNode, targetNodeType, targetAttrs, tr.doc.type.schema);
278
+ if (_contentSplits.length === 0) {
279
+ var schema = tr.doc.type.schema;
280
+ var marks = (0, _utils2.getMarksWithBreakout)(sourceNode, targetNodeType);
281
+ var codeBlock = schema.nodes.codeBlock.create(targetAttrs, null, marks);
282
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, codeBlock);
283
+ }
275
284
  return applySplitsToTransaction(tr, sourcePos, sourceNode.nodeSize, _contentSplits);
276
285
  }
277
286
 
@@ -319,7 +328,8 @@ var splitContentForCodeBlock = function splitContentForCodeBlock(sourceNode, tar
319
328
  var flushCurrentCodeBlock = function flushCurrentCodeBlock() {
320
329
  if (currentTextContent.length > 0) {
321
330
  var codeText = currentTextContent.join('\n');
322
- var codeBlockNode = targetNodeType.create(targetAttrs, schema.text(codeText));
331
+ var marks = (0, _utils2.getMarksWithBreakout)(sourceNode, targetNodeType);
332
+ var codeBlockNode = targetNodeType.create(targetAttrs, schema.text(codeText), marks);
323
333
  splits.push(codeBlockNode);
324
334
  currentTextContent = [];
325
335
  }
@@ -390,7 +400,8 @@ var splitContentAroundUnsupportedBlocks = function splitContentAroundUnsupported
390
400
  }
391
401
  var flushCurrentContainer = function flushCurrentContainer() {
392
402
  if (currentContainerContent.length > 0) {
393
- var containerNode = targetNodeType.create(targetAttrs, _model.Fragment.fromArray(currentContainerContent));
403
+ var marks = (0, _utils2.getMarksWithBreakout)(sourceNode, targetNodeType);
404
+ var containerNode = targetNodeType.create(targetAttrs, _model.Fragment.fromArray(currentContainerContent), marks);
394
405
  splits.push(containerNode);
395
406
  currentContainerContent = [];
396
407
  }
@@ -4,31 +4,42 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.transformLayoutNode = exports.convertToLayout = void 0;
7
+ exports.transformLayoutNode = exports.createDefaultLayoutSection = exports.convertToLayout = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _styles = require("@atlaskit/editor-common/styles");
10
10
  var _model = require("@atlaskit/editor-prosemirror/model");
11
11
  var _utils = require("./layout/utils");
12
+ var _utils2 = require("./utils");
13
+ var createDefaultLayoutSection = exports.createDefaultLayoutSection = function createDefaultLayoutSection(schema, content, marks) {
14
+ var _schema$nodes = schema.nodes,
15
+ layoutSection = _schema$nodes.layoutSection,
16
+ layoutColumn = _schema$nodes.layoutColumn,
17
+ paragraph = _schema$nodes.paragraph;
18
+ var layoutContent = _model.Fragment.fromArray([layoutColumn.createChecked({
19
+ width: _styles.DEFAULT_TWO_COLUMN_LAYOUT_COLUMN_WIDTH
20
+ }, content), layoutColumn.create({
21
+ width: _styles.DEFAULT_TWO_COLUMN_LAYOUT_COLUMN_WIDTH
22
+ }, paragraph.createAndFill())]);
23
+ return layoutSection.createChecked(undefined, layoutContent, marks);
24
+ };
12
25
  var convertToLayout = exports.convertToLayout = function convertToLayout(context) {
13
26
  var tr = context.tr,
14
27
  sourceNode = context.sourceNode,
15
28
  sourcePos = context.sourcePos;
16
- var _ref = tr.doc.type.schema.nodes || {},
17
- layoutSection = _ref.layoutSection,
18
- layoutColumn = _ref.layoutColumn,
19
- paragraph = _ref.paragraph;
20
29
  var content = sourceNode.mark(sourceNode.marks.filter(function (mark) {
21
30
  return mark.type.name !== 'breakout';
22
31
  }));
23
- var layoutContent = _model.Fragment.fromArray([layoutColumn.createChecked({
24
- width: _styles.DEFAULT_TWO_COLUMN_LAYOUT_COLUMN_WIDTH
25
- }, content), layoutColumn.create({
26
- width: _styles.DEFAULT_TWO_COLUMN_LAYOUT_COLUMN_WIDTH
27
- }, paragraph.createAndFill())]);
28
- var layoutSectionNode = layoutSection.createChecked(undefined, layoutContent);
29
32
 
30
- // Replace the original node with the new layout node
31
- tr.replaceRangeWith(sourcePos, sourcePos + sourceNode.nodeSize, layoutSectionNode);
33
+ // Layout supports breakout mark that can have width attribute
34
+ // When other nodes with breakout (codeBlock and expand) are converted to a layout, the layout should get width of original node
35
+ var marks = (0, _utils2.getMarksWithBreakout)(sourceNode, tr.doc.type.schema.nodes.layoutSection);
36
+ var layoutSectionNode = createDefaultLayoutSection(tr.doc.type.schema, content, marks);
37
+ if ((0, _utils2.isHeadingOrParagraphNode)(sourceNode)) {
38
+ // -1 to fix when sourceNode is the last node in the document, unable to convert to layout
39
+ tr.replaceRangeWith(sourcePos > 0 ? sourcePos - 1 : sourcePos, sourcePos + sourceNode.nodeSize - 1, layoutSectionNode);
40
+ } else {
41
+ tr.replaceRangeWith(sourcePos, sourcePos + sourceNode.nodeSize, layoutSectionNode);
42
+ }
32
43
  return tr;
33
44
  };
34
45
  var transformLayoutNode = exports.transformLayoutNode = function transformLayoutNode(context) {
@@ -38,11 +49,11 @@ var transformLayoutNode = exports.transformLayoutNode = function transformLayout
38
49
  sourcePos = context.sourcePos,
39
50
  targetAttrs = context.targetAttrs;
40
51
  var schema = tr.doc.type.schema || {};
41
- var _ref2 = schema.nodes || {},
42
- layoutSection = _ref2.layoutSection,
43
- layoutColumn = _ref2.layoutColumn,
44
- paragraph = _ref2.paragraph,
45
- heading = _ref2.heading;
52
+ var _ref = schema.nodes || {},
53
+ layoutSection = _ref.layoutSection,
54
+ layoutColumn = _ref.layoutColumn,
55
+ paragraph = _ref.paragraph,
56
+ heading = _ref.heading;
46
57
  var layoutColumnNodes = [];
47
58
  var targetTextNodeType = targetNodeType === heading ? heading : paragraph;
48
59
  sourceNode.children.forEach(function (child) {
@@ -1,9 +1,11 @@
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
- exports.isListNodeType = exports.isListNode = exports.isLayoutNodeType = exports.isLayoutNode = exports.isHeadingOrParagraphNode = exports.isContainerNodeType = exports.isContainerNode = exports.isBlockNodeType = exports.isBlockNodeForExtraction = exports.isBlockNode = exports.getTargetNodeInfo = exports.getContentSupportChecker = exports.filterMarksForTargetNodeType = exports.convertNodeToInlineContent = exports.convertCodeBlockContentToParagraphs = void 0;
7
+ exports.isListNodeType = exports.isListNode = exports.isLayoutNodeType = exports.isLayoutNode = exports.isHeadingOrParagraphNode = exports.isContainerNodeType = exports.isContainerNode = exports.isBlockNodeType = exports.isBlockNodeForExtraction = exports.isBlockNode = exports.getTargetNodeInfo = exports.getMarksWithBreakout = exports.getContentSupportChecker = exports.filterMarksForTargetNodeType = exports.convertNodeToInlineContent = exports.convertCodeBlockContentToParagraphs = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
7
9
  var _model = require("@atlaskit/editor-prosemirror/model");
8
10
  var getTargetNodeInfo = exports.getTargetNodeInfo = function getTargetNodeInfo(targetType, nodes) {
9
11
  switch (targetType) {
@@ -202,4 +204,21 @@ var convertCodeBlockContentToParagraphs = exports.convertCodeBlockContentToParag
202
204
  paragraphNodes.push(paragraphNode);
203
205
  });
204
206
  return paragraphNodes;
207
+ };
208
+ var isBreakoutMarkSupported = function isBreakoutMarkSupported(nodeType) {
209
+ return ['codeBlock', 'expand', 'layoutSection'].includes(nodeType.name);
210
+ };
211
+ var getMarksWithBreakout = exports.getMarksWithBreakout = function getMarksWithBreakout(sourceNode, targetNodeType) {
212
+ var allowedMarks = targetNodeType.allowedMarks(sourceNode.marks);
213
+ var sourceBreakoutMark = sourceNode.marks.find(function (mark) {
214
+ return mark.type.name === 'breakout';
215
+ });
216
+ if (sourceBreakoutMark && isBreakoutMarkSupported(targetNodeType)) {
217
+ // Check if breakout mark is already in allowedMarks to avoid duplicates
218
+ var hasBreakoutMark = allowedMarks.some(function (mark) {
219
+ return mark.type.name === 'breakout';
220
+ });
221
+ return hasBreakoutMark ? allowedMarks : [].concat((0, _toConsumableArray2.default)(allowedMarks), [sourceBreakoutMark]);
222
+ }
223
+ return allowedMarks;
205
224
  };
@@ -9,12 +9,12 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _blockMenu = require("@atlaskit/editor-common/block-menu");
11
11
  var _editorToolbar = require("@atlaskit/editor-toolbar");
12
- var _changes = _interopRequireDefault(require("@atlaskit/icon/core/changes"));
13
- var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
14
12
  var _copyBlock = _interopRequireDefault(require("./copy-block"));
15
13
  var _copyLink = require("./copy-link");
16
14
  var _copySection = require("./copy-section");
17
15
  var _deleteButton = require("./delete-button");
16
+ var _deleteSection = require("./delete-section");
17
+ var _formatMenuNested = require("./format-menu-nested");
18
18
  var _formatMenuSection = require("./format-menu-section");
19
19
  var _moveDown = require("./move-down");
20
20
  var _moveUp = require("./move-up");
@@ -61,16 +61,7 @@ var getFormatMenuComponents = function getFormatMenuComponents(api) {
61
61
  children: null
62
62
  },
63
63
  children = _ref.children;
64
- return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
65
- text: "Format",
66
- elemBefore: /*#__PURE__*/_react.default.createElement(_changes.default, {
67
- label: ""
68
- }),
69
- elemAfter: /*#__PURE__*/_react.default.createElement(_chevronRight.default, {
70
- label: 'example nested menu'
71
- }),
72
- enableMaxHeight: true
73
- }, children);
64
+ return /*#__PURE__*/_react.default.createElement(_formatMenuNested.FormatMenuComponent, null, children);
74
65
  }
75
66
  }, {
76
67
  type: 'block-menu-section',
@@ -155,8 +146,8 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
155
146
  rank: _blockMenu.BLOCK_MENU_SECTION_RANK[_blockMenu.DELETE_MENU_SECTION.key],
156
147
  component: function component(_ref7) {
157
148
  var children = _ref7.children;
158
- return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
159
- hasSeparator: true
149
+ return /*#__PURE__*/_react.default.createElement(_deleteSection.DeleteSection, {
150
+ api: api
160
151
  }, children);
161
152
  }
162
153
  }], (0, _toConsumableArray2.default)(getMoveUpMoveDownMenuComponents(api)), [{
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useBlockMenu = exports.BlockMenuProvider = void 0;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
10
+ var BlockMenuContext = /*#__PURE__*/(0, _react.createContext)({
11
+ onDropdownOpenChanged: function onDropdownOpenChanged() {}
12
+ });
13
+ var useBlockMenu = exports.useBlockMenu = function useBlockMenu() {
14
+ var context = (0, _react.useContext)(BlockMenuContext);
15
+ if (!context) {
16
+ throw new Error('useBlockMenu must be used within BlockMenuProvider');
17
+ }
18
+ return context;
19
+ };
20
+ var BlockMenuProvider = exports.BlockMenuProvider = function BlockMenuProvider(_ref) {
21
+ var children = _ref.children,
22
+ api = _ref.api;
23
+ var onDropdownOpenChanged = (0, _react.useCallback)(function (isOpen) {
24
+ if (!isOpen) {
25
+ // On Dropdown closed, return focus to editor
26
+ setTimeout(function () {
27
+ return requestAnimationFrame(function () {
28
+ api === null || api === void 0 || api.core.actions.focus({
29
+ scrollIntoView: false
30
+ });
31
+ });
32
+ }, 1);
33
+ }
34
+ }, [api]);
35
+ return /*#__PURE__*/_react.default.createElement(BlockMenuContext.Provider, {
36
+ value: {
37
+ onDropdownOpenChanged: onDropdownOpenChanged
38
+ }
39
+ }, children);
40
+ };
@@ -1,4 +1,4 @@
1
- /* block-menu.tsx generated by @compiled/babel-plugin v0.36.1 */
1
+ /* block-menu.tsx generated by @compiled/babel-plugin v0.38.1 */
2
2
  "use strict";
3
3
 
4
4
  var _typeof = require("@babel/runtime/helpers/typeof");
@@ -18,6 +18,8 @@ var _uiReact = require("@atlaskit/editor-common/ui-react");
18
18
  var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
19
19
  var _editorToolbar = require("@atlaskit/editor-toolbar");
20
20
  var _compiled = require("@atlaskit/primitives/compiled");
21
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
22
+ var _blockMenuProvider = require("./block-menu-provider");
21
23
  var _blockMenuRenderer = require("./block-menu-renderer");
22
24
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
23
25
  var styles = {
@@ -73,15 +75,22 @@ var BlockMenu = function BlockMenu(_ref2) {
73
75
  isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
74
76
  isMenuOpen = _useSharedPluginState.isMenuOpen,
75
77
  currentUserIntent = _useSharedPluginState.currentUserIntent;
78
+ var _useBlockMenu = (0, _blockMenuProvider.useBlockMenu)(),
79
+ onDropdownOpenChanged = _useBlockMenu.onDropdownOpenChanged;
76
80
  var hasFocus = (_editorView$hasFocus = editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) !== null && _editorView$hasFocus !== void 0 ? _editorView$hasFocus : false;
77
81
  var hasSelection = !!editorView && !editorView.state.selection.empty;
82
+ var emptyLineEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true);
83
+
84
+ // hasSelection true, always show block menu
85
+ // hasSelection false, only show block menu when empty line experiment is enabled
86
+ var shouldShowBlockMenuForEmptyLine = hasSelection || emptyLineEnabled && !hasSelection;
78
87
  (0, _react.useEffect)(function () {
79
88
  var _api$userIntent;
80
- if (!isMenuOpen || !menuTriggerBy || !isSelectedViaDragHandle || !hasFocus || !hasSelection || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
89
+ if (!isMenuOpen || !menuTriggerBy || !isSelectedViaDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
81
90
  return;
82
91
  }
83
92
  api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
84
- }, [api, isMenuOpen, menuTriggerBy, isSelectedViaDragHandle, hasFocus, hasSelection, currentUserIntent]);
93
+ }, [api, isMenuOpen, menuTriggerBy, isSelectedViaDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent]);
85
94
  if (!isMenuOpen) {
86
95
  return null;
87
96
  }
@@ -94,13 +103,14 @@ var BlockMenu = function BlockMenu(_ref2) {
94
103
  })({
95
104
  tr: tr
96
105
  });
106
+ onDropdownOpenChanged(false);
97
107
  api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent(currentUserIntent === 'blockMenuOpen' ? 'default' : currentUserIntent || 'default')({
98
108
  tr: tr
99
109
  });
100
110
  return tr;
101
111
  });
102
112
  };
103
- if (!menuTriggerBy || !isSelectedViaDragHandle || !hasFocus || !hasSelection || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
113
+ if (!menuTriggerBy || !isSelectedViaDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
104
114
  closeMenu();
105
115
  return null;
106
116
  }
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
8
9
  var _react = _interopRequireDefault(require("react"));
9
10
  var _reactIntlNext = require("react-intl-next");
10
11
  var _blockMenu = require("@atlaskit/editor-common/block-menu");
@@ -15,6 +16,8 @@ var _state = require("@atlaskit/editor-prosemirror/state");
15
16
  var _utils = require("@atlaskit/editor-tables/utils");
16
17
  var _editorToolbar = require("@atlaskit/editor-toolbar");
17
18
  var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
19
+ 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; }
20
+ 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; }
18
21
  var toDOMFromFragment = function toDOMFromFragment(fragment, schema) {
19
22
  return _model.DOMSerializer.fromSchema(schema).serializeFragment(fragment);
20
23
  };
@@ -80,10 +83,15 @@ var CopyBlockMenuItem = function CopyBlockMenuItem(_ref) {
80
83
  // When nodeType.inlineContent is true, it will be treated as an inline node in the copyDomNode function,
81
84
  // but we want to treat it as a block node when copying, hence setting it to false here
82
85
  if (selection.node.type.name === 'codeBlock') {
83
- _nodeType.inlineContent = false;
86
+ var codeBlockNodeType = _objectSpread(_objectSpread({}, _nodeType), {}, {
87
+ inlineContent: false
88
+ });
89
+ var _domNode2 = (0, _copyButton.toDOM)(selection.node, schema);
90
+ (0, _copyButton.copyDomNode)(_domNode2, codeBlockNodeType, selection);
91
+ } else {
92
+ var _domNode3 = (0, _copyButton.toDOM)(selection.node, schema);
93
+ (0, _copyButton.copyDomNode)(_domNode3, _nodeType, selection);
84
94
  }
85
- var _domNode2 = (0, _copyButton.toDOM)(selection.node, schema);
86
- (0, _copyButton.copyDomNode)(_domNode2, _nodeType, selection);
87
95
  }
88
96
 
89
97
  // close the block menu after copying
@@ -7,14 +7,21 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.CopySection = void 0;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
  var _editorToolbar = require("@atlaskit/editor-toolbar");
10
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
10
11
  var _checkIsFormatMenuHidden = require("./utils/checkIsFormatMenuHidden");
11
12
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
12
13
  var CopySection = exports.CopySection = function CopySection(_ref) {
14
+ var _api$selection;
13
15
  var api = _ref.api,
14
16
  children = _ref.children;
15
17
  var isFormatMenuHidden = (0, _react.useCallback)(function () {
16
18
  return (0, _checkIsFormatMenuHidden.checkIsFormatMenuHidden)(api);
17
19
  }, [api]);
20
+ var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
21
+ var isEmptyLineSelected = !!(selection !== null && selection !== void 0 && selection.empty) && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true);
22
+ if (isEmptyLineSelected) {
23
+ return null;
24
+ }
18
25
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
19
26
  hasSeparator: !isFormatMenuHidden()
20
27
  }, children);
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.DeleteSection = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _editorToolbar = require("@atlaskit/editor-toolbar");
10
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
11
+ var DeleteSection = exports.DeleteSection = function DeleteSection(_ref) {
12
+ var _api$selection;
13
+ var api = _ref.api,
14
+ children = _ref.children;
15
+ var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
16
+ var isEmptyLineSelected = !!(selection !== null && selection !== void 0 && selection.empty) && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true);
17
+ if (isEmptyLineSelected) {
18
+ return null;
19
+ }
20
+ return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, {
21
+ hasSeparator: true
22
+ }, children);
23
+ };
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.FormatMenuComponent = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _reactIntlNext = require("react-intl-next");
10
+ var _blockMenu = require("@atlaskit/editor-common/block-menu");
11
+ var _editorToolbar = require("@atlaskit/editor-toolbar");
12
+ var _changes = _interopRequireDefault(require("@atlaskit/icon/core/changes"));
13
+ var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
14
+ var FormatMenuComponent = exports.FormatMenuComponent = function FormatMenuComponent(_ref) {
15
+ var children = _ref.children;
16
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
17
+ formatMessage = _useIntl.formatMessage;
18
+ return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
19
+ text: formatMessage(_blockMenu.messages.turnInto),
20
+ elemBefore: /*#__PURE__*/_react.default.createElement(_changes.default, {
21
+ label: ""
22
+ }),
23
+ elemAfter: /*#__PURE__*/_react.default.createElement(_chevronRight.default, {
24
+ label: ""
25
+ }),
26
+ enableMaxHeight: true
27
+ }, children);
28
+ };
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.checkIsFormatMenuHidden = void 0;
7
7
  var _utils = require("@atlaskit/editor-prosemirror/utils");
8
8
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
9
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
9
10
  var _isNestedNode = require("./isNestedNode");
10
11
  var getIsFormatMenuHidden = function getIsFormatMenuHidden(selection, schema, menuTriggerBy) {
11
12
  var nodes = schema.nodes;
@@ -32,6 +33,39 @@ var getIsFormatMenuHidden = function getIsFormatMenuHidden(selection, schema, me
32
33
  var isNested = (0, _isNestedNode.isNestedNode)(selection, menuTriggerBy);
33
34
  return !content || isNested;
34
35
  };
36
+ var getIsFormatMenuHiddenEmptyLine = function getIsFormatMenuHiddenEmptyLine(selection, schema, menuTriggerBy) {
37
+ var nodes = schema.nodes;
38
+ if (!nodes) {
39
+ return false;
40
+ }
41
+ var isNested = (0, _isNestedNode.isNestedNode)(selection, menuTriggerBy);
42
+ if (selection.empty || selection.content().size === 0) {
43
+ // if empty selection, show format menu
44
+ return false;
45
+ } else if (isNested) {
46
+ // if nested, always hide format menu
47
+ return true;
48
+ } else {
49
+ var content;
50
+ var allowedNodes = [nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList];
51
+ if ((0, _expValEquals.expValEquals)('platform_editor_block_menu_layout_format', 'isEnabled', true)) {
52
+ allowedNodes.push(nodes.layoutSection);
53
+ }
54
+ if ((0, _expValEquals.expValEquals)('platform_editor_block_menu_expand_format', 'isEnabled', true)) {
55
+ allowedNodes.push(nodes.expand);
56
+ }
57
+ var selectedNode = (0, _utils.findSelectedNodeOfType)(allowedNodes)(selection);
58
+ if (selectedNode) {
59
+ content = selectedNode.node;
60
+ } else {
61
+ var listTypeOrBlockQuoteNode = (0, _utils.findParentNodeOfType)([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.listItem, nodes.taskItem])(selection);
62
+ if (listTypeOrBlockQuoteNode) {
63
+ content = listTypeOrBlockQuoteNode.node;
64
+ }
65
+ }
66
+ return !content;
67
+ }
68
+ };
35
69
  var checkIsFormatMenuHidden = exports.checkIsFormatMenuHidden = function checkIsFormatMenuHidden(api) {
36
70
  var _api$selection, _api$core$sharedState, _api$blockControls;
37
71
  var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
@@ -40,5 +74,5 @@ var checkIsFormatMenuHidden = exports.checkIsFormatMenuHidden = function checkIs
40
74
  if (!selection || !schema || !menuTriggerBy) {
41
75
  return false;
42
76
  }
43
- return getIsFormatMenuHidden(selection, schema, menuTriggerBy);
77
+ return (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true) ? getIsFormatMenuHiddenEmptyLine(selection, schema, menuTriggerBy) : getIsFormatMenuHidden(selection, schema, menuTriggerBy);
44
78
  };
@@ -4,6 +4,7 @@ import { formatNode } from './editor-commands/formatNode';
4
4
  import { createPlugin } from './pm-plugins/main';
5
5
  import BlockMenu from './ui/block-menu';
6
6
  import { getBlockMenuComponents } from './ui/block-menu-components';
7
+ import { BlockMenuProvider } from './ui/block-menu-provider';
7
8
  export const blockMenuPlugin = ({
8
9
  api,
9
10
  config
@@ -54,13 +55,15 @@ export const blockMenuPlugin = ({
54
55
  popupsBoundariesElement,
55
56
  popupsScrollableElement
56
57
  }) {
57
- return /*#__PURE__*/React.createElement(BlockMenu, {
58
+ return /*#__PURE__*/React.createElement(BlockMenuProvider, {
59
+ api: api
60
+ }, /*#__PURE__*/React.createElement(BlockMenu, {
58
61
  editorView: editorView,
59
62
  api: api,
60
63
  mountTo: popupsMountPoint,
61
64
  boundariesElement: popupsBoundariesElement,
62
65
  scrollableElement: popupsScrollableElement
63
- });
66
+ }));
64
67
  }
65
68
  };
66
69
  };