@atlaskit/editor-plugin-block-controls 20.1.3 → 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.
Files changed (29) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/ui/block-controls-left-surface.compiled.css +7 -1
  3. package/dist/cjs/ui/block-controls-left-surface.js +41 -27
  4. package/dist/cjs/ui/block-controls-left-surfaces.js +32 -12
  5. package/dist/cjs/ui/block-controls-right-surface.js +32 -24
  6. package/dist/cjs/ui/block-controls-right-surfaces.js +6 -4
  7. package/dist/cjs/ui/block-controls-surface-components.js +142 -0
  8. package/dist/cjs/ui/utils/get-surface-placement.js +63 -16
  9. package/dist/cjs/ui/visibility-container.js +42 -7
  10. package/dist/es2019/ui/block-controls-left-surface.compiled.css +7 -1
  11. package/dist/es2019/ui/block-controls-left-surface.js +44 -29
  12. package/dist/es2019/ui/block-controls-left-surfaces.js +41 -16
  13. package/dist/es2019/ui/block-controls-right-surface.js +35 -26
  14. package/dist/es2019/ui/block-controls-right-surfaces.js +6 -4
  15. package/dist/es2019/ui/block-controls-surface-components.js +129 -0
  16. package/dist/es2019/ui/utils/get-surface-placement.js +59 -7
  17. package/dist/es2019/ui/visibility-container.js +44 -6
  18. package/dist/esm/ui/block-controls-left-surface.compiled.css +7 -1
  19. package/dist/esm/ui/block-controls-left-surface.js +43 -29
  20. package/dist/esm/ui/block-controls-left-surfaces.js +33 -13
  21. package/dist/esm/ui/block-controls-right-surface.js +34 -26
  22. package/dist/esm/ui/block-controls-right-surfaces.js +6 -4
  23. package/dist/esm/ui/block-controls-surface-components.js +133 -0
  24. package/dist/esm/ui/utils/get-surface-placement.js +62 -15
  25. package/dist/esm/ui/visibility-container.js +41 -6
  26. package/dist/types/ui/block-controls-surface-components.d.ts +13 -0
  27. package/dist/types/ui/utils/get-surface-placement.d.ts +13 -0
  28. package/dist/types/ui/visibility-container.d.ts +14 -0
  29. package/package.json +2 -2
@@ -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
- return side === 'right' ? {
47
- left: nodeRect.right + gap,
48
- top,
49
- transform: '',
50
- height
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
- export const VisibilityContainer = ({
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
- if (editorExperiment('platform_editor_preview_panel_responsiveness', true, {
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
  };
@@ -1,7 +1,13 @@
1
1
  ._zulpv77o{gap:var(--ds-space-025,2px)}._154iu2gc{top:var(--ds-space-100,8px)}
2
2
  ._17c61i8t{position-visibility:anchors-valid}
3
+ ._1bahesu3{justify-content:flex-end}
3
4
  ._1e0c1txw{display:flex}
5
+ ._1f38ffwv{container-name:block-controls-left-gutter}
4
6
  ._1pbyb4wl{z-index:100}
5
7
  ._4cvr1h6o{align-items:center}
8
+ ._7cca15wb{container-type:inline-size}
6
9
  ._kqsw1if8{position:sticky}
7
- ._kqswstnw{position:absolute}
10
+ ._kqswstnw{position:absolute}
11
+ ._lcxvglyw{pointer-events:none}
12
+ ._w1y61wug>*{pointer-events:auto}
13
+ @container block-controls-left-gutter (max-width: 67px){._19vrglyw>[data-editor-block-control-item]:nth-last-child(n+3){display:none}}
@@ -4,12 +4,16 @@ import { ax, ix } from "@compiled/react/runtime";
4
4
  import React from 'react';
5
5
  import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls/block-control-ui-context';
6
6
  import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-controls/surface-keys';
7
- import { SurfaceRenderer, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
7
+ import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model/surface-renderer';
8
8
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
9
+ import { BlockControlsVisibilityProvider } from './block-controls-surface-components';
9
10
  import { getBlockControlsSurfaceControlSide } from './block-controls-surface-context';
10
- import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
11
- import { VisibilityContainer } from './visibility-container';
11
+ import { useBlockControlsVisibility } from './visibility-container';
12
12
  var leftSurfaceOuterStyles = null;
13
+ var leftSurfaceGutterStyles = {
14
+ container: "_1f38ffwv _7cca15wb _lcxvglyw",
15
+ row: "_1bahesu3 _lcxvglyw _w1y61wug _19vrglyw"
16
+ };
13
17
  var leftSurfaceRowStyles = null;
14
18
 
15
19
  // Applied in addition to leftSurfaceRowStyles when the target node is sticky-eligible (e.g. long
@@ -17,23 +21,24 @@ var leftSurfaceRowStyles = null;
17
21
  // can stick near the top of the viewport instead of scrolling off with the node's top edge.
18
22
  // Keep in sync with STICKY_CONTROLS_TOP_MARGIN in ./consts (must be a static literal here).
19
23
  var leftSurfaceStickyStyles = null;
20
- /** Renders one left block-controls surface at a document position. */
21
- export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref) {
24
+ var BlockControlsLeftSurfaceContent = function BlockControlsLeftSurfaceContent(_ref) {
22
25
  var api = _ref.api,
23
26
  components = _ref.components,
24
27
  forceVisibleOnMouseOut = _ref.forceVisibleOnMouseOut,
25
28
  placement = _ref.placement,
26
29
  source = _ref.source,
27
30
  surfaceContext = _ref.surfaceContext;
28
- if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
29
- return null;
30
- }
31
- var _partitionComponentsB = partitionComponentsByPersistence(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext),
32
- hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
33
- persistentComponents = _partitionComponentsB.persistentComponents;
34
- var willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
35
- var willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext);
31
+ var blockControlsContext = surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT);
32
+ var controlSide = getBlockControlsSurfaceControlSide(blockControlsContext, isExperimentEnabled('platform_editor_controls_reliable_anchor'));
33
+ var _useBlockControlsVisi = useBlockControlsVisibility({
34
+ api: api,
35
+ controlSide: controlSide,
36
+ forceVisibleOnMouseOut: forceVisibleOnMouseOut
37
+ }),
38
+ shouldHideHoverControls = _useBlockControlsVisi.shouldHide,
39
+ useCssStyles = _useBlockControlsVisi.useCssStyles;
36
40
  var isSticky = placement.isSticky;
41
+ var isTopLevel = (blockControlsContext === null || blockControlsContext === void 0 ? void 0 : blockControlsContext.targetNode.parentType) === 'doc';
37
42
  return /*#__PURE__*/React.createElement("div", {
38
43
  "data-editor-block-controls-surface": true,
39
44
  "data-editor-block-controls-side": "left",
@@ -41,27 +46,36 @@ export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref) {
41
46
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Placement is resolved per target node, from its runtime DOM geometry or from its CSS anchor.
42
47
  ,
43
48
  style: placement.style,
44
- className: ax(["_kqswstnw _17c61i8t _1pbyb4wl"])
49
+ className: ax(["_kqswstnw _17c61i8t _1pbyb4wl", isTopLevel && leftSurfaceGutterStyles.container])
45
50
  }, /*#__PURE__*/React.createElement("div", {
46
- className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
47
- }, willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
48
- api: api,
49
- controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
50
- forceVisibleOnMouseOut: forceVisibleOnMouseOut,
51
- shouldUseDisplayContents: true
51
+ className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isTopLevel && leftSurfaceGutterStyles.row, isSticky && "_kqsw1if8 _154iu2gc"])
52
+ }, /*#__PURE__*/React.createElement(BlockControlsVisibilityProvider, {
53
+ shouldHideHoverControls: shouldHideHoverControls,
54
+ useCssStyles: useCssStyles
52
55
  }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
53
- components: hoverOnlyComponents,
56
+ components: components,
54
57
  surface: BLOCK_CONTROLS_LEFT_SURFACE,
55
58
  surfaceContext: surfaceContext
56
- })), willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
59
+ }))));
60
+ };
61
+
62
+ /** Renders one left block-controls surface at a document position. */
63
+ export var BlockControlsLeftSurface = function BlockControlsLeftSurface(_ref2) {
64
+ var api = _ref2.api,
65
+ components = _ref2.components,
66
+ forceVisibleOnMouseOut = _ref2.forceVisibleOnMouseOut,
67
+ placement = _ref2.placement,
68
+ source = _ref2.source,
69
+ surfaceContext = _ref2.surfaceContext;
70
+ if (!placement) {
71
+ return null;
72
+ }
73
+ return /*#__PURE__*/React.createElement(BlockControlsLeftSurfaceContent, {
57
74
  api: api,
58
- controlSide: getBlockControlsSurfaceControlSide(surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT), isExperimentEnabled('platform_editor_controls_reliable_anchor')),
75
+ components: components,
59
76
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
60
- isPersistent: true,
61
- shouldUseDisplayContents: true
62
- }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
63
- components: persistentComponents,
64
- surface: BLOCK_CONTROLS_LEFT_SURFACE,
77
+ placement: placement,
78
+ source: source,
65
79
  surfaceContext: surfaceContext
66
- }))));
80
+ });
67
81
  };
@@ -15,14 +15,13 @@ import { BLOCK_CONTROLS_LEFT_SURFACE } from '@atlaskit/editor-common/block-contr
15
15
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
16
16
  import { isCSSAnchorSupported } from '@atlaskit/editor-common/styles';
17
17
  import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
18
- import { willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
19
18
  import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
20
19
  import { BlockControlsLeftSurface } from './block-controls-left-surface';
20
+ import { getBlockControlsLeftSurfaceComponents } from './block-controls-surface-components';
21
21
  import { createBlockControlsSurfaceContextForPosition } from './block-controls-surface-context';
22
22
  import { getBlockControlsSurfaceTargets } from './block-controls-surface-targets';
23
23
  import { getNodeContentElement } from './utils/get-node-content-element';
24
- import { getAbsoluteSurfacePlacement, getAnchoredSurfacePlacement, getSurfacePlacement, toMeasuredSurfaceWrapperPlacement } from './utils/get-surface-placement';
25
- import { hasSurfaceControls } from './utils/has-surface-controls';
24
+ import { getAbsoluteSurfacePlacement, getAnchoredLeftGutterSurfacePlacement, getAnchoredSurfacePlacement, getLeftGutterSurfacePlacement, getSurfacePlacement, toMeasuredSurfaceWrapperPlacement } from './utils/get-surface-placement';
26
25
  var EMPTY_SURFACE_POSITIONS = [];
27
26
  var EMPTY_SURFACE_ANCHORS = new Map();
28
27
  var EMPTY_SURFACE_COMPONENTS = [];
@@ -60,14 +59,20 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
60
59
  return [];
61
60
  }
62
61
  var surfaceContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, context);
63
- if (!hasSurfaceControls(components) || !willSurfaceRender(components, BLOCK_CONTROLS_LEFT_SURFACE, surfaceContext)) {
62
+ var surfaceComponents = getBlockControlsLeftSurfaceComponents(components, surfaceContext);
63
+ if (!surfaceComponents) {
64
64
  return [];
65
65
  }
66
66
  // The cache supplies the same anchor names used by ProseMirror decorations.
67
67
  var anchorName = isCSSAnchorSupported() ? surfaceAnchors.get(target.position) : undefined;
68
+ // Top-level controls can respond to the available left gutter without the surface
69
+ // host knowing which controls are registered or how they adapt.
70
+ var isTopLevel = context.targetNode.parentType === 'doc';
68
71
  return [_objectSpread(_objectSpread({}, target), {}, {
69
72
  anchorName: anchorName,
70
73
  blockControlsContext: context,
74
+ isTopLevel: isTopLevel,
75
+ surfaceComponents: surfaceComponents,
71
76
  surfaceContext: surfaceContext
72
77
  })];
73
78
  });
@@ -80,15 +85,22 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
80
85
  return new Map(surfaces.flatMap(function (_ref3) {
81
86
  var anchorName = _ref3.anchorName,
82
87
  blockControlsContext = _ref3.blockControlsContext,
88
+ isTopLevel = _ref3.isTopLevel,
83
89
  position = _ref3.position;
84
- return anchorName ? [[position, getAnchoredSurfacePlacement({
90
+ if (!anchorName) {
91
+ return [];
92
+ }
93
+ var options = {
85
94
  anchorName: anchorName,
95
+ layout: blockControlsContext.targetNode.node.attrs.layout,
86
96
  nodeType: blockControlsContext.targetNode.type.name,
87
97
  nodeTypeWithLevel: getNodeTypeWithLevel(blockControlsContext.targetNode.node),
88
- layout: blockControlsContext.targetNode.node.attrs.layout,
89
- parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType,
98
+ parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType
99
+ };
100
+ var placement = isTopLevel ? getAnchoredLeftGutterSurfacePlacement(options) : getAnchoredSurfacePlacement(_objectSpread(_objectSpread({}, options), {}, {
90
101
  side: 'left'
91
- })]] : [];
102
+ }));
103
+ return [[position, placement]];
92
104
  }));
93
105
  }, [surfaces]);
94
106
  // Only the surfaces that still need measuring drive the effect below, so a document of anchored
@@ -122,6 +134,7 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
122
134
  }
123
135
  var measurementTargets = measuredSurfaces.flatMap(function (_ref5) {
124
136
  var blockControlsContext = _ref5.blockControlsContext,
137
+ isTopLevel = _ref5.isTopLevel,
125
138
  position = _ref5.position;
126
139
  var targetNodeElement = editorView.nodeDOM(blockControlsContext.targetNode.pos);
127
140
  var targetElementRoot = targetNodeElement instanceof HTMLElement ? targetNodeElement : targetNodeElement === null || targetNodeElement === void 0 ? void 0 : targetNodeElement.parentElement;
@@ -130,6 +143,7 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
130
143
  }
131
144
  return [{
132
145
  blockControlsContext: blockControlsContext,
146
+ isTopLevel: isTopLevel,
133
147
  position: position,
134
148
  targetElement: getNodeContentElement(targetElementRoot, blockControlsContext.targetNode.type.name),
135
149
  targetElementRoot: targetElementRoot
@@ -149,23 +163,28 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
149
163
  _step;
150
164
  try {
151
165
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
152
- var _targetElementRoot$ge;
166
+ var _targetElementRoot$ge, _offsetParentRect$lef;
153
167
  var _step$value = _step.value,
154
168
  blockControlsContext = _step$value.blockControlsContext,
169
+ isTopLevel = _step$value.isTopLevel,
155
170
  position = _step$value.position,
156
171
  targetElement = _step$value.targetElement,
157
172
  targetElementRoot = _step$value.targetElementRoot;
158
173
  if (!targetElementRoot.isConnected || !targetElement.isConnected) {
159
174
  continue;
160
175
  }
161
- var placement = getSurfacePlacement({
176
+ var options = {
162
177
  layout: (_targetElementRoot$ge = targetElementRoot.getAttribute('layout')) !== null && _targetElementRoot$ge !== void 0 ? _targetElementRoot$ge : '',
163
178
  nodeRect: targetElement.getBoundingClientRect(),
164
179
  nodeType: blockControlsContext.targetNode.type.name,
165
180
  nodeTypeWithLevel: getNodeTypeWithLevel(blockControlsContext.targetNode.node),
166
- parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType,
181
+ parentNodeType: blockControlsContext.targetNode.parentType === 'doc' ? undefined : blockControlsContext.targetNode.parentType
182
+ };
183
+ var placement = isTopLevel ? getLeftGutterSurfacePlacement(_objectSpread(_objectSpread({}, options), {}, {
184
+ leftGutterBoundary: (_offsetParentRect$lef = offsetParentRect === null || offsetParentRect === void 0 ? void 0 : offsetParentRect.left) !== null && _offsetParentRect$lef !== void 0 ? _offsetParentRect$lef : 0
185
+ })) : getSurfacePlacement(_objectSpread(_objectSpread({}, options), {}, {
167
186
  side: 'left'
168
- });
187
+ }));
169
188
  nextPlacements.set(position, toMeasuredSurfaceWrapperPlacement(getAbsoluteSurfacePlacement({
170
189
  offsetParentRect: offsetParentRect,
171
190
  offsetParentScrollLeft: offsetParentScrollLeft,
@@ -251,10 +270,11 @@ export var BlockControlsLeftSurfaces = function BlockControlsLeftSurfaces(_ref)
251
270
  var _activeNode$handleOpt, _anchoredPlacements$g;
252
271
  var position = _ref6.position,
253
272
  source = _ref6.source,
273
+ surfaceComponents = _ref6.surfaceComponents,
254
274
  surfaceContext = _ref6.surfaceContext;
255
275
  return /*#__PURE__*/React.createElement(BlockControlsLeftSurface, {
256
276
  api: api,
257
- components: components,
277
+ components: surfaceComponents,
258
278
  forceVisibleOnMouseOut: Boolean(activeNode === null || activeNode === void 0 || (_activeNode$handleOpt = activeNode.handleOptions) === null || _activeNode$handleOpt === void 0 ? void 0 : _activeNode$handleOpt.isFocused),
259
279
  key: position,
260
280
  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, willSurfaceRender } from '@atlaskit/editor-ui-control-model/surface-renderer';
7
- import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
8
- import { VisibilityContainer } from './visibility-container';
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
  var rightSurfaceOuterStyles = null;
10
10
  var rightSurfaceRowStyles = null;
11
11
 
@@ -14,22 +14,20 @@ var 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
  var rightSurfaceStickyStyles = null;
17
- /** Renders one right block-controls surface at a document position. */
18
- export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref) {
17
+ var BlockControlsRightSurfaceContent = function BlockControlsRightSurfaceContent(_ref) {
19
18
  var api = _ref.api,
20
19
  components = _ref.components,
21
20
  forceVisibleOnMouseOut = _ref.forceVisibleOnMouseOut,
22
21
  placement = _ref.placement,
23
22
  source = _ref.source,
24
23
  surfaceContext = _ref.surfaceContext;
25
- if (!placement || !willSurfaceRender(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext)) {
26
- return null;
27
- }
28
- var _partitionComponentsB = partitionComponentsByPersistence(components, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext),
29
- hoverOnlyComponents = _partitionComponentsB.hoverOnlyComponents,
30
- persistentComponents = _partitionComponentsB.persistentComponents;
31
- var willRenderPersistent = willSurfaceRender(persistentComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
32
- var willRenderHoverOnly = willSurfaceRender(hoverOnlyComponents, BLOCK_CONTROLS_RIGHT_SURFACE, surfaceContext);
24
+ var _useBlockControlsVisi = useBlockControlsVisibility({
25
+ api: api,
26
+ controlSide: 'right',
27
+ forceVisibleOnMouseOut: forceVisibleOnMouseOut
28
+ }),
29
+ shouldHideHoverControls = _useBlockControlsVisi.shouldHide,
30
+ useCssStyles = _useBlockControlsVisi.useCssStyles;
33
31
  var isSticky = placement.isSticky;
34
32
  return /*#__PURE__*/React.createElement("div", {
35
33
  "data-editor-block-controls-surface": true,
@@ -41,23 +39,33 @@ export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref)
41
39
  className: ax(["_kqswstnw _17c61i8t _1pbyb4wl"])
42
40
  }, /*#__PURE__*/React.createElement("div", {
43
41
  className: ax(["_zulpv77o _4cvr1h6o _1e0c1txw", isSticky && "_kqsw1if8 _154iu2gc"])
44
- }, willRenderPersistent && /*#__PURE__*/React.createElement(VisibilityContainer, {
45
- api: api,
46
- controlSide: "right",
47
- isPersistent: true,
48
- shouldUseDisplayContents: true
42
+ }, /*#__PURE__*/React.createElement(BlockControlsVisibilityProvider, {
43
+ shouldHideHoverControls: shouldHideHoverControls,
44
+ useCssStyles: useCssStyles
49
45
  }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
50
- components: persistentComponents,
46
+ components: components,
51
47
  surface: BLOCK_CONTROLS_RIGHT_SURFACE,
52
48
  surfaceContext: surfaceContext
53
- })), willRenderHoverOnly && /*#__PURE__*/React.createElement(VisibilityContainer, {
49
+ }))));
50
+ };
51
+
52
+ /** Renders one right block-controls surface at a document position. */
53
+ export var BlockControlsRightSurface = function BlockControlsRightSurface(_ref2) {
54
+ var api = _ref2.api,
55
+ components = _ref2.components,
56
+ forceVisibleOnMouseOut = _ref2.forceVisibleOnMouseOut,
57
+ placement = _ref2.placement,
58
+ source = _ref2.source,
59
+ surfaceContext = _ref2.surfaceContext;
60
+ if (!placement) {
61
+ return null;
62
+ }
63
+ return /*#__PURE__*/React.createElement(BlockControlsRightSurfaceContent, {
54
64
  api: api,
55
- controlSide: "right",
65
+ components: components,
56
66
  forceVisibleOnMouseOut: forceVisibleOnMouseOut,
57
- shouldUseDisplayContents: true
58
- }, /*#__PURE__*/React.createElement(SurfaceRenderer, {
59
- components: hoverOnlyComponents,
60
- surface: BLOCK_CONTROLS_RIGHT_SURFACE,
67
+ placement: placement,
68
+ source: source,
61
69
  surfaceContext: surfaceContext
62
- }))));
70
+ });
63
71
  };