diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 3544f580367101..45936e4b3e5473 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -115,7 +115,14 @@ public static function set_global_style_block_names() { continue; } // If it has a duotone filter preset, save the block name and the preset slug. - $slug = self::gutenberg_get_slug_from_attr( $duotone_attr ); + if ( is_string( $duotone_attr ) ) { + $slug = self::gutenberg_get_slug_from_attr( $duotone_attr ); + // If the block has custom colors, we generate a slug for it and save it. + } else { + $slug = self::custom_unique_slug( $duotone_attr ); + self::$global_styles_presets[ $slug ]['slug'] = $slug; + self::$global_styles_presets[ $slug ]['colors'] = $duotone_attr; + } if ( $slug && $slug !== $duotone_attr ) { self::$global_styles_block_names[ $block_node['name'] ] = $slug; @@ -247,6 +254,16 @@ public static function output_global_styles() { } } + /** + * Generate a unique slug for the filter based on the array of colors. + * + * @param string $duotone_attr The duotone attribute from a block. + * @return string A unique string that defines the custom filter. + */ + public static function custom_unique_slug( $duotone_attr ) { + return wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); + } + /** * Render out the duotone CSS styles and SVG. * @@ -304,8 +321,8 @@ public static function render_duotone_support( $block_content, $block ) { // Pass through the CSS value. $declaration_value = $duotone_attr; } elseif ( $is_custom ) { - // Build a unique slug for the filter based on the array of colors. - $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); + + $slug = self::custom_unique_slug( $duotone_attr ); $filter_data = array( 'slug' => $slug, diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index cce2b61f0786e7..887b2e01b6840a 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -15,6 +15,7 @@ import { import { useSelect } from '@wordpress/data'; import { useContext, useMemo } from '@wordpress/element'; import { getCSSRules } from '@wordpress/style-engine'; +import { cleanForSlug } from '@wordpress/url'; /** * Internal dependencies @@ -23,7 +24,7 @@ import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils'; import { getTypographyFontSizeValue } from './typography-utils'; import { GlobalStylesContext } from './context'; import { useGlobalSetting } from './hooks'; -import { PresetDuotoneFilter } from '../duotone/components'; +import { PresetDuotoneFilter, DuotoneFilter } from '../duotone/components'; import { getGapCSSValue } from '../../hooks/gap'; import { store as blockEditorStore } from '../../store'; @@ -260,11 +261,20 @@ export function getStylesDeclarations( const cssProperty = key.startsWith( '--' ) ? key : kebabCase( key ); - declarations.push( - `${ cssProperty }: ${ compileStyleValue( - get( blockStyles, pathToValue ) - ) }` - ); + + //The duotone filter is not one of the presets so we need to build the svg and the filter ID + if ( Array.isArray( blockStyles.filter?.duotone ) ) { + const slug = duotoneSlug( blockStyles.filter.duotone ); + declarations.push( + `${ cssProperty }: url('#wp-duotone-${ slug }')` + ); + } else { + declarations.push( + `${ cssProperty }: ${ compileStyleValue( + get( blockStyles, pathToValue ) + ) }` + ); + } } return declarations; @@ -900,6 +910,32 @@ export const toStyles = ( return ruleset; }; +function duotoneSlug( colors ) { + return colors + .map( ( x ) => cleanForSlug( x ).replaceAll( '-', '' ) ) + .join( '-' ); +} + +export function customSvgFilters( tree, blockSelectors ) { + const nodesWithStyles = getNodesWithStyles( tree, blockSelectors ); + + return nodesWithStyles + .filter( + ( { styles, duotoneSelector } ) => + duotoneSelector && Array.isArray( styles.filter?.duotone ) + ) + .flatMap( ( node ) => { + const slug = duotoneSlug( node.styles.filter.duotone ); + return ( + + ); + } ); +} + export function toSvgFilters( tree, blockSelectors ) { const nodesWithSettings = getNodesWithSettings( tree, blockSelectors ); return nodesWithSettings.flatMap( ( { presets } ) => { @@ -1050,7 +1086,9 @@ export function useGlobalStylesOutput() { disableLayoutStyles ); - const filters = toSvgFilters( mergedConfig, blockSelectors ); + const presetSvgs = toSvgFilters( mergedConfig, blockSelectors ); + const customSvgs = customSvgFilters( mergedConfig, blockSelectors ); + const stylesheets = [ { css: customProperties, @@ -1083,7 +1121,11 @@ export function useGlobalStylesOutput() { } } ); - return [ stylesheets, mergedConfig.settings, filters ]; + return [ + stylesheets, + mergedConfig.settings, + [ ...presetSvgs, ...customSvgs ], + ]; }, [ hasBlockGapSupport, hasFallbackGapSupport, diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 2ff2e732298044..3f34e1783930bb 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -15,6 +15,7 @@ export const ROOT_BLOCK_SUPPORTS = [ 'background', 'backgroundColor', 'color', + 'filter', 'linkColor', 'captionColor', 'buttonColor', diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index a50c82241dd12d..590422ccff99cc 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -14,6 +14,7 @@ const ROOT_BLOCK_SUPPORTS = [ 'background', 'backgroundColor', 'color', + 'filter', 'linkColor', 'captionColor', 'buttonColor', diff --git a/packages/blocks/src/store/test/private-selectors.js b/packages/blocks/src/store/test/private-selectors.js index 8eca5c2e859ea1..7e31e7c3e87621 100644 --- a/packages/blocks/src/store/test/private-selectors.js +++ b/packages/blocks/src/store/test/private-selectors.js @@ -29,6 +29,7 @@ describe( 'private selectors', () => { 'background', 'backgroundColor', 'color', + 'filter', 'linkColor', 'captionColor', 'buttonColor', @@ -51,6 +52,7 @@ describe( 'private selectors', () => { 'background', 'backgroundColor', 'color', + 'filter', 'linkColor', 'captionColor', 'buttonColor', @@ -78,6 +80,7 @@ describe( 'private selectors', () => { 'background', 'backgroundColor', 'color', + 'filter', 'linkColor', 'captionColor', 'buttonColor', diff --git a/packages/edit-site/src/components/global-styles/duotone-panel.js b/packages/edit-site/src/components/global-styles/duotone-panel.js index c8cf095df4fe24..e1ce0c99fdfdcc 100644 --- a/packages/edit-site/src/components/global-styles/duotone-panel.js +++ b/packages/edit-site/src/components/global-styles/duotone-panel.js @@ -53,6 +53,11 @@ function DuotonePanel( { name } ) { defaultSetting: 'color.defaultPalette', } ); + const disableCustomColors = ! useSetting( 'color.custom' ); + const disableCustomDuotone = + ! useSetting( 'color.customDuotone' ) || + ( colorPalette?.length === 0 && disableCustomColors ); + if ( duotonePalette?.length === 0 ) { return null; } @@ -68,8 +73,8 @@ function DuotonePanel( { name } ) {