@atlaskit/editor-plugin-block-controls 8.7.2 → 8.8.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 +11 -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 +5 -7
|
@@ -5,6 +5,7 @@ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
|
5
5
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
6
6
|
import { findParentNode, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
7
7
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
8
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
9
|
import { isInTextSelection, isNestedNodeSelected, isNonEditableBlock, isSelectionInNode } from '../ui/utils/document-checks';
|
|
9
10
|
import { createNewLine } from '../ui/utils/editor-commands';
|
|
10
11
|
import { calculatePosition } from './quick-insert-calculate-position';
|
|
@@ -55,7 +56,7 @@ const vanillaQuickInsert = ({
|
|
|
55
56
|
* Create a Node which contains the quick insert button
|
|
56
57
|
*/
|
|
57
58
|
export const createVanillaButton = props => {
|
|
58
|
-
var _props$api$typeAhead, _props$api$typeAhead$, _props$api$blockContr, _props$api$blockContr2, _props$api$typeAhead2, _props$api$
|
|
59
|
+
var _props$api$typeAhead, _props$api$typeAhead$, _props$api$blockContr, _props$api$blockContr2, _props$api$blockContr3, _props$api$blockContr4, _props$api$blockContr5, _props$api$blockContr6, _props$api$blockContr7, _props$api$editorView, _props$api$editorView2, _props$api$typeAhead2, _props$api$blockContr8;
|
|
59
60
|
const {
|
|
60
61
|
dom
|
|
61
62
|
} = DOMSerializer.renderSpec(document, vanillaQuickInsert(props));
|
|
@@ -73,11 +74,18 @@ export const createVanillaButton = props => {
|
|
|
73
74
|
// Dynamically control the visibility of the node
|
|
74
75
|
let isTypeAheadOpen = (_props$api$typeAhead = props.api.typeAhead) === null || _props$api$typeAhead === void 0 ? void 0 : (_props$api$typeAhead$ = _props$api$typeAhead.sharedState.currentState()) === null || _props$api$typeAhead$ === void 0 ? void 0 : _props$api$typeAhead$.isOpen;
|
|
75
76
|
let isEditing = (_props$api$blockContr = props.api.blockControls) === null || _props$api$blockContr === void 0 ? void 0 : (_props$api$blockContr2 = _props$api$blockContr.sharedState.currentState()) === null || _props$api$blockContr2 === void 0 ? void 0 : _props$api$blockContr2.isEditing;
|
|
77
|
+
let hoverSide = (_props$api$blockContr3 = props.api.blockControls) === null || _props$api$blockContr3 === void 0 ? void 0 : (_props$api$blockContr4 = _props$api$blockContr3.sharedState.currentState()) === null || _props$api$blockContr4 === void 0 ? void 0 : _props$api$blockContr4.hoverSide;
|
|
78
|
+
let rightSideControlsEnabled = (_props$api$blockContr5 = (_props$api$blockContr6 = props.api.blockControls) === null || _props$api$blockContr6 === void 0 ? void 0 : (_props$api$blockContr7 = _props$api$blockContr6.sharedState.currentState()) === null || _props$api$blockContr7 === void 0 ? void 0 : _props$api$blockContr7.rightSideControlsEnabled) !== null && _props$api$blockContr5 !== void 0 ? _props$api$blockContr5 : false;
|
|
79
|
+
let editorViewMode = (_props$api$editorView = props.api.editorViewMode) === null || _props$api$editorView === void 0 ? void 0 : (_props$api$editorView2 = _props$api$editorView.sharedState.currentState()) === null || _props$api$editorView2 === void 0 ? void 0 : _props$api$editorView2.mode;
|
|
76
80
|
const changeDOMVisibility = () => {
|
|
77
81
|
if (!(dom instanceof HTMLElement)) {
|
|
78
82
|
return;
|
|
79
83
|
}
|
|
80
|
-
|
|
84
|
+
const isViewMode = editorViewMode === 'view';
|
|
85
|
+
const shouldRestrictBySide = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && !isViewMode;
|
|
86
|
+
// Only restrict by side when hoverSide is known. When undefined, show quick insert.
|
|
87
|
+
const sideHidden = shouldRestrictBySide && hoverSide !== undefined ? hoverSide !== 'left' : false;
|
|
88
|
+
if (isTypeAheadOpen || isEditing || sideHidden) {
|
|
81
89
|
dom.classList.add('blocks-quick-insert-invisible-container');
|
|
82
90
|
dom.classList.remove('blocks-quick-insert-visible-container');
|
|
83
91
|
} else {
|
|
@@ -92,12 +100,28 @@ export const createVanillaButton = props => {
|
|
|
92
100
|
isTypeAheadOpen = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isOpen;
|
|
93
101
|
changeDOMVisibility();
|
|
94
102
|
}));
|
|
95
|
-
props.cleanupCallbacks.push((_props$api$
|
|
103
|
+
props.cleanupCallbacks.push((_props$api$blockContr8 = props.api.blockControls) === null || _props$api$blockContr8 === void 0 ? void 0 : _props$api$blockContr8.sharedState.onChange(({
|
|
96
104
|
nextSharedState
|
|
97
105
|
}) => {
|
|
106
|
+
var _nextSharedState$righ;
|
|
98
107
|
isEditing = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isEditing;
|
|
108
|
+
hoverSide = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.hoverSide;
|
|
109
|
+
rightSideControlsEnabled = (_nextSharedState$righ = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.rightSideControlsEnabled) !== null && _nextSharedState$righ !== void 0 ? _nextSharedState$righ : false;
|
|
99
110
|
changeDOMVisibility();
|
|
100
111
|
}));
|
|
112
|
+
// Only subscribe to view mode when right-side controls are enabled (editorViewMode affects side restriction)
|
|
113
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
114
|
+
var _props$api$editorView3, _props$api$editorView4, _props$api$editorView5;
|
|
115
|
+
const unsubscribeViewMode = (_props$api$editorView3 = props.api.editorViewMode) === null || _props$api$editorView3 === void 0 ? void 0 : (_props$api$editorView4 = (_props$api$editorView5 = _props$api$editorView3.sharedState).onChange) === null || _props$api$editorView4 === void 0 ? void 0 : _props$api$editorView4.call(_props$api$editorView5, ({
|
|
116
|
+
nextSharedState
|
|
117
|
+
}) => {
|
|
118
|
+
editorViewMode = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.mode;
|
|
119
|
+
changeDOMVisibility();
|
|
120
|
+
});
|
|
121
|
+
if (unsubscribeViewMode) {
|
|
122
|
+
props.cleanupCallbacks.push(unsubscribeViewMode);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
101
125
|
return dom;
|
|
102
126
|
};
|
|
103
127
|
const TEXT_PARENT_TYPES = ['paragraph', 'heading', 'blockquote', 'taskItem', 'decisionItem'];
|
|
@@ -16,7 +16,6 @@ import { dragToMoveDown, dragToMoveLeft, dragToMoveRight, dragToMoveUp, getAriaK
|
|
|
16
16
|
import { blockControlsMessages } from '@atlaskit/editor-common/messages';
|
|
17
17
|
import { expandToBlockRange, isMultiBlockRange } from '@atlaskit/editor-common/selection';
|
|
18
18
|
import { DRAG_HANDLE_WIDTH, tableControlsSpacing } from '@atlaskit/editor-common/styles';
|
|
19
|
-
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
20
19
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
21
20
|
import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
|
|
22
21
|
import { akEditorFullPageNarrowBreakout, akEditorTableToolbarSize, relativeSizeToBaseFontSize } from '@atlaskit/editor-shared-styles/consts';
|
|
@@ -415,16 +414,19 @@ export const DragHandle = ({
|
|
|
415
414
|
});
|
|
416
415
|
const [isFocused, setIsFocused] = useState(Boolean(handleOptions === null || handleOptions === void 0 ? void 0 : handleOptions.isFocused));
|
|
417
416
|
const {
|
|
418
|
-
macroInteractionUpdates
|
|
419
|
-
|
|
420
|
-
|
|
417
|
+
macroInteractionUpdates,
|
|
418
|
+
selection,
|
|
419
|
+
isShiftDown,
|
|
420
|
+
interactionState
|
|
421
|
+
} = useSharedPluginStateWithSelector(api, ['featureFlags', 'selection', 'blockControls', 'interaction'], states => {
|
|
422
|
+
var _states$featureFlagsS, _states$selectionStat, _states$blockControls, _states$interactionSt;
|
|
421
423
|
return {
|
|
422
|
-
macroInteractionUpdates: (_states$featureFlagsS = states.featureFlagsState) === null || _states$featureFlagsS === void 0 ? void 0 : _states$featureFlagsS.macroInteractionUpdates
|
|
424
|
+
macroInteractionUpdates: (_states$featureFlagsS = states.featureFlagsState) === null || _states$featureFlagsS === void 0 ? void 0 : _states$featureFlagsS.macroInteractionUpdates,
|
|
425
|
+
selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection,
|
|
426
|
+
isShiftDown: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isShiftDown,
|
|
427
|
+
interactionState: (_states$interactionSt = states.interactionState) === null || _states$interactionSt === void 0 ? void 0 : _states$interactionSt.interactionState
|
|
423
428
|
};
|
|
424
429
|
});
|
|
425
|
-
const selection = useSharedPluginStateSelector(api, 'selection.selection');
|
|
426
|
-
const isShiftDown = useSharedPluginStateSelector(api, 'blockControls.isShiftDown');
|
|
427
|
-
const interactionState = useSharedPluginStateSelector(api, 'interaction.interactionState');
|
|
428
430
|
const start = getPos();
|
|
429
431
|
const isLayoutColumn = nodeType === 'layoutColumn';
|
|
430
432
|
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
@@ -1110,6 +1112,7 @@ export const DragHandle = ({
|
|
|
1110
1112
|
onDrop: handleOnDrop,
|
|
1111
1113
|
disabled: dragHandleDisabled,
|
|
1112
1114
|
"data-editor-block-ctrl-drag-handle": true,
|
|
1115
|
+
"data-blocks-drag-handle": expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) || undefined,
|
|
1113
1116
|
"data-testid": "block-ctrl-drag-handle",
|
|
1114
1117
|
"aria-label": dragHandleAriaLabel,
|
|
1115
1118
|
onBlur: expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true) ? () => setIsFocused(false) : undefined
|
|
@@ -1187,8 +1190,15 @@ export const DragHandleWithVisibility = ({
|
|
|
1187
1190
|
isTopLevelNode,
|
|
1188
1191
|
anchorRectCache
|
|
1189
1192
|
}) => {
|
|
1193
|
+
const rightSideControlsEnabled = useSharedPluginStateWithSelector(api, ['blockControls'], states => {
|
|
1194
|
+
var _states$blockControls2, _states$blockControls3;
|
|
1195
|
+
return {
|
|
1196
|
+
rightSideControlsEnabled: (_states$blockControls2 = (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.rightSideControlsEnabled) !== null && _states$blockControls2 !== void 0 ? _states$blockControls2 : false
|
|
1197
|
+
};
|
|
1198
|
+
}).rightSideControlsEnabled;
|
|
1190
1199
|
return jsx(VisibilityContainer, {
|
|
1191
|
-
api: api
|
|
1200
|
+
api: api,
|
|
1201
|
+
controlSide: rightSideControlsEnabled ? 'left' : undefined
|
|
1192
1202
|
}, jsx(DragHandle, {
|
|
1193
1203
|
view: view,
|
|
1194
1204
|
api: api,
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles, @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
6
6
|
import { css, Global, jsx } from '@emotion/react';
|
|
7
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
7
8
|
import { ANCHOR_VARIABLE_NAME, DRAG_HANDLE_WIDTH, isCSSAnchorSupported, tableControlsSpacing } from '@atlaskit/editor-common/styles';
|
|
8
9
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
9
|
-
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
10
10
|
import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
|
|
11
11
|
import { akEditorBreakoutPadding, akEditorCalculatedWideLayoutWidth, akEditorCalculatedWideLayoutWidthSmallViewport, akEditorFullPageNarrowBreakout, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced } from '@atlaskit/editor-shared-styles';
|
|
12
12
|
import { layers } from '@atlaskit/theme/constants';
|
|
@@ -544,9 +544,15 @@ const dragAnchorStyles = css({
|
|
|
544
544
|
export const GlobalStylesWrapper = ({
|
|
545
545
|
api
|
|
546
546
|
}) => {
|
|
547
|
-
const
|
|
548
|
-
|
|
547
|
+
const {
|
|
548
|
+
isDragging: isDraggingFromState
|
|
549
|
+
} = useSharedPluginStateWithSelector(api, ['blockControls'], states => {
|
|
550
|
+
var _states$blockControls;
|
|
551
|
+
return {
|
|
552
|
+
isDragging: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isDragging
|
|
553
|
+
};
|
|
549
554
|
});
|
|
555
|
+
const isDragging = expValEquals('platform_editor_block_controls_perf_optimization', 'isEnabled', true) ? isDraggingFromState : false;
|
|
550
556
|
const shouldRenderAnchors = isCSSAnchorSupported() && expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true);
|
|
551
557
|
const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
|
|
552
558
|
return jsx(Global, {
|
|
@@ -8,10 +8,10 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|
|
8
8
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
9
9
|
import { css, jsx } from '@emotion/react';
|
|
10
10
|
import { bind } from 'bind-event-listener';
|
|
11
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
11
12
|
import { ToolTipContent } from '@atlaskit/editor-common/keymaps';
|
|
12
13
|
import { blockControlsMessages as messages } from '@atlaskit/editor-common/messages';
|
|
13
14
|
import { tableControlsSpacing } from '@atlaskit/editor-common/styles';
|
|
14
|
-
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
15
15
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
16
16
|
import { findParentNode, findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
17
17
|
import { relativeSizeToBaseFontSize } from '@atlaskit/editor-shared-styles';
|
|
@@ -152,7 +152,14 @@ export const TypeAheadControl = ({
|
|
|
152
152
|
rootNodeType,
|
|
153
153
|
anchorRectCache
|
|
154
154
|
}) => {
|
|
155
|
-
const
|
|
155
|
+
const {
|
|
156
|
+
macroInteractionUpdates
|
|
157
|
+
} = useSharedPluginStateWithSelector(api, ['featureFlags'], states => {
|
|
158
|
+
var _states$featureFlagsS;
|
|
159
|
+
return {
|
|
160
|
+
macroInteractionUpdates: (_states$featureFlagsS = states.featureFlagsState) === null || _states$featureFlagsS === void 0 ? void 0 : _states$featureFlagsS.macroInteractionUpdates
|
|
161
|
+
};
|
|
162
|
+
});
|
|
156
163
|
const [positionStyles, setPositionStyles] = useState({
|
|
157
164
|
display: 'none'
|
|
158
165
|
});
|
|
@@ -359,8 +366,15 @@ export const QuickInsertWithVisibility = ({
|
|
|
359
366
|
rootNodeType,
|
|
360
367
|
anchorRectCache
|
|
361
368
|
}) => {
|
|
369
|
+
const rightSideControlsEnabled = useSharedPluginStateWithSelector(api, ['blockControls'], states => {
|
|
370
|
+
var _states$blockControls, _states$blockControls2;
|
|
371
|
+
return {
|
|
372
|
+
rightSideControlsEnabled: (_states$blockControls = (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.rightSideControlsEnabled) !== null && _states$blockControls !== void 0 ? _states$blockControls : false
|
|
373
|
+
};
|
|
374
|
+
}).rightSideControlsEnabled;
|
|
362
375
|
return jsx(VisibilityContainer, {
|
|
363
|
-
api: api
|
|
376
|
+
api: api,
|
|
377
|
+
controlSide: rightSideControlsEnabled ? 'left' : undefined
|
|
364
378
|
}, jsx(TypeAheadControl, {
|
|
365
379
|
view: view,
|
|
366
380
|
api: api,
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* @jsxRuntime classic
|
|
3
3
|
* @jsx jsx
|
|
4
4
|
*/
|
|
5
|
-
import React from 'react';
|
|
5
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
8
8
|
import { css, jsx } from '@emotion/react';
|
|
9
|
-
import {
|
|
9
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
10
10
|
import { akEditorFullPageNarrowBreakout } from '@atlaskit/editor-shared-styles';
|
|
11
11
|
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- to be migrated to @atlaskit/primitives/compiled – go/akcss
|
|
12
12
|
import { Box, xcss } from '@atlaskit/primitives';
|
|
13
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
13
14
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
15
|
+
const RIGHT_CONTROL_HIDE_DELAY_MS = 150;
|
|
14
16
|
const baseStyles = xcss({
|
|
15
17
|
transition: 'opacity 0.1s ease-in-out, visibility 0.1s ease-in-out'
|
|
16
18
|
});
|
|
@@ -40,15 +42,69 @@ const hiddenStylesCSS = css({
|
|
|
40
42
|
});
|
|
41
43
|
export const VisibilityContainer = ({
|
|
42
44
|
api,
|
|
43
|
-
children
|
|
45
|
+
children,
|
|
46
|
+
controlSide
|
|
44
47
|
}) => {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
const {
|
|
49
|
+
isTypeAheadOpen,
|
|
50
|
+
isEditing,
|
|
51
|
+
isMouseOut,
|
|
52
|
+
hoverSide,
|
|
53
|
+
editorViewMode,
|
|
54
|
+
userIntent,
|
|
55
|
+
rightSideControlsEnabled
|
|
56
|
+
} = useSharedPluginStateWithSelector(api, ['typeAhead', 'blockControls', 'editorViewMode', 'userIntent'], states => {
|
|
57
|
+
var _states$typeAheadStat, _states$blockControls, _states$blockControls2, _states$blockControls3, _states$editorViewMod, _states$userIntentSta, _states$blockControls4;
|
|
58
|
+
return {
|
|
59
|
+
isTypeAheadOpen: (_states$typeAheadStat = states.typeAheadState) === null || _states$typeAheadStat === void 0 ? void 0 : _states$typeAheadStat.isOpen,
|
|
60
|
+
isEditing: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isEditing,
|
|
61
|
+
isMouseOut: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isMouseOut,
|
|
62
|
+
hoverSide: (_states$blockControls3 = states.blockControlsState) === null || _states$blockControls3 === void 0 ? void 0 : _states$blockControls3.hoverSide,
|
|
63
|
+
editorViewMode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode,
|
|
64
|
+
userIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent,
|
|
65
|
+
rightSideControlsEnabled: (_states$blockControls4 = states.blockControlsState) === null || _states$blockControls4 === void 0 ? void 0 : _states$blockControls4.rightSideControlsEnabled
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
const isViewMode = editorViewMode === 'view';
|
|
69
|
+
const shouldRestrictBySide = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && controlSide !== undefined && !isViewMode;
|
|
70
|
+
// Only restrict by side when hoverSide is known (after mousemove). When undefined, show both
|
|
71
|
+
// controls so drag handle is visible on load and for keyboard-only users.
|
|
72
|
+
const sideHidden = shouldRestrictBySide && hoverSide !== undefined ? hoverSide !== controlSide : false;
|
|
73
|
+
// In view mode with right-side controls, we delay hiding on isMouseOut (see below) so the right-edge
|
|
74
|
+
// button stays visible when the user moves from the block toward the button (e.g. in edit/live
|
|
75
|
+
// pages), avoiding flicker as the mouse crosses boundaries.
|
|
76
|
+
const hideOnMouseOut = isMouseOut;
|
|
77
|
+
const shouldHideImmediate = isTypeAheadOpen || isEditing || hideOnMouseOut || userIntent === 'aiStreaming' || sideHidden;
|
|
48
78
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
const
|
|
79
|
+
// Delay hiding the right control in view mode to reduce flickering when moving from block
|
|
80
|
+
// toward the right-edge button (avoids rapid show/hide as mouse crosses boundaries).
|
|
81
|
+
const isRightControlViewMode = isViewMode && rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true) && controlSide === 'right';
|
|
82
|
+
// When in right-control view mode, we delay hiding so start visible; useEffect will update after delay
|
|
83
|
+
const [delayedShouldHide, setDelayedShouldHide] = useState(false);
|
|
84
|
+
const hideTimeoutRef = useRef(null);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!isRightControlViewMode) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!shouldHideImmediate) {
|
|
90
|
+
if (hideTimeoutRef.current) {
|
|
91
|
+
clearTimeout(hideTimeoutRef.current);
|
|
92
|
+
hideTimeoutRef.current = null;
|
|
93
|
+
}
|
|
94
|
+
setDelayedShouldHide(false);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
98
|
+
hideTimeoutRef.current = null;
|
|
99
|
+
setDelayedShouldHide(true);
|
|
100
|
+
}, RIGHT_CONTROL_HIDE_DELAY_MS);
|
|
101
|
+
return () => {
|
|
102
|
+
if (hideTimeoutRef.current) {
|
|
103
|
+
clearTimeout(hideTimeoutRef.current);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}, [shouldHideImmediate, isRightControlViewMode]);
|
|
107
|
+
const shouldHide = isRightControlViewMode ? delayedShouldHide : shouldHideImmediate;
|
|
52
108
|
if (editorExperiment('platform_editor_preview_panel_responsiveness', true, {
|
|
53
109
|
exposure: true
|
|
54
110
|
})) {
|
|
@@ -6,6 +6,7 @@ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
|
6
6
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
7
7
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
10
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
10
11
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
11
12
|
import { handleKeyDownWithPreservedSelection } from './editor-commands/handle-key-down-with-preserved-selection';
|
|
@@ -23,8 +24,11 @@ import { createSelectionPreservationPlugin } from './pm-plugins/selection-preser
|
|
|
23
24
|
import { selectNode } from './pm-plugins/utils/getSelection';
|
|
24
25
|
import { GlobalStylesWrapper } from './ui/global-styles';
|
|
25
26
|
export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
26
|
-
var
|
|
27
|
+
var _config$rightSideCont;
|
|
28
|
+
var api = _ref.api,
|
|
29
|
+
config = _ref.config;
|
|
27
30
|
var nodeDecorationRegistry = [];
|
|
31
|
+
var rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
|
|
28
32
|
return {
|
|
29
33
|
name: 'blockControls',
|
|
30
34
|
actions: {
|
|
@@ -46,13 +50,15 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
46
50
|
plugin: function plugin(_ref2) {
|
|
47
51
|
var getIntl = _ref2.getIntl,
|
|
48
52
|
nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
|
|
49
|
-
return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry);
|
|
53
|
+
return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true));
|
|
50
54
|
}
|
|
51
55
|
}];
|
|
52
56
|
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
53
57
|
pmPlugins.push({
|
|
54
58
|
name: 'blockControlsInteractionTrackingPlugin',
|
|
55
|
-
plugin:
|
|
59
|
+
plugin: function plugin() {
|
|
60
|
+
return createInteractionTrackingPlugin(rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true));
|
|
61
|
+
}
|
|
56
62
|
});
|
|
57
63
|
}
|
|
58
64
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
@@ -325,6 +331,11 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
325
331
|
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
326
332
|
var _interactionTrackingP2, _interactionTrackingP3;
|
|
327
333
|
sharedState.isMouseOut = (_interactionTrackingP2 = (_interactionTrackingP3 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP3 === void 0 ? void 0 : _interactionTrackingP3.isMouseOut) !== null && _interactionTrackingP2 !== void 0 ? _interactionTrackingP2 : false;
|
|
334
|
+
sharedState.rightSideControlsEnabled = rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true);
|
|
335
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
336
|
+
var _interactionTrackingP4;
|
|
337
|
+
sharedState.hoverSide = (_interactionTrackingP4 = interactionTrackingPluginKey.getState(editorState)) === null || _interactionTrackingP4 === void 0 ? void 0 : _interactionTrackingP4.hoverSide;
|
|
338
|
+
}
|
|
328
339
|
}
|
|
329
340
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
330
341
|
var _selectionPreservatio;
|
|
@@ -77,6 +77,9 @@ export var dragHandleDecoration = function dragHandleDecoration(_ref) {
|
|
|
77
77
|
var element = document.createElement('span');
|
|
78
78
|
// inline decoration causes focus issues when refocusing Editor into first line
|
|
79
79
|
element.style.display = 'block';
|
|
80
|
+
if (expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
81
|
+
element.setAttribute('data-blocks-decorator-widget', 'true');
|
|
82
|
+
}
|
|
80
83
|
element.setAttribute('data-testid', 'block-ctrl-decorator-widget');
|
|
81
84
|
element.setAttribute('data-blocks-drag-handle-container', 'true');
|
|
82
85
|
element.setAttribute('data-blocks-drag-handle-key', key);
|
|
@@ -68,6 +68,9 @@ export var quickInsertButtonDecoration = function quickInsertButtonDecoration(_r
|
|
|
68
68
|
}
|
|
69
69
|
element.contentEditable = 'false';
|
|
70
70
|
element.setAttribute('data-blocks-quick-insert-container', 'true');
|
|
71
|
+
if (expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
72
|
+
element.setAttribute('data-blocks-quick-insert-button', 'true');
|
|
73
|
+
}
|
|
71
74
|
element.setAttribute('data-testid', 'block-ctrl-quick-insert-button');
|
|
72
75
|
if (editorExperiment('platform_editor_block_control_optimise_render', true, {
|
|
73
76
|
exposure: true
|
|
@@ -38,7 +38,7 @@ var getDefaultNodeSelector = memoizeOne(function () {
|
|
|
38
38
|
return getNodeSelector([].concat(_toConsumableArray(IGNORE_NODES_NEXT), ['media']), [].concat(_toConsumableArray(IGNORE_NODE_DESCENDANTS_ADVANCED_LAYOUT), ['table']));
|
|
39
39
|
});
|
|
40
40
|
export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
41
|
-
var _api$blockControls, _api$editorDisabled, _target$classList;
|
|
41
|
+
var _api$blockControls, _api$editorDisabled, _api$editorViewMode, _api$blockControls$sh, _api$blockControls2, _target$classList;
|
|
42
42
|
var _ref = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {},
|
|
43
43
|
isDragging = _ref.isDragging,
|
|
44
44
|
activeNode = _ref.activeNode,
|
|
@@ -49,10 +49,14 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
|
49
49
|
editorDisabled: false
|
|
50
50
|
},
|
|
51
51
|
editorDisabled = _ref2.editorDisabled;
|
|
52
|
+
var editorViewMode = api === null || api === void 0 || (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 || (_api$editorViewMode = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode === void 0 ? void 0 : _api$editorViewMode.mode;
|
|
53
|
+
var isViewMode = editorViewMode === 'view';
|
|
52
54
|
var toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
|
|
53
55
|
|
|
54
|
-
// We shouldn't be firing mouse over transactions when the editor is disabled
|
|
55
|
-
|
|
56
|
+
// We shouldn't be firing mouse over transactions when the editor is disabled,
|
|
57
|
+
// except in view mode when right-side controls are enabled (show controls on block hover)
|
|
58
|
+
var rightSideControlsEnabled = (_api$blockControls$sh = api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.rightSideControlsEnabled) !== null && _api$blockControls$sh !== void 0 ? _api$blockControls$sh : false;
|
|
59
|
+
if (editorDisabled && (!isViewMode || !(rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)))) {
|
|
56
60
|
return false;
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -75,6 +79,18 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
|
75
79
|
return false;
|
|
76
80
|
}
|
|
77
81
|
var rootElement = target === null || target === void 0 ? void 0 : target.closest(isNativeAnchorSupported ? getDefaultNodeSelector() : "[data-drag-handler-anchor-name]");
|
|
82
|
+
|
|
83
|
+
// When hovering over the right-edge button (rendered in a portal outside the block), resolve the
|
|
84
|
+
// block from the container's anchor so activeNode stays set and the button remains visible.
|
|
85
|
+
if (!rootElement && rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
86
|
+
var rightEdgeContainer = target === null || target === void 0 ? void 0 : target.closest('[data-blocks-right-edge-button-container]');
|
|
87
|
+
if (rightEdgeContainer) {
|
|
88
|
+
var anchor = rightEdgeContainer.getAttribute('data-blocks-right-edge-button-anchor');
|
|
89
|
+
if (anchor) {
|
|
90
|
+
rootElement = view.dom.querySelector("[".concat(getAnchorAttrName(), "=\"").concat(CSS.escape(anchor), "\"]"));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
78
94
|
if (rootElement) {
|
|
79
95
|
var _rootElement$parentEl;
|
|
80
96
|
// We want to exlude handles from showing for empty paragraph and heading nodes
|
|
@@ -183,22 +199,22 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
|
|
|
183
199
|
// as when it is a multi-selection, the showDragHandleAt command interfere with selection
|
|
184
200
|
// sometimes makes the multi-selection not continous after block menu is opened with keyboard
|
|
185
201
|
if (!(isMultipleSelected && isMenuOpen && blockMenuOptions !== null && blockMenuOptions !== void 0 && blockMenuOptions.openedViaKeyboard)) {
|
|
186
|
-
var _api$core, _api$
|
|
187
|
-
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$
|
|
202
|
+
var _api$core, _api$blockControls3;
|
|
203
|
+
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.commands.showDragHandleAt(targetPos, anchorName, nodeType, undefined, rootPos !== null && rootPos !== void 0 ? rootPos : targetPos, rootAnchorName !== null && rootAnchorName !== void 0 ? rootAnchorName : anchorName, rootNodeType !== null && rootNodeType !== void 0 ? rootNodeType : nodeType));
|
|
188
204
|
}
|
|
189
205
|
} else {
|
|
190
|
-
var _api$core2, _api$
|
|
191
|
-
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(api === null || api === void 0 || (_api$
|
|
206
|
+
var _api$core2, _api$blockControls4;
|
|
207
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.commands.showDragHandleAt(targetPos, anchorName, nodeType, undefined, rootPos !== null && rootPos !== void 0 ? rootPos : targetPos, rootAnchorName !== null && rootAnchorName !== void 0 ? rootAnchorName : anchorName, rootNodeType !== null && rootNodeType !== void 0 ? rootNodeType : nodeType));
|
|
192
208
|
}
|
|
193
209
|
} else {
|
|
194
|
-
var _api$core3, _api$
|
|
195
|
-
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 || (_api$
|
|
210
|
+
var _api$core3, _api$blockControls5;
|
|
211
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 ? void 0 : _api$blockControls5.commands.showDragHandleAt(targetPos, anchorName, nodeType));
|
|
196
212
|
}
|
|
197
213
|
if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
|
|
198
214
|
var _api$userIntent;
|
|
199
215
|
if (isMenuOpen && originalAnchorName && (api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent) === 'blockMenuOpen') {
|
|
200
|
-
var _api$core4, _api$
|
|
201
|
-
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$
|
|
216
|
+
var _api$core4, _api$blockControls6;
|
|
217
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 ? void 0 : _api$blockControls6.commands.toggleBlockMenu());
|
|
202
218
|
}
|
|
203
219
|
}
|
|
204
220
|
}
|
|
@@ -18,4 +18,15 @@ export var mouseEnter = function mouseEnter(view) {
|
|
|
18
18
|
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
19
19
|
type: 'mouseEnter'
|
|
20
20
|
}));
|
|
21
|
+
};
|
|
22
|
+
export var setHoverSide = function setHoverSide(view, side) {
|
|
23
|
+
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
24
|
+
type: 'setHoverSide',
|
|
25
|
+
side: side
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
export var clearHoverSide = function clearHoverSide(view) {
|
|
29
|
+
view.dispatch(view.state.tr.setMeta(interactionTrackingPluginKey, {
|
|
30
|
+
type: 'clearHoverSide'
|
|
31
|
+
}));
|
|
21
32
|
};
|
|
@@ -1,14 +1,110 @@
|
|
|
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
|
+
var pendingByView = new WeakMap();
|
|
7
|
+
|
|
8
|
+
/** Per-view RAF handle so clearPendingHoverSide cancels only that view's callback. */
|
|
9
|
+
var rafIdByView = new WeakMap();
|
|
10
|
+
var cancelScheduledProcessForView = function cancelScheduledProcessForView(view) {
|
|
11
|
+
var id = rafIdByView.get(view);
|
|
12
|
+
if (id !== undefined) {
|
|
13
|
+
cancelAnimationFrame(id);
|
|
14
|
+
rafIdByView.delete(view);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var clearPendingHoverSide = function clearPendingHoverSide(view) {
|
|
18
|
+
pendingByView.delete(view);
|
|
19
|
+
cancelScheduledProcessForView(view);
|
|
20
|
+
};
|
|
21
|
+
var BLOCK_SELECTORS = '[data-node-anchor], [data-drag-handler-anchor-name]';
|
|
22
|
+
var TABLE_SELECTOR = '[data-prosemirror-node-name="table"]';
|
|
23
|
+
var RIGHT_EDGE_SELECTOR = '[data-blocks-right-edge-button-container]';
|
|
24
|
+
var isInsideTable = function 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
|
+
var processHoverSide = function processHoverSide(view) {
|
|
29
|
+
var event = pendingByView.get(view);
|
|
30
|
+
if (!event) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
pendingByView.delete(view);
|
|
34
|
+
rafIdByView.delete(view);
|
|
35
|
+
var editorContentArea = view.dom.closest('.ak-editor-content-area');
|
|
36
|
+
if (!(editorContentArea instanceof HTMLElement)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
var state = getInteractionTrackingState(view.state);
|
|
40
|
+
var 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
|
+
var 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
|
+
var 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
|
+
var blockElement = target === null || target === void 0 ? void 0 : target.closest(BLOCK_SELECTORS);
|
|
61
|
+
var 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
|
+
var _boundsElement$getBou = boundsElement.getBoundingClientRect(),
|
|
72
|
+
left = _boundsElement$getBou.left,
|
|
73
|
+
right = _boundsElement$getBou.right;
|
|
74
|
+
var midpoint = (left + right) / 2;
|
|
75
|
+
var nextHoverSide = event.clientX > midpoint ? 'right' : 'left';
|
|
76
|
+
if ((state === null || state === void 0 ? void 0 : state.hoverSide) !== nextHoverSide) {
|
|
77
|
+
setHoverSide(view, nextHoverSide);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
export var handleMouseMove = function handleMouseMove(view, event) {
|
|
81
|
+
var rightSideControlsEnabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
4
82
|
var 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
|
+
var id = requestAnimationFrame(function () {
|
|
98
|
+
processHoverSide(view);
|
|
99
|
+
});
|
|
100
|
+
rafIdByView.set(view, id);
|
|
9
101
|
return false;
|
|
10
102
|
};
|
|
11
103
|
export var handleMouseLeave = function handleMouseLeave(view) {
|
|
104
|
+
var rightSideControlsEnabled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
105
|
+
if (rightSideControlsEnabled && expValEquals('confluence_remix_icon_right_side', 'isEnabled', true)) {
|
|
106
|
+
clearPendingHoverSide(view);
|
|
107
|
+
}
|
|
12
108
|
mouseLeave(view);
|
|
13
109
|
return false;
|
|
14
110
|
};
|