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

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 +20 -0
  2. package/dist/cjs/blockMenuPlugin.js +2 -2
  3. package/dist/cjs/editor-commands/transform-node-utils/flattenStep.js +18 -8
  4. package/dist/cjs/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +50 -0
  5. package/dist/cjs/editor-commands/transform-node-utils/steps/flattenListStep.js +12 -2
  6. package/dist/cjs/editor-commands/transform-node-utils/steps/unwrapListStep.js +10 -2
  7. package/dist/cjs/editor-commands/transform-node-utils/transform.js +20 -5
  8. package/dist/cjs/editor-commands/transformNode.js +5 -3
  9. package/dist/cjs/editor-commands/transforms/utils.js +3 -1
  10. package/dist/cjs/ui/block-menu.js +38 -33
  11. package/dist/es2019/blockMenuPlugin.js +2 -2
  12. package/dist/es2019/editor-commands/transform-node-utils/flattenStep.js +16 -6
  13. package/dist/es2019/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +46 -0
  14. package/dist/es2019/editor-commands/transform-node-utils/steps/flattenListStep.js +12 -2
  15. package/dist/es2019/editor-commands/transform-node-utils/steps/unwrapListStep.js +10 -2
  16. package/dist/es2019/editor-commands/transform-node-utils/transform.js +20 -5
  17. package/dist/es2019/editor-commands/transformNode.js +5 -3
  18. package/dist/es2019/editor-commands/transforms/utils.js +3 -1
  19. package/dist/es2019/ui/block-menu.js +38 -33
  20. package/dist/esm/blockMenuPlugin.js +2 -2
  21. package/dist/esm/editor-commands/transform-node-utils/flattenStep.js +18 -8
  22. package/dist/esm/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +44 -0
  23. package/dist/esm/editor-commands/transform-node-utils/steps/flattenListStep.js +12 -2
  24. package/dist/esm/editor-commands/transform-node-utils/steps/unwrapListStep.js +10 -2
  25. package/dist/esm/editor-commands/transform-node-utils/transform.js +20 -5
  26. package/dist/esm/editor-commands/transformNode.js +5 -3
  27. package/dist/esm/editor-commands/transforms/utils.js +3 -1
  28. package/dist/esm/ui/block-menu.js +38 -33
  29. package/dist/types/blockMenuPluginType.d.ts +2 -2
  30. package/dist/types/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.d.ts +20 -0
  31. package/dist/types/editor-commands/transform-node-utils/steps/unwrapListStep.d.ts +3 -0
  32. package/dist/types/editor-commands/transform-node-utils/transform.d.ts +2 -1
  33. package/dist/types/editor-commands/transform-node-utils/types.d.ts +1 -0
  34. package/dist/types/editor-commands/transformNode.d.ts +2 -2
  35. package/dist/types/editor-commands/transforms/types.d.ts +2 -1
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types-ts4.5/blockMenuPluginType.d.ts +2 -2
  38. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.d.ts +20 -0
  39. package/dist/types-ts4.5/editor-commands/transform-node-utils/steps/unwrapListStep.d.ts +3 -0
  40. package/dist/types-ts4.5/editor-commands/transform-node-utils/transform.d.ts +2 -1
  41. package/dist/types-ts4.5/editor-commands/transform-node-utils/types.d.ts +1 -0
  42. package/dist/types-ts4.5/editor-commands/transformNode.d.ts +2 -2
  43. package/dist/types-ts4.5/editor-commands/transforms/types.d.ts +2 -1
  44. package/dist/types-ts4.5/index.d.ts +1 -0
  45. package/package.json +2 -2
@@ -1,4 +1,6 @@
1
+ import { breakoutResizableNodes } from '@atlaskit/editor-common/utils';
1
2
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
2
4
  export const getTargetNodeInfo = (targetType, nodes) => {
3
5
  switch (targetType) {
4
6
  case 'heading1':
@@ -198,7 +200,7 @@ export const convertCodeBlockContentToParagraphs = (codeBlockNode, schema) => {
198
200
  return paragraphNodes;
199
201
  };
200
202
  const isBreakoutMarkSupported = nodeType => {
201
- return ['codeBlock', 'expand', 'layoutSection'].includes(nodeType.name);
203
+ return editorExperiment('platform_synced_block', true) ? breakoutResizableNodes.includes(nodeType.name) : ['codeBlock', 'expand', 'layoutSection'].includes(nodeType.name);
202
204
  };
203
205
  export const getMarksWithBreakout = (sourceNode, targetNodeType) => {
204
206
  const allowedMarks = targetNodeType.allowedMarks(sourceNode.marks);
@@ -124,7 +124,7 @@ const BlockMenu = ({
124
124
  boundariesElement,
125
125
  scrollableElement
126
126
  }) => {
127
- var _editorView$dom, _ref;
127
+ var _editorView$dom, _ref, _api$analytics3;
128
128
  const {
129
129
  menuTriggerBy,
130
130
  isSelectedViaDragHandle,
@@ -194,6 +194,13 @@ const BlockMenu = ({
194
194
  return tr;
195
195
  });
196
196
  };
197
+ const handleClickOutside = e => {
198
+ // check if the clicked element was another drag handle, if so don't close the menu
199
+ if (e.target instanceof HTMLElement && e.target.closest(DRAG_HANDLE_SELECTOR)) {
200
+ return;
201
+ }
202
+ closeMenu();
203
+ };
197
204
  const closeMenu = () => {
198
205
  api === null || api === void 0 ? void 0 : api.core.actions.execute(({
199
206
  tr
@@ -220,39 +227,37 @@ const BlockMenu = ({
220
227
  popupRef.current = el;
221
228
  }
222
229
  };
223
- if (targetHandleRef instanceof HTMLElement) {
224
- var _api$analytics3;
225
- return /*#__PURE__*/React.createElement(ErrorBoundary, {
226
- component: ACTION_SUBJECT.BLOCK_MENU,
227
- dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
228
- fallbackComponent: null
229
- }, /*#__PURE__*/React.createElement(PopupWithListeners, {
230
- alignX: 'right',
231
- alignY: 'start',
232
- handleClickOutside: closeMenu,
233
- handleEscapeKeydown: closeMenu,
234
- handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
235
- mountTo: mountTo,
236
- boundariesElement: boundariesElement,
237
- scrollableElement: scrollableElement,
238
- target: targetHandleRef,
239
- zIndex: akEditorFloatingOverlapPanelZIndex,
240
- fitWidth: DEFAULT_MENU_WIDTH,
241
- fitHeight: menuHeight,
242
- preventOverflow: true,
243
- stick: true,
244
- offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
245
- focusTrap: openedViaKeyboard ?
246
- // Only enable focus trap when opened via keyboard to make sure the focus is on the first focusable menu item
247
- {
248
- initialFocus: undefined
249
- } : undefined
250
- }, /*#__PURE__*/React.createElement(BlockMenuContent, {
251
- api: api,
252
- setRef: setRef
253
- })));
254
- } else {
230
+ if (!(targetHandleRef instanceof HTMLElement)) {
255
231
  return null;
256
232
  }
233
+ return /*#__PURE__*/React.createElement(ErrorBoundary, {
234
+ component: ACTION_SUBJECT.BLOCK_MENU,
235
+ dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
236
+ fallbackComponent: null
237
+ }, /*#__PURE__*/React.createElement(PopupWithListeners, {
238
+ alignX: 'right',
239
+ alignY: 'start',
240
+ handleClickOutside: handleClickOutside,
241
+ handleEscapeKeydown: closeMenu,
242
+ handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
243
+ mountTo: mountTo,
244
+ boundariesElement: boundariesElement,
245
+ scrollableElement: scrollableElement,
246
+ target: targetHandleRef,
247
+ zIndex: akEditorFloatingOverlapPanelZIndex,
248
+ fitWidth: DEFAULT_MENU_WIDTH,
249
+ fitHeight: menuHeight,
250
+ preventOverflow: true,
251
+ stick: true,
252
+ offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
253
+ focusTrap: openedViaKeyboard ?
254
+ // Only enable focus trap when opened via keyboard to make sure the focus is on the first focusable menu item
255
+ {
256
+ initialFocus: undefined
257
+ } : undefined
258
+ }, /*#__PURE__*/React.createElement(BlockMenuContent, {
259
+ api: api,
260
+ setRef: setRef
261
+ })));
257
262
  };
258
263
  export default injectIntl(BlockMenu);
@@ -35,8 +35,8 @@ export var blockMenuPlugin = function blockMenuPlugin(_ref) {
35
35
  formatNode: function formatNode(targetType, analyticsAttrs) {
36
36
  return _formatNode(api)(targetType, analyticsAttrs);
37
37
  },
38
- transformNode: function transformNode(targetType, analyticsAttrs) {
39
- return _transformNode(api)(targetType, analyticsAttrs);
38
+ transformNode: function transformNode(targetType, metadata) {
39
+ return _transformNode(api)(targetType, metadata);
40
40
  }
41
41
  },
42
42
  getSharedState: function getSharedState(editorState) {
@@ -1,15 +1,25 @@
1
1
  export var flattenStep = function flattenStep(nodes, context) {
2
2
  var schema = context.schema,
3
3
  targetNodeTypeName = context.targetNodeTypeName;
4
+ var targetNodeType = schema.nodes[targetNodeTypeName];
5
+ if (!targetNodeType) {
6
+ return nodes;
7
+ }
4
8
 
5
9
  // TODO: EDITOR-2920 - Implement flattening logic.
6
- // This is a simplified preliminary approach. We might want to use prosemirror-markdown functions.
7
- var codeBlockContent = nodes.map(function (node) {
8
- return node.content.textBetween(0, node.content.size, '\n');
9
- }).join('\n');
10
- var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, schema.text(codeBlockContent));
11
- if (!outputNode) {
12
- return nodes;
10
+ var isTargetCodeBlock = targetNodeTypeName === 'codeBlock';
11
+ if (isTargetCodeBlock) {
12
+ // This strips explicitly text nodes
13
+ var codeBlockContent = nodes.map(function (node) {
14
+ return node.content.textBetween(0, node.content.size, '\n');
15
+ }).join('\n');
16
+ return [schema.nodes.codeBlock.create({}, schema.text(codeBlockContent))];
13
17
  }
14
- return [outputNode];
18
+ return nodes.map(function (node) {
19
+ var isValidWithin = targetNodeType.validContent(node.content);
20
+ if (!isValidWithin) {
21
+ return node;
22
+ }
23
+ return schema.nodes.paragraph.create({}, node.content);
24
+ });
15
25
  };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Applies target text type conversion. If the target type is a heading, converts textblock nodes
3
+ * (paragraphs, headings) to heading nodes with the specified level. Otherwise, leaves nodes unchanged.
4
+ * Non-textblock nodes are always left unchanged.
5
+ *
6
+ * @example
7
+ * Input:
8
+ * - paragraph "Heading 1"
9
+ * - paragraph "Heading 2"
10
+ *
11
+ * Output (with target: heading, level: 2):
12
+ * - heading (level: 2) "Heading 1"
13
+ * - heading (level: 2) "Heading 2"
14
+ *
15
+ * @param nodes
16
+ * @param context
17
+ * @returns
18
+ */
19
+ export var applyTargetTextTypeStep = function applyTargetTextTypeStep(nodes, context) {
20
+ var schema = context.schema,
21
+ targetNodeTypeName = context.targetNodeTypeName,
22
+ targetAttrs = context.targetAttrs;
23
+ if (targetNodeTypeName !== 'heading') {
24
+ return nodes;
25
+ }
26
+ var headingType = schema.nodes.heading;
27
+ if (!headingType) {
28
+ return nodes;
29
+ }
30
+
31
+ // Default to level 1 if no level is specified
32
+ // The level should ideally come from targetAttrs, but if not available, use default
33
+ var headingLevel = typeof (targetAttrs === null || targetAttrs === void 0 ? void 0 : targetAttrs.level) === 'number' ? targetAttrs.level : 1;
34
+ return nodes.map(function (node) {
35
+ if (node.isTextblock) {
36
+ // Convert textblock nodes (paragraphs, headings) to heading with specified level
37
+ return headingType.create({
38
+ level: headingLevel
39
+ }, node.content);
40
+ }
41
+ // Non-textblock nodes are left unchanged
42
+ return node;
43
+ });
44
+ };
@@ -3,7 +3,7 @@ import { isListWithIndentation } from '../nodeChecks';
3
3
  var extractNestedLists = function extractNestedLists(node, schema) {
4
4
  var items = [];
5
5
  var paragraph = schema.nodes.paragraph;
6
- var itemTypes = [schema.nodes.listItem, schema.nodes.taskItem];
6
+ var itemTypes = [schema.nodes.listItem, schema.nodes.taskItem, schema.nodes.decisionItem];
7
7
  var _extract = function extract(currentNode) {
8
8
  currentNode.forEach(function (child) {
9
9
  if (itemTypes.some(function (type) {
@@ -11,11 +11,21 @@ var extractNestedLists = function extractNestedLists(node, schema) {
11
11
  })) {
12
12
  var contentWithoutNestedLists = [];
13
13
  var nestedLists = [];
14
+
15
+ // Check if this item type expects inline content (taskItem, decisionItem)
16
+ // vs block content (listItem) based on the schema definition
17
+ var isInlineItem = child.type.inlineContent;
14
18
  child.forEach(function (grandChild) {
15
19
  if (isListWithIndentation(grandChild.type.name, schema)) {
16
20
  nestedLists.push(grandChild);
17
21
  } else if (grandChild.isText) {
18
- contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
22
+ // For taskItem/decisionItem, keep text as-is (they support inline content)
23
+ // For listItem, wrap text in paragraph (they require block content)
24
+ if (isInlineItem) {
25
+ contentWithoutNestedLists.push(grandChild);
26
+ } else {
27
+ contentWithoutNestedLists.push(paragraph.createAndFill({}, grandChild));
28
+ }
19
29
  } else {
20
30
  contentWithoutNestedLists.push(grandChild);
21
31
  }
@@ -3,6 +3,9 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  * Given an array of nodes, processes each list removing all parent list nodes and
4
4
  * just returning their child contents.
5
5
  *
6
+ * For lists with block content (bulletList, orderedList), it extracts the block nodes directly.
7
+ * For lists with inline content (taskList, decisionList), it wraps the content in paragraphs.
8
+ *
6
9
  * @example
7
10
  * Input:
8
11
  * - bulletList
@@ -20,14 +23,19 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
20
23
  * @returns
21
24
  */
22
25
  export var unwrapListStep = function unwrapListStep(nodes, context) {
23
- var listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
26
+ var listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList, context.schema.nodes.decisionList];
24
27
  return nodes.flatMap(function (node) {
25
28
  if (listTypes.some(function (type) {
26
29
  return node.type === type;
27
30
  })) {
28
31
  var listItems = [];
29
32
  node.forEach(function (listItem) {
30
- listItems.push.apply(listItems, _toConsumableArray(listItem.children));
33
+ // if isTaskItem or isDecisionItem, convert to paragraph
34
+ if (listItem.type.name === 'taskItem' || listItem.type.name === 'decisionItem') {
35
+ listItems.push(context.schema.nodes.paragraph.create({}, listItem.content));
36
+ } else {
37
+ listItems.push.apply(listItems, _toConsumableArray(listItem.children));
38
+ }
31
39
  });
32
40
  return listItems;
33
41
  }
@@ -1,5 +1,6 @@
1
1
  import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
2
2
  import { flattenStep } from './flattenStep';
3
+ import { applyTargetTextTypeStep } from './steps/applyTargetTextTypeStep';
3
4
  import { decisionListToListStep } from './steps/decisionListToListStep';
4
5
  import { flattenListStep } from './steps/flattenListStep';
5
6
  import { listToDecisionListStep } from './steps/listToDecisionListStep';
@@ -29,19 +30,19 @@ var TRANSFORM_STEPS = {
29
30
  atomic: undefined,
30
31
  container: [unwrapStep, wrapStep],
31
32
  list: undefined,
32
- text: [unwrapStep]
33
+ text: [unwrapStep, applyTargetTextTypeStep]
33
34
  },
34
35
  list: {
35
36
  atomic: undefined,
36
37
  container: [wrapStep],
37
38
  list: [listToListStep],
38
- text: [flattenListStep, unwrapListStep]
39
+ text: [flattenListStep, unwrapListStep, applyTargetTextTypeStep]
39
40
  },
40
41
  text: {
41
42
  atomic: undefined,
42
43
  container: [wrapStep],
43
44
  list: [wrapIntoListStep],
44
- text: [stubStep]
45
+ text: [flattenStep, applyTargetTextTypeStep]
45
46
  }
46
47
  };
47
48
 
@@ -124,6 +125,18 @@ var TRANSFORM_STEPS_OVERRIDE = {
124
125
  orderedList: [decisionListToListStep],
125
126
  taskList: [decisionListToListStep],
126
127
  layoutSection: [wrapIntoLayoutStep]
128
+ },
129
+ blockCard: {
130
+ layoutSection: [wrapIntoLayoutStep]
131
+ },
132
+ embedCard: {
133
+ layoutSection: [wrapIntoLayoutStep]
134
+ },
135
+ extension: {
136
+ layoutSection: [wrapIntoLayoutStep]
137
+ },
138
+ bodiedExtension: {
139
+ layoutSection: [wrapIntoLayoutStep]
127
140
  }
128
141
  };
129
142
  var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
@@ -138,7 +151,8 @@ export var getOutputNodes = function getOutputNodes(_ref) {
138
151
  var sourceNode = _ref.sourceNode,
139
152
  targetNodeType = _ref.targetNodeType,
140
153
  schema = _ref.schema,
141
- isNested = _ref.isNested;
154
+ isNested = _ref.isNested,
155
+ targetAttrs = _ref.targetAttrs;
142
156
  var nodesToReplace = [sourceNode];
143
157
  var selectedNodeTypeName = toNodeTypeValue(sourceNode.type.name);
144
158
  var initialTargetNodeTypeName = toNodeTypeValue(targetNodeType.name);
@@ -151,7 +165,8 @@ export var getOutputNodes = function getOutputNodes(_ref) {
151
165
  var context = {
152
166
  fromNode: sourceNode,
153
167
  targetNodeTypeName: targetNodeTypeName,
154
- schema: schema
168
+ schema: schema,
169
+ targetAttrs: targetAttrs
155
170
  };
156
171
  if (!steps || steps.length === 0) {
157
172
  return;
@@ -7,7 +7,7 @@ import { isListNode } from './transforms/utils';
7
7
  export var transformNode = function transformNode(api) {
8
8
  return (
9
9
  // eslint-disable-next-line no-unused-vars
10
- function (targetType, analyticsAttrs) {
10
+ function (targetType, metadata) {
11
11
  return function (_ref) {
12
12
  var _api$blockControls;
13
13
  var tr = _ref.tr;
@@ -20,8 +20,9 @@ export var transformNode = function transformNode(api) {
20
20
  var _expandSelectionToBlo = expandSelectionToBlockRange(preservedSelection),
21
21
  $from = _expandSelectionToBlo.$from,
22
22
  $to = _expandSelectionToBlo.$to;
23
- var isNested = isNestedNode(preservedSelection, '');
24
23
  var selectedParent = $from.parent;
24
+ var isParentLayout = selectedParent.type === nodes.layoutColumn;
25
+ var isNestedExceptLayout = isNestedNode(preservedSelection, '') && !isParentLayout;
25
26
  var fragment = Fragment.empty;
26
27
  var isList = isListNode(selectedParent);
27
28
  var slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
@@ -30,7 +31,8 @@ export var transformNode = function transformNode(api) {
30
31
  sourceNode: node,
31
32
  targetNodeType: targetType,
32
33
  schema: tr.doc.type.schema,
33
- isNested: isNested
34
+ isNested: isNestedExceptLayout,
35
+ targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs
34
36
  });
35
37
  if (outputNode) {
36
38
  fragment = fragment.append(Fragment.fromArray(outputNode));
@@ -1,5 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { breakoutResizableNodes } from '@atlaskit/editor-common/utils';
2
3
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
4
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
3
5
  export var getTargetNodeInfo = function getTargetNodeInfo(targetType, nodes) {
4
6
  switch (targetType) {
5
7
  case 'heading1':
@@ -199,7 +201,7 @@ export var convertCodeBlockContentToParagraphs = function convertCodeBlockConten
199
201
  return paragraphNodes;
200
202
  };
201
203
  var isBreakoutMarkSupported = function isBreakoutMarkSupported(nodeType) {
202
- return ['codeBlock', 'expand', 'layoutSection'].includes(nodeType.name);
204
+ return editorExperiment('platform_synced_block', true) ? breakoutResizableNodes.includes(nodeType.name) : ['codeBlock', 'expand', 'layoutSection'].includes(nodeType.name);
203
205
  };
204
206
  export var getMarksWithBreakout = function getMarksWithBreakout(sourceNode, targetNodeType) {
205
207
  var allowedMarks = targetNodeType.allowedMarks(sourceNode.marks);
@@ -118,7 +118,7 @@ var BlockMenuContent = function BlockMenuContent(_ref3) {
118
118
  })));
119
119
  };
120
120
  var BlockMenu = function BlockMenu(_ref4) {
121
- var _editorView$dom, _ref5;
121
+ var _editorView$dom, _ref5, _api$analytics3;
122
122
  var editorView = _ref4.editorView,
123
123
  api = _ref4.api,
124
124
  mountTo = _ref4.mountTo,
@@ -193,6 +193,13 @@ var BlockMenu = function BlockMenu(_ref4) {
193
193
  return tr;
194
194
  });
195
195
  };
196
+ var handleClickOutside = function handleClickOutside(e) {
197
+ // check if the clicked element was another drag handle, if so don't close the menu
198
+ if (e.target instanceof HTMLElement && e.target.closest(DRAG_HANDLE_SELECTOR)) {
199
+ return;
200
+ }
201
+ closeMenu();
202
+ };
196
203
  var closeMenu = function closeMenu() {
197
204
  api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
198
205
  var _api$blockControls3, _api$userIntent3;
@@ -218,39 +225,37 @@ var BlockMenu = function BlockMenu(_ref4) {
218
225
  popupRef.current = el;
219
226
  }
220
227
  };
221
- if (targetHandleRef instanceof HTMLElement) {
222
- var _api$analytics3;
223
- return /*#__PURE__*/React.createElement(ErrorBoundary, {
224
- component: ACTION_SUBJECT.BLOCK_MENU,
225
- dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
226
- fallbackComponent: null
227
- }, /*#__PURE__*/React.createElement(PopupWithListeners, {
228
- alignX: 'right',
229
- alignY: 'start',
230
- handleClickOutside: closeMenu,
231
- handleEscapeKeydown: closeMenu,
232
- handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
233
- mountTo: mountTo,
234
- boundariesElement: boundariesElement,
235
- scrollableElement: scrollableElement,
236
- target: targetHandleRef,
237
- zIndex: akEditorFloatingOverlapPanelZIndex,
238
- fitWidth: DEFAULT_MENU_WIDTH,
239
- fitHeight: menuHeight,
240
- preventOverflow: true,
241
- stick: true,
242
- offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
243
- focusTrap: openedViaKeyboard ?
244
- // Only enable focus trap when opened via keyboard to make sure the focus is on the first focusable menu item
245
- {
246
- initialFocus: undefined
247
- } : undefined
248
- }, /*#__PURE__*/React.createElement(BlockMenuContent, {
249
- api: api,
250
- setRef: setRef
251
- })));
252
- } else {
228
+ if (!(targetHandleRef instanceof HTMLElement)) {
253
229
  return null;
254
230
  }
231
+ return /*#__PURE__*/React.createElement(ErrorBoundary, {
232
+ component: ACTION_SUBJECT.BLOCK_MENU,
233
+ dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
234
+ fallbackComponent: null
235
+ }, /*#__PURE__*/React.createElement(PopupWithListeners, {
236
+ alignX: 'right',
237
+ alignY: 'start',
238
+ handleClickOutside: handleClickOutside,
239
+ handleEscapeKeydown: closeMenu,
240
+ handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
241
+ mountTo: mountTo,
242
+ boundariesElement: boundariesElement,
243
+ scrollableElement: scrollableElement,
244
+ target: targetHandleRef,
245
+ zIndex: akEditorFloatingOverlapPanelZIndex,
246
+ fitWidth: DEFAULT_MENU_WIDTH,
247
+ fitHeight: menuHeight,
248
+ preventOverflow: true,
249
+ stick: true,
250
+ offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
251
+ focusTrap: openedViaKeyboard ?
252
+ // Only enable focus trap when opened via keyboard to make sure the focus is on the first focusable menu item
253
+ {
254
+ initialFocus: undefined
255
+ } : undefined
256
+ }, /*#__PURE__*/React.createElement(BlockMenuContent, {
257
+ api: api,
258
+ setRef: setRef
259
+ })));
255
260
  };
256
261
  export default injectIntl(BlockMenu);
@@ -5,12 +5,12 @@ import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
5
5
  import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
6
6
  import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
7
7
  import type { NodeType } from '@atlaskit/editor-prosemirror/model';
8
- import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeAnalyticsAttrs } from './editor-commands/transforms/types';
8
+ import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeMetadata } from './editor-commands/transforms/types';
9
9
  export declare enum FLAG_ID {
10
10
  LINK_COPIED_TO_CLIPBOARD = "link-copied-to-clipboard"
11
11
  }
12
12
  type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
13
- type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
13
+ type TransformNodeCommand = (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;
14
14
  export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
15
15
  actions: {
16
16
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
@@ -0,0 +1,20 @@
1
+ import type { TransformStep } from '../types';
2
+ /**
3
+ * Applies target text type conversion. If the target type is a heading, converts textblock nodes
4
+ * (paragraphs, headings) to heading nodes with the specified level. Otherwise, leaves nodes unchanged.
5
+ * Non-textblock nodes are always left unchanged.
6
+ *
7
+ * @example
8
+ * Input:
9
+ * - paragraph "Heading 1"
10
+ * - paragraph "Heading 2"
11
+ *
12
+ * Output (with target: heading, level: 2):
13
+ * - heading (level: 2) "Heading 1"
14
+ * - heading (level: 2) "Heading 2"
15
+ *
16
+ * @param nodes
17
+ * @param context
18
+ * @returns
19
+ */
20
+ export declare const applyTargetTextTypeStep: TransformStep;
@@ -3,6 +3,9 @@ import type { TransformStep } from '../types';
3
3
  * Given an array of nodes, processes each list removing all parent list nodes and
4
4
  * just returning their child contents.
5
5
  *
6
+ * For lists with block content (bulletList, orderedList), it extracts the block nodes directly.
7
+ * For lists with inline content (taskList, decisionList), it wraps the content in paragraphs.
8
+ *
6
9
  * @example
7
10
  * Input:
8
11
  * - bulletList
@@ -3,7 +3,8 @@ interface GetOutputNodesArgs {
3
3
  isNested: boolean;
4
4
  schema: Schema;
5
5
  sourceNode: PMNode;
6
+ targetAttrs?: Record<string, unknown>;
6
7
  targetNodeType: NodeType;
7
8
  }
8
- export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, isNested, }: GetOutputNodesArgs) => PMNode[] | undefined;
9
+ export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, isNested, targetAttrs, }: GetOutputNodesArgs) => PMNode[] | undefined;
9
10
  export {};
@@ -8,5 +8,6 @@ export type TransformStep = (nodes: PMNode[], context: TransformStepContext) =>
8
8
  export interface TransformStepContext {
9
9
  fromNode: PMNode;
10
10
  schema: Schema;
11
+ targetAttrs?: Record<string, unknown>;
11
12
  targetNodeTypeName: NodeTypeName;
12
13
  }
@@ -1,5 +1,5 @@
1
1
  import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
2
  import { type NodeType } from '@atlaskit/editor-prosemirror/model';
3
3
  import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
- import type { TransformNodeAnalyticsAttrs } from './transforms/types';
5
- export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
4
+ import type { TransformNodeMetadata } from './transforms/types';
5
+ export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;
@@ -7,7 +7,8 @@ export type FormatNodeAnalyticsAttrs = {
7
7
  inputMethod: INPUT_METHOD.BLOCK_MENU;
8
8
  triggeredFrom: INPUT_METHOD.MOUSE | INPUT_METHOD.KEYBOARD;
9
9
  };
10
- export type TransformNodeAnalyticsAttrs = FormatNodeAnalyticsAttrs & {
10
+ export type TransformNodeMetadata = FormatNodeAnalyticsAttrs & {
11
+ targetAttrs?: Record<string, unknown>;
11
12
  targetTypeName: TransfromNodeTargetType;
12
13
  };
13
14
  export type TransformFunction = (context: TransformContext) => Transaction | null;
@@ -1,2 +1,3 @@
1
1
  export { blockMenuPlugin } from './blockMenuPlugin';
2
2
  export type { BlockMenuPlugin, RegisterBlockMenuComponent, Parent, BlockMenuPluginOptions, BlockMenuSharedState, } from './blockMenuPluginType';
3
+ export type { TransformNodeMetadata } from './editor-commands/transforms/types';
@@ -5,12 +5,12 @@ import type { DecorationsPlugin } from '@atlaskit/editor-plugin-decorations';
5
5
  import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
6
6
  import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
7
7
  import type { NodeType } from '@atlaskit/editor-prosemirror/model';
8
- import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeAnalyticsAttrs } from './editor-commands/transforms/types';
8
+ import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType, TransformNodeMetadata } from './editor-commands/transforms/types';
9
9
  export declare enum FLAG_ID {
10
10
  LINK_COPIED_TO_CLIPBOARD = "link-copied-to-clipboard"
11
11
  }
12
12
  type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
13
- type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
13
+ type TransformNodeCommand = (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;
14
14
  export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
15
15
  actions: {
16
16
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
@@ -0,0 +1,20 @@
1
+ import type { TransformStep } from '../types';
2
+ /**
3
+ * Applies target text type conversion. If the target type is a heading, converts textblock nodes
4
+ * (paragraphs, headings) to heading nodes with the specified level. Otherwise, leaves nodes unchanged.
5
+ * Non-textblock nodes are always left unchanged.
6
+ *
7
+ * @example
8
+ * Input:
9
+ * - paragraph "Heading 1"
10
+ * - paragraph "Heading 2"
11
+ *
12
+ * Output (with target: heading, level: 2):
13
+ * - heading (level: 2) "Heading 1"
14
+ * - heading (level: 2) "Heading 2"
15
+ *
16
+ * @param nodes
17
+ * @param context
18
+ * @returns
19
+ */
20
+ export declare const applyTargetTextTypeStep: TransformStep;
@@ -3,6 +3,9 @@ import type { TransformStep } from '../types';
3
3
  * Given an array of nodes, processes each list removing all parent list nodes and
4
4
  * just returning their child contents.
5
5
  *
6
+ * For lists with block content (bulletList, orderedList), it extracts the block nodes directly.
7
+ * For lists with inline content (taskList, decisionList), it wraps the content in paragraphs.
8
+ *
6
9
  * @example
7
10
  * Input:
8
11
  * - bulletList
@@ -3,7 +3,8 @@ interface GetOutputNodesArgs {
3
3
  isNested: boolean;
4
4
  schema: Schema;
5
5
  sourceNode: PMNode;
6
+ targetAttrs?: Record<string, unknown>;
6
7
  targetNodeType: NodeType;
7
8
  }
8
- export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, isNested, }: GetOutputNodesArgs) => PMNode[] | undefined;
9
+ export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, isNested, targetAttrs, }: GetOutputNodesArgs) => PMNode[] | undefined;
9
10
  export {};
@@ -8,5 +8,6 @@ export type TransformStep = (nodes: PMNode[], context: TransformStepContext) =>
8
8
  export interface TransformStepContext {
9
9
  fromNode: PMNode;
10
10
  schema: Schema;
11
+ targetAttrs?: Record<string, unknown>;
11
12
  targetNodeTypeName: NodeTypeName;
12
13
  }
@@ -1,5 +1,5 @@
1
1
  import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
2
  import { type NodeType } from '@atlaskit/editor-prosemirror/model';
3
3
  import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
- import type { TransformNodeAnalyticsAttrs } from './transforms/types';
5
- export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: TransformNodeAnalyticsAttrs) => EditorCommand;
4
+ import type { TransformNodeMetadata } from './transforms/types';
5
+ export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, metadata?: TransformNodeMetadata) => EditorCommand;