From be5028c4e2ea8a9d0a5be461d889853e2b787047 Mon Sep 17 00:00:00 2001 From: Jorge Date: Thu, 19 Aug 2021 16:14:40 +0100 Subject: [PATCH 1/8] Add: API to allow blocks to access global styles. --- ...-rest-block-editor-settings-controller.php | 2 +- lib/global-styles.php | 4 +- packages/block-editor/src/components/index.js | 1 + .../components/line-height-control/index.js | 8 +- .../src/components/use-style/index.js | 52 ++++ .../block-editor/src/hooks/line-height.js | 3 + packages/block-editor/src/utils/index.js | 4 + .../src/utils/style-variable-resolution.js | 180 ++++++++++++++ packages/blocks/src/api/constants.js | 42 ++++ packages/blocks/src/api/index.js | 1 + .../editor/global-styles-provider.js | 30 ++- .../editor/global-styles-renderer.js | 3 +- .../edit-site/src/components/editor/utils.js | 222 +----------------- .../provider/use-block-editor-settings.js | 1 + 14 files changed, 318 insertions(+), 235 deletions(-) create mode 100644 packages/block-editor/src/components/use-style/index.js create mode 100644 packages/block-editor/src/utils/style-variable-resolution.js diff --git a/lib/class-wp-rest-block-editor-settings-controller.php b/lib/class-wp-rest-block-editor-settings-controller.php index 1d66d1f903b0e5..6de3788fe28c24 100644 --- a/lib/class-wp-rest-block-editor-settings-controller.php +++ b/lib/class-wp-rest-block-editor-settings-controller.php @@ -149,7 +149,7 @@ public function get_item_schema() { '__experimentalStyles' => array( 'description' => __( 'Styles consolidated from core, theme, and user origins.', 'gutenberg' ), 'type' => 'object', - 'context' => array( 'mobile' ), + 'context' => array( 'post-editor', 'site-editor', 'widgets-editor', 'mobile' ), ), 'alignWide' => array( diff --git a/lib/global-styles.php b/lib/global-styles.php index a749a66c40cf0d..6e18284a10bcb8 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -111,9 +111,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && } $consolidated = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, $origin ); - if ( 'mobile' === $context ) { - $settings['__experimentalStyles'] = $consolidated->get_raw_data()['styles']; - } + $settings['__experimentalStyles'] = $consolidated->get_raw_data()['styles']; if ( 'site-editor' === $context ) { $theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, 'theme' ); diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 99c1042b991730..b81a1e897a49a0 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -147,3 +147,4 @@ export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursi export { default as BlockEditorProvider } from './provider'; export { default as useSetting } from './use-setting'; +export { default as __experimentalUseStyle } from './use-style'; diff --git a/packages/block-editor/src/components/line-height-control/index.js b/packages/block-editor/src/components/line-height-control/index.js index f4b5261b40acee..c3c0f74908c338 100644 --- a/packages/block-editor/src/components/line-height-control/index.js +++ b/packages/block-editor/src/components/line-height-control/index.js @@ -15,7 +15,11 @@ import { isLineHeightDefined, } from './utils'; -export default function LineHeightControl( { value: lineHeight, onChange } ) { +export default function LineHeightControl( { + value: lineHeight, + onChange, + placeholder = BASE_DEFAULT_VALUE, +} ) { const isDefined = isLineHeightDefined( lineHeight ); const handleOnKeyDown = ( event ) => { @@ -70,7 +74,7 @@ export default function LineHeightControl( { value: lineHeight, onChange } ) { onKeyDown={ handleOnKeyDown } onChange={ handleOnChange } label={ __( 'Line height' ) } - placeholder={ BASE_DEFAULT_VALUE } + placeholder={ placeholder } step={ STEP } type="number" value={ value } diff --git a/packages/block-editor/src/components/use-style/index.js b/packages/block-editor/src/components/use-style/index.js new file mode 100644 index 00000000000000..540b4ae3422bcc --- /dev/null +++ b/packages/block-editor/src/components/use-style/index.js @@ -0,0 +1,52 @@ +/** + * External dependencies + */ +import { get } from 'lodash'; + +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { useBlockEditContext } from '../block-edit'; +import { store as blockEditorStore } from '../../store'; +import { getResolvedStyleVariable } from '../../utils/style-variable-resolution'; + +/** + * Hook that retrieves the global styles of a block. + * It works with nested objects using by finding the value at path. + * + * @param {string|Array} path The path to the setting. + * + * @return {any} Returns the style value defined for the path. + * + * @example + * ```js + * const backgroundColor = useStyle( 'color.background' ); + * ``` + */ +export default function useStyle( path ) { + const { name: blockName } = useBlockEditContext(); + + const setting = useSelect( + ( select ) => { + const settings = select( blockEditorStore ).getSettings(); + const settingsForBlock = get( settings, [ + '__experimentalStyles', + 'blocks', + blockName, + ] ); + return getResolvedStyleVariable( + settings.__experimentalFeatures, + blockName, + get( settingsForBlock, path ) + ); + }, + [ blockName, path ] + ); + + return setting; +} diff --git a/packages/block-editor/src/hooks/line-height.js b/packages/block-editor/src/hooks/line-height.js index 1d57366878b214..315106332b6ddd 100644 --- a/packages/block-editor/src/hooks/line-height.js +++ b/packages/block-editor/src/hooks/line-height.js @@ -9,6 +9,7 @@ import { hasBlockSupport } from '@wordpress/blocks'; import LineHeightControl from '../components/line-height-control'; import { cleanEmptyObject } from './utils'; import useSetting from '../components/use-setting'; +import useStyle from '../components/use-style'; export const LINE_HEIGHT_SUPPORT_KEY = 'typography.lineHeight'; @@ -24,6 +25,7 @@ export function LineHeightEdit( props ) { attributes: { style }, } = props; const isDisabled = useIsLineHeightDisabled( props ); + const defaultLineHeight = useStyle( [ 'typography', 'lineHeight' ] ); if ( isDisabled ) { return null; @@ -45,6 +47,7 @@ export function LineHeightEdit( props ) { ); } diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index f498a6bf4740bb..b01ed4be6d5fd2 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1,3 +1,7 @@ export { default as transformStyles } from './transform-styles'; export * from './theme'; export * from './block-variation-transforms'; +export { + getResolvedStyleVariable as __experimentalGetResolvedStyleVariable, + getPresetVariableRepresentingAValue as __experimentalGetPresetVariableRepresentingAValue, +} from './style-variable-resolution'; diff --git a/packages/block-editor/src/utils/style-variable-resolution.js b/packages/block-editor/src/utils/style-variable-resolution.js new file mode 100644 index 00000000000000..3d4bc7e29721ae --- /dev/null +++ b/packages/block-editor/src/utils/style-variable-resolution.js @@ -0,0 +1,180 @@ +/** + * External dependencies + */ +import { get, find, isString, kebabCase } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __EXPERIMENTAL_PRESET_METADATA as PRESET_METADATA } from '@wordpress/blocks'; + +const STYLE_PROPERTIES_TO_CSS_VAR_INFIX = { + linkColor: 'color', + backgroundColor: 'color', + background: 'gradient', +}; + +function findInPresetsBy( + features, + context, + presetPath, + presetProperty, + presetValueValue +) { + // Block presets take priority above root level presets. + const orderedPresetsByOrigin = [ + get( features, [ 'blocks', context, ...presetPath ] ), + get( features, presetPath ), + ]; + for ( const presetByOrigin of orderedPresetsByOrigin ) { + if ( presetByOrigin ) { + // Preset origins ordered by priority. + const origins = [ 'user', 'theme', 'core' ]; + for ( const origin of origins ) { + const presets = presetByOrigin[ origin ]; + if ( presets ) { + const presetObject = find( + presets, + ( preset ) => + preset[ presetProperty ] === presetValueValue + ); + if ( presetObject ) { + if ( presetProperty === 'slug' ) { + return presetObject; + } + // if there is a highest priority preset with the same slug but different value the preset we found was overwritten and should be ignored. + const highestPresetObjectWithSameSlug = findInPresetsBy( + features, + context, + presetPath, + 'slug', + presetObject.slug + ); + if ( + highestPresetObjectWithSameSlug[ + presetProperty + ] === presetObject[ presetProperty ] + ) { + return presetObject; + } + return undefined; + } + } + } + } + } +} + +function getValueFromPresetVariable( + features, + blockName, + variable, + [ presetType, slug ] +) { + const metadata = find( PRESET_METADATA, [ 'cssVarInfix', presetType ] ); + if ( ! metadata ) { + return variable; + } + + const presetObject = findInPresetsBy( + features, + blockName, + metadata.path, + 'slug', + slug + ); + + if ( presetObject ) { + const { valueKey } = metadata; + const result = presetObject[ valueKey ]; + return getResolvedStyleVariable( features, blockName, result ); + } + + return variable; +} + +function getValueFromCustomVariable( features, blockName, variable, path ) { + const result = + get( features, [ 'blocks', blockName, 'custom', ...path ] ) ?? + get( features, [ 'custom', ...path ] ); + if ( ! result ) { + return variable; + } + // A variable may reference another variable so we need recursion until we find the value. + return getResolvedStyleVariable( features, blockName, result ); +} + +export function getResolvedStyleVariable( features, context, variable ) { + if ( ! variable || ! isString( variable ) ) { + return variable; + } + const INTERNAL_REFERENCE_PREFIX = 'var:'; + const CSS_REFERENCE_PREFIX = 'var(--wp--'; + const CSS_REFERENCE_SUFFIX = ')'; + + let parsedVar; + + if ( variable.startsWith( INTERNAL_REFERENCE_PREFIX ) ) { + parsedVar = variable + .slice( INTERNAL_REFERENCE_PREFIX.length ) + .split( '|' ); + } else if ( + variable.startsWith( CSS_REFERENCE_PREFIX ) && + variable.endsWith( CSS_REFERENCE_SUFFIX ) + ) { + parsedVar = variable + .slice( CSS_REFERENCE_PREFIX.length, -CSS_REFERENCE_SUFFIX.length ) + .split( '--' ); + } else { + // Value is raw. + return variable; + } + + const [ type, ...path ] = parsedVar; + if ( type === 'preset' ) { + return getValueFromPresetVariable( features, context, variable, path ); + } + if ( type === 'custom' ) { + return getValueFromCustomVariable( features, context, variable, path ); + } + return variable; +} + +export function getPresetVariableRepresentingAValue( + features, + context, + propertyName, + value +) { + if ( ! value ) { + return value; + } + + const cssVarInfix = + STYLE_PROPERTIES_TO_CSS_VAR_INFIX[ propertyName ] || + kebabCase( propertyName ); + + const metadata = find( PRESET_METADATA, [ 'cssVarInfix', cssVarInfix ] ); + if ( ! metadata ) { + // The property doesn't have preset data + // so the value should be returned as it is. + return value; + } + const { valueKey, path } = metadata; + + const presetObject = findInPresetsBy( + features, + context, + path, + valueKey, + value + ); + + if ( ! presetObject ) { + // Value wasn't found in the presets, + // so it must be a custom value. + return value; + } + + return `var:preset|${ cssVarInfix }|${ presetObject.slug }`; +} diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index d7ce7cafd25261..d54dbfee6a5570 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -124,3 +124,45 @@ export const __EXPERIMENTAL_ELEMENTS = { h5: 'h5', h6: 'h6', }; + +export const __EXPERIMENTAL_PRESET_METADATA = [ + { + path: [ 'color', 'palette' ], + valueKey: 'color', + cssVarInfix: 'color', + classes: [ + { classSuffix: 'color', propertyName: 'color' }, + { + classSuffix: 'background-color', + propertyName: 'background-color', + }, + { + classSuffix: 'border-color', + propertyName: 'border-color', + }, + ], + }, + { + path: [ 'color', 'gradients' ], + valueKey: 'gradient', + cssVarInfix: 'gradient', + classes: [ + { + classSuffix: 'gradient-background', + propertyName: 'background', + }, + ], + }, + { + path: [ 'typography', 'fontSizes' ], + valueKey: 'size', + cssVarInfix: 'font-size', + classes: [ { classSuffix: 'font-size', propertyName: 'font-size' } ], + }, + { + path: [ 'typography', 'fontFamilies' ], + valueKey: 'fontFamily', + cssVarInfix: 'font-family', + classes: [], + }, +]; diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 394fddaa5de6e3..fc22e6cebfa2ef 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -159,4 +159,5 @@ export { default as node } from './node'; export { __EXPERIMENTAL_STYLE_PROPERTY, __EXPERIMENTAL_ELEMENTS, + __EXPERIMENTAL_PRESET_METADATA, } from './constants'; diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index d85aecdf251bcc..3a95752ff0bcb4 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -16,10 +16,15 @@ import { import { __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY, __EXPERIMENTAL_ELEMENTS as ELEMENTS, + __EXPERIMENTAL_PRESET_METADATA as PRESET_METADATA, store as blocksStore, } from '@wordpress/blocks'; import { useEntityProp } from '@wordpress/core-data'; import { useSelect, useDispatch } from '@wordpress/data'; +import { + __experimentalGetResolvedStyleVariable as getResolvedStyleVariable, + __experimentalGetPresetVariableRepresentingAValue as getPresetVariableRepresentingAValue, +} from '@wordpress/block-editor'; /** * Internal dependencies @@ -28,9 +33,6 @@ import { ROOT_BLOCK_NAME, ROOT_BLOCK_SELECTOR, ROOT_BLOCK_SUPPORTS, - getValueFromVariable, - getPresetVariable, - PRESET_METADATA, } from './utils'; import { toCustomProperties, toStyles } from './global-styles-renderer'; import { store as editSiteStore } from '../../store'; @@ -256,7 +258,11 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { if ( origin === 'theme' ) { const value = get( themeStyles?.styles, path ); - return getValueFromVariable( themeStyles, context, value ); + return getResolvedStyleVariable( + themeStyles.settings, + context, + value + ); } if ( origin === 'user' ) { @@ -265,11 +271,19 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { // We still need to use merged styles here because the // presets used to resolve user variable may be defined a // layer down ( core, theme, or user ). - return getValueFromVariable( mergedStyles, context, value ); + return getResolvedStyleVariable( + mergedStyles.setting, + context, + value + ); } const value = get( mergedStyles?.styles, path ); - return getValueFromVariable( mergedStyles, context, value ); + return getResolvedStyleVariable( + mergedStyles.settings, + context, + value + ); }, setStyle: ( context, propertyName, newValue ) => { const newContent = { ...userStyles }; @@ -288,8 +302,8 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { set( newStyles, propertyPath, - getPresetVariable( - mergedStyles, + getPresetVariableRepresentingAValue( + mergedStyles.settings, context, propertyName, newValue diff --git a/packages/edit-site/src/components/editor/global-styles-renderer.js b/packages/edit-site/src/components/editor/global-styles-renderer.js index fdec33c3fc0230..caa6b6fd744ee8 100644 --- a/packages/edit-site/src/components/editor/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/global-styles-renderer.js @@ -20,12 +20,13 @@ import { import { __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY, __EXPERIMENTAL_ELEMENTS as ELEMENTS, + __EXPERIMENTAL_PRESET_METADATA as PRESET_METADATA, } from '@wordpress/blocks'; /** * Internal dependencies */ -import { PRESET_METADATA, ROOT_BLOCK_SELECTOR } from './utils'; +import { ROOT_BLOCK_SELECTOR } from './utils'; function compileStyleValue( uncompiledValue ) { const VARIABLE_REFERENCE_PREFIX = 'var:'; diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index ba883f330ea264..cd4e4719887b9b 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -1,11 +1,12 @@ /** * External dependencies */ -import { get, find, forEach, camelCase, isString } from 'lodash'; +import { get } from 'lodash'; /** * WordPress dependencies */ import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ @@ -28,69 +29,6 @@ export const ROOT_BLOCK_SUPPORTS = [ 'textTransform', ]; -export const PRESET_METADATA = [ - { - path: [ 'color', 'palette' ], - valueKey: 'color', - cssVarInfix: 'color', - classes: [ - { classSuffix: 'color', propertyName: 'color' }, - { - classSuffix: 'background-color', - propertyName: 'background-color', - }, - { - classSuffix: 'border-color', - propertyName: 'border-color', - }, - ], - }, - { - path: [ 'color', 'gradients' ], - valueKey: 'gradient', - cssVarInfix: 'gradient', - classes: [ - { - classSuffix: 'gradient-background', - propertyName: 'background', - }, - ], - }, - { - path: [ 'typography', 'fontSizes' ], - valueKey: 'size', - cssVarInfix: 'font-size', - classes: [ { classSuffix: 'font-size', propertyName: 'font-size' } ], - }, - { - path: [ 'typography', 'fontFamilies' ], - valueKey: 'fontFamily', - cssVarInfix: 'font-family', - classes: [], - }, -]; - -const STYLE_PROPERTIES_TO_CSS_VAR_INFIX = { - linkColor: 'color', - backgroundColor: 'color', - background: 'gradient', -}; - -function getPresetMetadataFromStyleProperty( styleProperty ) { - if ( ! getPresetMetadataFromStyleProperty.MAP ) { - getPresetMetadataFromStyleProperty.MAP = {}; - PRESET_METADATA.forEach( ( { cssVarInfix }, index ) => { - getPresetMetadataFromStyleProperty.MAP[ camelCase( cssVarInfix ) ] = - PRESET_METADATA[ index ]; - } ); - forEach( STYLE_PROPERTIES_TO_CSS_VAR_INFIX, ( value, key ) => { - getPresetMetadataFromStyleProperty.MAP[ key ] = - getPresetMetadataFromStyleProperty.MAP[ value ]; - } ); - } - return getPresetMetadataFromStyleProperty.MAP[ styleProperty ]; -} - const PATHS_WITH_MERGE = { 'color.gradients': true, 'color.palette': true, @@ -110,159 +48,3 @@ export function useSetting( path, blockName = '' ) { } return result; } - -function findInPresetsBy( - styles, - context, - presetPath, - presetProperty, - presetValueValue -) { - // Block presets take priority above root level presets. - const orderedPresetsByOrigin = [ - get( styles, [ 'settings', 'blocks', context, ...presetPath ] ), - get( styles, [ 'settings', ...presetPath ] ), - ]; - for ( const presetByOrigin of orderedPresetsByOrigin ) { - if ( presetByOrigin ) { - // Preset origins ordered by priority. - const origins = [ 'user', 'theme', 'core' ]; - for ( const origin of origins ) { - const presets = presetByOrigin[ origin ]; - if ( presets ) { - const presetObject = find( - presets, - ( preset ) => - preset[ presetProperty ] === presetValueValue - ); - if ( presetObject ) { - if ( presetProperty === 'slug' ) { - return presetObject; - } - // if there is a highest priority preset with the same slug but different value the preset we found was overwritten and should be ignored. - const highestPresetObjectWithSameSlug = findInPresetsBy( - styles, - context, - presetPath, - 'slug', - presetObject.slug - ); - if ( - highestPresetObjectWithSameSlug[ - presetProperty - ] === presetObject[ presetProperty ] - ) { - return presetObject; - } - return undefined; - } - } - } - } - } -} - -export function getPresetVariable( styles, context, propertyName, value ) { - if ( ! value ) { - return value; - } - - const metadata = getPresetMetadataFromStyleProperty( propertyName ); - if ( ! metadata ) { - // The property doesn't have preset data - // so the value should be returned as it is. - return value; - } - const { valueKey, path, cssVarInfix } = metadata; - - const presetObject = findInPresetsBy( - styles, - context, - path, - valueKey, - value - ); - - if ( ! presetObject ) { - // Value wasn't found in the presets, - // so it must be a custom value. - return value; - } - - return `var:preset|${ cssVarInfix }|${ presetObject.slug }`; -} - -function getValueFromPresetVariable( - styles, - blockName, - variable, - [ presetType, slug ] -) { - presetType = camelCase( presetType ); - const metadata = getPresetMetadataFromStyleProperty( presetType ); - if ( ! metadata ) { - return variable; - } - - const presetObject = findInPresetsBy( - styles, - blockName, - metadata.path, - 'slug', - slug - ); - - if ( presetObject ) { - const { valueKey } = metadata; - const result = presetObject[ valueKey ]; - return getValueFromVariable( styles, blockName, result ); - } - - return variable; -} - -function getValueFromCustomVariable( styles, blockName, variable, path ) { - const result = - get( styles, [ 'settings', 'blocks', blockName, 'custom', ...path ] ) ?? - get( styles, [ 'settings', 'custom', ...path ] ); - if ( ! result ) { - return variable; - } - // A variable may reference another variable so we need recursion until we find the value. - return getValueFromVariable( styles, blockName, result ); -} - -export function getValueFromVariable( styles, blockName, variable ) { - if ( ! variable || ! isString( variable ) ) { - return variable; - } - - let parsedVar; - const INTERNAL_REFERENCE_PREFIX = 'var:'; - const CSS_REFERENCE_PREFIX = 'var(--wp--'; - const CSS_REFERENCE_SUFFIX = ')'; - if ( variable.startsWith( INTERNAL_REFERENCE_PREFIX ) ) { - parsedVar = variable - .slice( INTERNAL_REFERENCE_PREFIX.length ) - .split( '|' ); - } else if ( - variable.startsWith( CSS_REFERENCE_PREFIX ) && - variable.endsWith( CSS_REFERENCE_SUFFIX ) - ) { - parsedVar = variable - .slice( CSS_REFERENCE_PREFIX.length, -CSS_REFERENCE_SUFFIX.length ) - .split( '--' ); - } else { - // Value is raw. - return variable; - } - - const [ type, ...path ] = parsedVar; - if ( type === 'preset' ) { - return getValueFromPresetVariable( styles, blockName, variable, path ); - } - if ( type === 'custom' ) { - return getValueFromCustomVariable( styles, blockName, variable, path ); - } - return variable; -} diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 41d00d360fc15e..c120c375a89156 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -72,6 +72,7 @@ function useBlockEditorSettings( settings, hasTemplate ) { '__experimentalBlockDirectory', '__experimentalBlockPatternCategories', '__experimentalBlockPatterns', + '__experimentalStyles', '__experimentalFeatures', '__experimentalGlobalStylesBaseStyles', '__experimentalGlobalStylesUserEntityId', From c866a2638ea880b6138e1d7974439cf40a5541f2 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Tue, 31 Aug 2021 16:50:02 +0100 Subject: [PATCH 2/8] Update packages/block-editor/src/utils/style-variable-resolution.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- packages/block-editor/src/utils/style-variable-resolution.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/utils/style-variable-resolution.js b/packages/block-editor/src/utils/style-variable-resolution.js index 3d4bc7e29721ae..48490dcb9c9590 100644 --- a/packages/block-editor/src/utils/style-variable-resolution.js +++ b/packages/block-editor/src/utils/style-variable-resolution.js @@ -126,7 +126,7 @@ export function getResolvedStyleVariable( features, context, variable ) { .slice( CSS_REFERENCE_PREFIX.length, -CSS_REFERENCE_SUFFIX.length ) .split( '--' ); } else { - // Value is raw. + // We don't know how to parse the value: either is raw of uses complex CSS such as `calc(1px * var(--wp--variable) )` return variable; } From 5cdb0f42fd3660ffb9e919086ffa84c36d20719c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Tue, 31 Aug 2021 16:50:26 +0100 Subject: [PATCH 3/8] Update packages/edit-site/src/components/editor/global-styles-provider.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- .../edit-site/src/components/editor/global-styles-provider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index 3a95752ff0bcb4..09a84842159539 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -272,7 +272,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { // presets used to resolve user variable may be defined a // layer down ( core, theme, or user ). return getResolvedStyleVariable( - mergedStyles.setting, + mergedStyles.settings, context, value ); From 6773622122e33d86f8fe79f8927956c351779682 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 31 Aug 2021 18:14:21 +0100 Subject: [PATCH 4/8] Feedback applied --- lib/global-styles.php | 4 +- .../src/components/use-style/index.js | 37 +++++----- packages/block-editor/src/utils/index.js | 4 +- .../src/utils/style-variable-resolution.js | 68 +++++++++++-------- .../editor/global-styles-provider.js | 13 ++-- .../edit-site/src/components/editor/utils.js | 2 +- 6 files changed, 69 insertions(+), 59 deletions(-) diff --git a/lib/global-styles.php b/lib/global-styles.php index 6e18284a10bcb8..0cf5e4bb92415d 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -111,7 +111,9 @@ function_exists( 'gutenberg_is_edit_site_page' ) && } $consolidated = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, $origin ); - $settings['__experimentalStyles'] = $consolidated->get_raw_data()['styles']; + if ( 'site-editor' !== $context ) { + $settings['__experimentalStyles'] = $consolidated->get_raw_data()['styles']; + } if ( 'site-editor' === $context ) { $theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, 'theme' ); diff --git a/packages/block-editor/src/components/use-style/index.js b/packages/block-editor/src/components/use-style/index.js index 540b4ae3422bcc..e62c802d1de9b7 100644 --- a/packages/block-editor/src/components/use-style/index.js +++ b/packages/block-editor/src/components/use-style/index.js @@ -7,13 +7,14 @@ import { get } from 'lodash'; * WordPress dependencies */ import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ import { useBlockEditContext } from '../block-edit'; import { store as blockEditorStore } from '../../store'; -import { getResolvedStyleVariable } from '../../utils/style-variable-resolution'; +import { getValueFromVariable } from '../../utils/style-variable-resolution'; /** * Hook that retrieves the global styles of a block. @@ -31,22 +32,20 @@ import { getResolvedStyleVariable } from '../../utils/style-variable-resolution' export default function useStyle( path ) { const { name: blockName } = useBlockEditContext(); - const setting = useSelect( - ( select ) => { - const settings = select( blockEditorStore ).getSettings(); - const settingsForBlock = get( settings, [ - '__experimentalStyles', - 'blocks', - blockName, - ] ); - return getResolvedStyleVariable( - settings.__experimentalFeatures, - blockName, - get( settingsForBlock, path ) - ); - }, - [ blockName, path ] - ); - - return setting; + const settings = useSelect( ( select ) => { + return select( blockEditorStore ).getSettings(); + }, [] ); + const settingsForBlock = get( settings, [ + '__experimentalStyles', + 'blocks', + blockName, + ] ); + const value = get( settingsForBlock, path ); + return useMemo( () => { + return getValueFromVariable( + settings.__experimentalFeatures, + blockName, + value + ); + }, [ settings.__experimentalFeatures, blockName, value ] ); } diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index b01ed4be6d5fd2..498376b2d90fcb 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -2,6 +2,6 @@ export { default as transformStyles } from './transform-styles'; export * from './theme'; export * from './block-variation-transforms'; export { - getResolvedStyleVariable as __experimentalGetResolvedStyleVariable, - getPresetVariableRepresentingAValue as __experimentalGetPresetVariableRepresentingAValue, + getValueFromVariable as __experimentalGetValueFromVariable, + getPresetVariableFromValue as __experimentalGetPresetVariableFromValue, } from './style-variable-resolution'; diff --git a/packages/block-editor/src/utils/style-variable-resolution.js b/packages/block-editor/src/utils/style-variable-resolution.js index 48490dcb9c9590..c369b4becf182f 100644 --- a/packages/block-editor/src/utils/style-variable-resolution.js +++ b/packages/block-editor/src/utils/style-variable-resolution.js @@ -16,14 +16,14 @@ const STYLE_PROPERTIES_TO_CSS_VAR_INFIX = { function findInPresetsBy( features, - context, + blockName, presetPath, presetProperty, presetValueValue ) { // Block presets take priority above root level presets. const orderedPresetsByOrigin = [ - get( features, [ 'blocks', context, ...presetPath ] ), + get( features, [ 'blocks', blockName, ...presetPath ] ), get( features, presetPath ), ]; for ( const presetByOrigin of orderedPresetsByOrigin ) { @@ -45,7 +45,7 @@ function findInPresetsBy( // if there is a highest priority preset with the same slug but different value the preset we found was overwritten and should be ignored. const highestPresetObjectWithSameSlug = findInPresetsBy( features, - context, + blockName, presetPath, 'slug', presetObject.slug @@ -87,7 +87,7 @@ function getValueFromPresetVariable( if ( presetObject ) { const { valueKey } = metadata; const result = presetObject[ valueKey ]; - return getResolvedStyleVariable( features, blockName, result ); + return getValueFromVariable( features, blockName, result ); } return variable; @@ -101,29 +101,27 @@ function getValueFromCustomVariable( features, blockName, variable, path ) { return variable; } // A variable may reference another variable so we need recursion until we find the value. - return getResolvedStyleVariable( features, blockName, result ); + return getValueFromVariable( features, blockName, result ); } -export function getResolvedStyleVariable( features, context, variable ) { +export function getValueFromVariable( features, blockName, variable ) { if ( ! variable || ! isString( variable ) ) { return variable; } - const INTERNAL_REFERENCE_PREFIX = 'var:'; - const CSS_REFERENCE_PREFIX = 'var(--wp--'; - const CSS_REFERENCE_SUFFIX = ')'; + const USER_VALUE_PREFIX = 'var:'; + const THEME_VALUE_PREFIX = 'var(--wp--'; + const THEME_VALUE_SUFFIX = ')'; let parsedVar; - if ( variable.startsWith( INTERNAL_REFERENCE_PREFIX ) ) { - parsedVar = variable - .slice( INTERNAL_REFERENCE_PREFIX.length ) - .split( '|' ); + if ( variable.startsWith( USER_VALUE_PREFIX ) ) { + parsedVar = variable.slice( USER_VALUE_PREFIX.length ).split( '|' ); } else if ( - variable.startsWith( CSS_REFERENCE_PREFIX ) && - variable.endsWith( CSS_REFERENCE_SUFFIX ) + variable.startsWith( THEME_VALUE_PREFIX ) && + variable.endsWith( THEME_VALUE_SUFFIX ) ) { parsedVar = variable - .slice( CSS_REFERENCE_PREFIX.length, -CSS_REFERENCE_SUFFIX.length ) + .slice( THEME_VALUE_PREFIX.length, -THEME_VALUE_SUFFIX.length ) .split( '--' ); } else { // We don't know how to parse the value: either is raw of uses complex CSS such as `calc(1px * var(--wp--variable) )` @@ -132,48 +130,58 @@ export function getResolvedStyleVariable( features, context, variable ) { const [ type, ...path ] = parsedVar; if ( type === 'preset' ) { - return getValueFromPresetVariable( features, context, variable, path ); + return getValueFromPresetVariable( + features, + blockName, + variable, + path + ); } if ( type === 'custom' ) { - return getValueFromCustomVariable( features, context, variable, path ); + return getValueFromCustomVariable( + features, + blockName, + variable, + path + ); } return variable; } -export function getPresetVariableRepresentingAValue( +export function getPresetVariableFromValue( features, - context, - propertyName, - value + blockName, + presetPropertyName, + presetPropertyValue ) { - if ( ! value ) { - return value; + if ( ! presetPropertyValue ) { + return presetPropertyValue; } const cssVarInfix = - STYLE_PROPERTIES_TO_CSS_VAR_INFIX[ propertyName ] || - kebabCase( propertyName ); + STYLE_PROPERTIES_TO_CSS_VAR_INFIX[ presetPropertyName ] || + kebabCase( presetPropertyName ); const metadata = find( PRESET_METADATA, [ 'cssVarInfix', cssVarInfix ] ); if ( ! metadata ) { // The property doesn't have preset data // so the value should be returned as it is. - return value; + return presetPropertyValue; } const { valueKey, path } = metadata; const presetObject = findInPresetsBy( features, - context, + blockName, path, valueKey, - value + presetPropertyValue ); if ( ! presetObject ) { // Value wasn't found in the presets, // so it must be a custom value. - return value; + return presetPropertyValue; } return `var:preset|${ cssVarInfix }|${ presetObject.slug }`; diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index 09a84842159539..181c4d9a2be452 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -22,8 +22,8 @@ import { import { useEntityProp } from '@wordpress/core-data'; import { useSelect, useDispatch } from '@wordpress/data'; import { - __experimentalGetResolvedStyleVariable as getResolvedStyleVariable, - __experimentalGetPresetVariableRepresentingAValue as getPresetVariableRepresentingAValue, + __experimentalGetValueFromVariable as getValueFromVariable, + __experimentalGetPresetVariableFromValue as getPresetVariableFromValue, } from '@wordpress/block-editor'; /** @@ -258,7 +258,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { if ( origin === 'theme' ) { const value = get( themeStyles?.styles, path ); - return getResolvedStyleVariable( + return getValueFromVariable( themeStyles.settings, context, value @@ -271,7 +271,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { // We still need to use merged styles here because the // presets used to resolve user variable may be defined a // layer down ( core, theme, or user ). - return getResolvedStyleVariable( + return getValueFromVariable( mergedStyles.settings, context, value @@ -279,7 +279,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { } const value = get( mergedStyles?.styles, path ); - return getResolvedStyleVariable( + return getValueFromVariable( mergedStyles.settings, context, value @@ -302,7 +302,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { set( newStyles, propertyPath, - getPresetVariableRepresentingAValue( + getPresetVariableFromValue( mergedStyles.settings, context, propertyName, @@ -337,6 +337,7 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { }, ], __experimentalFeatures: mergedStyles.settings, + __experimentalStyles: mergedStyles.styles, } ); }, [ blocks, mergedStyles ] ); diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index cd4e4719887b9b..49148154997824 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { get } from 'lodash'; +import { get } from 'lodash'; /** * WordPress dependencies */ From f23ad12b69323232274053d88ce6e40a5ff2b19c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 1 Sep 2021 16:39:20 +0100 Subject: [PATCH 5/8] Update lib/class-wp-rest-block-editor-settings-controller.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- lib/class-wp-rest-block-editor-settings-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class-wp-rest-block-editor-settings-controller.php b/lib/class-wp-rest-block-editor-settings-controller.php index 6de3788fe28c24..46bca84400ba54 100644 --- a/lib/class-wp-rest-block-editor-settings-controller.php +++ b/lib/class-wp-rest-block-editor-settings-controller.php @@ -149,7 +149,7 @@ public function get_item_schema() { '__experimentalStyles' => array( 'description' => __( 'Styles consolidated from core, theme, and user origins.', 'gutenberg' ), 'type' => 'object', - 'context' => array( 'post-editor', 'site-editor', 'widgets-editor', 'mobile' ), + 'context' => array( 'post-editor', 'widgets-editor', 'mobile' ), ), 'alignWide' => array( From d926d6426c08c279ee3ec4aacc8f97235743cdfa Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 1 Sep 2021 16:39:38 +0100 Subject: [PATCH 6/8] Update packages/block-editor/src/components/use-style/index.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- packages/block-editor/src/components/use-style/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-style/index.js b/packages/block-editor/src/components/use-style/index.js index e62c802d1de9b7..1a83f31d179e01 100644 --- a/packages/block-editor/src/components/use-style/index.js +++ b/packages/block-editor/src/components/use-style/index.js @@ -35,7 +35,7 @@ export default function useStyle( path ) { const settings = useSelect( ( select ) => { return select( blockEditorStore ).getSettings(); }, [] ); - const settingsForBlock = get( settings, [ + const stylesForBlock = get( settings, [ '__experimentalStyles', 'blocks', blockName, From b1a110332e7c0f75cf88b90b072b6f59cb29630c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 1 Sep 2021 16:39:47 +0100 Subject: [PATCH 7/8] Update packages/block-editor/src/components/use-style/index.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André <583546+oandregal@users.noreply.github.com> --- packages/block-editor/src/components/use-style/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-style/index.js b/packages/block-editor/src/components/use-style/index.js index 1a83f31d179e01..b7d30274502a70 100644 --- a/packages/block-editor/src/components/use-style/index.js +++ b/packages/block-editor/src/components/use-style/index.js @@ -40,7 +40,7 @@ export default function useStyle( path ) { 'blocks', blockName, ] ); - const value = get( settingsForBlock, path ); + const value = get( stylesForBlock, path ); return useMemo( () => { return getValueFromVariable( settings.__experimentalFeatures, From c78a32292b54d357d4c570ac34c2dc1605e6017c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 1 Sep 2021 17:43:34 +0200 Subject: [PATCH 8/8] Add tests for getPresetVariableFromValue --- .../test/get-preset-variable-from-value.js | 402 ++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 packages/block-editor/src/utils/test/get-preset-variable-from-value.js diff --git a/packages/block-editor/src/utils/test/get-preset-variable-from-value.js b/packages/block-editor/src/utils/test/get-preset-variable-from-value.js new file mode 100644 index 00000000000000..4f35d47aea6ca4 --- /dev/null +++ b/packages/block-editor/src/utils/test/get-preset-variable-from-value.js @@ -0,0 +1,402 @@ +/** + * Internal dependencies + */ +import { getPresetVariableFromValue } from '../style-variable-resolution'; + +describe( 'getPresetVariableFromValue', () => { + it( 'returns the block preset variable when the value matches both the global & block presets', () => { + const presetPropertyValue = '#ff0000'; + const features = { + color: { + palette: { + core: [ + { + name: 'Red vintage', + slug: 'red-vintage', + color: presetPropertyValue, + }, + ], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + name: 'red', + slug: 'red', + color: presetPropertyValue, + }, + ], + theme: [], + user: [], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red' ); + } ); + + it( 'returns the global preset variable when the value matches only the global preset', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [ + { + name: 'Red cherry', + slug: 'red-cherry', + color: presetPropertyValue, + }, + ], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { name: 'red', slug: 'red', color: '#ff0000' }, + ], + theme: [], + user: [], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red-cherry' ); + } ); + + it( 'returns the block preset variable when the value matches only the block preset', () => { + const presetPropertyValue = '#ff0000'; + const features = { + color: { + palette: { + core: [ + { + name: 'Red cherry', + slug: 'red-cherry', + color: '#990F02', + }, + ], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + name: 'red', + slug: 'red', + color: presetPropertyValue, + }, + ], + theme: [], + user: [], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red' ); + } ); + + it( 'returns the user-provided preset variable when the value matches in core, theme, and user presets', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red-cherry', + color: presetPropertyValue, + }, + ], + theme: [ + { + slug: 'red-vintage', + color: presetPropertyValue, + }, + ], + user: [ + { slug: 'red', color: presetPropertyValue }, + ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red' ); + } ); + + it( 'returns the user-provided preset variable when the value matches only the user preset', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red-cherry', + color: '#ff0000', + }, + ], + theme: [ + { + slug: 'red-vintage', + color: '#ff0000', + }, + ], + user: [ + { slug: 'red', color: presetPropertyValue }, + ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red' ); + } ); + + it( 'returns the theme-provided preset variable when the value matches both core & theme presets', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red-cherry', + color: presetPropertyValue, + }, + ], + theme: [ + { + slug: 'red-vintage', + color: presetPropertyValue, + }, + ], + user: [ { slug: 'red', color: '#ff0000' } ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red-vintage' ); + } ); + + it( 'returns the theme-provided preset variable when the value matches only the theme preset', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red-cherry', + color: '#ff0000', + }, + ], + theme: [ + { + slug: 'red-vintage', + color: presetPropertyValue, + }, + ], + user: [ { slug: 'red', color: '#ff0000' } ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red-vintage' ); + } ); + + it( 'returns the core-provided preset variable when the value matches only the core preset', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red-cherry', + color: presetPropertyValue, + }, + ], + theme: [ + { + slug: 'red-vintage', + color: '#ff0000', + }, + ], + user: [ { slug: 'red', color: '#ff0000' } ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + expect( result ).toBe( 'var:preset|color|red-cherry' ); + } ); + + it( 'returns the same value when the preset has been overriden by a higher priority origin', () => { + const presetPropertyValue = '#990F02'; + const features = { + color: { + palette: { + core: [], + theme: [], + user: [], + }, + }, + blocks: { + 'core/paragraph': { + color: { + palette: { + core: [ + { + slug: 'red', + color: presetPropertyValue, + }, + ], + theme: [ + { + slug: 'red', + color: presetPropertyValue, + }, + ], + user: [ { slug: 'red', color: '#ff0000' } ], + }, + }, + }, + }, + }; + const blockName = 'core/paragraph'; + const presetPropertyName = 'color'; + const result = getPresetVariableFromValue( + features, + blockName, + presetPropertyName, + presetPropertyValue + ); + // The theme-provided value matches the given presetPropertyValue. + // However, the user has overriden that preset (same slug), + // hence we should ignore the theme-provided preset. + expect( result ).toBe( presetPropertyValue ); + } ); +} );