@atlaskit/editor-plugin-block-menu 5.0.15 → 5.0.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 (32) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/blockMenuPlugin.js +4 -0
  3. package/dist/cjs/editor-commands/transform-node-utils/stubStep.js +9 -0
  4. package/dist/cjs/editor-commands/transform-node-utils/transform.js +83 -0
  5. package/dist/cjs/editor-commands/transform-node-utils/types.js +37 -0
  6. package/dist/cjs/editor-commands/transform-node-utils/utils.js +49 -0
  7. package/dist/cjs/editor-commands/transformNode.js +30 -0
  8. package/dist/es2019/blockMenuPlugin.js +4 -0
  9. package/dist/es2019/editor-commands/transform-node-utils/stubStep.js +3 -0
  10. package/dist/es2019/editor-commands/transform-node-utils/transform.js +79 -0
  11. package/dist/es2019/editor-commands/transform-node-utils/types.js +27 -0
  12. package/dist/es2019/editor-commands/transform-node-utils/utils.js +44 -0
  13. package/dist/es2019/editor-commands/transformNode.js +25 -0
  14. package/dist/esm/blockMenuPlugin.js +4 -0
  15. package/dist/esm/editor-commands/transform-node-utils/stubStep.js +3 -0
  16. package/dist/esm/editor-commands/transform-node-utils/transform.js +78 -0
  17. package/dist/esm/editor-commands/transform-node-utils/types.js +31 -0
  18. package/dist/esm/editor-commands/transform-node-utils/utils.js +43 -0
  19. package/dist/esm/editor-commands/transformNode.js +24 -0
  20. package/dist/types/blockMenuPluginType.d.ts +5 -1
  21. package/dist/types/editor-commands/transform-node-utils/stubStep.d.ts +2 -0
  22. package/dist/types/editor-commands/transform-node-utils/transform.d.ts +8 -0
  23. package/dist/types/editor-commands/transform-node-utils/types.d.ts +12 -0
  24. package/dist/types/editor-commands/transform-node-utils/utils.d.ts +3 -0
  25. package/dist/types/editor-commands/transformNode.d.ts +5 -0
  26. package/dist/types-ts4.5/blockMenuPluginType.d.ts +5 -1
  27. package/dist/types-ts4.5/editor-commands/transform-node-utils/stubStep.d.ts +2 -0
  28. package/dist/types-ts4.5/editor-commands/transform-node-utils/transform.d.ts +8 -0
  29. package/dist/types-ts4.5/editor-commands/transform-node-utils/types.d.ts +12 -0
  30. package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +3 -0
  31. package/dist/types-ts4.5/editor-commands/transformNode.d.ts +5 -0
  32. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 5.0.16
4
+
5
+ ### Patch Changes
6
+
7
+ - [`459eb2064ff46`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/459eb2064ff46) -
8
+ [ux] Implements base for the new transform logic for the block menu.
9
+ - Updated dependencies
10
+
3
11
  ## 5.0.15
4
12
 
5
13
  ### Patch Changes
@@ -8,6 +8,7 @@ exports.blockMenuPlugin = void 0;
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
  var _editorActions = require("./editor-actions");
10
10
  var _formatNode2 = require("./editor-commands/formatNode");
11
+ var _transformNode2 = require("./editor-commands/transformNode");
11
12
  var _main = require("./pm-plugins/main");
12
13
  var _blockMenu = _interopRequireDefault(require("./ui/block-menu"));
13
14
  var _blockMenuComponents = require("./ui/block-menu-components");
@@ -39,6 +40,9 @@ var blockMenuPlugin = exports.blockMenuPlugin = function blockMenuPlugin(_ref) {
39
40
  commands: {
40
41
  formatNode: function formatNode(targetType, analyticsAttrs) {
41
42
  return (0, _formatNode2.formatNode)(api)(targetType, analyticsAttrs);
43
+ },
44
+ transformNode: function transformNode(targetType, analyticsAttrs) {
45
+ return (0, _transformNode2.transformNode)(api)(targetType, analyticsAttrs);
42
46
  }
43
47
  },
44
48
  getSharedState: function getSharedState(editorState) {
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.stubStep = void 0;
7
+ var stubStep = exports.stubStep = function stubStep(nodes, context) {
8
+ return nodes;
9
+ };
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getOutputNodes = void 0;
7
+ var _stubStep = require("./stubStep");
8
+ var _types = require("./types");
9
+ // Exampled step for overrides:
10
+ // - open Block menu on a paragraph, click 'Panel' in the Turn into'
11
+ // - expected to put paragraph into a panel
12
+ var wrapIntoPanelStep = function wrapIntoPanelStep(nodes, context) {
13
+ var newNode = context.schema.nodes.panel.createAndFill({}, nodes);
14
+ return newNode ? [newNode] : [];
15
+ };
16
+
17
+ // Transform steps for combinations of node categories (block/container/list/text)
18
+ var TRANSFORM_STEPS = {
19
+ atomic: {
20
+ atomic: undefined,
21
+ container: [_stubStep.stubStep],
22
+ list: undefined,
23
+ text: undefined
24
+ },
25
+ container: {
26
+ atomic: undefined,
27
+ container: [_stubStep.stubStep],
28
+ list: undefined,
29
+ text: undefined
30
+ },
31
+ list: {
32
+ atomic: undefined,
33
+ container: [_stubStep.stubStep],
34
+ list: [_stubStep.stubStep],
35
+ text: [_stubStep.stubStep]
36
+ },
37
+ text: {
38
+ atomic: undefined,
39
+ container: [_stubStep.stubStep],
40
+ list: [_stubStep.stubStep],
41
+ text: [_stubStep.stubStep]
42
+ }
43
+ };
44
+
45
+ // Transform steps for specific pairs of node types that cannot be processed
46
+ // using generic rules/steps from TRANSFORM_STEPS.
47
+ var TRANSFORM_STEPS_OVERRIDE = {
48
+ paragraph: {
49
+ panel: [wrapIntoPanelStep]
50
+ }
51
+ };
52
+ var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
53
+ var _TRANSFORM_STEPS_OVER, _TRANSFORM_STEPS_OVER2;
54
+ var fromCategory = _types.NODE_CATEGORY_BY_TYPE[selectedNodeTypeName];
55
+ var toCategory = _types.NODE_CATEGORY_BY_TYPE[targetNodeTypeName];
56
+ var steps = (_TRANSFORM_STEPS_OVER = (_TRANSFORM_STEPS_OVER2 = TRANSFORM_STEPS_OVERRIDE[selectedNodeTypeName]) === null || _TRANSFORM_STEPS_OVER2 === void 0 ? void 0 : _TRANSFORM_STEPS_OVER2[targetNodeTypeName]) !== null && _TRANSFORM_STEPS_OVER !== void 0 ? _TRANSFORM_STEPS_OVER : TRANSFORM_STEPS[fromCategory][toCategory];
57
+ return steps;
58
+ };
59
+ // Note: Currently works only for single node in the selection
60
+ var getOutputNodes = exports.getOutputNodes = function getOutputNodes(_ref) {
61
+ var sourceNode = _ref.sourceNode,
62
+ targetNodeType = _ref.targetNodeType,
63
+ schema = _ref.schema;
64
+ var nodesToReplace = [sourceNode];
65
+ var selectedNodeTypeName = (0, _types.toNodeTypeValue)(sourceNode.type.name);
66
+ var targetNodeTypeName = (0, _types.toNodeTypeValue)(targetNodeType.name);
67
+ if (!selectedNodeTypeName || !targetNodeTypeName) {
68
+ // We may decide to return an empty array or undefined here
69
+ return;
70
+ }
71
+ var steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
72
+ var context = {
73
+ fromNode: sourceNode,
74
+ targetNodeTypeName: targetNodeTypeName,
75
+ schema: schema
76
+ };
77
+ if (!steps || steps.length === 0) {
78
+ return;
79
+ }
80
+ return steps.reduce(function (nodes, step) {
81
+ return step(nodes, context);
82
+ }, nodesToReplace);
83
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toNodeTypeValue = exports.isNodeTypeName = exports.NODE_CATEGORY_BY_TYPE = void 0;
7
+ var NODE_CATEGORY_BY_TYPE = exports.NODE_CATEGORY_BY_TYPE = {
8
+ blockquote: 'container',
9
+ blockCard: 'atomic',
10
+ bodiedExtension: 'atomic',
11
+ bulletList: 'list',
12
+ codeBlock: 'container',
13
+ decisionList: 'list',
14
+ embedCard: 'atomic',
15
+ expand: 'container',
16
+ extension: 'atomic',
17
+ heading: 'text',
18
+ layout: 'container',
19
+ media: 'atomic',
20
+ mediaGroup: 'atomic',
21
+ mediaSingle: 'atomic',
22
+ multiBodiedExtension: 'atomic',
23
+ orderedList: 'list',
24
+ panel: 'container',
25
+ paragraph: 'text',
26
+ nestedExpand: 'container',
27
+ taskList: 'list',
28
+ table: 'atomic'
29
+ };
30
+ var isNodeTypeName = exports.isNodeTypeName = function isNodeTypeName(value) {
31
+ return value in NODE_CATEGORY_BY_TYPE;
32
+ };
33
+ var toNodeTypeValue = exports.toNodeTypeValue = function toNodeTypeValue(value) {
34
+ return value && isNodeTypeName(value) ? value : null;
35
+ };
36
+
37
+ // Note: We are still deciding what should be in the context.
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getSelectedNode = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
9
+ var _editorTables = require("@atlaskit/editor-tables");
10
+ var getSelectedNode = exports.getSelectedNode = function getSelectedNode(selection) {
11
+ if (selection instanceof _state.NodeSelection) {
12
+ return {
13
+ node: selection.node,
14
+ pos: selection.$from.pos,
15
+ start: 0,
16
+ // ?
17
+ depth: selection.$from.depth
18
+ };
19
+ } else if (selection instanceof _editorTables.CellSelection) {
20
+ var tableSelected = (0, _utils.findParentNodeOfType)(selection.$from.doc.type.schema.nodes.table)(selection);
21
+ return tableSelected;
22
+ } else if (selection instanceof _state.TextSelection) {
23
+ var _selection$$from$doc$ = selection.$from.doc.type.schema.nodes,
24
+ blockquote = _selection$$from$doc$.blockquote,
25
+ bulletList = _selection$$from$doc$.bulletList,
26
+ orderedList = _selection$$from$doc$.orderedList,
27
+ taskList = _selection$$from$doc$.taskList,
28
+ codeBlock = _selection$$from$doc$.codeBlock,
29
+ paragraph = _selection$$from$doc$.paragraph,
30
+ heading = _selection$$from$doc$.heading;
31
+ var quoteSelected = (0, _utils.findParentNodeOfType)([blockquote])(selection);
32
+ if (quoteSelected) {
33
+ return quoteSelected;
34
+ }
35
+ var codeBlockSelected = (0, _utils.findParentNodeOfType)([codeBlock])(selection);
36
+ if (codeBlockSelected) {
37
+ return codeBlockSelected;
38
+ }
39
+ var listSelected = (0, _utils.findParentNodeOfType)([bulletList, taskList, orderedList])(selection);
40
+ if (listSelected) {
41
+ return listSelected;
42
+ }
43
+ var paragraphOrHeading = (0, _utils.findParentNodeOfType)([paragraph, heading])(selection);
44
+ if (paragraphOrHeading) {
45
+ return paragraphOrHeading;
46
+ }
47
+ }
48
+ return undefined;
49
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.transformNode = void 0;
7
+ var _utils = require("../editor-commands/transform-node-utils/utils");
8
+ var _transform = require("./transform-node-utils/transform");
9
+ var transformNode = exports.transformNode = function transformNode(api) {
10
+ return function (targetType, analyticsAttrs) {
11
+ return function (_ref) {
12
+ var tr = _ref.tr;
13
+ var selection = tr.selection;
14
+ var source = (0, _utils.getSelectedNode)(selection);
15
+ if (!source) {
16
+ return tr;
17
+ }
18
+ var outputNodes = (0, _transform.getOutputNodes)({
19
+ sourceNode: source.node,
20
+ targetNodeType: targetType,
21
+ schema: selection.$from.doc.type.schema
22
+ });
23
+ if (!outputNodes) {
24
+ return tr;
25
+ }
26
+ tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
27
+ return tr;
28
+ };
29
+ };
30
+ };
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { createBlockMenuRegistry } from './editor-actions';
3
3
  import { formatNode } from './editor-commands/formatNode';
4
+ import { transformNode } from './editor-commands/transformNode';
4
5
  import { createPlugin } from './pm-plugins/main';
5
6
  import BlockMenu from './ui/block-menu';
6
7
  import { getBlockMenuComponents } from './ui/block-menu-components';
@@ -33,6 +34,9 @@ export const blockMenuPlugin = ({
33
34
  commands: {
34
35
  formatNode: (targetType, analyticsAttrs) => {
35
36
  return formatNode(api)(targetType, analyticsAttrs);
37
+ },
38
+ transformNode: (targetType, analyticsAttrs) => {
39
+ return transformNode(api)(targetType, analyticsAttrs);
36
40
  }
37
41
  },
38
42
  getSharedState(editorState) {
@@ -0,0 +1,3 @@
1
+ export const stubStep = (nodes, context) => {
2
+ return nodes;
3
+ };
@@ -0,0 +1,79 @@
1
+ import { stubStep } from './stubStep';
2
+ import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
3
+
4
+ // Exampled step for overrides:
5
+ // - open Block menu on a paragraph, click 'Panel' in the Turn into'
6
+ // - expected to put paragraph into a panel
7
+ const wrapIntoPanelStep = (nodes, context) => {
8
+ const newNode = context.schema.nodes.panel.createAndFill({}, nodes);
9
+ return newNode ? [newNode] : [];
10
+ };
11
+
12
+ // Transform steps for combinations of node categories (block/container/list/text)
13
+ const TRANSFORM_STEPS = {
14
+ atomic: {
15
+ atomic: undefined,
16
+ container: [stubStep],
17
+ list: undefined,
18
+ text: undefined
19
+ },
20
+ container: {
21
+ atomic: undefined,
22
+ container: [stubStep],
23
+ list: undefined,
24
+ text: undefined
25
+ },
26
+ list: {
27
+ atomic: undefined,
28
+ container: [stubStep],
29
+ list: [stubStep],
30
+ text: [stubStep]
31
+ },
32
+ text: {
33
+ atomic: undefined,
34
+ container: [stubStep],
35
+ list: [stubStep],
36
+ text: [stubStep]
37
+ }
38
+ };
39
+
40
+ // Transform steps for specific pairs of node types that cannot be processed
41
+ // using generic rules/steps from TRANSFORM_STEPS.
42
+ const TRANSFORM_STEPS_OVERRIDE = {
43
+ paragraph: {
44
+ panel: [wrapIntoPanelStep]
45
+ }
46
+ };
47
+ const getTransformStepsForNodeTypes = (selectedNodeTypeName, targetNodeTypeName) => {
48
+ var _TRANSFORM_STEPS_OVER, _TRANSFORM_STEPS_OVER2;
49
+ const fromCategory = NODE_CATEGORY_BY_TYPE[selectedNodeTypeName];
50
+ const toCategory = NODE_CATEGORY_BY_TYPE[targetNodeTypeName];
51
+ const steps = (_TRANSFORM_STEPS_OVER = (_TRANSFORM_STEPS_OVER2 = TRANSFORM_STEPS_OVERRIDE[selectedNodeTypeName]) === null || _TRANSFORM_STEPS_OVER2 === void 0 ? void 0 : _TRANSFORM_STEPS_OVER2[targetNodeTypeName]) !== null && _TRANSFORM_STEPS_OVER !== void 0 ? _TRANSFORM_STEPS_OVER : TRANSFORM_STEPS[fromCategory][toCategory];
52
+ return steps;
53
+ };
54
+ // Note: Currently works only for single node in the selection
55
+ export const getOutputNodes = ({
56
+ sourceNode,
57
+ targetNodeType,
58
+ schema
59
+ }) => {
60
+ const nodesToReplace = [sourceNode];
61
+ const selectedNodeTypeName = toNodeTypeValue(sourceNode.type.name);
62
+ const targetNodeTypeName = toNodeTypeValue(targetNodeType.name);
63
+ if (!selectedNodeTypeName || !targetNodeTypeName) {
64
+ // We may decide to return an empty array or undefined here
65
+ return;
66
+ }
67
+ const steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
68
+ const context = {
69
+ fromNode: sourceNode,
70
+ targetNodeTypeName,
71
+ schema
72
+ };
73
+ if (!steps || steps.length === 0) {
74
+ return;
75
+ }
76
+ return steps.reduce((nodes, step) => {
77
+ return step(nodes, context);
78
+ }, nodesToReplace);
79
+ };
@@ -0,0 +1,27 @@
1
+ export const NODE_CATEGORY_BY_TYPE = {
2
+ blockquote: 'container',
3
+ blockCard: 'atomic',
4
+ bodiedExtension: 'atomic',
5
+ bulletList: 'list',
6
+ codeBlock: 'container',
7
+ decisionList: 'list',
8
+ embedCard: 'atomic',
9
+ expand: 'container',
10
+ extension: 'atomic',
11
+ heading: 'text',
12
+ layout: 'container',
13
+ media: 'atomic',
14
+ mediaGroup: 'atomic',
15
+ mediaSingle: 'atomic',
16
+ multiBodiedExtension: 'atomic',
17
+ orderedList: 'list',
18
+ panel: 'container',
19
+ paragraph: 'text',
20
+ nestedExpand: 'container',
21
+ taskList: 'list',
22
+ table: 'atomic'
23
+ };
24
+ export const isNodeTypeName = value => value in NODE_CATEGORY_BY_TYPE;
25
+ export const toNodeTypeValue = value => value && isNodeTypeName(value) ? value : null;
26
+
27
+ // Note: We are still deciding what should be in the context.
@@ -0,0 +1,44 @@
1
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
+ import { CellSelection } from '@atlaskit/editor-tables';
4
+ export const getSelectedNode = selection => {
5
+ if (selection instanceof NodeSelection) {
6
+ return {
7
+ node: selection.node,
8
+ pos: selection.$from.pos,
9
+ start: 0,
10
+ // ?
11
+ depth: selection.$from.depth
12
+ };
13
+ } else if (selection instanceof CellSelection) {
14
+ const tableSelected = findParentNodeOfType(selection.$from.doc.type.schema.nodes.table)(selection);
15
+ return tableSelected;
16
+ } else if (selection instanceof TextSelection) {
17
+ const {
18
+ blockquote,
19
+ bulletList,
20
+ orderedList,
21
+ taskList,
22
+ codeBlock,
23
+ paragraph,
24
+ heading
25
+ } = selection.$from.doc.type.schema.nodes;
26
+ const quoteSelected = findParentNodeOfType([blockquote])(selection);
27
+ if (quoteSelected) {
28
+ return quoteSelected;
29
+ }
30
+ const codeBlockSelected = findParentNodeOfType([codeBlock])(selection);
31
+ if (codeBlockSelected) {
32
+ return codeBlockSelected;
33
+ }
34
+ const listSelected = findParentNodeOfType([bulletList, taskList, orderedList])(selection);
35
+ if (listSelected) {
36
+ return listSelected;
37
+ }
38
+ const paragraphOrHeading = findParentNodeOfType([paragraph, heading])(selection);
39
+ if (paragraphOrHeading) {
40
+ return paragraphOrHeading;
41
+ }
42
+ }
43
+ return undefined;
44
+ };
@@ -0,0 +1,25 @@
1
+ import { getSelectedNode } from '../editor-commands/transform-node-utils/utils';
2
+ import { getOutputNodes } from './transform-node-utils/transform';
3
+ export const transformNode = api => (targetType, analyticsAttrs) => {
4
+ return ({
5
+ tr
6
+ }) => {
7
+ const {
8
+ selection
9
+ } = tr;
10
+ const source = getSelectedNode(selection);
11
+ if (!source) {
12
+ return tr;
13
+ }
14
+ const outputNodes = getOutputNodes({
15
+ sourceNode: source.node,
16
+ targetNodeType: targetType,
17
+ schema: selection.$from.doc.type.schema
18
+ });
19
+ if (!outputNodes) {
20
+ return tr;
21
+ }
22
+ tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
23
+ return tr;
24
+ };
25
+ };
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { createBlockMenuRegistry } from './editor-actions';
3
3
  import { formatNode as _formatNode } from './editor-commands/formatNode';
4
+ import { transformNode as _transformNode } from './editor-commands/transformNode';
4
5
  import { createPlugin } from './pm-plugins/main';
5
6
  import BlockMenu from './ui/block-menu';
6
7
  import { getBlockMenuComponents } from './ui/block-menu-components';
@@ -32,6 +33,9 @@ export var blockMenuPlugin = function blockMenuPlugin(_ref) {
32
33
  commands: {
33
34
  formatNode: function formatNode(targetType, analyticsAttrs) {
34
35
  return _formatNode(api)(targetType, analyticsAttrs);
36
+ },
37
+ transformNode: function transformNode(targetType, analyticsAttrs) {
38
+ return _transformNode(api)(targetType, analyticsAttrs);
35
39
  }
36
40
  },
37
41
  getSharedState: function getSharedState(editorState) {
@@ -0,0 +1,3 @@
1
+ export var stubStep = function stubStep(nodes, context) {
2
+ return nodes;
3
+ };
@@ -0,0 +1,78 @@
1
+ import { stubStep } from './stubStep';
2
+ import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
3
+
4
+ // Exampled step for overrides:
5
+ // - open Block menu on a paragraph, click 'Panel' in the Turn into'
6
+ // - expected to put paragraph into a panel
7
+ var wrapIntoPanelStep = function wrapIntoPanelStep(nodes, context) {
8
+ var newNode = context.schema.nodes.panel.createAndFill({}, nodes);
9
+ return newNode ? [newNode] : [];
10
+ };
11
+
12
+ // Transform steps for combinations of node categories (block/container/list/text)
13
+ var TRANSFORM_STEPS = {
14
+ atomic: {
15
+ atomic: undefined,
16
+ container: [stubStep],
17
+ list: undefined,
18
+ text: undefined
19
+ },
20
+ container: {
21
+ atomic: undefined,
22
+ container: [stubStep],
23
+ list: undefined,
24
+ text: undefined
25
+ },
26
+ list: {
27
+ atomic: undefined,
28
+ container: [stubStep],
29
+ list: [stubStep],
30
+ text: [stubStep]
31
+ },
32
+ text: {
33
+ atomic: undefined,
34
+ container: [stubStep],
35
+ list: [stubStep],
36
+ text: [stubStep]
37
+ }
38
+ };
39
+
40
+ // Transform steps for specific pairs of node types that cannot be processed
41
+ // using generic rules/steps from TRANSFORM_STEPS.
42
+ var TRANSFORM_STEPS_OVERRIDE = {
43
+ paragraph: {
44
+ panel: [wrapIntoPanelStep]
45
+ }
46
+ };
47
+ var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
48
+ var _TRANSFORM_STEPS_OVER, _TRANSFORM_STEPS_OVER2;
49
+ var fromCategory = NODE_CATEGORY_BY_TYPE[selectedNodeTypeName];
50
+ var toCategory = NODE_CATEGORY_BY_TYPE[targetNodeTypeName];
51
+ var steps = (_TRANSFORM_STEPS_OVER = (_TRANSFORM_STEPS_OVER2 = TRANSFORM_STEPS_OVERRIDE[selectedNodeTypeName]) === null || _TRANSFORM_STEPS_OVER2 === void 0 ? void 0 : _TRANSFORM_STEPS_OVER2[targetNodeTypeName]) !== null && _TRANSFORM_STEPS_OVER !== void 0 ? _TRANSFORM_STEPS_OVER : TRANSFORM_STEPS[fromCategory][toCategory];
52
+ return steps;
53
+ };
54
+ // Note: Currently works only for single node in the selection
55
+ export var getOutputNodes = function getOutputNodes(_ref) {
56
+ var sourceNode = _ref.sourceNode,
57
+ targetNodeType = _ref.targetNodeType,
58
+ schema = _ref.schema;
59
+ var nodesToReplace = [sourceNode];
60
+ var selectedNodeTypeName = toNodeTypeValue(sourceNode.type.name);
61
+ var targetNodeTypeName = toNodeTypeValue(targetNodeType.name);
62
+ if (!selectedNodeTypeName || !targetNodeTypeName) {
63
+ // We may decide to return an empty array or undefined here
64
+ return;
65
+ }
66
+ var steps = getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName);
67
+ var context = {
68
+ fromNode: sourceNode,
69
+ targetNodeTypeName: targetNodeTypeName,
70
+ schema: schema
71
+ };
72
+ if (!steps || steps.length === 0) {
73
+ return;
74
+ }
75
+ return steps.reduce(function (nodes, step) {
76
+ return step(nodes, context);
77
+ }, nodesToReplace);
78
+ };
@@ -0,0 +1,31 @@
1
+ export var NODE_CATEGORY_BY_TYPE = {
2
+ blockquote: 'container',
3
+ blockCard: 'atomic',
4
+ bodiedExtension: 'atomic',
5
+ bulletList: 'list',
6
+ codeBlock: 'container',
7
+ decisionList: 'list',
8
+ embedCard: 'atomic',
9
+ expand: 'container',
10
+ extension: 'atomic',
11
+ heading: 'text',
12
+ layout: 'container',
13
+ media: 'atomic',
14
+ mediaGroup: 'atomic',
15
+ mediaSingle: 'atomic',
16
+ multiBodiedExtension: 'atomic',
17
+ orderedList: 'list',
18
+ panel: 'container',
19
+ paragraph: 'text',
20
+ nestedExpand: 'container',
21
+ taskList: 'list',
22
+ table: 'atomic'
23
+ };
24
+ export var isNodeTypeName = function isNodeTypeName(value) {
25
+ return value in NODE_CATEGORY_BY_TYPE;
26
+ };
27
+ export var toNodeTypeValue = function toNodeTypeValue(value) {
28
+ return value && isNodeTypeName(value) ? value : null;
29
+ };
30
+
31
+ // Note: We are still deciding what should be in the context.
@@ -0,0 +1,43 @@
1
+ import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
+ import { CellSelection } from '@atlaskit/editor-tables';
4
+ export var getSelectedNode = function getSelectedNode(selection) {
5
+ if (selection instanceof NodeSelection) {
6
+ return {
7
+ node: selection.node,
8
+ pos: selection.$from.pos,
9
+ start: 0,
10
+ // ?
11
+ depth: selection.$from.depth
12
+ };
13
+ } else if (selection instanceof CellSelection) {
14
+ var tableSelected = findParentNodeOfType(selection.$from.doc.type.schema.nodes.table)(selection);
15
+ return tableSelected;
16
+ } else if (selection instanceof TextSelection) {
17
+ var _selection$$from$doc$ = selection.$from.doc.type.schema.nodes,
18
+ blockquote = _selection$$from$doc$.blockquote,
19
+ bulletList = _selection$$from$doc$.bulletList,
20
+ orderedList = _selection$$from$doc$.orderedList,
21
+ taskList = _selection$$from$doc$.taskList,
22
+ codeBlock = _selection$$from$doc$.codeBlock,
23
+ paragraph = _selection$$from$doc$.paragraph,
24
+ heading = _selection$$from$doc$.heading;
25
+ var quoteSelected = findParentNodeOfType([blockquote])(selection);
26
+ if (quoteSelected) {
27
+ return quoteSelected;
28
+ }
29
+ var codeBlockSelected = findParentNodeOfType([codeBlock])(selection);
30
+ if (codeBlockSelected) {
31
+ return codeBlockSelected;
32
+ }
33
+ var listSelected = findParentNodeOfType([bulletList, taskList, orderedList])(selection);
34
+ if (listSelected) {
35
+ return listSelected;
36
+ }
37
+ var paragraphOrHeading = findParentNodeOfType([paragraph, heading])(selection);
38
+ if (paragraphOrHeading) {
39
+ return paragraphOrHeading;
40
+ }
41
+ }
42
+ return undefined;
43
+ };
@@ -0,0 +1,24 @@
1
+ import { getSelectedNode } from '../editor-commands/transform-node-utils/utils';
2
+ import { getOutputNodes } from './transform-node-utils/transform';
3
+ export var transformNode = function transformNode(api) {
4
+ return function (targetType, analyticsAttrs) {
5
+ return function (_ref) {
6
+ var tr = _ref.tr;
7
+ var selection = tr.selection;
8
+ var source = getSelectedNode(selection);
9
+ if (!source) {
10
+ return tr;
11
+ }
12
+ var outputNodes = getOutputNodes({
13
+ sourceNode: source.node,
14
+ targetNodeType: targetType,
15
+ schema: selection.$from.doc.type.schema
16
+ });
17
+ if (!outputNodes) {
18
+ return tr;
19
+ }
20
+ tr.replaceWith(source.pos, source.pos + source.node.nodeSize, outputNodes);
21
+ return tr;
22
+ };
23
+ };
24
+ };
@@ -4,14 +4,18 @@ import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls
4
4
  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
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
7
8
  import type { FormatNodeTargetType, FormatNodeAnalyticsAttrs } from './editor-commands/transforms/types';
9
+ type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
10
+ type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
8
11
  export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
9
12
  actions: {
10
13
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
11
14
  registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
12
15
  };
13
16
  commands: {
14
- formatNode: (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
17
+ formatNode: FormatNodeCommand;
18
+ transformNode: TransformNodeCommand;
15
19
  };
16
20
  dependencies: [
17
21
  OptionalPlugin<BlockControlsPlugin>,
@@ -0,0 +1,2 @@
1
+ import type { TransformStep } from './types';
2
+ export declare const stubStep: TransformStep;
@@ -0,0 +1,8 @@
1
+ import type { Node as PMNode, NodeType, Schema } from '@atlaskit/editor-prosemirror/model';
2
+ interface GetOutputNodesArgs {
3
+ schema: Schema;
4
+ sourceNode: PMNode;
5
+ targetNodeType: NodeType;
6
+ }
7
+ export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, }: GetOutputNodesArgs) => PMNode[] | undefined;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
2
+ export type NodeTypeName = 'blockquote' | 'blockCard' | 'bodiedExtension' | 'bulletList' | 'codeBlock' | 'decisionList' | 'embedCard' | 'expand' | 'extension' | 'heading' | 'layout' | 'media' | 'mediaGroup' | 'mediaSingle' | 'multiBodiedExtension' | 'orderedList' | 'panel' | 'paragraph' | 'nestedExpand' | 'taskList' | 'table';
3
+ export type NodeCategory = 'atomic' | 'container' | 'list' | 'text';
4
+ export declare const NODE_CATEGORY_BY_TYPE: Record<NodeTypeName, NodeCategory>;
5
+ export declare const isNodeTypeName: (value: string) => value is NodeTypeName;
6
+ export declare const toNodeTypeValue: (value?: string | null) => NodeTypeName | null;
7
+ export type TransformStep = (nodes: PMNode[], context: TransformStepContext) => PMNode[];
8
+ export interface TransformStepContext {
9
+ fromNode: PMNode;
10
+ schema: Schema;
11
+ targetNodeTypeName: NodeTypeName;
12
+ }
@@ -0,0 +1,3 @@
1
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
3
+ export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
@@ -0,0 +1,5 @@
1
+ import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
3
+ import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
+ import type { FormatNodeAnalyticsAttrs } from './transforms/types';
5
+ export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
@@ -4,14 +4,18 @@ import type { BlockControlsPlugin } from '@atlaskit/editor-plugin-block-controls
4
4
  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
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
7
8
  import type { FormatNodeTargetType, FormatNodeAnalyticsAttrs } from './editor-commands/transforms/types';
9
+ type FormatNodeCommand = (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
10
+ type TransformNodeCommand = (targetType: NodeType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
8
11
  export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
9
12
  actions: {
10
13
  getBlockMenuComponents: () => Array<RegisterBlockMenuComponent>;
11
14
  registerBlockMenuComponents: (blockMenuComponents: Array<RegisterBlockMenuComponent>) => void;
12
15
  };
13
16
  commands: {
14
- formatNode: (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
17
+ formatNode: FormatNodeCommand;
18
+ transformNode: TransformNodeCommand;
15
19
  };
16
20
  dependencies: [
17
21
  OptionalPlugin<BlockControlsPlugin>,
@@ -0,0 +1,2 @@
1
+ import type { TransformStep } from './types';
2
+ export declare const stubStep: TransformStep;
@@ -0,0 +1,8 @@
1
+ import type { Node as PMNode, NodeType, Schema } from '@atlaskit/editor-prosemirror/model';
2
+ interface GetOutputNodesArgs {
3
+ schema: Schema;
4
+ sourceNode: PMNode;
5
+ targetNodeType: NodeType;
6
+ }
7
+ export declare const getOutputNodes: ({ sourceNode, targetNodeType, schema, }: GetOutputNodesArgs) => PMNode[] | undefined;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
2
+ export type NodeTypeName = 'blockquote' | 'blockCard' | 'bodiedExtension' | 'bulletList' | 'codeBlock' | 'decisionList' | 'embedCard' | 'expand' | 'extension' | 'heading' | 'layout' | 'media' | 'mediaGroup' | 'mediaSingle' | 'multiBodiedExtension' | 'orderedList' | 'panel' | 'paragraph' | 'nestedExpand' | 'taskList' | 'table';
3
+ export type NodeCategory = 'atomic' | 'container' | 'list' | 'text';
4
+ export declare const NODE_CATEGORY_BY_TYPE: Record<NodeTypeName, NodeCategory>;
5
+ export declare const isNodeTypeName: (value: string) => value is NodeTypeName;
6
+ export declare const toNodeTypeValue: (value?: string | null) => NodeTypeName | null;
7
+ export type TransformStep = (nodes: PMNode[], context: TransformStepContext) => PMNode[];
8
+ export interface TransformStepContext {
9
+ fromNode: PMNode;
10
+ schema: Schema;
11
+ targetNodeTypeName: NodeTypeName;
12
+ }
@@ -0,0 +1,3 @@
1
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { type ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
3
+ export declare const getSelectedNode: (selection: Selection) => ContentNodeWithPos | undefined;
@@ -0,0 +1,5 @@
1
+ import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
+ import type { NodeType } from '@atlaskit/editor-prosemirror/model';
3
+ import type { BlockMenuPlugin } from '../blockMenuPluginType';
4
+ import type { FormatNodeAnalyticsAttrs } from './transforms/types';
5
+ export declare const transformNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: NodeType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "5.0.15",
3
+ "version": "5.0.16",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -44,12 +44,12 @@
44
44
  "@atlaskit/platform-feature-flags": "^1.1.0",
45
45
  "@atlaskit/platform-feature-flags-react": "^0.4.0",
46
46
  "@atlaskit/primitives": "^16.2.0",
47
- "@atlaskit/tmp-editor-statsig": "^13.41.0",
47
+ "@atlaskit/tmp-editor-statsig": "^13.42.0",
48
48
  "@atlaskit/tokens": "^8.2.0",
49
49
  "@babel/runtime": "^7.0.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@atlaskit/editor-common": "^110.33.0",
52
+ "@atlaskit/editor-common": "^110.34.0",
53
53
  "react": "^18.2.0",
54
54
  "react-intl-next": "npm:react-intl@^5.18.1"
55
55
  },