UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

154 lines (153 loc) • 6.92 kB
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);