From aa1e759d21c67823c0be5008a80dd0c50163cf1a Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 13:44:35 +0000 Subject: [PATCH 01/17] Naive implementation --- packages/block-editor/src/hooks/duotone.js | 40 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index a33ad059cb6653..fcf7cd91d40816 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -77,7 +77,7 @@ function useMultiOriginPresets( { presetSetting, defaultSetting } ) { function DuotonePanel( { attributes, setAttributes } ) { const style = attributes?.style; - const duotone = style?.color?.duotone; + let duotone = style?.color?.duotone; const duotonePalette = useMultiOriginPresets( { presetSetting: 'color.duotone', @@ -96,6 +96,17 @@ function DuotonePanel( { attributes, setAttributes } ) { return null; } + if ( ! Array.isArray( duotone ) ) { + // find the duotone preset with the slug duotone + // if found, return duotone.colors + // if not found, return false + const preset = duotonePalette.find( ( duotonePreset ) => { + return duotonePreset.slug === duotone; + } ); + + duotone = preset?.colors; + } + return ( { + // See if there is a duotone preset with the same colors + // as the new duotone colors. + const preset = duotonePalette.find( ( duotonePreset ) => { + return duotonePreset?.colors?.every( + ( val, index ) => val === newDuotone[ index ] + ); + } ); + const newStyle = { ...style, color: { ...style?.color, - duotone: newDuotone, + // If there is a preset, store the preset slug, + // otherwise store the colors array. + duotone: preset ? preset.slug : newDuotone, }, }; setAttributes( { style: newStyle } ); @@ -224,7 +245,20 @@ const withDuotoneStyles = createHigherOrderComponent( props.name, 'color.__experimentalDuotone' ); - const colors = props?.attributes?.style?.color?.duotone; + const duotonePalette = useMultiOriginPresets( { + presetSetting: 'color.duotone', + defaultSetting: 'color.defaultDuotone', + } ); + + let colors = props?.attributes?.style?.color?.duotone; + + if ( ! Array.isArray( colors ) ) { + const duotone = duotonePalette.find( ( dt ) => dt.slug === colors ); + + if ( duotone ) { + colors = duotone.colors; + } + } if ( ! duotoneSupport || ! colors ) { return ; From 13f8b756b700b2c74a1dc89561796cf6beb343ab Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 14:01:15 +0000 Subject: [PATCH 02/17] Refactor to named functions --- packages/block-editor/src/hooks/duotone.js | 51 ++++++++++++---------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index fcf7cd91d40816..e57ffbbded465d 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -75,9 +75,29 @@ function useMultiOriginPresets( { presetSetting, defaultSetting } ) { ); } +function getColorsFromDuotonePreset( duotone, duotonePalette ) { + if ( ! duotone ) { + return; + } + const preset = duotonePalette.find( ( { slug } ) => { + return slug === duotone; + } ); + + return preset ? preset.colors : duotone; +} + +function getDuotonePresetFromColors( colors, duotonePalette ) { + const preset = duotonePalette.find( ( duotonePreset ) => { + return duotonePreset?.colors?.every( + ( val, index ) => val === colors[ index ] + ); + } ); + + return preset ? preset.slug : colors; +} + function DuotonePanel( { attributes, setAttributes } ) { const style = attributes?.style; - let duotone = style?.color?.duotone; const duotonePalette = useMultiOriginPresets( { presetSetting: 'color.duotone', @@ -96,16 +116,10 @@ function DuotonePanel( { attributes, setAttributes } ) { return null; } - if ( ! Array.isArray( duotone ) ) { - // find the duotone preset with the slug duotone - // if found, return duotone.colors - // if not found, return false - const preset = duotonePalette.find( ( duotonePreset ) => { - return duotonePreset.slug === duotone; - } ); - - duotone = preset?.colors; - } + const duotone = getColorsFromDuotonePreset( + style?.color?.duotone, + duotonePalette + ); return ( @@ -116,21 +130,14 @@ function DuotonePanel( { attributes, setAttributes } ) { disableCustomColors={ disableCustomColors } value={ duotone } onChange={ ( newDuotone ) => { - // See if there is a duotone preset with the same colors - // as the new duotone colors. - const preset = duotonePalette.find( ( duotonePreset ) => { - return duotonePreset?.colors?.every( - ( val, index ) => val === newDuotone[ index ] - ); - } ); - const newStyle = { ...style, color: { ...style?.color, - // If there is a preset, store the preset slug, - // otherwise store the colors array. - duotone: preset ? preset.slug : newDuotone, + duotone: getDuotonePresetFromColors( + newDuotone, + duotonePalette + ), }, }; setAttributes( { style: newStyle } ); From ef853d6b2cdd35f152332600c122737a1168ad70 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 16:53:12 +0000 Subject: [PATCH 03/17] Fix order of hooks --- packages/block-editor/src/hooks/duotone.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index e57ffbbded465d..a0653917c9b0aa 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -257,6 +257,8 @@ const withDuotoneStyles = createHigherOrderComponent( defaultSetting: 'color.defaultDuotone', } ); + const id = `wp-duotone-${ useInstanceId( BlockListBlock ) }`; + let colors = props?.attributes?.style?.color?.duotone; if ( ! Array.isArray( colors ) ) { @@ -271,8 +273,6 @@ const withDuotoneStyles = createHigherOrderComponent( return ; } - const id = `wp-duotone-${ useInstanceId( BlockListBlock ) }`; - // Extra .editor-styles-wrapper specificity is needed in the editor // since we're not using inline styles to apply the filter. We need to // override duotone applied by global styles and theme.json. From 53a4173efb8c838713f7699ac4344946802c4898 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 16:53:41 +0000 Subject: [PATCH 04/17] Utilise existing duotone presets on front of site --- lib/block-supports/duotone.php | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index ca9f614a263491..da19d5669ce8c3 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -445,14 +445,29 @@ function gutenberg_render_duotone_support( $block_content, $block ) { return $block_content; } - $colors = $block['attrs']['style']['color']['duotone']; - $filter_key = is_array( $colors ) ? implode( '-', $colors ) : $colors; - $filter_preset = array( - 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), - 'colors' => $colors, - ); - $filter_property = gutenberg_get_duotone_filter_property( $filter_preset ); - $filter_id = gutenberg_get_duotone_filter_id( $filter_preset ); + // Possible values for duotone attribute: + // 1. array('#000000', '#ffffff') + // 2. 'preset-slug' + // 3. 'unset' (remove filter) + $duotone_attr = $block['attrs']['style']['color']['duotone']; + + if ( ! is_array( $duotone_attr ) && $duotone_attr !== 'unset' ) { + // If we have a preset slug we need to fetch the details for that preset. + $filter_preset = array( + 'slug' => $duotone_attr, + ); + $filter_property = "var(--wp--preset--duotone--$duotone_attr)"; + } else { + // If we have an array of colors not a preset slug. + $filter_key = is_array( $duotone_attr ) ? implode( '-', $duotone_attr ) : $duotone_attr; + $filter_preset = array( + 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), + 'colors' => $duotone_attr, + ); + $filter_property = gutenberg_get_duotone_filter_property( $filter_preset ); + } + + $filter_id = gutenberg_get_duotone_filter_id( $filter_preset ); $scope = '.' . $filter_id; $selectors = explode( ',', $duotone_support ); @@ -483,7 +498,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { ) ); - if ( 'unset' !== $colors ) { + if ( is_array( $duotone_attr ) ) { $filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset ); add_action( 'wp_footer', From 89f163480cccf370da1b989e6bcef9d2a84c23f3 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 16:58:18 +0000 Subject: [PATCH 05/17] Improve self documenting code --- lib/block-supports/duotone.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index da19d5669ce8c3..7e6c5ae517cb83 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -451,7 +451,10 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // 3. 'unset' (remove filter) $duotone_attr = $block['attrs']['style']['color']['duotone']; - if ( ! is_array( $duotone_attr ) && $duotone_attr !== 'unset' ) { + $is_duotone_colors_array = is_array( $duotone_attr ) && count( $duotone_attr ) === 2; + $is_duotone_unset = $duotone_attr === 'unset'; + + if ( ! $is_duotone_colors_array && ! $is_duotone_unset ) { // If we have a preset slug we need to fetch the details for that preset. $filter_preset = array( 'slug' => $duotone_attr, @@ -498,7 +501,9 @@ function gutenberg_render_duotone_support( $block_content, $block ) { ) ); - if ( is_array( $duotone_attr ) ) { + // For *non*-presets then generate an SVG for the filter. + // Note: duotone presets are already pre-generated so no need to do this again. + if ( $is_duotone_colors_array ) { $filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset ); add_action( 'wp_footer', From b3831a176679337a158b9861c689531605b3fa98 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 17:06:39 +0000 Subject: [PATCH 06/17] Refactor away redundant color prop of filter_preset --- lib/block-supports/duotone.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 7e6c5ae517cb83..76a7a60850ff0b 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -311,9 +311,6 @@ function gutenberg_get_duotone_filter_id( $preset ) { * @return string Duotone CSS filter property url value. */ function gutenberg_get_duotone_filter_property( $preset ) { - if ( isset( $preset['colors'] ) && 'unset' === $preset['colors'] ) { - return 'none'; - } $filter_id = gutenberg_get_duotone_filter_id( $preset ); return "url('#" . $filter_id . "')"; } @@ -446,15 +443,16 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } // Possible values for duotone attribute: - // 1. array('#000000', '#ffffff') - // 2. 'preset-slug' - // 3. 'unset' (remove filter) + // 1. array('#000000', '#ffffff'). + // 2. 'preset-slug'. + // 3. 'unset' (remove filter). $duotone_attr = $block['attrs']['style']['color']['duotone']; $is_duotone_colors_array = is_array( $duotone_attr ) && count( $duotone_attr ) === 2; $is_duotone_unset = $duotone_attr === 'unset'; + $is_duotone_preset = ! $is_duotone_colors_array && ! $is_duotone_unset; - if ( ! $is_duotone_colors_array && ! $is_duotone_unset ) { + if ( $is_duotone_preset ) { // If we have a preset slug we need to fetch the details for that preset. $filter_preset = array( 'slug' => $duotone_attr, @@ -464,10 +462,9 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // If we have an array of colors not a preset slug. $filter_key = is_array( $duotone_attr ) ? implode( '-', $duotone_attr ) : $duotone_attr; $filter_preset = array( - 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), - 'colors' => $duotone_attr, + 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), ); - $filter_property = gutenberg_get_duotone_filter_property( $filter_preset ); + $filter_property = $is_duotone_unset ? 'none' : gutenberg_get_duotone_filter_property( $filter_preset ); } $filter_id = gutenberg_get_duotone_filter_id( $filter_preset ); From 3db9ff8ac9d5b3b328a6c1ce95dcab0b7e8e986d Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 17:07:28 +0000 Subject: [PATCH 07/17] =?UTF-8?q?Satisfy=20master=20yoda=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/block-supports/duotone.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 76a7a60850ff0b..72eac60bd47fd9 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -449,7 +449,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $duotone_attr = $block['attrs']['style']['color']['duotone']; $is_duotone_colors_array = is_array( $duotone_attr ) && count( $duotone_attr ) === 2; - $is_duotone_unset = $duotone_attr === 'unset'; + $is_duotone_unset = 'unset' === $duotone_attr; $is_duotone_preset = ! $is_duotone_colors_array && ! $is_duotone_unset; if ( $is_duotone_preset ) { From 07d9df5e4e3179a76a9e9eccb521fd1f48b460b3 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 22 Feb 2023 17:19:38 +0000 Subject: [PATCH 08/17] More commenting --- lib/block-supports/duotone.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 72eac60bd47fd9..93053f8f42010b 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -453,22 +453,33 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $is_duotone_preset = ! $is_duotone_colors_array && ! $is_duotone_unset; if ( $is_duotone_preset ) { - // If we have a preset slug we need to fetch the details for that preset. $filter_preset = array( 'slug' => $duotone_attr, ); + + // Utilise existing CSS custom property. $filter_property = "var(--wp--preset--duotone--$duotone_attr)"; } else { - // If we have an array of colors not a preset slug. + // Handle when Duotone is either: + // - "unset" + // - an array of colors. + + // Build a unique slug for the filter based on the array of colors. $filter_key = is_array( $duotone_attr ) ? implode( '-', $duotone_attr ) : $duotone_attr; $filter_preset = array( 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), ); + + // Build a customised CSS filter property for unique slug. $filter_property = $is_duotone_unset ? 'none' : gutenberg_get_duotone_filter_property( $filter_preset ); } + // - Applied as a class attribute to the block wrapper. + // - Used as a selector to apply the filter to the block. $filter_id = gutenberg_get_duotone_filter_id( $filter_preset ); + // Build the CSS selectors to which the filter will be applied. + // Todo - encapsulate this in a function. $scope = '.' . $filter_id; $selectors = explode( ',', $duotone_support ); $scoped = array(); From a457af9e8781a6792786034cdc51f2cc53ae59c0 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 22 Feb 2023 15:24:22 -0600 Subject: [PATCH 09/17] Remove count() check for duotone color array Duotone color arrays can be more than 2 colors, and the code doesn't seem to handle 2 colors differently than 3 or more, so the count() === 2 was unnecessary. Since we've already defined the $is_duotone_colors_array, we can use it later instead of redoing another is_array() check. --- lib/block-supports/duotone.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 93053f8f42010b..124870a973d624 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -448,7 +448,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // 3. 'unset' (remove filter). $duotone_attr = $block['attrs']['style']['color']['duotone']; - $is_duotone_colors_array = is_array( $duotone_attr ) && count( $duotone_attr ) === 2; + $is_duotone_colors_array = is_array( $duotone_attr ); $is_duotone_unset = 'unset' === $duotone_attr; $is_duotone_preset = ! $is_duotone_colors_array && ! $is_duotone_unset; @@ -465,7 +465,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // - an array of colors. // Build a unique slug for the filter based on the array of colors. - $filter_key = is_array( $duotone_attr ) ? implode( '-', $duotone_attr ) : $duotone_attr; + $filter_key = $is_duotone_colors_array ? implode( '-', $duotone_attr ) : $duotone_attr; $filter_preset = array( 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), ); From 8e9c0ee287fca1a5350e45199d567b89f58ce2fc Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 05:54:25 +0000 Subject: [PATCH 10/17] Improve comments and linting --- lib/block-supports/duotone.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 124870a973d624..e1d739b8f306b6 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -443,9 +443,9 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } // Possible values for duotone attribute: - // 1. array('#000000', '#ffffff'). - // 2. 'preset-slug'. - // 3. 'unset' (remove filter). + // 1. Array of colors - e.g. array('#000000', '#ffffff'). + // 2. Slug of an existing Duotone preset - e.g. 'green-blue'. + // 3. The string 'unset' - indicates explicitly "no Duotone".. $duotone_attr = $block['attrs']['style']['color']['duotone']; $is_duotone_colors_array = is_array( $duotone_attr ); @@ -453,7 +453,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $is_duotone_preset = ! $is_duotone_colors_array && ! $is_duotone_unset; if ( $is_duotone_preset ) { - $filter_preset = array( + $filter_preset = array( 'slug' => $duotone_attr, ); @@ -465,8 +465,8 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // - an array of colors. // Build a unique slug for the filter based on the array of colors. - $filter_key = $is_duotone_colors_array ? implode( '-', $duotone_attr ) : $duotone_attr; - $filter_preset = array( + $filter_key = $is_duotone_colors_array ? implode( '-', $duotone_attr ) : $duotone_attr; + $filter_preset = array( 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), ); From d7ef38c2042e3b16f434a0ac9292ddb280f08207 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 06:02:32 +0000 Subject: [PATCH 11/17] Allow Duotone to be cleared using UI --- packages/block-editor/src/hooks/duotone.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index a0653917c9b0aa..ef60435d2ce5d4 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -87,6 +87,10 @@ function getColorsFromDuotonePreset( duotone, duotonePalette ) { } function getDuotonePresetFromColors( colors, duotonePalette ) { + if ( ! colors ) { + return; + } + const preset = duotonePalette.find( ( duotonePreset ) => { return duotonePreset?.colors?.every( ( val, index ) => val === colors[ index ] From 55f7dfef4c301ab906c42f24cd606568c3be4c3c Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 09:47:12 +0000 Subject: [PATCH 12/17] Add initial tests for getColorsFromDuotonePreset --- .../block-editor/src/hooks/test/duotone.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 packages/block-editor/src/hooks/test/duotone.js diff --git a/packages/block-editor/src/hooks/test/duotone.js b/packages/block-editor/src/hooks/test/duotone.js new file mode 100644 index 00000000000000..33269973902fdf --- /dev/null +++ b/packages/block-editor/src/hooks/test/duotone.js @@ -0,0 +1,39 @@ +/** + * Internal dependencies + */ +import { getColorsFromDuotonePreset } from '../duotone'; + +describe( 'getColorsFromDuotonePreset', () => { + const duotonePalette = [ + { + name: 'Dark grayscale', + colors: [ '#000000', '#7f7f7f' ], + slug: 'dark-grayscale', + }, + { + name: 'Grayscale', + colors: [ '#000000', '#ffffff' ], + slug: 'grayscale', + }, + { + name: 'Purple and yellow', + colors: [ '#8c00b7', '#fcff41' ], + slug: 'purple-yellow', + }, + ]; + it( 'should return undefined if no arguments are provided', () => { + expect( getColorsFromDuotonePreset() ).toBeUndefined(); + } ); + + it( 'should return undefined if no duotone preset is provided', () => { + expect( + getColorsFromDuotonePreset( undefined, duotonePalette ) + ).toBeUndefined(); + } ); + + it( 'should return undefined if a non-existent preset is provided', () => { + expect( + getColorsFromDuotonePreset( 'does-not-exist', duotonePalette ) + ).toBeUndefined(); + } ); +} ); From 5915bbd3fb868aae01ad194574bc434e8ef5dc7d Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 09:47:57 +0000 Subject: [PATCH 13/17] Be explicit about handling presets vs colors Previously the decision about how to handle values were deferred to the utility. Instead the consuming code should decide whether to look for a preset. --- packages/block-editor/src/hooks/duotone.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index ef60435d2ce5d4..7c7508cb574013 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -75,18 +75,18 @@ function useMultiOriginPresets( { presetSetting, defaultSetting } ) { ); } -function getColorsFromDuotonePreset( duotone, duotonePalette ) { +export function getColorsFromDuotonePreset( duotone, duotonePalette ) { if ( ! duotone ) { return; } - const preset = duotonePalette.find( ( { slug } ) => { + const preset = duotonePalette?.find( ( { slug } ) => { return slug === duotone; } ); - return preset ? preset.colors : duotone; + return preset ? preset.colors : undefined; } -function getDuotonePresetFromColors( colors, duotonePalette ) { +export function getDuotonePresetFromColors( colors, duotonePalette ) { if ( ! colors ) { return; } @@ -102,6 +102,7 @@ function getDuotonePresetFromColors( colors, duotonePalette ) { function DuotonePanel( { attributes, setAttributes } ) { const style = attributes?.style; + const duotoneStyle = style?.color?.duotone; const duotonePalette = useMultiOriginPresets( { presetSetting: 'color.duotone', @@ -120,10 +121,9 @@ function DuotonePanel( { attributes, setAttributes } ) { return null; } - const duotone = getColorsFromDuotonePreset( - style?.color?.duotone, - duotonePalette - ); + const duotonePresetOrColors = ! Array.isArray( duotoneStyle ) + ? getColorsFromDuotonePreset( duotoneStyle, duotonePalette ) + : duotoneStyle; return ( @@ -132,7 +132,7 @@ function DuotonePanel( { attributes, setAttributes } ) { colorPalette={ colorPalette } disableCustomDuotone={ disableCustomDuotone } disableCustomColors={ disableCustomColors } - value={ duotone } + value={ duotonePresetOrColors } onChange={ ( newDuotone ) => { const newStyle = { ...style, From 73bf14980ca90a5b54856805ce2d994a5a416947 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 09:49:26 +0000 Subject: [PATCH 14/17] Complete tests for getColorsFromDuotonePreset --- packages/block-editor/src/hooks/test/duotone.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-editor/src/hooks/test/duotone.js b/packages/block-editor/src/hooks/test/duotone.js index 33269973902fdf..43169c0ee98229 100644 --- a/packages/block-editor/src/hooks/test/duotone.js +++ b/packages/block-editor/src/hooks/test/duotone.js @@ -36,4 +36,10 @@ describe( 'getColorsFromDuotonePreset', () => { getColorsFromDuotonePreset( 'does-not-exist', duotonePalette ) ).toBeUndefined(); } ); + + it( 'should return the colors from the preset if found', () => { + expect( + getColorsFromDuotonePreset( 'purple-yellow', duotonePalette ) + ).toEqual( [ '#8c00b7', '#fcff41' ] ); + } ); } ); From 1ad076122323d188063fc3f1912ae5729543d3ea Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 09:57:06 +0000 Subject: [PATCH 15/17] Add tests and fix implementation of getDuotonePresetFromColors --- packages/block-editor/src/hooks/duotone.js | 6 +- .../block-editor/src/hooks/test/duotone.js | 90 +++++++++++++++---- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 7c7508cb574013..eb0046dcf3455b 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -87,17 +87,17 @@ export function getColorsFromDuotonePreset( duotone, duotonePalette ) { } export function getDuotonePresetFromColors( colors, duotonePalette ) { - if ( ! colors ) { + if ( ! colors || ! Array.isArray( colors ) ) { return; } - const preset = duotonePalette.find( ( duotonePreset ) => { + const preset = duotonePalette?.find( ( duotonePreset ) => { return duotonePreset?.colors?.every( ( val, index ) => val === colors[ index ] ); } ); - return preset ? preset.slug : colors; + return preset ? preset.slug : undefined; } function DuotonePanel( { attributes, setAttributes } ) { diff --git a/packages/block-editor/src/hooks/test/duotone.js b/packages/block-editor/src/hooks/test/duotone.js index 43169c0ee98229..b97c967d212f07 100644 --- a/packages/block-editor/src/hooks/test/duotone.js +++ b/packages/block-editor/src/hooks/test/duotone.js @@ -1,9 +1,12 @@ /** * Internal dependencies */ -import { getColorsFromDuotonePreset } from '../duotone'; +import { + getColorsFromDuotonePreset, + getDuotonePresetFromColors, +} from '../duotone'; -describe( 'getColorsFromDuotonePreset', () => { +describe( 'Duotone utilities', () => { const duotonePalette = [ { name: 'Dark grayscale', @@ -21,25 +24,76 @@ describe( 'getColorsFromDuotonePreset', () => { slug: 'purple-yellow', }, ]; - it( 'should return undefined if no arguments are provided', () => { - expect( getColorsFromDuotonePreset() ).toBeUndefined(); - } ); + describe( 'getColorsFromDuotonePreset', () => { + it( 'should return undefined if no arguments are provided', () => { + expect( getColorsFromDuotonePreset() ).toBeUndefined(); + } ); - it( 'should return undefined if no duotone preset is provided', () => { - expect( - getColorsFromDuotonePreset( undefined, duotonePalette ) - ).toBeUndefined(); - } ); + it( 'should return undefined if no duotone preset is provided', () => { + expect( + getColorsFromDuotonePreset( undefined, duotonePalette ) + ).toBeUndefined(); + } ); - it( 'should return undefined if a non-existent preset is provided', () => { - expect( - getColorsFromDuotonePreset( 'does-not-exist', duotonePalette ) - ).toBeUndefined(); + it( 'should return undefined if a non-existent preset is provided', () => { + expect( + getColorsFromDuotonePreset( 'does-not-exist', duotonePalette ) + ).toBeUndefined(); + } ); + + it( 'should return the colors from the preset if found', () => { + expect( + getColorsFromDuotonePreset( + duotonePalette[ 2 ].slug, + duotonePalette + ) + ).toEqual( duotonePalette[ 2 ].colors ); + } ); } ); - it( 'should return the colors from the preset if found', () => { - expect( - getColorsFromDuotonePreset( 'purple-yellow', duotonePalette ) - ).toEqual( [ '#8c00b7', '#fcff41' ] ); + describe( 'getDuotonePresetFromColors', () => { + it( 'should return undefined if no arguments are provided', () => { + expect( getDuotonePresetFromColors() ).toBeUndefined(); + } ); + + it( 'should return undefined if no colors are provided', () => { + expect( + getDuotonePresetFromColors( undefined, duotonePalette ) + ).toBeUndefined(); + } ); + + it( 'should return undefined if provided colors is not of valid type', () => { + const notAnArrayOfColorStrings = 'purple-yellow'; + expect( + getDuotonePresetFromColors( + notAnArrayOfColorStrings, + duotonePalette + ) + ).toBeUndefined(); + } ); + + it( 'should return undefined if no duotone palette is provided', () => { + expect( + getDuotonePresetFromColors( [ '#8c00b7', '#fcff41' ] ) + ).toBeUndefined(); + } ); + + it( 'should return undefined if the provided colors do not match any preset', () => { + expect( + getDuotonePresetFromColors( + [ '#000000', '#000000' ], + duotonePalette + ) + ).toBeUndefined(); + } ); + + it( 'should return the slug of the preset if found', () => { + expect( + getDuotonePresetFromColors( + duotonePalette[ 2 ].colors, + duotonePalette + ) + ).toEqual( duotonePalette[ 2 ].slug ); + } ); } ); } ); From a7f89db77bc57624152e063891be83995f0b33ae Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 10:01:44 +0000 Subject: [PATCH 16/17] Fix bug with selecting custom colors introduced during test refactor --- packages/block-editor/src/hooks/duotone.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index eb0046dcf3455b..fef0f8de32cddc 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -134,14 +134,16 @@ function DuotonePanel( { attributes, setAttributes } ) { disableCustomColors={ disableCustomColors } value={ duotonePresetOrColors } onChange={ ( newDuotone ) => { + const maybePreset = getDuotonePresetFromColors( + newDuotone, + duotonePalette + ); + const newStyle = { ...style, color: { ...style?.color, - duotone: getDuotonePresetFromColors( - newDuotone, - duotonePalette - ), + duotone: maybePreset ?? newDuotone, // use preset or fallback to custom colors. }, }; setAttributes( { style: newStyle } ); From a5c64eba7fe0f8c1506546e683b192f3f216aa60 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 23 Feb 2023 10:06:16 +0000 Subject: [PATCH 17/17] Fix custom colors Duotone on front end rendering --- lib/block-supports/duotone.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index e1d739b8f306b6..e0dea9e97cc2bb 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -467,7 +467,8 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build a unique slug for the filter based on the array of colors. $filter_key = $is_duotone_colors_array ? implode( '-', $duotone_attr ) : $duotone_attr; $filter_preset = array( - 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), + 'slug' => wp_unique_id( sanitize_key( $filter_key . '-' ) ), + 'colors' => $duotone_attr, // required for building the SVG with gutenberg_get_duotone_filter_svg. ); // Build a customised CSS filter property for unique slug. @@ -513,6 +514,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Note: duotone presets are already pre-generated so no need to do this again. if ( $is_duotone_colors_array ) { $filter_svg = gutenberg_get_duotone_filter_svg( $filter_preset ); + add_action( 'wp_footer', static function () use ( $filter_svg, $selector ) {