diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index 746c46fbf0a172..0a1ef42b0026fd 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { set, get } from 'lodash'; +import { set, get, mapValues } from 'lodash'; /** * WordPress dependencies @@ -15,11 +15,15 @@ import { } from '@wordpress/element'; import { useEntityProp } from '@wordpress/core-data'; import { __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY } from '@wordpress/blocks'; +import { useSelect, useDispatch } from '@wordpress/data'; /** * Internal dependencies */ -import getGlobalStyles from './global-styles-renderer'; +import { + default as getGlobalStyles, + mergeTrees, +} from './global-styles-renderer'; const EMPTY_CONTENT = '{}'; @@ -48,13 +52,20 @@ export const useGlobalStylesReset = () => { ]; }; -export default ( { children, baseStyles, contexts } ) => { +export default function GlobalStylesProvider( { + children, + baseStyles, + contexts, +} ) { const [ content, setContent ] = useGlobalStylesEntityContent(); - const userStyles = useMemo( - () => ( content ? JSON.parse( content ) : {} ), - [ content ] - ); + const { userStyles, mergedStyles } = useMemo( () => { + const parsedContent = content ? JSON.parse( content ) : {}; + return { + userStyles: parsedContent, + mergedStyles: mergeTrees( baseStyles, parsedContent ), + }; + }, [ content ] ); const nextValue = useMemo( () => ( { @@ -110,16 +121,27 @@ export default ( { children, baseStyles, contexts } ) => { .appendChild( styleNode ); } - styleNode.innerText = getGlobalStyles( - contexts, - baseStyles, - userStyles - ); + styleNode.innerText = getGlobalStyles( contexts, mergedStyles ); }, [ contexts, baseStyles, content ] ); + const settings = useSelect( ( select ) => + select( 'core/edit-site' ).getSettings() + ); + const { updateSettings } = useDispatch( 'core/edit-site' ); + + useEffect( () => { + updateSettings( { + ...settings, + __experimentalFeatures: mapValues( + mergedStyles, + ( value ) => value.settings || {} + ), + } ); + }, [ mergedStyles ] ); + return ( { children } ); -}; +} diff --git a/packages/edit-site/src/components/editor/global-styles-renderer.js b/packages/edit-site/src/components/editor/global-styles-renderer.js index 23de8d4876b8d7..d17c9459249923 100644 --- a/packages/edit-site/src/components/editor/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/global-styles-renderer.js @@ -13,39 +13,49 @@ import { __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY } from '@wordpress/bloc */ import { PRESET_CATEGORIES, LINK_COLOR_DECLARATION } from './utils'; -const mergeTrees = ( baseData, userData ) => { +export const mergeTrees = ( baseData, userData ) => { // Deep clone from base data. // // We don't use cloneDeep from lodash here // because we know the data is JSON compatible, // see https://github.com/lodash/lodash/issues/1984 - const mergedTree = JSON.parse( JSON.stringify( baseData ) ); + const mergedTree = baseData ? JSON.parse( JSON.stringify( baseData ) ) : {}; const styleKeys = [ 'typography', 'color' ]; + const settingKeys = [ 'typography', 'color', 'custom', 'spacing' ]; Object.keys( userData ).forEach( ( context ) => { styleKeys.forEach( ( key ) => { - // Normalize object shape: make sure the key exists under styles. + // Normalize object shape. if ( ! mergedTree[ context ].styles?.[ key ] ) { mergedTree[ context ].styles[ key ] = {}; } - - // Merge data: base + user. + // Merge base + user data. mergedTree[ context ].styles[ key ] = { ...mergedTree[ context ].styles[ key ], ...userData[ context ]?.styles?.[ key ], }; } ); + settingKeys.forEach( ( key ) => { + // Normalize object shape. + if ( ! mergedTree[ context ].settings?.[ key ] ) { + mergedTree[ context ].settings[ key ] = {}; + } + // Merge base + user data. + mergedTree[ context ].settings[ key ] = { + ...mergedTree[ context ].settings[ key ], + ...userData[ context ]?.settings?.[ key ], + }; + } ); } ); return mergedTree; }; -export default ( blockData, baseTree, userTree ) => { +export default ( blockData, tree ) => { const styles = []; // Can this be converted to a context, as the global context? // See comment in the server. styles.push( LINK_COLOR_DECLARATION ); - const tree = mergeTrees( baseTree, userTree ); /** * Transform given style tree into a set of style declarations. diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 5e6f676c2997a3..2272278608fc3e 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -211,3 +211,17 @@ export function setIsInserterOpened( isOpen ) { isOpen, }; } + +/** + * Returns an action object used to update the settings. + * + * @param {Object} settings New settings. + * + * @return {Object} Action object. + */ +export function updateSettings( settings ) { + return { + type: 'UPDATE_SETTINGS', + settings, + }; +}