@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
154 lines (153 loc) • 6.92 kB
JavaScript
import React, { createContext, useContext, useMemo } from 'react';
import { BLOCK_CONTROL_UI_CONTEXT } from '@atlaskit/editor-common/block-controls/block-control-ui-context';
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';
import { createSurfaceContext } from '@atlaskit/editor-ui-control-model/create-surface-context';
import { getComponentIdentity, resolveSurface } from '@atlaskit/editor-ui-control-model/surface-renderer';
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
import { partitionComponentsByPersistence } from './utils/partition-components-by-persistence';
import { VisibilityWrapper } from './visibility-container';
const BlockControlsVisibilityContext = /*#__PURE__*/createContext({
shouldHideHoverControls: false,
useCssStyles: false
});
const BlockControlItem = ({
children
}) => /*#__PURE__*/React.createElement("div", {
"data-editor-block-control-item": true
}, children);
const HoverBlockControlItem = ({
children
}) => {
const {
shouldHideHoverControls,
useCssStyles
} = useContext(BlockControlsVisibilityContext);
return /*#__PURE__*/React.createElement(BlockControlItem, null, /*#__PURE__*/React.createElement(VisibilityWrapper, {
shouldHide: shouldHideHoverControls,
useCssStyles: useCssStyles
}, children));
};
const PersistentBlockControlItem = ({
children
}) => {
const {
useCssStyles
} = useContext(BlockControlsVisibilityContext);
return /*#__PURE__*/React.createElement(BlockControlItem, null, /*#__PURE__*/React.createElement(VisibilityWrapper, {
shouldHide: false,
useCssStyles: useCssStyles
}, children));
};
export const BlockControlsVisibilityProvider = ({
children,
shouldHideHoverControls,
useCssStyles
}) => {
const value = useMemo(() => ({
shouldHideHoverControls,
useCssStyles
}), [shouldHideHoverControls, useCssStyles]);
return /*#__PURE__*/React.createElement(BlockControlsVisibilityContext.Provider, {
value: value
}, children);
};
const withoutVisibilityPredicate = component => {
const {
isHidden: _isHidden,
...visibleComponent
} = component;
return visibleComponent;
};
const withControlVisibility = (surfaceContext, controlVisibility) => {
const context = surfaceContext.get(BLOCK_CONTROL_UI_CONTEXT);
if (!context) {
return surfaceContext;
}
const controlContext = createSurfaceContext(BLOCK_CONTROL_UI_CONTEXT, {
...context,
controlVisibility: new Map(controlVisibility)
});
return {
get: token => {
var _controlContext$get;
return (_controlContext$get = controlContext.get(token)) !== null && _controlContext$get !== void 0 ? _controlContext$get : surfaceContext.get(token);
}
};
};
/**
* Replaces the shared surface group with one stable wrapper group per visible control. The wrappers
* inherit each control's rank, so SurfaceRenderer keeps the registry order without re-evaluating
* the controls' visibility predicates.
*/
const getBlockControlsSurfaceComponents = (components, {
group,
section,
surface
}, surfaceContext) => {
var _resolvedSurface$chil;
const resolvedSurface = resolveSurface(components, surface);
const groupIdentity = getComponentIdentity(group);
const controls = (_resolvedSurface$chil = resolvedSurface.childrenMap.get(groupIdentity)) !== null && _resolvedSurface$chil !== void 0 ? _resolvedSurface$chil : [];
const visibleControls = [];
const controlVisibility = isExperimentEnabled('platform_editor_remix_control_priority') ? new Map() : undefined;
for (const control of controls) {
var _control$isHidden, _control$isHidden2;
const isHidden = (_control$isHidden = (_control$isHidden2 = control.isHidden) === null || _control$isHidden2 === void 0 ? void 0 : _control$isHidden2.call(control, {
surfaceContext: controlVisibility ? withControlVisibility(surfaceContext, controlVisibility) : surfaceContext
})) !== null && _control$isHidden !== void 0 ? _control$isHidden : false;
controlVisibility === null || controlVisibility === void 0 ? void 0 : controlVisibility.set(control.key, isHidden);
if (!isHidden) {
visibleControls.push(control);
}
}
if (!resolvedSurface.root || visibleControls.length === 0) {
return undefined;
}
const controlIdentities = new Set(controls.map(getComponentIdentity));
const visibleControlIdentities = new Set(visibleControls.map(getComponentIdentity));
const {
persistentComponents
} = partitionComponentsByPersistence(resolvedSurface.components.filter(component => {
const identity = getComponentIdentity(component);
return !controlIdentities.has(identity) || visibleControlIdentities.has(identity);
}), surface, surfaceContext);
const persistentIdentities = new Set(persistentComponents.map(getComponentIdentity));
const structuralComponents = resolvedSurface.components.filter(component => {
const identity = getComponentIdentity(component);
return identity !== groupIdentity && !controlIdentities.has(identity);
}).map(withoutVisibilityPredicate);
const wrappedControls = visibleControls.flatMap(control => {
var _control$parents$find, _control$parents, _control$parents$find2;
const identity = getComponentIdentity(control);
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;
const wrapper = {
component: persistentIdentities.has(identity) ? PersistentBlockControlItem : HoverBlockControlItem,
key: `block-control-item:${identity}`,
parents: [{
...section,
rank
}],
type: 'group'
};
const visibleControl = {
...withoutVisibilityPredicate(control),
parents: [{
key: wrapper.key,
rank: 0,
type: wrapper.type
}]
};
return [wrapper, visibleControl];
});
return [...structuralComponents, ...wrappedControls];
};
export const getBlockControlsLeftSurfaceComponents = (components, surfaceContext) => getBlockControlsSurfaceComponents(components, {
group: BLOCK_CONTROLS_LEFT_GROUP,
section: BLOCK_CONTROLS_LEFT_SECTION,
surface: BLOCK_CONTROLS_LEFT_SURFACE
}, surfaceContext);
export const getBlockControlsRightSurfaceComponents = (components, surfaceContext) => getBlockControlsSurfaceComponents(components, {
group: BLOCK_CONTROLS_RIGHT_GROUP,
section: BLOCK_CONTROLS_RIGHT_SECTION,
surface: BLOCK_CONTROLS_RIGHT_SURFACE
}, surfaceContext);