diff --git a/package-lock.json b/package-lock.json
index e5095432624b79..c196eed47005ed 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17416,6 +17416,7 @@
"@wordpress/dom": "file:packages/dom",
"@wordpress/element": "file:packages/element",
"@wordpress/escape-html": "file:packages/escape-html",
+ "@wordpress/experiments": "file:packages/experiments",
"@wordpress/hooks": "file:packages/hooks",
"@wordpress/html-entities": "file:packages/html-entities",
"@wordpress/i18n": "file:packages/i18n",
@@ -17886,6 +17887,7 @@
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/editor": "file:packages/editor",
"@wordpress/element": "file:packages/element",
+ "@wordpress/experiments": "file:packages/experiments",
"@wordpress/hooks": "file:packages/hooks",
"@wordpress/html-entities": "file:packages/html-entities",
"@wordpress/i18n": "file:packages/i18n",
diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md
index 5a861eaa1acad7..7ccac465a336a1 100644
--- a/packages/block-editor/README.md
+++ b/packages/block-editor/README.md
@@ -348,6 +348,10 @@ _Returns_
Undocumented declaration.
+### experiments
+
+Experimental @wordpress/block-editor APIs.
+
### FontSizePicker
_Related_
diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json
index d33c015ad77dd4..00e570a3fefc42 100644
--- a/packages/block-editor/package.json
+++ b/packages/block-editor/package.json
@@ -45,6 +45,7 @@
"@wordpress/dom": "file:../dom",
"@wordpress/element": "file:../element",
"@wordpress/escape-html": "file:../escape-html",
+ "@wordpress/experiments": "file:../experiments",
"@wordpress/hooks": "file:../hooks",
"@wordpress/html-entities": "file:../html-entities",
"@wordpress/i18n": "file:../i18n",
diff --git a/packages/block-editor/src/components/global-styles/README.md b/packages/block-editor/src/components/global-styles/README.md
new file mode 100644
index 00000000000000..dc4d52eaff4d0b
--- /dev/null
+++ b/packages/block-editor/src/components/global-styles/README.md
@@ -0,0 +1,78 @@
+# Global Styles
+
+This folder contains all the necessary APIs to manipulate the global styles data. It can be potentially extracted to its own package.
+
+# Available public APIs
+
+## useGlobalStylesReset
+
+A React hook used to retrieve whether the Global Styles have been edited and a callback to reset to the default theme values.
+
+```js
+import { useGlobalStylesReset } from '@wordpress/block-editor';
+
+function MyComponent() {
+ const [ canReset, reset ] = useGlobalStylesReset();
+
+ return canReset
+ ?
+ : null;
+}
+```
+
+## useGlobalStylesOutput
+
+A React hook used to retrieve the styles array and settings to provide for block editor instances based on the current global styles.
+
+```js
+import { useGlobalStylesOutput, BlockEditorProvider, BlockList } from '@wordpress/block-editor';
+
+function MyComponent() {
+ const [ styles, settings ] = useGlobalStylesOutput();
+
+ return
+
+
+}
+```
+
+## useGlobalStyle
+
+A react hook used to retrieve the style applied to a given context.
+
+```js
+import { useGlobalStyle } from '@wordpress/block-editor';
+
+function MyComponent() {
+ // Text color for the site root.
+ const [ color, setColor ] = useGlobalStyle( 'color.text' );
+
+ // The user modified color for the core paragraph block.
+ const [ pColor, setPColor ] = useGlobalStyle( 'color.text', 'core/paragraph', 'user' );
+
+ return "Something";
+}
+```
+
+## useGlobalSetting
+
+A react hook used to retrieve the setting applied to a given context.
+
+```js
+import { useGlobalSetting } from '@wordpress/block-editor';
+
+function MyComponent() {
+ // The default color palette.
+ const [ colorPalette, setColorPalette ] = useGlobalSetting( 'color.palette' );
+
+ // The base (theme + core) color palette for the paragraph block,
+ // ignoring user provided palette.
+ // If the palette is not defined for the paragraph block, the root one is returned.
+ const [ pColor, setPColor ] = useGlobalSetting( 'color.palette', 'core/paragraph', 'base' );
+
+ return "Something";
+}
+```
diff --git a/packages/edit-site/src/components/global-styles/context.js b/packages/block-editor/src/components/global-styles/context.js
similarity index 100%
rename from packages/edit-site/src/components/global-styles/context.js
rename to packages/block-editor/src/components/global-styles/context.js
diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js
new file mode 100644
index 00000000000000..776b83b71aa4d9
--- /dev/null
+++ b/packages/block-editor/src/components/global-styles/hooks.js
@@ -0,0 +1,157 @@
+/**
+ * External dependencies
+ */
+import fastDeepEqual from 'fast-deep-equal/es6';
+import { get, set } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { useContext, useCallback } from '@wordpress/element';
+import { __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE } from '@wordpress/blocks';
+
+/**
+ * Internal dependencies
+ */
+import { getValueFromVariable, getPresetVariableFromValue } from './utils';
+import { GlobalStylesContext } from './context';
+
+const EMPTY_CONFIG = { settings: {}, styles: {} };
+
+export const useGlobalStylesReset = () => {
+ const { user: config, setUserConfig } = useContext( GlobalStylesContext );
+ const canReset = !! config && ! fastDeepEqual( config, EMPTY_CONFIG );
+ return [
+ canReset,
+ useCallback(
+ () => setUserConfig( () => EMPTY_CONFIG ),
+ [ setUserConfig ]
+ ),
+ ];
+};
+
+export function useGlobalSetting( path, blockName, source = 'all' ) {
+ const {
+ merged: mergedConfig,
+ base: baseConfig,
+ user: userConfig,
+ setUserConfig,
+ } = useContext( GlobalStylesContext );
+
+ const fullPath = ! blockName
+ ? `settings.${ path }`
+ : `settings.blocks.${ blockName }.${ path }`;
+
+ const setSetting = ( newValue ) => {
+ setUserConfig( ( currentConfig ) => {
+ // Deep clone `currentConfig` to avoid mutating it later.
+ const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
+ const pathToSet = PATHS_WITH_MERGE[ path ]
+ ? fullPath + '.custom'
+ : fullPath;
+ set( newUserConfig, pathToSet, newValue );
+
+ return newUserConfig;
+ } );
+ };
+
+ const getSettingValueForContext = ( name ) => {
+ const currentPath = ! name
+ ? `settings.${ path }`
+ : `settings.blocks.${ name }.${ path }`;
+
+ const getSettingValue = ( configToUse ) => {
+ const result = get( configToUse, currentPath );
+ if ( PATHS_WITH_MERGE[ path ] ) {
+ return result?.custom ?? result?.theme ?? result?.default;
+ }
+ return result;
+ };
+
+ let result;
+ switch ( source ) {
+ case 'all':
+ result = getSettingValue( mergedConfig );
+ break;
+ case 'user':
+ result = getSettingValue( userConfig );
+ break;
+ case 'base':
+ result = getSettingValue( baseConfig );
+ break;
+ default:
+ throw 'Unsupported source';
+ }
+
+ return result;
+ };
+
+ // Unlike styles settings get inherited from top level settings.
+ const resultWithFallback =
+ getSettingValueForContext( blockName ) ?? getSettingValueForContext();
+
+ return [ resultWithFallback, setSetting ];
+}
+
+export function useGlobalStyle( path, blockName, source = 'all' ) {
+ const {
+ merged: mergedConfig,
+ base: baseConfig,
+ user: userConfig,
+ setUserConfig,
+ } = useContext( GlobalStylesContext );
+ const finalPath = ! blockName
+ ? `styles.${ path }`
+ : `styles.blocks.${ blockName }.${ path }`;
+
+ const setStyle = ( newValue ) => {
+ setUserConfig( ( currentConfig ) => {
+ // Deep clone `currentConfig` to avoid mutating it later.
+ const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
+ set(
+ newUserConfig,
+ finalPath,
+ getPresetVariableFromValue(
+ mergedConfig.settings,
+ blockName,
+ path,
+ newValue
+ )
+ );
+ return newUserConfig;
+ } );
+ };
+
+ let result;
+ switch ( source ) {
+ case 'all':
+ result = getValueFromVariable(
+ mergedConfig,
+ blockName,
+ // The stlyes.css path is allowed to be empty, so don't revert to base if undefined.
+ finalPath === 'styles.css'
+ ? get( userConfig, finalPath )
+ : get( userConfig, finalPath ) ??
+ get( baseConfig, finalPath )
+ );
+ break;
+ case 'user':
+ result = getValueFromVariable(
+ mergedConfig,
+ blockName,
+ get( userConfig, finalPath )
+ );
+ break;
+ case 'base':
+ result = getValueFromVariable(
+ baseConfig,
+ blockName,
+ get( baseConfig, finalPath )
+ );
+ break;
+ default:
+ throw 'Unsupported source';
+ }
+
+ return [ result, setStyle ];
+}
diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js
new file mode 100644
index 00000000000000..cd0c8cdf487c55
--- /dev/null
+++ b/packages/block-editor/src/components/global-styles/index.js
@@ -0,0 +1,7 @@
+export {
+ useGlobalStylesReset,
+ useGlobalSetting,
+ useGlobalStyle,
+} from './hooks';
+export { useGlobalStylesOutput } from './use-global-styles-output';
+export { GlobalStylesContext } from './context';
diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/block-editor/src/components/global-styles/test/typography-utils.js
similarity index 100%
rename from packages/edit-site/src/components/global-styles/test/typography-utils.js
rename to packages/block-editor/src/components/global-styles/test/typography-utils.js
diff --git a/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js
similarity index 100%
rename from packages/edit-site/src/components/global-styles/test/use-global-styles-output.js
rename to packages/block-editor/src/components/global-styles/test/use-global-styles-output.js
diff --git a/packages/edit-site/src/components/global-styles/test/utils.js b/packages/block-editor/src/components/global-styles/test/utils.js
similarity index 100%
rename from packages/edit-site/src/components/global-styles/test/utils.js
rename to packages/block-editor/src/components/global-styles/test/utils.js
diff --git a/packages/edit-site/src/components/global-styles/typography-utils.js b/packages/block-editor/src/components/global-styles/typography-utils.js
similarity index 96%
rename from packages/edit-site/src/components/global-styles/typography-utils.js
rename to packages/block-editor/src/components/global-styles/typography-utils.js
index 5720fdeb6ce91e..bfbc2569211c3d 100644
--- a/packages/edit-site/src/components/global-styles/typography-utils.js
+++ b/packages/block-editor/src/components/global-styles/typography-utils.js
@@ -5,9 +5,9 @@
*/
/**
- * WordPress dependencies
+ * Internal dependencies
*/
-import { getComputedFluidTypographyValue } from '@wordpress/block-editor';
+import { getComputedFluidTypographyValue } from '../font-sizes/fluid-utils';
/**
* @typedef {Object} FluidPreset
diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
similarity index 99%
rename from packages/edit-site/src/components/global-styles/use-global-styles-output.js
rename to packages/block-editor/src/components/global-styles/use-global-styles-output.js
index 080148b926559f..cc7dc5c6669fdb 100644
--- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -15,11 +15,6 @@ import {
import { useSelect } from '@wordpress/data';
import { useContext, useMemo } from '@wordpress/element';
import { getCSSRules } from '@wordpress/style-engine';
-import {
- __unstablePresetDuotoneFilter as PresetDuotoneFilter,
- __experimentalGetGapCSSValue as getGapCSSValue,
- store as blockEditorStore,
-} from '@wordpress/block-editor';
/**
* Internal dependencies
@@ -27,7 +22,10 @@ import {
import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils';
import { getTypographyFontSizeValue } from './typography-utils';
import { GlobalStylesContext } from './context';
-import { useSetting } from './hooks';
+import { useGlobalSetting } from './hooks';
+import { PresetDuotoneFilter } from '../duotone/components';
+import { getGapCSSValue } from '../../hooks/gap';
+import { store as blockEditorStore } from '../../store';
// List of block support features that can have their related styles
// generated under their own feature level selector rather than the block's.
@@ -999,7 +997,7 @@ function updateConfigWithSeparator( config ) {
export function useGlobalStylesOutput() {
let { merged: mergedConfig } = useContext( GlobalStylesContext );
- const [ blockGap ] = useSetting( 'spacing.blockGap' );
+ const [ blockGap ] = useGlobalSetting( 'spacing.blockGap' );
const hasBlockGapSupport = blockGap !== null;
const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support.
const disableLayoutStyles = useSelect( ( select ) => {
diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js
new file mode 100644
index 00000000000000..e3c3bf47d4a5a3
--- /dev/null
+++ b/packages/block-editor/src/components/global-styles/utils.js
@@ -0,0 +1,366 @@
+/**
+ * External dependencies
+ */
+import { get } from 'lodash';
+
+/**
+ * Internal dependencies
+ */
+import { getTypographyFontSizeValue } from './typography-utils';
+
+/* Supporting data. */
+export const ROOT_BLOCK_NAME = 'root';
+export const ROOT_BLOCK_SELECTOR = 'body';
+export const ROOT_BLOCK_SUPPORTS = [
+ 'background',
+ 'backgroundColor',
+ 'color',
+ 'linkColor',
+ 'buttonColor',
+ 'fontFamily',
+ 'fontSize',
+ 'fontStyle',
+ 'fontWeight',
+ 'lineHeight',
+ 'textDecoration',
+ 'textTransform',
+ 'padding',
+];
+
+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: [ 'color', 'duotone' ],
+ cssVarInfix: 'duotone',
+ valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`,
+ classes: [],
+ },
+ {
+ path: [ 'typography', 'fontSizes' ],
+ valueFunc: ( preset, { typography: typographySettings } ) =>
+ getTypographyFontSizeValue( preset, typographySettings ),
+ valueKey: 'size',
+ cssVarInfix: 'font-size',
+ classes: [ { classSuffix: 'font-size', propertyName: 'font-size' } ],
+ },
+ {
+ path: [ 'typography', 'fontFamilies' ],
+ valueKey: 'fontFamily',
+ cssVarInfix: 'font-family',
+ classes: [
+ { classSuffix: 'font-family', propertyName: 'font-family' },
+ ],
+ },
+ {
+ path: [ 'spacing', 'spacingSizes' ],
+ valueKey: 'size',
+ cssVarInfix: 'spacing',
+ valueFunc: ( { size } ) => size,
+ classes: [],
+ },
+];
+
+export const STYLE_PATH_TO_CSS_VAR_INFIX = {
+ 'color.background': 'color',
+ 'color.text': 'color',
+ 'elements.link.color.text': 'color',
+ 'elements.link.:hover.color.text': 'color',
+ 'elements.link.typography.fontFamily': 'font-family',
+ 'elements.link.typography.fontSize': 'font-size',
+ 'elements.button.color.text': 'color',
+ 'elements.button.color.background': 'color',
+ 'elements.button.typography.fontFamily': 'font-family',
+ 'elements.button.typography.fontSize': 'font-size',
+ 'elements.heading.color': 'color',
+ 'elements.heading.color.background': 'color',
+ 'elements.heading.typography.fontFamily': 'font-family',
+ 'elements.heading.gradient': 'gradient',
+ 'elements.heading.color.gradient': 'gradient',
+ 'elements.h1.color': 'color',
+ 'elements.h1.color.background': 'color',
+ 'elements.h1.typography.fontFamily': 'font-family',
+ 'elements.h1.color.gradient': 'gradient',
+ 'elements.h2.color': 'color',
+ 'elements.h2.color.background': 'color',
+ 'elements.h2.typography.fontFamily': 'font-family',
+ 'elements.h2.color.gradient': 'gradient',
+ 'elements.h3.color': 'color',
+ 'elements.h3.color.background': 'color',
+ 'elements.h3.typography.fontFamily': 'font-family',
+ 'elements.h3.color.gradient': 'gradient',
+ 'elements.h4.color': 'color',
+ 'elements.h4.color.background': 'color',
+ 'elements.h4.typography.fontFamily': 'font-family',
+ 'elements.h4.color.gradient': 'gradient',
+ 'elements.h5.color': 'color',
+ 'elements.h5.color.background': 'color',
+ 'elements.h5.typography.fontFamily': 'font-family',
+ 'elements.h5.color.gradient': 'gradient',
+ 'elements.h6.color': 'color',
+ 'elements.h6.color.background': 'color',
+ 'elements.h6.typography.fontFamily': 'font-family',
+ 'elements.h6.color.gradient': 'gradient',
+ 'color.gradient': 'gradient',
+ 'typography.fontSize': 'font-size',
+ 'typography.fontFamily': 'font-family',
+};
+
+// A static list of block attributes that store global style preset slugs.
+export const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = {
+ 'color.background': 'backgroundColor',
+ 'color.text': 'textColor',
+ 'color.gradient': 'gradient',
+ 'typography.fontSize': 'fontSize',
+ 'typography.fontFamily': 'fontFamily',
+};
+
+function findInPresetsBy(
+ features,
+ blockName,
+ presetPath,
+ presetProperty,
+ presetValueValue
+) {
+ // Block presets take priority above root level presets.
+ const orderedPresetsByOrigin = [
+ get( features, [ 'blocks', blockName, ...presetPath ] ),
+ get( features, presetPath ),
+ ];
+
+ for ( const presetByOrigin of orderedPresetsByOrigin ) {
+ if ( presetByOrigin ) {
+ // Preset origins ordered by priority.
+ const origins = [ 'custom', 'theme', 'default' ];
+ for ( const origin of origins ) {
+ const presets = presetByOrigin[ origin ];
+ if ( presets ) {
+ const presetObject = presets.find(
+ ( 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,
+ blockName,
+ presetPath,
+ 'slug',
+ presetObject.slug
+ );
+ if (
+ highestPresetObjectWithSameSlug[
+ presetProperty
+ ] === presetObject[ presetProperty ]
+ ) {
+ return presetObject;
+ }
+ return undefined;
+ }
+ }
+ }
+ }
+ }
+}
+
+export function getPresetVariableFromValue(
+ features,
+ blockName,
+ variableStylePath,
+ presetPropertyValue
+) {
+ if ( ! presetPropertyValue ) {
+ return presetPropertyValue;
+ }
+
+ const cssVarInfix = STYLE_PATH_TO_CSS_VAR_INFIX[ variableStylePath ];
+
+ const metadata = PRESET_METADATA.find(
+ ( data ) => data.cssVarInfix === cssVarInfix
+ );
+
+ if ( ! metadata ) {
+ // The property doesn't have preset data
+ // so the value should be returned as it is.
+ return presetPropertyValue;
+ }
+ const { valueKey, path } = metadata;
+
+ const presetObject = findInPresetsBy(
+ features,
+ blockName,
+ path,
+ valueKey,
+ presetPropertyValue
+ );
+
+ if ( ! presetObject ) {
+ // Value wasn't found in the presets,
+ // so it must be a custom value.
+ return presetPropertyValue;
+ }
+
+ return `var:preset|${ cssVarInfix }|${ presetObject.slug }`;
+}
+
+function getValueFromPresetVariable(
+ features,
+ blockName,
+ variable,
+ [ presetType, slug ]
+) {
+ const metadata = PRESET_METADATA.find(
+ ( data ) => data.cssVarInfix === presetType
+ );
+ if ( ! metadata ) {
+ return variable;
+ }
+
+ const presetObject = findInPresetsBy(
+ features.settings,
+ blockName,
+ metadata.path,
+ 'slug',
+ slug
+ );
+
+ if ( presetObject ) {
+ const { valueKey } = metadata;
+ const result = presetObject[ valueKey ];
+ return getValueFromVariable( features, blockName, result );
+ }
+
+ return variable;
+}
+
+function getValueFromCustomVariable( features, blockName, variable, path ) {
+ const result =
+ get( features.settings, [ 'blocks', blockName, 'custom', ...path ] ) ??
+ get( features.settings, [ 'custom', ...path ] );
+ if ( ! result ) {
+ return variable;
+ }
+ // A variable may reference another variable so we need recursion until we find the value.
+ return getValueFromVariable( features, blockName, result );
+}
+
+/**
+ * Attempts to fetch the value of a theme.json CSS variable.
+ *
+ * @param {Object} features GlobalStylesContext config, e.g., user, base or merged. Represents the theme.json tree.
+ * @param {string} blockName The name of a block as represented in the styles property. E.g., 'root' for root-level, and 'core/${blockName}' for blocks.
+ * @param {string|*} variable An incoming style value. A CSS var value is expected, but it could be any value.
+ * @return {string|*|{ref}} The value of the CSS var, if found. If not found, the passed variable argument.
+ */
+export function getValueFromVariable( features, blockName, variable ) {
+ if ( ! variable || typeof variable !== 'string' ) {
+ if ( variable?.ref && typeof variable?.ref === 'string' ) {
+ const refPath = variable.ref.split( '.' );
+ variable = get( features, refPath );
+ // Presence of another ref indicates a reference to another dynamic value.
+ // Pointing to another dynamic value is not supported.
+ if ( ! variable || !! variable?.ref ) {
+ return variable;
+ }
+ } else {
+ return variable;
+ }
+ }
+ const USER_VALUE_PREFIX = 'var:';
+ const THEME_VALUE_PREFIX = 'var(--wp--';
+ const THEME_VALUE_SUFFIX = ')';
+
+ let parsedVar;
+
+ if ( variable.startsWith( USER_VALUE_PREFIX ) ) {
+ parsedVar = variable.slice( USER_VALUE_PREFIX.length ).split( '|' );
+ } else if (
+ variable.startsWith( THEME_VALUE_PREFIX ) &&
+ variable.endsWith( THEME_VALUE_SUFFIX )
+ ) {
+ parsedVar = variable
+ .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) )`
+ return variable;
+ }
+
+ const [ type, ...path ] = parsedVar;
+ if ( type === 'preset' ) {
+ return getValueFromPresetVariable(
+ features,
+ blockName,
+ variable,
+ path
+ );
+ }
+ if ( type === 'custom' ) {
+ return getValueFromCustomVariable(
+ features,
+ blockName,
+ variable,
+ path
+ );
+ }
+ return variable;
+}
+
+/**
+ * Function that scopes a selector with another one. This works a bit like
+ * SCSS nesting except the `&` operator isn't supported.
+ *
+ * @example
+ * ```js
+ * const scope = '.a, .b .c';
+ * const selector = '> .x, .y';
+ * const merged = scopeSelector( scope, selector );
+ * // merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
+ * ```
+ *
+ * @param {string} scope Selector to scope to.
+ * @param {string} selector Original selector.
+ *
+ * @return {string} Scoped selector.
+ */
+export function scopeSelector( scope, selector ) {
+ const scopes = scope.split( ',' );
+ const selectors = selector.split( ',' );
+
+ const selectorsScoped = [];
+ scopes.forEach( ( outer ) => {
+ selectors.forEach( ( inner ) => {
+ selectorsScoped.push( `${ outer.trim() } ${ inner.trim() }` );
+ } );
+ } );
+
+ return selectorsScoped.join( ', ' );
+}
diff --git a/packages/block-editor/src/experiments.js b/packages/block-editor/src/experiments.js
new file mode 100644
index 00000000000000..b217e14ec273be
--- /dev/null
+++ b/packages/block-editor/src/experiments.js
@@ -0,0 +1,23 @@
+/**
+ * WordPress dependencies
+ */
+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/experiments';
+
+/**
+ * Internal dependencies
+ */
+import * as globalStyles from './components/global-styles';
+
+export const { lock, unlock } =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
+ '@wordpress/block-editor'
+ );
+
+/**
+ * Experimental @wordpress/block-editor APIs.
+ */
+export const experiments = {};
+lock( experiments, {
+ ...globalStyles,
+} );
diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js
index 1c81c910b21e12..d883aa455bc8f3 100644
--- a/packages/block-editor/src/index.js
+++ b/packages/block-editor/src/index.js
@@ -20,3 +20,4 @@ export * from './elements';
export * from './utils';
export { storeConfig, store } from './store';
export { SETTINGS_DEFAULTS } from './store/defaults';
+export { experiments } from './experiments';
diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json
index f3a8e8d72edd49..dc1ba91a20f142 100644
--- a/packages/edit-site/package.json
+++ b/packages/edit-site/package.json
@@ -39,6 +39,7 @@
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/editor": "file:../editor",
"@wordpress/element": "file:../element",
+ "@wordpress/experiments": "file:../experiments",
"@wordpress/hooks": "file:../hooks",
"@wordpress/html-entities": "file:../html-entities",
"@wordpress/i18n": "file:../i18n",
diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js
index 6dc3bbd9c4a975..5cc592131c6b8b 100644
--- a/packages/edit-site/src/components/global-styles-renderer/index.js
+++ b/packages/edit-site/src/components/global-styles-renderer/index.js
@@ -3,16 +3,15 @@
*/
import { useEffect } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';
+import { unlock } from '../../experiments';
-/**
- * Internal dependencies
- */
-import { useGlobalStylesOutput } from '../global-styles/use-global-styles-output';
+const { useGlobalStylesOutput } = unlock( blockEditorExperiments );
function useGlobalStylesRenderer() {
const [ styles, settings, svgFilters ] = useGlobalStylesOutput();
diff --git a/packages/edit-site/src/components/global-styles/README.md b/packages/edit-site/src/components/global-styles/README.md
index ac728f3eb8bf52..9077b9e468d383 100644
--- a/packages/edit-site/src/components/global-styles/README.md
+++ b/packages/edit-site/src/components/global-styles/README.md
@@ -1,6 +1,6 @@
# Global Styles
-This folder contains all the necessary APIs to render the global styles UI and to manipulate the global styles data. It can be potentially extracted to its own package.
+This folder contains the global styles UI.
# Available public APIs
@@ -15,77 +15,3 @@ function MyComponent() {
return ;
}
```
-
-## useGlobalStylesReset
-
-A React hook used to retrieve whether the Global Styles have been edited and a callback to reset to the default theme values.
-
-```js
-import { useGlobalStylesReset } from './global-styles';
-
-function MyComponent() {
- const [ canReset, reset ] = useGlobalStylesReset();
-
- return canReset
- ?
- : null;
-}
-```
-
-## useGlobalStylesOutput
-
-A React hook used to retrieve the styles array and settings to provide for block editor instances based on the current global styles.
-
-```js
-import { useGlobalStylesOutput } from './global-styles';
-import { BlockEditorProvider, BlockList } from '@wordpress/block-editor';
-
-function MyComponent() {
- const [ styles, settings ] = useGlobalStylesOutput();
-
- return
-
-
-}
-```
-
-## useStyle
-
-A react hook used to retrieve the style applied to a given context.
-
-```js
-import { useStyle } from './global-styles';
-
-function MyComponent() {
- // Text color for the site root.
- const [ color, setColor ] = useStyle( 'color.text' );
-
- // The user modified color for the core paragraph block.
- const [ pColor, setPColor ] = useStyle( 'color.text', 'core/paragraph', 'user' );
-
- return "Something";
-}
-```
-
-## useSetting
-
-A react hook used to retrieve the setting applied to a given context.
-
-```js
-import { useSetting } from './global-styles';
-
-function MyComponent() {
- // The default color palette.
- const [ colorPalette, setColorPalette ] = useSetting( 'color.palette' );
-
- // The base (theme + core) color palette for the paragraph block,
- // ignoring user provided palette.
- // If the palette is not defined for the paragraph block, the root one is returned.
- const [ pColor, setPColor ] = useSetting( 'color.palette', 'core/paragraph', 'base' );
-
- return "Something";
-}
-```
diff --git a/packages/edit-site/src/components/global-styles/border-panel.js b/packages/edit-site/src/components/global-styles/border-panel.js
index 91d467dfb13fdd..cc38d09b4c716a 100644
--- a/packages/edit-site/src/components/global-styles/border-panel.js
+++ b/packages/edit-site/src/components/global-styles/border-panel.js
@@ -1,7 +1,10 @@
/**
* WordPress dependencies
*/
-import { __experimentalBorderRadiusControl as BorderRadiusControl } from '@wordpress/block-editor';
+import {
+ __experimentalBorderRadiusControl as BorderRadiusControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
import {
__experimentalBorderBoxControl as BorderBoxControl,
__experimentalHasSplitBorders as hasSplitBorders,
@@ -15,12 +18,10 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import {
- getSupportedGlobalStylesPanels,
- useColorsPerOrigin,
- useSetting,
- useStyle,
-} from './hooks';
+import { getSupportedGlobalStylesPanels, useColorsPerOrigin } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
export function useHasBorderPanel( name ) {
const controls = [
@@ -36,7 +37,7 @@ export function useHasBorderPanel( name ) {
function useHasBorderColorControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
- useSetting( 'border.color', name )[ 0 ] &&
+ useGlobalSetting( 'border.color', name )[ 0 ] &&
supports.includes( 'borderColor' )
);
}
@@ -44,7 +45,7 @@ function useHasBorderColorControl( name ) {
function useHasBorderRadiusControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
- useSetting( 'border.radius', name )[ 0 ] &&
+ useGlobalSetting( 'border.radius', name )[ 0 ] &&
supports.includes( 'borderRadius' )
);
}
@@ -52,7 +53,7 @@ function useHasBorderRadiusControl( name ) {
function useHasBorderStyleControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
- useSetting( 'border.style', name )[ 0 ] &&
+ useGlobalSetting( 'border.style', name )[ 0 ] &&
supports.includes( 'borderStyle' )
);
}
@@ -60,7 +61,7 @@ function useHasBorderStyleControl( name ) {
function useHasBorderWidthControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
- useSetting( 'border.width', name )[ 0 ] &&
+ useGlobalSetting( 'border.width', name )[ 0 ] &&
supports.includes( 'borderWidth' )
);
}
@@ -97,12 +98,15 @@ function applyAllFallbackStyles( border ) {
export default function BorderPanel( { name, variationPath = '' } ) {
// To better reflect if the user has customized a value we need to
// ensure the style value being checked is from the `user` origin.
- const [ userBorderStyles ] = useStyle(
+ const [ userBorderStyles ] = useGlobalStyle(
`${ variationPath }border`,
name,
'user'
);
- const [ border, setBorder ] = useStyle( `${ variationPath }border`, name );
+ const [ border, setBorder ] = useGlobalStyle(
+ `${ variationPath }border`,
+ name
+ );
const colors = useColorsPerOrigin( name );
const showBorderColor = useHasBorderColorControl( name );
@@ -111,7 +115,7 @@ export default function BorderPanel( { name, variationPath = '' } ) {
// Border radius.
const showBorderRadius = useHasBorderRadiusControl( name );
- const [ borderRadiusValues, setBorderRadius ] = useStyle(
+ const [ borderRadiusValues, setBorderRadius ] = useGlobalStyle(
`${ variationPath }border.radius`,
name
);
diff --git a/packages/edit-site/src/components/global-styles/color-palette-panel.js b/packages/edit-site/src/components/global-styles/color-palette-panel.js
index fd2c10568de216..f29adec52b5cec 100644
--- a/packages/edit-site/src/components/global-styles/color-palette-panel.js
+++ b/packages/edit-site/src/components/global-styles/color-palette-panel.js
@@ -6,37 +6,40 @@ import {
__experimentalVStack as VStack,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { useSetting } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting } = unlock( blockEditorExperiments );
export default function ColorPalettePanel( { name } ) {
- const [ themeColors, setThemeColors ] = useSetting(
+ const [ themeColors, setThemeColors ] = useGlobalSetting(
'color.palette.theme',
name
);
- const [ baseThemeColors ] = useSetting(
+ const [ baseThemeColors ] = useGlobalSetting(
'color.palette.theme',
name,
'base'
);
- const [ defaultColors, setDefaultColors ] = useSetting(
+ const [ defaultColors, setDefaultColors ] = useGlobalSetting(
'color.palette.default',
name
);
- const [ baseDefaultColors ] = useSetting(
+ const [ baseDefaultColors ] = useGlobalSetting(
'color.palette.default',
name,
'base'
);
- const [ customColors, setCustomColors ] = useSetting(
+ const [ customColors, setCustomColors ] = useGlobalSetting(
'color.palette.custom',
name
);
- const [ defaultPaletteEnabled ] = useSetting(
+ const [ defaultPaletteEnabled ] = useGlobalSetting(
'color.defaultPalette',
name
);
diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js
index 34ec3101410ba3..944ec4afb8bb1e 100644
--- a/packages/edit-site/src/components/global-styles/custom-css.js
+++ b/packages/edit-site/src/components/global-styles/custom-css.js
@@ -8,15 +8,18 @@ import {
PanelBody,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { useStyle } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalStyle } = unlock( blockEditorExperiments );
function CustomCSSControl() {
- const [ customCSS, setCustomCSS ] = useStyle( 'css' );
- const [ themeCSS ] = useStyle( 'css', null, 'base' );
+ const [ customCSS, setCustomCSS ] = useGlobalStyle( 'css' );
+ const [ themeCSS ] = useGlobalStyle( 'css', null, 'base' );
const ignoreThemeCustomCSS = '/* IgnoreThemeCustomCSS */';
// If there is custom css from theme.json show it in the edit box
diff --git a/packages/edit-site/src/components/global-styles/dimensions-panel.js b/packages/edit-site/src/components/global-styles/dimensions-panel.js
index 960ec0936cd42f..772eb5f3e47f5c 100644
--- a/packages/edit-site/src/components/global-styles/dimensions-panel.js
+++ b/packages/edit-site/src/components/global-styles/dimensions-panel.js
@@ -20,13 +20,17 @@ import {
__experimentalUseCustomSides as useCustomSides,
__experimentalHeightControl as HeightControl,
__experimentalSpacingSizesControl as SpacingSizesControl,
+ experiments as blockEditorExperiments,
} from '@wordpress/block-editor';
import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import { getSupportedGlobalStylesPanels, useSetting, useStyle } from './hooks';
+import { getSupportedGlobalStylesPanels } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
const AXIAL_SIDES = [ 'horizontal', 'vertical' ];
@@ -50,48 +54,48 @@ export function useHasDimensionsPanel( name ) {
function useHasContentSize( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'layout.contentSize', name );
+ const [ settings ] = useGlobalSetting( 'layout.contentSize', name );
return settings && supports.includes( 'contentSize' );
}
function useHasWideSize( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'layout.wideSize', name );
+ const [ settings ] = useGlobalSetting( 'layout.wideSize', name );
return settings && supports.includes( 'wideSize' );
}
function useHasPadding( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'spacing.padding', name );
+ const [ settings ] = useGlobalSetting( 'spacing.padding', name );
return settings && supports.includes( 'padding' );
}
function useHasMargin( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'spacing.margin', name );
+ const [ settings ] = useGlobalSetting( 'spacing.margin', name );
return settings && supports.includes( 'margin' );
}
function useHasGap( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'spacing.blockGap', name );
+ const [ settings ] = useGlobalSetting( 'spacing.blockGap', name );
return settings && supports.includes( 'blockGap' );
}
function useHasMinHeight( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ settings ] = useSetting( 'dimensions.minHeight', name );
+ const [ settings ] = useGlobalSetting( 'dimensions.minHeight', name );
return settings && supports.includes( 'minHeight' );
}
function useHasSpacingPresets() {
- const [ settings ] = useSetting( 'spacing.spacingSizes' );
+ const [ settings ] = useGlobalSetting( 'spacing.spacingSizes' );
return settings && settings.length > 0;
}
@@ -156,11 +160,11 @@ function splitGapValue( value ) {
// Props for managing `layout.contentSize`.
function useContentSizeProps( name ) {
- const [ contentSizeValue, setContentSizeValue ] = useSetting(
+ const [ contentSizeValue, setContentSizeValue ] = useGlobalSetting(
'layout.contentSize',
name
);
- const [ userSetContentSizeValue ] = useSetting(
+ const [ userSetContentSizeValue ] = useGlobalSetting(
'layout.contentSize',
name,
'user'
@@ -177,11 +181,11 @@ function useContentSizeProps( name ) {
// Props for managing `layout.wideSize`.
function useWideSizeProps( name ) {
- const [ wideSizeValue, setWideSizeValue ] = useSetting(
+ const [ wideSizeValue, setWideSizeValue ] = useGlobalSetting(
'layout.wideSize',
name
);
- const [ userSetWideSizeValue ] = useSetting(
+ const [ userSetWideSizeValue ] = useGlobalSetting(
'layout.wideSize',
name,
'user'
@@ -198,7 +202,7 @@ function useWideSizeProps( name ) {
// Props for managing `spacing.padding`.
function usePaddingProps( name, variationPath = '' ) {
- const [ rawPadding, setRawPadding ] = useStyle(
+ const [ rawPadding, setRawPadding ] = useGlobalStyle(
variationPath + 'spacing.padding',
name
);
@@ -213,7 +217,7 @@ function usePaddingProps( name, variationPath = '' ) {
setRawPadding( padding );
};
const resetPaddingValue = () => setPaddingValues( {} );
- const [ userSetPaddingValue ] = useStyle(
+ const [ userSetPaddingValue ] = useGlobalStyle(
variationPath + 'spacing.padding',
name,
'user'
@@ -233,7 +237,7 @@ function usePaddingProps( name, variationPath = '' ) {
// Props for managing `spacing.margin`.
function useMarginProps( name, variationPath = '' ) {
- const [ rawMargin, setRawMargin ] = useStyle(
+ const [ rawMargin, setRawMargin ] = useGlobalStyle(
variationPath + 'spacing.margin',
name
);
@@ -263,7 +267,7 @@ function useMarginProps( name, variationPath = '' ) {
// Props for managing `spacing.blockGap`.
function useBlockGapProps( name, variationPath = '' ) {
- const [ gapValue, setGapValue ] = useStyle(
+ const [ gapValue, setGapValue ] = useGlobalStyle(
variationPath + 'spacing.blockGap',
name
);
@@ -272,7 +276,7 @@ function useBlockGapProps( name, variationPath = '' ) {
const isAxialGap =
gapSides && gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) );
const resetGapValue = () => setGapValue( undefined );
- const [ userSetGapValue ] = useStyle(
+ const [ userSetGapValue ] = useGlobalStyle(
variationPath + 'spacing.blockGap',
name,
'user'
@@ -306,7 +310,7 @@ function useBlockGapProps( name, variationPath = '' ) {
// Props for managing `dimensions.minHeight`.
function useMinHeightProps( name, variationPath = '' ) {
- const [ minHeightValue, setMinHeightValue ] = useStyle(
+ const [ minHeightValue, setMinHeightValue ] = useGlobalStyle(
variationPath + 'dimensions.minHeight',
name
);
@@ -329,7 +333,7 @@ export default function DimensionsPanel( { name, variationPath = '' } ) {
const showMinHeightControl = useHasMinHeight( name );
const showSpacingPresetsControl = useHasSpacingPresets();
const units = useCustomUnits( {
- availableUnits: useSetting( 'spacing.units', name )[ 0 ] || [
+ availableUnits: useGlobalSetting( 'spacing.units', name )[ 0 ] || [
'%',
'px',
'em',
diff --git a/packages/edit-site/src/components/global-styles/global-styles-provider.js b/packages/edit-site/src/components/global-styles/global-styles-provider.js
index 68e190443d1f35..55705223831223 100644
--- a/packages/edit-site/src/components/global-styles/global-styles-provider.js
+++ b/packages/edit-site/src/components/global-styles/global-styles-provider.js
@@ -9,12 +9,15 @@ import { mergeWith, isEmpty, mapValues } from 'lodash';
import { useMemo, useCallback } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { GlobalStylesContext } from './context';
import CanvasSpinner from '../canvas-spinner';
+import { unlock } from '../../experiments';
+
+const { GlobalStylesContext } = unlock( blockEditorExperiments );
function mergeTreesCustomizer( _, srcValue ) {
// We only pass as arrays the presets,
diff --git a/packages/edit-site/src/components/global-styles/gradients-palette-panel.js b/packages/edit-site/src/components/global-styles/gradients-palette-panel.js
index 22cad685a3185d..6febec95e11971 100644
--- a/packages/edit-site/src/components/global-styles/gradients-palette-panel.js
+++ b/packages/edit-site/src/components/global-styles/gradients-palette-panel.js
@@ -8,48 +8,54 @@ import {
DuotonePicker,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { useSetting } from './hooks';
import Subtitle from './subtitle';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting } = unlock( blockEditorExperiments );
const noop = () => {};
export default function GradientPalettePanel( { name } ) {
- const [ themeGradients, setThemeGradients ] = useSetting(
+ const [ themeGradients, setThemeGradients ] = useGlobalSetting(
'color.gradients.theme',
name
);
- const [ baseThemeGradients ] = useSetting(
+ const [ baseThemeGradients ] = useGlobalSetting(
'color.gradients.theme',
name,
'base'
);
- const [ defaultGradients, setDefaultGradients ] = useSetting(
+ const [ defaultGradients, setDefaultGradients ] = useGlobalSetting(
'color.gradients.default',
name
);
- const [ baseDefaultGradients ] = useSetting(
+ const [ baseDefaultGradients ] = useGlobalSetting(
'color.gradients.default',
name,
'base'
);
- const [ customGradients, setCustomGradients ] = useSetting(
+ const [ customGradients, setCustomGradients ] = useGlobalSetting(
'color.gradients.custom',
name
);
- const [ defaultPaletteEnabled ] = useSetting(
+ const [ defaultPaletteEnabled ] = useGlobalSetting(
'color.defaultGradients',
name
);
- const [ customDuotone ] = useSetting( 'color.duotone.custom' ) || [];
- const [ defaultDuotone ] = useSetting( 'color.duotone.default' ) || [];
- const [ themeDuotone ] = useSetting( 'color.duotone.theme' ) || [];
- const [ defaultDuotoneEnabled ] = useSetting( 'color.defaultDuotone' );
+ const [ customDuotone ] = useGlobalSetting( 'color.duotone.custom' ) || [];
+ const [ defaultDuotone ] =
+ useGlobalSetting( 'color.duotone.default' ) || [];
+ const [ themeDuotone ] = useGlobalSetting( 'color.duotone.theme' ) || [];
+ const [ defaultDuotoneEnabled ] = useGlobalSetting(
+ 'color.defaultDuotone'
+ );
const duotonePalette = [
...( customDuotone || [] ),
diff --git a/packages/edit-site/src/components/global-styles/hooks.js b/packages/edit-site/src/components/global-styles/hooks.js
index c767f1a488cbfd..0dadd18c7827dc 100644
--- a/packages/edit-site/src/components/global-styles/hooks.js
+++ b/packages/edit-site/src/components/global-styles/hooks.js
@@ -1,8 +1,7 @@
/**
* External dependencies
*/
-import fastDeepEqual from 'fast-deep-equal/es6';
-import { get, set } from 'lodash';
+import { get } from 'lodash';
import { colord, extend } from 'colord';
import a11yPlugin from 'colord/plugins/a11y';
@@ -10,162 +9,23 @@ import a11yPlugin from 'colord/plugins/a11y';
* WordPress dependencies
*/
import { _x } from '@wordpress/i18n';
-import { useContext, useCallback, useMemo } from '@wordpress/element';
+import { useMemo } from '@wordpress/element';
import {
getBlockType,
- __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE,
__EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY,
} from '@wordpress/blocks';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
-import { getValueFromVariable, getPresetVariableFromValue } from './utils';
-import { GlobalStylesContext } from './context';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting } = unlock( blockEditorExperiments );
// Enable colord's a11y plugin.
extend( [ a11yPlugin ] );
-const EMPTY_CONFIG = { settings: {}, styles: {} };
-
-export const useGlobalStylesReset = () => {
- const { user: config, setUserConfig } = useContext( GlobalStylesContext );
- const canReset = !! config && ! fastDeepEqual( config, EMPTY_CONFIG );
- return [
- canReset,
- useCallback(
- () => setUserConfig( () => EMPTY_CONFIG ),
- [ setUserConfig ]
- ),
- ];
-};
-
-export function useSetting( path, blockName, source = 'all' ) {
- const {
- merged: mergedConfig,
- base: baseConfig,
- user: userConfig,
- setUserConfig,
- } = useContext( GlobalStylesContext );
-
- const fullPath = ! blockName
- ? `settings.${ path }`
- : `settings.blocks.${ blockName }.${ path }`;
-
- const setSetting = ( newValue ) => {
- setUserConfig( ( currentConfig ) => {
- // Deep clone `currentConfig` to avoid mutating it later.
- const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
- const pathToSet = PATHS_WITH_MERGE[ path ]
- ? fullPath + '.custom'
- : fullPath;
- set( newUserConfig, pathToSet, newValue );
-
- return newUserConfig;
- } );
- };
-
- const getSettingValueForContext = ( name ) => {
- const currentPath = ! name
- ? `settings.${ path }`
- : `settings.blocks.${ name }.${ path }`;
-
- const getSettingValue = ( configToUse ) => {
- const result = get( configToUse, currentPath );
- if ( PATHS_WITH_MERGE[ path ] ) {
- return result?.custom ?? result?.theme ?? result?.default;
- }
- return result;
- };
-
- let result;
- switch ( source ) {
- case 'all':
- result = getSettingValue( mergedConfig );
- break;
- case 'user':
- result = getSettingValue( userConfig );
- break;
- case 'base':
- result = getSettingValue( baseConfig );
- break;
- default:
- throw 'Unsupported source';
- }
-
- return result;
- };
-
- // Unlike styles settings get inherited from top level settings.
- const resultWithFallback =
- getSettingValueForContext( blockName ) ?? getSettingValueForContext();
-
- return [ resultWithFallback, setSetting ];
-}
-
-export function useStyle( path, blockName, source = 'all' ) {
- const {
- merged: mergedConfig,
- base: baseConfig,
- user: userConfig,
- setUserConfig,
- } = useContext( GlobalStylesContext );
- const finalPath = ! blockName
- ? `styles.${ path }`
- : `styles.blocks.${ blockName }.${ path }`;
-
- const setStyle = ( newValue ) => {
- setUserConfig( ( currentConfig ) => {
- // Deep clone `currentConfig` to avoid mutating it later.
- const newUserConfig = JSON.parse( JSON.stringify( currentConfig ) );
- set(
- newUserConfig,
- finalPath,
- getPresetVariableFromValue(
- mergedConfig.settings,
- blockName,
- path,
- newValue
- )
- );
- return newUserConfig;
- } );
- };
-
- let result;
- switch ( source ) {
- case 'all':
- result = getValueFromVariable(
- mergedConfig,
- blockName,
- // The stlyes.css path is allowed to be empty, so don't revert to base if undefined.
- finalPath === 'styles.css'
- ? get( userConfig, finalPath )
- : get( userConfig, finalPath ) ??
- get( baseConfig, finalPath )
- );
- break;
- case 'user':
- result = getValueFromVariable(
- mergedConfig,
- blockName,
- get( userConfig, finalPath )
- );
- break;
- case 'base':
- result = getValueFromVariable(
- baseConfig,
- blockName,
- get( baseConfig, finalPath )
- );
- break;
- default:
- throw 'Unsupported source';
- }
-
- return [ result, setStyle ];
-}
-
const ROOT_BLOCK_SUPPORTS = [
'background',
'backgroundColor',
@@ -247,10 +107,12 @@ export function getSupportedGlobalStylesPanels( name ) {
}
export function useColorsPerOrigin( name ) {
- const [ customColors ] = useSetting( 'color.palette.custom', name );
- const [ themeColors ] = useSetting( 'color.palette.theme', name );
- const [ defaultColors ] = useSetting( 'color.palette.default', name );
- const [ shouldDisplayDefaultColors ] = useSetting( 'color.defaultPalette' );
+ const [ customColors ] = useGlobalSetting( 'color.palette.custom', name );
+ const [ themeColors ] = useGlobalSetting( 'color.palette.theme', name );
+ const [ defaultColors ] = useGlobalSetting( 'color.palette.default', name );
+ const [ shouldDisplayDefaultColors ] = useGlobalSetting(
+ 'color.defaultPalette'
+ );
return useMemo( () => {
const result = [];
@@ -290,10 +152,19 @@ export function useColorsPerOrigin( name ) {
}
export function useGradientsPerOrigin( name ) {
- const [ customGradients ] = useSetting( 'color.gradients.custom', name );
- const [ themeGradients ] = useSetting( 'color.gradients.theme', name );
- const [ defaultGradients ] = useSetting( 'color.gradients.default', name );
- const [ shouldDisplayDefaultGradients ] = useSetting(
+ const [ customGradients ] = useGlobalSetting(
+ 'color.gradients.custom',
+ name
+ );
+ const [ themeGradients ] = useGlobalSetting(
+ 'color.gradients.theme',
+ name
+ );
+ const [ defaultGradients ] = useGlobalSetting(
+ 'color.gradients.default',
+ name
+ );
+ const [ shouldDisplayDefaultGradients ] = useGlobalSetting(
'color.defaultGradients'
);
@@ -335,7 +206,7 @@ export function useGradientsPerOrigin( name ) {
}
export function useColorRandomizer( name ) {
- const [ themeColors, setThemeColors ] = useSetting(
+ const [ themeColors, setThemeColors ] = useGlobalSetting(
'color.palette.theme',
name
);
diff --git a/packages/edit-site/src/components/global-styles/index.js b/packages/edit-site/src/components/global-styles/index.js
index 026a4fd759f325..5533852c1ac68b 100644
--- a/packages/edit-site/src/components/global-styles/index.js
+++ b/packages/edit-site/src/components/global-styles/index.js
@@ -1,3 +1 @@
export { default as GlobalStylesUI } from './ui';
-export { useGlobalStylesReset, useStyle, useSetting } from './hooks';
-export { useGlobalStylesOutput } from './use-global-styles-output';
diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js
index 0b4bbbbbb7f63e..09148a55bd57a7 100644
--- a/packages/edit-site/src/components/global-styles/palette.js
+++ b/packages/edit-site/src/components/global-styles/palette.js
@@ -13,23 +13,27 @@ import {
import { __, _n, sprintf } from '@wordpress/i18n';
import { shuffle } from '@wordpress/icons';
import { useMemo } from '@wordpress/element';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import Subtitle from './subtitle';
import { NavigationButtonAsItem } from './navigation-button';
-import { useColorRandomizer, useSetting } from './hooks';
+import { useColorRandomizer } from './hooks';
import ColorIndicatorWrapper from './color-indicator-wrapper';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting } = unlock( blockEditorExperiments );
const EMPTY_COLORS = [];
function Palette( { name } ) {
- const [ customColors ] = useSetting( 'color.palette.custom' );
- const [ themeColors ] = useSetting( 'color.palette.theme' );
- const [ defaultColors ] = useSetting( 'color.palette.default' );
+ const [ customColors ] = useGlobalSetting( 'color.palette.custom' );
+ const [ themeColors ] = useGlobalSetting( 'color.palette.theme' );
+ const [ defaultColors ] = useGlobalSetting( 'color.palette.default' );
- const [ defaultPaletteEnabled ] = useSetting(
+ const [ defaultPaletteEnabled ] = useGlobalSetting(
'color.defaultPalette',
name
);
diff --git a/packages/edit-site/src/components/global-styles/preview.js b/packages/edit-site/src/components/global-styles/preview.js
index 14ade992f0fc7b..521e0d2d7ed1b2 100644
--- a/packages/edit-site/src/components/global-styles/preview.js
+++ b/packages/edit-site/src/components/global-styles/preview.js
@@ -4,6 +4,7 @@
import {
__unstableIframe as Iframe,
__unstableEditorStyles as EditorStyles,
+ experiments as blockEditorExperiments,
} from '@wordpress/block-editor';
import {
__unstableMotion as motion,
@@ -16,8 +17,11 @@ import { useState, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
-import { useSetting, useStyle } from './hooks';
-import { useGlobalStylesOutput } from './use-global-styles-output';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle, useGlobalStylesOutput } = unlock(
+ blockEditorExperiments
+);
const firstFrame = {
start: {
@@ -56,23 +60,25 @@ const normalizedHeight = 152;
const normalizedColorSwatchSize = 32;
const StylesPreview = ( { label, isFocused, withHoverView } ) => {
- const [ fontWeight ] = useStyle( 'typography.fontWeight' );
- const [ fontFamily = 'serif' ] = useStyle( 'typography.fontFamily' );
- const [ headingFontFamily = fontFamily ] = useStyle(
+ const [ fontWeight ] = useGlobalStyle( 'typography.fontWeight' );
+ const [ fontFamily = 'serif' ] = useGlobalStyle( 'typography.fontFamily' );
+ const [ headingFontFamily = fontFamily ] = useGlobalStyle(
'elements.h1.typography.fontFamily'
);
- const [ headingFontWeight = fontWeight ] = useStyle(
+ const [ headingFontWeight = fontWeight ] = useGlobalStyle(
'elements.h1.typography.fontWeight'
);
- const [ textColor = 'black' ] = useStyle( 'color.text' );
- const [ headingColor = textColor ] = useStyle( 'elements.h1.color.text' );
- const [ backgroundColor = 'white' ] = useStyle( 'color.background' );
- const [ gradientValue ] = useStyle( 'color.gradient' );
+ const [ textColor = 'black' ] = useGlobalStyle( 'color.text' );
+ const [ headingColor = textColor ] = useGlobalStyle(
+ 'elements.h1.color.text'
+ );
+ const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' );
+ const [ gradientValue ] = useGlobalStyle( 'color.gradient' );
const [ styles ] = useGlobalStylesOutput();
const disableMotion = useReducedMotion();
- const [ coreColors ] = useSetting( 'color.palette.core' );
- const [ themeColors ] = useSetting( 'color.palette.theme' );
- const [ customColors ] = useSetting( 'color.palette.custom' );
+ const [ coreColors ] = useGlobalSetting( 'color.palette.core' );
+ const [ themeColors ] = useGlobalSetting( 'color.palette.theme' );
+ const [ customColors ] = useGlobalSetting( 'color.palette.custom' );
const [ isHovered, setIsHovered ] = useState( false );
const [ containerResizeListener, { width } ] = useResizeObserver();
const ratio = width ? width / normalizedWidth : 1;
diff --git a/packages/edit-site/src/components/global-styles/screen-background-color.js b/packages/edit-site/src/components/global-styles/screen-background-color.js
index d7227cc6e29ba3..6ae0ece5e848ea 100644
--- a/packages/edit-site/src/components/global-styles/screen-background-color.js
+++ b/packages/edit-site/src/components/global-styles/screen-background-color.js
@@ -7,7 +7,10 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
+import {
+ __experimentalColorGradientControl as ColorGradientControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
/**
* Internal dependencies
@@ -17,16 +20,17 @@ import {
getSupportedGlobalStylesPanels,
useColorsPerOrigin,
useGradientsPerOrigin,
- useSetting,
- useStyle,
} from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
function ScreenBackgroundColor( { name, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ solids ] = useSetting( 'color.palette', name );
- const [ gradients ] = useSetting( 'color.gradients', name );
- const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
- const [ areCustomGradientsEnabled ] = useSetting(
+ const [ solids ] = useGlobalSetting( 'color.palette', name );
+ const [ gradients ] = useGlobalSetting( 'color.gradients', name );
+ const [ areCustomSolidsEnabled ] = useGlobalSetting( 'color.custom', name );
+ const [ areCustomGradientsEnabled ] = useGlobalSetting(
'color.customGradient',
name
);
@@ -34,7 +38,10 @@ function ScreenBackgroundColor( { name, variationPath = '' } ) {
const colorsPerOrigin = useColorsPerOrigin( name );
const gradientsPerOrigin = useGradientsPerOrigin( name );
- const [ isBackgroundEnabled ] = useSetting( 'color.background', name );
+ const [ isBackgroundEnabled ] = useGlobalSetting(
+ 'color.background',
+ name
+ );
const hasBackgroundColor =
supports.includes( 'backgroundColor' ) &&
@@ -43,20 +50,20 @@ function ScreenBackgroundColor( { name, variationPath = '' } ) {
const hasGradientColor =
supports.includes( 'background' ) &&
( gradients.length > 0 || areCustomGradientsEnabled );
- const [ backgroundColor, setBackgroundColor ] = useStyle(
+ const [ backgroundColor, setBackgroundColor ] = useGlobalStyle(
variationPath + 'color.background',
name
);
- const [ userBackgroundColor ] = useStyle(
+ const [ userBackgroundColor ] = useGlobalStyle(
variationPath + 'color.background',
name,
'user'
);
- const [ gradient, setGradient ] = useStyle(
+ const [ gradient, setGradient ] = useGlobalStyle(
variationPath + 'color.gradient',
name
);
- const [ userGradient ] = useStyle(
+ const [ userGradient ] = useGlobalStyle(
variationPath + 'color.gradient',
name,
'user'
diff --git a/packages/edit-site/src/components/global-styles/screen-button-color.js b/packages/edit-site/src/components/global-styles/screen-button-color.js
index 27ae7a07831475..bc420ac79e425c 100644
--- a/packages/edit-site/src/components/global-styles/screen-button-color.js
+++ b/packages/edit-site/src/components/global-styles/screen-button-color.js
@@ -2,48 +2,52 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
+import {
+ __experimentalColorGradientControl as ColorGradientControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import ScreenHeader from './header';
-import {
- getSupportedGlobalStylesPanels,
- useSetting,
- useStyle,
- useColorsPerOrigin,
-} from './hooks';
+import { getSupportedGlobalStylesPanels, useColorsPerOrigin } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
function ScreenButtonColor( { name, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ solids ] = useSetting( 'color.palette', name );
- const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
+ const [ solids ] = useGlobalSetting( 'color.palette', name );
+ const [ areCustomSolidsEnabled ] = useGlobalSetting( 'color.custom', name );
const colorsPerOrigin = useColorsPerOrigin( name );
- const [ isBackgroundEnabled ] = useSetting( 'color.background', name );
+ const [ isBackgroundEnabled ] = useGlobalSetting(
+ 'color.background',
+ name
+ );
const hasButtonColor =
supports.includes( 'buttonColor' ) &&
isBackgroundEnabled &&
( solids.length > 0 || areCustomSolidsEnabled );
- const [ buttonTextColor, setButtonTextColor ] = useStyle(
+ const [ buttonTextColor, setButtonTextColor ] = useGlobalStyle(
variationPath + 'elements.button.color.text',
name
);
- const [ userButtonTextColor ] = useStyle(
+ const [ userButtonTextColor ] = useGlobalStyle(
'elements.button.color.text',
name,
'user'
);
- const [ buttonBgColor, setButtonBgColor ] = useStyle(
+ const [ buttonBgColor, setButtonBgColor ] = useGlobalStyle(
'elements.button.color.background',
name
);
- const [ userButtonBgColor ] = useStyle(
+ const [ userButtonBgColor ] = useGlobalStyle(
'elements.button.color.background',
name,
'user'
diff --git a/packages/edit-site/src/components/global-styles/screen-colors.js b/packages/edit-site/src/components/global-styles/screen-colors.js
index 4de6056f7d767f..2d863f6a2b6d28 100644
--- a/packages/edit-site/src/components/global-styles/screen-colors.js
+++ b/packages/edit-site/src/components/global-styles/screen-colors.js
@@ -10,6 +10,7 @@ import {
FlexItem,
ColorIndicator,
} from '@wordpress/components';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
@@ -17,11 +18,14 @@ import {
import ScreenHeader from './header';
import Palette from './palette';
import { NavigationButtonAsItem } from './navigation-button';
-import { getSupportedGlobalStylesPanels, useStyle } from './hooks';
+import { getSupportedGlobalStylesPanels } from './hooks';
import Subtitle from './subtitle';
import ColorIndicatorWrapper from './color-indicator-wrapper';
import BlockPreviewPanel from './block-preview-panel';
import { getVariationClassNameFromPath } from './utils';
+import { unlock } from '../../experiments';
+
+const { useGlobalStyle } = unlock( blockEditorExperiments );
function variationPathToURL( variationPath ) {
if ( ! variationPath ) {
@@ -36,11 +40,11 @@ function BackgroundColorItem( { name, parentMenu, variationPath = '' } ) {
const hasSupport =
supports.includes( 'backgroundColor' ) ||
supports.includes( 'background' );
- const [ backgroundColor ] = useStyle(
+ const [ backgroundColor ] = useGlobalStyle(
variationPath + 'color.background',
name
);
- const [ gradientValue ] = useStyle(
+ const [ gradientValue ] = useGlobalStyle(
variationPath + 'color.gradient',
name
);
@@ -76,7 +80,7 @@ function BackgroundColorItem( { name, parentMenu, variationPath = '' } ) {
function TextColorItem( { name, parentMenu, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasSupport = supports.includes( 'color' );
- const [ color ] = useStyle( variationPath + 'color.text', name );
+ const [ color ] = useGlobalStyle( variationPath + 'color.text', name );
if ( ! hasSupport ) {
return null;
@@ -109,11 +113,11 @@ function TextColorItem( { name, parentMenu, variationPath = '' } ) {
function LinkColorItem( { name, parentMenu, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasSupport = supports.includes( 'linkColor' );
- const [ color ] = useStyle(
+ const [ color ] = useGlobalStyle(
variationPath + 'elements.link.color.text',
name
);
- const [ colorHover ] = useStyle(
+ const [ colorHover ] = useGlobalStyle(
variationPath + 'elements.link.:hover.color.text',
name
);
@@ -151,11 +155,11 @@ function LinkColorItem( { name, parentMenu, variationPath = '' } ) {
function HeadingColorItem( { name, parentMenu, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasSupport = supports.includes( 'color' );
- const [ color ] = useStyle(
+ const [ color ] = useGlobalStyle(
variationPath + 'elements.heading.color.text',
name
);
- const [ bgColor ] = useStyle(
+ const [ bgColor ] = useGlobalStyle(
variationPath + 'elements.heading.color.background',
name
);
@@ -191,11 +195,11 @@ function HeadingColorItem( { name, parentMenu, variationPath = '' } ) {
function ButtonColorItem( { name, parentMenu, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasSupport = supports.includes( 'buttonColor' );
- const [ color ] = useStyle(
+ const [ color ] = useGlobalStyle(
variationPath + 'elements.button.color.text',
name
);
- const [ bgColor ] = useStyle(
+ const [ bgColor ] = useGlobalStyle(
variationPath + 'elements.button.color.background',
name
);
diff --git a/packages/edit-site/src/components/global-styles/screen-heading-color.js b/packages/edit-site/src/components/global-styles/screen-heading-color.js
index c666873026811b..18566051bb9bc2 100644
--- a/packages/edit-site/src/components/global-styles/screen-heading-color.js
+++ b/packages/edit-site/src/components/global-styles/screen-heading-color.js
@@ -6,7 +6,10 @@ import {
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
-import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
+import {
+ __experimentalColorGradientControl as ColorGradientControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
import { useState } from '@wordpress/element';
/**
@@ -15,25 +18,29 @@ import { useState } from '@wordpress/element';
import ScreenHeader from './header';
import {
getSupportedGlobalStylesPanels,
- useSetting,
- useStyle,
useColorsPerOrigin,
useGradientsPerOrigin,
} from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
function ScreenHeadingColor( { name, variationPath = '' } ) {
const [ selectedLevel, setCurrentTab ] = useState( 'heading' );
const supports = getSupportedGlobalStylesPanels( name );
- const [ solids ] = useSetting( 'color.palette', name );
- const [ gradients ] = useSetting( 'color.gradients', name );
- const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
- const [ areCustomGradientsEnabled ] = useSetting(
+ const [ solids ] = useGlobalSetting( 'color.palette', name );
+ const [ gradients ] = useGlobalSetting( 'color.gradients', name );
+ const [ areCustomSolidsEnabled ] = useGlobalSetting( 'color.custom', name );
+ const [ areCustomGradientsEnabled ] = useGlobalSetting(
'color.customGradient',
name
);
- const [ isTextEnabled ] = useSetting( 'color.text', name );
- const [ isBackgroundEnabled ] = useSetting( 'color.background', name );
+ const [ isTextEnabled ] = useGlobalSetting( 'color.text', name );
+ const [ isBackgroundEnabled ] = useGlobalSetting(
+ 'color.background',
+ name
+ );
const colorsPerOrigin = useColorsPerOrigin( name );
const gradientsPerOrigin = useGradientsPerOrigin( name );
@@ -51,30 +58,30 @@ function ScreenHeadingColor( { name, variationPath = '' } ) {
supports.includes( 'background' ) &&
( gradients.length > 0 || areCustomGradientsEnabled );
- const [ color, setColor ] = useStyle(
+ const [ color, setColor ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.text',
name
);
- const [ userColor ] = useStyle(
+ const [ userColor ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.text',
name,
'user'
);
- const [ backgroundColor, setBackgroundColor ] = useStyle(
+ const [ backgroundColor, setBackgroundColor ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.background',
name
);
- const [ userBackgroundColor ] = useStyle(
+ const [ userBackgroundColor ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.background',
name,
'user'
);
- const [ gradient, setGradient ] = useStyle(
+ const [ gradient, setGradient ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.gradient',
name
);
- const [ userGradient ] = useStyle(
+ const [ userGradient ] = useGlobalStyle(
variationPath + 'elements.' + selectedLevel + '.color.gradient',
name,
'user'
diff --git a/packages/edit-site/src/components/global-styles/screen-link-color.js b/packages/edit-site/src/components/global-styles/screen-link-color.js
index 855e8e91c81dbf..049c2cc99d47af 100644
--- a/packages/edit-site/src/components/global-styles/screen-link-color.js
+++ b/packages/edit-site/src/components/global-styles/screen-link-color.js
@@ -2,27 +2,29 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
+import {
+ __experimentalColorGradientControl as ColorGradientControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
import { TabPanel } from '@wordpress/components';
+
/**
* Internal dependencies
*/
import ScreenHeader from './header';
-import {
- getSupportedGlobalStylesPanels,
- useSetting,
- useStyle,
- useColorsPerOrigin,
-} from './hooks';
+import { getSupportedGlobalStylesPanels, useColorsPerOrigin } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
function ScreenLinkColor( { name, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ solids ] = useSetting( 'color.palette', name );
- const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
+ const [ solids ] = useGlobalSetting( 'color.palette', name );
+ const [ areCustomSolidsEnabled ] = useGlobalSetting( 'color.custom', name );
const colorsPerOrigin = useColorsPerOrigin( name );
- const [ isLinkEnabled ] = useSetting( 'color.link', name );
+ const [ isLinkEnabled ] = useGlobalSetting( 'color.link', name );
const hasLinkColor =
supports.includes( 'linkColor' ) &&
@@ -32,15 +34,15 @@ function ScreenLinkColor( { name, variationPath = '' } ) {
const pseudoStates = {
default: {
label: __( 'Default' ),
- value: useStyle(
+ value: useGlobalStyle(
variationPath + 'elements.link.color.text',
name
)[ 0 ],
- handler: useStyle(
+ handler: useGlobalStyle(
variationPath + 'elements.link.color.text',
name
)[ 1 ],
- userValue: useStyle(
+ userValue: useGlobalStyle(
variationPath + 'elements.link.color.text',
name,
'user'
@@ -48,15 +50,15 @@ function ScreenLinkColor( { name, variationPath = '' } ) {
},
hover: {
label: __( 'Hover' ),
- value: useStyle(
+ value: useGlobalStyle(
variationPath + 'elements.link.:hover.color.text',
name
)[ 0 ],
- handler: useStyle(
+ handler: useGlobalStyle(
variationPath + 'elements.link.:hover.color.text',
name
)[ 1 ],
- userValue: useStyle(
+ userValue: useGlobalStyle(
variationPath + 'elements.link.:hover.color.text',
name,
'user'
diff --git a/packages/edit-site/src/components/global-styles/screen-style-variations.js b/packages/edit-site/src/components/global-styles/screen-style-variations.js
index b88b81a0c08d17..a94edce1cf92f0 100644
--- a/packages/edit-site/src/components/global-styles/screen-style-variations.js
+++ b/packages/edit-site/src/components/global-styles/screen-style-variations.js
@@ -23,15 +23,20 @@ import {
CardBody,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-import { store as blockEditorStore } from '@wordpress/block-editor';
+import {
+ store as blockEditorStore,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { mergeBaseAndUserConfigs } from './global-styles-provider';
-import { GlobalStylesContext } from './context';
import StylesPreview from './preview';
import ScreenHeader from './header';
+import { unlock } from '../../experiments';
+
+const { GlobalStylesContext } = unlock( blockEditorExperiments );
function compareVariations( a, b ) {
return (
diff --git a/packages/edit-site/src/components/global-styles/screen-text-color.js b/packages/edit-site/src/components/global-styles/screen-text-color.js
index 7521b3b68728e7..d61cea759fd8ad 100644
--- a/packages/edit-site/src/components/global-styles/screen-text-color.js
+++ b/packages/edit-site/src/components/global-styles/screen-text-color.js
@@ -2,24 +2,25 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
+import {
+ __experimentalColorGradientControl as ColorGradientControl,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import ScreenHeader from './header';
-import {
- getSupportedGlobalStylesPanels,
- useSetting,
- useStyle,
- useColorsPerOrigin,
-} from './hooks';
+import { getSupportedGlobalStylesPanels, useColorsPerOrigin } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
function ScreenTextColor( { name, variationPath = '' } ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ solids ] = useSetting( 'color.palette', name );
- const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
- const [ isTextEnabled ] = useSetting( 'color.text', name );
+ const [ solids ] = useGlobalSetting( 'color.palette', name );
+ const [ areCustomSolidsEnabled ] = useGlobalSetting( 'color.custom', name );
+ const [ isTextEnabled ] = useGlobalSetting( 'color.text', name );
const colorsPerOrigin = useColorsPerOrigin( name );
@@ -28,8 +29,11 @@ function ScreenTextColor( { name, variationPath = '' } ) {
isTextEnabled &&
( solids.length > 0 || areCustomSolidsEnabled );
- const [ color, setColor ] = useStyle( variationPath + 'color.text', name );
- const [ userColor ] = useStyle(
+ const [ color, setColor ] = useGlobalStyle(
+ variationPath + 'color.text',
+ name
+ );
+ const [ userColor ] = useGlobalStyle(
variationPath + 'color.text',
name,
'user'
diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js
index a92e00361e4c7b..bd56273781a3f8 100644
--- a/packages/edit-site/src/components/global-styles/screen-typography.js
+++ b/packages/edit-site/src/components/global-styles/screen-typography.js
@@ -8,17 +8,20 @@ import {
__experimentalHStack as HStack,
FlexItem,
} from '@wordpress/components';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import ScreenHeader from './header';
import { NavigationButtonAsItem } from './navigation-button';
-import { useStyle } from './hooks';
import Subtitle from './subtitle';
import TypographyPanel from './typography-panel';
import BlockPreviewPanel from './block-preview-panel';
import { getVariationClassNameFromPath } from './utils';
+import { unlock } from '../../experiments';
+
+const { useGlobalStyle } = unlock( blockEditorExperiments );
function Item( { name, parentMenu, element, label } ) {
const hasSupport = ! name;
@@ -30,16 +33,28 @@ function Item( { name, parentMenu, element, label } ) {
textDecoration: 'underline',
}
: {};
- const [ fontFamily ] = useStyle( prefix + 'typography.fontFamily', name );
- const [ fontStyle ] = useStyle( prefix + 'typography.fontStyle', name );
- const [ fontWeight ] = useStyle( prefix + 'typography.fontWeight', name );
- const [ letterSpacing ] = useStyle(
+ const [ fontFamily ] = useGlobalStyle(
+ prefix + 'typography.fontFamily',
+ name
+ );
+ const [ fontStyle ] = useGlobalStyle(
+ prefix + 'typography.fontStyle',
+ name
+ );
+ const [ fontWeight ] = useGlobalStyle(
+ prefix + 'typography.fontWeight',
+ name
+ );
+ const [ letterSpacing ] = useGlobalStyle(
prefix + 'typography.letterSpacing',
name
);
- const [ backgroundColor ] = useStyle( prefix + 'color.background', name );
- const [ gradientValue ] = useStyle( prefix + 'color.gradient', name );
- const [ color ] = useStyle( prefix + 'color.text', name );
+ const [ backgroundColor ] = useGlobalStyle(
+ prefix + 'color.background',
+ name
+ );
+ const [ gradientValue ] = useGlobalStyle( prefix + 'color.gradient', name );
+ const [ color ] = useGlobalStyle( prefix + 'color.text', name );
if ( ! hasSupport ) {
return null;
diff --git a/packages/edit-site/src/components/global-styles/typography-panel.js b/packages/edit-site/src/components/global-styles/typography-panel.js
index b793d81978ef20..938605ba11c4ae 100644
--- a/packages/edit-site/src/components/global-styles/typography-panel.js
+++ b/packages/edit-site/src/components/global-styles/typography-panel.js
@@ -8,6 +8,7 @@ import {
__experimentalLetterSpacingControl as LetterSpacingControl,
__experimentalTextTransformControl as TextTransformControl,
__experimentalTextDecorationControl as TextDecorationControl,
+ experiments as blockEditorExperiments,
} from '@wordpress/block-editor';
import {
FontSizePicker,
@@ -19,7 +20,10 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import { getSupportedGlobalStylesPanels, useSetting, useStyle } from './hooks';
+import { getSupportedGlobalStylesPanels } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );
export function useHasTypographyPanel( name ) {
const hasFontFamily = useHasFontFamilyControl( name );
@@ -38,14 +42,17 @@ export function useHasTypographyPanel( name ) {
function useHasFontFamilyControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
- const [ fontFamilies ] = useSetting( 'typography.fontFamilies', name );
+ const [ fontFamilies ] = useGlobalSetting(
+ 'typography.fontFamilies',
+ name
+ );
return supports.includes( 'fontFamily' ) && !! fontFamilies?.length;
}
function useHasLineHeightControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return (
- useSetting( 'typography.lineHeight', name )[ 0 ] &&
+ useGlobalSetting( 'typography.lineHeight', name )[ 0 ] &&
supports.includes( 'lineHeight' )
);
}
@@ -53,10 +60,10 @@ function useHasLineHeightControl( name ) {
function useHasAppearanceControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasFontStyles =
- useSetting( 'typography.fontStyle', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontStyle', name )[ 0 ] &&
supports.includes( 'fontStyle' );
const hasFontWeights =
- useSetting( 'typography.fontWeight', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontWeight', name )[ 0 ] &&
supports.includes( 'fontWeight' );
return hasFontStyles || hasFontWeights;
}
@@ -64,10 +71,10 @@ function useHasAppearanceControl( name ) {
function useAppearanceControlLabel( name ) {
const supports = getSupportedGlobalStylesPanels( name );
const hasFontStyles =
- useSetting( 'typography.fontStyle', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontStyle', name )[ 0 ] &&
supports.includes( 'fontStyle' );
const hasFontWeights =
- useSetting( 'typography.fontWeight', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontWeight', name )[ 0 ] &&
supports.includes( 'fontWeight' );
if ( ! hasFontStyles ) {
return __( 'Font weight' );
@@ -79,7 +86,7 @@ function useAppearanceControlLabel( name ) {
}
function useHasLetterSpacingControl( name, element ) {
- const setting = useSetting( 'typography.letterSpacing', name )[ 0 ];
+ const setting = useGlobalSetting( 'typography.letterSpacing', name )[ 0 ];
if ( ! setting ) {
return false;
}
@@ -91,7 +98,7 @@ function useHasLetterSpacingControl( name, element ) {
}
function useHasTextTransformControl( name, element ) {
- const setting = useSetting( 'typography.textTransform', name )[ 0 ];
+ const setting = useGlobalSetting( 'typography.textTransform', name )[ 0 ];
if ( ! setting ) {
return false;
}
@@ -110,16 +117,16 @@ function useHasTextDecorationControl( name, element ) {
}
function useStyleWithReset( path, blockName ) {
- const [ style, setStyle ] = useStyle( path, blockName );
- const [ userStyle ] = useStyle( path, blockName, 'user' );
+ const [ style, setStyle ] = useGlobalStyle( path, blockName );
+ const [ userStyle ] = useGlobalStyle( path, blockName, 'user' );
const hasStyle = () => !! userStyle;
const resetStyle = () => setStyle( undefined );
return [ style, setStyle, hasStyle, resetStyle ];
}
function useFontSizeWithReset( path, blockName ) {
- const [ fontSize, setStyleCallback ] = useStyle( path, blockName );
- const [ userStyle ] = useStyle( path, blockName, 'user' );
+ const [ fontSize, setStyleCallback ] = useGlobalStyle( path, blockName );
+ const [ userStyle ] = useGlobalStyle( path, blockName, 'user' );
const hasFontSize = () => !! userStyle;
const resetFontSize = () => setStyleCallback( undefined );
const setFontSize = ( newValue, metadata ) => {
@@ -138,20 +145,20 @@ function useFontSizeWithReset( path, blockName ) {
}
function useFontAppearance( prefix, name ) {
- const [ fontStyle, setFontStyle ] = useStyle(
+ const [ fontStyle, setFontStyle ] = useGlobalStyle(
prefix + 'typography.fontStyle',
name
);
- const [ userFontStyle ] = useStyle(
+ const [ userFontStyle ] = useGlobalStyle(
prefix + 'typography.fontStyle',
name,
'user'
);
- const [ fontWeight, setFontWeight ] = useStyle(
+ const [ fontWeight, setFontWeight ] = useGlobalStyle(
prefix + 'typography.fontWeight',
name
);
- const [ userFontWeight ] = useStyle(
+ const [ userFontWeight ] = useGlobalStyle(
prefix + 'typography.fontWeight',
name,
'user'
@@ -184,18 +191,21 @@ export default function TypographyPanel( {
} else if ( element && element !== 'text' ) {
prefix = `elements.${ element }.`;
}
- const [ fontSizes ] = useSetting( 'typography.fontSizes', name );
+ const [ fontSizes ] = useGlobalSetting( 'typography.fontSizes', name );
- const disableCustomFontSizes = ! useSetting(
+ const disableCustomFontSizes = ! useGlobalSetting(
'typography.customFontSize',
name
)[ 0 ];
- const [ fontFamilies ] = useSetting( 'typography.fontFamilies', name );
+ const [ fontFamilies ] = useGlobalSetting(
+ 'typography.fontFamilies',
+ name
+ );
const hasFontStyles =
- useSetting( 'typography.fontStyle', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontStyle', name )[ 0 ] &&
supports.includes( 'fontStyle' );
const hasFontWeights =
- useSetting( 'typography.fontWeight', name )[ 0 ] &&
+ useGlobalSetting( 'typography.fontWeight', name )[ 0 ] &&
supports.includes( 'fontWeight' );
const hasFontFamilyEnabled = useHasFontFamilyControl( name );
const hasLineHeightEnabled = useHasLineHeightControl( name );
diff --git a/packages/edit-site/src/components/global-styles/typography-preview.js b/packages/edit-site/src/components/global-styles/typography-preview.js
index b0e134ab0cce59..49c0d4e73b95b4 100644
--- a/packages/edit-site/src/components/global-styles/typography-preview.js
+++ b/packages/edit-site/src/components/global-styles/typography-preview.js
@@ -1,7 +1,14 @@
+/**
+ * WordPress dependencies
+ */
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
+
/**
* Internal dependencies
*/
-import { useStyle } from './hooks';
+import { unlock } from '../../experiments';
+
+const { useGlobalStyle } = unlock( blockEditorExperiments );
export default function TypographyPreview( { name, element, headingLevel } ) {
let prefix = '';
@@ -11,14 +18,26 @@ export default function TypographyPreview( { name, element, headingLevel } ) {
prefix = `elements.${ element }.`;
}
- const [ fontFamily ] = useStyle( prefix + 'typography.fontFamily', name );
- const [ gradientValue ] = useStyle( prefix + 'color.gradient', name );
- const [ backgroundColor ] = useStyle( prefix + 'color.background', name );
- const [ color ] = useStyle( prefix + 'color.text', name );
- const [ fontSize ] = useStyle( prefix + 'typography.fontSize', name );
- const [ fontStyle ] = useStyle( prefix + 'typography.fontStyle', name );
- const [ fontWeight ] = useStyle( prefix + 'typography.fontWeight', name );
- const [ letterSpacing ] = useStyle(
+ const [ fontFamily ] = useGlobalStyle(
+ prefix + 'typography.fontFamily',
+ name
+ );
+ const [ gradientValue ] = useGlobalStyle( prefix + 'color.gradient', name );
+ const [ backgroundColor ] = useGlobalStyle(
+ prefix + 'color.background',
+ name
+ );
+ const [ color ] = useGlobalStyle( prefix + 'color.text', name );
+ const [ fontSize ] = useGlobalStyle( prefix + 'typography.fontSize', name );
+ const [ fontStyle ] = useGlobalStyle(
+ prefix + 'typography.fontStyle',
+ name
+ );
+ const [ fontWeight ] = useGlobalStyle(
+ prefix + 'typography.fontWeight',
+ name
+ );
+ const [ letterSpacing ] = useGlobalStyle(
prefix + 'typography.letterSpacing',
name
);
diff --git a/packages/edit-site/src/components/global-styles/utils.js b/packages/edit-site/src/components/global-styles/utils.js
index b33383451ccd3e..8c20de6508fb64 100644
--- a/packages/edit-site/src/components/global-styles/utils.js
+++ b/packages/edit-site/src/components/global-styles/utils.js
@@ -1,370 +1,3 @@
-/**
- * External dependencies
- */
-import { get } from 'lodash';
-
-/**
- * Internal dependencies
- */
-import { getTypographyFontSizeValue } from './typography-utils';
-
-/* Supporting data. */
-export const ROOT_BLOCK_NAME = 'root';
-export const ROOT_BLOCK_SELECTOR = 'body';
-export const ROOT_BLOCK_SUPPORTS = [
- 'background',
- 'backgroundColor',
- 'color',
- 'linkColor',
- 'buttonColor',
- 'fontFamily',
- 'fontSize',
- 'fontStyle',
- 'fontWeight',
- 'lineHeight',
- 'textDecoration',
- 'textTransform',
- 'padding',
-];
-
-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: [ 'color', 'duotone' ],
- cssVarInfix: 'duotone',
- valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`,
- classes: [],
- },
- {
- path: [ 'typography', 'fontSizes' ],
- valueFunc: ( preset, { typography: typographySettings } ) =>
- getTypographyFontSizeValue( preset, typographySettings ),
- valueKey: 'size',
- cssVarInfix: 'font-size',
- classes: [ { classSuffix: 'font-size', propertyName: 'font-size' } ],
- },
- {
- path: [ 'typography', 'fontFamilies' ],
- valueKey: 'fontFamily',
- cssVarInfix: 'font-family',
- classes: [
- { classSuffix: 'font-family', propertyName: 'font-family' },
- ],
- },
- {
- path: [ 'spacing', 'spacingSizes' ],
- valueKey: 'size',
- cssVarInfix: 'spacing',
- valueFunc: ( { size } ) => size,
- classes: [],
- },
-];
-
-export const STYLE_PATH_TO_CSS_VAR_INFIX = {
- 'color.background': 'color',
- 'color.text': 'color',
- 'elements.link.color.text': 'color',
- 'elements.link.:hover.color.text': 'color',
- 'elements.link.typography.fontFamily': 'font-family',
- 'elements.link.typography.fontSize': 'font-size',
- 'elements.button.color.text': 'color',
- 'elements.button.color.background': 'color',
- 'elements.button.typography.fontFamily': 'font-family',
- 'elements.button.typography.fontSize': 'font-size',
- 'elements.heading.color': 'color',
- 'elements.heading.color.background': 'color',
- 'elements.heading.typography.fontFamily': 'font-family',
- 'elements.heading.gradient': 'gradient',
- 'elements.heading.color.gradient': 'gradient',
- 'elements.h1.color': 'color',
- 'elements.h1.color.background': 'color',
- 'elements.h1.typography.fontFamily': 'font-family',
- 'elements.h1.color.gradient': 'gradient',
- 'elements.h2.color': 'color',
- 'elements.h2.color.background': 'color',
- 'elements.h2.typography.fontFamily': 'font-family',
- 'elements.h2.color.gradient': 'gradient',
- 'elements.h3.color': 'color',
- 'elements.h3.color.background': 'color',
- 'elements.h3.typography.fontFamily': 'font-family',
- 'elements.h3.color.gradient': 'gradient',
- 'elements.h4.color': 'color',
- 'elements.h4.color.background': 'color',
- 'elements.h4.typography.fontFamily': 'font-family',
- 'elements.h4.color.gradient': 'gradient',
- 'elements.h5.color': 'color',
- 'elements.h5.color.background': 'color',
- 'elements.h5.typography.fontFamily': 'font-family',
- 'elements.h5.color.gradient': 'gradient',
- 'elements.h6.color': 'color',
- 'elements.h6.color.background': 'color',
- 'elements.h6.typography.fontFamily': 'font-family',
- 'elements.h6.color.gradient': 'gradient',
- 'color.gradient': 'gradient',
- 'typography.fontSize': 'font-size',
- 'typography.fontFamily': 'font-family',
-};
-
-// A static list of block attributes that store global style preset slugs.
-export const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = {
- 'color.background': 'backgroundColor',
- 'color.text': 'textColor',
- 'color.gradient': 'gradient',
- 'typography.fontSize': 'fontSize',
- 'typography.fontFamily': 'fontFamily',
-};
-
-function findInPresetsBy(
- features,
- blockName,
- presetPath,
- presetProperty,
- presetValueValue
-) {
- // Block presets take priority above root level presets.
- const orderedPresetsByOrigin = [
- get( features, [ 'blocks', blockName, ...presetPath ] ),
- get( features, presetPath ),
- ];
-
- for ( const presetByOrigin of orderedPresetsByOrigin ) {
- if ( presetByOrigin ) {
- // Preset origins ordered by priority.
- const origins = [ 'custom', 'theme', 'default' ];
- for ( const origin of origins ) {
- const presets = presetByOrigin[ origin ];
- if ( presets ) {
- const presetObject = presets.find(
- ( 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,
- blockName,
- presetPath,
- 'slug',
- presetObject.slug
- );
- if (
- highestPresetObjectWithSameSlug[
- presetProperty
- ] === presetObject[ presetProperty ]
- ) {
- return presetObject;
- }
- return undefined;
- }
- }
- }
- }
- }
-}
-
-export function getPresetVariableFromValue(
- features,
- blockName,
- variableStylePath,
- presetPropertyValue
-) {
- if ( ! presetPropertyValue ) {
- return presetPropertyValue;
- }
-
- const cssVarInfix = STYLE_PATH_TO_CSS_VAR_INFIX[ variableStylePath ];
-
- const metadata = PRESET_METADATA.find(
- ( data ) => data.cssVarInfix === cssVarInfix
- );
-
- if ( ! metadata ) {
- // The property doesn't have preset data
- // so the value should be returned as it is.
- return presetPropertyValue;
- }
- const { valueKey, path } = metadata;
-
- const presetObject = findInPresetsBy(
- features,
- blockName,
- path,
- valueKey,
- presetPropertyValue
- );
-
- if ( ! presetObject ) {
- // Value wasn't found in the presets,
- // so it must be a custom value.
- return presetPropertyValue;
- }
-
- return `var:preset|${ cssVarInfix }|${ presetObject.slug }`;
-}
-
-function getValueFromPresetVariable(
- features,
- blockName,
- variable,
- [ presetType, slug ]
-) {
- const metadata = PRESET_METADATA.find(
- ( data ) => data.cssVarInfix === presetType
- );
- if ( ! metadata ) {
- return variable;
- }
-
- const presetObject = findInPresetsBy(
- features.settings,
- blockName,
- metadata.path,
- 'slug',
- slug
- );
-
- if ( presetObject ) {
- const { valueKey } = metadata;
- const result = presetObject[ valueKey ];
- return getValueFromVariable( features, blockName, result );
- }
-
- return variable;
-}
-
-function getValueFromCustomVariable( features, blockName, variable, path ) {
- const result =
- get( features.settings, [ 'blocks', blockName, 'custom', ...path ] ) ??
- get( features.settings, [ 'custom', ...path ] );
- if ( ! result ) {
- return variable;
- }
- // A variable may reference another variable so we need recursion until we find the value.
- return getValueFromVariable( features, blockName, result );
-}
-
-/**
- * Attempts to fetch the value of a theme.json CSS variable.
- *
- * @param {Object} features GlobalStylesContext config, e.g., user, base or merged. Represents the theme.json tree.
- * @param {string} blockName The name of a block as represented in the styles property. E.g., 'root' for root-level, and 'core/${blockName}' for blocks.
- * @param {string|*} variable An incoming style value. A CSS var value is expected, but it could be any value.
- * @return {string|*|{ref}} The value of the CSS var, if found. If not found, the passed variable argument.
- */
-export function getValueFromVariable( features, blockName, variable ) {
- if ( ! variable || typeof variable !== 'string' ) {
- if ( variable?.ref && typeof variable?.ref === 'string' ) {
- const refPath = variable.ref.split( '.' );
- variable = get( features, refPath );
- // Presence of another ref indicates a reference to another dynamic value.
- // Pointing to another dynamic value is not supported.
- if ( ! variable || !! variable?.ref ) {
- return variable;
- }
- } else {
- return variable;
- }
- }
- const USER_VALUE_PREFIX = 'var:';
- const THEME_VALUE_PREFIX = 'var(--wp--';
- const THEME_VALUE_SUFFIX = ')';
-
- let parsedVar;
-
- if ( variable.startsWith( USER_VALUE_PREFIX ) ) {
- parsedVar = variable.slice( USER_VALUE_PREFIX.length ).split( '|' );
- } else if (
- variable.startsWith( THEME_VALUE_PREFIX ) &&
- variable.endsWith( THEME_VALUE_SUFFIX )
- ) {
- parsedVar = variable
- .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) )`
- return variable;
- }
-
- const [ type, ...path ] = parsedVar;
- if ( type === 'preset' ) {
- return getValueFromPresetVariable(
- features,
- blockName,
- variable,
- path
- );
- }
- if ( type === 'custom' ) {
- return getValueFromCustomVariable(
- features,
- blockName,
- variable,
- path
- );
- }
- return variable;
-}
-
-/**
- * Function that scopes a selector with another one. This works a bit like
- * SCSS nesting except the `&` operator isn't supported.
- *
- * @example
- * ```js
- * const scope = '.a, .b .c';
- * const selector = '> .x, .y';
- * const merged = scopeSelector( scope, selector );
- * // merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
- * ```
- *
- * @param {string} scope Selector to scope to.
- * @param {string} selector Original selector.
- *
- * @return {string} Scoped selector.
- */
-export function scopeSelector( scope, selector ) {
- const scopes = scope.split( ',' );
- const selectors = selector.split( ',' );
-
- const selectorsScoped = [];
- scopes.forEach( ( outer ) => {
- selectors.forEach( ( inner ) => {
- selectorsScoped.push( `${ outer.trim() } ${ inner.trim() }` );
- } );
- } );
-
- return selectorsScoped.join( ', ' );
-}
-
/**
*
* @param {string} path The variation path in the Global Styles tree.
diff --git a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js b/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js
index 8f6df129a4e91b..d33beb68e5757a 100644
--- a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js
+++ b/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js
@@ -13,13 +13,17 @@ import { styles, moreVertical, seen } from '@wordpress/icons';
import { useDispatch, useSelect } from '@wordpress/data';
import { store as preferencesStore } from '@wordpress/preferences';
import { useState, useEffect } from '@wordpress/element';
+import { experiments as blockEditorExperiments } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import DefaultSidebar from './default-sidebar';
-import { GlobalStylesUI, useGlobalStylesReset } from '../global-styles';
+import { GlobalStylesUI } from '../global-styles';
import { store as editSiteStore } from '../../store';
+import { unlock } from '../../experiments';
+
+const { useGlobalStylesReset } = unlock( blockEditorExperiments );
export default function GlobalStylesSidebar() {
const [ canReset, onReset ] = useGlobalStylesReset();
diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js
index b44b2b7b259b4e..af38a19161ec3c 100644
--- a/packages/edit-site/src/components/style-book/index.js
+++ b/packages/edit-site/src/components/style-book/index.js
@@ -19,7 +19,10 @@ import {
getBlockFromExample,
createBlock,
} from '@wordpress/blocks';
-import { BlockPreview } from '@wordpress/block-editor';
+import {
+ BlockPreview,
+ experiments as blockEditorExperiments,
+} from '@wordpress/block-editor';
import { closeSmall } from '@wordpress/icons';
import { useResizeObserver } from '@wordpress/compose';
import { useMemo, memo } from '@wordpress/element';
@@ -27,7 +30,9 @@ import { useMemo, memo } from '@wordpress/element';
/**
* Internal dependencies
*/
-import { useStyle } from '../global-styles';
+import { unlock } from '../../experiments';
+
+const { useGlobalStyle } = unlock( blockEditorExperiments );
const SLOT_FILL_NAME = 'EditSiteStyleBook';
const { Slot: StyleBookSlot, Fill: StyleBookFill } =
@@ -81,8 +86,8 @@ function getExamples() {
function StyleBook( { isSelected, onSelect, onClose } ) {
const [ resizeObserver, sizes ] = useResizeObserver();
- const [ textColor ] = useStyle( 'color.text' );
- const [ backgroundColor ] = useStyle( 'color.background' );
+ const [ textColor ] = useGlobalStyle( 'color.text' );
+ const [ backgroundColor ] = useGlobalStyle( 'color.background' );
const examples = useMemo( getExamples, [] );
const tabs = useMemo(
() =>
diff --git a/packages/edit-site/src/experiments.js b/packages/edit-site/src/experiments.js
new file mode 100644
index 00000000000000..a5c54a29b44751
--- /dev/null
+++ b/packages/edit-site/src/experiments.js
@@ -0,0 +1,10 @@
+/**
+ * WordPress dependencies
+ */
+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/experiments';
+
+export const { lock, unlock } =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
+ '@wordpress/edit-site'
+ );
diff --git a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js
index 6d29de4fdc9eed..c23b184876eb93 100644
--- a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js
+++ b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js
@@ -11,6 +11,7 @@ import { createHigherOrderComponent } from '@wordpress/compose';
import {
InspectorAdvancedControls,
store as blockEditorStore,
+ experiments as blockEditorExperiments,
} from '@wordpress/block-editor';
import { BaseControl, Button } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
@@ -26,11 +27,68 @@ import { store as noticesStore } from '@wordpress/notices';
* Internal dependencies
*/
import { getSupportedGlobalStylesPanels } from '../../components/global-styles/hooks';
-import { GlobalStylesContext } from '../../components/global-styles/context';
-import {
- STYLE_PATH_TO_CSS_VAR_INFIX,
- STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE,
-} from '../../components/global-styles/utils';
+import { unlock } from '../../experiments';
+
+const { GlobalStylesContext } = unlock( blockEditorExperiments );
+
+// TODO: Temporary duplication of constant in @wordpress/block-editor. Can be
+// removed by moving PushChangesToGlobalStylesControl to
+// @wordpress/block-editor.
+const STYLE_PATH_TO_CSS_VAR_INFIX = {
+ 'color.background': 'color',
+ 'color.text': 'color',
+ 'elements.link.color.text': 'color',
+ 'elements.link.:hover.color.text': 'color',
+ 'elements.link.typography.fontFamily': 'font-family',
+ 'elements.link.typography.fontSize': 'font-size',
+ 'elements.button.color.text': 'color',
+ 'elements.button.color.background': 'color',
+ 'elements.button.typography.fontFamily': 'font-family',
+ 'elements.button.typography.fontSize': 'font-size',
+ 'elements.heading.color': 'color',
+ 'elements.heading.color.background': 'color',
+ 'elements.heading.typography.fontFamily': 'font-family',
+ 'elements.heading.gradient': 'gradient',
+ 'elements.heading.color.gradient': 'gradient',
+ 'elements.h1.color': 'color',
+ 'elements.h1.color.background': 'color',
+ 'elements.h1.typography.fontFamily': 'font-family',
+ 'elements.h1.color.gradient': 'gradient',
+ 'elements.h2.color': 'color',
+ 'elements.h2.color.background': 'color',
+ 'elements.h2.typography.fontFamily': 'font-family',
+ 'elements.h2.color.gradient': 'gradient',
+ 'elements.h3.color': 'color',
+ 'elements.h3.color.background': 'color',
+ 'elements.h3.typography.fontFamily': 'font-family',
+ 'elements.h3.color.gradient': 'gradient',
+ 'elements.h4.color': 'color',
+ 'elements.h4.color.background': 'color',
+ 'elements.h4.typography.fontFamily': 'font-family',
+ 'elements.h4.color.gradient': 'gradient',
+ 'elements.h5.color': 'color',
+ 'elements.h5.color.background': 'color',
+ 'elements.h5.typography.fontFamily': 'font-family',
+ 'elements.h5.color.gradient': 'gradient',
+ 'elements.h6.color': 'color',
+ 'elements.h6.color.background': 'color',
+ 'elements.h6.typography.fontFamily': 'font-family',
+ 'elements.h6.color.gradient': 'gradient',
+ 'color.gradient': 'gradient',
+ 'typography.fontSize': 'font-size',
+ 'typography.fontFamily': 'font-family',
+};
+
+// TODO: Temporary duplication of constant in @wordpress/block-editor. Can be
+// removed by moving PushChangesToGlobalStylesControl to
+// @wordpress/block-editor.
+const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = {
+ 'color.background': 'backgroundColor',
+ 'color.text': 'textColor',
+ 'color.gradient': 'gradient',
+ 'typography.fontSize': 'fontSize',
+ 'typography.fontFamily': 'fontFamily',
+};
function getChangesToPush( name, attributes ) {
return getSupportedGlobalStylesPanels( name ).flatMap( ( key ) => {
diff --git a/packages/experiments/src/implementation.js b/packages/experiments/src/implementation.js
index bf333b7e2646f8..b818a3669d8e7a 100644
--- a/packages/experiments/src/implementation.js
+++ b/packages/experiments/src/implementation.js
@@ -13,6 +13,7 @@ const CORE_MODULES_USING_EXPERIMENTS = [
'@wordpress/data',
'@wordpress/blocks',
'@wordpress/block-editor',
+ '@wordpress/edit-site',
];
/**