From d35b1239bf9a413f1835880ca0e4256ae4e935d9 Mon Sep 17 00:00:00 2001 From: Jorge Date: Fri, 29 May 2020 13:11:08 +0100 Subject: [PATCH] Update: Make global styles shape consistent with local styles shape. --- lib/experimental-default-theme.json | 5 + lib/global-styles.php | 27 ++--- .../components/colors-gradients/control.js | 5 +- packages/block-editor/src/hooks/color.js | 48 ++++++++ packages/block-editor/src/hooks/style.js | 105 +++++++++++++++--- packages/block-library/src/columns/block.json | 3 +- packages/block-library/src/group/block.json | 3 +- packages/block-library/src/heading/block.json | 4 +- .../block-library/src/media-text/block.json | 3 +- .../block-library/src/paragraph/block.json | 5 +- packages/block-library/src/style.scss | 3 + .../editor/src/components/provider/index.js | 1 + 12 files changed, 175 insertions(+), 37 deletions(-) diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index 1d1cfdabce390f..179633d51a9957 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -128,6 +128,11 @@ "typography": { "dropCap": false } + }, + "styles": { + "color": { + "link": "#00e" + } } } } diff --git a/lib/global-styles.php b/lib/global-styles.php index c2f9eb250646fc..faedf9a7d853c7 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -324,11 +324,12 @@ function gutenberg_experimental_global_styles_get_block_data() { */ function gutenberg_experimental_global_styles_flatten_styles_tree( $styles ) { $mappings = array( - 'line-height' => array( 'typography', 'lineHeight' ), - 'font-size' => array( 'typography', 'fontSize' ), - 'background' => array( 'color', 'gradient' ), - 'background-color' => array( 'color', 'background' ), - 'color' => array( 'color', 'text' ), + 'line-height' => array( 'typography', 'lineHeight' ), + 'font-size' => array( 'typography', 'fontSize' ), + 'background' => array( 'color', 'gradient' ), + 'background-color' => array( 'color', 'background' ), + 'color' => array( 'color', 'text' ), + '--wp--color--link' => array( 'color', 'link' ), ); $result = array(); @@ -502,10 +503,6 @@ function gutenberg_experimental_global_styles_get_stylesheet() { * and enqueues the resulting stylesheet. */ function gutenberg_experimental_global_styles_enqueue_assets() { - if ( ! gutenberg_experimental_global_styles_has_theme_json_support() ) { - return; - } - $stylesheet = gutenberg_experimental_global_styles_get_stylesheet(); wp_register_style( 'global-styles', false, array(), true, true ); @@ -520,18 +517,18 @@ function gutenberg_experimental_global_styles_enqueue_assets() { * @return array New block editor settings */ function gutenberg_experimental_global_styles_settings( $settings ) { - if ( ! gutenberg_experimental_global_styles_has_theme_json_support() ) { - return $settings; - } - $settings['__experimentalGlobalStylesUserEntityId'] = gutenberg_experimental_global_styles_get_user_cpt_id(); - $global_styles = gutenberg_experimental_global_styles_merge_trees( + $global_styles_base = gutenberg_experimental_global_styles_merge_trees( gutenberg_experimental_global_styles_get_core(), gutenberg_experimental_global_styles_get_theme() ); - $settings['__experimentalGlobalStylesBase'] = $global_styles; + $settings['__experimentalGlobalStylesBase'] = $global_styles_base; + $settings['__experimentalGlobalStyles'] = gutenberg_experimental_global_styles_merge_trees( + $global_styles_base, + gutenberg_experimental_global_styles_get_user() + ); // Add the styles for the editor via the settings // so they get processed as if they were added via add_editor_styles: diff --git a/packages/block-editor/src/components/colors-gradients/control.js b/packages/block-editor/src/components/colors-gradients/control.js index 1d167f4b77f3d4..9b9fea52186a72 100644 --- a/packages/block-editor/src/components/colors-gradients/control.js +++ b/packages/block-editor/src/components/colors-gradients/control.js @@ -88,6 +88,7 @@ function ColorGradientControlInner( { onGradientChange, colorValue, gradientValue, + clearable, } ) { const canChooseAColor = onColorChange && ( ! isEmpty( colors ) || ! disableCustomColors ); @@ -152,7 +153,7 @@ function ColorGradientControlInner( { } : onColorChange } - { ...{ colors, disableCustomColors } } + { ...{ colors, disableCustomColors, clearable } } /> ) } { ( currentTab === 'gradient' || ! canChooseAColor ) && ( @@ -166,7 +167,7 @@ function ColorGradientControlInner( { } : onGradientChange } - { ...{ gradients, disableCustomGradients } } + { ...{ gradients, disableCustomGradients, clearable } } /> ) } diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index c4f80ff9c02ef0..0fde1641b6faa8 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -34,6 +34,16 @@ export const COLOR_SUPPORT_KEY = '__experimentalColor'; const hasColorSupport = ( blockType ) => Platform.OS === 'web' && hasBlockSupport( blockType, COLOR_SUPPORT_KEY ); +const hasLinkColorSupport = ( blockType ) => { + if ( Platform.OS !== 'web' ) { + return false; + } + + const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY ); + + return isObject( colorSupport ) && !! colorSupport.linkColor; +}; + const hasGradientSupport = ( blockType ) => { if ( Platform.OS !== 'web' ) { return false; @@ -151,6 +161,15 @@ export function addEditProps( settings ) { return settings; } +const getLinkColorFromAttributeValue = ( colors, value ) => { + const attributeParsed = /var:preset\|color\|(.+)/.exec( value ); + if ( attributeParsed && attributeParsed[ 1 ] ) { + return getColorObjectByAttributeValues( colors, attributeParsed[ 1 ] ) + .color; + } + return value; +}; + /** * Inspector control panel containing the color related configuration * @@ -245,6 +264,21 @@ export function ColorEdit( props ) { }; }; + const onChangeLinkColor = ( value ) => { + const colorObject = getColorObjectByColorValue( colors, value ); + props.setAttributes( { + style: { + ...props.attributes.style, + color: { + ...props.attributes.style?.color, + link: colorObject?.slug + ? `var:preset|color|${ colorObject.slug }` + : value, + }, + }, + } ); + }; + return ( ); diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index f23a5c2612e2bc..9bdb535de4f03c 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { has, get } from 'lodash'; +import { has, get, startsWith, reduce, merge } from 'lodash'; /** * WordPress dependencies @@ -11,7 +11,13 @@ import { hasBlockSupport } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { PanelBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { Platform } from '@wordpress/element'; +import { + Platform, + createContext, + useContext, + useMemo, +} from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -35,6 +41,20 @@ const typographySupportKeys = [ const hasStyleSupport = ( blockType ) => styleSupportKeys.some( ( key ) => hasBlockSupport( blockType, key ) ); +const VARIABLE_REFERENCE_PREFIX = 'var:'; +const VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE = '|'; +const VARIABLE_PATH_SEPARATOR_TOKEN_STYLE = '--'; +function compileStyleValue( uncompiledValue ) { + if ( startsWith( uncompiledValue, VARIABLE_REFERENCE_PREFIX ) ) { + const variable = uncompiledValue + .slice( VARIABLE_REFERENCE_PREFIX.length ) + .split( VARIABLE_PATH_SEPARATOR_TOKEN_ATTRIBUTE ) + .join( VARIABLE_PATH_SEPARATOR_TOKEN_STYLE ); + return `var(--wp--${ variable })`; + } + return uncompiledValue; +} + /** * Returns the inline styles to add depending on the style object * @@ -48,12 +68,13 @@ export function getInlineStyles( styles = {} ) { background: [ 'color', 'gradient' ], backgroundColor: [ 'color', 'background' ], color: [ 'color', 'text' ], + '--wp--color--link': [ 'color', 'link' ], }; const output = {}; Object.entries( mappings ).forEach( ( [ styleKey, objectKey ] ) => { if ( has( styles, objectKey ) ) { - output[ styleKey ] = get( styles, objectKey ); + output[ styleKey ] = compileStyleValue( get( styles, objectKey ) ); } } ); @@ -130,6 +151,18 @@ export function addEditProps( settings ) { return settings; } +const GlobalStylesContext = createContext( {} ); + +// Todo: Move this specification to the block.json +const selectorMapping = { + 'core/heading/h1': ( { level } ) => level === 1, + 'core/heading/h2': ( { level } ) => level === 2, + 'core/heading/h3': ( { level } ) => level === 3, + 'core/heading/h4': ( { level } ) => level === 4, + 'core/heading/h5': ( { level } ) => level === 5, + 'core/heading/h6': ( { level } ) => level === 6, +}; + /** * Override the default edit UI to include new inspector controls for * all the custom styles configs. @@ -144,18 +177,60 @@ export const withBlockControls = createHigherOrderComponent( hasBlockSupport( blockName, key ) ); - return [ - Platform.OS === 'web' && hasTypographySupport && ( - - - - - - - ), - , - , - ]; + const { __experimentalGlobalStyles } = useSelect( ( select ) => { + return select( 'core/block-editor' ).getSettings(); + }, [] ); + const globalStylesContext = useContext( GlobalStylesContext ); + + const globalStylesBlock = useMemo( () => { + const globalBlockSpecificStyles = reduce( + __experimentalGlobalStyles, + ( accumulator, value, selector ) => { + if ( + selector === blockName || + ( selector.startsWith( blockName + '/' ) && + selectorMapping[ selector ] && + selectorMapping[ selector ]( props.attributes ) ) + ) { + return merge( accumulator, value.styles ); + } + return accumulator; + }, + {} + ); + + // The styles are merged according the following priority: + // First: Local block styles. + // Second: Styles targeting the block specifically. + // Third: Styles inherited from the parent blocks. + // Forth: The global styles applied to the root. + return merge( + {}, + __experimentalGlobalStyles?.global?.styles || {}, + globalStylesContext || {}, + globalBlockSpecificStyles, + props.attributes.style || {} + ); + } ); + + return ( + + { Platform.OS === 'web' && hasTypographySupport && ( + + + + + + + ) } + + + + ); }, 'withToolbarControls' ); diff --git a/packages/block-library/src/columns/block.json b/packages/block-library/src/columns/block.json index a27c693b8134b8..352b1e5caaaa48 100644 --- a/packages/block-library/src/columns/block.json +++ b/packages/block-library/src/columns/block.json @@ -14,7 +14,8 @@ "html": false, "lightBlockWrapper": true, "__experimentalColor": { - "gradients": true + "gradients": true, + "linkColor": true } } } diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index ab4e81aa334426..1e32b1443cbc85 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -16,7 +16,8 @@ "html": false, "lightBlockWrapper": true, "__experimentalColor": { - "gradients": true + "gradients": true, + "linkColor": true } } } diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index eb367c9c4bf735..a3618fc0793147 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -24,7 +24,9 @@ "anchor": true, "__unstablePasteTextInline": true, "lightBlockWrapper": true, - "__experimentalColor": true, + "__experimentalColor": { + "linkColor": true + }, "__experimentalLineHeight": true, "__experimentalFontSize": true } diff --git a/packages/block-library/src/media-text/block.json b/packages/block-library/src/media-text/block.json index 71a706fe1f3a69..91f12cf51b460c 100644 --- a/packages/block-library/src/media-text/block.json +++ b/packages/block-library/src/media-text/block.json @@ -84,7 +84,8 @@ ], "html": false, "__experimentalColor": { - "gradients": true + "gradients": true, + "linkColor": true } } } diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index ae17bc373f2062..a121b9155217f2 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -30,7 +30,10 @@ "className": false, "__unstablePasteTextInline": true, "lightBlockWrapper": true, - "__experimentalColor": true, + "__experimentalColor": { + "linkColor": true + }, + "__experimentalLinkColor": true, "__experimentalLineHeight": true, "__experimentalFontSize": true, "__experimentalFeatures": { diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index deb2c477fb80b5..d6d233b96945c6 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -234,6 +234,9 @@ background: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%); } /* stylelint-enable function-comma-space-after */ + a { + color: var(--wp--color--link); + } } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 074f93fe2ae1ff..76bab9510edc14 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -121,6 +121,7 @@ class EditorProvider extends Component { '__experimentalEnableFullSiteEditingDemo', '__experimentalFeatures', '__experimentalGlobalStylesUserEntityId', + '__experimentalGlobalStyles', '__experimentalGlobalStylesBase', '__experimentalPreferredStyleVariations', 'alignWide',