@atlaskit/editor-plugin-block-controls 8.7.2 → 8.8.1
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 +17 -0
- package/dist/cjs/blockControlsPlugin.js +14 -3
- package/dist/cjs/pm-plugins/decorations-drag-handle.js +3 -0
- package/dist/cjs/pm-plugins/decorations-quick-insert-button.js +3 -0
- package/dist/cjs/pm-plugins/handle-mouse-over.js +27 -11
- package/dist/cjs/pm-plugins/interaction-tracking/commands.js +12 -1
- package/dist/cjs/pm-plugins/interaction-tracking/handle-mouse-move.js +96 -1
- package/dist/cjs/pm-plugins/interaction-tracking/pm-plugin.js +92 -3
- package/dist/cjs/pm-plugins/main.js +129 -25
- package/dist/cjs/pm-plugins/vanilla-quick-insert.js +36 -13
- package/dist/cjs/ui/drag-handle.js +19 -9
- package/dist/cjs/ui/global-styles.js +9 -4
- package/dist/cjs/ui/quick-insert-button.js +16 -3
- package/dist/cjs/ui/visibility-container.js +70 -9
- package/dist/es2019/blockControlsPlugin.js +12 -3
- package/dist/es2019/pm-plugins/decorations-drag-handle.js +3 -0
- package/dist/es2019/pm-plugins/decorations-quick-insert-button.js +3 -0
- package/dist/es2019/pm-plugins/handle-mouse-over.js +27 -11
- package/dist/es2019/pm-plugins/interaction-tracking/commands.js +11 -0
- package/dist/es2019/pm-plugins/interaction-tracking/handle-mouse-move.js +98 -3
- package/dist/es2019/pm-plugins/interaction-tracking/pm-plugin.js +89 -4
- package/dist/es2019/pm-plugins/main.js +73 -18
- package/dist/es2019/pm-plugins/vanilla-quick-insert.js +27 -3
- package/dist/es2019/ui/drag-handle.js +19 -9
- package/dist/es2019/ui/global-styles.js +9 -3
- package/dist/es2019/ui/quick-insert-button.js +17 -3
- package/dist/es2019/ui/visibility-container.js +65 -9
- package/dist/esm/blockControlsPlugin.js +14 -3
- package/dist/esm/pm-plugins/decorations-drag-handle.js +3 -0
- package/dist/esm/pm-plugins/decorations-quick-insert-button.js +3 -0
- package/dist/esm/pm-plugins/handle-mouse-over.js +27 -11
- package/dist/esm/pm-plugins/interaction-tracking/commands.js +11 -0
- package/dist/esm/pm-plugins/interaction-tracking/handle-mouse-move.js +98 -2
- package/dist/esm/pm-plugins/interaction-tracking/pm-plugin.js +93 -3
- package/dist/esm/pm-plugins/main.js +129 -25
- package/dist/esm/pm-plugins/vanilla-quick-insert.js +36 -13
- package/dist/esm/ui/drag-handle.js +19 -9
- package/dist/esm/ui/global-styles.js +9 -4
- package/dist/esm/ui/quick-insert-button.js +16 -3
- package/dist/esm/ui/visibility-container.js +68 -9
- package/dist/types/blockControlsPluginType.d.ts +25 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/pm-plugins/interaction-tracking/commands.d.ts +2 -0
- package/dist/types/pm-plugins/interaction-tracking/handle-mouse-move.d.ts +2 -2
- package/dist/types/pm-plugins/interaction-tracking/pm-plugin.d.ts +5 -1
- package/dist/types/pm-plugins/main.d.ts +2 -2
- package/dist/types/ui/visibility-container.d.ts +2 -1
- package/dist/types-ts4.5/blockControlsPluginType.d.ts +27 -1
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/interaction-tracking/commands.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/interaction-tracking/handle-mouse-move.d.ts +2 -2
- package/dist/types-ts4.5/pm-plugins/interaction-tracking/pm-plugin.d.ts +5 -1
- package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -2
- package/dist/types-ts4.5/ui/visibility-container.d.ts +2 -1
- package/package.json +7 -9
|
@@ -3,6 +3,7 @@ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
|
3
3
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
4
4
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
7
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
7
8
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
8
9
|
import { handleKeyDownWithPreservedSelection } from './editor-commands/handle-key-down-with-preserved-selection';
|
|
@@ -20,9 +21,12 @@ import { createSelectionPreservationPlugin } from './pm-plugins/selection-preser
|
|
|
20
21
|
import { selectNode } from './pm-plugins/utils/getSelection';
|
|
21
22
|
import { GlobalStylesWrapper } from './ui/global-styles';
|
|
22
23
|
export const blockControlsPlugin = ({
|
|
23
|
-
api
|
|
24
|
+
api,
|
|
25
|
+
config
|
|
24
26
|
}) => {
|
|
27
|
+
var _config$rightSideCont;
|
|
25
28
|
const nodeDecorationRegistry = [];
|
|
29
|
+
const rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
|
|
26
30
|
return {
|
|
27
31
|
name: 'blockControls',
|
|
28
32
|
actions: {
|
|
@@ -42,12 +46,12 @@ export const blockControlsPlugin = ({
|
|
|
42
46
|
plugin: ({
|
|
43
47
|
getIntl,
|
|
44
48
|
nodeViewPortalProviderAPI
|
|
45
|
-
}) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry)
|
|
49
|
+
}) => createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true))
|
|
46
50
|
}];
|
|
47
51
|
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
48
52
|
pmPlugins.push({
|
|
49
53
|
name: 'blockControlsInteractionTrackingPlugin',
|
|
50
|
-
plugin: createInteractionTrackingPlugin
|
|
54
|
+
plugin: () => createInteractionTrackingPlugin(rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true))
|
|
51
55
|
});
|
|
52
56
|
}
|
|
53
57
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
@@ -317,6 +321,11 @@ export const blockControlsPlugin = ({
|
|
|
317
321
|
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
318
322
|
var _interactionTrackingP2, _interactionTrackingP3;
|
|
319
323
|
sharedState.isMouseOut = (_interactionTrackingP2 = (_interactionTrackingP3 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP3 === void 0 ? void 0 : _interactionTrackingP3.isMouseOut) !== null && _interactionTrackingP2 !== void 0 ? _interactionTrackingP2 : false;
|
|
324
|
+
sharedState.rightSideControlsEnabled = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true);
|
|
325
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
326
|
+
var _interactionTrackingP4;
|
|
327
|
+
sharedState.hoverSide = (_interactionTrackingP4 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP4 === void 0 ? void 0 : _interactionTrackingP4.hoverSide;
|
|
328
|
+
}
|
|
320
329
|
}
|
|
321
330
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
322
331
|
var _selectionPreservatio;
|
|
@@ -76,6 +76,9 @@ export const dragHandleDecoration = ({
|
|
|
76
76
|
const element = document.createElement('span');
|
|
77
77
|
// inline decoration causes focus issues when refocusing Editor into first line
|
|
78
78
|
element.style.display = 'block';
|
|
79
|
+
if (expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
80
|
+
element.setAttribute('data-blocks-decorator-widget', 'true');
|
|
81
|
+
}
|
|
79
82
|
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
80
83
|
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
81
84
|
element.setAttribute('data-blocks-drag-handle-key', key);
|
|
@@ -67,6 +67,9 @@ export const quickInsertButtonDecoration = ({
|
|
|
67
67
|
}
|
|
68
68
|
element.contentEditable = 'false';
|
|
69
69
|
element.setAttribute('data-blocks-quick-insert-container', 'true');
|
|
70
|
+
if (expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
71
|
+
element.setAttribute('data-blocks-quick-insert-button', 'true');
|
|
72
|
+
}
|
|
70
73
|
element.setAttribute('data-testid', 'block-ctrl-quick-insert-button');
|
|
71
74
|
if (editorExperiment('platform_editor_block_control_optimise_render', true, {
|
|
72
75
|
exposure: true
|
|
@@ -35,7 +35,7 @@ const getDefaultNodeSelector = memoizeOne(() => {
|
|
|
35
35
|
return getNodeSelector([...IGNORE_NODES_NEXT, 'media'], [...IGNORE_NODE_DESCENDANTS_ADVANCED_LAYOUT, 'table']);
|
|
36
36
|
});
|
|
37
37
|
export const handleMouseOver = (view, event, api) => {
|
|
38
|
-
var _api$blockControls, _api$editorDisabled, _target$classList;
|
|
38
|
+
var _api$blockControls, _api$editorDisabled, _api$editorViewMode, _api$editorViewMode$s, _api$blockControls$sh, _api$blockControls2, _api$blockControls2$s, _target$classList;
|
|
39
39
|
const {
|
|
40
40
|
isDragging,
|
|
41
41
|
activeNode,
|
|
@@ -48,10 +48,14 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
48
48
|
} = (api === null || api === void 0 ? void 0 : (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 ? void 0 : _api$editorDisabled.sharedState.currentState()) || {
|
|
49
49
|
editorDisabled: false
|
|
50
50
|
};
|
|
51
|
+
const editorViewMode = api === null || api === void 0 ? void 0 : (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 ? void 0 : (_api$editorViewMode$s = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode$s === void 0 ? void 0 : _api$editorViewMode$s.mode;
|
|
52
|
+
const isViewMode = editorViewMode === 'view';
|
|
51
53
|
const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
|
|
52
54
|
|
|
53
|
-
// We shouldn't be firing mouse over transactions when the editor is disabled
|
|
54
|
-
|
|
55
|
+
// We shouldn't be firing mouse over transactions when the editor is disabled,
|
|
56
|
+
// except in view mode when right-side controls are enabled (show controls on block hover)
|
|
57
|
+
const rightSideControlsEnabled = (_api$blockControls$sh = api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$s = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2$s === void 0 ? void 0 : _api$blockControls2$s.rightSideControlsEnabled) !== null && _api$blockControls$sh !== void 0 ? _api$blockControls$sh : false;
|
|
58
|
+
if (editorDisabled && (!isViewMode || !(rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)))) {
|
|
55
59
|
return false;
|
|
56
60
|
}
|
|
57
61
|
|
|
@@ -74,6 +78,18 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
74
78
|
return false;
|
|
75
79
|
}
|
|
76
80
|
let rootElement = target === null || target === void 0 ? void 0 : target.closest(isNativeAnchorSupported ? getDefaultNodeSelector() : `[data-drag-handler-anchor-name]`);
|
|
81
|
+
|
|
82
|
+
// When hovering over the right-edge button (rendered in a portal outside the block), resolve the
|
|
83
|
+
// block from the container's anchor so activeNode stays set and the button remains visible.
|
|
84
|
+
if (!rootElement && rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
85
|
+
const rightEdgeContainer = target === null || target === void 0 ? void 0 : target.closest('[data-blocks-right-edge-button-container]');
|
|
86
|
+
if (rightEdgeContainer) {
|
|
87
|
+
const anchor = rightEdgeContainer.getAttribute('data-blocks-right-edge-button-anchor');
|
|
88
|
+
if (anchor) {
|
|
89
|
+
rootElement = view.dom.querySelector(`[${getAnchorAttrName()}="${CSS.escape(anchor)}"]`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
77
93
|
if (rootElement) {
|
|
78
94
|
var _rootElement$parentEl;
|
|
79
95
|
// We want to exlude handles from showing for empty paragraph and heading nodes
|
|
@@ -182,22 +198,22 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
182
198
|
// as when it is a multi-selection, the showDragHandleAt command interfere with selection
|
|
183
199
|
// sometimes makes the multi-selection not continous after block menu is opened with keyboard
|
|
184
200
|
if (!(isMultipleSelected && isMenuOpen && blockMenuOptions !== null && blockMenuOptions !== void 0 && blockMenuOptions.openedViaKeyboard)) {
|
|
185
|
-
var _api$core, _api$
|
|
186
|
-
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$
|
|
201
|
+
var _api$core, _api$blockControls3, _rootPos, _rootAnchorName, _rootNodeType;
|
|
202
|
+
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.showDragHandleAt(targetPos, anchorName, nodeType, undefined, (_rootPos = rootPos) !== null && _rootPos !== void 0 ? _rootPos : targetPos, (_rootAnchorName = rootAnchorName) !== null && _rootAnchorName !== void 0 ? _rootAnchorName : anchorName, (_rootNodeType = rootNodeType) !== null && _rootNodeType !== void 0 ? _rootNodeType : nodeType));
|
|
187
203
|
}
|
|
188
204
|
} else {
|
|
189
|
-
var _api$core2, _api$
|
|
190
|
-
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(api === null || api === void 0 ? void 0 : (_api$
|
|
205
|
+
var _api$core2, _api$blockControls4, _rootPos2, _rootAnchorName2, _rootNodeType2;
|
|
206
|
+
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.commands.showDragHandleAt(targetPos, anchorName, nodeType, undefined, (_rootPos2 = rootPos) !== null && _rootPos2 !== void 0 ? _rootPos2 : targetPos, (_rootAnchorName2 = rootAnchorName) !== null && _rootAnchorName2 !== void 0 ? _rootAnchorName2 : anchorName, (_rootNodeType2 = rootNodeType) !== null && _rootNodeType2 !== void 0 ? _rootNodeType2 : nodeType));
|
|
191
207
|
}
|
|
192
208
|
} else {
|
|
193
|
-
var _api$core3, _api$
|
|
194
|
-
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(api === null || api === void 0 ? void 0 : (_api$
|
|
209
|
+
var _api$core3, _api$blockControls5;
|
|
210
|
+
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 ? void 0 : _api$blockControls5.commands.showDragHandleAt(targetPos, anchorName, nodeType));
|
|
195
211
|
}
|
|
196
212
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
197
213
|
var _api$userIntent, _api$userIntent$share;
|
|
198
214
|
if (isMenuOpen && originalAnchorName && (api === null || api === void 0 ? void 0 : (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : (_api$userIntent$share = _api$userIntent.sharedState.currentState()) === null || _api$userIntent$share === void 0 ? void 0 : _api$userIntent$share.currentUserIntent) === 'blockMenuOpen') {
|
|
199
|
-
var _api$core4, _api$
|
|
200
|
-
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(api === null || api === void 0 ? void 0 : (_api$
|
|
215
|
+
var _api$core4, _api$blockControls6;
|
|
216
|
+
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 ? void 0 : _api$blockControls6.commands.toggleBlockMenu());
|
|
201
217
|
}
|
|
202
218
|
}
|
|
203
219
|
}
|
|
@@ -18,4 +18,15 @@ export const mouseEnter = view => {
|
|
|
18
18
|
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
19
19
|
type: 'mouseEnter'
|
|
20
20
|
}));
|
|
21
|
+
};
|
|
22
|
+
export const setHoverSide = (view, side) => {
|
|
23
|
+
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
24
|
+
type: 'setHoverSide',
|
|
25
|
+
side
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
export const clearHoverSide = view => {
|
|
29
|
+
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
30
|
+
type: 'clearHoverSide'
|
|
31
|
+
}));
|
|
21
32
|
};
|
|
@@ -1,14 +1,109 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
2
|
+
import { clearHoverSide, mouseEnter, mouseLeave, setHoverSide, stopEditing } from './commands';
|
|
2
3
|
import { getInteractionTrackingState } from './pm-plugin';
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
/** Per-view pending hover state; avoids cross-editor singleton. */
|
|
6
|
+
const pendingByView = new WeakMap();
|
|
7
|
+
|
|
8
|
+
/** Per-view RAF handle so clearPendingHoverSide cancels only that view's callback. */
|
|
9
|
+
const rafIdByView = new WeakMap();
|
|
10
|
+
const cancelScheduledProcessForView = view => {
|
|
11
|
+
const id = rafIdByView.get(view);
|
|
12
|
+
if (id !== undefined) {
|
|
13
|
+
cancelAnimationFrame(id);
|
|
14
|
+
rafIdByView.delete(view);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const clearPendingHoverSide = view => {
|
|
18
|
+
pendingByView.delete(view);
|
|
19
|
+
cancelScheduledProcessForView(view);
|
|
20
|
+
};
|
|
21
|
+
const BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
|
|
22
|
+
const TABLE_SELECTOR = '[data-prosemirror-node-name="table"]';
|
|
23
|
+
const RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
|
|
24
|
+
const isInsideTable = element => {
|
|
25
|
+
var _element$getAttribute;
|
|
26
|
+
return element.closest(TABLE_SELECTOR) !== null || ((_element$getAttribute = element.getAttribute) === null || _element$getAttribute === void 0 ? void 0 : _element$getAttribute.call(element, 'data-prosemirror-node-name')) === 'table';
|
|
27
|
+
};
|
|
28
|
+
const processHoverSide = view => {
|
|
29
|
+
const event = pendingByView.get(view);
|
|
30
|
+
if (!event) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
pendingByView.delete(view);
|
|
34
|
+
rafIdByView.delete(view);
|
|
35
|
+
const editorContentArea = view.dom.closest('.ak-editor-content-area');
|
|
36
|
+
if (!(editorContentArea instanceof HTMLElement)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const state = getInteractionTrackingState(view.state);
|
|
40
|
+
const target = event.target instanceof HTMLElement ? event.target : null;
|
|
41
|
+
|
|
42
|
+
// When hovering over block controls directly, infer side from which control we're over.
|
|
43
|
+
// This is more reliable than bounds when controls are in portals outside the editor DOM.
|
|
44
|
+
const rightEdgeElement = target === null || target === void 0 ? void 0 : target.closest(RIGHT_EDGE_SELECTOR);
|
|
45
|
+
if (rightEdgeElement) {
|
|
46
|
+
if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== 'right') {
|
|
47
|
+
setHoverSide(view, 'right');
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const leftControlElement = target === null || target === void 0 ? void 0 : target.closest('[data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]');
|
|
52
|
+
if (leftControlElement) {
|
|
53
|
+
if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== 'left') {
|
|
54
|
+
setHoverSide(view, 'left');
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Use the hovered block's midpoint when hovering over block content.
|
|
60
|
+
const blockElement = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
|
|
61
|
+
const boundsElement = blockElement instanceof HTMLElement ? blockElement : editorContentArea;
|
|
62
|
+
|
|
63
|
+
// Tables show block controls at table level; don't restrict by side so drag handle
|
|
64
|
+
// stays visible when hovering anywhere in the table (e.g. paragraph in second cell).
|
|
65
|
+
if (isInsideTable(boundsElement)) {
|
|
66
|
+
if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== undefined) {
|
|
67
|
+
clearHoverSide(view);
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const {
|
|
72
|
+
left,
|
|
73
|
+
right
|
|
74
|
+
} = boundsElement.getBoundingClientRect();
|
|
75
|
+
const midpoint = (left + right) / 2;
|
|
76
|
+
const nextHoverSide = event.clientX > midpoint ? 'right' : 'left';
|
|
77
|
+
if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== nextHoverSide) {
|
|
78
|
+
setHoverSide(view, nextHoverSide);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
export const handleMouseMove = (view, event, rightSideControlsEnabled = false) => {
|
|
4
82
|
const state = getInteractionTrackingState(view.state);
|
|
5
83
|
// if user has stopped editing and moved their mouse, show block controls again
|
|
6
84
|
if (state !== null && state !== void 0 && state.isEditing) {
|
|
7
85
|
stopEditing(view);
|
|
8
86
|
}
|
|
87
|
+
|
|
88
|
+
// Only track hover side when right-side controls are enabled and experiment is on (performance)
|
|
89
|
+
if (!rightSideControlsEnabled || !expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (!(event instanceof MouseEvent)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
pendingByView.set(view, event);
|
|
96
|
+
cancelScheduledProcessForView(view);
|
|
97
|
+
const id = requestAnimationFrame(() => {
|
|
98
|
+
processHoverSide(view);
|
|
99
|
+
});
|
|
100
|
+
rafIdByView.set(view, id);
|
|
9
101
|
return false;
|
|
10
102
|
};
|
|
11
|
-
export const handleMouseLeave = view => {
|
|
103
|
+
export const handleMouseLeave = (view, rightSideControlsEnabled = false) => {
|
|
104
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
105
|
+
clearPendingHoverSide(view);
|
|
106
|
+
}
|
|
12
107
|
mouseLeave(view);
|
|
13
108
|
return false;
|
|
14
109
|
};
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { bind } from 'bind-event-listener';
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
5
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
5
6
|
import { handleKeyDown } from './handle-key-down';
|
|
6
7
|
import { handleMouseEnter, handleMouseLeave, handleMouseMove } from './handle-mouse-move';
|
|
8
|
+
|
|
9
|
+
/** Elements that extend the editor hover area (block controls, right-edge button, etc.) */
|
|
10
|
+
const BLOCK_CONTROLS_HOVER_AREA_SELECTOR = '[data-blocks-right-edge-button-container], [data-blocks-drag-handle-container], [data-testid="block-ctrl-drag-handle"], [data-testid="block-ctrl-drag-handle-container"], [data-testid="block-ctrl-decorator-widget"], [data-testid="block-ctrl-quick-insert-button"]';
|
|
11
|
+
const MOUSE_LEAVE_DEBOUNCE_MS = 200;
|
|
12
|
+
const isMovingToBlockControlsArea = target => target instanceof Element && !!target.closest(BLOCK_CONTROLS_HOVER_AREA_SELECTOR);
|
|
7
13
|
export const interactionTrackingPluginKey = new PluginKey('interactionTrackingPlugin');
|
|
8
|
-
export const createInteractionTrackingPlugin = () => {
|
|
14
|
+
export const createInteractionTrackingPlugin = (rightSideControlsEnabled = false) => {
|
|
9
15
|
return new SafePlugin({
|
|
10
16
|
key: interactionTrackingPluginKey,
|
|
11
17
|
state: {
|
|
@@ -30,10 +36,17 @@ export const createInteractionTrackingPlugin = () => {
|
|
|
30
36
|
break;
|
|
31
37
|
case 'mouseLeave':
|
|
32
38
|
newState.isMouseOut = true;
|
|
39
|
+
newState.hoverSide = undefined;
|
|
33
40
|
break;
|
|
34
41
|
case 'mouseEnter':
|
|
35
42
|
newState.isMouseOut = false;
|
|
36
43
|
break;
|
|
44
|
+
case 'setHoverSide':
|
|
45
|
+
newState.hoverSide = meta.side;
|
|
46
|
+
break;
|
|
47
|
+
case 'clearHoverSide':
|
|
48
|
+
newState.hoverSide = undefined;
|
|
49
|
+
break;
|
|
37
50
|
}
|
|
38
51
|
return {
|
|
39
52
|
...pluginState,
|
|
@@ -44,30 +57,102 @@ export const createInteractionTrackingPlugin = () => {
|
|
|
44
57
|
props: {
|
|
45
58
|
handleKeyDown,
|
|
46
59
|
handleDOMEvents: {
|
|
47
|
-
mousemove: handleMouseMove
|
|
60
|
+
mousemove: (view, event) => handleMouseMove(view, event, rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true))
|
|
48
61
|
}
|
|
49
62
|
},
|
|
50
63
|
view: editorExperiment('platform_editor_controls', 'variant1') ? view => {
|
|
51
64
|
const editorContentArea = view.dom.closest('.ak-editor-content-area');
|
|
65
|
+
const remixRightSideEnabled = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true);
|
|
52
66
|
let unbindMouseEnter;
|
|
53
67
|
let unbindMouseLeave;
|
|
68
|
+
let unbindDocumentMouseMove;
|
|
69
|
+
let mouseLeaveTimeoutId = null;
|
|
70
|
+
let lastMousePosition = {
|
|
71
|
+
x: 0,
|
|
72
|
+
y: 0
|
|
73
|
+
};
|
|
74
|
+
const scheduleMouseLeave = event => {
|
|
75
|
+
if (mouseLeaveTimeoutId) {
|
|
76
|
+
clearTimeout(mouseLeaveTimeoutId);
|
|
77
|
+
mouseLeaveTimeoutId = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Don't set isMouseOut when moving to block controls (right-edge button, drag handle, etc.)
|
|
81
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && isMovingToBlockControlsArea(event.relatedTarget)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
mouseLeaveTimeoutId = setTimeout(() => {
|
|
85
|
+
mouseLeaveTimeoutId = null;
|
|
86
|
+
// Before dispatching, check if mouse has moved to block controls (e.g. through empty space)
|
|
87
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && typeof document !== 'undefined') {
|
|
88
|
+
const el = document.elementFromPoint(lastMousePosition.x, lastMousePosition.y);
|
|
89
|
+
if (el && isMovingToBlockControlsArea(el)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
handleMouseLeave(view, rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true));
|
|
94
|
+
}, MOUSE_LEAVE_DEBOUNCE_MS);
|
|
95
|
+
};
|
|
96
|
+
const cancelScheduledMouseLeave = () => {
|
|
97
|
+
if (mouseLeaveTimeoutId) {
|
|
98
|
+
clearTimeout(mouseLeaveTimeoutId);
|
|
99
|
+
mouseLeaveTimeoutId = null;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
54
102
|
if (editorContentArea) {
|
|
103
|
+
if (remixRightSideEnabled && typeof document !== 'undefined') {
|
|
104
|
+
unbindDocumentMouseMove = bind(document, {
|
|
105
|
+
type: 'mousemove',
|
|
106
|
+
listener: event => {
|
|
107
|
+
lastMousePosition = {
|
|
108
|
+
x: event.clientX,
|
|
109
|
+
y: event.clientY
|
|
110
|
+
};
|
|
111
|
+
// Use document-level mousemove so we get events when hovering over block
|
|
112
|
+
// controls (which may be in portals outside the editor DOM). Without this,
|
|
113
|
+
// handleDOMEvents.mousemove only fires when over the editor content.
|
|
114
|
+
if (editorContentArea.contains(event.target) || isMovingToBlockControlsArea(event.target)) {
|
|
115
|
+
handleMouseMove(view, event, rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true));
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
options: {
|
|
119
|
+
passive: true
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
55
123
|
unbindMouseEnter = bind(editorContentArea, {
|
|
56
124
|
type: 'mouseenter',
|
|
57
125
|
listener: () => {
|
|
126
|
+
if (remixRightSideEnabled) {
|
|
127
|
+
cancelScheduledMouseLeave();
|
|
128
|
+
}
|
|
58
129
|
handleMouseEnter(view);
|
|
59
130
|
}
|
|
60
131
|
});
|
|
61
132
|
unbindMouseLeave = bind(editorContentArea, {
|
|
62
133
|
type: 'mouseleave',
|
|
63
|
-
listener:
|
|
64
|
-
|
|
134
|
+
listener: event => {
|
|
135
|
+
const e = event;
|
|
136
|
+
lastMousePosition = {
|
|
137
|
+
x: e.clientX,
|
|
138
|
+
y: e.clientY
|
|
139
|
+
};
|
|
140
|
+
if (remixRightSideEnabled) {
|
|
141
|
+
scheduleMouseLeave(e);
|
|
142
|
+
} else {
|
|
143
|
+
handleMouseLeave(view, false);
|
|
144
|
+
}
|
|
65
145
|
}
|
|
66
146
|
});
|
|
67
147
|
}
|
|
68
148
|
return {
|
|
69
149
|
destroy: () => {
|
|
70
150
|
var _unbindMouseEnter, _unbindMouseLeave;
|
|
151
|
+
if (remixRightSideEnabled) {
|
|
152
|
+
var _unbindDocumentMouseM;
|
|
153
|
+
cancelScheduledMouseLeave();
|
|
154
|
+
(_unbindDocumentMouseM = unbindDocumentMouseMove) === null || _unbindDocumentMouseM === void 0 ? void 0 : _unbindDocumentMouseM();
|
|
155
|
+
}
|
|
71
156
|
(_unbindMouseEnter = unbindMouseEnter) === null || _unbindMouseEnter === void 0 ? void 0 : _unbindMouseEnter();
|
|
72
157
|
(_unbindMouseLeave = unbindMouseLeave) === null || _unbindMouseLeave === void 0 ? void 0 : _unbindMouseLeave();
|
|
73
158
|
}
|
|
@@ -234,8 +234,8 @@ const getDecorationAtPos = (state, decorations, pos, to) => {
|
|
|
234
234
|
const nodeDecAtActivePos = nodeDecsAtActivePos.pop();
|
|
235
235
|
return nodeDecAtActivePos;
|
|
236
236
|
};
|
|
237
|
-
export const apply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, anchorRectCache, resizeObserverWidth, pragmaticCleanup) => {
|
|
238
|
-
var _api$limitedMode, _api$limitedMode$shar, _api$limitedMode$shar2, _meta$multiSelectDnD, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging2, _meta$isDragging3, _meta$toggleMenu, _meta$toggleMenu2, _meta$toggleMenu3, _meta$toggleMenu4, _meta$toggleMenu5, _meta$toggleMenu6, _meta$toggleMenu7, _meta$toggleMenu8, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown, _meta$lastDragCancell;
|
|
237
|
+
export const apply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, anchorRectCache, resizeObserverWidth, pragmaticCleanup) => {
|
|
238
|
+
var _api$limitedMode, _api$limitedMode$shar, _api$limitedMode$shar2, _meta$multiSelectDnD, _api$editorViewMode, _api$editorViewMode$s, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging2, _meta$isDragging3, _meta$toggleMenu, _meta$toggleMenu2, _meta$toggleMenu3, _meta$toggleMenu4, _meta$toggleMenu5, _meta$toggleMenu6, _meta$toggleMenu7, _meta$toggleMenu8, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$isShiftDown, _meta$lastDragCancell;
|
|
239
239
|
let {
|
|
240
240
|
activeNode,
|
|
241
241
|
decorations,
|
|
@@ -348,6 +348,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
348
348
|
}
|
|
349
349
|
const maybeNodeCountChanged = !isAllText && numReplaceSteps > 0;
|
|
350
350
|
let latestActiveNode = meta === null || meta === void 0 ? void 0 : meta.activeNode;
|
|
351
|
+
const isViewMode = (api === null || api === void 0 ? void 0 : (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 ? void 0 : (_api$editorViewMode$s = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode$s === void 0 ? void 0 : _api$editorViewMode$s.mode) === 'view';
|
|
351
352
|
if (!latestActiveNode && (!isActiveNodeDeleted || isReplacedWithSameSize)) {
|
|
352
353
|
latestActiveNode = activeNode;
|
|
353
354
|
}
|
|
@@ -443,12 +444,21 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
443
444
|
decorations = decorations.remove(old);
|
|
444
445
|
}
|
|
445
446
|
}
|
|
447
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && isViewMode) {
|
|
448
|
+
for (const factory of nodeDecorationRegistry) {
|
|
449
|
+
if (factory.showInViewMode) {
|
|
450
|
+
var _activeNode1, _activeNode10;
|
|
451
|
+
const old = decorations.find((_activeNode1 = activeNode) === null || _activeNode1 === void 0 ? void 0 : _activeNode1.rootPos, (_activeNode10 = activeNode) === null || _activeNode10 === void 0 ? void 0 : _activeNode10.rootPos, spec => spec.type === factory.type);
|
|
452
|
+
decorations = decorations.remove(old);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
446
456
|
}
|
|
447
457
|
} else if (api) {
|
|
448
|
-
var _latestActiveNode5;
|
|
449
|
-
if (shouldRecreateHandle) {
|
|
450
|
-
var
|
|
451
|
-
const oldHandle = findHandleDec(decorations, (
|
|
458
|
+
var _latestActiveNode5, _latestActiveNode14;
|
|
459
|
+
if (shouldRecreateHandle && (!rightSideControlsEnabled || !isViewMode)) {
|
|
460
|
+
var _activeNode11, _activeNode12, _latestActiveNode, _latestActiveNode2, _latestActiveNode3, _latestActiveNode4;
|
|
461
|
+
const oldHandle = findHandleDec(decorations, (_activeNode11 = activeNode) === null || _activeNode11 === void 0 ? void 0 : _activeNode11.pos, (_activeNode12 = activeNode) === null || _activeNode12 === void 0 ? void 0 : _activeNode12.pos);
|
|
452
462
|
decorations = decorations.remove(oldHandle);
|
|
453
463
|
const handleDec = dragHandleDecoration({
|
|
454
464
|
api,
|
|
@@ -465,9 +475,9 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
465
475
|
}
|
|
466
476
|
if (shouldRecreateQuickInsertButton && ((_latestActiveNode5 = latestActiveNode) === null || _latestActiveNode5 === void 0 ? void 0 : _latestActiveNode5.rootPos) !== undefined &&
|
|
467
477
|
// platform_editor_controls note: enables quick insert
|
|
468
|
-
flags.toolbarFlagsEnabled) {
|
|
469
|
-
var
|
|
470
|
-
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (
|
|
478
|
+
flags.toolbarFlagsEnabled && (!rightSideControlsEnabled || !isViewMode)) {
|
|
479
|
+
var _activeNode13, _activeNode14, _latestActiveNode6, _latestActiveNode7, _latestActiveNode8, _latestActiveNode9, _latestActiveNode0;
|
|
480
|
+
const oldQuickInsertButton = findQuickInsertInsertButtonDecoration(decorations, (_activeNode13 = activeNode) === null || _activeNode13 === void 0 ? void 0 : _activeNode13.rootPos, (_activeNode14 = activeNode) === null || _activeNode14 === void 0 ? void 0 : _activeNode14.rootPos);
|
|
471
481
|
decorations = decorations.remove(oldQuickInsertButton);
|
|
472
482
|
const quickInsertButton = quickInsertButtonDecoration({
|
|
473
483
|
api,
|
|
@@ -484,8 +494,8 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
484
494
|
decorations = decorations.add(newState.doc, [quickInsertButton]);
|
|
485
495
|
if (fg('platform_editor_expose_block_controls_deco_api')) {
|
|
486
496
|
for (const factory of nodeDecorationRegistry) {
|
|
487
|
-
var
|
|
488
|
-
const old = decorations.find((
|
|
497
|
+
var _activeNode15, _activeNode16, _latestActiveNode1, _latestActiveNode10, _latestActiveNode11, _latestActiveNode12, _latestActiveNode13;
|
|
498
|
+
const old = decorations.find((_activeNode15 = activeNode) === null || _activeNode15 === void 0 ? void 0 : _activeNode15.rootPos, (_activeNode16 = activeNode) === null || _activeNode16 === void 0 ? void 0 : _activeNode16.rootPos, spec => spec.type === factory.type);
|
|
489
499
|
decorations = decorations.remove(old);
|
|
490
500
|
const dec = factory.create({
|
|
491
501
|
editorState: newState,
|
|
@@ -500,6 +510,43 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
500
510
|
}
|
|
501
511
|
}
|
|
502
512
|
}
|
|
513
|
+
|
|
514
|
+
// In view mode (edit/live pages), show right-side controls on block hover (without drag handle or quick insert)
|
|
515
|
+
if (isViewMode && ((_latestActiveNode14 = latestActiveNode) === null || _latestActiveNode14 === void 0 ? void 0 : _latestActiveNode14.rootPos) !== undefined && flags.toolbarFlagsEnabled && rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
516
|
+
const rootPos = latestActiveNode.rootPos;
|
|
517
|
+
for (const factory of nodeDecorationRegistry) {
|
|
518
|
+
if (factory.showInViewMode) {
|
|
519
|
+
var _latestActiveNode15, _latestActiveNode16, _latestActiveNode17, _latestActiveNode18, _latestActiveNode19;
|
|
520
|
+
const existingAtPos = decorations.find(rootPos, rootPos, spec => spec.type === factory.type);
|
|
521
|
+
// Skip remove/re-add when decoration already exists at correct position - avoids
|
|
522
|
+
// flickering from widget destroy/recreate on every transaction (e.g. on hover).
|
|
523
|
+
if (existingAtPos.length > 0) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
// Remove any stale decoration at a different position (e.g. after moving to another block)
|
|
527
|
+
const stale = decorations.find(0, newState.doc.nodeSize, spec => spec.type === factory.type);
|
|
528
|
+
decorations = decorations.remove(stale);
|
|
529
|
+
const dec = factory.create({
|
|
530
|
+
editorState: newState,
|
|
531
|
+
nodeViewPortalProviderAPI,
|
|
532
|
+
anchorName: (_latestActiveNode15 = latestActiveNode) === null || _latestActiveNode15 === void 0 ? void 0 : _latestActiveNode15.anchorName,
|
|
533
|
+
nodeType: (_latestActiveNode16 = latestActiveNode) === null || _latestActiveNode16 === void 0 ? void 0 : _latestActiveNode16.nodeType,
|
|
534
|
+
rootPos: (_latestActiveNode17 = latestActiveNode) === null || _latestActiveNode17 === void 0 ? void 0 : _latestActiveNode17.rootPos,
|
|
535
|
+
rootAnchorName: (_latestActiveNode18 = latestActiveNode) === null || _latestActiveNode18 === void 0 ? void 0 : _latestActiveNode18.rootAnchorName,
|
|
536
|
+
rootNodeType: (_latestActiveNode19 = latestActiveNode) === null || _latestActiveNode19 === void 0 ? void 0 : _latestActiveNode19.rootNodeType
|
|
537
|
+
});
|
|
538
|
+
decorations = decorations.add(newState.doc, [dec]);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} else if (isViewMode && rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
542
|
+
// Remove view-mode right-side decorations when no active node
|
|
543
|
+
for (const factory of nodeDecorationRegistry) {
|
|
544
|
+
if (factory.showInViewMode) {
|
|
545
|
+
const old = decorations.find(0, newState.doc.nodeSize, spec => spec.type === factory.type);
|
|
546
|
+
decorations = decorations.remove(old);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
503
550
|
}
|
|
504
551
|
|
|
505
552
|
// Drop targets may be missing when the node count is being changed during a drag
|
|
@@ -547,12 +594,15 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
547
594
|
let newActiveNode;
|
|
548
595
|
// platform_editor_controls note: enables quick insert
|
|
549
596
|
if (flags.toolbarFlagsEnabled) {
|
|
550
|
-
var
|
|
597
|
+
var _latestActiveNode20, _latestActiveNode21;
|
|
551
598
|
// remove isEmptyDoc check and let decorations render and determine their own visibility
|
|
552
|
-
|
|
599
|
+
// In view mode with right-side controls we render node decorations (right-edge button), not the
|
|
600
|
+
// handle - so findHandleDec is always empty. Don't clear activeNode in that case.
|
|
601
|
+
const hasHandleOrViewModeControls = findHandleDec(decorations, (_latestActiveNode20 = latestActiveNode) === null || _latestActiveNode20 === void 0 ? void 0 : _latestActiveNode20.pos, (_latestActiveNode21 = latestActiveNode) === null || _latestActiveNode21 === void 0 ? void 0 : _latestActiveNode21.pos).length > 0 || isViewMode && rightSideControlsEnabled;
|
|
602
|
+
newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
|
|
553
603
|
} else {
|
|
554
|
-
var
|
|
555
|
-
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (
|
|
604
|
+
var _latestActiveNode22, _latestActiveNode23;
|
|
605
|
+
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && findHandleDec(decorations, (_latestActiveNode22 = latestActiveNode) === null || _latestActiveNode22 === void 0 ? void 0 : _latestActiveNode22.pos, (_latestActiveNode23 = latestActiveNode) === null || _latestActiveNode23 === void 0 ? void 0 : _latestActiveNode23.pos).length === 0 ? null : latestActiveNode;
|
|
556
606
|
}
|
|
557
607
|
let isMenuOpenNew = isMenuOpen;
|
|
558
608
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
@@ -596,7 +646,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
596
646
|
isSelectedViaDragHandle: isSelectedViaDragHandleNew
|
|
597
647
|
};
|
|
598
648
|
};
|
|
599
|
-
export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry) => {
|
|
649
|
+
export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false) => {
|
|
600
650
|
const {
|
|
601
651
|
formatMessage
|
|
602
652
|
} = getIntl();
|
|
@@ -623,7 +673,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
623
673
|
init() {
|
|
624
674
|
return initialState;
|
|
625
675
|
},
|
|
626
|
-
apply: (tr, currentState, _, newState) => apply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, anchorRectCache, resizeObserverWidth, pragmaticCleanup)
|
|
676
|
+
apply: (tr, currentState, _, newState) => apply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, anchorRectCache, resizeObserverWidth, pragmaticCleanup)
|
|
627
677
|
},
|
|
628
678
|
props: {
|
|
629
679
|
decorations: state => {
|
|
@@ -633,7 +683,12 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
633
683
|
}
|
|
634
684
|
const isDisabled = api === null || api === void 0 ? void 0 : (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 ? void 0 : (_api$editorDisabled$s = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled$s === void 0 ? void 0 : _api$editorDisabled$s.editorDisabled;
|
|
635
685
|
if (isDisabled) {
|
|
636
|
-
|
|
686
|
+
var _api$editorViewMode2, _api$editorViewMode2$;
|
|
687
|
+
const remixRightSideEnabled = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true);
|
|
688
|
+
// Hide decorations when disabled, except in view mode when right-side controls are enabled
|
|
689
|
+
if (!remixRightSideEnabled || (api === null || api === void 0 ? void 0 : (_api$editorViewMode2 = api.editorViewMode) === null || _api$editorViewMode2 === void 0 ? void 0 : (_api$editorViewMode2$ = _api$editorViewMode2.sharedState.currentState()) === null || _api$editorViewMode2$ === void 0 ? void 0 : _api$editorViewMode2$.mode) !== 'view') {
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
637
692
|
}
|
|
638
693
|
return (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
|
|
639
694
|
},
|