diff --git a/packages/edit-site/src/components/global-styles/hooks.js b/packages/edit-site/src/components/global-styles/hooks.js index 6ecb1de03a1446..5bc823a81dbf7a 100644 --- a/packages/edit-site/src/components/global-styles/hooks.js +++ b/packages/edit-site/src/components/global-styles/hooks.js @@ -9,21 +9,16 @@ import a11yPlugin from 'colord/plugins/a11y'; */ import { store as blocksStore } from '@wordpress/blocks'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { useContext } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { mergeBaseAndUserConfigs } from './global-styles-provider'; import { useCurrentMergeThemeStyleVariationsWithUserConfig } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; -import { getFontFamilies } from './utils'; import { unlock } from '../../lock-unlock'; import { useSelect } from '@wordpress/data'; -const { useGlobalSetting, useGlobalStyle, GlobalStylesContext } = unlock( - blockEditorPrivateApis -); +const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorPrivateApis ); // Enable colord's a11y plugin. extend( [ a11yPlugin ] ); @@ -141,38 +136,17 @@ export function useTypographyVariations() { useCurrentMergeThemeStyleVariationsWithUserConfig( { property: 'typography', } ); - - const { base } = useContext( GlobalStylesContext ); /* - * Filter duplicate variations based on whether the variaitons - * have different heading and body font families. + * Filter out variations with no settings or styles. */ return typographyVariations?.length - ? Object.values( - typographyVariations.reduce( ( acc, variation ) => { - const [ bodyFontFamily, headingFontFamily ] = - getFontFamilies( - mergeBaseAndUserConfigs( base, variation ) - ); - - // Always preseve the default variation. - if ( variation?.title === 'Default' ) { - acc[ - `${ headingFontFamily?.name }:${ bodyFontFamily?.name }` - ] = variation; - } else if ( - headingFontFamily?.name && - bodyFontFamily?.name && - ! acc[ - `${ headingFontFamily?.name }:${ bodyFontFamily?.name }` - ] - ) { - acc[ - `${ headingFontFamily?.name }:${ bodyFontFamily?.name }` - ] = variation; - } - return acc; - }, {} ) - ) + ? typographyVariations.filter( ( variation ) => { + const { settings, styles, title } = variation; + return ( + title === __( 'Default' ) || // Always preseve the default variation. + Object.keys( settings ).length > 0 || + Object.keys( styles ).length > 0 + ); + } ) : []; } diff --git a/packages/edit-site/src/components/global-styles/style-variations-container.js b/packages/edit-site/src/components/global-styles/style-variations-container.js index 5ce6ce25a0fb1d..0d19bcedb174b6 100644 --- a/packages/edit-site/src/components/global-styles/style-variations-container.js +++ b/packages/edit-site/src/components/global-styles/style-variations-container.js @@ -12,6 +12,7 @@ import { __ } from '@wordpress/i18n'; */ import PreviewStyles from './preview-styles'; import Variation from './variations/variation'; +import { isVariationWithSingleProperty } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property'; export default function StyleVariationsContainer( { gap = 2 } ) { const variations = useSelect( ( select ) => { @@ -20,6 +21,14 @@ export default function StyleVariationsContainer( { gap = 2 } ) { ).__experimentalGetCurrentThemeGlobalStylesVariations(); }, [] ); + // Filter out variations that are of single property type, i.e. color or typography variations. + const multiplePropertyVariations = variations?.filter( ( variation ) => { + return ( + ! isVariationWithSingleProperty( variation, 'color' ) && + ! isVariationWithSingleProperty( variation, 'typography' ) + ); + } ); + const withEmptyVariation = useMemo( () => { return [ { @@ -27,13 +36,13 @@ export default function StyleVariationsContainer( { gap = 2 } ) { settings: {}, styles: {}, }, - ...( variations ?? [] ).map( ( variation ) => ( { + ...( multiplePropertyVariations ?? [] ).map( ( variation ) => ( { ...variation, settings: variation.settings ?? {}, styles: variation.styles ?? {}, } ) ), ]; - }, [ variations ] ); + }, [ multiplePropertyVariations ] ); return ( { - let result = { - ...filterObjectByProperty( cloneDeep( variation ), property ), - title: variation?.title, - description: variation?.description, - }; - - if ( clonedBaseVariation ) { - /* - * Overwrites all baseVariation object `styleProperty` properties - * with the theme variation `styleProperty` properties. - */ - result = mergeBaseAndUserConfigs( clonedBaseVariation, result ); - } - return result; - } ); + let processedStyleVariations = variations.reduce( + ( accumulator, variation ) => { + const variationFilteredByProperty = filterObjectByProperty( + cloneDeep( variation ), + property + ); + // Remove variations that are empty once the property is filtered out. + if ( Object.keys( variationFilteredByProperty ).length === 0 ) { + return accumulator; + } + + let result = { + ...variationFilteredByProperty, + title: variation?.title, + description: variation?.description, + }; + + if ( clonedBaseVariation ) { + /* + * Overwrites all baseVariation object `styleProperty` properties + * with the theme variation `styleProperty` properties. + */ + result = mergeBaseAndUserConfigs( + clonedBaseVariation, + result + ); + } + + // Detect if this is a duplicate variation. + const isDuplicate = accumulator.some( ( item ) => { + return ( + JSON.stringify( item.styles ) === + JSON.stringify( result?.styles ) && + JSON.stringify( item.settings ) === + JSON.stringify( result?.settings ) + ); + } ); + if ( isDuplicate ) { + return accumulator; + } + + // If the variation is not a duplicate, add it to the accumulator. + accumulator.push( result ); + return accumulator; + }, + [] // Initial accumulator value. + ); if ( 'function' === typeof filter ) { processedStyleVariations = @@ -178,3 +209,25 @@ export default function useThemeStyleVariationsByProperty( { return processedStyleVariations; }, [ variations, property, baseVariation, filter ] ); } + +/** + * Compares a style variation to the same variation filtered by a single property. + * Returns true if the variation contains only the property specified. + * + * @param {Object} variation The variation to compare. + * @param {string} property The property to compare. + * @return {boolean} Whether the variation contains only a single property. + */ +export function isVariationWithSingleProperty( variation, property ) { + const variationWithProperty = filterObjectByProperty( + cloneDeep( variation ), + property + ); + + return ( + JSON.stringify( variationWithProperty?.styles ) === + JSON.stringify( variation?.styles ) && + JSON.stringify( variationWithProperty?.settings ) === + JSON.stringify( variation?.settings ) + ); +}