diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index c1449d6d8b298f..cd4ad0cea50e0d 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -10,7 +10,7 @@ import { } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; import { useContext, useMemo } from '@wordpress/element'; -import { getCSSRules } from '@wordpress/style-engine'; +import { getCSSRules, getCSSValueFromRawStyle } from '@wordpress/style-engine'; import { privateApis as componentsPrivateApis } from '@wordpress/components'; /** @@ -24,7 +24,6 @@ import { scopeFeatureSelectors, appendToSelector, getBlockStyleVariationSelector, - compileStyleValue, getResolvedValue, } from './utils'; import { getBlockCSSSelector } from './get-block-css-selector'; @@ -357,7 +356,7 @@ export function getStylesDeclarations( ? name : kebabCase( name ); declarations.push( - `${ cssProperty }: ${ compileStyleValue( + `${ cssProperty }: ${ getCSSValueFromRawStyle( getValueFromObjectPath( styleValue, [ prop ] ) ) }` ); @@ -369,7 +368,7 @@ export function getStylesDeclarations( ? key : kebabCase( key ); declarations.push( - `${ cssProperty }: ${ compileStyleValue( + `${ cssProperty }: ${ getCSSValueFromRawStyle( getValueFromObjectPath( blockStyles, pathToValue ) ) }` ); diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 8de479e39382e5..4cd93357b081b3 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -7,6 +7,7 @@ import fastDeepEqual from 'fast-deep-equal/es6'; * WordPress dependencies */ import { useViewportMatch } from '@wordpress/compose'; +import { getCSSValueFromRawStyle } from '@wordpress/style-engine'; /** * Internal dependencies @@ -526,34 +527,6 @@ export function getBlockStyleVariationSelector( variation, blockSelector ) { return result.join( ',' ); } -/** - * Converts style preset values `var:` to CSS custom var values. - * TODO: Export and use the style engine util: getCSSVarFromStyleValue(). - * - * Example: - * - * compileStyleValue( 'var:preset|color|primary' ) // returns 'var(--wp--color-primary)' - * - * @param {string} uncompiledValue A block style value. - * @return {string} The compiled, or original value. - */ -export function compileStyleValue( uncompiledValue ) { - const VARIABLE_REFERENCE_PREFIX = 'var:'; - if ( - 'string' === typeof uncompiledValue && - uncompiledValue?.startsWith?.( VARIABLE_REFERENCE_PREFIX ) - ) { - const VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE = '|'; - const VARIABLE_PATH_SEPARATOR_TOKEN_STYLE = '--'; - const variable = uncompiledValue - .slice( VARIABLE_REFERENCE_PREFIX.length ) - .split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE ) - .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); - return `var(--wp--${ variable })`; - } - return uncompiledValue; -} - /** * Looks up a theme file URI based on a relative path. * @@ -591,7 +564,7 @@ export function getResolvedRefValue( ruleValue, tree ) { if ( typeof ruleValue !== 'string' && ruleValue?.ref ) { const refPath = ruleValue.ref.split( '.' ); - const resolvedRuleValue = compileStyleValue( + const resolvedRuleValue = getCSSValueFromRawStyle( getValueFromObjectPath( tree, refPath ) ); diff --git a/packages/style-engine/CHANGELOG.md b/packages/style-engine/CHANGELOG.md index d393e427a63071..42928ac9fbd3c7 100644 --- a/packages/style-engine/CHANGELOG.md +++ b/packages/style-engine/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Style engine: export util to compile CSS custom var from preset string. ([#64490](https://github.com/WordPress/gutenberg/pull/64490)) + ## 2.5.0 (2024-08-07) ## 2.4.0 (2024-07-24) diff --git a/packages/style-engine/README.md b/packages/style-engine/README.md index 44b78eed8a81a6..14e8edbd0dec26 100644 --- a/packages/style-engine/README.md +++ b/packages/style-engine/README.md @@ -258,6 +258,22 @@ _Changelog_ `6.1.0` Introduced in WordPress core. +### getCSSValueFromRawStyle + +Returns a WordPress CSS custom var value from incoming style preset value. The preset value follows the pattern `var:description|context|slug`. + +Example: + +`getCSSValueFromRawStyle( 'var:preset|color|heavenlyBlue' )` // returns 'var(--wp--preset--color--heavenly-blue)' + +_Parameters_ + +- _styleValue_ `string | any`: A raw style value. + +_Returns_ + +- `string | unknown`: A CSS var value. + ## Glossary diff --git a/packages/style-engine/src/index.ts b/packages/style-engine/src/index.ts index fe5b9929877be7..102d5842e7a0be 100644 --- a/packages/style-engine/src/index.ts +++ b/packages/style-engine/src/index.ts @@ -91,3 +91,6 @@ export function getCSSRules( return rules; } + +// Export style utils. +export { getCSSValueFromRawStyle } from './styles/utils'; diff --git a/packages/style-engine/src/styles/test/utils.js b/packages/style-engine/src/styles/test/utils.js new file mode 100644 index 00000000000000..02f0adf494e71f --- /dev/null +++ b/packages/style-engine/src/styles/test/utils.js @@ -0,0 +1,54 @@ +/** + * Internal dependencies + */ +import { camelCaseJoin, getCSSValueFromRawStyle, upperFirst } from '../utils'; + +describe( 'utils', () => { + describe( 'upperFirst()', () => { + it( 'should return an string with a capitalized first letter', () => { + expect( upperFirst( 'toontown' ) ).toEqual( 'Toontown' ); + } ); + } ); + + describe( 'camelCaseJoin()', () => { + it( 'should return a camelCase string', () => { + expect( camelCaseJoin( [ 'toon', 'town' ] ) ).toEqual( 'toonTown' ); + } ); + } ); + + describe( 'getCSSValueFromRawStyle()', () => { + it.each( [ + [ 'min(40%, 400px)', 'min(40%, 400px)' ], + [ + 'var(--wp--preset--color--yellow-bun)', + 'var:preset|color|yellow-bun', + ], + [ 'var(--wp--preset--font-size--h-1)', 'var:preset|font-size|h1' ], + [ + 'var(--wp--preset--font-size--1-px)', + 'var:preset|font-size|1px', + ], + [ + 'var(--wp--preset--color--orange-11-orange)', + 'var:preset|color|orange11orange', + ], + [ + 'var(--wp--preset--color--heavenly-blue)', + 'var:preset|color|heavenlyBlue', + ], + [ + 'var(--wp--preset--background--dark-secrets-100)', + 'var:preset|background|dark_Secrets_100', + ], + [ null, null ], + [ false, false ], + [ 1000, 1000 ], + [ undefined, undefined ], + ] )( + 'should return %s using an incoming value of %s', + ( expected, value ) => { + expect( getCSSValueFromRawStyle( value ) ).toEqual( expected ); + } + ); + } ); +} ); diff --git a/packages/style-engine/src/styles/utils.ts b/packages/style-engine/src/styles/utils.ts index 00e9dab8b5892b..0c9b40c384b101 100644 --- a/packages/style-engine/src/styles/utils.ts +++ b/packages/style-engine/src/styles/utils.ts @@ -61,7 +61,7 @@ export function generateRule( { selector: options?.selector, key: ruleKey, - value: getCSSVarFromStyleValue( styleValue ), + value: getCSSValueFromRawStyle( styleValue ), }, ] : []; @@ -103,7 +103,7 @@ export function generateBoxRules( } else { const sideRules = individualProperties.reduce( ( acc: GeneratedCSSRule[], side: string ) => { - const value: string | undefined = getCSSVarFromStyleValue( + const value = getCSSValueFromRawStyle( getStyleValueByPath( boxStyle, [ side ] ) ); if ( value ) { @@ -127,13 +127,21 @@ export function generateBoxRules( } /** - * Returns a CSS var value from incoming style value following the pattern `var:description|context|slug`. + * Returns a WordPress CSS custom var value from incoming style preset value. + * The preset value follows the pattern `var:description|context|slug`. + * + * Example: + * + * `getCSSValueFromRawStyle( 'var:preset|color|heavenlyBlue' )` // returns 'var(--wp--preset--color--heavenly-blue)' * * @param styleValue A raw style value. * - * @return string A CSS var value. + * @return A CSS var value. */ -export function getCSSVarFromStyleValue( styleValue: string ): string { + +export function getCSSValueFromRawStyle( + styleValue: string | any +): string | unknown { if ( typeof styleValue === 'string' && styleValue.startsWith( VARIABLE_REFERENCE_PREFIX ) diff --git a/packages/style-engine/src/test/utils.js b/packages/style-engine/src/test/utils.js deleted file mode 100644 index 9f1f84d2b45310..00000000000000 --- a/packages/style-engine/src/test/utils.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Internal dependencies - */ -import { - camelCaseJoin, - getCSSVarFromStyleValue, - upperFirst, -} from '../styles/utils'; - -describe( 'utils', () => { - describe( 'upperFirst()', () => { - it( 'should return an string with a capitalized first letter', () => { - expect( upperFirst( 'toontown' ) ).toEqual( 'Toontown' ); - } ); - } ); - - describe( 'camelCaseJoin()', () => { - it( 'should return a camelCase string', () => { - expect( camelCaseJoin( [ 'toon', 'town' ] ) ).toEqual( 'toonTown' ); - } ); - } ); - - describe( 'getCSSVarFromStyleValue()', () => { - it( 'should return a compiled CSS var', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|yellow-bun' ) - ).toEqual( 'var(--wp--preset--color--yellow-bun)' ); - } ); - - it( 'should kebab case numbers', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|font-size|h1' ) - ).toEqual( 'var(--wp--preset--font-size--h-1)' ); - } ); - - it( 'should kebab case numbers as prefix', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|font-size|1px' ) - ).toEqual( 'var(--wp--preset--font-size--1-px)' ); - } ); - - it( 'should kebab case both sides of numbers', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|orange11orange' ) - ).toEqual( 'var(--wp--preset--color--orange-11-orange)' ); - } ); - - it( 'should kebab case camel case', () => { - expect( - getCSSVarFromStyleValue( 'var:preset|color|heavenlyBlue' ) - ).toEqual( 'var(--wp--preset--color--heavenly-blue)' ); - } ); - - it( 'should kebab case underscores', () => { - expect( - getCSSVarFromStyleValue( - 'var:preset|background|dark_Secrets_100' - ) - ).toEqual( 'var(--wp--preset--background--dark-secrets-100)' ); - } ); - } ); -} ); diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 5b361836a8e375..8de623fcfcb2bf 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -94,7 +94,7 @@ export interface StyleOptions { export interface GeneratedCSSRule { selector?: string; - value: string; + value: string | unknown; /** * The CSS key in JS style attribute format, compatible with React. * E.g. `paddingTop` instead of `padding-top`.