@atlaskit/editor-plugin-block-menu 4.0.2 → 4.0.4
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.
- package/CHANGELOG.md +19 -0
- package/afm-dev-agents/tsconfig.json +3 -0
- package/afm-jira/tsconfig.json +3 -0
- package/afm-passionfruit/tsconfig.json +3 -0
- package/afm-post-office/tsconfig.json +3 -0
- package/afm-rovo-extension/tsconfig.json +3 -0
- package/afm-townsquare/tsconfig.json +3 -0
- package/dist/cjs/editor-commands/formatNode.js +59 -2
- package/dist/cjs/editor-commands/transforms/container-transforms.js +15 -1
- package/dist/cjs/ui/block-menu-renderer.js +46 -42
- package/dist/cjs/ui/block-menu.js +9 -5
- package/dist/cjs/ui/delete-button.js +14 -2
- package/dist/es2019/editor-commands/formatNode.js +61 -1
- package/dist/es2019/editor-commands/transforms/container-transforms.js +13 -1
- package/dist/es2019/ui/block-menu-renderer.js +46 -42
- package/dist/es2019/ui/block-menu.js +9 -5
- package/dist/es2019/ui/delete-button.js +15 -3
- package/dist/esm/editor-commands/formatNode.js +59 -1
- package/dist/esm/editor-commands/transforms/container-transforms.js +15 -1
- package/dist/esm/ui/block-menu-renderer.js +46 -42
- package/dist/esm/ui/block-menu.js +9 -5
- package/dist/esm/ui/delete-button.js +15 -3
- package/dist/types/editor-commands/formatNode.d.ts +10 -0
- package/dist/types-ts4.5/editor-commands/formatNode.d.ts +10 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 4.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`1eda79686167c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1eda79686167c) -
|
|
8
|
+
ED-29418: Fix empty code block convert to lists
|
|
9
|
+
- [`0778701e62192`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0778701e62192) -
|
|
10
|
+
[ux] ED-29424 Focus first menu item when block menu is opened and remove decorations when delete
|
|
11
|
+
button unmounts
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
14
|
+
## 4.0.3
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [`c158b1ba4f0fd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c158b1ba4f0fd) -
|
|
19
|
+
ED-29388: fix converting empty list
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 4.0.2
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
{
|
|
24
24
|
"path": "../../../design-system/dropdown-menu/afm-dev-agents/tsconfig.json"
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../../editor-plugin-analytics/afm-dev-agents/tsconfig.json"
|
|
28
|
+
},
|
|
26
29
|
{
|
|
27
30
|
"path": "../../editor-plugin-block-controls/afm-dev-agents/tsconfig.json"
|
|
28
31
|
},
|
package/afm-jira/tsconfig.json
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
{
|
|
24
24
|
"path": "../../../design-system/dropdown-menu/afm-passionfruit/tsconfig.json"
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../../editor-plugin-analytics/afm-passionfruit/tsconfig.json"
|
|
28
|
+
},
|
|
26
29
|
{
|
|
27
30
|
"path": "../../editor-plugin-block-controls/afm-passionfruit/tsconfig.json"
|
|
28
31
|
},
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
{
|
|
24
24
|
"path": "../../../design-system/dropdown-menu/afm-post-office/tsconfig.json"
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../../editor-plugin-analytics/afm-post-office/tsconfig.json"
|
|
28
|
+
},
|
|
26
29
|
{
|
|
27
30
|
"path": "../../editor-plugin-block-controls/afm-post-office/tsconfig.json"
|
|
28
31
|
},
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
{
|
|
24
24
|
"path": "../../../design-system/dropdown-menu/afm-rovo-extension/tsconfig.json"
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../../editor-plugin-analytics/afm-rovo-extension/tsconfig.json"
|
|
28
|
+
},
|
|
26
29
|
{
|
|
27
30
|
"path": "../../editor-plugin-block-controls/afm-rovo-extension/tsconfig.json"
|
|
28
31
|
},
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
{
|
|
24
24
|
"path": "../../../design-system/dropdown-menu/afm-townsquare/tsconfig.json"
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../../editor-plugin-analytics/afm-townsquare/tsconfig.json"
|
|
28
|
+
},
|
|
26
29
|
{
|
|
27
30
|
"path": "../../editor-plugin-block-controls/afm-townsquare/tsconfig.json"
|
|
28
31
|
},
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.formatNode = void 0;
|
|
6
|
+
exports.formatNodeSelectEmptyList = exports.formatNode = void 0;
|
|
7
7
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
8
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
9
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
9
10
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
10
11
|
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
|
|
11
12
|
var _selection = require("./selection");
|
|
12
13
|
var _layoutTransforms = require("./transforms/layout-transforms");
|
|
13
14
|
var _transformNodeToTargetType = require("./transforms/transformNodeToTargetType");
|
|
15
|
+
var _utils2 = require("./transforms/utils");
|
|
14
16
|
/**
|
|
15
17
|
* Handles formatting when selection is empty by inserting a new target node
|
|
16
18
|
*/
|
|
@@ -50,6 +52,42 @@ var formatNodeWhenSelectionEmpty = function formatNodeWhenSelectionEmpty(tr, tar
|
|
|
50
52
|
return tr;
|
|
51
53
|
};
|
|
52
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Handles formatting when an empty list is selected
|
|
57
|
+
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
58
|
+
*/
|
|
59
|
+
var formatNodeSelectEmptyList = exports.formatNodeSelectEmptyList = function formatNodeSelectEmptyList(tr, targetType, listNode, schema) {
|
|
60
|
+
var nodes = schema.nodes;
|
|
61
|
+
var headingLevel = 1;
|
|
62
|
+
var finalTargetType = targetType;
|
|
63
|
+
if (targetType.startsWith('heading')) {
|
|
64
|
+
var levelString = targetType.slice(-1);
|
|
65
|
+
var level = parseInt(levelString, 10);
|
|
66
|
+
if (!isNaN(level) && level >= 1 && level <= 6) {
|
|
67
|
+
headingLevel = level;
|
|
68
|
+
finalTargetType = 'heading';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var replaceNode = null;
|
|
72
|
+
if (finalTargetType === 'layoutSection') {
|
|
73
|
+
var emptyPara = nodes.paragraph.createAndFill();
|
|
74
|
+
if (emptyPara) {
|
|
75
|
+
replaceNode = (0, _layoutTransforms.createDefaultLayoutSection)(schema, emptyPara);
|
|
76
|
+
}
|
|
77
|
+
} else if (finalTargetType === 'heading') {
|
|
78
|
+
replaceNode = nodes.heading.createAndFill({
|
|
79
|
+
level: headingLevel
|
|
80
|
+
});
|
|
81
|
+
} else {
|
|
82
|
+
replaceNode = nodes[finalTargetType].createAndFill();
|
|
83
|
+
}
|
|
84
|
+
if (replaceNode) {
|
|
85
|
+
tr.replaceWith(listNode.pos, listNode.pos + listNode.node.nodeSize, replaceNode);
|
|
86
|
+
tr.setSelection(new _state.TextSelection(tr.doc.resolve(listNode.pos)));
|
|
87
|
+
}
|
|
88
|
+
return tr;
|
|
89
|
+
};
|
|
90
|
+
|
|
53
91
|
/**
|
|
54
92
|
* Formats the current node or selection to the specified target type
|
|
55
93
|
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
@@ -69,7 +107,26 @@ var formatNode = exports.formatNode = function formatNode(api) {
|
|
|
69
107
|
|
|
70
108
|
// when selection is empty, we insert a empty target node
|
|
71
109
|
if (selection.empty && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true)) {
|
|
72
|
-
|
|
110
|
+
var listNodes = [];
|
|
111
|
+
// need to find if there is any list node in the current selection
|
|
112
|
+
// As when select a empty list, selection is empty, but we want to convert the list instead of inserting a target node
|
|
113
|
+
// findSelectedNodeOfType does not work when selection is empty, so we use nodesBetween
|
|
114
|
+
tr.doc.nodesBetween(selection.from, selection.to, function (node, pos) {
|
|
115
|
+
if ((0, _utils2.isListNodeType)(node.type)) {
|
|
116
|
+
listNodes.push({
|
|
117
|
+
node: node,
|
|
118
|
+
pos: pos
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// get the first list node as when click on drag handle if there are list node
|
|
123
|
+
// can only select one list at a time, so we just need to find the first one
|
|
124
|
+
if (listNodes.length > 0 && (0, _platformFeatureFlags.fg)('platform_editor_block_menu_patch_2')) {
|
|
125
|
+
var firstChild = listNodes[0];
|
|
126
|
+
return formatNodeSelectEmptyList(tr, targetType, firstChild, schema);
|
|
127
|
+
} else {
|
|
128
|
+
return formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema);
|
|
129
|
+
}
|
|
73
130
|
}
|
|
74
131
|
|
|
75
132
|
// Try to find the current node from selection
|
|
@@ -8,6 +8,7 @@ exports.unwrapAndConvertToList = exports.unwrapAndConvertToBlockType = exports.t
|
|
|
8
8
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
9
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
10
10
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
11
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
11
12
|
var _inlineNodeTransforms = require("./inline-node-transforms");
|
|
12
13
|
var _utils2 = require("./utils");
|
|
13
14
|
var convertInvalidNodeToValidNodeType = function convertInvalidNodeToValidNodeType(sourceContent, sourceNodeType, validNodeType, withMarks) {
|
|
@@ -203,7 +204,11 @@ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAnd
|
|
|
203
204
|
heading = _schema$nodes2.heading;
|
|
204
205
|
var isTargetTaskList = targetNodeType === taskList;
|
|
205
206
|
var createListItemFromInline = function createListItemFromInline(content) {
|
|
206
|
-
|
|
207
|
+
if (!content && (0, _platformFeatureFlags.fg)('platform_editor_block_menu_patch_2')) {
|
|
208
|
+
return isTargetTaskList ? taskItem.create() : listItem.create(null, paragraph.create());
|
|
209
|
+
} else {
|
|
210
|
+
return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
|
|
211
|
+
}
|
|
207
212
|
};
|
|
208
213
|
var getInlineContent = function getInlineContent(textblock) {
|
|
209
214
|
var inlineContent = [];
|
|
@@ -233,6 +238,15 @@ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAnd
|
|
|
233
238
|
};
|
|
234
239
|
if (sourceNode.type.name === 'codeBlock') {
|
|
235
240
|
var codeText = sourceNode.textContent;
|
|
241
|
+
// check if code block only contains newline characters
|
|
242
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
243
|
+
var isOnlyNewLines = function isOnlyNewLines(codeText) {
|
|
244
|
+
return codeText.replace(/\n/g, '').trim() === '';
|
|
245
|
+
};
|
|
246
|
+
if ((!codeText || isOnlyNewLines(codeText)) && (0, _platformFeatureFlags.fg)('platform_editor_block_menu_patch_2')) {
|
|
247
|
+
// Empty code block - create an empty list item
|
|
248
|
+
currentListItems.push(createListItemFromInline());
|
|
249
|
+
}
|
|
236
250
|
if (codeText) {
|
|
237
251
|
var lines = codeText.split('\n');
|
|
238
252
|
// Remove empty lines
|
|
@@ -9,6 +9,7 @@ exports.BlockMenuRenderer = void 0;
|
|
|
9
9
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _uiMenu = require("@atlaskit/editor-common/ui-menu");
|
|
12
|
+
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
|
|
12
13
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
13
14
|
var NoOp = function NoOp(props) {
|
|
14
15
|
return null;
|
|
@@ -50,48 +51,51 @@ var BlockMenuRenderer = exports.BlockMenuRenderer = function BlockMenuRenderer(_
|
|
|
50
51
|
var menuSections = getSortedNonNestedSections(components);
|
|
51
52
|
var menuItems = components.filter(isMenuItem);
|
|
52
53
|
var nestedMenus = components.filter(isNestedMenu);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
54
|
+
var renderMenu = function renderMenu() {
|
|
55
|
+
return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, menuSections.map(function (section) {
|
|
56
|
+
// Get all items for the current section, including nested menus, and sort them by rank
|
|
57
|
+
var currentSectionItemsSorted = getSortedChildren([].concat((0, _toConsumableArray2.default)(menuItems), (0, _toConsumableArray2.default)(nestedMenus)), section.key);
|
|
58
|
+
if (currentSectionItemsSorted.length === 0) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
// iterate over the current section items, if it is nested menu, get their children, sort them
|
|
63
|
+
// if they are menu items, just render as they are sorted above
|
|
64
|
+
var getChildrenWithNestedItems = function getChildrenWithNestedItems(items) {
|
|
65
|
+
return items.map(function (item) {
|
|
66
|
+
if (isNestedMenu(item)) {
|
|
67
|
+
var sortedNestedSections = getSortedNestedSections(components, item.key);
|
|
68
|
+
return sortedNestedSections.map(function (section) {
|
|
69
|
+
var sortedNestedMenuItems = getSortedChildren(menuItems, section.key);
|
|
70
|
+
var NestedMenuComponent = item.component || fallbacks.nestedMenu || NoOp;
|
|
71
|
+
var NestedSection = section.component || fallbacks.section || NoOp;
|
|
72
|
+
return /*#__PURE__*/_react.default.createElement(NestedMenuComponent, {
|
|
73
|
+
key: item.key
|
|
74
|
+
}, /*#__PURE__*/_react.default.createElement(NestedSection, {
|
|
75
|
+
key: section.key
|
|
76
|
+
}, sortedNestedMenuItems.map(function (nestedItem) {
|
|
77
|
+
var NestedMenuItemComponent = nestedItem.component || fallbacks.item || NoOp;
|
|
78
|
+
return /*#__PURE__*/_react.default.createElement(NestedMenuItemComponent, {
|
|
79
|
+
key: nestedItem.key
|
|
80
|
+
});
|
|
81
|
+
})));
|
|
82
|
+
});
|
|
83
|
+
} else {
|
|
84
|
+
var ItemComponent = item.component || fallbacks.item || NoOp;
|
|
85
|
+
return /*#__PURE__*/_react.default.createElement(ItemComponent, {
|
|
73
86
|
key: item.key
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
var children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
92
|
-
var SectionComponent = section.component || fallbacks.section || NoOp;
|
|
93
|
-
return /*#__PURE__*/_react.default.createElement(SectionComponent, {
|
|
94
|
-
key: section.key
|
|
95
|
-
}, children);
|
|
96
|
-
})));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
var children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
92
|
+
var SectionComponent = section.component || fallbacks.section || NoOp;
|
|
93
|
+
return /*#__PURE__*/_react.default.createElement(SectionComponent, {
|
|
94
|
+
key: section.key
|
|
95
|
+
}, children);
|
|
96
|
+
}));
|
|
97
|
+
};
|
|
98
|
+
return (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? /*#__PURE__*/_react.default.createElement(_uiMenu.ArrowKeyNavigationProvider, {
|
|
99
|
+
type: _uiMenu.ArrowKeyNavigationType.MENU
|
|
100
|
+
}, renderMenu()) : renderMenu();
|
|
97
101
|
};
|
|
@@ -64,18 +64,20 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
64
64
|
boundariesElement = _ref2.boundariesElement,
|
|
65
65
|
scrollableElement = _ref2.scrollableElement;
|
|
66
66
|
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls', 'userIntent'], function (states) {
|
|
67
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta;
|
|
67
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
|
|
68
68
|
return {
|
|
69
69
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
70
70
|
isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
|
|
71
71
|
isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
|
|
72
|
-
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent
|
|
72
|
+
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
73
|
+
openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 || (_states$blockControls4 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.openedViaKeyboard
|
|
73
74
|
};
|
|
74
75
|
}),
|
|
75
76
|
menuTriggerBy = _useSharedPluginState.menuTriggerBy,
|
|
76
77
|
isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
|
|
77
78
|
isMenuOpen = _useSharedPluginState.isMenuOpen,
|
|
78
|
-
currentUserIntent = _useSharedPluginState.currentUserIntent
|
|
79
|
+
currentUserIntent = _useSharedPluginState.currentUserIntent,
|
|
80
|
+
openedViaKeyboard = _useSharedPluginState.openedViaKeyboard;
|
|
79
81
|
var _useBlockMenu = (0, _blockMenuProvider.useBlockMenu)(),
|
|
80
82
|
onDropdownOpenChanged = _useBlockMenu.onDropdownOpenChanged,
|
|
81
83
|
fireAnalyticsEvent = _useBlockMenu.fireAnalyticsEvent;
|
|
@@ -86,7 +88,7 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
86
88
|
// hasSelection true, always show block menu
|
|
87
89
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
88
90
|
var shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
89
|
-
var selectedByShortcutORDragHandle = isSelectedViaDragHandle;
|
|
91
|
+
var selectedByShortcutORDragHandle = isSelectedViaDragHandle || openedViaKeyboard && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
90
92
|
(0, _react.useEffect)(function () {
|
|
91
93
|
var _api$userIntent;
|
|
92
94
|
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutORDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
@@ -149,7 +151,9 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
149
151
|
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
150
152
|
,
|
|
151
153
|
stick: true,
|
|
152
|
-
focusTrap: true
|
|
154
|
+
focusTrap: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? openedViaKeyboard ? {
|
|
155
|
+
initialFocus: undefined
|
|
156
|
+
} : true : undefined,
|
|
153
157
|
offset: [_styles.DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
154
158
|
}, /*#__PURE__*/_react.default.createElement(BlockMenuContent, {
|
|
155
159
|
api: api
|
|
@@ -78,10 +78,22 @@ var DeleteDropdownItemContent = function DeleteDropdownItemContent(_ref) {
|
|
|
78
78
|
return tr;
|
|
79
79
|
});
|
|
80
80
|
}, [api, nodeTypes]);
|
|
81
|
-
var onRemoveHoverDecoration = function
|
|
81
|
+
var onRemoveHoverDecoration = (0, _react.useCallback)(function () {
|
|
82
82
|
var _api$decorations2, _api$decorations2$rem;
|
|
83
83
|
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$decorations2 = api.decorations) === null || _api$decorations2 === void 0 || (_api$decorations2 = _api$decorations2.commands) === null || _api$decorations2 === void 0 || (_api$decorations2$rem = _api$decorations2.removeDecoration) === null || _api$decorations2$rem === void 0 ? void 0 : _api$decorations2$rem.call(_api$decorations2));
|
|
84
|
-
};
|
|
84
|
+
}, [api]);
|
|
85
|
+
(0, _react.useEffect)(function () {
|
|
86
|
+
if (!(0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
return function () {
|
|
90
|
+
if (!(0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// clean up hover decoration when unmounting
|
|
94
|
+
onRemoveHoverDecoration();
|
|
95
|
+
};
|
|
96
|
+
}, [onRemoveHoverDecoration]);
|
|
85
97
|
var text = (0, _platformFeatureFlags.fg)('platform_editor_block_menu_patch_1') ? formatMessage(_messages.blockMenuMessages.deleteBlock) : formatMessage(_blockMenu.messages.deleteBlock);
|
|
86
98
|
return /*#__PURE__*/_react.default.createElement(_box.Box, {
|
|
87
99
|
onMouseEnter: onShowHoverDecoration,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { findParentNodeOfType, findSelectedNodeOfType, safeInsert as pmSafeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
5
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
5
6
|
import { setSelectionAfterTransform } from './selection';
|
|
6
7
|
import { createDefaultLayoutSection } from './transforms/layout-transforms';
|
|
7
8
|
import { transformNodeToTargetType } from './transforms/transformNodeToTargetType';
|
|
9
|
+
import { isListNodeType } from './transforms/utils';
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Handles formatting when selection is empty by inserting a new target node
|
|
10
13
|
*/
|
|
@@ -48,6 +51,44 @@ const formatNodeWhenSelectionEmpty = (tr, targetType, nodePos, schema) => {
|
|
|
48
51
|
return tr;
|
|
49
52
|
};
|
|
50
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Handles formatting when an empty list is selected
|
|
56
|
+
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
57
|
+
*/
|
|
58
|
+
export const formatNodeSelectEmptyList = (tr, targetType, listNode, schema) => {
|
|
59
|
+
const {
|
|
60
|
+
nodes
|
|
61
|
+
} = schema;
|
|
62
|
+
let headingLevel = 1;
|
|
63
|
+
let finalTargetType = targetType;
|
|
64
|
+
if (targetType.startsWith('heading')) {
|
|
65
|
+
const levelString = targetType.slice(-1);
|
|
66
|
+
const level = parseInt(levelString, 10);
|
|
67
|
+
if (!isNaN(level) && level >= 1 && level <= 6) {
|
|
68
|
+
headingLevel = level;
|
|
69
|
+
finalTargetType = 'heading';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let replaceNode = null;
|
|
73
|
+
if (finalTargetType === 'layoutSection') {
|
|
74
|
+
const emptyPara = nodes.paragraph.createAndFill();
|
|
75
|
+
if (emptyPara) {
|
|
76
|
+
replaceNode = createDefaultLayoutSection(schema, emptyPara);
|
|
77
|
+
}
|
|
78
|
+
} else if (finalTargetType === 'heading') {
|
|
79
|
+
replaceNode = nodes.heading.createAndFill({
|
|
80
|
+
level: headingLevel
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
replaceNode = nodes[finalTargetType].createAndFill();
|
|
84
|
+
}
|
|
85
|
+
if (replaceNode) {
|
|
86
|
+
tr.replaceWith(listNode.pos, listNode.pos + listNode.node.nodeSize, replaceNode);
|
|
87
|
+
tr.setSelection(new TextSelection(tr.doc.resolve(listNode.pos)));
|
|
88
|
+
}
|
|
89
|
+
return tr;
|
|
90
|
+
};
|
|
91
|
+
|
|
51
92
|
/**
|
|
52
93
|
* Formats the current node or selection to the specified target type
|
|
53
94
|
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
@@ -71,7 +112,26 @@ export const formatNode = api => targetType => {
|
|
|
71
112
|
|
|
72
113
|
// when selection is empty, we insert a empty target node
|
|
73
114
|
if (selection.empty && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true)) {
|
|
74
|
-
|
|
115
|
+
const listNodes = [];
|
|
116
|
+
// need to find if there is any list node in the current selection
|
|
117
|
+
// As when select a empty list, selection is empty, but we want to convert the list instead of inserting a target node
|
|
118
|
+
// findSelectedNodeOfType does not work when selection is empty, so we use nodesBetween
|
|
119
|
+
tr.doc.nodesBetween(selection.from, selection.to, (node, pos) => {
|
|
120
|
+
if (isListNodeType(node.type)) {
|
|
121
|
+
listNodes.push({
|
|
122
|
+
node,
|
|
123
|
+
pos
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// get the first list node as when click on drag handle if there are list node
|
|
128
|
+
// can only select one list at a time, so we just need to find the first one
|
|
129
|
+
if (listNodes.length > 0 && fg('platform_editor_block_menu_patch_2')) {
|
|
130
|
+
const firstChild = listNodes[0];
|
|
131
|
+
return formatNodeSelectEmptyList(tr, targetType, firstChild, schema);
|
|
132
|
+
} else {
|
|
133
|
+
return formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema);
|
|
134
|
+
}
|
|
75
135
|
}
|
|
76
136
|
|
|
77
137
|
// Try to find the current node from selection
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
2
2
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
4
|
import { getInlineNodeTextContent } from './inline-node-transforms';
|
|
4
5
|
import { isBlockNodeType, isListNodeType, isContainerNodeType, isBlockNodeForExtraction, convertNodeToInlineContent, getContentSupportChecker, convertCodeBlockContentToParagraphs, filterMarksForTargetNodeType, getMarksWithBreakout } from './utils';
|
|
5
6
|
const convertInvalidNodeToValidNodeType = (sourceContent, sourceNodeType, validNodeType, withMarks) => {
|
|
@@ -204,7 +205,11 @@ export const unwrapAndConvertToList = ({
|
|
|
204
205
|
} = schema.nodes;
|
|
205
206
|
const isTargetTaskList = targetNodeType === taskList;
|
|
206
207
|
const createListItemFromInline = content => {
|
|
207
|
-
|
|
208
|
+
if (!content && fg('platform_editor_block_menu_patch_2')) {
|
|
209
|
+
return isTargetTaskList ? taskItem.create() : listItem.create(null, paragraph.create());
|
|
210
|
+
} else {
|
|
211
|
+
return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
|
|
212
|
+
}
|
|
208
213
|
};
|
|
209
214
|
const getInlineContent = textblock => {
|
|
210
215
|
const inlineContent = [];
|
|
@@ -234,6 +239,13 @@ export const unwrapAndConvertToList = ({
|
|
|
234
239
|
};
|
|
235
240
|
if (sourceNode.type.name === 'codeBlock') {
|
|
236
241
|
const codeText = sourceNode.textContent;
|
|
242
|
+
// check if code block only contains newline characters
|
|
243
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
244
|
+
const isOnlyNewLines = codeText => codeText.replace(/\n/g, '').trim() === '';
|
|
245
|
+
if ((!codeText || isOnlyNewLines(codeText)) && fg('platform_editor_block_menu_patch_2')) {
|
|
246
|
+
// Empty code block - create an empty list item
|
|
247
|
+
currentListItems.push(createListItemFromInline());
|
|
248
|
+
}
|
|
237
249
|
if (codeText) {
|
|
238
250
|
const lines = codeText.split('\n');
|
|
239
251
|
// Remove empty lines
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { Fragment } from 'react';
|
|
2
2
|
import { ArrowKeyNavigationProvider, ArrowKeyNavigationType } from '@atlaskit/editor-common/ui-menu';
|
|
3
|
+
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
3
4
|
const NoOp = props => null;
|
|
4
5
|
const isNonNestedMenuSection = component => {
|
|
5
6
|
return component.type === 'block-menu-section' && !('parent' in component);
|
|
@@ -29,48 +30,51 @@ export const BlockMenuRenderer = ({
|
|
|
29
30
|
const menuSections = getSortedNonNestedSections(components);
|
|
30
31
|
const menuItems = components.filter(isMenuItem);
|
|
31
32
|
const nestedMenus = components.filter(isNestedMenu);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
33
|
+
const renderMenu = () => {
|
|
34
|
+
return /*#__PURE__*/React.createElement(Fragment, null, menuSections.map(section => {
|
|
35
|
+
// Get all items for the current section, including nested menus, and sort them by rank
|
|
36
|
+
const currentSectionItemsSorted = getSortedChildren([...menuItems, ...nestedMenus], section.key);
|
|
37
|
+
if (currentSectionItemsSorted.length === 0) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
// iterate over the current section items, if it is nested menu, get their children, sort them
|
|
42
|
+
// if they are menu items, just render as they are sorted above
|
|
43
|
+
const getChildrenWithNestedItems = items => {
|
|
44
|
+
return items.map(item => {
|
|
45
|
+
if (isNestedMenu(item)) {
|
|
46
|
+
const sortedNestedSections = getSortedNestedSections(components, item.key);
|
|
47
|
+
return sortedNestedSections.map(section => {
|
|
48
|
+
const sortedNestedMenuItems = getSortedChildren(menuItems, section.key);
|
|
49
|
+
const NestedMenuComponent = item.component || fallbacks.nestedMenu || NoOp;
|
|
50
|
+
const NestedSection = section.component || fallbacks.section || NoOp;
|
|
51
|
+
return /*#__PURE__*/React.createElement(NestedMenuComponent, {
|
|
52
|
+
key: item.key
|
|
53
|
+
}, /*#__PURE__*/React.createElement(NestedSection, {
|
|
54
|
+
key: section.key
|
|
55
|
+
}, sortedNestedMenuItems.map(nestedItem => {
|
|
56
|
+
const NestedMenuItemComponent = nestedItem.component || fallbacks.item || NoOp;
|
|
57
|
+
return /*#__PURE__*/React.createElement(NestedMenuItemComponent, {
|
|
58
|
+
key: nestedItem.key
|
|
59
|
+
});
|
|
60
|
+
})));
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
const ItemComponent = item.component || fallbacks.item || NoOp;
|
|
64
|
+
return /*#__PURE__*/React.createElement(ItemComponent, {
|
|
52
65
|
key: item.key
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
const children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
71
|
-
const SectionComponent = section.component || fallbacks.section || NoOp;
|
|
72
|
-
return /*#__PURE__*/React.createElement(SectionComponent, {
|
|
73
|
-
key: section.key
|
|
74
|
-
}, children);
|
|
75
|
-
})));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
71
|
+
const SectionComponent = section.component || fallbacks.section || NoOp;
|
|
72
|
+
return /*#__PURE__*/React.createElement(SectionComponent, {
|
|
73
|
+
key: section.key
|
|
74
|
+
}, children);
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
return expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? /*#__PURE__*/React.createElement(ArrowKeyNavigationProvider, {
|
|
78
|
+
type: ArrowKeyNavigationType.MENU
|
|
79
|
+
}, renderMenu()) : renderMenu();
|
|
76
80
|
};
|
|
@@ -55,14 +55,16 @@ const BlockMenu = ({
|
|
|
55
55
|
menuTriggerBy,
|
|
56
56
|
isSelectedViaDragHandle,
|
|
57
57
|
isMenuOpen,
|
|
58
|
-
currentUserIntent
|
|
58
|
+
currentUserIntent,
|
|
59
|
+
openedViaKeyboard
|
|
59
60
|
} = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], states => {
|
|
60
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta;
|
|
61
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4, _states$blockControls5;
|
|
61
62
|
return {
|
|
62
63
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
63
64
|
isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
|
|
64
65
|
isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
|
|
65
|
-
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent
|
|
66
|
+
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
67
|
+
openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : (_states$blockControls5 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
|
|
66
68
|
};
|
|
67
69
|
});
|
|
68
70
|
const {
|
|
@@ -76,7 +78,7 @@ const BlockMenu = ({
|
|
|
76
78
|
// hasSelection true, always show block menu
|
|
77
79
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
78
80
|
const shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
79
|
-
const selectedByShortcutORDragHandle = isSelectedViaDragHandle;
|
|
81
|
+
const selectedByShortcutORDragHandle = isSelectedViaDragHandle || openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
80
82
|
useEffect(() => {
|
|
81
83
|
var _api$userIntent;
|
|
82
84
|
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutORDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
@@ -140,7 +142,9 @@ const BlockMenu = ({
|
|
|
140
142
|
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
141
143
|
,
|
|
142
144
|
stick: true,
|
|
143
|
-
focusTrap: true
|
|
145
|
+
focusTrap: expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? openedViaKeyboard ? {
|
|
146
|
+
initialFocus: undefined
|
|
147
|
+
} : true : undefined,
|
|
144
148
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
145
149
|
}, /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
146
150
|
api: api
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect } from 'react';
|
|
2
2
|
import { useIntl, injectIntl } from 'react-intl-next';
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { messages } from '@atlaskit/editor-common/block-menu';
|
|
@@ -74,10 +74,22 @@ const DeleteDropdownItemContent = ({
|
|
|
74
74
|
return tr;
|
|
75
75
|
});
|
|
76
76
|
}, [api, nodeTypes]);
|
|
77
|
-
const onRemoveHoverDecoration = () => {
|
|
77
|
+
const onRemoveHoverDecoration = useCallback(() => {
|
|
78
78
|
var _api$decorations2, _api$decorations2$com, _api$decorations2$com2;
|
|
79
79
|
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$decorations2 = api.decorations) === null || _api$decorations2 === void 0 ? void 0 : (_api$decorations2$com = _api$decorations2.commands) === null || _api$decorations2$com === void 0 ? void 0 : (_api$decorations2$com2 = _api$decorations2$com.removeDecoration) === null || _api$decorations2$com2 === void 0 ? void 0 : _api$decorations2$com2.call(_api$decorations2$com));
|
|
80
|
-
};
|
|
80
|
+
}, [api]);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (!expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
return () => {
|
|
86
|
+
if (!expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// clean up hover decoration when unmounting
|
|
90
|
+
onRemoveHoverDecoration();
|
|
91
|
+
};
|
|
92
|
+
}, [onRemoveHoverDecoration]);
|
|
81
93
|
const text = fg('platform_editor_block_menu_patch_1') ? formatMessage(blockMenuMessages.deleteBlock) : formatMessage(messages.deleteBlock);
|
|
82
94
|
return /*#__PURE__*/React.createElement(Box, {
|
|
83
95
|
onMouseEnter: onShowHoverDecoration,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { findParentNodeOfType, findSelectedNodeOfType, safeInsert as pmSafeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
3
4
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
5
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
5
6
|
import { setSelectionAfterTransform } from './selection';
|
|
6
7
|
import { createDefaultLayoutSection } from './transforms/layout-transforms';
|
|
7
8
|
import { transformNodeToTargetType } from './transforms/transformNodeToTargetType';
|
|
9
|
+
import { isListNodeType } from './transforms/utils';
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Handles formatting when selection is empty by inserting a new target node
|
|
10
13
|
*/
|
|
@@ -44,6 +47,42 @@ var formatNodeWhenSelectionEmpty = function formatNodeWhenSelectionEmpty(tr, tar
|
|
|
44
47
|
return tr;
|
|
45
48
|
};
|
|
46
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Handles formatting when an empty list is selected
|
|
52
|
+
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
53
|
+
*/
|
|
54
|
+
export var formatNodeSelectEmptyList = function formatNodeSelectEmptyList(tr, targetType, listNode, schema) {
|
|
55
|
+
var nodes = schema.nodes;
|
|
56
|
+
var headingLevel = 1;
|
|
57
|
+
var finalTargetType = targetType;
|
|
58
|
+
if (targetType.startsWith('heading')) {
|
|
59
|
+
var levelString = targetType.slice(-1);
|
|
60
|
+
var level = parseInt(levelString, 10);
|
|
61
|
+
if (!isNaN(level) && level >= 1 && level <= 6) {
|
|
62
|
+
headingLevel = level;
|
|
63
|
+
finalTargetType = 'heading';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
var replaceNode = null;
|
|
67
|
+
if (finalTargetType === 'layoutSection') {
|
|
68
|
+
var emptyPara = nodes.paragraph.createAndFill();
|
|
69
|
+
if (emptyPara) {
|
|
70
|
+
replaceNode = createDefaultLayoutSection(schema, emptyPara);
|
|
71
|
+
}
|
|
72
|
+
} else if (finalTargetType === 'heading') {
|
|
73
|
+
replaceNode = nodes.heading.createAndFill({
|
|
74
|
+
level: headingLevel
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
replaceNode = nodes[finalTargetType].createAndFill();
|
|
78
|
+
}
|
|
79
|
+
if (replaceNode) {
|
|
80
|
+
tr.replaceWith(listNode.pos, listNode.pos + listNode.node.nodeSize, replaceNode);
|
|
81
|
+
tr.setSelection(new TextSelection(tr.doc.resolve(listNode.pos)));
|
|
82
|
+
}
|
|
83
|
+
return tr;
|
|
84
|
+
};
|
|
85
|
+
|
|
47
86
|
/**
|
|
48
87
|
* Formats the current node or selection to the specified target type
|
|
49
88
|
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
@@ -63,7 +102,26 @@ export var formatNode = function formatNode(api) {
|
|
|
63
102
|
|
|
64
103
|
// when selection is empty, we insert a empty target node
|
|
65
104
|
if (selection.empty && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true)) {
|
|
66
|
-
|
|
105
|
+
var listNodes = [];
|
|
106
|
+
// need to find if there is any list node in the current selection
|
|
107
|
+
// As when select a empty list, selection is empty, but we want to convert the list instead of inserting a target node
|
|
108
|
+
// findSelectedNodeOfType does not work when selection is empty, so we use nodesBetween
|
|
109
|
+
tr.doc.nodesBetween(selection.from, selection.to, function (node, pos) {
|
|
110
|
+
if (isListNodeType(node.type)) {
|
|
111
|
+
listNodes.push({
|
|
112
|
+
node: node,
|
|
113
|
+
pos: pos
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// get the first list node as when click on drag handle if there are list node
|
|
118
|
+
// can only select one list at a time, so we just need to find the first one
|
|
119
|
+
if (listNodes.length > 0 && fg('platform_editor_block_menu_patch_2')) {
|
|
120
|
+
var firstChild = listNodes[0];
|
|
121
|
+
return formatNodeSelectEmptyList(tr, targetType, firstChild, schema);
|
|
122
|
+
} else {
|
|
123
|
+
return formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema);
|
|
124
|
+
}
|
|
67
125
|
}
|
|
68
126
|
|
|
69
127
|
// Try to find the current node from selection
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
2
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
4
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
5
|
import { getInlineNodeTextContent } from './inline-node-transforms';
|
|
5
6
|
import { isBlockNodeType, isListNodeType, isContainerNodeType, isBlockNodeForExtraction, convertNodeToInlineContent, getContentSupportChecker, convertCodeBlockContentToParagraphs, filterMarksForTargetNodeType, getMarksWithBreakout } from './utils';
|
|
6
7
|
var convertInvalidNodeToValidNodeType = function convertInvalidNodeToValidNodeType(sourceContent, sourceNodeType, validNodeType, withMarks) {
|
|
@@ -196,7 +197,11 @@ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
|
|
|
196
197
|
heading = _schema$nodes2.heading;
|
|
197
198
|
var isTargetTaskList = targetNodeType === taskList;
|
|
198
199
|
var createListItemFromInline = function createListItemFromInline(content) {
|
|
199
|
-
|
|
200
|
+
if (!content && fg('platform_editor_block_menu_patch_2')) {
|
|
201
|
+
return isTargetTaskList ? taskItem.create() : listItem.create(null, paragraph.create());
|
|
202
|
+
} else {
|
|
203
|
+
return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
|
|
204
|
+
}
|
|
200
205
|
};
|
|
201
206
|
var getInlineContent = function getInlineContent(textblock) {
|
|
202
207
|
var inlineContent = [];
|
|
@@ -226,6 +231,15 @@ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
|
|
|
226
231
|
};
|
|
227
232
|
if (sourceNode.type.name === 'codeBlock') {
|
|
228
233
|
var codeText = sourceNode.textContent;
|
|
234
|
+
// check if code block only contains newline characters
|
|
235
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
236
|
+
var isOnlyNewLines = function isOnlyNewLines(codeText) {
|
|
237
|
+
return codeText.replace(/\n/g, '').trim() === '';
|
|
238
|
+
};
|
|
239
|
+
if ((!codeText || isOnlyNewLines(codeText)) && fg('platform_editor_block_menu_patch_2')) {
|
|
240
|
+
// Empty code block - create an empty list item
|
|
241
|
+
currentListItems.push(createListItemFromInline());
|
|
242
|
+
}
|
|
229
243
|
if (codeText) {
|
|
230
244
|
var lines = codeText.split('\n');
|
|
231
245
|
// Remove empty lines
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
2
|
import React, { Fragment } from 'react';
|
|
3
3
|
import { ArrowKeyNavigationProvider, ArrowKeyNavigationType } from '@atlaskit/editor-common/ui-menu';
|
|
4
|
+
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
4
5
|
var NoOp = function NoOp(props) {
|
|
5
6
|
return null;
|
|
6
7
|
};
|
|
@@ -41,48 +42,51 @@ export var BlockMenuRenderer = function BlockMenuRenderer(_ref) {
|
|
|
41
42
|
var menuSections = getSortedNonNestedSections(components);
|
|
42
43
|
var menuItems = components.filter(isMenuItem);
|
|
43
44
|
var nestedMenus = components.filter(isNestedMenu);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
45
|
+
var renderMenu = function renderMenu() {
|
|
46
|
+
return /*#__PURE__*/React.createElement(Fragment, null, menuSections.map(function (section) {
|
|
47
|
+
// Get all items for the current section, including nested menus, and sort them by rank
|
|
48
|
+
var currentSectionItemsSorted = getSortedChildren([].concat(_toConsumableArray(menuItems), _toConsumableArray(nestedMenus)), section.key);
|
|
49
|
+
if (currentSectionItemsSorted.length === 0) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
// iterate over the current section items, if it is nested menu, get their children, sort them
|
|
54
|
+
// if they are menu items, just render as they are sorted above
|
|
55
|
+
var getChildrenWithNestedItems = function getChildrenWithNestedItems(items) {
|
|
56
|
+
return items.map(function (item) {
|
|
57
|
+
if (isNestedMenu(item)) {
|
|
58
|
+
var sortedNestedSections = getSortedNestedSections(components, item.key);
|
|
59
|
+
return sortedNestedSections.map(function (section) {
|
|
60
|
+
var sortedNestedMenuItems = getSortedChildren(menuItems, section.key);
|
|
61
|
+
var NestedMenuComponent = item.component || fallbacks.nestedMenu || NoOp;
|
|
62
|
+
var NestedSection = section.component || fallbacks.section || NoOp;
|
|
63
|
+
return /*#__PURE__*/React.createElement(NestedMenuComponent, {
|
|
64
|
+
key: item.key
|
|
65
|
+
}, /*#__PURE__*/React.createElement(NestedSection, {
|
|
66
|
+
key: section.key
|
|
67
|
+
}, sortedNestedMenuItems.map(function (nestedItem) {
|
|
68
|
+
var NestedMenuItemComponent = nestedItem.component || fallbacks.item || NoOp;
|
|
69
|
+
return /*#__PURE__*/React.createElement(NestedMenuItemComponent, {
|
|
70
|
+
key: nestedItem.key
|
|
71
|
+
});
|
|
72
|
+
})));
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
var ItemComponent = item.component || fallbacks.item || NoOp;
|
|
76
|
+
return /*#__PURE__*/React.createElement(ItemComponent, {
|
|
64
77
|
key: item.key
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
};
|
|
82
|
-
var children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
83
|
-
var SectionComponent = section.component || fallbacks.section || NoOp;
|
|
84
|
-
return /*#__PURE__*/React.createElement(SectionComponent, {
|
|
85
|
-
key: section.key
|
|
86
|
-
}, children);
|
|
87
|
-
})));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
var children = getChildrenWithNestedItems(currentSectionItemsSorted);
|
|
83
|
+
var SectionComponent = section.component || fallbacks.section || NoOp;
|
|
84
|
+
return /*#__PURE__*/React.createElement(SectionComponent, {
|
|
85
|
+
key: section.key
|
|
86
|
+
}, children);
|
|
87
|
+
}));
|
|
88
|
+
};
|
|
89
|
+
return expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? /*#__PURE__*/React.createElement(ArrowKeyNavigationProvider, {
|
|
90
|
+
type: ArrowKeyNavigationType.MENU
|
|
91
|
+
}, renderMenu()) : renderMenu();
|
|
88
92
|
};
|
|
@@ -56,18 +56,20 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
56
56
|
boundariesElement = _ref2.boundariesElement,
|
|
57
57
|
scrollableElement = _ref2.scrollableElement;
|
|
58
58
|
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], function (states) {
|
|
59
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta;
|
|
59
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
|
|
60
60
|
return {
|
|
61
61
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
62
62
|
isSelectedViaDragHandle: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isSelectedViaDragHandle,
|
|
63
63
|
isMenuOpen: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isMenuOpen,
|
|
64
|
-
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent
|
|
64
|
+
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
65
|
+
openedViaKeyboard: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 || (_states$blockControls4 = _states$blockControls4.blockMenuOptions) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.openedViaKeyboard
|
|
65
66
|
};
|
|
66
67
|
}),
|
|
67
68
|
menuTriggerBy = _useSharedPluginState.menuTriggerBy,
|
|
68
69
|
isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
|
|
69
70
|
isMenuOpen = _useSharedPluginState.isMenuOpen,
|
|
70
|
-
currentUserIntent = _useSharedPluginState.currentUserIntent
|
|
71
|
+
currentUserIntent = _useSharedPluginState.currentUserIntent,
|
|
72
|
+
openedViaKeyboard = _useSharedPluginState.openedViaKeyboard;
|
|
71
73
|
var _useBlockMenu = useBlockMenu(),
|
|
72
74
|
onDropdownOpenChanged = _useBlockMenu.onDropdownOpenChanged,
|
|
73
75
|
fireAnalyticsEvent = _useBlockMenu.fireAnalyticsEvent;
|
|
@@ -78,7 +80,7 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
78
80
|
// hasSelection true, always show block menu
|
|
79
81
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
80
82
|
var shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
81
|
-
var selectedByShortcutORDragHandle = isSelectedViaDragHandle;
|
|
83
|
+
var selectedByShortcutORDragHandle = isSelectedViaDragHandle || openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
82
84
|
useEffect(function () {
|
|
83
85
|
var _api$userIntent;
|
|
84
86
|
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutORDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
@@ -141,7 +143,9 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
141
143
|
preventOverflow: true // disables forced horizontal placement when forcePlacement is on, so fitWidth controls flipping
|
|
142
144
|
,
|
|
143
145
|
stick: true,
|
|
144
|
-
focusTrap: true
|
|
146
|
+
focusTrap: expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? openedViaKeyboard ? {
|
|
147
|
+
initialFocus: undefined
|
|
148
|
+
} : true : undefined,
|
|
145
149
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
146
150
|
}, /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
147
151
|
api: api
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect } from 'react';
|
|
2
2
|
import { useIntl, injectIntl } from 'react-intl-next';
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { messages } from '@atlaskit/editor-common/block-menu';
|
|
@@ -69,10 +69,22 @@ var DeleteDropdownItemContent = function DeleteDropdownItemContent(_ref) {
|
|
|
69
69
|
return tr;
|
|
70
70
|
});
|
|
71
71
|
}, [api, nodeTypes]);
|
|
72
|
-
var onRemoveHoverDecoration = function
|
|
72
|
+
var onRemoveHoverDecoration = useCallback(function () {
|
|
73
73
|
var _api$decorations2, _api$decorations2$rem;
|
|
74
74
|
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$decorations2 = api.decorations) === null || _api$decorations2 === void 0 || (_api$decorations2 = _api$decorations2.commands) === null || _api$decorations2 === void 0 || (_api$decorations2$rem = _api$decorations2.removeDecoration) === null || _api$decorations2$rem === void 0 ? void 0 : _api$decorations2$rem.call(_api$decorations2));
|
|
75
|
-
};
|
|
75
|
+
}, [api]);
|
|
76
|
+
useEffect(function () {
|
|
77
|
+
if (!expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
return function () {
|
|
81
|
+
if (!expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// clean up hover decoration when unmounting
|
|
85
|
+
onRemoveHoverDecoration();
|
|
86
|
+
};
|
|
87
|
+
}, [onRemoveHoverDecoration]);
|
|
76
88
|
var text = fg('platform_editor_block_menu_patch_1') ? formatMessage(blockMenuMessages.deleteBlock) : formatMessage(messages.deleteBlock);
|
|
77
89
|
return /*#__PURE__*/React.createElement(Box, {
|
|
78
90
|
onMouseEnter: onShowHoverDecoration,
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
+
import { type Schema, type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
4
|
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
3
5
|
import type { FormatNodeTargetType } from './transforms/types';
|
|
6
|
+
/**
|
|
7
|
+
* Handles formatting when an empty list is selected
|
|
8
|
+
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
9
|
+
*/
|
|
10
|
+
export declare const formatNodeSelectEmptyList: (tr: Transaction, targetType: FormatNodeTargetType, listNode: {
|
|
11
|
+
node: PMNode;
|
|
12
|
+
pos: number;
|
|
13
|
+
}, schema: Schema) => Transaction;
|
|
4
14
|
/**
|
|
5
15
|
* Formats the current node or selection to the specified target type
|
|
6
16
|
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
+
import { type Schema, type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
4
|
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
3
5
|
import type { FormatNodeTargetType } from './transforms/types';
|
|
6
|
+
/**
|
|
7
|
+
* Handles formatting when an empty list is selected
|
|
8
|
+
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
9
|
+
*/
|
|
10
|
+
export declare const formatNodeSelectEmptyList: (tr: Transaction, targetType: FormatNodeTargetType, listNode: {
|
|
11
|
+
node: PMNode;
|
|
12
|
+
pos: number;
|
|
13
|
+
}, schema: Schema) => Transaction;
|
|
4
14
|
/**
|
|
5
15
|
* Formats the current node or selection to the specified target type
|
|
6
16
|
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@atlaskit/css": "^0.14.0",
|
|
32
32
|
"@atlaskit/dropdown-menu": "^16.3.0",
|
|
33
|
-
"@atlaskit/editor-plugin-analytics": "^6.
|
|
34
|
-
"@atlaskit/editor-plugin-block-controls": "^7.
|
|
33
|
+
"@atlaskit/editor-plugin-analytics": "^6.1.0",
|
|
34
|
+
"@atlaskit/editor-plugin-block-controls": "^7.2.0",
|
|
35
35
|
"@atlaskit/editor-plugin-decorations": "^6.1.0",
|
|
36
36
|
"@atlaskit/editor-plugin-selection": "^6.0.0",
|
|
37
37
|
"@atlaskit/editor-plugin-user-intent": "^4.0.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
41
41
|
"@atlaskit/editor-toolbar": "^0.10.0",
|
|
42
42
|
"@atlaskit/icon": "^28.3.0",
|
|
43
|
-
"@atlaskit/icon-lab": "^5.
|
|
43
|
+
"@atlaskit/icon-lab": "^5.8.0",
|
|
44
44
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
45
45
|
"@atlaskit/primitives": "^14.15.0",
|
|
46
46
|
"@atlaskit/tmp-editor-statsig": "^12.32.0",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@babel/runtime": "^7.0.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"@atlaskit/editor-common": "^110.
|
|
51
|
+
"@atlaskit/editor-common": "^110.4.0",
|
|
52
52
|
"react": "^18.2.0",
|
|
53
53
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
54
54
|
},
|