@atlaskit/editor-plugin-block-menu 20.0.3 → 20.0.5
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 +20 -0
- package/dist/cjs/editor-commands/transform-node-utils/TRANSFORMATION_MATRIX.js +20 -6
- package/dist/cjs/editor-commands/transform-node-utils/transform.js +11 -3
- package/dist/cjs/ui/block-menu-renderer/fallbacks.js +3 -0
- package/dist/cjs/ui/block-menu-target-visibility-context.js +12 -0
- package/dist/cjs/ui/block-menu.js +79 -12
- package/dist/cjs/ui/format-menu-nested.js +3 -0
- package/dist/es2019/editor-commands/transform-node-utils/TRANSFORMATION_MATRIX.js +20 -6
- package/dist/es2019/editor-commands/transform-node-utils/transform.js +7 -4
- package/dist/es2019/ui/block-menu-renderer/fallbacks.js +3 -0
- package/dist/es2019/ui/block-menu-target-visibility-context.js +4 -0
- package/dist/es2019/ui/block-menu.js +73 -12
- package/dist/es2019/ui/format-menu-nested.js +3 -0
- package/dist/esm/editor-commands/transform-node-utils/TRANSFORMATION_MATRIX.js +20 -6
- package/dist/esm/editor-commands/transform-node-utils/transform.js +11 -3
- package/dist/esm/ui/block-menu-renderer/fallbacks.js +3 -0
- package/dist/esm/ui/block-menu-target-visibility-context.js +6 -0
- package/dist/esm/ui/block-menu.js +79 -12
- package/dist/esm/ui/format-menu-nested.js +3 -0
- package/dist/types/ui/block-menu-target-visibility-context.d.ts +3 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 20.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`2fbdbadc1a47c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2fbdbadc1a47c) -
|
|
8
|
+
Convert direct container headings and nested list paragraphs to Normal or Small text while
|
|
9
|
+
preserving other nested content under platform_editor_block_menu_small_text.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 20.0.4
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`981dd11bb4ed2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/981dd11bb4ed2) -
|
|
17
|
+
Add opt-in target visibility handling to editor popups, and use it to hide the Jira description
|
|
18
|
+
block menu while its originating node is outside the visible viewport. The popup reappears when
|
|
19
|
+
its target returns, preserving an open nested menu, behind the
|
|
20
|
+
`platform_editor_popup_target_visibility` experiment.
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
|
|
3
23
|
## 20.0.3
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.TRANSFORMATION_MATRIX_PANEL_C1 = exports.TRANSFORMATION_MATRIX = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
9
10
|
var _applyTargetTextTypeStep = require("./steps/applyTargetTextTypeStep");
|
|
10
11
|
var _convertEachNodeStep = require("./steps/convertEachNodeStep");
|
|
11
12
|
var _decisionListToListStep = require("./steps/decisionListToListStep");
|
|
@@ -24,6 +25,19 @@ var _wrapMixedContentStep = require("./steps/wrapMixedContentStep");
|
|
|
24
25
|
var _wrapStep = require("./steps/wrapStep");
|
|
25
26
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
26
27
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
28
|
+
var applyTargetHeadingToParagraphStep = function applyTargetHeadingToParagraphStep(nodes, context) {
|
|
29
|
+
if (!(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_menu_small_text')) {
|
|
30
|
+
return nodes;
|
|
31
|
+
}
|
|
32
|
+
return nodes.map(function (node) {
|
|
33
|
+
var _applyTargetTextTypeS;
|
|
34
|
+
if (node.type.name !== 'heading') {
|
|
35
|
+
return node;
|
|
36
|
+
}
|
|
37
|
+
return (_applyTargetTextTypeS = (0, _applyTargetTextTypeStep.applyTargetTextTypeStep)([node], context).at(0)) !== null && _applyTargetTextTypeS !== void 0 ? _applyTargetTextTypeS : node;
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
27
41
|
/**
|
|
28
42
|
* Creates the transformation matrix for all node type pairs.
|
|
29
43
|
* When includePanelC1 is true (platform_editor_nest_table_in_panel experiment on),
|
|
@@ -71,7 +85,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
71
85
|
expand: [_unwrapStep.unwrapStep, _wrapStep.wrapStep],
|
|
72
86
|
nestedExpand: [_unwrapStep.unwrapStep, _wrapStep.wrapStep],
|
|
73
87
|
layoutSection: [_unwrapStep.unwrapStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
74
|
-
paragraph: [_unwrapStep.unwrapStep]
|
|
88
|
+
paragraph: [_unwrapStep.unwrapStep, applyTargetHeadingToParagraphStep]
|
|
75
89
|
},
|
|
76
90
|
panel_c1: includePanelC1 ? {
|
|
77
91
|
blockquote: [_unwrapStep.unwrapStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
@@ -79,7 +93,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
79
93
|
expand: [_unwrapStep.unwrapStep, _wrapStep.wrapStep],
|
|
80
94
|
nestedExpand: [_unwrapStep.unwrapStep, _wrapStep.wrapStep],
|
|
81
95
|
layoutSection: [_unwrapStep.unwrapStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
82
|
-
paragraph: [_unwrapStep.unwrapStep]
|
|
96
|
+
paragraph: [_unwrapStep.unwrapStep, applyTargetHeadingToParagraphStep]
|
|
83
97
|
} : {},
|
|
84
98
|
expand: _objectSpread(_objectSpread({
|
|
85
99
|
panel: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep]
|
|
@@ -89,7 +103,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
89
103
|
blockquote: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
90
104
|
layoutSection: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
91
105
|
nestedExpand: [_unwrapExpandStep.unwrapExpandStep, _wrapStep.wrapStep],
|
|
92
|
-
paragraph: [_unwrapExpandStep.unwrapExpandStep]
|
|
106
|
+
paragraph: [_unwrapExpandStep.unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
93
107
|
}),
|
|
94
108
|
nestedExpand: _objectSpread(_objectSpread({
|
|
95
109
|
panel: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep]
|
|
@@ -98,7 +112,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
98
112
|
} : {}), {}, {
|
|
99
113
|
blockquote: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
100
114
|
layoutSection: [_unwrapExpandStep.unwrapExpandStep, _wrapMixedContentStep.wrapMixedContentStep],
|
|
101
|
-
paragraph: [_unwrapExpandStep.unwrapExpandStep]
|
|
115
|
+
paragraph: [_unwrapExpandStep.unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
102
116
|
}),
|
|
103
117
|
blockquote: _objectSpread(_objectSpread({
|
|
104
118
|
expand: [_wrapStep.wrapStep],
|
|
@@ -108,7 +122,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
108
122
|
}, includePanelC1 ? {
|
|
109
123
|
panel_c1: [_unwrapStep.unwrapStep, _wrapStep.wrapStep]
|
|
110
124
|
} : {}), {}, {
|
|
111
|
-
paragraph: [_unwrapStep.unwrapStep],
|
|
125
|
+
paragraph: [_unwrapStep.unwrapStep, applyTargetHeadingToParagraphStep],
|
|
112
126
|
decisionList: [_unwrapStep.unwrapStep, _wrapBlockquoteToDecisionListStep.wrapBlockquoteToDecisionListStep]
|
|
113
127
|
}),
|
|
114
128
|
layoutSection: _objectSpread(_objectSpread({
|
|
@@ -119,7 +133,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
119
133
|
}, includePanelC1 ? {
|
|
120
134
|
panel_c1: [_unwrapLayoutStep.unwrapLayoutStep, _wrapMixedContentStep.wrapMixedContentStep]
|
|
121
135
|
} : {}), {}, {
|
|
122
|
-
paragraph: [_unwrapLayoutStep.unwrapLayoutStep]
|
|
136
|
+
paragraph: [_unwrapLayoutStep.unwrapLayoutStep, applyTargetHeadingToParagraphStep]
|
|
123
137
|
}),
|
|
124
138
|
codeBlock: _objectSpread(_objectSpread({
|
|
125
139
|
blockquote: [_wrapStep.wrapStep],
|
|
@@ -13,7 +13,14 @@ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
|
13
13
|
var _utils = require("../transform-node-utils/utils");
|
|
14
14
|
var _TRANSFORMATION_MATRIX = require("./TRANSFORMATION_MATRIX");
|
|
15
15
|
var _types = require("./types");
|
|
16
|
+
var LIST_NODE_TYPE_NAMES = new Set(['bulletList', 'orderedList', 'taskList', 'decisionList', 'listItem', 'taskItem', 'blockTaskItem', 'decisionItem']);
|
|
17
|
+
var shouldRecurseThroughListNode = function shouldRecurseThroughListNode(node) {
|
|
18
|
+
return LIST_NODE_TYPE_NAMES.has(node.type.name);
|
|
19
|
+
};
|
|
16
20
|
var _applyTargetNodeMarks = function applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema) {
|
|
21
|
+
var shouldRecurseIntoChildren = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : function () {
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
17
24
|
var nextNode = node;
|
|
18
25
|
if (node.type === targetNodeType) {
|
|
19
26
|
var marksAfterRemovals = (marksToRemove !== null && marksToRemove !== void 0 ? marksToRemove : []).reduce(function (currentMarks, name) {
|
|
@@ -29,12 +36,12 @@ var _applyTargetNodeMarks = function applyTargetNodeMarks(node, targetNodeType,
|
|
|
29
36
|
}, marksAfterRemovals);
|
|
30
37
|
nextNode = node.mark(marks);
|
|
31
38
|
}
|
|
32
|
-
if (nextNode.childCount === 0) {
|
|
39
|
+
if (!shouldRecurseIntoChildren(nextNode) || nextNode.childCount === 0) {
|
|
33
40
|
return nextNode;
|
|
34
41
|
}
|
|
35
42
|
var children = [];
|
|
36
43
|
nextNode.forEach(function (child) {
|
|
37
|
-
return children.push(_applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema));
|
|
44
|
+
return children.push(_applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema, shouldRecurseIntoChildren));
|
|
38
45
|
});
|
|
39
46
|
return nextNode.copy(_model.Fragment.fromArray(children));
|
|
40
47
|
};
|
|
@@ -112,12 +119,13 @@ var convertNodesToTargetType = exports.convertNodesToTargetType = function conve
|
|
|
112
119
|
}, sourceNodes);
|
|
113
120
|
return upgradePanelNodesToPanelC1(_resultNodes, parentNode, schema);
|
|
114
121
|
}
|
|
122
|
+
var shouldLimitTargetNodeMarkRecursion = targetNodeTypeName === 'paragraph' && ['multi', 'panel', 'panel_c1', 'expand', 'nestedExpand', 'blockquote', 'layoutSection'].includes(selectedNodeTypeName);
|
|
115
123
|
var resultNodes = (_steps$reduce = steps === null || steps === void 0 ? void 0 : steps.reduce(function (nodes, step) {
|
|
116
124
|
return step(nodes, context);
|
|
117
125
|
}, sourceNodes)) !== null && _steps$reduce !== void 0 ? _steps$reduce : sourceNodes;
|
|
118
126
|
var upgradedNodes = steps !== null && steps !== void 0 && steps.length ? upgradePanelNodesToPanelC1(resultNodes, parentNode, schema) : resultNodes;
|
|
119
127
|
return upgradedNodes.map(function (node) {
|
|
120
|
-
return _applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema);
|
|
128
|
+
return _applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema, shouldLimitTargetNodeMarkRecursion ? shouldRecurseThroughListNode : undefined);
|
|
121
129
|
});
|
|
122
130
|
};
|
|
123
131
|
var isTransformDisabledBasedOnStepsConfig = exports.isTransformDisabledBasedOnStepsConfig = function isTransformDisabledBasedOnStepsConfig(selectedNodeType, targetNodeType) {
|
|
@@ -10,11 +10,14 @@ var _reactIntl = require("react-intl");
|
|
|
10
10
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
11
11
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
12
12
|
var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
|
|
13
|
+
var _blockMenuTargetVisibilityContext = require("../block-menu-target-visibility-context");
|
|
13
14
|
var FallbackNestedMenu = function FallbackNestedMenu(_ref) {
|
|
14
15
|
var children = _ref.children;
|
|
15
16
|
var _useIntl = (0, _reactIntl.useIntl)(),
|
|
16
17
|
formatMessage = _useIntl.formatMessage;
|
|
18
|
+
var targetVisible = (0, _blockMenuTargetVisibilityContext.useBlockMenuTargetVisibility)();
|
|
17
19
|
return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
|
|
20
|
+
isPopupVisible: targetVisible,
|
|
18
21
|
elemBefore: undefined,
|
|
19
22
|
elemAfter: /*#__PURE__*/_react.default.createElement(_chevronRight.default, {
|
|
20
23
|
label: "",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useBlockMenuTargetVisibility = exports.BlockMenuTargetVisibilityProvider = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var BlockMenuTargetVisibilityContext = /*#__PURE__*/(0, _react.createContext)(undefined);
|
|
9
|
+
var BlockMenuTargetVisibilityProvider = exports.BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
|
|
10
|
+
var useBlockMenuTargetVisibility = exports.useBlockMenuTargetVisibility = function useBlockMenuTargetVisibility() {
|
|
11
|
+
return (0, _react.useContext)(BlockMenuTargetVisibilityContext);
|
|
12
|
+
};
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
9
9
|
exports.default = void 0;
|
|
10
10
|
require("./block-menu.compiled.css");
|
|
11
11
|
var _runtime = require("@compiled/react/runtime");
|
|
12
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
12
13
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
14
|
var _react = _interopRequireWildcard(require("react"));
|
|
14
15
|
var _reactIntl = require("react-intl");
|
|
@@ -30,7 +31,10 @@ var _redo = require("@atlaskit/prosemirror-history/redo");
|
|
|
30
31
|
var _undo = require("@atlaskit/prosemirror-history/undo");
|
|
31
32
|
var _blockMenuProvider = require("./block-menu-provider");
|
|
32
33
|
var _BlockMenuRenderer = require("./block-menu-renderer/BlockMenuRenderer");
|
|
34
|
+
var _blockMenuTargetVisibilityContext = require("./block-menu-target-visibility-context");
|
|
33
35
|
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); }
|
|
36
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
37
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
34
38
|
var styles = {
|
|
35
39
|
base: "_2rko12b0 _bfhk1bhr _16qs130s",
|
|
36
40
|
maxWidthStyles: "_p12fnklw",
|
|
@@ -180,17 +184,20 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
180
184
|
mountTo = _ref5.mountTo,
|
|
181
185
|
boundariesElement = _ref5.boundariesElement,
|
|
182
186
|
scrollableElement = _ref5.scrollableElement;
|
|
187
|
+
var isPopupTargetVisibilityEnabled = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_popup_target_visibility');
|
|
183
188
|
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls', 'userIntent'], function (states) {
|
|
184
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$
|
|
189
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5;
|
|
185
190
|
return {
|
|
186
191
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
187
|
-
|
|
188
|
-
|
|
192
|
+
menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
|
|
193
|
+
isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
|
|
194
|
+
isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
|
|
189
195
|
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
190
|
-
openedViaKeyboard: (_states$
|
|
196
|
+
openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 || (_states$blockControls5 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
|
|
191
197
|
};
|
|
192
198
|
}),
|
|
193
199
|
menuTriggerBy = _useSharedPluginState.menuTriggerBy,
|
|
200
|
+
menuTriggerByNode = _useSharedPluginState.menuTriggerByNode,
|
|
194
201
|
isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
|
|
195
202
|
isMenuOpen = _useSharedPluginState.isMenuOpen,
|
|
196
203
|
currentUserIntent = _useSharedPluginState.currentUserIntent,
|
|
@@ -228,6 +235,8 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
228
235
|
anchoredToRef.current = menuTriggerBy;
|
|
229
236
|
}
|
|
230
237
|
var targetHandleRef = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(_styles.DRAG_HANDLE_SELECTOR);
|
|
238
|
+
var menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
|
|
239
|
+
var visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
|
|
231
240
|
var closeMenu = _react.default.useCallback(function () {
|
|
232
241
|
api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
|
|
233
242
|
var _api$blockControls, _api$userIntent2;
|
|
@@ -257,19 +266,71 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
257
266
|
_React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
|
|
258
267
|
menuHeight = _React$useState4[0],
|
|
259
268
|
setMenuHeight = _React$useState4[1];
|
|
269
|
+
var _React$useState5 = _react.default.useState({
|
|
270
|
+
isVisible: undefined,
|
|
271
|
+
restoreFocusTo: null
|
|
272
|
+
}),
|
|
273
|
+
_React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
|
|
274
|
+
targetVisibility = _React$useState6[0],
|
|
275
|
+
setTargetVisibility = _React$useState6[1];
|
|
276
|
+
var targetVisible = targetVisibility.isVisible,
|
|
277
|
+
restoreFocusTo = targetVisibility.restoreFocusTo;
|
|
278
|
+
// CSS visibility can move focus to the document body. Preserve the active menu item so the
|
|
279
|
+
// existing focus-loss guard does not close the menus during a temporary scroll transition.
|
|
280
|
+
var handleTargetVisibilityChanged = _react.default.useCallback(function (isVisible) {
|
|
281
|
+
var _popupRef$current;
|
|
282
|
+
if (isVisible) {
|
|
283
|
+
setTargetVisibility(function (current) {
|
|
284
|
+
return {
|
|
285
|
+
isVisible: true,
|
|
286
|
+
restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Capture focus before scheduling the state update so the updater stays pure.
|
|
293
|
+
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
294
|
+
var activeElement = document.activeElement;
|
|
295
|
+
var isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(_styles.NESTED_DROPDOWN_MENU) !== null);
|
|
296
|
+
setTargetVisibility({
|
|
297
|
+
isVisible: false,
|
|
298
|
+
restoreFocusTo: isFocusInMenu ? activeElement : null
|
|
299
|
+
});
|
|
300
|
+
}, []);
|
|
301
|
+
_react.default.useLayoutEffect(function () {
|
|
302
|
+
if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
var _restoreFocusTo$owner = restoreFocusTo.ownerDocument,
|
|
306
|
+
activeElement = _restoreFocusTo$owner.activeElement,
|
|
307
|
+
body = _restoreFocusTo$owner.body,
|
|
308
|
+
documentElement = _restoreFocusTo$owner.documentElement;
|
|
309
|
+
var focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
|
|
310
|
+
if (restoreFocusTo.isConnected && focusWasLost) {
|
|
311
|
+
restoreFocusTo.focus({
|
|
312
|
+
preventScroll: true
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
setTargetVisibility(function (current) {
|
|
316
|
+
return _objectSpread(_objectSpread({}, current), {}, {
|
|
317
|
+
restoreFocusTo: null
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
|
|
260
321
|
var targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
|
|
261
322
|
_react.default.useLayoutEffect(function () {
|
|
262
|
-
var _popupRef$
|
|
323
|
+
var _popupRef$current2;
|
|
263
324
|
if (!isMenuOpen) {
|
|
264
325
|
return;
|
|
265
326
|
}
|
|
266
327
|
onDropdownOpenChanged(true);
|
|
267
|
-
setMenuHeight(((_popupRef$
|
|
328
|
+
setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
|
|
268
329
|
}, [isMenuOpen, onDropdownOpenChanged]);
|
|
269
330
|
|
|
270
331
|
// Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
|
|
271
332
|
// dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
|
|
272
|
-
var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
|
|
333
|
+
var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
|
|
273
334
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
274
335
|
document.activeElement === targetHandleRef || popupRef.current && (
|
|
275
336
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
@@ -340,6 +401,10 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
340
401
|
if (!(targetHandleRef instanceof HTMLElement)) {
|
|
341
402
|
return null;
|
|
342
403
|
}
|
|
404
|
+
var blockMenuContent = /*#__PURE__*/_react.default.createElement(BlockMenuContent, {
|
|
405
|
+
api: api,
|
|
406
|
+
setRef: setRef
|
|
407
|
+
});
|
|
343
408
|
return /*#__PURE__*/_react.default.createElement(_errorBoundary.ErrorBoundary, {
|
|
344
409
|
component: _analytics.ACTION_SUBJECT.BLOCK_MENU,
|
|
345
410
|
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
|
|
@@ -354,11 +419,14 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
354
419
|
boundariesElement: boundariesElement,
|
|
355
420
|
scrollableElement: scrollableElement,
|
|
356
421
|
target: targetHandleRef,
|
|
422
|
+
visibilityTarget: visibilityTarget,
|
|
357
423
|
zIndex: _editorSharedStyles.akEditorFloatingOverlapPanelZIndex,
|
|
358
424
|
fitWidth: DEFAULT_MENU_WIDTH,
|
|
359
425
|
fitHeight: menuHeight,
|
|
360
426
|
preventOverflow: true,
|
|
361
|
-
stick: true
|
|
427
|
+
stick: true,
|
|
428
|
+
hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
|
|
429
|
+
onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
|
|
362
430
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
363
431
|
,
|
|
364
432
|
offset: [_styles.DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
|
|
@@ -367,10 +435,9 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
367
435
|
{
|
|
368
436
|
initialFocus: undefined
|
|
369
437
|
} : undefined
|
|
370
|
-
}, /*#__PURE__*/_react.default.createElement(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
})));
|
|
438
|
+
}, isPopupTargetVisibilityEnabled ? /*#__PURE__*/_react.default.createElement(_blockMenuTargetVisibilityContext.BlockMenuTargetVisibilityProvider, {
|
|
439
|
+
value: targetVisible
|
|
440
|
+
}, blockMenuContent) : blockMenuContent));
|
|
374
441
|
};
|
|
375
442
|
|
|
376
443
|
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
|
@@ -14,6 +14,7 @@ var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
|
14
14
|
var _changes = _interopRequireDefault(require("@atlaskit/icon/core/changes"));
|
|
15
15
|
var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
|
|
16
16
|
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
17
|
+
var _blockMenuTargetVisibilityContext = require("./block-menu-target-visibility-context");
|
|
17
18
|
var _consts = require("./consts");
|
|
18
19
|
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); }
|
|
19
20
|
var BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
|
|
@@ -25,6 +26,7 @@ var FormatMenuComponent = exports.FormatMenuComponent = function FormatMenuCompo
|
|
|
25
26
|
children = _ref.children;
|
|
26
27
|
var _useIntl = (0, _reactIntl.useIntl)(),
|
|
27
28
|
formatMessage = _useIntl.formatMessage;
|
|
29
|
+
var targetVisible = (0, _blockMenuTargetVisibilityContext.useBlockMenuTargetVisibility)();
|
|
28
30
|
var formatMenuLabel = _messages.blockMenuMessages.changeFormat;
|
|
29
31
|
var handleClick = (0, _react.useCallback)(function () {
|
|
30
32
|
api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
|
|
@@ -43,6 +45,7 @@ var FormatMenuComponent = exports.FormatMenuComponent = function FormatMenuCompo
|
|
|
43
45
|
});
|
|
44
46
|
}, [api]);
|
|
45
47
|
return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
|
|
48
|
+
isPopupVisible: targetVisible,
|
|
46
49
|
text: formatMessage(formatMenuLabel),
|
|
47
50
|
elemBefore: /*#__PURE__*/_react.default.createElement(_changes.default, {
|
|
48
51
|
label: "",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
1
2
|
import { applyTargetTextTypeStep } from './steps/applyTargetTextTypeStep';
|
|
2
3
|
import { convertEachNodeStep } from './steps/convertEachNodeStep';
|
|
3
4
|
import { decisionListToListStep } from './steps/decisionListToListStep';
|
|
@@ -14,6 +15,19 @@ import { wrapBlockquoteToDecisionListStep } from './steps/wrapBlockquoteToDecisi
|
|
|
14
15
|
import { wrapIntoListStep } from './steps/wrapIntoListStep';
|
|
15
16
|
import { wrapMixedContentStep } from './steps/wrapMixedContentStep';
|
|
16
17
|
import { wrapStep } from './steps/wrapStep';
|
|
18
|
+
const applyTargetHeadingToParagraphStep = (nodes, context) => {
|
|
19
|
+
if (!isExperimentEnabled('platform_editor_block_menu_small_text')) {
|
|
20
|
+
return nodes;
|
|
21
|
+
}
|
|
22
|
+
return nodes.map(node => {
|
|
23
|
+
var _applyTargetTextTypeS;
|
|
24
|
+
if (node.type.name !== 'heading') {
|
|
25
|
+
return node;
|
|
26
|
+
}
|
|
27
|
+
return (_applyTargetTextTypeS = applyTargetTextTypeStep([node], context).at(0)) !== null && _applyTargetTextTypeS !== void 0 ? _applyTargetTextTypeS : node;
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
17
31
|
/**
|
|
18
32
|
* Creates the transformation matrix for all node type pairs.
|
|
19
33
|
* When includePanelC1 is true (platform_editor_nest_table_in_panel experiment on),
|
|
@@ -60,7 +74,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
60
74
|
expand: [unwrapStep, wrapStep],
|
|
61
75
|
nestedExpand: [unwrapStep, wrapStep],
|
|
62
76
|
layoutSection: [unwrapStep, wrapMixedContentStep],
|
|
63
|
-
paragraph: [unwrapStep]
|
|
77
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep]
|
|
64
78
|
},
|
|
65
79
|
panel_c1: includePanelC1 ? {
|
|
66
80
|
blockquote: [unwrapStep, wrapMixedContentStep],
|
|
@@ -68,7 +82,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
68
82
|
expand: [unwrapStep, wrapStep],
|
|
69
83
|
nestedExpand: [unwrapStep, wrapStep],
|
|
70
84
|
layoutSection: [unwrapStep, wrapMixedContentStep],
|
|
71
|
-
paragraph: [unwrapStep]
|
|
85
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep]
|
|
72
86
|
} : {},
|
|
73
87
|
expand: {
|
|
74
88
|
panel: [unwrapExpandStep, wrapMixedContentStep],
|
|
@@ -78,7 +92,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
78
92
|
blockquote: [unwrapExpandStep, wrapMixedContentStep],
|
|
79
93
|
layoutSection: [unwrapExpandStep, wrapMixedContentStep],
|
|
80
94
|
nestedExpand: [unwrapExpandStep, wrapStep],
|
|
81
|
-
paragraph: [unwrapExpandStep]
|
|
95
|
+
paragraph: [unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
82
96
|
},
|
|
83
97
|
nestedExpand: {
|
|
84
98
|
panel: [unwrapExpandStep, wrapMixedContentStep],
|
|
@@ -87,7 +101,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
87
101
|
} : {}),
|
|
88
102
|
blockquote: [unwrapExpandStep, wrapMixedContentStep],
|
|
89
103
|
layoutSection: [unwrapExpandStep, wrapMixedContentStep],
|
|
90
|
-
paragraph: [unwrapExpandStep]
|
|
104
|
+
paragraph: [unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
91
105
|
},
|
|
92
106
|
blockquote: {
|
|
93
107
|
expand: [wrapStep],
|
|
@@ -97,7 +111,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
97
111
|
...(includePanelC1 ? {
|
|
98
112
|
panel_c1: [unwrapStep, wrapStep]
|
|
99
113
|
} : {}),
|
|
100
|
-
paragraph: [unwrapStep],
|
|
114
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep],
|
|
101
115
|
decisionList: [unwrapStep, wrapBlockquoteToDecisionListStep]
|
|
102
116
|
},
|
|
103
117
|
layoutSection: {
|
|
@@ -108,7 +122,7 @@ const createTransformationMatrix = includePanelC1 => ({
|
|
|
108
122
|
...(includePanelC1 ? {
|
|
109
123
|
panel_c1: [unwrapLayoutStep, wrapMixedContentStep]
|
|
110
124
|
} : {}),
|
|
111
|
-
paragraph: [unwrapLayoutStep]
|
|
125
|
+
paragraph: [unwrapLayoutStep, applyTargetHeadingToParagraphStep]
|
|
112
126
|
},
|
|
113
127
|
codeBlock: {
|
|
114
128
|
blockquote: [wrapStep],
|
|
@@ -5,7 +5,9 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
|
5
5
|
import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
|
|
6
6
|
import { TRANSFORMATION_MATRIX, TRANSFORMATION_MATRIX_PANEL_C1 } from './TRANSFORMATION_MATRIX';
|
|
7
7
|
import { getNodeName, toNodeTypeValue } from './types';
|
|
8
|
-
const
|
|
8
|
+
const LIST_NODE_TYPE_NAMES = new Set(['bulletList', 'orderedList', 'taskList', 'decisionList', 'listItem', 'taskItem', 'blockTaskItem', 'decisionItem']);
|
|
9
|
+
const shouldRecurseThroughListNode = node => LIST_NODE_TYPE_NAMES.has(node.type.name);
|
|
10
|
+
const applyTargetNodeMarks = (node, targetNodeType, marksToAdd, marksToRemove, schema, shouldRecurseIntoChildren = () => true) => {
|
|
9
11
|
let nextNode = node;
|
|
10
12
|
if (node.type === targetNodeType) {
|
|
11
13
|
const marksAfterRemovals = (marksToRemove !== null && marksToRemove !== void 0 ? marksToRemove : []).reduce((currentMarks, name) => {
|
|
@@ -18,11 +20,11 @@ const applyTargetNodeMarks = (node, targetNodeType, marksToAdd, marksToRemove, s
|
|
|
18
20
|
}, marksAfterRemovals);
|
|
19
21
|
nextNode = node.mark(marks);
|
|
20
22
|
}
|
|
21
|
-
if (nextNode.childCount === 0) {
|
|
23
|
+
if (!shouldRecurseIntoChildren(nextNode) || nextNode.childCount === 0) {
|
|
22
24
|
return nextNode;
|
|
23
25
|
}
|
|
24
26
|
const children = [];
|
|
25
|
-
nextNode.forEach(child => children.push(applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema)));
|
|
27
|
+
nextNode.forEach(child => children.push(applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema, shouldRecurseIntoChildren)));
|
|
26
28
|
return nextNode.copy(Fragment.fromArray(children));
|
|
27
29
|
};
|
|
28
30
|
|
|
@@ -98,9 +100,10 @@ export const convertNodesToTargetType = ({
|
|
|
98
100
|
const resultNodes = steps.reduce((nodes, step) => step(nodes, context), sourceNodes);
|
|
99
101
|
return upgradePanelNodesToPanelC1(resultNodes, parentNode, schema);
|
|
100
102
|
}
|
|
103
|
+
const shouldLimitTargetNodeMarkRecursion = targetNodeTypeName === 'paragraph' && ['multi', 'panel', 'panel_c1', 'expand', 'nestedExpand', 'blockquote', 'layoutSection'].includes(selectedNodeTypeName);
|
|
101
104
|
const resultNodes = (_steps$reduce = steps === null || steps === void 0 ? void 0 : steps.reduce((nodes, step) => step(nodes, context), sourceNodes)) !== null && _steps$reduce !== void 0 ? _steps$reduce : sourceNodes;
|
|
102
105
|
const upgradedNodes = steps !== null && steps !== void 0 && steps.length ? upgradePanelNodesToPanelC1(resultNodes, parentNode, schema) : resultNodes;
|
|
103
|
-
return upgradedNodes.map(node => applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema));
|
|
106
|
+
return upgradedNodes.map(node => applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema, shouldLimitTargetNodeMarkRecursion ? shouldRecurseThroughListNode : undefined));
|
|
104
107
|
};
|
|
105
108
|
export const isTransformDisabledBasedOnStepsConfig = (selectedNodeType, targetNodeType) => {
|
|
106
109
|
const steps = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? TRANSFORMATION_MATRIX_PANEL_C1[selectedNodeType][targetNodeType] : TRANSFORMATION_MATRIX[selectedNodeType][targetNodeType];
|
|
@@ -3,13 +3,16 @@ import { useIntl } from 'react-intl';
|
|
|
3
3
|
import { blockMenuMessages } from '@atlaskit/editor-common/messages';
|
|
4
4
|
import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
5
5
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
6
|
+
import { useBlockMenuTargetVisibility } from '../block-menu-target-visibility-context';
|
|
6
7
|
const FallbackNestedMenu = ({
|
|
7
8
|
children
|
|
8
9
|
}) => {
|
|
9
10
|
const {
|
|
10
11
|
formatMessage
|
|
11
12
|
} = useIntl();
|
|
13
|
+
const targetVisible = useBlockMenuTargetVisibility();
|
|
12
14
|
return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
|
|
15
|
+
isPopupVisible: targetVisible,
|
|
13
16
|
elemBefore: undefined,
|
|
14
17
|
elemAfter: /*#__PURE__*/React.createElement(ChevronRightIcon, {
|
|
15
18
|
label: "",
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
const BlockMenuTargetVisibilityContext = /*#__PURE__*/createContext(undefined);
|
|
3
|
+
export const BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
|
|
4
|
+
export const useBlockMenuTargetVisibility = () => useContext(BlockMenuTargetVisibilityContext);
|
|
@@ -21,6 +21,7 @@ import { redo } from '@atlaskit/prosemirror-history/redo';
|
|
|
21
21
|
import { undo } from '@atlaskit/prosemirror-history/undo';
|
|
22
22
|
import { useBlockMenu } from './block-menu-provider';
|
|
23
23
|
import { BlockMenuRenderer } from './block-menu-renderer/BlockMenuRenderer';
|
|
24
|
+
import { BlockMenuTargetVisibilityProvider } from './block-menu-target-visibility-context';
|
|
24
25
|
const styles = {
|
|
25
26
|
base: "_2rko12b0 _bfhk1bhr _16qs130s",
|
|
26
27
|
maxWidthStyles: "_p12fnklw",
|
|
@@ -168,20 +169,23 @@ const BlockMenu = ({
|
|
|
168
169
|
scrollableElement
|
|
169
170
|
}) => {
|
|
170
171
|
var _openMenuHandleRef$cu, _editorView$dom, _ref2, _api$analytics2;
|
|
172
|
+
const isPopupTargetVisibilityEnabled = isExperimentEnabled('platform_editor_popup_target_visibility');
|
|
171
173
|
const {
|
|
172
174
|
menuTriggerBy,
|
|
175
|
+
menuTriggerByNode,
|
|
173
176
|
isSelectedViaDragHandle,
|
|
174
177
|
isMenuOpen,
|
|
175
178
|
currentUserIntent,
|
|
176
179
|
openedViaKeyboard
|
|
177
180
|
} = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], states => {
|
|
178
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$
|
|
181
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5, _states$blockControls6;
|
|
179
182
|
return {
|
|
180
183
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
|
|
185
|
+
isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
|
|
186
|
+
isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
|
|
183
187
|
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
184
|
-
openedViaKeyboard: (_states$
|
|
188
|
+
openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 ? void 0 : (_states$blockControls6 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls6 === void 0 ? void 0 : _states$blockControls6.openedViaKeyboard
|
|
185
189
|
};
|
|
186
190
|
});
|
|
187
191
|
const {
|
|
@@ -213,6 +217,8 @@ const BlockMenu = ({
|
|
|
213
217
|
anchoredToRef.current = menuTriggerBy;
|
|
214
218
|
}
|
|
215
219
|
const targetHandleRef = isExperimentEnabled('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 ? void 0 : (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
220
|
+
const menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
|
|
221
|
+
const visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
|
|
216
222
|
const closeMenu = React.useCallback(() => {
|
|
217
223
|
api === null || api === void 0 ? void 0 : api.core.actions.execute(({
|
|
218
224
|
tr
|
|
@@ -240,19 +246,68 @@ const BlockMenu = ({
|
|
|
240
246
|
const prevIsMenuOpenRef = useRef(false);
|
|
241
247
|
const popupRef = useRef(undefined);
|
|
242
248
|
const [menuHeight, setMenuHeight] = React.useState(0);
|
|
249
|
+
const [targetVisibility, setTargetVisibility] = React.useState({
|
|
250
|
+
isVisible: undefined,
|
|
251
|
+
restoreFocusTo: null
|
|
252
|
+
});
|
|
253
|
+
const {
|
|
254
|
+
isVisible: targetVisible,
|
|
255
|
+
restoreFocusTo
|
|
256
|
+
} = targetVisibility;
|
|
257
|
+
// CSS visibility can move focus to the document body. Preserve the active menu item so the
|
|
258
|
+
// existing focus-loss guard does not close the menus during a temporary scroll transition.
|
|
259
|
+
const handleTargetVisibilityChanged = React.useCallback(isVisible => {
|
|
260
|
+
var _popupRef$current;
|
|
261
|
+
if (isVisible) {
|
|
262
|
+
setTargetVisibility(current => ({
|
|
263
|
+
isVisible: true,
|
|
264
|
+
restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
|
|
265
|
+
}));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Capture focus before scheduling the state update so the updater stays pure.
|
|
270
|
+
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
271
|
+
const activeElement = document.activeElement;
|
|
272
|
+
const isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(NESTED_DROPDOWN_MENU) !== null);
|
|
273
|
+
setTargetVisibility({
|
|
274
|
+
isVisible: false,
|
|
275
|
+
restoreFocusTo: isFocusInMenu ? activeElement : null
|
|
276
|
+
});
|
|
277
|
+
}, []);
|
|
278
|
+
React.useLayoutEffect(() => {
|
|
279
|
+
if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const {
|
|
283
|
+
activeElement,
|
|
284
|
+
body,
|
|
285
|
+
documentElement
|
|
286
|
+
} = restoreFocusTo.ownerDocument;
|
|
287
|
+
const focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
|
|
288
|
+
if (restoreFocusTo.isConnected && focusWasLost) {
|
|
289
|
+
restoreFocusTo.focus({
|
|
290
|
+
preventScroll: true
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
setTargetVisibility(current => ({
|
|
294
|
+
...current,
|
|
295
|
+
restoreFocusTo: null
|
|
296
|
+
}));
|
|
297
|
+
}, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
|
|
243
298
|
const targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
|
|
244
299
|
React.useLayoutEffect(() => {
|
|
245
|
-
var _popupRef$
|
|
300
|
+
var _popupRef$current2;
|
|
246
301
|
if (!isMenuOpen) {
|
|
247
302
|
return;
|
|
248
303
|
}
|
|
249
304
|
onDropdownOpenChanged(true);
|
|
250
|
-
setMenuHeight(((_popupRef$
|
|
305
|
+
setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
|
|
251
306
|
}, [isMenuOpen, onDropdownOpenChanged]);
|
|
252
307
|
|
|
253
308
|
// Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
|
|
254
309
|
// dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
|
|
255
|
-
const hasFocus = (_ref2 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
|
|
310
|
+
const hasFocus = (_ref2 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
|
|
256
311
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
257
312
|
document.activeElement === targetHandleRef || popupRef.current && (
|
|
258
313
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
@@ -323,6 +378,10 @@ const BlockMenu = ({
|
|
|
323
378
|
if (!(targetHandleRef instanceof HTMLElement)) {
|
|
324
379
|
return null;
|
|
325
380
|
}
|
|
381
|
+
const blockMenuContent = /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
382
|
+
api: api,
|
|
383
|
+
setRef: setRef
|
|
384
|
+
});
|
|
326
385
|
return /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
327
386
|
component: ACTION_SUBJECT.BLOCK_MENU,
|
|
328
387
|
dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
|
|
@@ -337,11 +396,14 @@ const BlockMenu = ({
|
|
|
337
396
|
boundariesElement: boundariesElement,
|
|
338
397
|
scrollableElement: scrollableElement,
|
|
339
398
|
target: targetHandleRef,
|
|
399
|
+
visibilityTarget: visibilityTarget,
|
|
340
400
|
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
341
401
|
fitWidth: DEFAULT_MENU_WIDTH,
|
|
342
402
|
fitHeight: menuHeight,
|
|
343
403
|
preventOverflow: true,
|
|
344
|
-
stick: true
|
|
404
|
+
stick: true,
|
|
405
|
+
hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
|
|
406
|
+
onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
|
|
345
407
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
346
408
|
,
|
|
347
409
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
|
|
@@ -350,10 +412,9 @@ const BlockMenu = ({
|
|
|
350
412
|
{
|
|
351
413
|
initialFocus: undefined
|
|
352
414
|
} : undefined
|
|
353
|
-
}, /*#__PURE__*/React.createElement(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
})));
|
|
415
|
+
}, isPopupTargetVisibilityEnabled ? /*#__PURE__*/React.createElement(BlockMenuTargetVisibilityProvider, {
|
|
416
|
+
value: targetVisible
|
|
417
|
+
}, blockMenuContent) : blockMenuContent));
|
|
357
418
|
};
|
|
358
419
|
|
|
359
420
|
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
|
@@ -6,6 +6,7 @@ import { ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
|
6
6
|
import ChangesIcon from '@atlaskit/icon/core/changes';
|
|
7
7
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
9
|
+
import { useBlockMenuTargetVisibility } from './block-menu-target-visibility-context';
|
|
9
10
|
import { BLOCK_MENU_ITEM_NAME } from './consts';
|
|
10
11
|
const BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
|
|
11
12
|
const shouldIgnoreBlockMenuTransformSpotlightCloseEvent = event => event.target instanceof Element && event.target.closest(BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR) !== null;
|
|
@@ -16,6 +17,7 @@ export const FormatMenuComponent = ({
|
|
|
16
17
|
const {
|
|
17
18
|
formatMessage
|
|
18
19
|
} = useIntl();
|
|
20
|
+
const targetVisible = useBlockMenuTargetVisibility();
|
|
19
21
|
const formatMenuLabel = blockMenuMessages.changeFormat;
|
|
20
22
|
const handleClick = useCallback(() => {
|
|
21
23
|
api === null || api === void 0 ? void 0 : api.core.actions.execute(({
|
|
@@ -35,6 +37,7 @@ export const FormatMenuComponent = ({
|
|
|
35
37
|
});
|
|
36
38
|
}, [api]);
|
|
37
39
|
return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
|
|
40
|
+
isPopupVisible: targetVisible,
|
|
38
41
|
text: formatMessage(formatMenuLabel),
|
|
39
42
|
elemBefore: /*#__PURE__*/React.createElement(ChangesIcon, {
|
|
40
43
|
label: "",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
4
5
|
import { applyTargetTextTypeStep } from './steps/applyTargetTextTypeStep';
|
|
5
6
|
import { convertEachNodeStep } from './steps/convertEachNodeStep';
|
|
6
7
|
import { decisionListToListStep } from './steps/decisionListToListStep';
|
|
@@ -17,6 +18,19 @@ import { wrapBlockquoteToDecisionListStep } from './steps/wrapBlockquoteToDecisi
|
|
|
17
18
|
import { wrapIntoListStep } from './steps/wrapIntoListStep';
|
|
18
19
|
import { wrapMixedContentStep } from './steps/wrapMixedContentStep';
|
|
19
20
|
import { wrapStep } from './steps/wrapStep';
|
|
21
|
+
var applyTargetHeadingToParagraphStep = function applyTargetHeadingToParagraphStep(nodes, context) {
|
|
22
|
+
if (!isExperimentEnabled('platform_editor_block_menu_small_text')) {
|
|
23
|
+
return nodes;
|
|
24
|
+
}
|
|
25
|
+
return nodes.map(function (node) {
|
|
26
|
+
var _applyTargetTextTypeS;
|
|
27
|
+
if (node.type.name !== 'heading') {
|
|
28
|
+
return node;
|
|
29
|
+
}
|
|
30
|
+
return (_applyTargetTextTypeS = applyTargetTextTypeStep([node], context).at(0)) !== null && _applyTargetTextTypeS !== void 0 ? _applyTargetTextTypeS : node;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
20
34
|
/**
|
|
21
35
|
* Creates the transformation matrix for all node type pairs.
|
|
22
36
|
* When includePanelC1 is true (platform_editor_nest_table_in_panel experiment on),
|
|
@@ -64,7 +78,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
64
78
|
expand: [unwrapStep, wrapStep],
|
|
65
79
|
nestedExpand: [unwrapStep, wrapStep],
|
|
66
80
|
layoutSection: [unwrapStep, wrapMixedContentStep],
|
|
67
|
-
paragraph: [unwrapStep]
|
|
81
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep]
|
|
68
82
|
},
|
|
69
83
|
panel_c1: includePanelC1 ? {
|
|
70
84
|
blockquote: [unwrapStep, wrapMixedContentStep],
|
|
@@ -72,7 +86,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
72
86
|
expand: [unwrapStep, wrapStep],
|
|
73
87
|
nestedExpand: [unwrapStep, wrapStep],
|
|
74
88
|
layoutSection: [unwrapStep, wrapMixedContentStep],
|
|
75
|
-
paragraph: [unwrapStep]
|
|
89
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep]
|
|
76
90
|
} : {},
|
|
77
91
|
expand: _objectSpread(_objectSpread({
|
|
78
92
|
panel: [unwrapExpandStep, wrapMixedContentStep]
|
|
@@ -82,7 +96,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
82
96
|
blockquote: [unwrapExpandStep, wrapMixedContentStep],
|
|
83
97
|
layoutSection: [unwrapExpandStep, wrapMixedContentStep],
|
|
84
98
|
nestedExpand: [unwrapExpandStep, wrapStep],
|
|
85
|
-
paragraph: [unwrapExpandStep]
|
|
99
|
+
paragraph: [unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
86
100
|
}),
|
|
87
101
|
nestedExpand: _objectSpread(_objectSpread({
|
|
88
102
|
panel: [unwrapExpandStep, wrapMixedContentStep]
|
|
@@ -91,7 +105,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
91
105
|
} : {}), {}, {
|
|
92
106
|
blockquote: [unwrapExpandStep, wrapMixedContentStep],
|
|
93
107
|
layoutSection: [unwrapExpandStep, wrapMixedContentStep],
|
|
94
|
-
paragraph: [unwrapExpandStep]
|
|
108
|
+
paragraph: [unwrapExpandStep, applyTargetHeadingToParagraphStep]
|
|
95
109
|
}),
|
|
96
110
|
blockquote: _objectSpread(_objectSpread({
|
|
97
111
|
expand: [wrapStep],
|
|
@@ -101,7 +115,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
101
115
|
}, includePanelC1 ? {
|
|
102
116
|
panel_c1: [unwrapStep, wrapStep]
|
|
103
117
|
} : {}), {}, {
|
|
104
|
-
paragraph: [unwrapStep],
|
|
118
|
+
paragraph: [unwrapStep, applyTargetHeadingToParagraphStep],
|
|
105
119
|
decisionList: [unwrapStep, wrapBlockquoteToDecisionListStep]
|
|
106
120
|
}),
|
|
107
121
|
layoutSection: _objectSpread(_objectSpread({
|
|
@@ -112,7 +126,7 @@ var createTransformationMatrix = function createTransformationMatrix(includePane
|
|
|
112
126
|
}, includePanelC1 ? {
|
|
113
127
|
panel_c1: [unwrapLayoutStep, wrapMixedContentStep]
|
|
114
128
|
} : {}), {}, {
|
|
115
|
-
paragraph: [unwrapLayoutStep]
|
|
129
|
+
paragraph: [unwrapLayoutStep, applyTargetHeadingToParagraphStep]
|
|
116
130
|
}),
|
|
117
131
|
codeBlock: _objectSpread(_objectSpread({
|
|
118
132
|
blockquote: [wrapStep],
|
|
@@ -6,7 +6,14 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
|
6
6
|
import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
|
|
7
7
|
import { TRANSFORMATION_MATRIX, TRANSFORMATION_MATRIX_PANEL_C1 } from './TRANSFORMATION_MATRIX';
|
|
8
8
|
import { getNodeName, toNodeTypeValue } from './types';
|
|
9
|
+
var LIST_NODE_TYPE_NAMES = new Set(['bulletList', 'orderedList', 'taskList', 'decisionList', 'listItem', 'taskItem', 'blockTaskItem', 'decisionItem']);
|
|
10
|
+
var shouldRecurseThroughListNode = function shouldRecurseThroughListNode(node) {
|
|
11
|
+
return LIST_NODE_TYPE_NAMES.has(node.type.name);
|
|
12
|
+
};
|
|
9
13
|
var _applyTargetNodeMarks = function applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema) {
|
|
14
|
+
var shouldRecurseIntoChildren = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : function () {
|
|
15
|
+
return true;
|
|
16
|
+
};
|
|
10
17
|
var nextNode = node;
|
|
11
18
|
if (node.type === targetNodeType) {
|
|
12
19
|
var marksAfterRemovals = (marksToRemove !== null && marksToRemove !== void 0 ? marksToRemove : []).reduce(function (currentMarks, name) {
|
|
@@ -22,12 +29,12 @@ var _applyTargetNodeMarks = function applyTargetNodeMarks(node, targetNodeType,
|
|
|
22
29
|
}, marksAfterRemovals);
|
|
23
30
|
nextNode = node.mark(marks);
|
|
24
31
|
}
|
|
25
|
-
if (nextNode.childCount === 0) {
|
|
32
|
+
if (!shouldRecurseIntoChildren(nextNode) || nextNode.childCount === 0) {
|
|
26
33
|
return nextNode;
|
|
27
34
|
}
|
|
28
35
|
var children = [];
|
|
29
36
|
nextNode.forEach(function (child) {
|
|
30
|
-
return children.push(_applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema));
|
|
37
|
+
return children.push(_applyTargetNodeMarks(child, targetNodeType, marksToAdd, marksToRemove, schema, shouldRecurseIntoChildren));
|
|
31
38
|
});
|
|
32
39
|
return nextNode.copy(Fragment.fromArray(children));
|
|
33
40
|
};
|
|
@@ -105,12 +112,13 @@ export var convertNodesToTargetType = function convertNodesToTargetType(_ref3) {
|
|
|
105
112
|
}, sourceNodes);
|
|
106
113
|
return upgradePanelNodesToPanelC1(_resultNodes, parentNode, schema);
|
|
107
114
|
}
|
|
115
|
+
var shouldLimitTargetNodeMarkRecursion = targetNodeTypeName === 'paragraph' && ['multi', 'panel', 'panel_c1', 'expand', 'nestedExpand', 'blockquote', 'layoutSection'].includes(selectedNodeTypeName);
|
|
108
116
|
var resultNodes = (_steps$reduce = steps === null || steps === void 0 ? void 0 : steps.reduce(function (nodes, step) {
|
|
109
117
|
return step(nodes, context);
|
|
110
118
|
}, sourceNodes)) !== null && _steps$reduce !== void 0 ? _steps$reduce : sourceNodes;
|
|
111
119
|
var upgradedNodes = steps !== null && steps !== void 0 && steps.length ? upgradePanelNodesToPanelC1(resultNodes, parentNode, schema) : resultNodes;
|
|
112
120
|
return upgradedNodes.map(function (node) {
|
|
113
|
-
return _applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema);
|
|
121
|
+
return _applyTargetNodeMarks(node, targetNodeType, marksToAdd, marksToRemove, schema, shouldLimitTargetNodeMarkRecursion ? shouldRecurseThroughListNode : undefined);
|
|
114
122
|
});
|
|
115
123
|
};
|
|
116
124
|
export var isTransformDisabledBasedOnStepsConfig = function isTransformDisabledBasedOnStepsConfig(selectedNodeType, targetNodeType) {
|
|
@@ -3,11 +3,14 @@ import { useIntl } from 'react-intl';
|
|
|
3
3
|
import { blockMenuMessages } from '@atlaskit/editor-common/messages';
|
|
4
4
|
import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
5
5
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
6
|
+
import { useBlockMenuTargetVisibility } from '../block-menu-target-visibility-context';
|
|
6
7
|
var FallbackNestedMenu = function FallbackNestedMenu(_ref) {
|
|
7
8
|
var children = _ref.children;
|
|
8
9
|
var _useIntl = useIntl(),
|
|
9
10
|
formatMessage = _useIntl.formatMessage;
|
|
11
|
+
var targetVisible = useBlockMenuTargetVisibility();
|
|
10
12
|
return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
|
|
13
|
+
isPopupVisible: targetVisible,
|
|
11
14
|
elemBefore: undefined,
|
|
12
15
|
elemAfter: /*#__PURE__*/React.createElement(ChevronRightIcon, {
|
|
13
16
|
label: "",
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
var BlockMenuTargetVisibilityContext = /*#__PURE__*/createContext(undefined);
|
|
3
|
+
export var BlockMenuTargetVisibilityProvider = BlockMenuTargetVisibilityContext.Provider;
|
|
4
|
+
export var useBlockMenuTargetVisibility = function useBlockMenuTargetVisibility() {
|
|
5
|
+
return useContext(BlockMenuTargetVisibilityContext);
|
|
6
|
+
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/* block-menu.tsx generated by @compiled/babel-plugin v3.0.2 */
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
3
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
4
|
import "./block-menu.compiled.css";
|
|
4
5
|
import { ax, ix } from "@compiled/react/runtime";
|
|
6
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
8
|
import React, { useContext, useEffect, useRef } from 'react';
|
|
6
9
|
import { injectIntl } from 'react-intl';
|
|
7
10
|
import { cx } from '@atlaskit/css';
|
|
@@ -22,6 +25,7 @@ import { redo } from '@atlaskit/prosemirror-history/redo';
|
|
|
22
25
|
import { undo } from '@atlaskit/prosemirror-history/undo';
|
|
23
26
|
import { useBlockMenu } from './block-menu-provider';
|
|
24
27
|
import { BlockMenuRenderer } from './block-menu-renderer/BlockMenuRenderer';
|
|
28
|
+
import { BlockMenuTargetVisibilityProvider } from './block-menu-target-visibility-context';
|
|
25
29
|
var styles = {
|
|
26
30
|
base: "_2rko12b0 _bfhk1bhr _16qs130s",
|
|
27
31
|
maxWidthStyles: "_p12fnklw",
|
|
@@ -171,17 +175,20 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
171
175
|
mountTo = _ref5.mountTo,
|
|
172
176
|
boundariesElement = _ref5.boundariesElement,
|
|
173
177
|
scrollableElement = _ref5.scrollableElement;
|
|
178
|
+
var isPopupTargetVisibilityEnabled = isExperimentEnabled('platform_editor_popup_target_visibility');
|
|
174
179
|
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], function (states) {
|
|
175
|
-
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$
|
|
180
|
+
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$blockControls4, _states$userIntentSta, _states$blockControls5;
|
|
176
181
|
return {
|
|
177
182
|
menuTriggerBy: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.menuTriggerBy,
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
menuTriggerByNode: isPopupTargetVisibilityEnabled ? (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerByNode : undefined,
|
|
184
|
+
isSelectedViaDragHandle: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.isSelectedViaDragHandle,
|
|
185
|
+
isMenuOpen: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.isMenuOpen,
|
|
180
186
|
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
181
|
-
openedViaKeyboard: (_states$
|
|
187
|
+
openedViaKeyboard: (_states$blockControls5 = states.blockControlsState) === null || _states$blockControls5 === void 0 || (_states$blockControls5 = _states$blockControls5.blockMenuOptions) === null || _states$blockControls5 === void 0 ? void 0 : _states$blockControls5.openedViaKeyboard
|
|
182
188
|
};
|
|
183
189
|
}),
|
|
184
190
|
menuTriggerBy = _useSharedPluginState.menuTriggerBy,
|
|
191
|
+
menuTriggerByNode = _useSharedPluginState.menuTriggerByNode,
|
|
185
192
|
isSelectedViaDragHandle = _useSharedPluginState.isSelectedViaDragHandle,
|
|
186
193
|
isMenuOpen = _useSharedPluginState.isMenuOpen,
|
|
187
194
|
currentUserIntent = _useSharedPluginState.currentUserIntent,
|
|
@@ -219,6 +226,8 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
219
226
|
anchoredToRef.current = menuTriggerBy;
|
|
220
227
|
}
|
|
221
228
|
var targetHandleRef = isExperimentEnabled('platform_editor_block_control_migration') ? (_openMenuHandleRef$cu = openMenuHandleRef.current) !== null && _openMenuHandleRef$cu !== void 0 ? _openMenuHandleRef$cu : surfaceDragHandle : editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
229
|
+
var menuTargetNode = menuTriggerByNode && (editorView === null || editorView === void 0 ? void 0 : editorView.nodeDOM(menuTriggerByNode.pos));
|
|
230
|
+
var visibilityTarget = menuTargetNode instanceof HTMLElement ? menuTargetNode : undefined;
|
|
222
231
|
var closeMenu = React.useCallback(function () {
|
|
223
232
|
api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
|
|
224
233
|
var _api$blockControls, _api$userIntent2;
|
|
@@ -248,19 +257,71 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
248
257
|
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
249
258
|
menuHeight = _React$useState4[0],
|
|
250
259
|
setMenuHeight = _React$useState4[1];
|
|
260
|
+
var _React$useState5 = React.useState({
|
|
261
|
+
isVisible: undefined,
|
|
262
|
+
restoreFocusTo: null
|
|
263
|
+
}),
|
|
264
|
+
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
265
|
+
targetVisibility = _React$useState6[0],
|
|
266
|
+
setTargetVisibility = _React$useState6[1];
|
|
267
|
+
var targetVisible = targetVisibility.isVisible,
|
|
268
|
+
restoreFocusTo = targetVisibility.restoreFocusTo;
|
|
269
|
+
// CSS visibility can move focus to the document body. Preserve the active menu item so the
|
|
270
|
+
// existing focus-loss guard does not close the menus during a temporary scroll transition.
|
|
271
|
+
var handleTargetVisibilityChanged = React.useCallback(function (isVisible) {
|
|
272
|
+
var _popupRef$current;
|
|
273
|
+
if (isVisible) {
|
|
274
|
+
setTargetVisibility(function (current) {
|
|
275
|
+
return {
|
|
276
|
+
isVisible: true,
|
|
277
|
+
restoreFocusTo: current.isVisible === false ? current.restoreFocusTo : null
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Capture focus before scheduling the state update so the updater stays pure.
|
|
284
|
+
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
285
|
+
var activeElement = document.activeElement;
|
|
286
|
+
var isFocusInMenu = activeElement instanceof HTMLElement && (((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.contains(activeElement)) || activeElement.closest(NESTED_DROPDOWN_MENU) !== null);
|
|
287
|
+
setTargetVisibility({
|
|
288
|
+
isVisible: false,
|
|
289
|
+
restoreFocusTo: isFocusInMenu ? activeElement : null
|
|
290
|
+
});
|
|
291
|
+
}, []);
|
|
292
|
+
React.useLayoutEffect(function () {
|
|
293
|
+
if (!isPopupTargetVisibilityEnabled || !targetVisible || !restoreFocusTo) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
var _restoreFocusTo$owner = restoreFocusTo.ownerDocument,
|
|
297
|
+
activeElement = _restoreFocusTo$owner.activeElement,
|
|
298
|
+
body = _restoreFocusTo$owner.body,
|
|
299
|
+
documentElement = _restoreFocusTo$owner.documentElement;
|
|
300
|
+
var focusWasLost = activeElement === null || activeElement === body || activeElement === documentElement;
|
|
301
|
+
if (restoreFocusTo.isConnected && focusWasLost) {
|
|
302
|
+
restoreFocusTo.focus({
|
|
303
|
+
preventScroll: true
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
setTargetVisibility(function (current) {
|
|
307
|
+
return _objectSpread(_objectSpread({}, current), {}, {
|
|
308
|
+
restoreFocusTo: null
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}, [isPopupTargetVisibilityEnabled, restoreFocusTo, targetVisible]);
|
|
251
312
|
var targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
|
|
252
313
|
React.useLayoutEffect(function () {
|
|
253
|
-
var _popupRef$
|
|
314
|
+
var _popupRef$current2;
|
|
254
315
|
if (!isMenuOpen) {
|
|
255
316
|
return;
|
|
256
317
|
}
|
|
257
318
|
onDropdownOpenChanged(true);
|
|
258
|
-
setMenuHeight(((_popupRef$
|
|
319
|
+
setMenuHeight(((_popupRef$current2 = popupRef.current) === null || _popupRef$current2 === void 0 ? void 0 : _popupRef$current2.clientHeight) || FALLBACK_MENU_HEIGHT);
|
|
259
320
|
}, [isMenuOpen, onDropdownOpenChanged]);
|
|
260
321
|
|
|
261
322
|
// Nested dropdowns are portaled outside the block-menu popup. Sparse surface reconciliation
|
|
262
323
|
// dispatches after the menu opens, so a re-render can occur while focus is inside that portal.
|
|
263
|
-
var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) ||
|
|
324
|
+
var hasFocus = (_ref8 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || isPopupTargetVisibilityEnabled && (targetVisible === false || restoreFocusTo !== null) ||
|
|
264
325
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
265
326
|
document.activeElement === targetHandleRef || popupRef.current && (
|
|
266
327
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
@@ -331,6 +392,10 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
331
392
|
if (!(targetHandleRef instanceof HTMLElement)) {
|
|
332
393
|
return null;
|
|
333
394
|
}
|
|
395
|
+
var blockMenuContent = /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
396
|
+
api: api,
|
|
397
|
+
setRef: setRef
|
|
398
|
+
});
|
|
334
399
|
return /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
335
400
|
component: ACTION_SUBJECT.BLOCK_MENU,
|
|
336
401
|
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent,
|
|
@@ -345,11 +410,14 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
345
410
|
boundariesElement: boundariesElement,
|
|
346
411
|
scrollableElement: scrollableElement,
|
|
347
412
|
target: targetHandleRef,
|
|
413
|
+
visibilityTarget: visibilityTarget,
|
|
348
414
|
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
349
415
|
fitWidth: DEFAULT_MENU_WIDTH,
|
|
350
416
|
fitHeight: menuHeight,
|
|
351
417
|
preventOverflow: true,
|
|
352
|
-
stick: true
|
|
418
|
+
stick: true,
|
|
419
|
+
hideWhenTargetOutOfView: isPopupTargetVisibilityEnabled,
|
|
420
|
+
onTargetVisibilityChanged: isPopupTargetVisibilityEnabled ? handleTargetVisibilityChanged : undefined
|
|
353
421
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
354
422
|
,
|
|
355
423
|
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
|
|
@@ -358,10 +426,9 @@ var BlockMenu = function BlockMenu(_ref5) {
|
|
|
358
426
|
{
|
|
359
427
|
initialFocus: undefined
|
|
360
428
|
} : undefined
|
|
361
|
-
}, /*#__PURE__*/React.createElement(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
})));
|
|
429
|
+
}, isPopupTargetVisibilityEnabled ? /*#__PURE__*/React.createElement(BlockMenuTargetVisibilityProvider, {
|
|
430
|
+
value: targetVisible
|
|
431
|
+
}, blockMenuContent) : blockMenuContent));
|
|
365
432
|
};
|
|
366
433
|
|
|
367
434
|
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
|
@@ -6,6 +6,7 @@ import { ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
|
6
6
|
import ChangesIcon from '@atlaskit/icon/core/changes';
|
|
7
7
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
9
|
+
import { useBlockMenuTargetVisibility } from './block-menu-target-visibility-context';
|
|
9
10
|
import { BLOCK_MENU_ITEM_NAME } from './consts';
|
|
10
11
|
var BLOCK_MENU_TRANSFORM_SPOTLIGHT_PORTAL_SELECTOR = '[data-test-id="block-menu-transform-spotlight-portal-container"]';
|
|
11
12
|
var shouldIgnoreBlockMenuTransformSpotlightCloseEvent = function shouldIgnoreBlockMenuTransformSpotlightCloseEvent(event) {
|
|
@@ -16,6 +17,7 @@ export var FormatMenuComponent = function FormatMenuComponent(_ref) {
|
|
|
16
17
|
children = _ref.children;
|
|
17
18
|
var _useIntl = useIntl(),
|
|
18
19
|
formatMessage = _useIntl.formatMessage;
|
|
20
|
+
var targetVisible = useBlockMenuTargetVisibility();
|
|
19
21
|
var formatMenuLabel = blockMenuMessages.changeFormat;
|
|
20
22
|
var handleClick = useCallback(function () {
|
|
21
23
|
api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
|
|
@@ -34,6 +36,7 @@ export var FormatMenuComponent = function FormatMenuComponent(_ref) {
|
|
|
34
36
|
});
|
|
35
37
|
}, [api]);
|
|
36
38
|
return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
|
|
39
|
+
isPopupVisible: targetVisible,
|
|
37
40
|
text: formatMessage(formatMenuLabel),
|
|
38
41
|
elemBefore: /*#__PURE__*/React.createElement(ChangesIcon, {
|
|
39
42
|
label: "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "20.0.
|
|
3
|
+
"version": "20.0.5",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,21 +35,21 @@
|
|
|
35
35
|
"@atlaskit/editor-prosemirror": "^9.0.0",
|
|
36
36
|
"@atlaskit/editor-shared-styles": "^4.3.0",
|
|
37
37
|
"@atlaskit/editor-tables": "^3.2.0",
|
|
38
|
-
"@atlaskit/editor-toolbar": "^2.
|
|
38
|
+
"@atlaskit/editor-toolbar": "^2.8.0",
|
|
39
39
|
"@atlaskit/flag": "^19.0.0",
|
|
40
40
|
"@atlaskit/icon": "^38.0.0",
|
|
41
41
|
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
42
42
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
43
43
|
"@atlaskit/primitives": "^22.5.0",
|
|
44
44
|
"@atlaskit/prosemirror-history": "^1.2.0",
|
|
45
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
45
|
+
"@atlaskit/tmp-editor-statsig": "^209.0.0",
|
|
46
46
|
"@atlaskit/tokens": "^20.0.0",
|
|
47
47
|
"@babel/runtime": "^7.0.0",
|
|
48
48
|
"bind-event-listener": "^3.0.0",
|
|
49
49
|
"memoize-one": "^6.0.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@atlaskit/editor-common": "^125.
|
|
52
|
+
"@atlaskit/editor-common": "^125.4.0",
|
|
53
53
|
"react": "^18.2.0 || ^19.2.0",
|
|
54
54
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
55
55
|
},
|