@atlaskit/editor-plugin-block-controls 20.0.3 → 20.1.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 +19 -0
- package/dist/cjs/blockControlsPlugin.js +53 -17
- package/dist/cjs/editor-commands/show-drag-handle.js +17 -5
- package/dist/cjs/pm-plugins/decorations-anchor.js +2 -1
- package/dist/cjs/pm-plugins/decorations-drop-target-active.js +2 -1
- package/dist/cjs/pm-plugins/decorations-drop-target.js +2 -1
- package/dist/cjs/pm-plugins/decorations-surface-anchor.js +72 -0
- package/dist/cjs/pm-plugins/handle-mouse-down.js +2 -1
- package/dist/cjs/pm-plugins/handle-mouse-over.js +3 -2
- package/dist/cjs/pm-plugins/handle-sparse-mouse-over.js +125 -0
- package/dist/cjs/pm-plugins/main.js +66 -54
- package/dist/cjs/pm-plugins/sparse-surfaces.js +49 -0
- package/dist/cjs/pm-plugins/utils/sparse-surface-candidates.js +419 -0
- package/dist/cjs/pm-plugins/utils/sparse-surfaces-mapping.js +108 -0
- package/dist/cjs/pm-plugins/utils/sparse-surfaces-state.js +53 -0
- package/dist/cjs/pm-plugins/utils/sparse-surfaces-view.js +134 -0
- package/dist/cjs/pm-plugins/utils/surface-viewport.js +223 -0
- package/dist/cjs/pm-plugins/utils/transactions.js +5 -0
- package/dist/cjs/ui/block-controls-left-surfaces.js +31 -25
- package/dist/cjs/ui/block-controls-right-surfaces.js +31 -25
- package/dist/cjs/ui/block-controls-surface-context.js +1 -0
- package/dist/cjs/ui/block-controls-surface-drag-handle-registration.js +6 -7
- package/dist/cjs/ui/block-controls-surface-drag-handle.js +6 -2
- package/dist/cjs/ui/drag-handle.js +5 -3
- package/dist/cjs/ui/drop-target-layout.js +3 -2
- package/dist/cjs/ui/drop-target.js +3 -2
- package/dist/cjs/ui/global-styles.js +69 -27
- package/dist/cjs/ui/inline-drop-target.js +6 -5
- package/dist/cjs/ui/utils/anchor-name.js +2 -1
- package/dist/cjs/ui/utils/dom-attr-name.js +3 -2
- package/dist/cjs/ui/utils/get-surface-placement.js +2 -1
- package/dist/es2019/blockControlsPlugin.js +42 -8
- package/dist/es2019/editor-commands/show-drag-handle.js +14 -2
- package/dist/es2019/pm-plugins/decorations-anchor.js +2 -1
- package/dist/es2019/pm-plugins/decorations-drop-target-active.js +2 -1
- package/dist/es2019/pm-plugins/decorations-drop-target.js +2 -1
- package/dist/es2019/pm-plugins/decorations-surface-anchor.js +56 -0
- package/dist/es2019/pm-plugins/handle-mouse-down.js +2 -1
- package/dist/es2019/pm-plugins/handle-mouse-over.js +3 -2
- package/dist/es2019/pm-plugins/handle-sparse-mouse-over.js +116 -0
- package/dist/es2019/pm-plugins/main.js +70 -54
- package/dist/es2019/pm-plugins/sparse-surfaces.js +37 -0
- package/dist/es2019/pm-plugins/utils/sparse-surface-candidates.js +305 -0
- package/dist/es2019/pm-plugins/utils/sparse-surfaces-mapping.js +78 -0
- package/dist/es2019/pm-plugins/utils/sparse-surfaces-state.js +39 -0
- package/dist/es2019/pm-plugins/utils/sparse-surfaces-view.js +121 -0
- package/dist/es2019/pm-plugins/utils/surface-viewport.js +192 -0
- package/dist/es2019/pm-plugins/utils/transactions.js +5 -0
- package/dist/es2019/ui/block-controls-left-surfaces.js +21 -14
- package/dist/es2019/ui/block-controls-right-surfaces.js +21 -14
- package/dist/es2019/ui/block-controls-surface-context.js +1 -0
- package/dist/es2019/ui/block-controls-surface-drag-handle-registration.js +4 -5
- package/dist/es2019/ui/block-controls-surface-drag-handle.js +6 -2
- package/dist/es2019/ui/drag-handle.js +5 -3
- package/dist/es2019/ui/drop-target-layout.js +3 -2
- package/dist/es2019/ui/drop-target.js +3 -2
- package/dist/es2019/ui/global-styles.js +67 -28
- package/dist/es2019/ui/inline-drop-target.js +6 -5
- package/dist/es2019/ui/utils/anchor-name.js +2 -1
- package/dist/es2019/ui/utils/dom-attr-name.js +3 -2
- package/dist/es2019/ui/utils/get-surface-placement.js +2 -1
- package/dist/esm/blockControlsPlugin.js +53 -17
- package/dist/esm/editor-commands/show-drag-handle.js +17 -5
- package/dist/esm/pm-plugins/decorations-anchor.js +2 -1
- package/dist/esm/pm-plugins/decorations-drop-target-active.js +2 -1
- package/dist/esm/pm-plugins/decorations-drop-target.js +2 -1
- package/dist/esm/pm-plugins/decorations-surface-anchor.js +65 -0
- package/dist/esm/pm-plugins/handle-mouse-down.js +2 -1
- package/dist/esm/pm-plugins/handle-mouse-over.js +3 -2
- package/dist/esm/pm-plugins/handle-sparse-mouse-over.js +119 -0
- package/dist/esm/pm-plugins/main.js +66 -54
- package/dist/esm/pm-plugins/sparse-surfaces.js +43 -0
- package/dist/esm/pm-plugins/utils/sparse-surface-candidates.js +413 -0
- package/dist/esm/pm-plugins/utils/sparse-surfaces-mapping.js +101 -0
- package/dist/esm/pm-plugins/utils/sparse-surfaces-state.js +46 -0
- package/dist/esm/pm-plugins/utils/sparse-surfaces-view.js +127 -0
- package/dist/esm/pm-plugins/utils/surface-viewport.js +217 -0
- package/dist/esm/pm-plugins/utils/transactions.js +5 -0
- package/dist/esm/ui/block-controls-left-surfaces.js +33 -27
- package/dist/esm/ui/block-controls-right-surfaces.js +33 -27
- package/dist/esm/ui/block-controls-surface-context.js +1 -0
- package/dist/esm/ui/block-controls-surface-drag-handle-registration.js +7 -8
- package/dist/esm/ui/block-controls-surface-drag-handle.js +6 -2
- package/dist/esm/ui/drag-handle.js +5 -3
- package/dist/esm/ui/drop-target-layout.js +3 -2
- package/dist/esm/ui/drop-target.js +3 -2
- package/dist/esm/ui/global-styles.js +70 -28
- package/dist/esm/ui/inline-drop-target.js +6 -5
- package/dist/esm/ui/utils/anchor-name.js +2 -1
- package/dist/esm/ui/utils/dom-attr-name.js +3 -2
- package/dist/esm/ui/utils/get-surface-placement.js +2 -1
- package/dist/types/blockControlsPluginType.d.ts +10 -3
- package/dist/types/pm-plugins/decorations-surface-anchor.d.ts +22 -0
- package/dist/types/pm-plugins/handle-sparse-mouse-over.d.ts +5 -0
- package/dist/types/pm-plugins/main.d.ts +2 -9
- package/dist/types/pm-plugins/sparse-surfaces.d.ts +8 -0
- package/dist/types/pm-plugins/utils/sparse-surface-candidates.d.ts +89 -0
- package/dist/types/pm-plugins/utils/sparse-surfaces-mapping.d.ts +20 -0
- package/dist/types/pm-plugins/utils/sparse-surfaces-state.d.ts +27 -0
- package/dist/types/pm-plugins/utils/sparse-surfaces-view.d.ts +15 -0
- package/dist/types/pm-plugins/utils/surface-viewport.d.ts +10 -0
- package/dist/types/ui/utils/get-surface-placement.d.ts +3 -2
- package/package.json +5 -5
- package/dist/cjs/pm-plugins/utils/surface-node-positions.js +0 -100
- package/dist/es2019/pm-plugins/utils/surface-node-positions.js +0 -78
- package/dist/esm/pm-plugins/utils/surface-node-positions.js +0 -93
- package/dist/types/pm-plugins/utils/surface-node-positions.d.ts +0 -14
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
2
|
+
export const TYPE_SURFACE_ANCHOR_DEC = 'block-controls-surface-anchor';
|
|
3
|
+
export const SURFACE_ANCHOR_ATTR = 'data-block-controls-surface-anchor';
|
|
4
|
+
export const SURFACE_NODE_TYPE_ATTR = 'data-block-controls-surface-node-type';
|
|
5
|
+
export const SURFACE_ANCHOR_VARIABLE = '--block-controls-surface-anchor-name';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* These node views expose the box used by the measured placement fallback rather than their
|
|
9
|
+
* ProseMirror node wrapper. The marker carries the name through a custom property so sparse CSS
|
|
10
|
+
* can name that inner box without adding a widget or changing the node view.
|
|
11
|
+
*/
|
|
12
|
+
const INNER_CONTENT_NODE_TYPES = new Set(['blockCard', 'bodiedExtension', 'embedCard', 'extension', 'mediaSingle', 'multiBodiedExtension', 'table']);
|
|
13
|
+
const getMarkerStyle = (nodeType, anchorName) => {
|
|
14
|
+
const inheritedName = `${SURFACE_ANCHOR_VARIABLE}: ${anchorName};`;
|
|
15
|
+
|
|
16
|
+
// Inner boxes get their anchor from the sparse global selector. Naming only the node wrapper
|
|
17
|
+
// would position media/table/extension controls against the wrapper instead of visible content.
|
|
18
|
+
return INNER_CONTENT_NODE_TYPES.has(nodeType) ? inheritedName : `${inheritedName} anchor-name: ${anchorName};`;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Builds sparse CSS anchor decorations from already-qualified cached positions. Anchor identity is
|
|
23
|
+
* supplied by the editor's native node-anchor provider so sparse surfaces and consumers share the
|
|
24
|
+
* same `data-node-anchor`.
|
|
25
|
+
*/
|
|
26
|
+
export const createSurfaceAnchorDecorations = (state, positions, resolveAnchorName, previousAnchors) => {
|
|
27
|
+
const anchors = new Map();
|
|
28
|
+
const decorations = [];
|
|
29
|
+
for (const position of positions) {
|
|
30
|
+
if (anchors.has(position)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const node = state.doc.nodeAt(position);
|
|
34
|
+
if (!(node !== null && node !== void 0 && node.isBlock)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const anchorName = resolveAnchorName(node, position, previousAnchors === null || previousAnchors === void 0 ? void 0 : previousAnchors.get(position));
|
|
38
|
+
if (!anchorName) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
anchors.set(position, anchorName);
|
|
42
|
+
decorations.push(Decoration.node(position, position + node.nodeSize, {
|
|
43
|
+
[SURFACE_ANCHOR_ATTR]: anchorName,
|
|
44
|
+
[SURFACE_NODE_TYPE_ATTR]: node.type.name,
|
|
45
|
+
style: getMarkerStyle(node.type.name, anchorName)
|
|
46
|
+
}, {
|
|
47
|
+
type: TYPE_SURFACE_ANCHOR_DEC,
|
|
48
|
+
anchorName,
|
|
49
|
+
nodeType: node.type.name
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
anchors,
|
|
54
|
+
decorations: DecorationSet.create(state.doc, decorations)
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
|
|
2
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
2
3
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
3
4
|
export const handleMouseDown = api => (view, event) => {
|
|
4
5
|
if (!(event.target instanceof HTMLElement)) {
|
|
@@ -12,7 +13,7 @@ export const handleMouseDown = api => (view, event) => {
|
|
|
12
13
|
if (!rootNode) {
|
|
13
14
|
return false;
|
|
14
15
|
}
|
|
15
|
-
if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
|
|
16
|
+
if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
|
|
16
17
|
var _rootNode$type$name, _rootNode$type$name2;
|
|
17
18
|
const anchorName = api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(rootNode, rootPos);
|
|
18
19
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import memoizeOne from 'memoize-one';
|
|
2
2
|
import { isMultiBlockSelection } from '@atlaskit/editor-common/selection';
|
|
3
3
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
4
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
4
5
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
5
6
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
|
|
6
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -132,7 +133,7 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
132
133
|
// Ignored via go/ees005
|
|
133
134
|
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
134
135
|
const target = event.target;
|
|
135
|
-
const isNativeAnchorSupported = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true);
|
|
136
|
+
const isNativeAnchorSupported = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration');
|
|
136
137
|
if (target !== null && target !== void 0 && (_target$classList = target.classList) !== null && _target$classList !== void 0 && _target$classList.contains('ProseMirror')) {
|
|
137
138
|
return false;
|
|
138
139
|
}
|
|
@@ -204,7 +205,7 @@ export const handleMouseOver = (view, event, api) => {
|
|
|
204
205
|
// This must happen before anchorName is read so the correct node's handle is shown.
|
|
205
206
|
rootElement = redirectParagraphToWrappedMedia(rootElement, isNativeAnchorSupported);
|
|
206
207
|
let anchorName;
|
|
207
|
-
if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
|
|
208
|
+
if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
|
|
208
209
|
anchorName = rootElement.getAttribute(getAnchorAttrName());
|
|
209
210
|
|
|
210
211
|
// don't show handles if we can't find an anchor
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
3
|
+
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
4
|
+
import { getNodeTypeWithLevel } from './decorations-common';
|
|
5
|
+
const OPAQUE_BLOCKS = new Set(['table', 'bulletList', 'orderedList', 'taskList', 'decisionList', 'mediaSingle']);
|
|
6
|
+
const EXCLUDED_BLOCKS = new Set(['listItem', 'tableRow', 'tableCell', 'tableHeader', 'caption']);
|
|
7
|
+
const isPanelNodeTypeName = nodeTypeName => nodeTypeName === 'panel' || nodeTypeName === 'panel_c1' && expValEqualsNoExposure('platform_editor_controls_reliable_anchor', 'isEnabled', true) && fg('platform_editor_controls_reliable_anchor_patch_1');
|
|
8
|
+
const redirectParagraphToWrappedMedia = (view, $target, targetPosition) => {
|
|
9
|
+
const node = view.state.doc.nodeAt(targetPosition);
|
|
10
|
+
if (!node || node.type.name !== 'paragraph') {
|
|
11
|
+
return {
|
|
12
|
+
position: targetPosition,
|
|
13
|
+
node
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const index = $target.index();
|
|
17
|
+
for (const siblingIndex of [index - 1, index + 1]) {
|
|
18
|
+
if (siblingIndex < 0 || siblingIndex >= $target.parent.childCount) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const sibling = $target.parent.child(siblingIndex);
|
|
22
|
+
if ((sibling.type.name === 'mediaSingle' || sibling.type.name === 'embedCard') && (sibling.attrs.layout === 'wrap-left' || sibling.attrs.layout === 'wrap-right')) {
|
|
23
|
+
return {
|
|
24
|
+
position: siblingIndex < index ? targetPosition - sibling.nodeSize : targetPosition + node.nodeSize,
|
|
25
|
+
node: sibling
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
position: targetPosition,
|
|
31
|
+
node
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** Resolves hover from PM structure so the first hover can create its sparse candidate. */
|
|
36
|
+
export const handleSparseMouseOver = (view, event, api) => {
|
|
37
|
+
var _api$editorDisabled$s, _api$editorDisabled, _api$editorDisabled$s2, _api$editorViewMode, _api$editorViewMode$s, _api$showDiff$sharedS, _api$showDiff, _api$showDiff$sharedS2, _api$userIntent, _api$userIntent$share, _$pos$nodeAfter, _controls$activeNode, _anchors$get, _anchors$get2;
|
|
38
|
+
const controls = api === null || api === void 0 ? void 0 : api.blockControls.sharedState.currentState();
|
|
39
|
+
if (!api || controls !== null && controls !== void 0 && controls.isDragging || !(event.target instanceof Element) || event.target === view.dom) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const editorDisabled = (_api$editorDisabled$s = (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 ? void 0 : (_api$editorDisabled$s2 = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled$s2 === void 0 ? void 0 : _api$editorDisabled$s2.editorDisabled) !== null && _api$editorDisabled$s !== void 0 ? _api$editorDisabled$s : false;
|
|
43
|
+
const editorViewMode = (_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;
|
|
44
|
+
if (editorDisabled && (editorViewMode !== 'view' || !(controls !== null && controls !== void 0 && controls.rightSideControlsEnabled))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const isDisplayingDiff = (_api$showDiff$sharedS = (_api$showDiff = api.showDiff) === null || _api$showDiff === void 0 ? void 0 : (_api$showDiff$sharedS2 = _api$showDiff.sharedState.currentState()) === null || _api$showDiff$sharedS2 === void 0 ? void 0 : _api$showDiff$sharedS2.isDisplayingChanges) !== null && _api$showDiff$sharedS !== void 0 ? _api$showDiff$sharedS : false;
|
|
48
|
+
const currentUserIntent = (_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;
|
|
49
|
+
if ((isDisplayingDiff || currentUserIntent === 'reviewing') && expValEqualsNoExposure('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
let position;
|
|
53
|
+
try {
|
|
54
|
+
position = view.posAtDOM(event.target, 0);
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const $pos = view.state.doc.resolve(position);
|
|
59
|
+
let targetPosition;
|
|
60
|
+
let opaque = false;
|
|
61
|
+
for (let depth = 1; depth <= $pos.depth; depth++) {
|
|
62
|
+
const node = $pos.node(depth);
|
|
63
|
+
if (!node.isBlock || EXCLUDED_BLOCKS.has(node.type.name)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
targetPosition = $pos.before(depth);
|
|
67
|
+
if (OPAQUE_BLOCKS.has(node.type.name)) {
|
|
68
|
+
opaque = true;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!opaque && (_$pos$nodeAfter = $pos.nodeAfter) !== null && _$pos$nodeAfter !== void 0 && _$pos$nodeAfter.isBlock && !EXCLUDED_BLOCKS.has($pos.nodeAfter.type.name)) {
|
|
73
|
+
// Browser positions over non-editable node chrome can resolve to the first editable child.
|
|
74
|
+
// Keep the ancestor unless that child actually owns the hovered DOM target.
|
|
75
|
+
const nodeAfterDOM = view.nodeDOM(position);
|
|
76
|
+
if (nodeAfterDOM instanceof Element && nodeAfterDOM.contains(event.target)) {
|
|
77
|
+
targetPosition = position;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (targetPosition === undefined) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const initialNode = view.state.doc.nodeAt(targetPosition);
|
|
84
|
+
if (!initialNode) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const target = redirectParagraphToWrappedMedia(view, view.state.doc.resolve(targetPosition), targetPosition);
|
|
88
|
+
targetPosition = target.position;
|
|
89
|
+
const node = target.node;
|
|
90
|
+
if (!node || (controls === null || controls === void 0 ? void 0 : (_controls$activeNode = controls.activeNode) === null || _controls$activeNode === void 0 ? void 0 : _controls$activeNode.pos) === targetPosition) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const $target = view.state.doc.resolve(targetPosition);
|
|
94
|
+
if ($target.depth > 0 && (node.type.name === 'paragraph' || node.type.name === 'heading') && node.content.size === 0) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const parentNode = $target.parent;
|
|
98
|
+
const parentPosition = $target.depth > 0 ? $target.before($target.depth) : undefined;
|
|
99
|
+
const parentDOM = parentPosition === undefined ? undefined : view.nodeDOM(parentPosition);
|
|
100
|
+
if (isPanelNodeTypeName(parentNode.type.name) && !(parentDOM instanceof HTMLElement && parentDOM.classList.contains('ak-editor-panel__no-icon')) && $target.index() === 0) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (node.type.name === 'layoutColumn' && parentNode.type.name === 'layoutSection' && parentNode.childCount === 1 && expValEqualsNoExposure('advanced_layouts', 'isEnabled', true) && !expValEquals('platform_editor_layout_column_menu', 'isEnabled', true)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const anchors = controls === null || controls === void 0 ? void 0 : controls.surfaceAnchors;
|
|
107
|
+
const anchorName = (_anchors$get = anchors === null || anchors === void 0 ? void 0 : anchors.get(targetPosition)) !== null && _anchors$get !== void 0 ? _anchors$get : api.core.actions.getAnchorIdForNode(node, targetPosition);
|
|
108
|
+
const rootPos = $target.depth > 0 ? $target.before(1) : targetPosition;
|
|
109
|
+
const rootNode = view.state.doc.nodeAt(rootPos);
|
|
110
|
+
const rootAnchorName = (_anchors$get2 = anchors === null || anchors === void 0 ? void 0 : anchors.get(rootPos)) !== null && _anchors$get2 !== void 0 ? _anchors$get2 : rootNode ? api.core.actions.getAnchorIdForNode(rootNode, rootPos) : undefined;
|
|
111
|
+
if (!anchorName || !rootNode) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
api.core.actions.execute(api.blockControls.commands.showDragHandleAt(targetPosition, anchorName, getNodeTypeWithLevel(node), undefined, rootPos, rootAnchorName !== null && rootAnchorName !== void 0 ? rootAnchorName : anchorName, getNodeTypeWithLevel(rootNode)));
|
|
115
|
+
return false;
|
|
116
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import rafSchedule from 'raf-schd';
|
|
2
2
|
import { getDocument } from '@atlaskit/browser-apis';
|
|
3
3
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
4
|
-
import { BLOCK_CONTROLS_LEFT_SURFACE, BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
|
|
5
4
|
import { getBrowserInfo } from '@atlaskit/editor-common/browser';
|
|
6
5
|
import { getNodeIdProvider } from '@atlaskit/editor-common/node-anchor';
|
|
7
6
|
import { isMeasuring, startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
|
|
@@ -12,7 +11,6 @@ import { EDIT_AREA_ID } from '@atlaskit/editor-common/ui';
|
|
|
12
11
|
import { isEmptyDocument } from '@atlaskit/editor-common/utils';
|
|
13
12
|
import { PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
14
13
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
15
|
-
import { resolveSurface } from '@atlaskit/editor-ui-control-model/surface-renderer';
|
|
16
14
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
17
15
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
18
16
|
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
|
|
@@ -24,19 +22,20 @@ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equ
|
|
|
24
22
|
import { BLOCK_CONTROLS_SURFACE_SELECTOR } from '../ui/consts';
|
|
25
23
|
import { getAnchorAttrName } from '../ui/utils/dom-attr-name';
|
|
26
24
|
import { findNodeDecs, nodeDecorations } from './decorations-anchor';
|
|
25
|
+
import { getNodeTypeWithLevel } from './decorations-common';
|
|
27
26
|
import { createActiveDragHandleNodeDecoration, dragHandleDecoration, emptyParagraphNodeDecorations, findActiveDragHandleNodeDec, findHandleDec, TYPE_ACTIVE_HANDLE_DEC } from './decorations-drag-handle';
|
|
28
27
|
import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-target';
|
|
29
28
|
import { getActiveDropTargetDecorations } from './decorations-drop-target-active';
|
|
30
29
|
import { createActiveQuickInsertNodeDecoration, findActiveQuickInsertNodeDec, findQuickInsertInsertButtonDecoration, quickInsertButtonDecoration, TYPE_ACTIVE_QUICK_INSERT_NODE } from './decorations-quick-insert-button';
|
|
31
30
|
import { handleMouseDown } from './handle-mouse-down';
|
|
32
31
|
import { handleMouseOver } from './handle-mouse-over';
|
|
32
|
+
import { handleSparseMouseOver } from './handle-sparse-mouse-over';
|
|
33
33
|
import { boundKeydownHandler } from './keymap';
|
|
34
34
|
import { defaultActiveAnchorTracker } from './utils/active-anchor-tracker';
|
|
35
35
|
import { getMultiSelectAnalyticsAttributes } from './utils/analytics';
|
|
36
36
|
import { AnchorRectCache, isAnchorSupported } from './utils/anchor-utils';
|
|
37
37
|
import { selectNode } from './utils/getSelection';
|
|
38
38
|
import { getSelectedSlicePosition } from './utils/selection';
|
|
39
|
-
import { getSurfaceNodePositions, updateSurfaceNodePositions } from './utils/surface-node-positions';
|
|
40
39
|
import { getTrMetadata } from './utils/transactions';
|
|
41
40
|
export const key = new PluginKey('blockControls');
|
|
42
41
|
const EDITOR_BLOCKS_DRAG_INIT = 'Editor Blocks Drag Initialization Time';
|
|
@@ -233,16 +232,17 @@ const getDecorationAtPos = (state, decorations, pos, to) => {
|
|
|
233
232
|
const nodeDecAtActivePos = nodeDecsAtActivePos.pop();
|
|
234
233
|
return nodeDecAtActivePos;
|
|
235
234
|
};
|
|
236
|
-
export const apply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, anchorRectCache, resizeObserverWidth, pragmaticCleanup,
|
|
237
|
-
var _meta$multiSelectDnD, _api$editorViewMode, _api$editorViewMode$s, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging2, _meta$
|
|
235
|
+
export const apply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true, anchorRectCache, resizeObserverWidth, pragmaticCleanup, limitedModeTeardown) => {
|
|
236
|
+
var _meta$multiSelectDnD, _api$editorViewMode, _api$editorViewMode$s, _activeNode, _activeNode2, _meta$activeNode$hand, _activeNode3, _activeNode4, _meta$isDragging2, _meta$toggleMenu, _meta$isDragging3, _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;
|
|
238
237
|
let {
|
|
239
238
|
activeNode,
|
|
240
239
|
decorations,
|
|
241
240
|
isResizerResizing,
|
|
242
|
-
multiSelectDnD
|
|
241
|
+
multiSelectDnD
|
|
242
|
+
} = currentState;
|
|
243
|
+
const {
|
|
243
244
|
surfaceNodePositions
|
|
244
245
|
} = currentState;
|
|
245
|
-
const previousActiveNode = activeNode;
|
|
246
246
|
const {
|
|
247
247
|
editorHeight,
|
|
248
248
|
editorWidthLeft,
|
|
@@ -391,13 +391,28 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
391
391
|
if (activeNode.rootPos !== undefined) {
|
|
392
392
|
mappedRootPos = tr.mapping.mapResult(activeNode.rootPos, -1);
|
|
393
393
|
}
|
|
394
|
+
let mappedNodeType = activeNode.nodeType;
|
|
395
|
+
let mappedRootNodeType = activeNode.rootNodeType;
|
|
396
|
+
// Sparse mode does not redraw the old decorations. A block-type transaction may report
|
|
397
|
+
// a text range that excludes the active block position, so always refresh the already
|
|
398
|
+
// active node and root from the new document (for example, paragraph → heading-1).
|
|
399
|
+
if (isExperimentEnabled('platform_editor_block_control_migration')) {
|
|
400
|
+
const mappedNode = newState.doc.nodeAt(mappedPos.pos);
|
|
401
|
+
if (mappedNode !== null && mappedNode !== void 0 && mappedNode.isBlock) {
|
|
402
|
+
mappedNodeType = getNodeTypeWithLevel(mappedNode);
|
|
403
|
+
}
|
|
404
|
+
const mappedRootNode = mappedRootPos ? mappedRootPos.pos === mappedPos.pos && mappedNode ? mappedNode : newState.doc.nodeAt(mappedRootPos.pos) : undefined;
|
|
405
|
+
if (mappedRootNode !== null && mappedRootNode !== void 0 && mappedRootNode.isBlock) {
|
|
406
|
+
mappedRootNodeType = getNodeTypeWithLevel(mappedRootNode);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
394
409
|
activeNode = {
|
|
395
410
|
pos: mappedPos.pos,
|
|
396
411
|
anchorName: activeNode.anchorName,
|
|
397
|
-
nodeType:
|
|
412
|
+
nodeType: mappedNodeType,
|
|
398
413
|
rootPos: (_mappedRootPos$pos = (_mappedRootPos = mappedRootPos) === null || _mappedRootPos === void 0 ? void 0 : _mappedRootPos.pos) !== null && _mappedRootPos$pos !== void 0 ? _mappedRootPos$pos : activeNode.rootPos,
|
|
399
414
|
rootAnchorName: activeNode.rootAnchorName,
|
|
400
|
-
rootNodeType:
|
|
415
|
+
rootNodeType: mappedRootNodeType
|
|
401
416
|
};
|
|
402
417
|
}
|
|
403
418
|
}
|
|
@@ -433,7 +448,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
433
448
|
const isNodeDecsMissing = isDecSetEmpty || maybeNodeCountChanged || editorExperiment('platform_editor_breakout_resizing', true) && hasJustFinishedResizing;
|
|
434
449
|
const shouldRedrawNodeDecs = !isResizerResizing && (isNodeDecsMissing || (meta === null || meta === void 0 ? void 0 : meta.isDragging)) &&
|
|
435
450
|
// Skip expensive anchor node decoration recalculations when native anchor support is enabled
|
|
436
|
-
!expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true);
|
|
451
|
+
!(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration'));
|
|
437
452
|
let isActiveNodeModified = false;
|
|
438
453
|
if (api && shouldRedrawNodeDecs) {
|
|
439
454
|
const oldNodeDecs = findNodeDecs(newState, decorations, from, to);
|
|
@@ -507,14 +522,14 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
507
522
|
// In view mode with right-side controls, remove any lingering drag handle decorations
|
|
508
523
|
// (they may carry over from edit mode). Only remove drag handles specifically, not
|
|
509
524
|
// the remix button decorations (those are managed separately via showInViewMode).
|
|
510
|
-
if (
|
|
525
|
+
if (!isExperimentEnabled('platform_editor_block_control_migration') && isViewMode && rightSideControlsEnabled) {
|
|
511
526
|
const allHandleDecs = findHandleDec(decorations, 0, newState.doc.content.size);
|
|
512
527
|
if (allHandleDecs.length > 0) {
|
|
513
528
|
decorations = decorations.remove(allHandleDecs);
|
|
514
529
|
}
|
|
515
530
|
}
|
|
516
531
|
if (shouldRemoveHandle) {
|
|
517
|
-
if (
|
|
532
|
+
if (!isExperimentEnabled('platform_editor_block_control_migration')) {
|
|
518
533
|
var _activeNode5, _activeNode6;
|
|
519
534
|
const oldHandle = findHandleDec(decorations, (_activeNode5 = activeNode) === null || _activeNode5 === void 0 ? void 0 : _activeNode5.pos, (_activeNode6 = activeNode) === null || _activeNode6 === void 0 ? void 0 : _activeNode6.pos);
|
|
520
535
|
decorations = decorations.remove(oldHandle);
|
|
@@ -526,7 +541,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
526
541
|
// after a doc change (e.g. pressing Enter splits a node), DecorationSet.map() can shift the
|
|
527
542
|
// decoration to a different position, so a point-range search would miss it and leave a stale
|
|
528
543
|
// attribute on the wrong DOM node.
|
|
529
|
-
if ((
|
|
544
|
+
if ((!isExperimentEnabled('platform_editor_block_control_migration') || nodeDecorationRegistry.length > 0) && expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true)) {
|
|
530
545
|
const oldActiveNodeDec = findActiveDragHandleNodeDec(decorations, 0, newState.doc.content.size);
|
|
531
546
|
decorations = decorations.remove(oldActiveNodeDec);
|
|
532
547
|
const oldActiveQuickInsertDec = findActiveQuickInsertNodeDec(decorations, 0, newState.doc.content.size);
|
|
@@ -560,7 +575,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
560
575
|
} else if (api) {
|
|
561
576
|
var _latestActiveNode5, _latestActiveNode10;
|
|
562
577
|
// The registry surface replaces the legacy drag-handle decorations during migration.
|
|
563
|
-
if (
|
|
578
|
+
if (!isExperimentEnabled('platform_editor_block_control_migration') && shouldRecreateHandle && (!rightSideControlsEnabled || !isViewMode)) {
|
|
564
579
|
var _activeNode11, _activeNode12, _latestActiveNode, _latestActiveNode2, _latestActiveNode3, _latestActiveNode4;
|
|
565
580
|
const oldHandle = findHandleDec(decorations, (_activeNode11 = activeNode) === null || _activeNode11 === void 0 ? void 0 : _activeNode11.pos, (_activeNode12 = activeNode) === null || _activeNode12 === void 0 ? void 0 : _activeNode12.pos);
|
|
566
581
|
decorations = decorations.remove(oldHandle);
|
|
@@ -577,7 +592,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
577
592
|
});
|
|
578
593
|
decorations = decorations.add(newState.doc, [handleDec]);
|
|
579
594
|
}
|
|
580
|
-
if ((
|
|
595
|
+
if ((!isExperimentEnabled('platform_editor_block_control_migration') ||
|
|
581
596
|
// nodeDecorationRegistry consumers (e.g. the legacy Remix button) rely
|
|
582
597
|
// on that same anchor-name for their own CSS anchor() positioning, so this must still run
|
|
583
598
|
// when such a consumer exists even if the legacy drag handle itself is disabled.
|
|
@@ -788,7 +803,10 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
788
803
|
}
|
|
789
804
|
}
|
|
790
805
|
const isEmptyDoc = isEmptyDocument(newState.doc);
|
|
791
|
-
if (
|
|
806
|
+
if (isExperimentEnabled('platform_editor_block_control_migration') && (meta === null || meta === void 0 ? void 0 : meta.isDragging) === false) {
|
|
807
|
+
decorations = decorations.remove(findNodeDecs(newState, decorations));
|
|
808
|
+
}
|
|
809
|
+
if (isEmptyDoc && !(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration'))) {
|
|
792
810
|
const hasNodeDecoration = !!findNodeDecs(newState, decorations).length;
|
|
793
811
|
if (!hasNodeDecoration) {
|
|
794
812
|
decorations = decorations.add(newState.doc, [emptyParagraphNodeDecorations()]);
|
|
@@ -801,27 +819,31 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
801
819
|
// remove isEmptyDoc check and let decorations render and determine their own visibility
|
|
802
820
|
// In view mode with right-side controls we render node decorations (right-edge button), not the
|
|
803
821
|
// handle - so findHandleDec is always empty. Don't clear activeNode in that case.
|
|
804
|
-
const hasHandleOrViewModeControls =
|
|
822
|
+
const hasHandleOrViewModeControls = isExperimentEnabled('platform_editor_block_control_migration') || isViewMode && rightSideControlsEnabled || findHandleDec(decorations, (_latestActiveNode11 = latestActiveNode) === null || _latestActiveNode11 === void 0 ? void 0 : _latestActiveNode11.pos, (_latestActiveNode12 = latestActiveNode) === null || _latestActiveNode12 === void 0 ? void 0 : _latestActiveNode12.pos).length > 0;
|
|
805
823
|
// Keep the registry surface mounted while its Block Menu owns focus.
|
|
806
|
-
const keepActiveNodeForOpenBlockMenu =
|
|
824
|
+
const keepActiveNodeForOpenBlockMenu = isExperimentEnabled('platform_editor_block_control_migration') && isMenuOpen;
|
|
807
825
|
newActiveNode = meta !== null && meta !== void 0 && meta.editorBlurred && !keepActiveNodeForOpenBlockMenu || !(meta !== null && meta !== void 0 && meta.activeNode) && !hasHandleOrViewModeControls ? null : latestActiveNode;
|
|
808
826
|
} else {
|
|
809
827
|
var _latestActiveNode13, _latestActiveNode14;
|
|
810
|
-
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) &&
|
|
811
|
-
}
|
|
812
|
-
if (flags.surfaceNodePositionsEnabled && resolvedSurfaces.length > 0) {
|
|
813
|
-
surfaceNodePositions = updateSurfaceNodePositions({
|
|
814
|
-
activeNode: newActiveNode,
|
|
815
|
-
currentPositions: surfaceNodePositions,
|
|
816
|
-
from,
|
|
817
|
-
newState,
|
|
818
|
-
previousActiveNode,
|
|
819
|
-
resolvedSurfaces,
|
|
820
|
-
to,
|
|
821
|
-
tr
|
|
822
|
-
});
|
|
828
|
+
newActiveNode = isEmptyDoc || !(meta !== null && meta !== void 0 && meta.activeNode) && !isExperimentEnabled('platform_editor_block_control_migration') && findHandleDec(decorations, (_latestActiveNode13 = latestActiveNode) === null || _latestActiveNode13 === void 0 ? void 0 : _latestActiveNode13.pos, (_latestActiveNode14 = latestActiveNode) === null || _latestActiveNode14 === void 0 ? void 0 : _latestActiveNode14.pos).length === 0 ? null : latestActiveNode;
|
|
823
829
|
}
|
|
824
830
|
let isMenuOpenNew = isMenuOpen;
|
|
831
|
+
let nextMenuTriggerByNode = (meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu = meta.toggleMenu) === null || _meta$toggleMenu === void 0 ? void 0 : _meta$toggleMenu.triggerByNode) || menuTriggerByNode;
|
|
832
|
+
if (isExperimentEnabled('platform_editor_block_control_migration') && tr.docChanged && menuTriggerByNode && !(meta !== null && meta !== void 0 && meta.toggleMenu)) {
|
|
833
|
+
var _menuTriggerByNode$ro, _newState$doc$nodeAt4;
|
|
834
|
+
const mapped = tr.mapping.mapResult(menuTriggerByNode.pos, 1);
|
|
835
|
+
const mappedRoot = tr.mapping.mapResult((_menuTriggerByNode$ro = menuTriggerByNode.rootPos) !== null && _menuTriggerByNode$ro !== void 0 ? _menuTriggerByNode$ro : menuTriggerByNode.pos, 1);
|
|
836
|
+
if (mapped.deleted || mappedRoot.deleted || !((_newState$doc$nodeAt4 = newState.doc.nodeAt(mapped.pos)) !== null && _newState$doc$nodeAt4 !== void 0 && _newState$doc$nodeAt4.isBlock)) {
|
|
837
|
+
nextMenuTriggerByNode = undefined;
|
|
838
|
+
isMenuOpenNew = false;
|
|
839
|
+
} else {
|
|
840
|
+
nextMenuTriggerByNode = {
|
|
841
|
+
...menuTriggerByNode,
|
|
842
|
+
pos: mapped.pos,
|
|
843
|
+
rootPos: mappedRoot.pos
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
}
|
|
825
847
|
if (meta !== null && meta !== void 0 && meta.closeMenu) {
|
|
826
848
|
isMenuOpenNew = false;
|
|
827
849
|
} else if (meta !== null && meta !== void 0 && meta.toggleMenu) {
|
|
@@ -841,8 +863,8 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
841
863
|
activeDropTargetNode: currentActiveDropTargetNode,
|
|
842
864
|
isDragging: (_meta$isDragging3 = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging3 !== void 0 ? _meta$isDragging3 : isDragging,
|
|
843
865
|
isMenuOpen: isMenuOpenNew,
|
|
844
|
-
menuTriggerBy: (meta === null || meta === void 0 ? void 0 : (_meta$
|
|
845
|
-
menuTriggerByNode:
|
|
866
|
+
menuTriggerBy: (meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu2 = meta.toggleMenu) === null || _meta$toggleMenu2 === void 0 ? void 0 : _meta$toggleMenu2.anchorName) || menuTriggerBy,
|
|
867
|
+
menuTriggerByNode: nextMenuTriggerByNode,
|
|
846
868
|
blockMenuOptions: {
|
|
847
869
|
canMoveUp: (meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu3 = meta.toggleMenu) === null || _meta$toggleMenu3 === void 0 ? void 0 : _meta$toggleMenu3.moveUp) !== undefined ? meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu4 = meta.toggleMenu) === null || _meta$toggleMenu4 === void 0 ? void 0 : _meta$toggleMenu4.moveUp : blockMenuOptions === null || blockMenuOptions === void 0 ? void 0 : blockMenuOptions.canMoveUp,
|
|
848
870
|
canMoveDown: (meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu5 = meta.toggleMenu) === null || _meta$toggleMenu5 === void 0 ? void 0 : _meta$toggleMenu5.moveDown) !== undefined ? meta === null || meta === void 0 ? void 0 : (_meta$toggleMenu6 = meta.toggleMenu) === null || _meta$toggleMenu6 === void 0 ? void 0 : _meta$toggleMenu6.moveDown : blockMenuOptions === null || blockMenuOptions === void 0 ? void 0 : blockMenuOptions.canMoveDown,
|
|
@@ -860,8 +882,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
860
882
|
isSelectedViaDragHandle: isSelectedViaDragHandleNew
|
|
861
883
|
};
|
|
862
884
|
};
|
|
863
|
-
export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true
|
|
864
|
-
var _api$uiControlRegistr, _api$uiControlRegistr2, _api$uiControlRegistr3, _api$uiControlRegistr4;
|
|
885
|
+
export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled = false, quickInsertButtonEnabled = true) => {
|
|
865
886
|
const {
|
|
866
887
|
formatMessage
|
|
867
888
|
} = getIntl();
|
|
@@ -869,15 +890,9 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
869
890
|
exposure: true
|
|
870
891
|
});
|
|
871
892
|
const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
|
|
872
|
-
// Mirrors `registryBlockControlsEnabled` in blockControlsPlugin.tsx: `legacyDragHandleEnabled` is
|
|
873
|
-
// only false once that gate is on.
|
|
874
|
-
const surfaceNodePositionsEnabled = !legacyDragHandleEnabled;
|
|
875
893
|
const flags = {
|
|
876
|
-
legacyDragHandleEnabled,
|
|
877
|
-
surfaceNodePositionsEnabled,
|
|
878
894
|
toolbarFlagsEnabled
|
|
879
895
|
};
|
|
880
|
-
const resolvedSurfaces = surfaceNodePositionsEnabled ? [resolveSurface((_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(BLOCK_CONTROLS_LEFT_SURFACE)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [], BLOCK_CONTROLS_LEFT_SURFACE), resolveSurface((_api$uiControlRegistr3 = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr4 = api.uiControlRegistry) === null || _api$uiControlRegistr4 === void 0 ? void 0 : _api$uiControlRegistr4.actions.getComponents(BLOCK_CONTROLS_RIGHT_SURFACE)) !== null && _api$uiControlRegistr3 !== void 0 ? _api$uiControlRegistr3 : [], BLOCK_CONTROLS_RIGHT_SURFACE)] : [];
|
|
881
896
|
let anchorRectCache;
|
|
882
897
|
if (!isAnchorSupported()) {
|
|
883
898
|
anchorRectCache = new AnchorRectCache();
|
|
@@ -891,13 +906,10 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
891
906
|
return new SafePlugin({
|
|
892
907
|
key,
|
|
893
908
|
state: {
|
|
894
|
-
init(
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
};
|
|
899
|
-
},
|
|
900
|
-
apply: (tr, currentState, _, newState) => apply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled, anchorRectCache, resizeObserverWidth, pragmaticCleanup, resolvedSurfaces, limitedModeTeardown)
|
|
909
|
+
init: () => ({
|
|
910
|
+
...initialState
|
|
911
|
+
}),
|
|
912
|
+
apply: (tr, currentState, _, newState) => apply(api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled, anchorRectCache, resizeObserverWidth, pragmaticCleanup, limitedModeTeardown)
|
|
901
913
|
},
|
|
902
914
|
props: {
|
|
903
915
|
decorations: state => {
|
|
@@ -917,7 +929,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
917
929
|
let decorationSet = (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
|
|
918
930
|
// In view mode with right-side controls, remove any lingering drag-handle decorations
|
|
919
931
|
// (created in edit mode) that may not have been cleaned up on mode switch.
|
|
920
|
-
if (decorationSet &&
|
|
932
|
+
if (decorationSet && !isExperimentEnabled('platform_editor_block_control_migration') && rightSideControlsEnabled && (api === null || api === void 0 ? void 0 : (_api$editorViewMode3 = api.editorViewMode) === null || _api$editorViewMode3 === void 0 ? void 0 : (_api$editorViewMode3$ = _api$editorViewMode3.sharedState.currentState()) === null || _api$editorViewMode3$ === void 0 ? void 0 : _api$editorViewMode3$.mode) === 'view') {
|
|
921
933
|
const handleDecs = findHandleDec(decorationSet, 0, state.doc.content.size);
|
|
922
934
|
if (handleDecs.length > 0) {
|
|
923
935
|
decorationSet = decorationSet.remove(handleDecs);
|
|
@@ -1070,10 +1082,14 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
1070
1082
|
// another layer of protection to prevent handling mouseover
|
|
1071
1083
|
// when native anchor with dnd is enabled in limited mode
|
|
1072
1084
|
// in case there are descripancies between getNodeIdProvider limited mode state
|
|
1073
|
-
if ((_getNodeIdProvider = getNodeIdProvider(view)) !== null && _getNodeIdProvider !== void 0 && _getNodeIdProvider.isLimitedMode() && expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
|
|
1085
|
+
if ((_getNodeIdProvider = getNodeIdProvider(view)) !== null && _getNodeIdProvider !== void 0 && _getNodeIdProvider.isLimitedMode() && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration'))) {
|
|
1074
1086
|
return;
|
|
1075
1087
|
}
|
|
1076
|
-
|
|
1088
|
+
if (isExperimentEnabled('platform_editor_block_control_migration')) {
|
|
1089
|
+
handleSparseMouseOver(view, event, api);
|
|
1090
|
+
} else {
|
|
1091
|
+
handleMouseOver(view, event, api);
|
|
1092
|
+
}
|
|
1077
1093
|
return false;
|
|
1078
1094
|
},
|
|
1079
1095
|
mousedown: (view, event) => {
|
|
@@ -1136,7 +1152,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
1136
1152
|
if (editorExperiment('platform_editor_controls', 'variant1')) {
|
|
1137
1153
|
var _api$core2;
|
|
1138
1154
|
// Focus moving into the registry surface remains inside the editor experience.
|
|
1139
|
-
const isChildOfSurface =
|
|
1155
|
+
const isChildOfSurface = isExperimentEnabled('platform_editor_block_control_migration') && event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest(BLOCK_CONTROLS_SURFACE_SELECTOR) !== null;
|
|
1140
1156
|
const shouldPreserveRemixInlineDropdownFocus = event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest('[data-editor-remix-inline-dropdown-preserve-focus]') !== null;
|
|
1141
1157
|
const isChildOfEditor = event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest(`#${EDIT_AREA_ID}`) !== null;
|
|
1142
1158
|
|
|
@@ -1178,7 +1194,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
1178
1194
|
|
|
1179
1195
|
// Registry surfaces have their own ResizeObservers and absolute placement.
|
|
1180
1196
|
// Width metadata only drives legacy widget recreation.
|
|
1181
|
-
if (
|
|
1197
|
+
if (!isExperimentEnabled('platform_editor_block_control_migration') && !isResizerResizing) {
|
|
1182
1198
|
const editorContentArea = entries[0].target;
|
|
1183
1199
|
// Ignored via go/ees005
|
|
1184
1200
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -1198,7 +1214,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
1198
1214
|
}
|
|
1199
1215
|
}
|
|
1200
1216
|
}));
|
|
1201
|
-
const shouldObserve = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)
|
|
1217
|
+
const shouldObserve = !(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) || !isAnchorSupported();
|
|
1202
1218
|
if (editorContentArea && shouldObserve) {
|
|
1203
1219
|
resizeObserverWidth.observe(editorContentArea);
|
|
1204
1220
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BLOCK_CONTROLS_SURFACE_INVALIDATION } from '@atlaskit/editor-common/block-controls/surface-candidate-invalidation';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
import { key as blockControlsKey } from './main';
|
|
6
|
+
import { emptySparseSurfaceCandidateState } from './utils/sparse-surface-candidates';
|
|
7
|
+
import { applySparseSurfacesTransaction, createInitialSparseSurfacesState } from './utils/sparse-surfaces-state';
|
|
8
|
+
import { createSparseSurfacesView } from './utils/sparse-surfaces-view';
|
|
9
|
+
export const sparseSurfacesKey = new PluginKey('blockControlsSparseSurfaces');
|
|
10
|
+
|
|
11
|
+
/** Owns sparse anchors independently of drag/drop decorations and their lifecycle. */
|
|
12
|
+
export const createSparseSurfacesPlugin = api => new SafePlugin({
|
|
13
|
+
key: sparseSurfacesKey,
|
|
14
|
+
state: {
|
|
15
|
+
init: () => createInitialSparseSurfacesState(emptySparseSurfaceCandidateState),
|
|
16
|
+
apply(tr, previous, _oldState, newState) {
|
|
17
|
+
return applySparseSurfacesTransaction({
|
|
18
|
+
invalidation: tr.getMeta(BLOCK_CONTROLS_SURFACE_INVALIDATION),
|
|
19
|
+
meta: tr.getMeta(sparseSurfacesKey),
|
|
20
|
+
newState,
|
|
21
|
+
previous,
|
|
22
|
+
tr
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
props: {
|
|
27
|
+
decorations(state) {
|
|
28
|
+
var _api$limitedMode, _api$limitedMode$shar, _blockControlsKey$get, _sparseSurfacesKey$ge;
|
|
29
|
+
return api !== null && api !== void 0 && (_api$limitedMode = api.limitedMode) !== null && _api$limitedMode !== void 0 && (_api$limitedMode$shar = _api$limitedMode.sharedState.currentState()) !== null && _api$limitedMode$shar !== void 0 && _api$limitedMode$shar.enabled || (_blockControlsKey$get = blockControlsKey.getState(state)) !== null && _blockControlsKey$get !== void 0 && _blockControlsKey$get.isDragging ? DecorationSet.empty : (_sparseSurfacesKey$ge = sparseSurfacesKey.getState(state)) === null || _sparseSurfacesKey$ge === void 0 ? void 0 : _sparseSurfacesKey$ge.decorations;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
view: view => createSparseSurfacesView({
|
|
33
|
+
api,
|
|
34
|
+
pluginKey: sparseSurfacesKey,
|
|
35
|
+
view
|
|
36
|
+
})
|
|
37
|
+
});
|