Skip to content

Commit

Permalink
Add link color as an element mechanism.
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgefilipecosta committed May 7, 2021
1 parent 236df22 commit 04039af
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 32 deletions.
63 changes: 63 additions & 0 deletions lib/block-supports/elements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/**
* Elements styles block support.
*
* @package gutenberg
*/

/**
* Render out the duotone stylesheet and SVG.
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function gutenberg_render_elements_support( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );

/*
* For now we only care about link color.
* This code in the future when we have a public API
* should take advantage of WP_Theme_JSON::compute_style_properties
* and work for any element and style.
*/
if ( null === $link_color ) {
return $block_content;
}
$class_name = 'wp-block-elements-container-' . uniqid();

if ( strpos( $link_color, 'var:preset|color|' ) !== false ) {
// Get the name from the string and add proper styles.
$index_to_splice = strrpos( $link_color, '|' ) + 1;
$link_color_name = substr( $link_color, $index_to_splice );
$link_color = "var(--wp--preset--color--$link_color_name)";
}

$style = "<style>.$class_name a{color: $link_color;}</style>\n";

// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
// Retrieve the opening tag of the first HTML element.
$html_element_matches;
preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
$first_element = $html_element_matches[0][0];
// If the first HTML element has a class attribute just add the new class
// as we do on layout and duotone.
if ( strpos( $first_element, 'class="' ) !== false ) {
$content = preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="' . $class_name . ' ',
$block_content,
1
);
} else {
// If the first HTML has no class attribute we should inject the attribute before the attribute at the end.
$first_element_offset = $html_element_matches[0][1];
$content = substr_replace( $block_content, ' class="' . $class_name . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
}
return $content . $style;

}


add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 );
4 changes: 3 additions & 1 deletion lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function gutenberg_experimental_global_styles_get_stylesheet( $tree, $type = 'al
*/
function gutenberg_experimental_global_styles_enqueue_assets() {
if (
! get_theme_support( 'experimental-link-color' ) && // link color support needs the presets CSS variables regardless of the presence of theme.json file.
! WP_Theme_JSON_Resolver::theme_has_support() ) {
return;
}
Expand Down Expand Up @@ -124,7 +125,8 @@ function_exists( 'gutenberg_is_edit_site_page' ) &&
$settings['__experimentalGlobalStylesUserEntityId'] = $user_cpt_id;
$settings['__experimentalGlobalStylesBaseStyles'] = $base_styles;
} elseif (
WP_Theme_JSON_Resolver::theme_has_support()
WP_Theme_JSON_Resolver::theme_has_support() ||
get_theme_support( 'experimental-link-color' ) // link color support needs the presets CSS variables regardless of the presence of theme.json file.
) {
// STEP 3 - ADD STYLES IF THEME HAS SUPPORT
//
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/query-utils.php';

require __DIR__ . '/block-supports/generated-classname.php';
require __DIR__ . '/block-supports/elements.php';
require __DIR__ . '/block-supports/colors.php';
require __DIR__ . '/block-supports/align.php';
require __DIR__ . '/block-supports/typography.php';
Expand Down
28 changes: 13 additions & 15 deletions packages/block-editor/src/hooks/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import { isObject } from 'lodash';
import { isObject, setWith, clone } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -303,17 +303,15 @@ 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,
},
},
} );
const newStyle = setWith(
style ? clone( style ) : {},
[ 'elements', 'link', 'color', 'text' ],
colorObject?.slug
? `var:preset|color|${ colorObject.slug }`
: value,
clone
);
props.setAttributes( { style: newStyle } );
};

return (
Expand Down Expand Up @@ -363,10 +361,10 @@ export function ColorEdit( props ) {
onColorChange: onChangeLinkColor,
colorValue: getLinkColorFromAttributeValue(
colors,
style?.color?.link
style?.elements?.link?.color?.text
),
clearable: !! props.attributes.style?.color
?.link,
clearable: !! style?.elements?.link?.color
?.text,
},
]
: [] ),
Expand Down
92 changes: 89 additions & 3 deletions packages/block-editor/src/hooks/style.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
/**
* External dependencies
*/
import { capitalize, get, has, omit, omitBy, startsWith } from 'lodash';
import {
capitalize,
kebabCase,
get,
has,
map,
omit,
omitBy,
startsWith,
isEmpty,
first,
} from 'lodash';
import classnames from 'classnames';

/**
* WordPress dependencies
Expand All @@ -12,7 +24,7 @@ import {
hasBlockSupport,
__EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY,
} from '@wordpress/blocks';
import { createHigherOrderComponent } from '@wordpress/compose';
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -31,6 +43,16 @@ const styleSupportKeys = [
SPACING_SUPPORT_KEY,
];

export const ELEMENTS = {
link: 'a',
h1: 'h1',
h2: 'h2',
h3: 'h3',
h4: 'h4',
h5: 'h5',
h6: 'h6',
};

const hasStyleSupport = ( blockType ) =>
styleSupportKeys.some( ( key ) => hasBlockSupport( blockType, key ) );

Expand Down Expand Up @@ -59,7 +81,8 @@ export function getInlineStyles( styles = {} ) {
Object.keys( STYLE_PROPERTY ).forEach( ( propKey ) => {
const path = STYLE_PROPERTY[ propKey ].value;
const subPaths = STYLE_PROPERTY[ propKey ].properties;
if ( has( styles, path ) ) {
// Ignore styles on elements because they are handled on the server.
if ( has( styles, path ) && 'elements' !== first( path ) ) {
if ( !! subPaths ) {
subPaths.forEach( ( suffix ) => {
output[
Expand All @@ -75,6 +98,24 @@ export function getInlineStyles( styles = {} ) {
return output;
}

function compileElementsStyles( selector, elements = {} ) {
return map( elements, ( styles, element ) => {
const linearStyles = getInlineStyles( styles );
if ( ! isEmpty( linearStyles ) ) {
return [
`.${ selector } ${ ELEMENTS[ element ] }{`,
...map(
linearStyles,
( value, property ) =>
`\t${ kebabCase( property ) }: ${ value }`
),
'}',
].join( '\n' );
}
return '';
} ).join( '\n' );
}

/**
* Filters registered block settings, extending attributes to include `style` attribute.
*
Expand Down Expand Up @@ -202,6 +243,45 @@ export const withBlockControls = createHigherOrderComponent(
'withToolbarControls'
);

/**
* Override the default block element to include duotone styles.
*
* @param {Function} BlockListBlock Original component
* @return {Function} Wrapped component
*/
const withElementsStyles = createHigherOrderComponent(
( BlockListBlock ) => ( props ) => {
const elements = props.attributes.style?.elements;
if ( ! elements ) {
return <BlockListBlock { ...props } />;
}
const blockElementsContainerIdentifier = `wp-block-elements-container-${ useInstanceId(
BlockListBlock
) }`;
const styles = compileElementsStyles(
blockElementsContainerIdentifier,
props.attributes.style?.elements
);

return (
<>
<style
dangerouslySetInnerHTML={ {
__html: styles,
} }
/>
<BlockListBlock
{ ...props }
className={ classnames(
props.classname,
blockElementsContainerIdentifier
) }
/>
</>
);
}
);

addFilter(
'blocks.registerBlockType',
'core/style/addAttribute',
Expand All @@ -225,3 +305,9 @@ addFilter(
'core/style/with-block-controls',
withBlockControls
);

addFilter(
'editor.BlockListBlock',
'core/editor/with-elements-styles',
withElementsStyles
);
4 changes: 4 additions & 0 deletions packages/blocks/src/api/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
value: [ 'color', 'text' ],
support: [ 'color' ],
},
linkColor: {
value: [ 'elements', 'link', 'color', 'text' ],
support: [ 'color', 'link' ],
},
fontFamily: {
value: [ 'typography', 'fontFamily' ],
support: [ '__experimentalFontFamily' ],
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/editor/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { store as editSiteStore } from '../../store';
export const ROOT_BLOCK_NAME = 'root';
export const ROOT_BLOCK_SELECTOR = 'body';
export const ROOT_BLOCK_SUPPORTS = [
//'--wp--style--color--link',
'background',
'backgroundColor',
'color',
'linkColor',
'fontFamily',
'fontSize',
'fontStyle',
Expand Down
24 changes: 12 additions & 12 deletions packages/edit-site/src/components/sidebar/color-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export function useHasColorPanel( { supports } ) {
return (
supports.includes( 'color' ) ||
supports.includes( 'backgroundColor' ) ||
supports.includes( 'background' )
//supports.includes( LINK_COLOR )
supports.includes( 'background' ) ||
supports.includes( 'linkColor' )
);
}

Expand Down Expand Up @@ -87,16 +87,16 @@ export default function ColorPanel( {
} );
}

//if ( supports.includes( LINK_COLOR ) ) {
// const color = getStyle( name, LINK_COLOR );
// const userColor = getStyle( name, LINK_COLOR, 'user' );
// settings.push( {
// colorValue: color,
// onColorChange: ( value ) => setStyle( name, LINK_COLOR, value ),
// label: __( 'Link color' ),
// clearable: color === userColor,
// } );
//}
if ( supports.includes( 'linkColor' ) ) {
const color = getStyle( name, 'linkColor' );
const userColor = getStyle( name, 'linkColor', 'user' );
settings.push( {
colorValue: color,
onColorChange: ( value ) => setStyle( name, 'linkColor', value ),
label: __( 'Link color' ),
clearable: color === userColor,
} );
}
return (
<PanelColorGradientSettings
title={ __( 'Color' ) }
Expand Down

0 comments on commit 04039af

Please sign in to comment.