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 }
>
-