@atlaskit/editor-plugin-block-menu 4.0.25 → 5.0.0
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 +14 -0
- package/afm-cc/tsconfig.json +3 -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/ui/block-menu.js +103 -40
- package/dist/cjs/ui/copy-link.js +2 -2
- package/dist/cjs/ui/utils/copyLink.js +5 -4
- package/dist/es2019/ui/block-menu.js +90 -27
- package/dist/es2019/ui/copy-link.js +2 -2
- package/dist/es2019/ui/utils/copyLink.js +4 -2
- package/dist/esm/ui/block-menu.js +103 -40
- package/dist/esm/ui/copy-link.js +2 -2
- package/dist/esm/ui/utils/copyLink.js +5 -4
- package/dist/types/blockMenuPluginType.d.ts +3 -2
- package/dist/types/ui/utils/copyLink.d.ts +1 -1
- package/dist/types-ts4.5/blockMenuPluginType.d.ts +3 -2
- package/dist/types-ts4.5/ui/utils/copyLink.d.ts +1 -1
- package/package.json +9 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-menu
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`6e51d74bb2a29`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6e51d74bb2a29) -
|
|
8
|
+
[ux] ED-29560 Use hash instead of query parameter for link to block
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- [`4f5569bde5e64`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4f5569bde5e64) -
|
|
13
|
+
Add new 'dragHandleSelected' user intent, use this to control table toolbar when drag handle is
|
|
14
|
+
selected
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
3
17
|
## 4.0.25
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/afm-cc/tsconfig.json
CHANGED
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
{
|
|
57
57
|
"path": "../../../platform/feature-flags/afm-dev-agents/tsconfig.json"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"path": "../../../platform/feature-flags-react/afm-dev-agents/tsconfig.json"
|
|
61
|
+
},
|
|
59
62
|
{
|
|
60
63
|
"path": "../../../design-system/primitives/afm-dev-agents/tsconfig.json"
|
|
61
64
|
},
|
package/afm-jira/tsconfig.json
CHANGED
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
{
|
|
57
57
|
"path": "../../../platform/feature-flags/afm-passionfruit/tsconfig.json"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"path": "../../../platform/feature-flags-react/afm-passionfruit/tsconfig.json"
|
|
61
|
+
},
|
|
59
62
|
{
|
|
60
63
|
"path": "../../../design-system/primitives/afm-passionfruit/tsconfig.json"
|
|
61
64
|
},
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
{
|
|
57
57
|
"path": "../../../platform/feature-flags/afm-post-office/tsconfig.json"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"path": "../../../platform/feature-flags-react/afm-post-office/tsconfig.json"
|
|
61
|
+
},
|
|
59
62
|
{
|
|
60
63
|
"path": "../../../design-system/primitives/afm-post-office/tsconfig.json"
|
|
61
64
|
},
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
{
|
|
57
57
|
"path": "../../../platform/feature-flags/afm-rovo-extension/tsconfig.json"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"path": "../../../platform/feature-flags-react/afm-rovo-extension/tsconfig.json"
|
|
61
|
+
},
|
|
59
62
|
{
|
|
60
63
|
"path": "../../../design-system/primitives/afm-rovo-extension/tsconfig.json"
|
|
61
64
|
},
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
{
|
|
57
57
|
"path": "../../../platform/feature-flags/afm-townsquare/tsconfig.json"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"path": "../../../platform/feature-flags-react/afm-townsquare/tsconfig.json"
|
|
61
|
+
},
|
|
59
62
|
{
|
|
60
63
|
"path": "../../../design-system/primitives/afm-townsquare/tsconfig.json"
|
|
61
64
|
},
|
|
@@ -19,6 +19,8 @@ var _ui = require("@atlaskit/editor-common/ui");
|
|
|
19
19
|
var _uiReact = require("@atlaskit/editor-common/ui-react");
|
|
20
20
|
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
|
|
21
21
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
22
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
23
|
+
var _platformFeatureFlagsReact = require("@atlaskit/platform-feature-flags-react");
|
|
22
24
|
var _compiled = require("@atlaskit/primitives/compiled");
|
|
23
25
|
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
|
|
24
26
|
var _blockMenuProvider = require("./block-menu-provider");
|
|
@@ -31,10 +33,81 @@ var styles = {
|
|
|
31
33
|
var DEFAULT_MENU_WIDTH = 230;
|
|
32
34
|
var DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
33
35
|
var PopupWithListeners = (0, _uiReact.withReactEditorViewOuterListeners)(_ui.Popup);
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
+
var useConditionalBlockMenuEffect = (0, _platformFeatureFlagsReact.conditionalHooksFactory)(function () {
|
|
37
|
+
return (0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_user_intent_fix');
|
|
38
|
+
}, function (_ref) {
|
|
36
39
|
var api = _ref.api,
|
|
37
|
-
|
|
40
|
+
isMenuOpen = _ref.isMenuOpen,
|
|
41
|
+
menuTriggerBy = _ref.menuTriggerBy,
|
|
42
|
+
selectedByShortcutOrDragHandle = _ref.selectedByShortcutOrDragHandle,
|
|
43
|
+
hasFocus = _ref.hasFocus,
|
|
44
|
+
shouldShowBlockMenuForEmptyLine = _ref.shouldShowBlockMenuForEmptyLine,
|
|
45
|
+
openedViaKeyboard = _ref.openedViaKeyboard,
|
|
46
|
+
prevIsMenuOpenRef = _ref.prevIsMenuOpenRef;
|
|
47
|
+
/**
|
|
48
|
+
* NOTE: do not add `currentUserIntent` to dependency array as it causes unnecessary re-renders and messes with the user intent state
|
|
49
|
+
*/
|
|
50
|
+
(0, _react.useEffect)(function () {
|
|
51
|
+
var _api$userIntent;
|
|
52
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
57
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
58
|
+
var _api$analytics;
|
|
59
|
+
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
|
|
60
|
+
action: _analytics.ACTION.OPENED,
|
|
61
|
+
actionSubject: _analytics.ACTION_SUBJECT.BLOCK_MENU,
|
|
62
|
+
eventType: _analytics.EVENT_TYPE.UI,
|
|
63
|
+
attributes: {
|
|
64
|
+
inputMethod: openedViaKeyboard ? _analytics.INPUT_METHOD.KEYBOARD : _analytics.INPUT_METHOD.MOUSE
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Update the previous state
|
|
70
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
71
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
72
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
73
|
+
}, function (_ref2) {
|
|
74
|
+
var api = _ref2.api,
|
|
75
|
+
isMenuOpen = _ref2.isMenuOpen,
|
|
76
|
+
menuTriggerBy = _ref2.menuTriggerBy,
|
|
77
|
+
selectedByShortcutOrDragHandle = _ref2.selectedByShortcutOrDragHandle,
|
|
78
|
+
hasFocus = _ref2.hasFocus,
|
|
79
|
+
shouldShowBlockMenuForEmptyLine = _ref2.shouldShowBlockMenuForEmptyLine,
|
|
80
|
+
currentUserIntent = _ref2.currentUserIntent,
|
|
81
|
+
openedViaKeyboard = _ref2.openedViaKeyboard,
|
|
82
|
+
prevIsMenuOpenRef = _ref2.prevIsMenuOpenRef;
|
|
83
|
+
(0, _react.useEffect)(function () {
|
|
84
|
+
var _api$userIntent2;
|
|
85
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
90
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
91
|
+
var _api$analytics2;
|
|
92
|
+
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
|
|
93
|
+
action: _analytics.ACTION.OPENED,
|
|
94
|
+
actionSubject: _analytics.ACTION_SUBJECT.BLOCK_MENU,
|
|
95
|
+
eventType: _analytics.EVENT_TYPE.UI,
|
|
96
|
+
attributes: {
|
|
97
|
+
inputMethod: openedViaKeyboard ? _analytics.INPUT_METHOD.KEYBOARD : _analytics.INPUT_METHOD.MOUSE
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Update the previous state
|
|
103
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
104
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
105
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
106
|
+
});
|
|
107
|
+
var BlockMenuContent = function BlockMenuContent(_ref3) {
|
|
108
|
+
var _api$blockMenu;
|
|
109
|
+
var api = _ref3.api,
|
|
110
|
+
setRef = _ref3.setRef;
|
|
38
111
|
var blockMenuComponents = api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 ? void 0 : _api$blockMenu.actions.getBlockMenuComponents();
|
|
39
112
|
var setOutsideClickTargetRef = (0, _react.useContext)(_uiReact.OutsideClickTargetRefContext);
|
|
40
113
|
var ref = function ref(el) {
|
|
@@ -63,13 +136,13 @@ var BlockMenuContent = function BlockMenuContent(_ref) {
|
|
|
63
136
|
}
|
|
64
137
|
}));
|
|
65
138
|
};
|
|
66
|
-
var BlockMenu = function BlockMenu(
|
|
67
|
-
var _editorView$dom,
|
|
68
|
-
var editorView =
|
|
69
|
-
api =
|
|
70
|
-
mountTo =
|
|
71
|
-
boundariesElement =
|
|
72
|
-
scrollableElement =
|
|
139
|
+
var BlockMenu = function BlockMenu(_ref4) {
|
|
140
|
+
var _editorView$dom, _ref5, _editorView$hasFocus;
|
|
141
|
+
var editorView = _ref4.editorView,
|
|
142
|
+
api = _ref4.api,
|
|
143
|
+
mountTo = _ref4.mountTo,
|
|
144
|
+
boundariesElement = _ref4.boundariesElement,
|
|
145
|
+
scrollableElement = _ref4.scrollableElement;
|
|
73
146
|
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls', 'userIntent'], function (states) {
|
|
74
147
|
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
|
|
75
148
|
return {
|
|
@@ -90,49 +163,39 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
90
163
|
var targetHandleRef = editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(_styles.DRAG_HANDLE_SELECTOR);
|
|
91
164
|
var prevIsMenuOpenRef = (0, _react.useRef)(false);
|
|
92
165
|
var popupRef = (0, _react.useRef)(undefined);
|
|
93
|
-
var hasFocus = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? (
|
|
166
|
+
var hasFocus = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? (_ref5 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || document.activeElement === targetHandleRef || popupRef.current && (popupRef.current.contains(document.activeElement) || popupRef.current === document.activeElement)) !== null && _ref5 !== void 0 ? _ref5 : false : (_editorView$hasFocus = editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) !== null && _editorView$hasFocus !== void 0 ? _editorView$hasFocus : false;
|
|
94
167
|
var hasSelection = !!editorView && !editorView.state.selection.empty;
|
|
95
168
|
// hasSelection true, always show block menu
|
|
96
169
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
97
170
|
var shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
98
|
-
var selectedByShortcutOrDragHandle = isSelectedViaDragHandle || openedViaKeyboard && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
99
|
-
(0, _react.useEffect)(function () {
|
|
100
|
-
var _api$userIntent;
|
|
101
|
-
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
171
|
+
var selectedByShortcutOrDragHandle = !!isSelectedViaDragHandle || !!openedViaKeyboard && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
104
172
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// Update the previous state
|
|
119
|
-
prevIsMenuOpenRef.current = isMenuOpen;
|
|
120
|
-
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
121
|
-
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard]);
|
|
173
|
+
// Use conditional hook based on feature flag
|
|
174
|
+
useConditionalBlockMenuEffect({
|
|
175
|
+
api: api,
|
|
176
|
+
isMenuOpen: isMenuOpen,
|
|
177
|
+
menuTriggerBy: menuTriggerBy,
|
|
178
|
+
selectedByShortcutOrDragHandle: selectedByShortcutOrDragHandle,
|
|
179
|
+
hasFocus: hasFocus,
|
|
180
|
+
shouldShowBlockMenuForEmptyLine: shouldShowBlockMenuForEmptyLine,
|
|
181
|
+
currentUserIntent: (0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_user_intent_fix') ? undefined : currentUserIntent,
|
|
182
|
+
openedViaKeyboard: openedViaKeyboard,
|
|
183
|
+
prevIsMenuOpenRef: prevIsMenuOpenRef
|
|
184
|
+
});
|
|
122
185
|
if (!isMenuOpen) {
|
|
123
186
|
return null;
|
|
124
187
|
}
|
|
125
188
|
var closeMenu = function closeMenu() {
|
|
126
|
-
api === null || api === void 0 || api.core.actions.execute(function (
|
|
127
|
-
var _api$blockControls, _api$
|
|
128
|
-
var tr =
|
|
189
|
+
api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
|
|
190
|
+
var _api$blockControls, _api$userIntent3;
|
|
191
|
+
var tr = _ref6.tr;
|
|
129
192
|
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu({
|
|
130
193
|
closeMenu: true
|
|
131
194
|
})({
|
|
132
195
|
tr: tr
|
|
133
196
|
});
|
|
134
197
|
onDropdownOpenChanged(false);
|
|
135
|
-
api === null || api === void 0 || (_api$
|
|
198
|
+
api === null || api === void 0 || (_api$userIntent3 = api.userIntent) === null || _api$userIntent3 === void 0 || _api$userIntent3.commands.setCurrentUserIntent(currentUserIntent === 'blockMenuOpen' ? 'default' : currentUserIntent || 'default')({
|
|
136
199
|
tr: tr
|
|
137
200
|
});
|
|
138
201
|
return tr;
|
|
@@ -148,10 +211,10 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
148
211
|
}
|
|
149
212
|
};
|
|
150
213
|
if (targetHandleRef instanceof HTMLElement) {
|
|
151
|
-
var _api$
|
|
214
|
+
var _api$analytics3;
|
|
152
215
|
return /*#__PURE__*/_react.default.createElement(_errorBoundary.ErrorBoundary, {
|
|
153
216
|
component: _analytics.ACTION_SUBJECT.BLOCK_MENU,
|
|
154
|
-
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$
|
|
217
|
+
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
|
|
155
218
|
fallbackComponent: null
|
|
156
219
|
}, /*#__PURE__*/_react.default.createElement(PopupWithListeners, {
|
|
157
220
|
alignX: 'right',
|
package/dist/cjs/ui/copy-link.js
CHANGED
|
@@ -46,8 +46,8 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
46
46
|
return tr;
|
|
47
47
|
});
|
|
48
48
|
onDropdownOpenChanged(false);
|
|
49
|
-
return (0, _copyLink.copyLink)(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
50
|
-
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
49
|
+
return (0, _copyLink.copyLink)(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api);
|
|
50
|
+
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api, onDropdownOpenChanged]);
|
|
51
51
|
var checkIsNestedNode = (0, _react.useCallback)(function () {
|
|
52
52
|
var _api$selection, _api$blockControls2;
|
|
53
53
|
var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
@@ -7,12 +7,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.copyLink = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
+
var _blockMenu = require("@atlaskit/editor-common/block-menu");
|
|
10
11
|
var _clipboard = require("@atlaskit/editor-common/clipboard");
|
|
11
12
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
13
|
var _editorTables = require("@atlaskit/editor-tables");
|
|
13
14
|
var copyLink = exports.copyLink = /*#__PURE__*/function () {
|
|
14
15
|
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(getLinkPath) {
|
|
15
|
-
var
|
|
16
|
+
var blockLinkHashPrefix,
|
|
16
17
|
api,
|
|
17
18
|
_api$selection,
|
|
18
19
|
node,
|
|
@@ -24,7 +25,7 @@ var copyLink = exports.copyLink = /*#__PURE__*/function () {
|
|
|
24
25
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
25
26
|
while (1) switch (_context.prev = _context.next) {
|
|
26
27
|
case 0:
|
|
27
|
-
|
|
28
|
+
blockLinkHashPrefix = _args.length > 1 && _args[1] !== undefined ? _args[1] : _blockMenu.DEFAULT_BLOCK_LINK_HASH_PREFIX;
|
|
28
29
|
api = _args.length > 2 ? _args[2] : undefined;
|
|
29
30
|
_context.prev = 2;
|
|
30
31
|
selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
@@ -48,8 +49,8 @@ var copyLink = exports.copyLink = /*#__PURE__*/function () {
|
|
|
48
49
|
}
|
|
49
50
|
return _context.abrupt("return", false);
|
|
50
51
|
case 10:
|
|
51
|
-
url = new URL(location.origin + path);
|
|
52
|
-
url.
|
|
52
|
+
url = new URL(location.origin + path); // append the localId as a hash fragment in the form #block-{localId}
|
|
53
|
+
url.hash = "".concat(blockLinkHashPrefix).concat(node.attrs.localId);
|
|
53
54
|
href = url.toString();
|
|
54
55
|
_context.next = 15;
|
|
55
56
|
return (0, _clipboard.copyToClipboard)(href);
|
|
@@ -12,6 +12,8 @@ import { Popup } from '@atlaskit/editor-common/ui';
|
|
|
12
12
|
import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
|
|
13
13
|
import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
|
|
14
14
|
import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
15
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
16
|
+
import { conditionalHooksFactory } from '@atlaskit/platform-feature-flags-react';
|
|
15
17
|
import { Box } from '@atlaskit/primitives/compiled';
|
|
16
18
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
17
19
|
import { useBlockMenu } from './block-menu-provider';
|
|
@@ -23,6 +25,77 @@ const styles = {
|
|
|
23
25
|
const DEFAULT_MENU_WIDTH = 230;
|
|
24
26
|
const DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
25
27
|
const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
|
|
28
|
+
const useConditionalBlockMenuEffect = conditionalHooksFactory(() => fg('platform_editor_toolbar_aifc_user_intent_fix'), ({
|
|
29
|
+
api,
|
|
30
|
+
isMenuOpen,
|
|
31
|
+
menuTriggerBy,
|
|
32
|
+
selectedByShortcutOrDragHandle,
|
|
33
|
+
hasFocus,
|
|
34
|
+
shouldShowBlockMenuForEmptyLine,
|
|
35
|
+
openedViaKeyboard,
|
|
36
|
+
prevIsMenuOpenRef
|
|
37
|
+
}) => {
|
|
38
|
+
/**
|
|
39
|
+
* NOTE: do not add `currentUserIntent` to dependency array as it causes unnecessary re-renders and messes with the user intent state
|
|
40
|
+
*/
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
var _api$userIntent;
|
|
43
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
48
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
49
|
+
var _api$analytics;
|
|
50
|
+
api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent({
|
|
51
|
+
action: ACTION.OPENED,
|
|
52
|
+
actionSubject: ACTION_SUBJECT.BLOCK_MENU,
|
|
53
|
+
eventType: EVENT_TYPE.UI,
|
|
54
|
+
attributes: {
|
|
55
|
+
inputMethod: openedViaKeyboard ? INPUT_METHOD.KEYBOARD : INPUT_METHOD.MOUSE
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Update the previous state
|
|
61
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
62
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
63
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
64
|
+
}, ({
|
|
65
|
+
api,
|
|
66
|
+
isMenuOpen,
|
|
67
|
+
menuTriggerBy,
|
|
68
|
+
selectedByShortcutOrDragHandle,
|
|
69
|
+
hasFocus,
|
|
70
|
+
shouldShowBlockMenuForEmptyLine,
|
|
71
|
+
currentUserIntent,
|
|
72
|
+
openedViaKeyboard,
|
|
73
|
+
prevIsMenuOpenRef
|
|
74
|
+
}) => {
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
var _api$userIntent2;
|
|
77
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
82
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
83
|
+
var _api$analytics2;
|
|
84
|
+
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent({
|
|
85
|
+
action: ACTION.OPENED,
|
|
86
|
+
actionSubject: ACTION_SUBJECT.BLOCK_MENU,
|
|
87
|
+
eventType: EVENT_TYPE.UI,
|
|
88
|
+
attributes: {
|
|
89
|
+
inputMethod: openedViaKeyboard ? INPUT_METHOD.KEYBOARD : INPUT_METHOD.MOUSE
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Update the previous state
|
|
95
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
96
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
97
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
98
|
+
});
|
|
26
99
|
const BlockMenuContent = ({
|
|
27
100
|
api,
|
|
28
101
|
setRef
|
|
@@ -85,30 +158,20 @@ const BlockMenu = ({
|
|
|
85
158
|
// hasSelection true, always show block menu
|
|
86
159
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
87
160
|
const shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
88
|
-
const selectedByShortcutOrDragHandle = isSelectedViaDragHandle || openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
var _api$userIntent;
|
|
91
|
-
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
161
|
+
const selectedByShortcutOrDragHandle = !!isSelectedViaDragHandle || !!openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
94
162
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// Update the previous state
|
|
109
|
-
prevIsMenuOpenRef.current = isMenuOpen;
|
|
110
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
111
|
-
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard]);
|
|
163
|
+
// Use conditional hook based on feature flag
|
|
164
|
+
useConditionalBlockMenuEffect({
|
|
165
|
+
api,
|
|
166
|
+
isMenuOpen,
|
|
167
|
+
menuTriggerBy,
|
|
168
|
+
selectedByShortcutOrDragHandle,
|
|
169
|
+
hasFocus,
|
|
170
|
+
shouldShowBlockMenuForEmptyLine,
|
|
171
|
+
currentUserIntent: fg('platform_editor_toolbar_aifc_user_intent_fix') ? undefined : currentUserIntent,
|
|
172
|
+
openedViaKeyboard,
|
|
173
|
+
prevIsMenuOpenRef
|
|
174
|
+
});
|
|
112
175
|
if (!isMenuOpen) {
|
|
113
176
|
return null;
|
|
114
177
|
}
|
|
@@ -116,14 +179,14 @@ const BlockMenu = ({
|
|
|
116
179
|
api === null || api === void 0 ? void 0 : api.core.actions.execute(({
|
|
117
180
|
tr
|
|
118
181
|
}) => {
|
|
119
|
-
var _api$blockControls, _api$
|
|
182
|
+
var _api$blockControls, _api$userIntent3;
|
|
120
183
|
api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.commands.toggleBlockMenu({
|
|
121
184
|
closeMenu: true
|
|
122
185
|
})({
|
|
123
186
|
tr
|
|
124
187
|
});
|
|
125
188
|
onDropdownOpenChanged(false);
|
|
126
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
189
|
+
api === null || api === void 0 ? void 0 : (_api$userIntent3 = api.userIntent) === null || _api$userIntent3 === void 0 ? void 0 : _api$userIntent3.commands.setCurrentUserIntent(currentUserIntent === 'blockMenuOpen' ? 'default' : currentUserIntent || 'default')({
|
|
127
190
|
tr
|
|
128
191
|
});
|
|
129
192
|
return tr;
|
|
@@ -139,10 +202,10 @@ const BlockMenu = ({
|
|
|
139
202
|
}
|
|
140
203
|
};
|
|
141
204
|
if (targetHandleRef instanceof HTMLElement) {
|
|
142
|
-
var _api$
|
|
205
|
+
var _api$analytics3;
|
|
143
206
|
return /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
144
207
|
component: ACTION_SUBJECT.BLOCK_MENU,
|
|
145
|
-
dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$
|
|
208
|
+
dispatchAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
|
|
146
209
|
fallbackComponent: null
|
|
147
210
|
}, /*#__PURE__*/React.createElement(PopupWithListeners, {
|
|
148
211
|
alignX: 'right',
|
|
@@ -41,8 +41,8 @@ const CopyLinkDropdownItemContent = ({
|
|
|
41
41
|
return tr;
|
|
42
42
|
});
|
|
43
43
|
onDropdownOpenChanged(false);
|
|
44
|
-
return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
45
|
-
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
44
|
+
return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api);
|
|
45
|
+
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api, onDropdownOpenChanged]);
|
|
46
46
|
const checkIsNestedNode = useCallback(() => {
|
|
47
47
|
var _api$selection, _api$selection$shared, _api$selection$shared2, _api$blockControls2, _api$blockControls2$s, _api$blockControls2$s2;
|
|
48
48
|
const selection = api === null || api === void 0 ? void 0 : (_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : (_api$selection$shared = _api$selection.sharedState) === null || _api$selection$shared === void 0 ? void 0 : (_api$selection$shared2 = _api$selection$shared.currentState()) === null || _api$selection$shared2 === void 0 ? void 0 : _api$selection$shared2.selection;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { DEFAULT_BLOCK_LINK_HASH_PREFIX } from '@atlaskit/editor-common/block-menu';
|
|
1
2
|
import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
|
|
2
3
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
4
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
4
|
-
export const copyLink = async (getLinkPath,
|
|
5
|
+
export const copyLink = async (getLinkPath, blockLinkHashPrefix = DEFAULT_BLOCK_LINK_HASH_PREFIX, api) => {
|
|
5
6
|
try {
|
|
6
7
|
var _api$selection, _api$selection$shared;
|
|
7
8
|
let node;
|
|
@@ -21,7 +22,8 @@ export const copyLink = async (getLinkPath, blockQueryParam = 'block', api) => {
|
|
|
21
22
|
return false;
|
|
22
23
|
}
|
|
23
24
|
const url = new URL(location.origin + path);
|
|
24
|
-
|
|
25
|
+
// append the localId as a hash fragment in the form #block-{localId}
|
|
26
|
+
url.hash = `${blockLinkHashPrefix}${node.attrs.localId}`;
|
|
25
27
|
const href = url.toString();
|
|
26
28
|
await copyToClipboard(href);
|
|
27
29
|
return true;
|
|
@@ -12,6 +12,8 @@ import { Popup } from '@atlaskit/editor-common/ui';
|
|
|
12
12
|
import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
|
|
13
13
|
import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
|
|
14
14
|
import { ToolbarDropdownItem, ToolbarDropdownItemSection, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
|
|
15
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
16
|
+
import { conditionalHooksFactory } from '@atlaskit/platform-feature-flags-react';
|
|
15
17
|
import { Box } from '@atlaskit/primitives/compiled';
|
|
16
18
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
17
19
|
import { useBlockMenu } from './block-menu-provider';
|
|
@@ -23,10 +25,81 @@ var styles = {
|
|
|
23
25
|
var DEFAULT_MENU_WIDTH = 230;
|
|
24
26
|
var DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
25
27
|
var PopupWithListeners = withReactEditorViewOuterListeners(Popup);
|
|
26
|
-
var
|
|
27
|
-
|
|
28
|
+
var useConditionalBlockMenuEffect = conditionalHooksFactory(function () {
|
|
29
|
+
return fg('platform_editor_toolbar_aifc_user_intent_fix');
|
|
30
|
+
}, function (_ref) {
|
|
28
31
|
var api = _ref.api,
|
|
29
|
-
|
|
32
|
+
isMenuOpen = _ref.isMenuOpen,
|
|
33
|
+
menuTriggerBy = _ref.menuTriggerBy,
|
|
34
|
+
selectedByShortcutOrDragHandle = _ref.selectedByShortcutOrDragHandle,
|
|
35
|
+
hasFocus = _ref.hasFocus,
|
|
36
|
+
shouldShowBlockMenuForEmptyLine = _ref.shouldShowBlockMenuForEmptyLine,
|
|
37
|
+
openedViaKeyboard = _ref.openedViaKeyboard,
|
|
38
|
+
prevIsMenuOpenRef = _ref.prevIsMenuOpenRef;
|
|
39
|
+
/**
|
|
40
|
+
* NOTE: do not add `currentUserIntent` to dependency array as it causes unnecessary re-renders and messes with the user intent state
|
|
41
|
+
*/
|
|
42
|
+
useEffect(function () {
|
|
43
|
+
var _api$userIntent;
|
|
44
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
49
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
50
|
+
var _api$analytics;
|
|
51
|
+
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
|
|
52
|
+
action: ACTION.OPENED,
|
|
53
|
+
actionSubject: ACTION_SUBJECT.BLOCK_MENU,
|
|
54
|
+
eventType: EVENT_TYPE.UI,
|
|
55
|
+
attributes: {
|
|
56
|
+
inputMethod: openedViaKeyboard ? INPUT_METHOD.KEYBOARD : INPUT_METHOD.MOUSE
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Update the previous state
|
|
62
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
63
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
64
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
65
|
+
}, function (_ref2) {
|
|
66
|
+
var api = _ref2.api,
|
|
67
|
+
isMenuOpen = _ref2.isMenuOpen,
|
|
68
|
+
menuTriggerBy = _ref2.menuTriggerBy,
|
|
69
|
+
selectedByShortcutOrDragHandle = _ref2.selectedByShortcutOrDragHandle,
|
|
70
|
+
hasFocus = _ref2.hasFocus,
|
|
71
|
+
shouldShowBlockMenuForEmptyLine = _ref2.shouldShowBlockMenuForEmptyLine,
|
|
72
|
+
currentUserIntent = _ref2.currentUserIntent,
|
|
73
|
+
openedViaKeyboard = _ref2.openedViaKeyboard,
|
|
74
|
+
prevIsMenuOpenRef = _ref2.prevIsMenuOpenRef;
|
|
75
|
+
useEffect(function () {
|
|
76
|
+
var _api$userIntent2;
|
|
77
|
+
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Fire analytics event when block menu opens (only on first transition from closed to open)
|
|
82
|
+
if (!prevIsMenuOpenRef.current && isMenuOpen) {
|
|
83
|
+
var _api$analytics2;
|
|
84
|
+
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
|
|
85
|
+
action: ACTION.OPENED,
|
|
86
|
+
actionSubject: ACTION_SUBJECT.BLOCK_MENU,
|
|
87
|
+
eventType: EVENT_TYPE.UI,
|
|
88
|
+
attributes: {
|
|
89
|
+
inputMethod: openedViaKeyboard ? INPUT_METHOD.KEYBOARD : INPUT_METHOD.MOUSE
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Update the previous state
|
|
95
|
+
prevIsMenuOpenRef.current = isMenuOpen;
|
|
96
|
+
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
97
|
+
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard, prevIsMenuOpenRef]);
|
|
98
|
+
});
|
|
99
|
+
var BlockMenuContent = function BlockMenuContent(_ref3) {
|
|
100
|
+
var _api$blockMenu;
|
|
101
|
+
var api = _ref3.api,
|
|
102
|
+
setRef = _ref3.setRef;
|
|
30
103
|
var blockMenuComponents = api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 ? void 0 : _api$blockMenu.actions.getBlockMenuComponents();
|
|
31
104
|
var setOutsideClickTargetRef = useContext(OutsideClickTargetRefContext);
|
|
32
105
|
var ref = function ref(el) {
|
|
@@ -55,13 +128,13 @@ var BlockMenuContent = function BlockMenuContent(_ref) {
|
|
|
55
128
|
}
|
|
56
129
|
}));
|
|
57
130
|
};
|
|
58
|
-
var BlockMenu = function BlockMenu(
|
|
59
|
-
var _editorView$dom,
|
|
60
|
-
var editorView =
|
|
61
|
-
api =
|
|
62
|
-
mountTo =
|
|
63
|
-
boundariesElement =
|
|
64
|
-
scrollableElement =
|
|
131
|
+
var BlockMenu = function BlockMenu(_ref4) {
|
|
132
|
+
var _editorView$dom, _ref5, _editorView$hasFocus;
|
|
133
|
+
var editorView = _ref4.editorView,
|
|
134
|
+
api = _ref4.api,
|
|
135
|
+
mountTo = _ref4.mountTo,
|
|
136
|
+
boundariesElement = _ref4.boundariesElement,
|
|
137
|
+
scrollableElement = _ref4.scrollableElement;
|
|
65
138
|
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['blockControls', 'userIntent'], function (states) {
|
|
66
139
|
var _states$blockControls, _states$blockControls2, _states$blockControls3, _states$userIntentSta, _states$blockControls4;
|
|
67
140
|
return {
|
|
@@ -82,49 +155,39 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
82
155
|
var targetHandleRef = editorView === null || editorView === void 0 || (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
83
156
|
var prevIsMenuOpenRef = useRef(false);
|
|
84
157
|
var popupRef = useRef(undefined);
|
|
85
|
-
var hasFocus = expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? (
|
|
158
|
+
var hasFocus = expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true) ? (_ref5 = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || document.activeElement === targetHandleRef || popupRef.current && (popupRef.current.contains(document.activeElement) || popupRef.current === document.activeElement)) !== null && _ref5 !== void 0 ? _ref5 : false : (_editorView$hasFocus = editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) !== null && _editorView$hasFocus !== void 0 ? _editorView$hasFocus : false;
|
|
86
159
|
var hasSelection = !!editorView && !editorView.state.selection.empty;
|
|
87
160
|
// hasSelection true, always show block menu
|
|
88
161
|
// hasSelection false, only show block menu when empty line experiment is enabled
|
|
89
162
|
var shouldShowBlockMenuForEmptyLine = hasSelection || !hasSelection && expValEqualsNoExposure('platform_editor_block_menu_empty_line', 'isEnabled', true);
|
|
90
|
-
var selectedByShortcutOrDragHandle = isSelectedViaDragHandle || openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
91
|
-
useEffect(function () {
|
|
92
|
-
var _api$userIntent;
|
|
93
|
-
if (!isMenuOpen || !menuTriggerBy || !selectedByShortcutOrDragHandle || !hasFocus || !shouldShowBlockMenuForEmptyLine || ['resizing', 'dragging'].includes(currentUserIntent || '')) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
163
|
+
var selectedByShortcutOrDragHandle = !!isSelectedViaDragHandle || !!openedViaKeyboard && expValEqualsNoExposure('platform_editor_block_menu_keyboard_navigation', 'isEnabled', true);
|
|
96
164
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// Update the previous state
|
|
111
|
-
prevIsMenuOpenRef.current = isMenuOpen;
|
|
112
|
-
api === null || api === void 0 || api.core.actions.execute(api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('blockMenuOpen'));
|
|
113
|
-
}, [api, isMenuOpen, menuTriggerBy, selectedByShortcutOrDragHandle, hasFocus, shouldShowBlockMenuForEmptyLine, currentUserIntent, openedViaKeyboard]);
|
|
165
|
+
// Use conditional hook based on feature flag
|
|
166
|
+
useConditionalBlockMenuEffect({
|
|
167
|
+
api: api,
|
|
168
|
+
isMenuOpen: isMenuOpen,
|
|
169
|
+
menuTriggerBy: menuTriggerBy,
|
|
170
|
+
selectedByShortcutOrDragHandle: selectedByShortcutOrDragHandle,
|
|
171
|
+
hasFocus: hasFocus,
|
|
172
|
+
shouldShowBlockMenuForEmptyLine: shouldShowBlockMenuForEmptyLine,
|
|
173
|
+
currentUserIntent: fg('platform_editor_toolbar_aifc_user_intent_fix') ? undefined : currentUserIntent,
|
|
174
|
+
openedViaKeyboard: openedViaKeyboard,
|
|
175
|
+
prevIsMenuOpenRef: prevIsMenuOpenRef
|
|
176
|
+
});
|
|
114
177
|
if (!isMenuOpen) {
|
|
115
178
|
return null;
|
|
116
179
|
}
|
|
117
180
|
var closeMenu = function closeMenu() {
|
|
118
|
-
api === null || api === void 0 || api.core.actions.execute(function (
|
|
119
|
-
var _api$blockControls, _api$
|
|
120
|
-
var tr =
|
|
181
|
+
api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
|
|
182
|
+
var _api$blockControls, _api$userIntent3;
|
|
183
|
+
var tr = _ref6.tr;
|
|
121
184
|
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || _api$blockControls.commands.toggleBlockMenu({
|
|
122
185
|
closeMenu: true
|
|
123
186
|
})({
|
|
124
187
|
tr: tr
|
|
125
188
|
});
|
|
126
189
|
onDropdownOpenChanged(false);
|
|
127
|
-
api === null || api === void 0 || (_api$
|
|
190
|
+
api === null || api === void 0 || (_api$userIntent3 = api.userIntent) === null || _api$userIntent3 === void 0 || _api$userIntent3.commands.setCurrentUserIntent(currentUserIntent === 'blockMenuOpen' ? 'default' : currentUserIntent || 'default')({
|
|
128
191
|
tr: tr
|
|
129
192
|
});
|
|
130
193
|
return tr;
|
|
@@ -140,10 +203,10 @@ var BlockMenu = function BlockMenu(_ref2) {
|
|
|
140
203
|
}
|
|
141
204
|
};
|
|
142
205
|
if (targetHandleRef instanceof HTMLElement) {
|
|
143
|
-
var _api$
|
|
206
|
+
var _api$analytics3;
|
|
144
207
|
return /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
145
208
|
component: ACTION_SUBJECT.BLOCK_MENU,
|
|
146
|
-
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$
|
|
209
|
+
dispatchAnalyticsEvent: api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent,
|
|
147
210
|
fallbackComponent: null
|
|
148
211
|
}, /*#__PURE__*/React.createElement(PopupWithListeners, {
|
|
149
212
|
alignX: 'right',
|
package/dist/esm/ui/copy-link.js
CHANGED
|
@@ -37,8 +37,8 @@ var CopyLinkDropdownItemContent = function CopyLinkDropdownItemContent(_ref) {
|
|
|
37
37
|
return tr;
|
|
38
38
|
});
|
|
39
39
|
onDropdownOpenChanged(false);
|
|
40
|
-
return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
41
|
-
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.
|
|
40
|
+
return copyLink(config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api);
|
|
41
|
+
}, [config === null || config === void 0 ? void 0 : config.getLinkPath, config === null || config === void 0 ? void 0 : config.blockLinkHashPrefix, api, onDropdownOpenChanged]);
|
|
42
42
|
var checkIsNestedNode = useCallback(function () {
|
|
43
43
|
var _api$selection, _api$blockControls2;
|
|
44
44
|
var selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState) === null || _api$selection === void 0 || (_api$selection = _api$selection.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
2
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { DEFAULT_BLOCK_LINK_HASH_PREFIX } from '@atlaskit/editor-common/block-menu';
|
|
3
4
|
import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
|
|
4
5
|
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
5
6
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
6
7
|
export var copyLink = /*#__PURE__*/function () {
|
|
7
8
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(getLinkPath) {
|
|
8
|
-
var
|
|
9
|
+
var blockLinkHashPrefix,
|
|
9
10
|
api,
|
|
10
11
|
_api$selection,
|
|
11
12
|
node,
|
|
@@ -17,7 +18,7 @@ export var copyLink = /*#__PURE__*/function () {
|
|
|
17
18
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
18
19
|
while (1) switch (_context.prev = _context.next) {
|
|
19
20
|
case 0:
|
|
20
|
-
|
|
21
|
+
blockLinkHashPrefix = _args.length > 1 && _args[1] !== undefined ? _args[1] : DEFAULT_BLOCK_LINK_HASH_PREFIX;
|
|
21
22
|
api = _args.length > 2 ? _args[2] : undefined;
|
|
22
23
|
_context.prev = 2;
|
|
23
24
|
selection = api === null || api === void 0 || (_api$selection = api.selection) === null || _api$selection === void 0 || (_api$selection = _api$selection.sharedState.currentState()) === null || _api$selection === void 0 ? void 0 : _api$selection.selection;
|
|
@@ -41,8 +42,8 @@ export var copyLink = /*#__PURE__*/function () {
|
|
|
41
42
|
}
|
|
42
43
|
return _context.abrupt("return", false);
|
|
43
44
|
case 10:
|
|
44
|
-
url = new URL(location.origin + path);
|
|
45
|
-
url.
|
|
45
|
+
url = new URL(location.origin + path); // append the localId as a hash fragment in the form #block-{localId}
|
|
46
|
+
url.hash = "".concat(blockLinkHashPrefix).concat(node.attrs.localId);
|
|
46
47
|
href = url.toString();
|
|
47
48
|
_context.next = 15;
|
|
48
49
|
return copyToClipboard(href);
|
|
@@ -25,9 +25,10 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
|
25
25
|
}>;
|
|
26
26
|
export type BlockMenuPluginOptions = {
|
|
27
27
|
/**
|
|
28
|
-
* Optional
|
|
28
|
+
* Optional hash prefix used for block-specific URL to create a deep link to specific block
|
|
29
|
+
* Default value from DEFAULT_BLOCK_LINK_HASH_PREFIX in @atlaskit/editor-common/block-menu
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
+
blockLinkHashPrefix?: string;
|
|
31
32
|
/**
|
|
32
33
|
* Optional function to retrieve the current link path for the editor context.
|
|
33
34
|
* @returns The current link path as a string, or null if no path is available
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { BlockMenuPlugin } from '../../blockMenuPluginType';
|
|
3
|
-
export declare const copyLink: (getLinkPath?: () => string | null,
|
|
3
|
+
export declare const copyLink: (getLinkPath?: () => string | null, blockLinkHashPrefix?: string, api?: ExtractInjectionAPI<BlockMenuPlugin>) => Promise<boolean>;
|
|
@@ -25,9 +25,10 @@ export type BlockMenuPlugin = NextEditorPlugin<'blockMenu', {
|
|
|
25
25
|
}>;
|
|
26
26
|
export type BlockMenuPluginOptions = {
|
|
27
27
|
/**
|
|
28
|
-
* Optional
|
|
28
|
+
* Optional hash prefix used for block-specific URL to create a deep link to specific block
|
|
29
|
+
* Default value from DEFAULT_BLOCK_LINK_HASH_PREFIX in @atlaskit/editor-common/block-menu
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
+
blockLinkHashPrefix?: string;
|
|
31
32
|
/**
|
|
32
33
|
* Optional function to retrieve the current link path for the editor context.
|
|
33
34
|
* @returns The current link path as a string, or null if no path is available
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
2
|
import type { BlockMenuPlugin } from '../../blockMenuPluginType';
|
|
3
|
-
export declare const copyLink: (getLinkPath?: () => string | null,
|
|
3
|
+
export declare const copyLink: (getLinkPath?: () => string | null, blockLinkHashPrefix?: string, api?: ExtractInjectionAPI<BlockMenuPlugin>) => Promise<boolean>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-menu",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "BlockMenu plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,24 +31,25 @@
|
|
|
31
31
|
"@atlaskit/css": "^0.15.0",
|
|
32
32
|
"@atlaskit/dropdown-menu": "^16.3.0",
|
|
33
33
|
"@atlaskit/editor-plugin-analytics": "^6.2.0",
|
|
34
|
-
"@atlaskit/editor-plugin-block-controls": "^7.
|
|
34
|
+
"@atlaskit/editor-plugin-block-controls": "^7.4.0",
|
|
35
35
|
"@atlaskit/editor-plugin-decorations": "^6.1.0",
|
|
36
36
|
"@atlaskit/editor-plugin-selection": "^6.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-user-intent": "^4.0.0",
|
|
38
38
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
39
|
-
"@atlaskit/editor-shared-styles": "^3.
|
|
39
|
+
"@atlaskit/editor-shared-styles": "^3.8.0",
|
|
40
40
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
41
41
|
"@atlaskit/editor-toolbar": "^0.15.0",
|
|
42
42
|
"@atlaskit/icon": "^28.5.0",
|
|
43
43
|
"@atlaskit/icon-lab": "^5.10.0",
|
|
44
44
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
45
|
+
"@atlaskit/platform-feature-flags-react": "^0.3.0",
|
|
45
46
|
"@atlaskit/primitives": "^16.0.0",
|
|
46
|
-
"@atlaskit/tmp-editor-statsig": "^13.
|
|
47
|
+
"@atlaskit/tmp-editor-statsig": "^13.16.0",
|
|
47
48
|
"@atlaskit/tokens": "^7.0.0",
|
|
48
49
|
"@babel/runtime": "^7.0.0"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
|
-
"@atlaskit/editor-common": "^110.
|
|
52
|
+
"@atlaskit/editor-common": "^110.15.0",
|
|
52
53
|
"react": "^18.2.0",
|
|
53
54
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
54
55
|
},
|
|
@@ -109,6 +110,9 @@
|
|
|
109
110
|
},
|
|
110
111
|
"platform_editor_block_menu_shouldfitcontainer": {
|
|
111
112
|
"type": "boolean"
|
|
113
|
+
},
|
|
114
|
+
"platform_editor_toolbar_aifc_user_intent_fix": {
|
|
115
|
+
"type": "boolean"
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
}
|