diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js index 11cb591f666897..21259966d8a63b 100644 --- a/packages/block-editor/src/hooks/block-style-variation.js +++ b/packages/block-editor/src/hooks/block-style-variation.js @@ -16,6 +16,7 @@ import { import { useStyleOverride } from './utils'; import { store as blockEditorStore } from '../store'; import { globalStylesDataKey } from '../store/private-keys'; +import { unlock } from '../lock-unlock'; const VARIATION_PREFIX = 'is-style-'; @@ -59,7 +60,127 @@ function getVariationNameFromClass( className, registeredStyles = [] ) { return null; } -function useBlockSyleVariation( name, variation, clientId ) { +// A helper component to apply a style override using the useStyleOverride hook. +function OverrideStyles( { override } ) { + useStyleOverride( override ); +} + +/** + * This component is used to generate new block style variation overrides + * based on an incoming theme config. If a matching style is found in the config, + * a new override is created and returned. The overrides can be used in conjunction with + * useStyleOverride to apply the new styles to the editor. Its use is + * subject to change. + * + * @param {Object} props Props. + * @param {Object} props.config A global styles object, containing settings and styles. + * @return {JSX.Element|undefined} An array of new block variation overrides. + */ +export function __unstableBlockStyleVariationOverridesWithConfig( { config } ) { + const { getBlockStyles, overrides } = useSelect( + ( select ) => ( { + getBlockStyles: select( blocksStore ).getBlockStyles, + overrides: unlock( select( blockEditorStore ) ).getStyleOverrides(), + } ), + [] + ); + const { getBlockName } = useSelect( blockEditorStore ); + + const overridesWithConfig = useMemo( () => { + if ( ! overrides?.length ) { + return; + } + const newOverrides = []; + const overriddenClientIds = []; + for ( const [ , override ] of overrides ) { + if ( + override?.variation && + override?.clientId && + /* + * Because this component overwrites existing style overrides, + * filter out any overrides that are already present in the store. + */ + ! overriddenClientIds.includes( override.clientId ) + ) { + const blockName = getBlockName( override.clientId ); + const configStyles = + config?.styles?.blocks?.[ blockName ]?.variations?.[ + override.variation + ]; + if ( configStyles ) { + const variationConfig = { + settings: config?.settings, + // The variation style data is all that is needed to generate + // the styles for the current application to a block. The variation + // name is updated to match the instance specific class name. + styles: { + blocks: { + [ blockName ]: { + variations: { + [ `${ override.variation }-${ override.clientId }` ]: + configStyles, + }, + }, + }, + }, + }; + const blockSelectors = getBlockSelectors( + getBlockTypes(), + getBlockStyles, + override.clientId + ); + const hasBlockGapSupport = false; + const hasFallbackGapSupport = true; + const disableLayoutStyles = true; + const disableRootPadding = true; + const variationStyles = toStyles( + variationConfig, + blockSelectors, + hasBlockGapSupport, + hasFallbackGapSupport, + disableLayoutStyles, + disableRootPadding, + { + blockGap: false, + blockStyles: true, + layoutStyles: false, + marginReset: false, + presets: false, + rootPadding: false, + variationStyles: true, + } + ); + newOverrides.push( { + id: `${ override.variation }-${ override.clientId }`, + css: variationStyles, + __unstableType: 'variation', + variation: override.variation, + // The clientId will be stored with the override and used to ensure + // the order of overrides matches the order of blocks so that the + // correct CSS cascade is maintained. + clientId: override.clientId, + } ); + overriddenClientIds.push( override.clientId ); + } + } + } + return newOverrides; + }, [ config, overrides, getBlockStyles, getBlockName ] ); + + if ( ! overridesWithConfig || ! overridesWithConfig.length ) { + return; + } + + return ( + <> + { overridesWithConfig.map( ( override ) => ( + + ) ) } + + ); +} + +function useBlockStyleVariation( name, variation, clientId ) { // Prefer global styles data in GlobalStylesContext, which are available // if in the site editor. Otherwise fall back to whatever is in the // editor settings and available in the post editor. @@ -112,7 +233,7 @@ function useBlockProps( { name, className, clientId } ) { const variation = getVariationNameFromClass( className, registeredStyles ); const variationClass = `${ VARIATION_PREFIX }${ variation }-${ clientId }`; - const { settings, styles } = useBlockSyleVariation( + const { settings, styles } = useBlockStyleVariation( name, variation, clientId @@ -157,6 +278,7 @@ function useBlockProps( { name, className, clientId } ) { id: `variation-${ clientId }`, css: variationStyles, __unstableType: 'variation', + variation, // The clientId will be stored with the override and used to ensure // the order of overrides matches the order of blocks so that the // correct CSS cascade is maintained. diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 89e6819c1d0314..bd1835571fdd4a 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -88,3 +88,4 @@ export { getTypographyClassesAndStyles } from './use-typography-props'; export { getGapCSSValue } from './gap'; export { useCachedTruthy } from './use-cached-truthy'; export { useZoomOut } from './use-zoom-out'; +export { __unstableBlockStyleVariationOverridesWithConfig } from './block-style-variation'; diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index d4eb7df553d3c0..26700ecf7b3fab 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -140,6 +140,7 @@ export function useStyleOverride( { css, assets, __unstableType, + variation, clientId, } = {} ) { const { setStyleOverride, deleteStyleOverride } = unlock( @@ -159,6 +160,7 @@ export function useStyleOverride( { css, assets, __unstableType, + variation, clientId, }; // Batch updates to style overrides to avoid triggering cascading renders diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index e6f3fc4cc39d6a..bfa6ac0c90c846 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -20,7 +20,11 @@ import { cleanEmptyObject, useStyleOverride } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; import { LayoutStyle } from './components/block-list/layout'; import { BlockRemovalWarningModal } from './components/block-removal-warning-modal'; -import { useLayoutClasses, useLayoutStyles } from './hooks'; +import { + useLayoutClasses, + useLayoutStyles, + __unstableBlockStyleVariationOverridesWithConfig, +} from './hooks'; import DimensionsTool from './components/dimensions-tool'; import ResolutionTool from './components/resolution-tool'; import TextAlignmentControl from './components/text-alignment-control'; @@ -88,4 +92,5 @@ lock( privateApis, { PrivatePublishDateTimePicker, useSpacingSizes, useBlockDisplayTitle, + __unstableBlockStyleVariationOverridesWithConfig, } ); diff --git a/packages/edit-site/src/components/revisions/index.js b/packages/edit-site/src/components/revisions/index.js index b726e79b15f2f7..d43b5e8d2ac025 100644 --- a/packages/edit-site/src/components/revisions/index.js +++ b/packages/edit-site/src/components/revisions/index.js @@ -25,6 +25,7 @@ const { ExperimentalBlockEditorProvider, GlobalStylesContext, useGlobalStylesOutputWithConfig, + __unstableBlockStyleVariationOverridesWithConfig, } = unlock( blockEditorPrivateApis ); const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); @@ -74,7 +75,6 @@ function Revisions( { userConfig, blocks } ) { name="revisions" tabIndex={ 0 } > -