From 1e744fb2c44ec668fe560c8e26dd6a85fbd1ac8d Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:22:47 +1100 Subject: [PATCH 1/4] useBlockPreview: Try alternative fix for displaying local style overrides --- .../src/components/block-preview/index.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index cf0937507be095..64ad0a65feb89d 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -16,6 +16,7 @@ import deprecated from '@wordpress/deprecated'; */ import { ExperimentalBlockEditorProvider } from '../provider'; import AutoHeightBlockPreview from './auto'; +import EditorStyles from '../editor-styles'; import { store as blockEditorStore } from '../../store'; import { BlockListItems } from '../block-list'; @@ -92,6 +93,17 @@ export function BlockPreview( { */ export default memo( BlockPreview ); +function InnerStyles() { + const { styles } = useSelect( ( select ) => { + const settings = select( blockEditorStore ).getSettings(); + return { + styles: settings.styles, + }; + }, [] ); + + return ; +} + /** * This hook is used to lightly mark an element as a block preview wrapper * element. Call this hook and pass the returned props to the element to mark as @@ -128,6 +140,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { value={ renderedBlocks } settings={ settings } > + ); From 1d036833fd6b1d9761bcfcdce1e9985cb0e4ef0f Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:26:56 +1100 Subject: [PATCH 2/4] Avoid duplicate styles, fix rendering issues in Safari --- .../src/components/block-preview/index.js | 6 +++- packages/block-editor/src/hooks/duotone.js | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 64ad0a65feb89d..1cbb3513dbd8ba 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -125,7 +125,11 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + styles: undefined, + __unstableIsPreviewMode: true, + } ), [ originalSettings ] ); const disabledRef = useDisabled(); diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 2bbe18793fe558..39a8979782a0c6 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -37,11 +37,22 @@ 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 { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; const EMPTY_ARRAY = []; +// Safari does not always update the duotone filter when the duotone colors +// are changed. This browser check is later used to force a re-render of the block +// element to ensure the duotone filter is updated. The check is included at the +// root of this file as it only needs to be run once per page load. +const isSafari = + window?.navigator.userAgent && + window.navigator.userAgent.includes( 'Safari' ) && + ! window.navigator.userAgent.includes( 'Chrome' ) && + ! window.navigator.userAgent.includes( 'Chromium' ); + extend( [ namesPlugin ] ); function useMultiOriginPresets( { presetSetting, defaultSetting } ) { @@ -223,6 +234,7 @@ const withDuotoneControls = createHigherOrderComponent( ); function DuotoneStyles( { + clientId, id: filterId, selector: duotoneSelector, attribute: duotoneAttr, @@ -278,6 +290,8 @@ function DuotoneStyles( { useDispatch( blockEditorStore ) ); + const blockElement = useBlockElement( clientId ); + useEffect( () => { if ( ! isValidFilter ) return; @@ -294,12 +308,30 @@ function DuotoneStyles( { __unstableType: 'svgs', } ); + // Safari does not always update the duotone filter when the duotone colors + // are changed. When using Safari, force the block element to be repainted by + // the browser to ensure any changes are reflected visually. This logic matches + // that used on the site frontend in `block-supports/duotone.php`. + if ( blockElement && isSafari ) { + const display = blockElement.style.display; + // Switch to `inline-block` to force a repaint. In the editor, `inline-block` + // is used instead of `none` to ensure that scroll position is not affected, + // as `none` results in the editor scrolling to the top of the block. + blockElement.style.display = 'inline-block'; + // Simply accessing el.offsetHeight flushes layout and style + // changes in WebKit without having to wait for setTimeout. + // eslint-disable-next-line no-unused-expressions + blockElement.offsetHeight; + blockElement.style.display = display; + } + return () => { deleteStyleOverride( filterId ); deleteStyleOverride( `duotone-${ filterId }` ); }; }, [ isValidFilter, + blockElement, colors, selector, filterId, @@ -378,6 +410,7 @@ const withDuotoneStyles = createHigherOrderComponent( <> { shouldRender && ( Date: Fri, 13 Oct 2023 15:46:07 +1100 Subject: [PATCH 3/4] Add more explanatory comments --- packages/block-editor/src/components/block-preview/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 1cbb3513dbd8ba..994347e5522673 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -95,6 +95,9 @@ export default memo( BlockPreview ); function InnerStyles() { const { styles } = useSelect( ( select ) => { + // Retrieve settings (and styles) from the preview's block editor store. + // Since `useBlockPreview` has already cleared out the parent's styles, + // these styles should only contain styles generated by the preview. const settings = select( blockEditorStore ).getSettings(); return { styles: settings.styles, @@ -127,7 +130,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { const settings = useMemo( () => ( { ...originalSettings, - styles: undefined, + styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. __unstableIsPreviewMode: true, } ), [ originalSettings ] From f07605589cb301bfbf0bd3320c15efc75650f732 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 16 Oct 2023 09:05:07 +1100 Subject: [PATCH 4/4] Remove additional check for styles within the block preview, as it is not needed since EditorStyles handles its own style overrides retrieval --- .../src/components/block-preview/index.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 994347e5522673..0fb7f55b9955d2 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -93,20 +93,6 @@ export function BlockPreview( { */ export default memo( BlockPreview ); -function InnerStyles() { - const { styles } = useSelect( ( select ) => { - // Retrieve settings (and styles) from the preview's block editor store. - // Since `useBlockPreview` has already cleared out the parent's styles, - // these styles should only contain styles generated by the preview. - const settings = select( blockEditorStore ).getSettings(); - return { - styles: settings.styles, - }; - }, [] ); - - return ; -} - /** * This hook is used to lightly mark an element as a block preview wrapper * element. Call this hook and pass the returned props to the element to mark as @@ -147,7 +133,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { value={ renderedBlocks } settings={ settings } > - + );