diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index b0f93fa8b2e06..342db267ff331 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -24,6 +24,7 @@ import { Platform, useCallback, useRef } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { getFilename } from '@wordpress/url'; +import { pure } from '@wordpress/compose'; /** * Internal dependencies @@ -41,13 +42,13 @@ export const IMAGE_BACKGROUND_TYPE = 'image'; * Checks if there is a current value in the background image block support * attributes. * - * @param {Object} props Block props. + * @param {Object} style Style attribute. * @return {boolean} Whether or not the block has a background image value set. */ -export function hasBackgroundImageValue( props ) { +export function hasBackgroundImageValue( style ) { const hasValue = - !! props.attributes.style?.background?.backgroundImage?.id || - !! props.attributes.style?.background?.backgroundImage?.url; + !! style?.background?.backgroundImage?.id || + !! style?.background?.backgroundImage?.url; return hasValue; } @@ -82,13 +83,10 @@ export function hasBackgroundSupport( blockName, feature = 'any' ) { * Resets the background image block support attributes. This can be used when disabling * the background image controls for a block via a `ToolsPanel`. * - * @param {Object} props Block props. - * @param {Object} props.attributes Block's attributes. - * @param {Object} props.setAttributes Function to set block's attributes. + * @param {Object} style Style attribute. + * @param {Function} setAttributes Function to set block's attributes. */ -export function resetBackgroundImage( { attributes = {}, setAttributes } ) { - const { style = {} } = attributes; - +export function resetBackgroundImage( style = {}, setAttributes ) { setAttributes( { style: cleanEmptyObject( { ...style, @@ -145,11 +143,13 @@ function InspectorImagePreview( { label, filename, url: imgUrl } ) { ); } -function BackgroundImagePanelItem( props ) { - const { attributes, clientId, setAttributes } = props; - - const { id, title, url } = - attributes.style?.background?.backgroundImage || {}; +function BackgroundImagePanelItem( { clientId, setAttributes } ) { + const style = useSelect( + ( select ) => + select( blockEditorStore ).getBlockAttributes( clientId )?.style, + [ clientId ] + ); + const { id, title, url } = style?.background?.backgroundImage || {}; const replaceContainerRef = useRef(); @@ -167,9 +167,9 @@ function BackgroundImagePanelItem( props ) { const onSelectMedia = ( media ) => { if ( ! media || ! media.url ) { const newStyle = { - ...attributes.style, + ...style, background: { - ...attributes.style?.background, + ...style?.background, backgroundImage: undefined, }, }; @@ -201,9 +201,9 @@ function BackgroundImagePanelItem( props ) { } const newStyle = { - ...attributes.style, + ...style, background: { - ...attributes.style?.background, + ...style?.background, backgroundImage: { url: media.url, id: media.id, @@ -244,14 +244,14 @@ function BackgroundImagePanelItem( props ) { }; }, [] ); - const hasValue = hasBackgroundImageValue( props ); + const hasValue = hasBackgroundImageValue( style ); return ( hasValue } label={ __( 'Background image' ) } - onDeselect={ () => resetBackgroundImage( props ) } + onDeselect={ () => resetBackgroundImage( style, setAttributes ) } isShownByDefault={ true } resetAllFilter={ resetAllFilter } panelId={ clientId } @@ -286,7 +286,7 @@ function BackgroundImagePanelItem( props ) { // closed and focus is redirected to the dropdown toggle button. toggleButton?.focus(); toggleButton?.click(); - resetBackgroundImage( props ); + resetBackgroundImage( style, setAttributes ); } } > { __( 'Reset ' ) } @@ -302,7 +302,7 @@ function BackgroundImagePanelItem( props ) { ); } -export function BackgroundImagePanel( props ) { +function BackgroundImagePanelPure( props ) { const [ backgroundImage ] = useSettings( 'background.backgroundImage' ); if ( ! backgroundImage || @@ -317,3 +317,5 @@ export function BackgroundImagePanel( props ) { ); } + +export const BackgroundImagePanel = pure( BackgroundImagePanelPure ); diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index c2d30d5501576..29e4afd2f018c 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -8,9 +8,10 @@ import classnames from 'classnames'; */ import { getBlockSupport } from '@wordpress/blocks'; import { __experimentalHasSplitBorders as hasSplitBorders } from '@wordpress/components'; -import { createHigherOrderComponent } from '@wordpress/compose'; +import { createHigherOrderComponent, pure } from '@wordpress/compose'; import { Platform, useCallback, useMemo } from '@wordpress/element'; import { addFilter } from '@wordpress/hooks'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -27,6 +28,7 @@ import { useHasBorderPanel, BorderPanel as StylesBorderPanel, } from '../components/global-styles'; +import { store as blockEditorStore } from '../store'; export const BORDER_SUPPORT_KEY = '__experimentalBorder'; @@ -135,16 +137,18 @@ function BordersInspectorControl( { children, resetAllFilter } ) { ); } -export function BorderPanel( props ) { - const { clientId, name, attributes, setAttributes } = props; +function BorderPanelPure( { clientId, name, setAttributes } ) { const settings = useBlockSettings( name ); const isEnabled = useHasBorderPanel( settings ); + function selector( select ) { + const { style, borderColor } = + select( blockEditorStore ).getBlockAttributes( clientId ) || {}; + return { style, borderColor }; + } + const { style, borderColor } = useSelect( selector, [ clientId ] ); const value = useMemo( () => { - return attributesToStyle( { - style: attributes.style, - borderColor: attributes.borderColor, - } ); - }, [ attributes.style, attributes.borderColor ] ); + return attributesToStyle( { style, borderColor } ); + }, [ style, borderColor ] ); const onChange = ( newStyle ) => { setAttributes( styleToAttributes( newStyle ) ); @@ -154,7 +158,7 @@ export function BorderPanel( props ) { return null; } - const defaultControls = getBlockSupport( props.name, [ + const defaultControls = getBlockSupport( name, [ BORDER_SUPPORT_KEY, '__experimentalDefaultControls', ] ); @@ -171,6 +175,8 @@ export function BorderPanel( props ) { ); } +export const BorderPanel = pure( BorderPanelPure ); + /** * Determine whether there is block support for border properties. * diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index 19fe4b0ea5ecd..94bcc599dd637 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -9,7 +9,8 @@ import classnames from 'classnames'; import { addFilter } from '@wordpress/hooks'; import { getBlockSupport } from '@wordpress/blocks'; import { useMemo, Platform, useCallback } from '@wordpress/element'; -import { createHigherOrderComponent } from '@wordpress/compose'; +import { createHigherOrderComponent, pure } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -32,6 +33,7 @@ import { default as StylesColorPanel, } from '../components/global-styles/color-panel'; import BlockColorContrastChecker from './contrast-checker'; +import { store as blockEditorStore } from '../store'; export const COLOR_SUPPORT_KEY = 'color'; @@ -289,23 +291,26 @@ function ColorInspectorControl( { children, resetAllFilter } ) { ); } -export function ColorEdit( props ) { - const { clientId, name, attributes, setAttributes } = props; +function ColorEditPure( { clientId, name, setAttributes } ) { const settings = useBlockSettings( name ); const isEnabled = useHasColorPanel( settings ); + function selector( select ) { + const { style, textColor, backgroundColor, gradient } = + select( blockEditorStore ).getBlockAttributes( clientId ) || {}; + return { style, textColor, backgroundColor, gradient }; + } + const { style, textColor, backgroundColor, gradient } = useSelect( + selector, + [ clientId ] + ); const value = useMemo( () => { return attributesToStyle( { - style: attributes.style, - textColor: attributes.textColor, - backgroundColor: attributes.backgroundColor, - gradient: attributes.gradient, + style, + textColor, + backgroundColor, + gradient, } ); - }, [ - attributes.style, - attributes.textColor, - attributes.backgroundColor, - attributes.gradient, - ] ); + }, [ style, textColor, backgroundColor, gradient ] ); const onChange = ( newStyle ) => { setAttributes( styleToAttributes( newStyle ) ); @@ -315,7 +320,7 @@ export function ColorEdit( props ) { return null; } - const defaultControls = getBlockSupport( props.name, [ + const defaultControls = getBlockSupport( name, [ COLOR_SUPPORT_KEY, '__experimentalDefaultControls', ] ); @@ -328,7 +333,7 @@ export function ColorEdit( props ) { // Deactivating it requires `enableContrastChecker` to have // an explicit value of `false`. false !== - getBlockSupport( props.name, [ + getBlockSupport( name, [ COLOR_SUPPORT_KEY, 'enableContrastChecker', ] ); @@ -343,7 +348,7 @@ export function ColorEdit( props ) { defaultControls={ defaultControls } enableContrastChecker={ false !== - getBlockSupport( props.name, [ + getBlockSupport( name, [ COLOR_SUPPORT_KEY, 'enableContrastChecker', ] ) @@ -356,6 +361,8 @@ export function ColorEdit( props ) { ); } +export const ColorEdit = pure( ColorEditPure ); + /** * This adds inline styles for color palette colors. * Ideally, this is not needed and themes should load their palettes on the editor. diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index 084763f0c21b1..4e2b17f363bdd 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -2,9 +2,10 @@ * WordPress dependencies */ import { useState, useEffect, useCallback } from '@wordpress/element'; -import { useDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { getBlockSupport } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; +import { pure } from '@wordpress/compose'; /** * Internal dependencies @@ -65,17 +66,19 @@ function DimensionsInspectorControl( { children, resetAllFilter } ) { ); } -export function DimensionsPanel( props ) { - const { - clientId, - name, - attributes, - setAttributes, - __unstableParentLayout, - } = props; +function DimensionsPanelPure( { + clientId, + name, + setAttributes, + __unstableParentLayout, +} ) { const settings = useBlockSettings( name, __unstableParentLayout ); const isEnabled = useHasDimensionsPanel( settings ); - const value = attributes.style; + const value = useSelect( + ( select ) => + select( blockEditorStore ).getBlockAttributes( clientId )?.style, + [ clientId ] + ); const [ visualizedProperty, setVisualizedProperty ] = useVisualizer(); const onChange = ( newStyle ) => { setAttributes( { @@ -87,11 +90,11 @@ export function DimensionsPanel( props ) { return null; } - const defaultDimensionsControls = getBlockSupport( props.name, [ + const defaultDimensionsControls = getBlockSupport( name, [ DIMENSIONS_SUPPORT_KEY, '__experimentalDefaultControls', ] ); - const defaultSpacingControls = getBlockSupport( props.name, [ + const defaultSpacingControls = getBlockSupport( name, [ SPACING_SUPPORT_KEY, '__experimentalDefaultControls', ] ); @@ -114,19 +117,23 @@ export function DimensionsPanel( props ) { { !! settings?.spacing?.padding && ( ) } { !! settings?.spacing?.margin && ( ) } ); } +export const DimensionsPanel = pure( DimensionsPanelPure ); + /** * @deprecated */ diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js index b6e4e50e30f9c..ca4436153d122 100644 --- a/packages/block-editor/src/hooks/padding.js +++ b/packages/block-editor/src/hooks/padding.js @@ -16,11 +16,11 @@ function getComputedCSS( element, property ) { .getPropertyValue( property ); } -export function PaddingVisualizer( { clientId, attributes, forceShow } ) { +export function PaddingVisualizer( { clientId, value, forceShow } ) { const blockElement = useBlockElement( clientId ); const [ style, setStyle ] = useState(); - const padding = attributes?.style?.spacing?.padding; + const padding = value?.spacing?.padding; useEffect( () => { if ( diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index d74e10b0208f1..8b3a475e1babe 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -361,16 +361,39 @@ export const withBlockStyleControls = createHigherOrderComponent( const shouldDisplayControls = useDisplayBlockControls(); const blockEditingMode = useBlockEditingMode(); + const { clientId, name, setAttributes, __unstableParentLayout } = props; return ( <> { shouldDisplayControls && blockEditingMode === 'default' && ( <> - - - - - + + + + + ) } diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index c7d1a6ba3b144..7d0e5e1c318d5 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -3,6 +3,8 @@ */ import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; import { useMemo, useCallback } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { pure } from '@wordpress/compose'; /** * Internal dependencies @@ -17,6 +19,7 @@ import { LINE_HEIGHT_SUPPORT_KEY } from './line-height'; import { FONT_FAMILY_SUPPORT_KEY } from './font-family'; import { FONT_SIZE_SUPPORT_KEY } from './font-size'; import { cleanEmptyObject, useBlockSettings } from './utils'; +import { store as blockEditorStore } from '../store'; function omit( object, keys ) { return Object.fromEntries( @@ -106,22 +109,24 @@ function TypographyInspectorControl( { children, resetAllFilter } ) { ); } -export function TypographyPanel( { +function TypographyPanelPure( { clientId, name, - attributes, setAttributes, __unstableParentLayout, } ) { + function selector( select ) { + const { style, fontFamily, fontSize } = + select( blockEditorStore ).getBlockAttributes( clientId ) || {}; + return { style, fontFamily, fontSize }; + } + const { style, fontFamily, fontSize } = useSelect( selector, [ clientId ] ); const settings = useBlockSettings( name, __unstableParentLayout ); const isEnabled = useHasTypographyPanel( settings ); - const value = useMemo( () => { - return attributesToStyle( { - style: attributes.style, - fontFamily: attributes.fontFamily, - fontSize: attributes.fontSize, - } ); - }, [ attributes.style, attributes.fontSize, attributes.fontFamily ] ); + const value = useMemo( + () => attributesToStyle( { style, fontFamily, fontSize } ), + [ style, fontSize, fontFamily ] + ); const onChange = ( newStyle ) => { setAttributes( styleToAttributes( newStyle ) ); @@ -148,6 +153,8 @@ export function TypographyPanel( { ); } +export const TypographyPanel = pure( TypographyPanelPure ); + export const hasTypographySupport = ( blockName ) => { return TYPOGRAPHY_SUPPORT_KEYS.some( ( key ) => hasBlockSupport( blockName, key )