From a8c5605f5dd077a601aefce6f58409f54d7d4447 Mon Sep 17 00:00:00 2001
From: Ella <4710635+ellatrix@users.noreply.github.com>
Date: Thu, 14 Sep 2023 16:34:12 +0300
Subject: [PATCH] Block editor: remove `__unstableElementContext` and filter
`EditorStyles` instead (#52888)
---
.../src/components/duotone/components.js | 133 ------------------
.../src/components/duotone/index.js | 7 -
.../src/components/duotone/utils.js | 65 +++++++++
.../src/components/editor-styles/index.js | 42 ++++--
.../global-styles/use-global-styles-output.js | 12 +-
packages/block-editor/src/components/index.js | 1 -
packages/block-editor/src/hooks/duotone.js | 85 ++++++-----
.../block-editor/src/store/private-actions.js | 15 ++
.../src/store/private-selectors.js | 11 ++
packages/block-editor/src/store/reducer.js | 22 +++
10 files changed, 187 insertions(+), 206 deletions(-)
delete mode 100644 packages/block-editor/src/components/duotone/components.js
delete mode 100644 packages/block-editor/src/components/duotone/index.js
diff --git a/packages/block-editor/src/components/duotone/components.js b/packages/block-editor/src/components/duotone/components.js
deleted file mode 100644
index 471c03502c588c..00000000000000
--- a/packages/block-editor/src/components/duotone/components.js
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * 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
deleted file mode 100644
index 919d67780d7c7d..00000000000000
--- a/packages/block-editor/src/components/duotone/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-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
index d7cbd0ccba26e9..ac58eca18bb9f8 100644
--- a/packages/block-editor/src/components/duotone/utils.js
+++ b/packages/block-editor/src/components/duotone/utils.js
@@ -23,3 +23,68 @@ export function getValuesFromColors( colors = [] ) {
return values;
}
+
+/**
+ * Stylesheet for disabling a global styles duotone filter.
+ *
+ * @param {string} selector Selector to disable the filter for.
+ *
+ * @return {string} Filter none style.
+ */
+export function getDuotoneUnsetStylesheet( selector ) {
+ return `${ selector }{filter:none}`;
+}
+
+/**
+ * SVG and stylesheet needed for rendering the duotone filter.
+ *
+ * @param {string} selector Selector to apply the filter to.
+ * @param {string} id Unique id for this duotone filter.
+ *
+ * @return {string} Duotone filter style.
+ */
+export function getDuotoneStylesheet( selector, id ) {
+ return `${ selector }{filter:url(#${ id })}`;
+}
+
+/**
+ * The SVG part of the duotone filter.
+ *
+ * @param {string} id Unique id for this duotone filter.
+ * @param {string[]} colors Color strings from dark to light.
+ *
+ * @return {string} Duotone SVG.
+ */
+export function getDuotoneFilter( id, colors ) {
+ const values = getValuesFromColors( colors );
+ return `
+`;
+}
diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js
index 08005ae83a99b1..85c54109d0231b 100644
--- a/packages/block-editor/src/components/editor-styles/index.js
+++ b/packages/block-editor/src/components/editor-styles/index.js
@@ -10,11 +10,14 @@ import a11yPlugin from 'colord/plugins/a11y';
*/
import { SVG } from '@wordpress/components';
import { useCallback, useMemo } from '@wordpress/element';
+import { useSelect } from '@wordpress/data';
/**
* Internal dependencies
*/
import transformStyles from '../../utils/transform-styles';
+import { store as blockEditorStore } from '../../store';
+import { unlock } from '../../lock-unlock';
extend( [ namesPlugin, a11yPlugin ] );
@@ -65,33 +68,42 @@ function useDarkThemeBodyClassName( styles, scope ) {
}
export default function EditorStyles( { styles, scope } ) {
- const stylesArray = useMemo(
- () => Object.values( styles ?? [] ),
- [ styles ]
+ const overrides = useSelect(
+ ( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(),
+ []
);
- const transformedStyles = useMemo(
- () =>
+ const [ transformedStyles, transformedSvgs ] = useMemo( () => {
+ const _styles = Object.values( styles ?? [] );
+
+ for ( const [ id, override ] of overrides ) {
+ const index = _styles.findIndex( ( { id: _id } ) => id === _id );
+ const overrideWithId = { ...override, id };
+ if ( index === -1 ) {
+ _styles.push( overrideWithId );
+ } else {
+ _styles[ index ] = overrideWithId;
+ }
+ }
+
+ return [
transformStyles(
- stylesArray.filter( ( style ) => style?.css ),
+ _styles.filter( ( style ) => style?.css ),
scope
),
- [ stylesArray, scope ]
- );
-
- const transformedSvgs = useMemo(
- () =>
- stylesArray
+ _styles
.filter( ( style ) => style.__unstableType === 'svgs' )
.map( ( style ) => style.assets )
.join( '' ),
- [ stylesArray ]
- );
+ ];
+ }, [ styles, overrides, scope ] );
return (
<>
{ /* Use an empty style element to have a document reference,
but this could be any element. */ }
-
+
{ transformedStyles.map( ( css, index ) => (
) ) }
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 e8cdd332e9cce6..01c4f5b8781d75 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
@@ -9,7 +9,7 @@ import {
store as blocksStore,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
-import { renderToString, useContext, useMemo } from '@wordpress/element';
+import { useContext, useMemo } from '@wordpress/element';
import { getCSSRules } from '@wordpress/style-engine';
/**
@@ -23,7 +23,7 @@ import {
} from './typography-utils';
import { GlobalStylesContext } from './context';
import { useGlobalSetting } from './hooks';
-import { PresetDuotoneFilter } from '../duotone/components';
+import { getDuotoneFilter } from '../duotone/utils';
import { getGapCSSValue } from '../../hooks/gap';
import { store as blockEditorStore } from '../../store';
import { LAYOUT_DEFINITIONS } from '../../layouts/definitions';
@@ -164,11 +164,9 @@ function getPresetsSvgFilters( blockPresets = {} ) {
.filter( ( origin ) => presetByOrigin[ origin ] )
.flatMap( ( origin ) =>
presetByOrigin[ origin ].map( ( preset ) =>
- renderToString(
-
+ getDuotoneFilter(
+ `wp-duotone-${ preset.slug }`,
+ preset.colors
)
)
)
diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js
index 7be30aa5a858ba..6edcd460e31ac4 100644
--- a/packages/block-editor/src/components/index.js
+++ b/packages/block-editor/src/components/index.js
@@ -5,7 +5,6 @@
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 2ecd35c99ee8c4..2bbe18793fe558 100644
--- a/packages/block-editor/src/hooks/duotone.js
+++ b/packages/block-editor/src/hooks/duotone.js
@@ -15,7 +15,8 @@ import {
} from '@wordpress/blocks';
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
-import { useMemo, useContext, createPortal } from '@wordpress/element';
+import { useMemo, useEffect } from '@wordpress/element';
+import { useDispatch } from '@wordpress/data';
/**
* Internal dependencies
@@ -26,45 +27,23 @@ import {
__experimentalDuotoneControl as DuotoneControl,
useSetting,
} from '../components';
-import BlockList from '../components/block-list';
import {
- __unstableDuotoneFilter as DuotoneFilter,
- __unstableDuotoneStylesheet as DuotoneStylesheet,
- __unstableDuotoneUnsetStylesheet as DuotoneUnsetStylesheet,
-} from '../components/duotone';
+ getDuotoneFilter,
+ getDuotoneStylesheet,
+ getDuotoneUnsetStylesheet,
+} from '../components/duotone/utils';
import { getBlockCSSSelector } from '../components/global-styles/get-block-css-selector';
import { scopeSelector } from '../components/global-styles/utils';
import { useBlockSettings } from './utils';
import { default as StylesFiltersPanel } from '../components/global-styles/filters-panel';
import { useBlockEditingMode } from '../components/block-editing-mode';
+import { store as blockEditorStore } from '../store';
+import { unlock } from '../lock-unlock';
const EMPTY_ARRAY = [];
extend( [ namesPlugin ] );
-/**
- * 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.
- * @param {string[]|"unset"} props.colors Array of RGB color strings ordered from dark to light.
- *
- * @return {WPElement} Duotone element.
- */
-function InlineDuotone( { selector, id, colors } ) {
- if ( colors === 'unset' ) {
- return ;
- }
-
- return (
- <>
-
-
- >
- );
-}
-
function useMultiOriginPresets( { presetSetting, defaultSetting } ) {
const disableDefault = ! useSetting( defaultSetting );
const userPresets =
@@ -248,8 +227,6 @@ function DuotoneStyles( {
selector: duotoneSelector,
attribute: duotoneAttr,
} ) {
- const element = useContext( BlockList.__unstableElementContext );
-
const duotonePalette = useMultiOriginPresets( {
presetSetting: 'color.duotone',
defaultSetting: 'color.defaultDuotone',
@@ -290,25 +267,47 @@ function DuotoneStyles( {
// Assuming the selector part is a subclass selector (not a tag name)
// so we can prepend the filter id class. If we want to support elements
// such as `img` or namespaces, we'll need to add a case for that here.
- return `.editor-styles-wrapper .${ filterId }${ selectorPart.trim() }`;
+ return `.${ filterId }${ selectorPart.trim() }`;
} );
const selector = selectorsScoped.join( ', ' );
const isValidFilter = Array.isArray( colors ) || colors === 'unset';
- return (
- element &&
- isValidFilter &&
- createPortal(
- ,
- element
- )
+ const { setStyleOverride, deleteStyleOverride } = unlock(
+ useDispatch( blockEditorStore )
);
+
+ useEffect( () => {
+ if ( ! isValidFilter ) return;
+
+ setStyleOverride( filterId, {
+ css:
+ colors !== 'unset'
+ ? getDuotoneStylesheet( selector, filterId )
+ : getDuotoneUnsetStylesheet( selector ),
+ __unstableType: 'presets',
+ } );
+ setStyleOverride( `duotone-${ filterId }`, {
+ assets:
+ colors !== 'unset' ? getDuotoneFilter( filterId, colors ) : '',
+ __unstableType: 'svgs',
+ } );
+
+ return () => {
+ deleteStyleOverride( filterId );
+ deleteStyleOverride( `duotone-${ filterId }` );
+ };
+ }, [
+ isValidFilter,
+ colors,
+ selector,
+ filterId,
+ setStyleOverride,
+ deleteStyleOverride,
+ ] );
+
+ return null;
}
/**
diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js
index 0171b4f442d197..dc62614b576812 100644
--- a/packages/block-editor/src/store/private-actions.js
+++ b/packages/block-editor/src/store/private-actions.js
@@ -275,3 +275,18 @@ export function setOpenedBlockSettingsMenu( clientId ) {
clientId,
};
}
+
+export function setStyleOverride( id, style ) {
+ return {
+ type: 'SET_STYLE_OVERRIDE',
+ id,
+ style,
+ };
+}
+
+export function deleteStyleOverride( id ) {
+ return {
+ type: 'DELETE_STYLE_OVERRIDE',
+ id,
+ };
+}
diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js
index 2dc5ad8360fa33..e77e478ba60466 100644
--- a/packages/block-editor/src/store/private-selectors.js
+++ b/packages/block-editor/src/store/private-selectors.js
@@ -149,3 +149,14 @@ export function getBlockRemovalRules( state ) {
export function getOpenedBlockSettingsMenu( state ) {
return state.openedBlockSettingsMenu;
}
+
+/**
+ * Returns all style overrides, intended to be merged with global editor styles.
+ *
+ * @param {Object} state Global application state.
+ *
+ * @return {Map} A map of style IDs to style overrides.
+ */
+export function getStyleOverrides( state ) {
+ return state.styleOverrides;
+}
diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js
index 4d1713ebcd0e0f..18048ce138eb23 100644
--- a/packages/block-editor/src/store/reducer.js
+++ b/packages/block-editor/src/store/reducer.js
@@ -1928,6 +1928,27 @@ export function openedBlockSettingsMenu( state = null, action ) {
return state;
}
+/**
+ * Reducer returning a map of style IDs to style overrides.
+ *
+ * @param {Map} state Current state.
+ * @param {Object} action Dispatched action.
+ *
+ * @return {Map} Updated state.
+ */
+export function styleOverrides( state = new Map(), action ) {
+ switch ( action.type ) {
+ case 'SET_STYLE_OVERRIDE':
+ return new Map( state ).set( action.id, action.style );
+ case 'DELETE_STYLE_OVERRIDE': {
+ const newState = new Map( state );
+ newState.delete( action.id );
+ return newState;
+ }
+ }
+ return state;
+}
+
const combinedReducers = combineReducers( {
blocks,
isTyping,
@@ -1951,6 +1972,7 @@ const combinedReducers = combineReducers( {
temporarilyEditingAsBlocks,
blockVisibility,
blockEditingModes,
+ styleOverrides,
removalPromptData,
blockRemovalRules,
openedBlockSettingsMenu,