Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global styles revisions: ensure that user-defined variation styles CSS is generated #62768

Merged
merged 10 commits into from
Jun 27, 2024
122 changes: 122 additions & 0 deletions packages/block-editor/src/hooks/block-style-variation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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-';

Expand Down Expand Up @@ -59,6 +60,126 @@ function getVariationNameFromClass( className, registeredStyles = [] ) {
return null;
}

// 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 ) => (
<OverrideStyles key={ override.id } override={ 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
Expand Down Expand Up @@ -157,6 +278,7 @@ function useBlockProps( { name, className, clientId } ) {
id: `variation-${ clientId }`,
css: variationStyles,
__unstableType: 'variation',
variation,
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
// 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.
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
2 changes: 2 additions & 0 deletions packages/block-editor/src/hooks/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export function useStyleOverride( {
css,
assets,
__unstableType,
variation,
clientId,
} = {} ) {
const { setStyleOverride, deleteStyleOverride } = unlock(
Expand All @@ -159,6 +160,7 @@ export function useStyleOverride( {
css,
assets,
__unstableType,
variation,
clientId,
};
// Batch updates to style overrides to avoid triggering cascading renders
Expand Down
7 changes: 6 additions & 1 deletion packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -88,4 +92,5 @@ lock( privateApis, {
PrivatePublishDateTimePicker,
useSpacingSizes,
useBlockDisplayTitle,
__unstableBlockStyleVariationOverridesWithConfig,
} );
10 changes: 9 additions & 1 deletion packages/edit-site/src/components/revisions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
ExperimentalBlockEditorProvider,
GlobalStylesContext,
useGlobalStylesOutputWithConfig,
__unstableBlockStyleVariationOverridesWithConfig,
} = unlock( blockEditorPrivateApis );
const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis );

Expand Down Expand Up @@ -74,7 +75,6 @@ function Revisions( { userConfig, blocks } ) {
name="revisions"
tabIndex={ 0 }
>
<EditorStyles styles={ editorStyles } />
<style>
{
// Forming a "block formatting context" to prevent margin collapsing.
Expand All @@ -88,6 +88,14 @@ function Revisions( { userConfig, blocks } ) {
settings={ settings }
>
<BlockList renderAppender={ false } />
{ /*
* Styles are printed inside the block editor provider,
* so they can access any registered style overrides.
*/ }
<EditorStyles styles={ editorStyles } />
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
<__unstableBlockStyleVariationOverridesWithConfig
config={ mergedConfig }
/>
</ExperimentalBlockEditorProvider>
</Disabled>
</Iframe>
Expand Down
Loading
Loading