diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index 933758f7eb76f5..5a78e7abeb3b4c 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -12,6 +12,7 @@ import { useMemo } from '@wordpress/element'; import BlockList from '../block-list'; import Iframe from '../iframe'; import EditorStyles from '../editor-styles'; +import { __unstablePresetDuotoneFilter as PresetDuotoneFilter } from '../../components/duotone'; import { store } from '../../store'; // This is used to avoid rendering the block list if the sizes change. @@ -28,11 +29,12 @@ function AutoBlockPreview( { useResizeObserver(); const [ contentResizeListener, { height: contentHeight } ] = useResizeObserver(); - const { styles, assets } = useSelect( ( select ) => { + const { styles, assets, duotone } = useSelect( ( select ) => { const settings = select( store ).getSettings(); return { styles: settings.styles, assets: settings.__unstableResolvedAssets, + duotone: settings.__experimentalFeatures?.color?.duotone, }; }, [] ); @@ -51,11 +53,14 @@ function AutoBlockPreview( { return styles; }, [ styles ] ); + const svgFilters = useMemo( () => { + return [ ...( duotone?.default ?? [] ), ...( duotone?.theme ?? [] ) ]; + }, [ duotone ] ); + // Initialize on render instead of module top level, to avoid circular dependency issues. MemoizedBlockList = MemoizedBlockList || pure( BlockList ); const scale = containerWidth / viewportWidth; - return (
{ containerResizeListener } @@ -106,6 +111,15 @@ function AutoBlockPreview( { } } > { contentResizeListener } + { + /* Filters need to be rendered before children to avoid Safari rendering issues. */ + svgFilters.map( ( preset ) => ( + + ) ) + } diff --git a/packages/block-editor/src/components/duotone/components.js b/packages/block-editor/src/components/duotone/components.js new file mode 100644 index 00000000000000..2ec019849a02a3 --- /dev/null +++ b/packages/block-editor/src/components/duotone/components.js @@ -0,0 +1,133 @@ +/** + * WordPress dependencies + */ +import { SVG } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { __unstableGetValuesFromColors as getValuesFromColors } from './index'; + +/** + * SVG and stylesheet needed for rendering the duotone filter. + * + * @param {Object} props Duotone props. + * @param {string} props.selector Selector to apply the filter to. + * @param {string} props.id Unique id for this duotone filter. + * + * @return {WPElement} Duotone element. + */ +export function DuotoneStylesheet( { selector, id } ) { + const css = ` +${ selector } { + filter: url( #${ id } ); +} +`; + return ; +} + +/** + * Stylesheet for disabling a global styles duotone filter. + * + * @param {Object} props Duotone props. + * @param {string} props.selector Selector to disable the filter for. + * + * @return {WPElement} Filter none style element. + */ +export function DuotoneUnsetStylesheet( { selector } ) { + const css = ` +${ selector } { + filter: none; +} +`; + return ; +} + +/** + * The SVG part of the duotone filter. + * + * @param {Object} props Duotone props. + * @param {string} props.id Unique id for this duotone filter. + * @param {string[]} props.colors Color strings from dark to light. + * + * @return {WPElement} Duotone SVG. + */ +export function DuotoneFilter( { id, colors } ) { + const values = getValuesFromColors( colors ); + return ( + + + + + + + + + + + + + + + ); +} + +/** + * SVG from a duotone preset + * + * @param {Object} props Duotone props. + * @param {Object} props.preset Duotone preset settings. + * + * @return {WPElement} Duotone element. + */ +export function PresetDuotoneFilter( { preset } ) { + return ( + + ); +} diff --git a/packages/block-editor/src/components/duotone/index.js b/packages/block-editor/src/components/duotone/index.js new file mode 100644 index 00000000000000..919d67780d7c7d --- /dev/null +++ b/packages/block-editor/src/components/duotone/index.js @@ -0,0 +1,7 @@ +export { getValuesFromColors as __unstableGetValuesFromColors } from './utils'; +export { + DuotoneFilter as __unstableDuotoneFilter, + PresetDuotoneFilter as __unstablePresetDuotoneFilter, + DuotoneStylesheet as __unstableDuotoneStylesheet, + DuotoneUnsetStylesheet as __unstableDuotoneUnsetStylesheet, +} from './components'; diff --git a/packages/block-editor/src/components/duotone/utils.js b/packages/block-editor/src/components/duotone/utils.js new file mode 100644 index 00000000000000..d7cbd0ccba26e9 --- /dev/null +++ b/packages/block-editor/src/components/duotone/utils.js @@ -0,0 +1,25 @@ +/** + * External dependencies + */ +import { colord } from 'colord'; + +/** + * Convert a list of colors to an object of R, G, and B values. + * + * @param {string[]} colors Array of RBG color strings. + * + * @return {Object} R, G, and B values. + */ +export function getValuesFromColors( colors = [] ) { + const values = { r: [], g: [], b: [], a: [] }; + + colors.forEach( ( color ) => { + const rgbColor = colord( color ).toRgb(); + values.r.push( rgbColor.r / 255 ); + values.g.push( rgbColor.g / 255 ); + values.b.push( rgbColor.b / 255 ); + values.a.push( rgbColor.a ); + } ); + + return values; +} diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 0dec53f9579528..cf1967e429cbf5 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -5,6 +5,7 @@ export * from './colors'; export * from './gradients'; export * from './font-sizes'; +export * from './duotone'; export { AlignmentControl, AlignmentToolbar } from './alignment-control'; export { default as Autocomplete } from './autocomplete'; export { diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index afcf3b4d27f914..5cc610ae1047b3 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -2,14 +2,13 @@ * External dependencies */ import classnames from 'classnames'; -import { colord, extend } from 'colord'; +import { extend } from 'colord'; import namesPlugin from 'colord/plugins/names'; /** * WordPress dependencies */ import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; -import { SVG } from '@wordpress/components'; import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose'; import { addFilter } from '@wordpress/hooks'; import { useMemo, useContext, createPortal } from '@wordpress/element'; @@ -23,139 +22,16 @@ import { useSetting, } from '../components'; import BlockList from '../components/block-list'; +import { + __unstableDuotoneFilter as DuotoneFilter, + __unstableDuotoneStylesheet as DuotoneStylesheet, + __unstableDuotoneUnsetStylesheet as DuotoneUnsetStylesheet, +} from '../components/duotone'; const EMPTY_ARRAY = []; extend( [ namesPlugin ] ); -/** - * Convert a list of colors to an object of R, G, and B values. - * - * @param {string[]} colors Array of RBG color strings. - * - * @return {Object} R, G, and B values. - */ -export function getValuesFromColors( colors = [] ) { - const values = { r: [], g: [], b: [], a: [] }; - - colors.forEach( ( color ) => { - const rgbColor = colord( color ).toRgb(); - values.r.push( rgbColor.r / 255 ); - values.g.push( rgbColor.g / 255 ); - values.b.push( rgbColor.b / 255 ); - values.a.push( rgbColor.a ); - } ); - - return values; -} - -/** - * SVG and stylesheet needed for rendering the duotone filter. - * - * @param {Object} props Duotone props. - * @param {string} props.selector Selector to apply the filter to. - * @param {string} props.id Unique id for this duotone filter. - * - * @return {WPElement} Duotone element. - */ -function DuotoneStylesheet( { selector, id } ) { - const css = ` -${ selector } { - filter: url( #${ id } ); -} -`; - return ; -} - -/** - * Stylesheet for disabling a global styles duotone filter. - * - * @param {Object} props Duotone props. - * @param {string} props.selector Selector to disable the filter for. - * - * @return {WPElement} Filter none style element. - */ -function DuotoneUnsetStylesheet( { selector } ) { - const css = ` -${ selector } { - filter: none; -} -`; - return ; -} - -/** - * The SVG part of the duotone filter. - * - * @param {Object} props Duotone props. - * @param {string} props.id Unique id for this duotone filter. - * @param {string[]} props.colors Color strings from dark to light. - * - * @return {WPElement} Duotone SVG. - */ -function DuotoneFilter( { id, colors } ) { - const values = getValuesFromColors( colors ); - return ( - - - - - - - - - - - - - - - ); -} - /** * SVG and stylesheet needed for rendering the duotone filter. * @@ -374,15 +250,6 @@ const withDuotoneStyles = createHigherOrderComponent( 'withDuotoneStyles' ); -export function PresetDuotoneFilter( { preset } ) { - return ( - - ); -} - addFilter( 'blocks.registerBlockType', 'core/editor/duotone/add-attributes', diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 36c3181092a17a..f95d4771a1c3b9 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -20,4 +20,3 @@ export { getBorderClassesAndStyles, useBorderProps } from './use-border-props'; export { getColorClassesAndStyles, useColorProps } from './use-color-props'; export { getSpacingClassesAndStyles } from './use-spacing-props'; export { useCachedTruthy } from './use-cached-truthy'; -export { PresetDuotoneFilter } from './duotone'; diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index 594c78859b25c8..b2fe8aec5e1ff0 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -3,7 +3,6 @@ */ import './hooks'; export { - PresetDuotoneFilter as __unstablePresetDuotoneFilter, getBorderClassesAndStyles as __experimentalGetBorderClassesAndStyles, useBorderProps as __experimentalUseBorderProps, getColorClassesAndStyles as __experimentalGetColorClassesAndStyles,