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 ac4c04f1d53f43..9b4730a7bb1fc4 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 @@ -16,7 +16,7 @@ import { import { BaseControl, Button } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { - __EXPERIMENTAL_STYLE_PROPERTY, + __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY, getBlockType, hasBlockSupport, } from '@wordpress/blocks'; @@ -30,23 +30,14 @@ import { store as noticesStore } from '@wordpress/notices'; import { useSupportedStyles } from '../../components/global-styles/hooks'; import { unlock } from '../../lock-unlock'; -const { cleanEmptyObject, GlobalStylesContext, useBlockEditingMode } = unlock( +const { GlobalStylesContext, useBlockEditingMode } = unlock( blockEditorPrivateApis ); -// Block Gap is a special case and isn't defined within the blocks -// style properties config. We'll add it here to allow it to be pushed -// to global styles as well. -const STYLE_PROPERTY = { - ...__EXPERIMENTAL_STYLE_PROPERTY, - blockGap: { value: [ 'spacing', 'blockGap' ] }, -}; - // 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 = { - 'border.color': 'color', 'color.background': 'color', 'color.text': 'color', 'elements.link.color.text': 'color', @@ -88,7 +79,6 @@ const STYLE_PATH_TO_CSS_VAR_INFIX = { 'elements.h6.typography.fontFamily': 'font-family', 'elements.h6.color.gradient': 'gradient', 'color.gradient': 'gradient', - blockGap: 'spacing', 'typography.fontSize': 'font-size', 'typography.fontFamily': 'font-family', }; @@ -97,7 +87,6 @@ const STYLE_PATH_TO_CSS_VAR_INFIX = { // removed by moving PushChangesToGlobalStylesControl to // @wordpress/block-editor. const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = { - 'border.color': 'borderColor', 'color.background': 'backgroundColor', 'color.text': 'textColor', 'color.gradient': 'gradient', @@ -107,124 +96,30 @@ const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = { const SUPPORTED_STYLES = [ 'border', 'color', 'spacing', 'typography' ]; -const flatBorderProperties = [ 'borderColor', 'borderWidth', 'borderStyle' ]; -const sides = [ 'top', 'right', 'bottom', 'left' ]; - -function getBorderStyleChanges( border, presetColor, userStyle ) { - if ( ! border && ! presetColor ) { - return []; - } - - const changes = [ - ...getFallbackBorderStyleChange( 'top', border, userStyle ), - ...getFallbackBorderStyleChange( 'right', border, userStyle ), - ...getFallbackBorderStyleChange( 'bottom', border, userStyle ), - ...getFallbackBorderStyleChange( 'left', border, userStyle ), - ]; - - // Handle a flat border i.e. all sides the same, CSS shorthand. - const { color: customColor, style, width } = border || {}; - const hasColorOrWidth = presetColor || customColor || width; - - if ( hasColorOrWidth && ! style ) { - // Global Styles need individual side configurations to overcome - // theme.json configurations which are per side as well. - sides.forEach( ( side ) => { - // Only add fallback border-style if global styles don't already - // have something set. - if ( ! userStyle?.[ side ]?.style ) { - changes.push( { - path: [ 'border', side, 'style' ], - value: 'solid', - } ); - } - } ); - } - - return changes; -} - -function getFallbackBorderStyleChange( side, border, globalBorderStyle ) { - if ( ! border?.[ side ] || globalBorderStyle?.[ side ]?.style ) { - return []; - } - - const { color, style, width } = border[ side ]; - const hasColorOrWidth = color || width; - - if ( ! hasColorOrWidth || style ) { - return []; - } - - return [ { path: [ 'border', side, 'style' ], value: 'solid' } ]; -} - -function useChangesToPush( name, attributes, userConfig ) { +function useChangesToPush( name, attributes ) { const supports = useSupportedStyles( name ); - const blockUserConfig = userConfig?.styles?.blocks?.[ name ]; - - return useMemo( () => { - const changes = supports.flatMap( ( key ) => { - if ( ! STYLE_PROPERTY[ key ] ) { - return []; - } - const { value: path } = STYLE_PROPERTY[ key ]; - const presetAttributeKey = path.join( '.' ); - const presetAttributeValue = - attributes[ - STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE[ presetAttributeKey ] - ]; - const value = presetAttributeValue - ? `var:preset|${ STYLE_PATH_TO_CSS_VAR_INFIX[ presetAttributeKey ] }|${ presetAttributeValue }` - : get( attributes.style, path ); - // Links only have a single support entry but have two element - // style properties, color and hover color. The following check - // will add the hover color to the changes if required. - if ( key === 'linkColor' ) { - const linkChanges = value ? [ { path, value } ] : []; - const hoverPath = [ - 'elements', - 'link', - ':hover', - 'color', - 'text', - ]; - const hoverValue = get( attributes.style, hoverPath ); - - if ( hoverValue ) { - linkChanges.push( { path: hoverPath, value: hoverValue } ); + return useMemo( + () => + supports.flatMap( ( key ) => { + if ( ! STYLE_PROPERTY[ key ] ) { + return []; } - - return linkChanges; - } - - // The shorthand border styles can't be mapped directly as global - // styles requires longhand config. - if ( flatBorderProperties.includes( key ) && value ) { - // The shorthand config path is included to clear the block attribute. - const borderChanges = [ { path, value } ]; - sides.forEach( ( side ) => { - const currentPath = [ ...path ]; - currentPath.splice( -1, 0, side ); - borderChanges.push( { path: currentPath, value } ); - } ); - return borderChanges; - } - - return value ? [ { path, value } ] : []; - } ); - - // To ensure display of a visible border, global styles require a - // default border style if a border color or width is present. - getBorderStyleChanges( - attributes.style?.border, - attributes.borderColor, - blockUserConfig?.border - ).forEach( ( change ) => changes.push( change ) ); - - return changes; - }, [ supports, attributes, blockUserConfig ] ); + const { value: path } = STYLE_PROPERTY[ key ]; + const presetAttributeKey = path.join( '.' ); + const presetAttributeValue = + attributes[ + STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE[ + presetAttributeKey + ] + ]; + const value = presetAttributeValue + ? `var:preset|${ STYLE_PATH_TO_CSS_VAR_INFIX[ presetAttributeKey ] }|${ presetAttributeValue }` + : get( attributes.style, path ); + return value ? [ { path, value } ] : []; + } ), + [ supports, name, attributes ] + ); } function cloneDeep( object ) { @@ -236,11 +131,11 @@ function PushChangesToGlobalStylesControl( { attributes, setAttributes, } ) { + const changes = useChangesToPush( name, attributes ); + const { user: userConfig, setUserConfig } = useContext( GlobalStylesContext ); - const changes = useChangesToPush( name, attributes, userConfig ); - const { __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); const { createSuccessNotice } = useDispatch( noticesStore ); @@ -260,22 +155,12 @@ function PushChangesToGlobalStylesControl( { set( newUserConfig, [ 'styles', 'blocks', name, ...path ], value ); } - const newBlockAttributes = { - borderColor: undefined, - backgroundColor: undefined, - textColor: undefined, - gradient: undefined, - fontSize: undefined, - fontFamily: undefined, - style: cleanEmptyObject( newBlockStyles ), - }; - // @wordpress/core-data doesn't support editing multiple entity types in // a single undo level. So for now, we disable @wordpress/core-data undo // tracking and implement our own Undo button in the snackbar // notification. __unstableMarkNextChangeAsNotPersistent(); - setAttributes( newBlockAttributes ); + setAttributes( { style: newBlockStyles } ); setUserConfig( () => newUserConfig, { undoIgnore: true } ); createSuccessNotice( @@ -291,7 +176,7 @@ function PushChangesToGlobalStylesControl( { label: __( 'Undo' ), onClick() { __unstableMarkNextChangeAsNotPersistent(); - setAttributes( attributes ); + setAttributes( { style: blockStyles } ); setUserConfig( () => userConfig, { undoIgnore: true, } ); @@ -300,16 +185,7 @@ function PushChangesToGlobalStylesControl( { ], } ); - }, [ - __unstableMarkNextChangeAsNotPersistent, - attributes, - changes, - createSuccessNotice, - name, - setAttributes, - setUserConfig, - userConfig, - ] ); + }, [ changes, attributes, userConfig, name ] ); return (