@atlaskit/editor-plugin-block-menu 5.2.14 → 5.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/editor-commands/transform-node-utils/nodeChecks.js +33 -0
  3. package/dist/cjs/editor-commands/transform-node-utils/steps/flattenListStep.js +7 -12
  4. package/dist/cjs/editor-commands/transform-node-utils/steps/listToDecisionListStep.js +3 -3
  5. package/dist/cjs/editor-commands/transform-node-utils/steps/listToListStep.js +11 -11
  6. package/dist/cjs/editor-commands/transform-node-utils/steps/wrapTextToCodeblock.js +21 -0
  7. package/dist/cjs/editor-commands/transform-node-utils/transform.js +5 -11
  8. package/dist/cjs/editor-commands/transform-node-utils/utils.js +20 -7
  9. package/dist/cjs/editor-commands/transform-node-utils/wrapIntoListStep.js +29 -7
  10. package/dist/cjs/ui/block-menu-components.js +1 -3
  11. package/dist/cjs/ui/copy-link.js +2 -2
  12. package/dist/cjs/ui/delete-section.js +1 -8
  13. package/dist/es2019/editor-commands/transform-node-utils/nodeChecks.js +23 -0
  14. package/dist/es2019/editor-commands/transform-node-utils/steps/flattenListStep.js +7 -6
  15. package/dist/es2019/editor-commands/transform-node-utils/steps/listToDecisionListStep.js +3 -4
  16. package/dist/es2019/editor-commands/transform-node-utils/steps/listToListStep.js +11 -12
  17. package/dist/es2019/editor-commands/transform-node-utils/steps/wrapTextToCodeblock.js +18 -0
  18. package/dist/es2019/editor-commands/transform-node-utils/transform.js +5 -11
  19. package/dist/es2019/editor-commands/transform-node-utils/utils.js +19 -4
  20. package/dist/es2019/editor-commands/transform-node-utils/wrapIntoListStep.js +29 -7
  21. package/dist/es2019/ui/block-menu-components.js +1 -3
  22. package/dist/es2019/ui/copy-link.js +2 -2
  23. package/dist/es2019/ui/delete-section.js +0 -7
  24. package/dist/esm/editor-commands/transform-node-utils/nodeChecks.js +27 -0
  25. package/dist/esm/editor-commands/transform-node-utils/steps/flattenListStep.js +7 -12
  26. package/dist/esm/editor-commands/transform-node-utils/steps/listToDecisionListStep.js +3 -4
  27. package/dist/esm/editor-commands/transform-node-utils/steps/listToListStep.js +11 -12
  28. package/dist/esm/editor-commands/transform-node-utils/steps/wrapTextToCodeblock.js +16 -0
  29. package/dist/esm/editor-commands/transform-node-utils/transform.js +5 -11
  30. package/dist/esm/editor-commands/transform-node-utils/utils.js +19 -6
  31. package/dist/esm/editor-commands/transform-node-utils/wrapIntoListStep.js +29 -7
  32. package/dist/esm/ui/block-menu-components.js +1 -3
  33. package/dist/esm/ui/copy-link.js +2 -2
  34. package/dist/esm/ui/delete-section.js +1 -8
  35. package/dist/types/editor-commands/transform-node-utils/nodeChecks.d.ts +17 -0
  36. package/dist/types/editor-commands/transform-node-utils/steps/wrapTextToCodeblock.d.ts +9 -0
  37. package/dist/types/editor-commands/transform-node-utils/utils.d.ts +8 -1
  38. package/dist/types/editor-commands/transform-node-utils/wrapIntoListStep.d.ts +7 -1
  39. package/dist/types/ui/delete-section.d.ts +1 -4
  40. package/dist/types-ts4.5/editor-commands/transform-node-utils/nodeChecks.d.ts +17 -0
  41. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/wrapTextToCodeblock.d.ts +9 -0
  42. package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +8 -1
  43. package/dist/types-ts4.5/editor-commands/transform-node-utils/wrapIntoListStep.d.ts +7 -1
  44. package/dist/types-ts4.5/ui/delete-section.d.ts +1 -4
  45. package/package.json +8 -8
@@ -8,6 +8,7 @@ import { unwrapLayoutStep } from './steps/unwrapLayoutStep';
8
8
  import { unwrapListStep } from './steps/unwrapListStep';
9
9
  import { wrapBlockquoteToDecisionListStep } from './steps/wrapBlockquoteToDecisionListStep';
10
10
  import { wrapMixedContentStep } from './steps/wrapMixedContentStep';
11
+ import { wrapTextToCodeblockStep } from './steps/wrapTextToCodeblock';
11
12
  import { stubStep } from './stubStep';
12
13
  import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
13
14
  import { unwrapExpandStep } from './unwrapExpandStep';
@@ -16,14 +17,6 @@ import { wrapIntoLayoutStep } from './wrapIntoLayoutStep';
16
17
  import { wrapIntoListStep } from './wrapIntoListStep';
17
18
  import { wrapStep } from './wrapStep';
18
19
 
19
- // Exampled step for overrides:
20
- // - open Block menu on a paragraph, click 'Panel' in the Turn into'
21
- // - expected to put paragraph into a panel
22
- const wrapIntoPanelStep = (nodes, context) => {
23
- const newNode = context.schema.nodes.panel.createAndFill({}, nodes);
24
- return newNode ? [newNode] : [];
25
- };
26
-
27
20
  // Transform steps for combinations of node categories (block/container/list/text)
28
21
  const TRANSFORM_STEPS = {
29
22
  atomic: {
@@ -46,8 +39,8 @@ const TRANSFORM_STEPS = {
46
39
  },
47
40
  text: {
48
41
  atomic: undefined,
49
- container: [stubStep],
50
- list: [stubStep],
42
+ container: [wrapStep],
43
+ list: [wrapIntoListStep],
51
44
  text: [stubStep]
52
45
  }
53
46
  };
@@ -56,7 +49,8 @@ const TRANSFORM_STEPS = {
56
49
  // using generic rules/steps from TRANSFORM_STEPS.
57
50
  const TRANSFORM_STEPS_OVERRIDE = {
58
51
  paragraph: {
59
- panel: [wrapIntoPanelStep]
52
+ codeBlock: [wrapTextToCodeblockStep],
53
+ layoutSection: [wrapIntoLayoutStep]
60
54
  },
61
55
  panel: {
62
56
  layoutSection: [unwrapStep, wrapIntoLayoutStep],
@@ -50,10 +50,6 @@ export const getTargetNodeTypeNameInContext = (nodeTypeName, isNested) => {
50
50
  }
51
51
  return nodeTypeName;
52
52
  };
53
- export const isListType = (node, schema) => {
54
- const lists = [schema.nodes.taskList, schema.nodes.bulletList, schema.nodes.orderedList];
55
- return lists.some(list => list === node.type);
56
- };
57
53
 
58
54
  /**
59
55
  * Converts a nestedExpand to a regular expand node.
@@ -100,4 +96,23 @@ export const getBlockNodesInRange = range => {
100
96
  }
101
97
  }
102
98
  return blockNodes;
99
+ };
100
+
101
+ /**
102
+ * Iterates over a nodes children and extracting text content, removing all other inline content and converting
103
+ * hardbreaks to newlines.
104
+ *
105
+ * @param node - The node to create text content from (should be paragraph)
106
+ * @returns The text content string.
107
+ */
108
+ export const createTextContent = node => {
109
+ const textContent = node.children.map(child => {
110
+ if (child.isText) {
111
+ return child.text;
112
+ } else if (child.type.name === 'hardBreak') {
113
+ return '\n';
114
+ }
115
+ return '';
116
+ });
117
+ return textContent.join('');
103
118
  };
@@ -1,13 +1,35 @@
1
- /** wrap nodes into bullet list or numbered list, does not work for task list */
1
+ import { isListWithTextContentOnly } from './nodeChecks';
2
+ const wrapIntoTaskOrDecisionList = (nodes, targetNodeTypeName, schema) => {
3
+ const itemNodeType = targetNodeTypeName === 'taskList' ? schema.nodes.taskItem : schema.nodes.decisionItem;
4
+ const inlineContent = nodes.flatMap(node => {
5
+ if (node.isTextblock) {
6
+ return node.children;
7
+ } else if (node.isText) {
8
+ return [node];
9
+ }
10
+ return [];
11
+ });
12
+ const itemNode = itemNodeType.create({}, inlineContent);
13
+ const outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, itemNode);
14
+ return outputNode ? [outputNode] : nodes;
15
+ };
16
+ const wrapIntoBulletOrOrderedList = (nodes, targetNodeTypeName, schema) => {
17
+ const listItemNode = schema.nodes.listItem.createAndFill({}, nodes);
18
+ const outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, listItemNode);
19
+ return outputNode ? [outputNode] : nodes;
20
+ };
21
+
22
+ /**
23
+ * Wraps nodes into bullet list, numbered list, task list, or decision list.
24
+ *
25
+ * @param nodes - The nodes to wrap.
26
+ * @param context - The transformation context containing schema and target node type.
27
+ * @returns The wrapped nodes.
28
+ */
2
29
  export const wrapIntoListStep = (nodes, context) => {
3
30
  const {
4
31
  schema,
5
32
  targetNodeTypeName
6
33
  } = context;
7
- const listItemNode = schema.nodes.listItem.createAndFill({}, nodes);
8
- const outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, listItemNode);
9
- if (outputNode) {
10
- return [outputNode];
11
- }
12
- return nodes;
34
+ return isListWithTextContentOnly(targetNodeTypeName, schema) ? wrapIntoTaskOrDecisionList(nodes, targetNodeTypeName, schema) : wrapIntoBulletOrOrderedList(nodes, targetNodeTypeName, schema);
13
35
  };
@@ -188,9 +188,7 @@ export const getBlockMenuComponents = ({
188
188
  component: ({
189
189
  children
190
190
  }) => {
191
- return /*#__PURE__*/React.createElement(DeleteSection, {
192
- api: api
193
- }, children);
191
+ return /*#__PURE__*/React.createElement(DeleteSection, null, children);
194
192
  }
195
193
  }, {
196
194
  type: 'block-menu-item',
@@ -84,8 +84,8 @@ const CopyLinkDropdownItemContent = ({
84
84
  });
85
85
  }, [api, blockLinkHashPrefix, getLinkPath, onDropdownOpenChanged, selection]);
86
86
 
87
- // Hide copy link when `platform_editor_adf_with_localid` feature flag is off or when the node is nested or on empty line
88
- if (!fg('platform_editor_adf_with_localid') || !!menuTriggerBy && isNestedNode(selection, menuTriggerBy) || selection !== null && selection !== void 0 && selection.empty) {
87
+ // Hide copy link when `platform_editor_adf_with_localid` feature flag is off or when the node is nested
88
+ if (!fg('platform_editor_adf_with_localid') || !!menuTriggerBy && isNestedNode(selection, menuTriggerBy)) {
89
89
  return null;
90
90
  }
91
91
  return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
@@ -1,15 +1,8 @@
1
1
  import React from 'react';
2
2
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
3
3
  export const DeleteSection = ({
4
- api,
5
4
  children
6
5
  }) => {
7
- var _api$selection, _api$selection$shared, _api$selection$shared2;
8
- const selection = api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : (_api$selection$shared = _api$selection.sharedState) === null || _api$selection$shared === void 0 ? void 0 : (_api$selection$shared2 = _api$selection$shared.currentState()) === null || _api$selection$shared2 === void 0 ? void 0 : _api$selection$shared2.selection;
9
- const isEmptyLineSelected = !!(selection !== null && selection !== void 0 && selection.empty);
10
- if (isEmptyLineSelected) {
11
- return null;
12
- }
13
6
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
14
7
  hasSeparator: true
15
8
  }, children);
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Checks if a node is a list type that supports indentation (bulletList, orderedList, taskList).
3
+ *
4
+ * @param node - The node to check.
5
+ * @param schema - ProseMirror schema for check
6
+ * @returns True if the node is a list type, false otherwise.
7
+ */
8
+ export var isListWithIndentation = function isListWithIndentation(nodeTypeName, schema) {
9
+ var lists = [schema.nodes.taskList, schema.nodes.bulletList, schema.nodes.orderedList];
10
+ return lists.some(function (list) {
11
+ return list.name === nodeTypeName;
12
+ });
13
+ };
14
+
15
+ /**
16
+ * Checks if a node is a list where its list items only support text content (taskList or decisionList).
17
+ *
18
+ * @param nodeTypeName - The node type name to check.
19
+ * @param schema - ProseMirror schema for check
20
+ * @returns True if the node is a list text type, false otherwise.
21
+ */
22
+ export var isListWithTextContentOnly = function isListWithTextContentOnly(nodeTypeName, schema) {
23
+ var lists = [schema.nodes.taskList, schema.nodes.decisionList];
24
+ return lists.some(function (list) {
25
+ return list.name === nodeTypeName;
26
+ });
27
+ };
@@ -1,7 +1,9 @@
1
1
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
- var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes, schema) {
2
+ import { isListWithIndentation } from '../nodeChecks';
3
+ var extractNestedLists = function extractNestedLists(node, schema) {
3
4
  var items = [];
4
5
  var paragraph = schema.nodes.paragraph;
6
+ var itemTypes = [schema.nodes.listItem, schema.nodes.taskItem];
5
7
  var _extract = function extract(currentNode) {
6
8
  currentNode.forEach(function (child) {
7
9
  if (itemTypes.some(function (type) {
@@ -10,9 +12,7 @@ var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes,
10
12
  var contentWithoutNestedLists = [];
11
13
  var nestedLists = [];
12
14
  child.forEach(function (grandChild) {
13
- if (listTypes.some(function (type) {
14
- return grandChild.type === type;
15
- })) {
15
+ if (isListWithIndentation(grandChild.type.name, schema)) {
16
16
  nestedLists.push(grandChild);
17
17
  } else if (grandChild.isText) {
18
18
  contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
@@ -24,9 +24,7 @@ var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes,
24
24
  nestedLists.forEach(function (nestedList) {
25
25
  _extract(nestedList);
26
26
  });
27
- } else if (listTypes.some(function (type) {
28
- return child.type === type;
29
- })) {
27
+ } else if (isListWithIndentation(child.type.name, schema)) {
30
28
  _extract(child);
31
29
  }
32
30
  });
@@ -65,12 +63,9 @@ var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes,
65
63
  * TODO: Lists with mixed types (e.g. bulletList with a taskItem) doesn't full flatten
66
64
  */
67
65
  export var flattenListStep = function flattenListStep(nodes, context) {
68
- var listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
69
66
  return nodes.map(function (node) {
70
- if (listTypes.some(function (type) {
71
- return node.type === type;
72
- })) {
73
- return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem], context.schema)));
67
+ if (isListWithIndentation(node.type.name, context.schema)) {
68
+ return node.copy(Fragment.from(extractNestedLists(node, context.schema)));
74
69
  }
75
70
  return node;
76
71
  });
@@ -1,6 +1,5 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
- import { isListType } from '../utils';
3
-
2
+ import { isListWithIndentation } from '../nodeChecks';
4
3
  /**
5
4
  * Transforms a bulletList, orderedList, or taskList into a decisionList.
6
5
  *
@@ -29,7 +28,7 @@ export var listToDecisionListStep = function listToDecisionListStep(nodes, conte
29
28
  var paragraphType = schema.nodes.paragraph;
30
29
  var unsupportedContent = [];
31
30
  var transformedNodes = nodes.map(function (node) {
32
- if (!isListType(node, schema)) {
31
+ if (!isListWithIndentation(node.type.name, schema)) {
33
32
  return node;
34
33
  }
35
34
  var decisionItems = [];
@@ -41,7 +40,7 @@ export var listToDecisionListStep = function listToDecisionListStep(nodes, conte
41
40
  itemContent.push.apply(itemContent, _toConsumableArray(child.children));
42
41
  } else if (child.isText) {
43
42
  itemContent.push(child);
44
- } else if (!isListType(child, schema)) {
43
+ } else if (!isListWithIndentation(child.type.name, schema)) {
45
44
  unsupportedContent.push(child);
46
45
  }
47
46
  });
@@ -1,7 +1,6 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
- import { isListType } from '../utils';
4
-
3
+ import { isListWithIndentation } from '../nodeChecks';
5
4
  /**
6
5
  * Recursively converts nested lists to the target list type.
7
6
  * This function handles the conversion of both the list container and its items,
@@ -15,13 +14,13 @@ var _transformList = function transformList(node, targetListType, targetItemType
15
14
  var schema = node.type.schema;
16
15
  var taskListType = schema.nodes.taskList;
17
16
  var isSourceTaskList = node.type === taskListType;
18
- var isTargetTaskList = targetListType === 'taskList';
17
+ var isTargetTaskList = targetListType === taskListType.name;
19
18
  var convertFromTaskListStructure = function convertFromTaskListStructure(node, targetListType, targetItemType) {
20
19
  var schema = node.type.schema;
21
20
  var targetListNodeType = schema.nodes[targetListType];
22
21
  var transformedContent = [];
23
22
  node.forEach(function (child) {
24
- if (isListType(child, schema)) {
23
+ if (isListWithIndentation(child.type.name, schema)) {
25
24
  // This is a nested list - it should become a child of the previous item
26
25
  if (transformedContent.length > 0) {
27
26
  var previousItem = transformedContent[transformedContent.length - 1];
@@ -33,7 +32,7 @@ var _transformList = function transformList(node, targetListType, targetItemType
33
32
  }
34
33
  // If there's no previous item, skip this nested list (orphaned)
35
34
  } else {
36
- var transformedItem = transformListItem(child, targetItemType, targetListType);
35
+ var transformedItem = transformListItem(child, targetListType, targetItemType);
37
36
  if (transformedItem) {
38
37
  transformedContent.push(transformedItem);
39
38
  }
@@ -46,19 +45,19 @@ var _transformList = function transformList(node, targetListType, targetItemType
46
45
  var targetListNodeType = schema.nodes[targetListType];
47
46
  var transformedContent = [];
48
47
  node.forEach(function (itemNode) {
49
- var transformedItem = transformListItem(itemNode, targetItemType, targetListType, true);
48
+ var transformedItem = transformListItem(itemNode, targetListType, targetItemType, true);
50
49
  if (transformedItem) {
51
50
  transformedContent.push(transformedItem);
52
51
  }
53
52
  itemNode.forEach(function (child) {
54
- if (isListType(child, schema)) {
53
+ if (isListWithIndentation(child.type.name, schema)) {
55
54
  transformedContent.push(_transformList(child, targetListType, targetItemType, unsupportedContent));
56
55
  }
57
56
  });
58
57
  });
59
58
  return targetListNodeType.create(node.attrs, transformedContent);
60
59
  };
61
- var transformListItem = function transformListItem(itemNode, targetItemType, targetListType) {
60
+ var transformListItem = function transformListItem(itemNode, targetListType, targetItemType) {
62
61
  var excludeNestedLists = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
63
62
  var schema = itemNode.type.schema;
64
63
  var targetItemNodeType = schema.nodes[targetItemType];
@@ -73,7 +72,7 @@ var _transformList = function transformList(node, targetListType, targetItemType
73
72
  } else if (child.isText) {
74
73
  inlineContent.push(child);
75
74
  // Nested lists will be extracted and placed as siblings in the taskList
76
- } else if (!isListType(child, schema)) {
75
+ } else if (!isListWithIndentation(child.type.name, schema)) {
77
76
  unsupportedContent.push(child);
78
77
  }
79
78
  });
@@ -84,7 +83,7 @@ var _transformList = function transformList(node, targetListType, targetItemType
84
83
  transformedContent.push(paragraphType.create(null, itemNode.content));
85
84
  } else {
86
85
  itemNode.forEach(function (child) {
87
- if (isListType(child, schema)) {
86
+ if (isListWithIndentation(child.type.name, schema)) {
88
87
  if (excludeNestedLists) {
89
88
  // Skip nested lists - they will be handled separately as siblings
90
89
  return;
@@ -104,7 +103,7 @@ var _transformList = function transformList(node, targetListType, targetItemType
104
103
  var targetListNodeType = schema.nodes[targetListType];
105
104
  var transformedContent = [];
106
105
  node.forEach(function (childNode) {
107
- var transformedItem = isListType(childNode, schema) ? _transformList(childNode, targetListType, targetItemType, unsupportedContent) : transformListItem(childNode, targetItemType, targetListType);
106
+ var transformedItem = isListWithIndentation(childNode.type.name, schema) ? _transformList(childNode, targetListType, targetItemType, unsupportedContent) : transformListItem(childNode, targetListType, targetItemType);
108
107
  if (transformedItem) {
109
108
  transformedContent.push(transformedItem);
110
109
  }
@@ -187,7 +186,7 @@ export var listToListStep = function listToListStep(nodes, context) {
187
186
  targetNodeTypeName = context.targetNodeTypeName;
188
187
  var unsupportedContent = [];
189
188
  var transformedNodes = nodes.map(function (node) {
190
- if (isListType(node, schema)) {
189
+ if (isListWithIndentation(node.type.name, schema)) {
191
190
  var targetItemType = targetNodeTypeName === 'taskList' ? 'taskItem' : 'listItem';
192
191
  return _transformList(node, targetNodeTypeName, targetItemType, unsupportedContent);
193
192
  }
@@ -0,0 +1,16 @@
1
+ import { createTextContent } from '../utils';
2
+
3
+ /**
4
+ * Transforms a paragraph (or heading) into a codeBlock by extracting its text content.
5
+ * This step handles the conversion of inline content (including marks) to plain text,
6
+ * which is required because codeBlocks can only contain plain text nodes.
7
+ *
8
+ * Example: paragraph with bold/italic/status → codeBlock with plain text
9
+ */
10
+ export var wrapTextToCodeblockStep = function wrapTextToCodeblockStep(nodes, context) {
11
+ var schema = context.schema;
12
+ return nodes.map(function (node) {
13
+ var codeBlockNode = schema.nodes.codeBlock.createAndFill({}, schema.text(createTextContent(node)));
14
+ return codeBlockNode !== null && codeBlockNode !== void 0 ? codeBlockNode : node;
15
+ });
16
+ };
@@ -8,6 +8,7 @@ import { unwrapLayoutStep } from './steps/unwrapLayoutStep';
8
8
  import { unwrapListStep } from './steps/unwrapListStep';
9
9
  import { wrapBlockquoteToDecisionListStep } from './steps/wrapBlockquoteToDecisionListStep';
10
10
  import { wrapMixedContentStep } from './steps/wrapMixedContentStep';
11
+ import { wrapTextToCodeblockStep } from './steps/wrapTextToCodeblock';
11
12
  import { stubStep } from './stubStep';
12
13
  import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
13
14
  import { unwrapExpandStep } from './unwrapExpandStep';
@@ -16,14 +17,6 @@ import { wrapIntoLayoutStep } from './wrapIntoLayoutStep';
16
17
  import { wrapIntoListStep } from './wrapIntoListStep';
17
18
  import { wrapStep } from './wrapStep';
18
19
 
19
- // Exampled step for overrides:
20
- // - open Block menu on a paragraph, click 'Panel' in the Turn into'
21
- // - expected to put paragraph into a panel
22
- var wrapIntoPanelStep = function wrapIntoPanelStep(nodes, context) {
23
- var newNode = context.schema.nodes.panel.createAndFill({}, nodes);
24
- return newNode ? [newNode] : [];
25
- };
26
-
27
20
  // Transform steps for combinations of node categories (block/container/list/text)
28
21
  var TRANSFORM_STEPS = {
29
22
  atomic: {
@@ -46,8 +39,8 @@ var TRANSFORM_STEPS = {
46
39
  },
47
40
  text: {
48
41
  atomic: undefined,
49
- container: [stubStep],
50
- list: [stubStep],
42
+ container: [wrapStep],
43
+ list: [wrapIntoListStep],
51
44
  text: [stubStep]
52
45
  }
53
46
  };
@@ -56,7 +49,8 @@ var TRANSFORM_STEPS = {
56
49
  // using generic rules/steps from TRANSFORM_STEPS.
57
50
  var TRANSFORM_STEPS_OVERRIDE = {
58
51
  paragraph: {
59
- panel: [wrapIntoPanelStep]
52
+ codeBlock: [wrapTextToCodeblockStep],
53
+ layoutSection: [wrapIntoLayoutStep]
60
54
  },
61
55
  panel: {
62
56
  layoutSection: [unwrapStep, wrapIntoLayoutStep],
@@ -49,12 +49,6 @@ export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInCont
49
49
  }
50
50
  return nodeTypeName;
51
51
  };
52
- export var isListType = function isListType(node, schema) {
53
- var lists = [schema.nodes.taskList, schema.nodes.bulletList, schema.nodes.orderedList];
54
- return lists.some(function (list) {
55
- return list === node.type;
56
- });
57
- };
58
52
 
59
53
  /**
60
54
  * Converts a nestedExpand to a regular expand node.
@@ -101,4 +95,23 @@ export var getBlockNodesInRange = function getBlockNodesInRange(range) {
101
95
  }
102
96
  }
103
97
  return blockNodes;
98
+ };
99
+
100
+ /**
101
+ * Iterates over a nodes children and extracting text content, removing all other inline content and converting
102
+ * hardbreaks to newlines.
103
+ *
104
+ * @param node - The node to create text content from (should be paragraph)
105
+ * @returns The text content string.
106
+ */
107
+ export var createTextContent = function createTextContent(node) {
108
+ var textContent = node.children.map(function (child) {
109
+ if (child.isText) {
110
+ return child.text;
111
+ } else if (child.type.name === 'hardBreak') {
112
+ return '\n';
113
+ }
114
+ return '';
115
+ });
116
+ return textContent.join('');
104
117
  };
@@ -1,11 +1,33 @@
1
- /** wrap nodes into bullet list or numbered list, does not work for task list */
1
+ import { isListWithTextContentOnly } from './nodeChecks';
2
+ var wrapIntoTaskOrDecisionList = function wrapIntoTaskOrDecisionList(nodes, targetNodeTypeName, schema) {
3
+ var itemNodeType = targetNodeTypeName === 'taskList' ? schema.nodes.taskItem : schema.nodes.decisionItem;
4
+ var inlineContent = nodes.flatMap(function (node) {
5
+ if (node.isTextblock) {
6
+ return node.children;
7
+ } else if (node.isText) {
8
+ return [node];
9
+ }
10
+ return [];
11
+ });
12
+ var itemNode = itemNodeType.create({}, inlineContent);
13
+ var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, itemNode);
14
+ return outputNode ? [outputNode] : nodes;
15
+ };
16
+ var wrapIntoBulletOrOrderedList = function wrapIntoBulletOrOrderedList(nodes, targetNodeTypeName, schema) {
17
+ var listItemNode = schema.nodes.listItem.createAndFill({}, nodes);
18
+ var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, listItemNode);
19
+ return outputNode ? [outputNode] : nodes;
20
+ };
21
+
22
+ /**
23
+ * Wraps nodes into bullet list, numbered list, task list, or decision list.
24
+ *
25
+ * @param nodes - The nodes to wrap.
26
+ * @param context - The transformation context containing schema and target node type.
27
+ * @returns The wrapped nodes.
28
+ */
2
29
  export var wrapIntoListStep = function wrapIntoListStep(nodes, context) {
3
30
  var schema = context.schema,
4
31
  targetNodeTypeName = context.targetNodeTypeName;
5
- var listItemNode = schema.nodes.listItem.createAndFill({}, nodes);
6
- var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, listItemNode);
7
- if (outputNode) {
8
- return [outputNode];
9
- }
10
- return nodes;
32
+ return isListWithTextContentOnly(targetNodeTypeName, schema) ? wrapIntoTaskOrDecisionList(nodes, targetNodeTypeName, schema) : wrapIntoBulletOrOrderedList(nodes, targetNodeTypeName, schema);
11
33
  };
@@ -196,9 +196,7 @@ export var getBlockMenuComponents = function getBlockMenuComponents(_ref7) {
196
196
  rank: MAIN_BLOCK_MENU_SECTION_RANK[DELETE_MENU_SECTION.key],
197
197
  component: function component(_ref0) {
198
198
  var children = _ref0.children;
199
- return /*#__PURE__*/React.createElement(DeleteSection, {
200
- api: api
201
- }, children);
199
+ return /*#__PURE__*/React.createElement(DeleteSection, null, children);
202
200
  }
203
201
  }, {
204
202
  type: 'block-menu-item',
@@ -76,8 +76,8 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
76
76
  });
77
77
  }, [api, blockLinkHashPrefix, getLinkPath, onDropdownOpenChanged, selection]);
78
78
 
79
- // Hide copy link when `platform_editor_adf_with_localid` feature flag is off or when the node is nested or on empty line
80
- if (!fg('platform_editor_adf_with_localid') || !!menuTriggerBy && isNestedNode(selection, menuTriggerBy) || selection !== null && selection !== void 0 && selection.empty) {
79
+ // Hide copy link when `platform_editor_adf_with_localid` feature flag is off or when the node is nested
80
+ if (!fg('platform_editor_adf_with_localid') || !!menuTriggerBy && isNestedNode(selection, menuTriggerBy)) {
81
81
  return null;
82
82
  }
83
83
  return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
@@ -1,14 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
3
3
  export var DeleteSection = function DeleteSection(_ref) {
4
- var _api$selection;
5
- var api = _ref.api,
6
- children = _ref.children;
7
- 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;
8
- var isEmptyLineSelected = !!(selection !== null && selection !== void 0 && selection.empty);
9
- if (isEmptyLineSelected) {
10
- return null;
11
- }
4
+ var children = _ref.children;
12
5
  return /*#__PURE__*/React.createElement(ToolbarDropdownItemSection, {
13
6
  hasSeparator: true
14
7
  }, children);
@@ -0,0 +1,17 @@
1
+ import type { Schema } from '@atlaskit/editor-prosemirror/model';
2
+ /**
3
+ * Checks if a node is a list type that supports indentation (bulletList, orderedList, taskList).
4
+ *
5
+ * @param node - The node to check.
6
+ * @param schema - ProseMirror schema for check
7
+ * @returns True if the node is a list type, false otherwise.
8
+ */
9
+ export declare const isListWithIndentation: (nodeTypeName: string, schema: Schema) => boolean;
10
+ /**
11
+ * Checks if a node is a list where its list items only support text content (taskList or decisionList).
12
+ *
13
+ * @param nodeTypeName - The node type name to check.
14
+ * @param schema - ProseMirror schema for check
15
+ * @returns True if the node is a list text type, false otherwise.
16
+ */
17
+ export declare const isListWithTextContentOnly: (nodeTypeName: string, schema: Schema) => boolean;
@@ -0,0 +1,9 @@
1
+ import type { TransformStep } from '../types';
2
+ /**
3
+ * Transforms a paragraph (or heading) into a codeBlock by extracting its text content.
4
+ * This step handles the conversion of inline content (including marks) to plain text,
5
+ * which is required because codeBlocks can only contain plain text nodes.
6
+ *
7
+ * Example: paragraph with bold/italic/status → codeBlock with plain text
8
+ */
9
+ export declare const wrapTextToCodeblockStep: TransformStep;
@@ -4,7 +4,6 @@ import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
4
4
  import type { NodeTypeName } from './types';
5
5
  export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
6
6
  export declare const getTargetNodeTypeNameInContext: (nodeTypeName: NodeTypeName | null, isNested?: boolean) => NodeTypeName | null;
7
- export declare const isListType: (node: PMNode, schema: Schema) => boolean;
8
7
  /**
9
8
  * Converts a nestedExpand to a regular expand node.
10
9
  * NestedExpands can only exist inside expands, so when breaking out or placing
@@ -18,3 +17,11 @@ export declare const convertNestedExpandToExpand: (node: PMNode, schema: Schema)
18
17
  */
19
18
  export declare const convertExpandToNestedExpand: (node: PMNode, schema: Schema) => PMNode | null;
20
19
  export declare const getBlockNodesInRange: (range: NodeRange) => PMNode[];
20
+ /**
21
+ * Iterates over a nodes children and extracting text content, removing all other inline content and converting
22
+ * hardbreaks to newlines.
23
+ *
24
+ * @param node - The node to create text content from (should be paragraph)
25
+ * @returns The text content string.
26
+ */
27
+ export declare const createTextContent: (node: PMNode) => string;
@@ -1,3 +1,9 @@
1
1
  import type { TransformStep } from './types';
2
- /** wrap nodes into bullet list or numbered list, does not work for task list */
2
+ /**
3
+ * Wraps nodes into bullet list, numbered list, task list, or decision list.
4
+ *
5
+ * @param nodes - The nodes to wrap.
6
+ * @param context - The transformation context containing schema and target node type.
7
+ * @returns The wrapped nodes.
8
+ */
3
9
  export declare const wrapIntoListStep: TransformStep;
@@ -1,7 +1,4 @@
1
1
  import React from 'react';
2
- import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
- import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
- export declare const DeleteSection: ({ api, children, }: {
5
- api: ExtractInjectionAPI<BlockMenuPlugin> | undefined;
2
+ export declare const DeleteSection: ({ children, }: {
6
3
  children: React.ReactNode;
7
4
  }) => React.JSX.Element | null;
@@ -0,0 +1,17 @@
1
+ import type { Schema } from '@atlaskit/editor-prosemirror/model';
2
+ /**
3
+ * Checks if a node is a list type that supports indentation (bulletList, orderedList, taskList).
4
+ *
5
+ * @param node - The node to check.
6
+ * @param schema - ProseMirror schema for check
7
+ * @returns True if the node is a list type, false otherwise.
8
+ */
9
+ export declare const isListWithIndentation: (nodeTypeName: string, schema: Schema) => boolean;
10
+ /**
11
+ * Checks if a node is a list where its list items only support text content (taskList or decisionList).
12
+ *
13
+ * @param nodeTypeName - The node type name to check.
14
+ * @param schema - ProseMirror schema for check
15
+ * @returns True if the node is a list text type, false otherwise.
16
+ */
17
+ export declare const isListWithTextContentOnly: (nodeTypeName: string, schema: Schema) => boolean;
@@ -0,0 +1,9 @@
1
+ import type { TransformStep } from '../types';
2
+ /**
3
+ * Transforms a paragraph (or heading) into a codeBlock by extracting its text content.
4
+ * This step handles the conversion of inline content (including marks) to plain text,
5
+ * which is required because codeBlocks can only contain plain text nodes.
6
+ *
7
+ * Example: paragraph with bold/italic/status → codeBlock with plain text
8
+ */
9
+ export declare const wrapTextToCodeblockStep: TransformStep;