@atlaskit/editor-plugin-block-controls 20.1.2 → 20.1.4
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 +18 -0
- package/dist/cjs/pm-plugins/selection-preservation/pm-plugin.js +17 -34
- package/dist/cjs/ui/block-controls-left-surface.compiled.css +7 -1
- package/dist/cjs/ui/block-controls-left-surface.js +41 -27
- package/dist/cjs/ui/block-controls-left-surfaces.js +32 -12
- package/dist/cjs/ui/block-controls-right-surface.js +32 -24
- package/dist/cjs/ui/block-controls-right-surfaces.js +6 -4
- package/dist/cjs/ui/block-controls-surface-components.js +142 -0
- package/dist/cjs/ui/utils/get-surface-placement.js +63 -16
- package/dist/cjs/ui/visibility-container.js +42 -7
- package/dist/es2019/pm-plugins/selection-preservation/pm-plugin.js +17 -34
- package/dist/es2019/ui/block-controls-left-surface.compiled.css +7 -1
- package/dist/es2019/ui/block-controls-left-surface.js +44 -29
- package/dist/es2019/ui/block-controls-left-surfaces.js +41 -16
- package/dist/es2019/ui/block-controls-right-surface.js +35 -26
- package/dist/es2019/ui/block-controls-right-surfaces.js +6 -4
- package/dist/es2019/ui/block-controls-surface-components.js +129 -0
- package/dist/es2019/ui/utils/get-surface-placement.js +59 -7
- package/dist/es2019/ui/visibility-container.js +44 -6
- package/dist/esm/pm-plugins/selection-preservation/pm-plugin.js +17 -34
- package/dist/esm/ui/block-controls-left-surface.compiled.css +7 -1
- package/dist/esm/ui/block-controls-left-surface.js +43 -29
- package/dist/esm/ui/block-controls-left-surfaces.js +33 -13
- package/dist/esm/ui/block-controls-right-surface.js +34 -26
- package/dist/esm/ui/block-controls-right-surfaces.js +6 -4
- package/dist/esm/ui/block-controls-surface-components.js +133 -0
- package/dist/esm/ui/utils/get-surface-placement.js +62 -15
- package/dist/esm/ui/visibility-container.js +41 -6
- package/dist/types/ui/block-controls-surface-components.d.ts +13 -0
- package/dist/types/ui/utils/get-surface-placement.d.ts +13 -0
- package/dist/types/ui/visibility-container.d.ts +14 -0
- package/package.json +3 -3
|
@@ -8,14 +8,13 @@ import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-contr
|
|
|
8
8
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
9
9
|
import { isCSSAnchorSupported } from '@atlaskit/editor-common/styles';
|
|
10
10
|
import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
|
|
11
|
-
import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
|
|
12
11
|
import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
|
|
13
12
|
import { BlockControlsLeftSurface } from './block-controls-left-surface';
|
|
13
|
+
import { getBlockControlsLeftSurfaceComponents } from './block-controls-surface-components';
|
|
14
14
|
import { createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
|
|
15
15
|
import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
|
|
16
16
|
import { getNodeContentElement } from './utils/get-node-content-element';
|
|
17
|
-
import { getAbsoluteSurfacePlacement, getAnchoredSurfacePlacement, getSurfacePlacement, toMeasuredSurfaceWrapperPlacement } from './utils/get-surface-placement';
|
|
18
|
-
import { hasSurfaceControls } from './utils/has-surface-controls';
|
|
17
|
+
import { getAbsoluteSurfacePlacement, getAnchoredLeftGutterSurfacePlacement, getAnchoredSurfacePlacement, getLeftGutterSurfacePlacement, getSurfacePlacement, toMeasuredSurfaceWrapperPlacement } from './utils/get-surface-placement';
|
|
19
18
|
const EMPTY_SURFACE_POSITIONS = [];
|
|
20
19
|
const EMPTY_SURFACE_ANCHORS = new Map();
|
|
21
20
|
const EMPTY_SURFACE_COMPONENTS = [];
|
|
@@ -53,15 +52,21 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
53
52
|
return [];
|
|
54
53
|
}
|
|
55
54
|
const surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
|
|
56
|
-
|
|
55
|
+
const surfaceComponents = getBlockControlsLeftSurfaceComponents(components, surfaceContext);
|
|
56
|
+
if (!surfaceComponents) {
|
|
57
57
|
return [];
|
|
58
58
|
}
|
|
59
59
|
// The cache supplies the same anchor names used by ProseMirror decorations.
|
|
60
60
|
const anchorName = isCSSAnchorSupported() ? surfaceAnchors.get(target.position) : undefined;
|
|
61
|
+
// Top-level controls can respond to the available left gutter without the surface
|
|
62
|
+
// host knowing which controls are registered or how they adapt.
|
|
63
|
+
const isTopLevel = context.targetNode.parentType === 'doc';
|
|
61
64
|
return [{
|
|
62
65
|
...target,
|
|
63
66
|
anchorName,
|
|
64
67
|
blockControlsContext: context,
|
|
68
|
+
isTopLevel,
|
|
69
|
+
surfaceComponents,
|
|
65
70
|
surfaceContext
|
|
66
71
|
}];
|
|
67
72
|
}), [activeNode, components, editorView, targets, surfaceAnchors, surfaceActiveNodes]);
|
|
@@ -72,15 +77,25 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
72
77
|
const anchoredPlacements = useMemo(() => new Map(surfaces.flatMap(({
|
|
73
78
|
anchorName,
|
|
74
79
|
blockControlsContext,
|
|
80
|
+
isTopLevel,
|
|
75
81
|
position
|
|
76
|
-
}) =>
|
|
77
|
-
anchorName
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
}) => {
|
|
83
|
+
if (!anchorName) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const options = {
|
|
87
|
+
anchorName,
|
|
88
|
+
layout: blockControlsContext.targetNode.node.attrs.layout,
|
|
89
|
+
nodeType: blockControlsContext.targetNode.type.name,
|
|
90
|
+
nodeTypeWithLevel: getNodeTypeWithLevel(blockControlsContext.targetNode.node),
|
|
91
|
+
parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType
|
|
92
|
+
};
|
|
93
|
+
const placement = isTopLevel ? getAnchoredLeftGutterSurfacePlacement(options) : getAnchoredSurfacePlacement({
|
|
94
|
+
...options,
|
|
95
|
+
side: 'left'
|
|
96
|
+
});
|
|
97
|
+
return [[position, placement]];
|
|
98
|
+
})), [surfaces]);
|
|
84
99
|
// Only the surfaces that still need measuring drive the effect below, so a document of anchored
|
|
85
100
|
// blocks binds no scroll or resize listeners at all.
|
|
86
101
|
//
|
|
@@ -106,6 +121,7 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
106
121
|
}
|
|
107
122
|
const measurementTargets = measuredSurfaces.flatMap(({
|
|
108
123
|
blockControlsContext,
|
|
124
|
+
isTopLevel,
|
|
109
125
|
position
|
|
110
126
|
}) => {
|
|
111
127
|
const targetNodeElement = editorView.nodeDOM(blockControlsContext.targetNode.pos);
|
|
@@ -115,6 +131,7 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
115
131
|
}
|
|
116
132
|
return [{
|
|
117
133
|
blockControlsContext,
|
|
134
|
+
isTopLevel,
|
|
118
135
|
position,
|
|
119
136
|
targetElement: getNodeContentElement(targetElementRoot, blockControlsContext.targetNode.type.name),
|
|
120
137
|
targetElementRoot
|
|
@@ -132,20 +149,27 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
132
149
|
const nextPlacements = new Map();
|
|
133
150
|
for (const {
|
|
134
151
|
blockControlsContext,
|
|
152
|
+
isTopLevel,
|
|
135
153
|
position,
|
|
136
154
|
targetElement,
|
|
137
155
|
targetElementRoot
|
|
138
156
|
} of measurementTargets) {
|
|
139
|
-
var _targetElementRoot$ge;
|
|
157
|
+
var _targetElementRoot$ge, _offsetParentRect$lef;
|
|
140
158
|
if (!targetElementRoot.isConnected || !targetElement.isConnected) {
|
|
141
159
|
continue;
|
|
142
160
|
}
|
|
143
|
-
const
|
|
161
|
+
const options = {
|
|
144
162
|
layout: (_targetElementRoot$ge = targetElementRoot.getAttribute('layout')) !== null && _targetElementRoot$ge !== void 0 ? _targetElementRoot$ge : '',
|
|
145
163
|
nodeRect: targetElement.getBoundingClientRect(),
|
|
146
164
|
nodeType: blockControlsContext.targetNode.type.name,
|
|
147
165
|
nodeTypeWithLevel: getNodeTypeWithLevel(blockControlsContext.targetNode.node),
|
|
148
|
-
parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType
|
|
166
|
+
parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType
|
|
167
|
+
};
|
|
168
|
+
const placement = isTopLevel ? getLeftGutterSurfacePlacement({
|
|
169
|
+
...options,
|
|
170
|
+
leftGutterBoundary: (_offsetParentRect$lef = offsetParentRect === null || offsetParentRect === void 0 ? void 0 : offsetParentRect.left) !== null && _offsetParentRect$lef !== void 0 ? _offsetParentRect$lef : 0
|
|
171
|
+
}) : getSurfacePlacement({
|
|
172
|
+
...options,
|
|
149
173
|
side: 'left'
|
|
150
174
|
});
|
|
151
175
|
nextPlacements.set(position, toMeasuredSurfaceWrapperPlacement(getAbsoluteSurfacePlacement({
|
|
@@ -218,12 +242,13 @@ export const BlockControlsLeftSurfaces = ({
|
|
|
218
242
|
return /*#__PURE__*/React.createElement(React.Fragment, null, surfaces.map(({
|
|
219
243
|
position,
|
|
220
244
|
source,
|
|
245
|
+
surfaceComponents,
|
|
221
246
|
surfaceContext
|
|
222
247
|
}) => {
|
|
223
248
|
var _activeNode$handleOpt, _anchoredPlacements$g;
|
|
224
249
|
return /*#__PURE__*/React.createElement(BlockControlsLeftSurface, {
|
|
225
250
|
api: api,
|
|
226
|
-
components:
|
|
251
|
+
components: surfaceComponents,
|
|
227
252
|
forceVisibleOnMouseOut: Boolean(activeNode === null || activeNode === void 0 ? void 0 : (_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused),
|
|
228
253
|
key: position,
|
|
229
254
|
placement: (_anchoredPlacements$g = anchoredPlacements.get(position)) !== null && _anchoredPlacements$g !== void 0 ? _anchoredPlacements$g : placements.get(position),
|
|
@@ -3,9 +3,9 @@ import "./block-controls-right-surface.compiled.css";
|
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
|
|
6
|
-
import { SurfaceRenderer
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model/surface-renderer';
|
|
7
|
+
import { BlockControlsVisibilityProvider } from './block-controls-surface-components';
|
|
8
|
+
import { useBlockControlsVisibility } from './visibility-container';
|
|
9
9
|
const rightSurfaceOuterStyles = null;
|
|
10
10
|
const rightSurfaceRowStyles = null;
|
|
11
11
|
|
|
@@ -14,8 +14,7 @@ const rightSurfaceRowStyles = null;
|
|
|
14
14
|
// can stick near the top of the viewport instead of scrolling off with the node's top edge.
|
|
15
15
|
// Keep in sync with STICKY_CONTROLS_TOP_MARGIN in ./consts (must be a static literal here).
|
|
16
16
|
const rightSurfaceStickyStyles = null;
|
|
17
|
-
|
|
18
|
-
export const BlockControlsRightSurface = ({
|
|
17
|
+
const BlockControlsRightSurfaceContent = ({
|
|
19
18
|
api,
|
|
20
19
|
components,
|
|
21
20
|
forceVisibleOnMouseOut,
|
|
@@ -23,15 +22,14 @@ export const BlockControlsRightSurface = ({
|
|
|
23
22
|
source,
|
|
24
23
|
surfaceContext
|
|
25
24
|
}) => {
|
|
26
|
-
if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
25
|
const {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} =
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
shouldHide: shouldHideHoverControls,
|
|
27
|
+
useCssStyles
|
|
28
|
+
} = useBlockControlsVisibility({
|
|
29
|
+
api,
|
|
30
|
+
controlSide: 'right',
|
|
31
|
+
forceVisibleOnMouseOut
|
|
32
|
+
});
|
|
35
33
|
const isSticky = placement.isSticky;
|
|
36
34
|
return /*#__PURE__*/React.createElement("div", {
|
|
37
35
|
"data-editor-block-controls-surface": true,
|
|
@@ -43,23 +41,34 @@ export const BlockControlsRightSurface = ({
|
|
|
43
41
|
className: ax(["_kqswstnw _17c61i8t _1pbyb4wl"])
|
|
44
42
|
}, /*#__PURE__*/React.createElement("div", {
|
|
45
43
|
className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
isPersistent: true,
|
|
50
|
-
shouldUseDisplayContents: true
|
|
44
|
+
}, /*#__PURE__*/React.createElement(BlockControlsVisibilityProvider, {
|
|
45
|
+
shouldHideHoverControls: shouldHideHoverControls,
|
|
46
|
+
useCssStyles: useCssStyles
|
|
51
47
|
}, /*#__PURE__*/React.createElement(SurfaceRenderer, {
|
|
52
|
-
components:
|
|
48
|
+
components: components,
|
|
53
49
|
surface: BLOCK_CONTROLS_RIGHT_SURFACE,
|
|
54
50
|
surfaceContext: surfaceContext
|
|
55
|
-
}))
|
|
51
|
+
}))));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/** Renders one right block-controls surface at a document position. */
|
|
55
|
+
export const BlockControlsRightSurface = ({
|
|
56
|
+
api,
|
|
57
|
+
components,
|
|
58
|
+
forceVisibleOnMouseOut,
|
|
59
|
+
placement,
|
|
60
|
+
source,
|
|
61
|
+
surfaceContext
|
|
62
|
+
}) => {
|
|
63
|
+
if (!placement) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return /*#__PURE__*/React.createElement(BlockControlsRightSurfaceContent, {
|
|
56
67
|
api: api,
|
|
57
|
-
|
|
68
|
+
components: components,
|
|
58
69
|
forceVisibleOnMouseOut: forceVisibleOnMouseOut,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
components: hoverOnlyComponents,
|
|
62
|
-
surface: BLOCK_CONTROLS_RIGHT_SURFACE,
|
|
70
|
+
placement: placement,
|
|
71
|
+
source: source,
|
|
63
72
|
surfaceContext: surfaceContext
|
|
64
|
-
})
|
|
73
|
+
});
|
|
65
74
|
};
|
|
@@ -8,14 +8,13 @@ import { BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-cont
|
|
|
8
8
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
9
9
|
import { isCSSAnchorSupported } from '@atlaskit/editor-common/styles';
|
|
10
10
|
import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
|
|
11
|
-
import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
|
|
12
11
|
import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
|
|
13
12
|
import { BlockControlsRightSurface } from './block-controls-right-surface';
|
|
13
|
+
import { getBlockControlsRightSurfaceComponents } from './block-controls-surface-components';
|
|
14
14
|
import { createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
|
|
15
15
|
import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
|
|
16
16
|
import { getNodeContentElement } from './utils/get-node-content-element';
|
|
17
17
|
import { getAbsoluteSurfacePlacement, getAnchoredSurfacePlacement, getSurfacePlacement, toMeasuredSurfaceWrapperPlacement } from './utils/get-surface-placement';
|
|
18
|
-
import { hasSurfaceControls } from './utils/has-surface-controls';
|
|
19
18
|
const EMPTY_SURFACE_POSITIONS = [];
|
|
20
19
|
const EMPTY_SURFACE_ANCHORS = new Map();
|
|
21
20
|
const EMPTY_SURFACE_COMPONENTS = [];
|
|
@@ -62,7 +61,8 @@ export const BlockControlsRightSurfaces = ({
|
|
|
62
61
|
return [];
|
|
63
62
|
}
|
|
64
63
|
const surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
|
|
65
|
-
|
|
64
|
+
const surfaceComponents = getBlockControlsRightSurfaceComponents(components, surfaceContext);
|
|
65
|
+
if (!surfaceComponents) {
|
|
66
66
|
return [];
|
|
67
67
|
}
|
|
68
68
|
// The cache supplies the same anchor names used by ProseMirror decorations.
|
|
@@ -71,6 +71,7 @@ export const BlockControlsRightSurfaces = ({
|
|
|
71
71
|
...target,
|
|
72
72
|
anchorName,
|
|
73
73
|
blockControlsContext: context,
|
|
74
|
+
surfaceComponents,
|
|
74
75
|
surfaceContext
|
|
75
76
|
}];
|
|
76
77
|
}), [activeNode, components, editorView, targets, surfaceAnchors, surfaceActiveNodes]);
|
|
@@ -227,12 +228,13 @@ export const BlockControlsRightSurfaces = ({
|
|
|
227
228
|
return /*#__PURE__*/React.createElement(React.Fragment, null, surfaces.map(({
|
|
228
229
|
position,
|
|
229
230
|
source,
|
|
231
|
+
surfaceComponents,
|
|
230
232
|
surfaceContext
|
|
231
233
|
}) => {
|
|
232
234
|
var _activeNode$handleOpt, _anchoredPlacements$g;
|
|
233
235
|
return /*#__PURE__*/React.createElement(BlockControlsRightSurface, {
|
|
234
236
|
api: api,
|
|
235
|
-
components:
|
|
237
|
+
components: surfaceComponents,
|
|
236
238
|
forceVisibleOnMouseOut: Boolean(activeNode === null || activeNode === void 0 ? void 0 : (_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused),
|
|
237
239
|
key: position,
|
|
238
240
|
placement: (_anchoredPlacements$g = anchoredPlacements.get(position)) !== null && _anchoredPlacements$g !== void 0 ? _anchoredPlacements$g : placements.get(position),
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
2
|
+
import { BLOCK_CONTROLS_LEFT_GROUP, BLOCK_CONTROLS_LEFT_SECTION, BLOCK_CONTROLS_LEFT_SURFACE, BLOCK_CONTROLS_RIGHT_GROUP, BLOCK_CONTROLS_RIGHT_SECTION, BLOCK_CONTROLS_RIGHT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
|
|
3
|
+
import { getComponentIdentity, resolveSurface } from '@atlaskit/editor-ui-control-model/surface-renderer';
|
|
4
|
+
import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
|
|
5
|
+
import { VisibilityWrapper } from './visibility-container';
|
|
6
|
+
const BlockControlsVisibilityContext = /*#__PURE__*/createContext({
|
|
7
|
+
shouldHideHoverControls: false,
|
|
8
|
+
useCssStyles: false
|
|
9
|
+
});
|
|
10
|
+
const BlockControlItem = ({
|
|
11
|
+
children
|
|
12
|
+
}) => /*#__PURE__*/React.createElement("div", {
|
|
13
|
+
"data-editor-block-control-item": true
|
|
14
|
+
}, children);
|
|
15
|
+
const HoverBlockControlItem = ({
|
|
16
|
+
children
|
|
17
|
+
}) => {
|
|
18
|
+
const {
|
|
19
|
+
shouldHideHoverControls,
|
|
20
|
+
useCssStyles
|
|
21
|
+
} = useContext(BlockControlsVisibilityContext);
|
|
22
|
+
return /*#__PURE__*/React.createElement(BlockControlItem, null, /*#__PURE__*/React.createElement(VisibilityWrapper, {
|
|
23
|
+
shouldHide: shouldHideHoverControls,
|
|
24
|
+
useCssStyles: useCssStyles
|
|
25
|
+
}, children));
|
|
26
|
+
};
|
|
27
|
+
const PersistentBlockControlItem = ({
|
|
28
|
+
children
|
|
29
|
+
}) => {
|
|
30
|
+
const {
|
|
31
|
+
useCssStyles
|
|
32
|
+
} = useContext(BlockControlsVisibilityContext);
|
|
33
|
+
return /*#__PURE__*/React.createElement(BlockControlItem, null, /*#__PURE__*/React.createElement(VisibilityWrapper, {
|
|
34
|
+
shouldHide: false,
|
|
35
|
+
useCssStyles: useCssStyles
|
|
36
|
+
}, children));
|
|
37
|
+
};
|
|
38
|
+
export const BlockControlsVisibilityProvider = ({
|
|
39
|
+
children,
|
|
40
|
+
shouldHideHoverControls,
|
|
41
|
+
useCssStyles
|
|
42
|
+
}) => {
|
|
43
|
+
const value = useMemo(() => ({
|
|
44
|
+
shouldHideHoverControls,
|
|
45
|
+
useCssStyles
|
|
46
|
+
}), [shouldHideHoverControls, useCssStyles]);
|
|
47
|
+
return /*#__PURE__*/React.createElement(BlockControlsVisibilityContext.Provider, {
|
|
48
|
+
value: value
|
|
49
|
+
}, children);
|
|
50
|
+
};
|
|
51
|
+
const withoutVisibilityPredicate = component => {
|
|
52
|
+
const {
|
|
53
|
+
isHidden: _isHidden,
|
|
54
|
+
...visibleComponent
|
|
55
|
+
} = component;
|
|
56
|
+
return visibleComponent;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Replaces the shared surface group with one stable wrapper group per visible control. The wrappers
|
|
61
|
+
* inherit each control's rank, so SurfaceRenderer keeps the registry order without re-evaluating
|
|
62
|
+
* the controls' visibility predicates.
|
|
63
|
+
*/
|
|
64
|
+
const getBlockControlsSurfaceComponents = (components, {
|
|
65
|
+
group,
|
|
66
|
+
section,
|
|
67
|
+
surface
|
|
68
|
+
}, surfaceContext) => {
|
|
69
|
+
var _resolvedSurface$chil;
|
|
70
|
+
const resolvedSurface = resolveSurface(components, surface);
|
|
71
|
+
const groupIdentity = getComponentIdentity(group);
|
|
72
|
+
const controls = (_resolvedSurface$chil = resolvedSurface.childrenMap.get(groupIdentity)) !== null && _resolvedSurface$chil !== void 0 ? _resolvedSurface$chil : [];
|
|
73
|
+
const visibleControls = controls.filter(control => {
|
|
74
|
+
var _control$isHidden, _control$isHidden2;
|
|
75
|
+
return !((_control$isHidden = (_control$isHidden2 = control.isHidden) === null || _control$isHidden2 === void 0 ? void 0 : _control$isHidden2.call(control, {
|
|
76
|
+
surfaceContext
|
|
77
|
+
})) !== null && _control$isHidden !== void 0 ? _control$isHidden : false);
|
|
78
|
+
});
|
|
79
|
+
if (!resolvedSurface.root || visibleControls.length === 0) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const controlIdentities = new Set(controls.map(getComponentIdentity));
|
|
83
|
+
const visibleControlIdentities = new Set(visibleControls.map(getComponentIdentity));
|
|
84
|
+
const {
|
|
85
|
+
persistentComponents
|
|
86
|
+
} = partitionComponentsByPersistence(resolvedSurface.components.filter(component => {
|
|
87
|
+
const identity = getComponentIdentity(component);
|
|
88
|
+
return !controlIdentities.has(identity) || visibleControlIdentities.has(identity);
|
|
89
|
+
}), surface, surfaceContext);
|
|
90
|
+
const persistentIdentities = new Set(persistentComponents.map(getComponentIdentity));
|
|
91
|
+
const structuralComponents = resolvedSurface.components.filter(component => {
|
|
92
|
+
const identity = getComponentIdentity(component);
|
|
93
|
+
return identity !== groupIdentity && !controlIdentities.has(identity);
|
|
94
|
+
}).map(withoutVisibilityPredicate);
|
|
95
|
+
const wrappedControls = visibleControls.flatMap(control => {
|
|
96
|
+
var _control$parents$find, _control$parents, _control$parents$find2;
|
|
97
|
+
const identity = getComponentIdentity(control);
|
|
98
|
+
const rank = (_control$parents$find = (_control$parents = control.parents) === null || _control$parents === void 0 ? void 0 : (_control$parents$find2 = _control$parents.find(parent => getComponentIdentity(parent) === groupIdentity)) === null || _control$parents$find2 === void 0 ? void 0 : _control$parents$find2.rank) !== null && _control$parents$find !== void 0 ? _control$parents$find : 0;
|
|
99
|
+
const wrapper = {
|
|
100
|
+
component: persistentIdentities.has(identity) ? PersistentBlockControlItem : HoverBlockControlItem,
|
|
101
|
+
key: `block-control-item:${identity}`,
|
|
102
|
+
parents: [{
|
|
103
|
+
...section,
|
|
104
|
+
rank
|
|
105
|
+
}],
|
|
106
|
+
type: 'group'
|
|
107
|
+
};
|
|
108
|
+
const visibleControl = {
|
|
109
|
+
...withoutVisibilityPredicate(control),
|
|
110
|
+
parents: [{
|
|
111
|
+
key: wrapper.key,
|
|
112
|
+
rank: 0,
|
|
113
|
+
type: wrapper.type
|
|
114
|
+
}]
|
|
115
|
+
};
|
|
116
|
+
return [wrapper, visibleControl];
|
|
117
|
+
});
|
|
118
|
+
return [...structuralComponents, ...wrappedControls];
|
|
119
|
+
};
|
|
120
|
+
export const getBlockControlsLeftSurfaceComponents = (components, surfaceContext) => getBlockControlsSurfaceComponents(components, {
|
|
121
|
+
group: BLOCK_CONTROLS_LEFT_GROUP,
|
|
122
|
+
section: BLOCK_CONTROLS_LEFT_SECTION,
|
|
123
|
+
surface: BLOCK_CONTROLS_LEFT_SURFACE
|
|
124
|
+
}, surfaceContext);
|
|
125
|
+
export const getBlockControlsRightSurfaceComponents = (components, surfaceContext) => getBlockControlsSurfaceComponents(components, {
|
|
126
|
+
group: BLOCK_CONTROLS_RIGHT_GROUP,
|
|
127
|
+
section: BLOCK_CONTROLS_RIGHT_SECTION,
|
|
128
|
+
surface: BLOCK_CONTROLS_RIGHT_SURFACE
|
|
129
|
+
}, surfaceContext);
|
|
@@ -43,18 +43,43 @@ export const getSurfacePlacement = ({
|
|
|
43
43
|
const gap = dragHandleGap(nodeType, parentNodeType);
|
|
44
44
|
const top = nodeRect.top + topPositionAdjustment(nodeTypeWithLevel, layout);
|
|
45
45
|
const height = shouldBeSticky(nodeType) ? nodeRect.height : undefined;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
if (side === 'right') {
|
|
47
|
+
return {
|
|
48
|
+
left: nodeRect.right + gap,
|
|
49
|
+
top,
|
|
50
|
+
transform: '',
|
|
51
|
+
height
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
52
55
|
left: nodeRect.left,
|
|
53
56
|
top,
|
|
54
57
|
transform: `translateX(calc(-100% - ${gap}px))`,
|
|
55
58
|
height
|
|
56
59
|
};
|
|
57
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Expands a measured left surface from the available gutter boundary to the target node.
|
|
63
|
+
*/
|
|
64
|
+
export const getLeftGutterSurfacePlacement = ({
|
|
65
|
+
leftGutterBoundary,
|
|
66
|
+
...options
|
|
67
|
+
}) => {
|
|
68
|
+
const placement = getSurfacePlacement({
|
|
69
|
+
...options,
|
|
70
|
+
side: 'left'
|
|
71
|
+
});
|
|
72
|
+
if (options.nodeType === 'layoutColumn') {
|
|
73
|
+
return placement;
|
|
74
|
+
}
|
|
75
|
+
const gap = dragHandleGap(options.nodeType, options.parentNodeType);
|
|
76
|
+
return {
|
|
77
|
+
...placement,
|
|
78
|
+
left: leftGutterBoundary,
|
|
79
|
+
transform: '',
|
|
80
|
+
width: Math.max(0, options.nodeRect.left - leftGutterBoundary - gap)
|
|
81
|
+
};
|
|
82
|
+
};
|
|
58
83
|
|
|
59
84
|
/**
|
|
60
85
|
* The insets to apply to a surface wrapper, plus whether that wrapper spans its target node.
|
|
@@ -78,7 +103,10 @@ export const toMeasuredSurfaceWrapperPlacement = placement => ({
|
|
|
78
103
|
height: placement.height,
|
|
79
104
|
left: placement.left,
|
|
80
105
|
top: placement.top,
|
|
81
|
-
transform: placement.transform
|
|
106
|
+
transform: placement.transform,
|
|
107
|
+
...(placement.width !== undefined ? {
|
|
108
|
+
width: placement.width
|
|
109
|
+
} : {})
|
|
82
110
|
}
|
|
83
111
|
});
|
|
84
112
|
|
|
@@ -135,4 +163,28 @@ export const getAnchoredSurfacePlacement = ({
|
|
|
135
163
|
transform: side === 'right' ? '' : `translateX(calc(-100% - ${gap}px))`
|
|
136
164
|
}
|
|
137
165
|
};
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Expands an anchored left surface across the available gutter without runtime measurement.
|
|
169
|
+
*/
|
|
170
|
+
export const getAnchoredLeftGutterSurfacePlacement = options => {
|
|
171
|
+
const placement = getAnchoredSurfacePlacement({
|
|
172
|
+
...options,
|
|
173
|
+
side: 'left'
|
|
174
|
+
});
|
|
175
|
+
if (options.nodeType === 'layoutColumn') {
|
|
176
|
+
return placement;
|
|
177
|
+
}
|
|
178
|
+
const gap = dragHandleGap(options.nodeType, options.parentNodeType);
|
|
179
|
+
return {
|
|
180
|
+
...placement,
|
|
181
|
+
style: {
|
|
182
|
+
...placement.style,
|
|
183
|
+
left: 0,
|
|
184
|
+
// In a `right` inset, `anchor(... left)` resolves from the containing block's right edge
|
|
185
|
+
// to the anchor's left edge. Adding the gap ends this wrapper just before the node.
|
|
186
|
+
right: `calc(anchor(${options.anchorName} left) + ${gap}px)`,
|
|
187
|
+
transform: ''
|
|
188
|
+
}
|
|
189
|
+
};
|
|
138
190
|
};
|
|
@@ -46,13 +46,16 @@ const hiddenStylesCSS = css({
|
|
|
46
46
|
const displayContentsStylesCSS = css({
|
|
47
47
|
display: 'contents'
|
|
48
48
|
});
|
|
49
|
-
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolves visibility once so a surface can apply the same state to each rendered control without
|
|
52
|
+
* creating a plugin-state subscription and hide-delay timer for every control wrapper.
|
|
53
|
+
*/
|
|
54
|
+
export const useBlockControlsVisibility = ({
|
|
50
55
|
api,
|
|
51
|
-
children,
|
|
52
56
|
controlSide,
|
|
53
57
|
forceVisibleOnMouseOut,
|
|
54
|
-
isPersistent
|
|
55
|
-
shouldUseDisplayContents
|
|
58
|
+
isPersistent
|
|
56
59
|
}) => {
|
|
57
60
|
const {
|
|
58
61
|
isTypeAheadOpen,
|
|
@@ -127,9 +130,21 @@ export const VisibilityContainer = ({
|
|
|
127
130
|
};
|
|
128
131
|
}, [shouldHideImmediate, isRightControlViewMode]);
|
|
129
132
|
const shouldHide = isRightControlViewMode ? delayedShouldHide : shouldHideImmediate;
|
|
130
|
-
|
|
133
|
+
const useCssStyles = editorExperiment('platform_editor_preview_panel_responsiveness', true, {
|
|
131
134
|
exposure: true
|
|
132
|
-
})
|
|
135
|
+
});
|
|
136
|
+
return {
|
|
137
|
+
shouldHide,
|
|
138
|
+
useCssStyles
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
export const VisibilityWrapper = ({
|
|
142
|
+
children,
|
|
143
|
+
shouldHide,
|
|
144
|
+
shouldUseDisplayContents,
|
|
145
|
+
useCssStyles
|
|
146
|
+
}) => {
|
|
147
|
+
if (useCssStyles) {
|
|
133
148
|
return jsx("div", {
|
|
134
149
|
css: [baseStylesCSS, shouldHide ? hiddenStylesCSS : visibleStylesCSS, shouldUseDisplayContents && displayContentsStylesCSS]
|
|
135
150
|
}, children);
|
|
@@ -139,4 +154,27 @@ export const VisibilityContainer = ({
|
|
|
139
154
|
, {
|
|
140
155
|
xcss: [baseStyles, shouldHide ? hiddenStyles : visibleStyles, shouldUseDisplayContents && displayContentsStyles]
|
|
141
156
|
}, children);
|
|
157
|
+
};
|
|
158
|
+
export const VisibilityContainer = ({
|
|
159
|
+
api,
|
|
160
|
+
children,
|
|
161
|
+
controlSide,
|
|
162
|
+
forceVisibleOnMouseOut,
|
|
163
|
+
isPersistent,
|
|
164
|
+
shouldUseDisplayContents
|
|
165
|
+
}) => {
|
|
166
|
+
const {
|
|
167
|
+
shouldHide,
|
|
168
|
+
useCssStyles
|
|
169
|
+
} = useBlockControlsVisibility({
|
|
170
|
+
api,
|
|
171
|
+
controlSide,
|
|
172
|
+
forceVisibleOnMouseOut,
|
|
173
|
+
isPersistent
|
|
174
|
+
});
|
|
175
|
+
return jsx(VisibilityWrapper, {
|
|
176
|
+
shouldHide: shouldHide,
|
|
177
|
+
shouldUseDisplayContents: shouldUseDisplayContents,
|
|
178
|
+
useCssStyles: useCssStyles
|
|
179
|
+
}, children);
|
|
142
180
|
};
|
|
@@ -5,7 +5,6 @@ import { bind } from 'bind-event-listener';
|
|
|
5
5
|
import { getDocument } from '@atlaskit/browser-apis';
|
|
6
6
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
7
7
|
import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
|
|
8
|
-
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
8
|
import { key } from '../main';
|
|
10
9
|
import { createPreservedSelection, mapPreservedSelection } from '../utils/selection';
|
|
11
10
|
import { stopPreservingSelection } from './editor-commands';
|
|
@@ -48,37 +47,25 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
48
47
|
key: selectionPreservationPluginKey,
|
|
49
48
|
state: {
|
|
50
49
|
init: function init() {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
} else {
|
|
57
|
-
return {
|
|
58
|
-
preservedSelection: undefined
|
|
59
|
-
};
|
|
60
|
-
}
|
|
50
|
+
return {
|
|
51
|
+
preservedSelection: undefined,
|
|
52
|
+
syncDomSelectionForDoc: undefined
|
|
53
|
+
};
|
|
61
54
|
},
|
|
62
55
|
apply: function apply(tr, pluginState) {
|
|
63
56
|
var meta = getSelectionPreservationMeta(tr);
|
|
64
57
|
var newState = _objectSpread({}, pluginState);
|
|
65
58
|
if ((meta === null || meta === void 0 ? void 0 : meta.type) === 'startPreserving') {
|
|
66
59
|
newState.preservedSelection = createPreservedSelection(tr.doc.resolve(tr.selection.from), tr.doc.resolve(tr.selection.to));
|
|
67
|
-
|
|
68
|
-
newState.syncDomSelectionForDoc = undefined;
|
|
69
|
-
}
|
|
60
|
+
newState.syncDomSelectionForDoc = undefined;
|
|
70
61
|
} else if ((meta === null || meta === void 0 ? void 0 : meta.type) === 'stopPreserving') {
|
|
71
62
|
newState.preservedSelection = undefined;
|
|
72
|
-
|
|
73
|
-
newState.syncDomSelectionForDoc = undefined;
|
|
74
|
-
}
|
|
63
|
+
newState.syncDomSelectionForDoc = undefined;
|
|
75
64
|
} else if (tr.docChanged) {
|
|
76
65
|
if (newState.preservedSelection) {
|
|
77
66
|
newState.preservedSelection = mapPreservedSelection(newState.preservedSelection, tr);
|
|
78
67
|
}
|
|
79
|
-
|
|
80
|
-
newState.syncDomSelectionForDoc = hasFormatSelectionSyncMeta(tr) ? tr.doc : undefined;
|
|
81
|
-
}
|
|
68
|
+
newState.syncDomSelectionForDoc = hasFormatSelectionSyncMeta(tr) ? tr.doc : undefined;
|
|
82
69
|
}
|
|
83
70
|
if (!compareSelections(newState.preservedSelection, pluginState.preservedSelection)) {
|
|
84
71
|
if (newState.preservedSelection) {
|
|
@@ -188,23 +175,19 @@ export var createSelectionPreservationPlugin = function createSelectionPreservat
|
|
|
188
175
|
var activeNodeChanged = prevActiveNode !== currActiveNode;
|
|
189
176
|
var docChanged = prevState.doc !== view.state.doc;
|
|
190
177
|
var hasFormatSyncRequestForCurrentDoc = (currPluginState === null || currPluginState === void 0 ? void 0 : currPluginState.syncDomSelectionForDoc) === view.state.doc;
|
|
191
|
-
var shouldSyncDOMSelection = (hasPreservedSelection && (preservedSelectionChanged || activeNodeChanged) ||
|
|
178
|
+
var shouldSyncDOMSelection = (hasPreservedSelection && (preservedSelectionChanged || activeNodeChanged) || hasFormatSyncRequestForCurrentDoc) && docChanged;
|
|
192
179
|
if (shouldSyncDOMSelection) {
|
|
193
180
|
var syncSelection = view.state.selection;
|
|
194
|
-
if (
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
cancelAnimationFrame(pendingFormatSelectionSyncFrame);
|
|
198
|
-
}
|
|
199
|
-
pendingFormatSelectionSyncFrame = requestAnimationFrame(function () {
|
|
200
|
-
pendingFormatSelectionSyncFrame = undefined;
|
|
201
|
-
syncDOMSelection(syncSelection, view, {
|
|
202
|
-
focusEditor: true
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
} else {
|
|
206
|
-
syncDOMSelection(syncSelection, view);
|
|
181
|
+
if (hasFormatSyncRequestForCurrentDoc) {
|
|
182
|
+
if (pendingFormatSelectionSyncFrame !== undefined) {
|
|
183
|
+
cancelAnimationFrame(pendingFormatSelectionSyncFrame);
|
|
207
184
|
}
|
|
185
|
+
pendingFormatSelectionSyncFrame = requestAnimationFrame(function () {
|
|
186
|
+
pendingFormatSelectionSyncFrame = undefined;
|
|
187
|
+
syncDOMSelection(syncSelection, view, {
|
|
188
|
+
focusEditor: true
|
|
189
|
+
});
|
|
190
|
+
});
|
|
208
191
|
} else {
|
|
209
192
|
syncDOMSelection(syncSelection, view);
|
|
210
193
|
}
|