From 2b39d9817bf15675b98bdb628fadb496121a0e91 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 28 Feb 2023 10:03:56 +0100 Subject: [PATCH] Extract a DimensionsPanel component as a reusable component between Global Styles and Block Inspector (#48070) --- .../components/child-layout-control/index.js | 106 +++ .../global-styles/dimensions-panel.js | 627 ++++++++++++++++++ .../src/components/global-styles/hooks.js | 132 ++-- .../src/components/global-styles/index.js | 6 +- .../block-editor/src/hooks/child-layout.js | 195 ------ packages/block-editor/src/hooks/dimensions.js | 354 +++------- packages/block-editor/src/hooks/gap.js | 208 ------ packages/block-editor/src/hooks/margin.js | 165 +---- packages/block-editor/src/hooks/min-height.js | 104 --- packages/block-editor/src/hooks/padding.js | 164 +---- packages/block-editor/src/hooks/typography.js | 55 +- packages/block-editor/src/hooks/utils.js | 90 +++ .../components/global-styles/context-menu.js | 14 +- .../global-styles/dimensions-panel.js | 620 ++--------------- .../global-styles/screen-block-list.js | 13 +- .../components/global-styles/screen-layout.js | 11 +- .../global-styles/typography-panel.js | 12 +- 17 files changed, 1070 insertions(+), 1806 deletions(-) create mode 100644 packages/block-editor/src/components/child-layout-control/index.js create mode 100644 packages/block-editor/src/components/global-styles/dimensions-panel.js delete mode 100644 packages/block-editor/src/hooks/child-layout.js delete mode 100644 packages/block-editor/src/hooks/min-height.js diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js new file mode 100644 index 00000000000000..b7679234ae5939 --- /dev/null +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -0,0 +1,106 @@ +/** + * WordPress dependencies + */ +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, + __experimentalUnitControl as UnitControl, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useEffect } from '@wordpress/element'; + +function helpText( selfStretch, parentLayout ) { + const { orientation = 'horizontal' } = parentLayout; + + if ( selfStretch === 'fill' ) { + return __( 'Stretch to fill available space.' ); + } + if ( selfStretch === 'fixed' && orientation === 'horizontal' ) { + return __( 'Specify a fixed width.' ); + } else if ( selfStretch === 'fixed' ) { + return __( 'Specify a fixed height.' ); + } + return __( 'Fit contents.' ); +} + +/** + * Form to edit the child layout value. + * + * @param {Object} props Props. + * @param {Object} props.value The child layout value. + * @param {Function} props.onChange Function to update the child layout value. + * @param {Object} props.parentLayout The parent layout value. + * + * @return {WPElement} child layout edit element. + */ +export default function ChildLayoutControl( { + value: childLayout = {}, + onChange, + parentLayout, +} ) { + const { selfStretch, flexSize } = childLayout; + + useEffect( () => { + if ( selfStretch === 'fixed' && ! flexSize ) { + onChange( { + ...childLayout, + selfStretch: 'fit', + } ); + } + }, [] ); + + return ( + <> + { + const newFlexSize = value !== 'fixed' ? null : flexSize; + onChange( { + ...childLayout, + selfStretch: value, + flexSize: newFlexSize, + } ); + } } + isBlock={ true } + > + + + + + { selfStretch === 'fixed' && ( + { + onChange( { + ...childLayout, + flexSize: value, + } ); + } } + value={ flexSize } + /> + ) } + + ); +} + +export function childLayoutOrientation( parentLayout ) { + const { orientation = 'horizontal' } = parentLayout; + + return orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' ); +} diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js new file mode 100644 index 00000000000000..b63d9c5d063739 --- /dev/null +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -0,0 +1,627 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + __experimentalToolsPanel as ToolsPanel, + __experimentalToolsPanelItem as ToolsPanelItem, + __experimentalBoxControl as BoxControl, + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalUnitControl as UnitControl, + __experimentalUseCustomUnits as useCustomUnits, + __experimentalView as View, +} from '@wordpress/components'; +import { Icon, positionCenter, stretchWide } from '@wordpress/icons'; +import { useCallback, Platform } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { getValueFromVariable } from './utils'; +import SpacingSizesControl from '../spacing-sizes-control'; +import HeightControl from '../height-control'; +import ChildLayoutControl from '../child-layout-control'; +import { cleanEmptyObject } from '../../hooks/utils'; + +const AXIAL_SIDES = [ 'horizontal', 'vertical' ]; + +export function useHasDimensionsPanel( settings ) { + const hasContentSize = useHasContentSize( settings ); + const hasWideSize = useHasWideSize( settings ); + const hasPadding = useHasPadding( settings ); + const hasMargin = useHasMargin( settings ); + const hasGap = useHasGap( settings ); + const hasMinHeight = useHasMinHeight( settings ); + const hasChildLayout = useHasChildLayout( settings ); + + return ( + Platform.OS === 'web' && + ( hasContentSize || + hasWideSize || + hasPadding || + hasMargin || + hasGap || + hasMinHeight || + hasChildLayout ) + ); +} + +function useHasContentSize( settings ) { + return settings?.layout?.contentSize; +} + +function useHasWideSize( settings ) { + return settings?.layout?.wideSize; +} + +function useHasPadding( settings ) { + return settings?.spacing?.padding; +} + +function useHasMargin( settings ) { + return settings?.spacing?.margin; +} + +function useHasGap( settings ) { + return settings?.spacing?.blockGap; +} + +function useHasMinHeight( settings ) { + return settings?.dimensions?.minHeight; +} + +function useHasChildLayout( settings ) { + const { + type: parentLayoutType = 'default', + default: { type: defaultParentLayoutType = 'default' } = {}, + allowSizingOnChildren = false, + } = settings?.parentLayout ?? {}; + + const support = + ( defaultParentLayoutType === 'flex' || parentLayoutType === 'flex' ) && + allowSizingOnChildren; + + return !! settings?.layout && support; +} + +function useHasSpacingPresets( settings ) { + const { + custom, + theme, + default: defaultPresets, + } = settings?.spacing?.spacingSizes || {}; + const presets = custom ?? theme ?? defaultPresets ?? []; + + return presets.length > 0; +} + +function filterValuesBySides( values, sides ) { + if ( ! sides ) { + // If no custom side configuration all sides are opted into by default. + return values; + } + + // Only include sides opted into within filtered values. + const filteredValues = {}; + sides.forEach( ( side ) => { + if ( side === 'vertical' ) { + filteredValues.top = values.top; + filteredValues.bottom = values.bottom; + } + if ( side === 'horizontal' ) { + filteredValues.left = values.left; + filteredValues.right = values.right; + } + filteredValues[ side ] = values?.[ side ]; + } ); + + return filteredValues; +} + +function splitStyleValue( value ) { + // Check for shorthand value (a string value). + if ( value && typeof value === 'string' ) { + // Convert to value for individual sides for BoxControl. + return { + top: value, + right: value, + bottom: value, + left: value, + }; + } + + return value; +} + +function splitGapValue( value ) { + // Check for shorthand value (a string value). + if ( value && typeof value === 'string' ) { + // If the value is a string, treat it as a single side (top) for the spacing controls. + return { + top: value, + }; + } + + if ( value ) { + return { + ...value, + right: value?.left, + bottom: value?.top, + }; + } + + return value; +} + +function DimensionsToolsPanel( { + resetAllFilter, + onChange, + value, + panelId, + children, +} ) { + const resetAll = () => { + const updatedValue = resetAllFilter( value ); + onChange( updatedValue ); + }; + + return ( + + { children } + + ); +} + +const DEFAULT_CONTROLS = { + contentSize: true, + wideSize: true, + padding: true, + margin: true, + blockGap: true, + minHeight: true, +}; + +export default function DimensionsPanel( { + as: Wrapper = DimensionsToolsPanel, + value, + onChange, + inheritedValue = value, + settings, + panelId, + defaultControls = DEFAULT_CONTROLS, + onVisualize = () => {}, + // Special case because the layout controls are not part of the dimensions panel + // in global styles but not in block inspector. + includeLayoutControls = false, +} ) { + const decodeValue = ( rawValue ) => + getValueFromVariable( { settings }, '', rawValue ); + + const showSpacingPresetsControl = useHasSpacingPresets( settings ); + const units = useCustomUnits( { + availableUnits: settings?.spacing?.units || [ + '%', + 'px', + 'em', + 'rem', + 'vw', + ], + } ); + + // Content Size + const showContentSizeControl = + useHasContentSize( settings ) && includeLayoutControls; + const contentSizeValue = decodeValue( inheritedValue?.layout?.contentSize ); + const setContentSizeValue = ( newValue ) => { + onChange( { + ...value, + layout: { + ...value?.layout, + contentSize: newValue, + }, + } ); + }; + const hasUserSetContentSizeValue = () => !! value?.layout?.contentSize; + const resetContentSizeValue = () => setContentSizeValue( undefined ); + + // Wide Size + const showWideSizeControl = + useHasWideSize( settings ) && includeLayoutControls; + const wideSizeValue = decodeValue( inheritedValue?.layout?.wideSize ); + const setWideSizeValue = ( newValue ) => { + onChange( { + ...value, + layout: { + ...value?.layout, + wideSize: newValue, + }, + } ); + }; + const hasUserSetWideSizeValue = () => !! value?.layout?.wideSize; + const resetWideSizeValue = () => setWideSizeValue( undefined ); + + // Padding + const showPaddingControl = useHasPadding( settings ); + const rawPadding = decodeValue( inheritedValue?.spacing?.padding ); + const paddingValues = splitStyleValue( rawPadding ); + const paddingSides = Array.isArray( settings?.spacing?.padding ) + ? settings?.spacing?.padding + : settings?.spacing?.padding?.sides; + const isAxialPadding = + paddingSides && + paddingSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); + const setPaddingValues = ( newPaddingValues ) => { + const padding = filterValuesBySides( newPaddingValues, paddingSides ); + onChange( { + ...value, + spacing: { + ...value?.spacing, + padding, + }, + } ); + }; + const hasPaddingValue = () => + !! value?.spacing?.padding && + Object.keys( value?.spacing?.padding ).length; + const resetPaddingValue = () => setPaddingValues( undefined ); + const onMouseOverPadding = () => onVisualize( 'padding' ); + + // Margin + const showMarginControl = useHasMargin( settings ); + const rawMargin = decodeValue( inheritedValue?.spacing?.margin ); + const marginValues = splitStyleValue( rawMargin ); + const marginSides = Array.isArray( settings?.spacing?.margin ) + ? settings?.spacing?.margin + : settings?.spacing?.margin?.sides; + const isAxialMargin = + marginSides && + marginSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); + const setMarginValues = ( newMarginValues ) => { + const margin = filterValuesBySides( newMarginValues, marginSides ); + onChange( { + ...value, + spacing: { + ...value?.spacing, + margin, + }, + } ); + }; + const hasMarginValue = () => + !! value?.spacing?.margin && + Object.keys( value?.spacing?.margin ).length; + const resetMarginValue = () => setMarginValues( undefined ); + const onMouseOverMargin = () => onVisualize( 'margin' ); + + // Block Gap + const showGapControl = useHasGap( settings ); + const gapValue = decodeValue( inheritedValue?.spacing?.blockGap ); + const gapValues = splitGapValue( gapValue ); + const gapSides = Array.isArray( settings?.spacing?.blockGap ) + ? settings?.spacing?.blockGap + : settings?.spacing?.blockGap?.sides; + const isAxialGap = + gapSides && gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); + const setGapValue = ( newGapValue ) => { + onChange( { + ...value, + spacing: { + ...value?.spacing, + blockGap: newGapValue, + }, + } ); + }; + const setGapValues = ( nextBoxGapValue ) => { + if ( ! nextBoxGapValue ) { + setGapValue( null ); + } + // If axial gap is not enabled, treat the 'top' value as the shorthand gap value. + if ( ! isAxialGap && nextBoxGapValue?.hasOwnProperty( 'top' ) ) { + setGapValue( nextBoxGapValue.top ); + } else { + setGapValue( { + top: nextBoxGapValue?.top, + left: nextBoxGapValue?.left, + } ); + } + }; + const resetGapValue = () => setGapValue( undefined ); + const hasGapValue = () => !! value?.spacing?.blockGap; + + // Min Height + const showMinHeightControl = useHasMinHeight( settings ); + const minHeightValue = decodeValue( inheritedValue?.dimensions?.minHeight ); + const setMinHeightValue = ( newValue ) => { + onChange( { + ...value, + dimensions: { + ...value?.dimensions, + minHeight: newValue, + }, + } ); + }; + const resetMinHeightValue = () => { + setMinHeightValue( undefined ); + }; + const hasMinHeightValue = () => !! value?.dimensions?.minHeight; + + // Child Layout + const showChildLayoutControl = useHasChildLayout( settings ); + const childLayout = inheritedValue?.layout; + const { orientation = 'horizontal' } = settings?.parentLayout ?? {}; + const childLayoutOrientationLabel = + orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' ); + const setChildLayout = ( newChildLayout ) => { + onChange( { + ...value, + layout: { + ...value?.layout, + ...newChildLayout, + }, + } ); + }; + const resetChildLayoutValue = () => { + setChildLayout( { + selfStretch: undefined, + flexSize: undefined, + } ); + }; + const hasChildLayoutValue = () => !! value?.layout; + + const resetAllFilter = useCallback( ( previousValue ) => { + return { + ...previousValue, + layout: cleanEmptyObject( { + ...previousValue?.layout, + contentSize: undefined, + wideSize: undefined, + selfStretch: undefined, + flexSize: undefined, + } ), + spacing: { + ...previousValue?.spacing, + padding: undefined, + margin: undefined, + blockGap: undefined, + }, + dimensions: { + ...previousValue?.dimensions, + minHeight: undefined, + }, + }; + }, [] ); + + const onMouseLeaveControls = () => onVisualize( false ); + + return ( + + { ( showContentSizeControl || showWideSizeControl ) && ( + + { __( 'Set the width of the main content area.' ) } + + ) } + { showContentSizeControl && ( + + + { + setContentSizeValue( nextContentSize ); + } } + units={ units } + /> + + + + + + ) } + { showWideSizeControl && ( + + + { + setWideSizeValue( nextWideSize ); + } } + units={ units } + /> + + + + + + ) } + { showPaddingControl && ( + + { ! showSpacingPresetsControl && ( + + ) } + { showSpacingPresetsControl && ( + + ) } + + ) } + { showMarginControl && ( + + { ! showSpacingPresetsControl && ( + + ) } + { showSpacingPresetsControl && ( + + ) } + + ) } + { showGapControl && ( + + { ! showSpacingPresetsControl && + ( isAxialGap ? ( + + ) : ( + + ) ) } + { showSpacingPresetsControl && ( + + ) } + + ) } + { showMinHeightControl && ( + + + + ) } + { showChildLayoutControl && ( + + + + ) } + + ); +} diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js index 020b84705958d3..33557025b84922 100644 --- a/packages/block-editor/src/components/global-styles/hooks.js +++ b/packages/block-editor/src/components/global-styles/hooks.js @@ -204,63 +204,105 @@ export function useGlobalStyle( return [ result, setStyle ]; } -export function useSupportedStyles( name, element ) { - const { supportedPanels } = useSelect( +/** + * React hook that overrides a global settings object with block and element specific settings. + * + * @param {Object} parentSettings Settings object. + * @param {blockName?} blockName Block name. + * @param {element?} element Element name. + * + * @return {Object} Merge of settings and supports. + */ +export function useSettingsForBlockElement( + parentSettings, + blockName, + element +) { + const { supportedStyles, supports } = useSelect( ( select ) => { return { - supportedPanels: unlock( + supportedStyles: unlock( select( blocksStore ) - ).getSupportedStyles( name, element ), + ).getSupportedStyles( blockName, element ), + supports: + select( blocksStore ).getBlockType( blockName )?.supports, }; }, - [ name, element ] + [ blockName, element ] ); - return supportedPanels; -} - -/** - * Given a settings object and a list of supported panels, - * returns a new settings object with the unsupported panels removed. - * - * @param {Object} settings Settings object. - * @param {string[]} supports Supported style panels. - * - * @return {Object} Merge of settings and supports. - */ -export function overrideSettingsWithSupports( settings, supports ) { - const updatedSettings = { ...settings }; + return useMemo( () => { + const updatedSettings = { ...parentSettings }; - if ( ! supports.includes( 'fontSize' ) ) { - updatedSettings.typography = { - ...updatedSettings.typography, - fontSizes: {}, - customFontSize: false, - }; - } - - if ( ! supports.includes( 'fontFamily' ) ) { - updatedSettings.typography = { - ...updatedSettings.typography, - fontFamilies: {}, - }; - } + if ( ! supportedStyles.includes( 'fontSize' ) ) { + updatedSettings.typography = { + ...updatedSettings.typography, + fontSizes: {}, + customFontSize: false, + }; + } - [ - 'lineHeight', - 'fontStyle', - 'fontWeight', - 'letterSpacing', - 'textTransform', - 'textDecoration', - ].forEach( ( key ) => { - if ( ! supports.includes( key ) ) { + if ( ! supportedStyles.includes( 'fontFamily' ) ) { updatedSettings.typography = { ...updatedSettings.typography, - [ key ]: false, + fontFamilies: {}, + }; + } + + [ + 'lineHeight', + 'fontStyle', + 'fontWeight', + 'letterSpacing', + 'textTransform', + 'textDecoration', + ].forEach( ( key ) => { + if ( ! supportedStyles.includes( key ) ) { + updatedSettings.typography = { + ...updatedSettings.typography, + [ key ]: false, + }; + } + } ); + + [ 'contentSize', 'wideSize' ].forEach( ( key ) => { + if ( ! supportedStyles.includes( key ) ) { + updatedSettings.layout = { + ...updatedSettings.layout, + [ key ]: false, + }; + } + } ); + + [ 'padding', 'margin', 'blockGap' ].forEach( ( key ) => { + if ( ! supportedStyles.includes( key ) ) { + updatedSettings.spacing = { + ...updatedSettings.spacing, + [ key ]: false, + }; + } + + const sides = Array.isArray( supports?.spacing?.[ key ] ) + ? supports?.spacing?.[ key ] + : supports?.spacing?.[ key ]?.sides; + if ( sides?.length ) { + updatedSettings.spacing = { + ...updatedSettings.spacing, + [ key ]: { + ...updatedSettings.spacing?.[ key ], + sides, + }, + }; + } + } ); + + if ( ! supportedStyles.includes( 'minHeight' ) ) { + updatedSettings.dimensions = { + ...updatedSettings.dimensions, + minHeight: false, }; } - } ); - return updatedSettings; + return updatedSettings; + }, [ parentSettings, supportedStyles, supports ] ); } diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js index 77582d2f054155..9c06af05b2e8b6 100644 --- a/packages/block-editor/src/components/global-styles/index.js +++ b/packages/block-editor/src/components/global-styles/index.js @@ -2,7 +2,7 @@ export { useGlobalStylesReset, useGlobalSetting, useGlobalStyle, - overrideSettingsWithSupports, + useSettingsForBlockElement, } from './hooks'; export { useGlobalStylesOutput } from './use-global-styles-output'; export { GlobalStylesContext } from './context'; @@ -10,3 +10,7 @@ export { default as TypographyPanel, useHasTypographyPanel, } from './typography-panel'; +export { + default as DimensionsPanel, + useHasDimensionsPanel, +} from './dimensions-panel'; diff --git a/packages/block-editor/src/hooks/child-layout.js b/packages/block-editor/src/hooks/child-layout.js deleted file mode 100644 index bf216f32995548..00000000000000 --- a/packages/block-editor/src/hooks/child-layout.js +++ /dev/null @@ -1,195 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalToggleGroupControl as ToggleGroupControl, - __experimentalToggleGroupControlOption as ToggleGroupControlOption, - __experimentalUnitControl as UnitControl, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useEffect } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import useSetting from '../components/use-setting'; - -function helpText( selfStretch, parentLayout ) { - const { orientation = 'horizontal' } = parentLayout; - - if ( selfStretch === 'fill' ) { - return __( 'Stretch to fill available space.' ); - } - if ( selfStretch === 'fixed' ) { - if ( orientation === 'horizontal' ) { - return __( 'Specify a fixed width.' ); - } - return __( 'Specify a fixed height.' ); - } - return __( 'Fit contents.' ); -} - -/** - * Inspector controls containing the child layout related configuration. - * - * @param {Object} props Block props. - * @param {Object} props.attributes Block attributes. - * @param {Object} props.setAttributes Function to set block attributes. - * @param {Object} props.__unstableParentLayout - * - * @return {WPElement} child layout edit element. - */ -export function ChildLayoutEdit( { - attributes, - setAttributes, - __unstableParentLayout: parentLayout, -} ) { - const { style = {} } = attributes; - const { layout: childLayout = {} } = style; - const { selfStretch, flexSize } = childLayout; - - useEffect( () => { - if ( selfStretch === 'fixed' && ! flexSize ) { - setAttributes( { - style: { - ...style, - layout: { - ...childLayout, - selfStretch: 'fit', - }, - }, - } ); - } - }, [] ); - - return ( - <> - { - const newFlexSize = value !== 'fixed' ? null : flexSize; - setAttributes( { - style: { - ...style, - layout: { - ...childLayout, - selfStretch: value, - flexSize: newFlexSize, - }, - }, - } ); - } } - isBlock={ true } - > - - - - - { selfStretch === 'fixed' && ( - { - setAttributes( { - style: { - ...style, - layout: { - ...childLayout, - flexSize: value, - }, - }, - } ); - } } - value={ flexSize } - /> - ) } - - ); -} - -/** - * Determines if there is child layout support. - * - * @param {Object} props Block Props object. - * @param {Object} props.__unstableParentLayout Parent layout. - * - * @return {boolean} Whether there is support. - */ -export function hasChildLayoutSupport( { - __unstableParentLayout: parentLayout = {}, -} ) { - const { - type: parentLayoutType = 'default', - default: { type: defaultParentLayoutType = 'default' } = {}, - allowSizingOnChildren = false, - } = parentLayout; - - const support = - ( defaultParentLayoutType === 'flex' || parentLayoutType === 'flex' ) && - allowSizingOnChildren; - - return support; -} - -/** - * Checks if there is a current value in the child layout attributes. - * - * @param {Object} props Block props. - * @return {boolean} Whether or not the block has a child layout value set. - */ -export function hasChildLayoutValue( props ) { - return props.attributes.style?.layout !== undefined; -} - -/** - * Resets the child layout attribute. This can be used when disabling - * child layout controls for a block via a progressive discovery panel. - * - * @param {Object} props Block props. - * @param {Object} props.attributes Block attributes. - * @param {Object} props.setAttributes Function to set block attributes. - */ -export function resetChildLayout( { attributes = {}, setAttributes } ) { - const { style } = attributes; - - setAttributes( { - style: { - ...style, - layout: undefined, - }, - } ); -} - -/** - * Custom hook that checks if child layout settings have been disabled. - * - * @param {Object} props Block props. - * - * @return {boolean} Whether the child layout setting is disabled. - */ -export function useIsChildLayoutDisabled( props ) { - const isDisabled = ! useSetting( 'layout' ); - - return ! hasChildLayoutSupport( props ) || isDisabled; -} - -export function childLayoutOrientation( parentLayout ) { - const { orientation = 'horizontal' } = parentLayout; - - return orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' ); -} diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index 14384d19b0000b..046800bf0144de 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -1,109 +1,89 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ -import { - __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import { Platform, useState } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import { getBlockSupport } from '@wordpress/blocks'; +import { useState, useEffect, useCallback } from '@wordpress/element'; import { useDispatch } from '@wordpress/data'; +import { getBlockSupport } from '@wordpress/blocks'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import InspectorControls from '../components/inspector-controls'; import { - GapEdit, - hasGapSupport, - hasGapValue, - resetGap, - useIsGapDisabled, -} from './gap'; -import { - MarginEdit, - MarginVisualizer, - hasMarginSupport, - hasMarginValue, - resetMargin, - useIsMarginDisabled, -} from './margin'; -import { - MinHeightEdit, - hasMinHeightSupport, - hasMinHeightValue, - resetMinHeight, - useIsMinHeightDisabled, -} from './min-height'; -import { - PaddingEdit, - PaddingVisualizer, - hasPaddingSupport, - hasPaddingValue, - resetPadding, - useIsPaddingDisabled, -} from './padding'; -import { - ChildLayoutEdit, - hasChildLayoutSupport, - hasChildLayoutValue, - resetChildLayout, - useIsChildLayoutDisabled, - childLayoutOrientation, -} from './child-layout'; -import useSetting from '../components/use-setting'; + DimensionsPanel as StylesDimensionsPanel, + useHasDimensionsPanel, +} from '../components/global-styles'; +import { MarginVisualizer } from './margin'; +import { PaddingVisualizer } from './padding'; import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; +import { cleanEmptyObject, useBlockSettings } from './utils'; + export const DIMENSIONS_SUPPORT_KEY = 'dimensions'; export const SPACING_SUPPORT_KEY = 'spacing'; export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ]; export const AXIAL_SIDES = [ 'vertical', 'horizontal' ]; -function useVisualizerMouseOver() { - const [ isMouseOver, setIsMouseOver ] = useState( false ); +function useVisualizer() { + const [ property, setProperty ] = useState( false ); const { hideBlockInterface, showBlockInterface } = unlock( useDispatch( blockEditorStore ) ); - const onMouseOver = ( e ) => { - e.stopPropagation(); - hideBlockInterface(); - setIsMouseOver( true ); - }; - const onMouseOut = ( e ) => { - e.stopPropagation(); - showBlockInterface(); - setIsMouseOver( false ); - }; - return { isMouseOver, onMouseOver, onMouseOut }; + useEffect( () => { + if ( ! property ) { + showBlockInterface(); + } else { + hideBlockInterface(); + } + }, [ property, showBlockInterface, hideBlockInterface ] ); + + return [ property, setProperty ]; +} + +function DimensionsInspectorControl( { children, resetAllFilter } ) { + const attributesResetAllFilter = useCallback( + ( attributes ) => { + const existingStyle = attributes.style; + const updatedStyle = resetAllFilter( existingStyle ); + return { + ...attributes, + style: updatedStyle, + }; + }, + [ resetAllFilter ] + ); + + return ( + + { children } + + ); } -/** - * Inspector controls for dimensions support. - * - * @param {Object} props Block props. - * - * @return {WPElement} Inspector controls for dimensions and spacing support features. - */ export function DimensionsPanel( props ) { - const isGapDisabled = useIsGapDisabled( props ); - const isPaddingDisabled = useIsPaddingDisabled( props ); - const isMarginDisabled = useIsMarginDisabled( props ); - const isMinHeightDisabled = useIsMinHeightDisabled( props ); - const isChildLayoutDisabled = useIsChildLayoutDisabled( props ); - const isDisabled = useIsDimensionsDisabled( props ); - const isSupported = hasDimensionsSupport( props ); - const spacingSizes = useSetting( 'spacing.spacingSizes' ); - const paddingMouseOver = useVisualizerMouseOver(); - const marginMouseOver = useVisualizerMouseOver(); + const { + clientId, + name, + attributes, + setAttributes, + __unstableParentLayout, + } = props; + const settings = useBlockSettings( name, __unstableParentLayout ); + const isEnabled = useHasDimensionsPanel( settings ); + const value = attributes.style; + const [ visualizedProperty, setVisualizedProperty ] = useVisualizer(); + const onChange = ( newStyle ) => { + setAttributes( { + style: cleanEmptyObject( newStyle ), + } ); + }; - if ( isDisabled || ! isSupported ) { + if ( ! isEnabled ) { return null; } @@ -111,133 +91,36 @@ export function DimensionsPanel( props ) { DIMENSIONS_SUPPORT_KEY, '__experimentalDefaultControls', ] ); - const defaultSpacingControls = getBlockSupport( props.name, [ SPACING_SUPPORT_KEY, '__experimentalDefaultControls', ] ); - - const createResetAllFilter = - ( attribute, featureSet ) => ( newAttributes ) => ( { - ...newAttributes, - style: { - ...newAttributes.style, - [ featureSet ]: { - ...newAttributes.style?.[ featureSet ], - [ attribute ]: undefined, - }, - }, - } ); - - const spacingClassnames = classnames( { - 'tools-panel-item-spacing': spacingSizes && spacingSizes.length > 0, - } ); - - const { __unstableParentLayout: parentLayout } = props; + const defaultControls = { + ...defaultDimensionsControls, + ...defaultSpacingControls, + }; return ( <> - - { ! isPaddingDisabled && ( - hasPaddingValue( props ) } - label={ __( 'Padding' ) } - onDeselect={ () => resetPadding( props ) } - resetAllFilter={ createResetAllFilter( - 'padding', - 'spacing' - ) } - isShownByDefault={ defaultSpacingControls?.padding } - panelId={ props.clientId } - > - - - ) } - { ! isMarginDisabled && ( - hasMarginValue( props ) } - label={ __( 'Margin' ) } - onDeselect={ () => resetMargin( props ) } - resetAllFilter={ createResetAllFilter( - 'margin', - 'spacing' - ) } - isShownByDefault={ defaultSpacingControls?.margin } - panelId={ props.clientId } - > - - - ) } - { ! isGapDisabled && ( - hasGapValue( props ) } - label={ __( 'Block spacing' ) } - onDeselect={ () => resetGap( props ) } - resetAllFilter={ createResetAllFilter( - 'blockGap', - 'spacing' - ) } - isShownByDefault={ defaultSpacingControls?.blockGap } - panelId={ props.clientId } - > - - - ) } - { ! isMinHeightDisabled && ( - hasMinHeightValue( props ) } - label={ __( 'Min. height' ) } - onDeselect={ () => resetMinHeight( props ) } - resetAllFilter={ createResetAllFilter( - 'minHeight', - 'dimensions' - ) } - isShownByDefault={ - defaultDimensionsControls?.minHeight - } - panelId={ props.clientId } - > - - - ) } - { ! isChildLayoutDisabled && ( - hasChildLayoutValue( props ) } - label={ childLayoutOrientation( parentLayout ) } - onDeselect={ () => resetChildLayout( props ) } - resetAllFilter={ createResetAllFilter( - 'selfStretch', - 'layout' - ) } - isShownByDefault={ false } - panelId={ props.clientId } - > - - - ) } - - { ! isPaddingDisabled && ( + + { !! settings?.spacing?.padding && ( ) } - { ! isMarginDisabled && ( + { !! settings?.spacing?.margin && ( ) } @@ -246,80 +129,13 @@ export function DimensionsPanel( props ) { } /** - * Determine whether there is dimensions related block support. - * - * @param {Object} props Block props. - * - * @return {boolean} Whether there is support. - */ -export function hasDimensionsSupport( props ) { - if ( Platform.OS !== 'web' ) { - return false; - } - - const { name: blockName } = props; - - return ( - hasGapSupport( blockName ) || - hasMinHeightSupport( blockName ) || - hasPaddingSupport( blockName ) || - hasMarginSupport( blockName ) || - hasChildLayoutSupport( props ) - ); -} - -/** - * Determines whether dimensions support has been disabled. - * - * @param {Object} props Block properties. - * - * @return {boolean} If spacing support is completely disabled. - */ -const useIsDimensionsDisabled = ( props = {} ) => { - const gapDisabled = useIsGapDisabled( props ); - const minHeightDisabled = useIsMinHeightDisabled( props ); - const paddingDisabled = useIsPaddingDisabled( props ); - const marginDisabled = useIsMarginDisabled( props ); - const childLayoutDisabled = useIsChildLayoutDisabled( props ); - - return ( - gapDisabled && - minHeightDisabled && - paddingDisabled && - marginDisabled && - childLayoutDisabled - ); -}; - -/** - * Custom hook to retrieve which padding/margin/blockGap is supported - * e.g. top, right, bottom or left. - * - * Sides are opted into by default. It is only if a specific side is set to - * false that it is omitted. - * - * @param {string} blockName Block name. - * @param {string} feature The feature custom sides relate to e.g. padding or margins. - * - * @return {string[] | undefined} Strings representing the custom sides available. + * @deprecated */ -export function useCustomSides( blockName, feature ) { - const support = getBlockSupport( blockName, SPACING_SUPPORT_KEY ); - - // Skip when setting is boolean as theme isn't setting arbitrary sides. - if ( ! support || typeof support[ feature ] === 'boolean' ) { - return; - } - - // Return if the setting is an array of sides (e.g. `[ 'top', 'bottom' ]`). - if ( Array.isArray( support[ feature ] ) ) { - return support[ feature ]; - } - - // Finally, attempt to return `.sides` if the setting is an object. - if ( support[ feature ]?.sides ) { - return support[ feature ].sides; - } +export function useCustomSides() { + deprecated( 'wp.blockEditor.__experimentalUseCustomSides', { + since: '6.3', + version: '6.4', + } ); } /** diff --git a/packages/block-editor/src/hooks/gap.js b/packages/block-editor/src/hooks/gap.js index badab83672199e..debe1ad1690782 100644 --- a/packages/block-editor/src/hooks/gap.js +++ b/packages/block-editor/src/hooks/gap.js @@ -1,50 +1,7 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { Platform } from '@wordpress/element'; -import { getBlockSupport } from '@wordpress/blocks'; -import { - __experimentalUseCustomUnits as useCustomUnits, - __experimentalBoxControl as BoxControl, - __experimentalUnitControl as UnitControl, -} from '@wordpress/components'; - /** * Internal dependencies */ -import { __unstableUseBlockRef as useBlockRef } from '../components/block-list/use-block-props/use-block-refs'; import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils'; -import SpacingSizesControl from '../components/spacing-sizes-control'; -import useSetting from '../components/use-setting'; -import { - AXIAL_SIDES, - SPACING_SUPPORT_KEY, - useCustomSides, - useIsDimensionsSupportValid, -} from './dimensions'; -import { cleanEmptyObject } from './utils'; - -/** - * Determines if there is gap support. - * - * @param {string|Object} blockType Block name or Block Type object. - * @return {boolean} Whether there is support. - */ -export function hasGapSupport( blockType ) { - const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY ); - return !! ( true === support || support?.blockGap ); -} - -/** - * Checks if there is a current value in the gap block support attributes. - * - * @param {Object} props Block props. - * @return {boolean} Whether or not the block has a gap value set. - */ -export function hasGapValue( props ) { - return props.attributes.style?.spacing?.blockGap !== undefined; -} /** * Returns a BoxControl object value from a given blockGap style value. @@ -87,168 +44,3 @@ export function getGapCSSValue( blockGapValue, defaultValue = '0' ) { return row === column ? row : `${ row } ${ column }`; } - -/** - * Resets the gap block support attribute. This can be used when disabling - * the gap support controls for a block via a progressive discovery panel. - * - * @param {Object} props Block props. - * @param {Object} props.attributes Block's attributes. - * @param {Object} props.setAttributes Function to set block's attributes. - */ -export function resetGap( { attributes = {}, setAttributes } ) { - const { style } = attributes; - - setAttributes( { - style: { - ...style, - spacing: { - ...style?.spacing, - blockGap: undefined, - }, - }, - } ); -} - -/** - * Custom hook that checks if gap settings have been disabled. - * - * @param {string} name The name of the block. - * @return {boolean} Whether the gap setting is disabled. - */ -export function useIsGapDisabled( { name: blockName } = {} ) { - const isDisabled = ! useSetting( 'spacing.blockGap' ); - const isInvalid = ! useIsDimensionsSupportValid( blockName, 'blockGap' ); - - return ! hasGapSupport( blockName ) || isDisabled || isInvalid; -} - -/** - * Inspector control panel containing the gap related configuration - * - * @param {Object} props - * - * @return {WPElement} Gap edit element. - */ -export function GapEdit( props ) { - const { - clientId, - attributes: { style }, - name: blockName, - setAttributes, - } = props; - - const spacingSizes = useSetting( 'spacing.spacingSizes' ); - - const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || [ - '%', - 'px', - 'em', - 'rem', - 'vw', - ], - } ); - const sides = useCustomSides( blockName, 'blockGap' ); - const ref = useBlockRef( clientId ); - - if ( useIsGapDisabled( props ) ) { - return null; - } - - const splitOnAxis = - sides && sides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - - const onChange = ( next ) => { - let blockGap = next; - - // If splitOnAxis activated we need to return a BoxControl object to the BoxControl component. - if ( !! next && splitOnAxis ) { - blockGap = { ...getGapBoxControlValueFromStyle( next ) }; - } else if ( next?.hasOwnProperty( 'top' ) ) { - // If splitOnAxis is not enabled, treat the 'top' value as the shorthand gap value. - blockGap = next.top; - } - - const newStyle = { - ...style, - spacing: { - ...style?.spacing, - blockGap, - }, - }; - - setAttributes( { - style: cleanEmptyObject( newStyle ), - } ); - - // In Safari, changing the `gap` CSS value on its own will not trigger the layout - // to be recalculated / re-rendered. To force the updated gap to re-render, here - // we replace the block's node with itself. - const isSafari = - window?.navigator.userAgent && - window.navigator.userAgent.includes( 'Safari' ) && - ! window.navigator.userAgent.includes( 'Chrome ' ) && - ! window.navigator.userAgent.includes( 'Chromium ' ); - - if ( ref.current && isSafari ) { - ref.current.parentNode?.replaceChild( ref.current, ref.current ); - } - }; - - const gapValue = getGapBoxControlValueFromStyle( style?.spacing?.blockGap ); - - // The BoxControl component expects a full complement of side values. - // Gap row and column values translate to top/bottom and left/right respectively. - const boxControlGapValue = splitOnAxis - ? { - ...gapValue, - right: gapValue?.left, - bottom: gapValue?.top, - } - : { - top: gapValue?.top, - }; - - return Platform.select( { - web: ( - <> - { ( ! spacingSizes || spacingSizes?.length === 0 ) && - ( splitOnAxis ? ( - - ) : ( - - ) ) } - { spacingSizes?.length > 0 && ( - - ) } - - ), - native: null, - } ); -} diff --git a/packages/block-editor/src/hooks/margin.js b/packages/block-editor/src/hooks/margin.js index b2c3bab595e661..b93616ba32599f 100644 --- a/packages/block-editor/src/hooks/margin.js +++ b/packages/block-editor/src/hooks/margin.js @@ -1,178 +1,15 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { - Platform, - useMemo, - useRef, - useState, - useEffect, -} from '@wordpress/element'; -import { getBlockSupport } from '@wordpress/blocks'; -import { - __experimentalUseCustomUnits as useCustomUnits, - __experimentalBoxControl as BoxControl, -} from '@wordpress/components'; +import { useMemo, useRef, useState, useEffect } from '@wordpress/element'; import isShallowEqual from '@wordpress/is-shallow-equal'; /** * Internal dependencies */ -import useSetting from '../components/use-setting'; -import { - AXIAL_SIDES, - SPACING_SUPPORT_KEY, - useCustomSides, - useIsDimensionsSupportValid, -} from './dimensions'; -import { cleanEmptyObject } from './utils'; import BlockPopover from '../components/block-popover'; -import SpacingSizesControl from '../components/spacing-sizes-control'; import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils'; -/** - * Determines if there is margin support. - * - * @param {string|Object} blockType Block name or Block Type object. - * - * @return {boolean} Whether there is support. - */ -export function hasMarginSupport( blockType ) { - const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY ); - return !! ( true === support || support?.margin ); -} - -/** - * Checks if there is a current value in the margin block support attributes. - * - * @param {Object} props Block props. - * @return {boolean} Whether or not the block has a margin value set. - */ -export function hasMarginValue( props ) { - return props.attributes.style?.spacing?.margin !== undefined; -} - -/** - * Resets the margin block support attributes. This can be used when disabling - * the margin support 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. - */ -export function resetMargin( { attributes = {}, setAttributes } ) { - const { style } = attributes; - - setAttributes( { - style: cleanEmptyObject( { - ...style, - spacing: { - ...style?.spacing, - margin: undefined, - }, - } ), - } ); -} - -/** - * Custom hook that checks if margin settings have been disabled. - * - * @param {string} name The name of the block. - * - * @return {boolean} Whether margin setting is disabled. - */ -export function useIsMarginDisabled( { name: blockName } = {} ) { - const isDisabled = ! useSetting( 'spacing.margin' ); - const isInvalid = ! useIsDimensionsSupportValid( blockName, 'margin' ); - - return ! hasMarginSupport( blockName ) || isDisabled || isInvalid; -} - -/** - * Inspector control panel containing the margin related configuration - * - * @param {Object} props Block props. - * - * @return {WPElement} Margin edit element. - */ -export function MarginEdit( props ) { - const { - name: blockName, - attributes: { style }, - setAttributes, - onMouseOver, - onMouseOut, - } = props; - - const spacingSizes = useSetting( 'spacing.spacingSizes' ); - - const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || [ - '%', - 'px', - 'em', - 'rem', - 'vw', - ], - } ); - const sides = useCustomSides( blockName, 'margin' ); - const splitOnAxis = - sides && sides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - - if ( useIsMarginDisabled( props ) ) { - return null; - } - - const onChange = ( next ) => { - const newStyle = { - ...style, - spacing: { - ...style?.spacing, - margin: next, - }, - }; - - setAttributes( { - style: cleanEmptyObject( newStyle ), - } ); - }; - - return Platform.select( { - web: ( - <> - { ( ! spacingSizes || spacingSizes?.length === 0 ) && ( - - ) } - { spacingSizes?.length > 0 && ( - - ) } - - ), - native: null, - } ); -} - export function MarginVisualizer( { clientId, attributes, forceShow } ) { const margin = attributes?.style?.spacing?.margin; diff --git a/packages/block-editor/src/hooks/min-height.js b/packages/block-editor/src/hooks/min-height.js deleted file mode 100644 index e123f0cee98b22..00000000000000 --- a/packages/block-editor/src/hooks/min-height.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * WordPress dependencies - */ -import { getBlockSupport } from '@wordpress/blocks'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import useSetting from '../components/use-setting'; -import HeightControl from '../components/height-control'; -import { DIMENSIONS_SUPPORT_KEY } from './dimensions'; -import { cleanEmptyObject } from './utils'; - -/** - * Determines if there is minHeight support. - * - * @param {string|Object} blockType Block name or Block Type object. - * @return {boolean} Whether there is support. - */ -export function hasMinHeightSupport( blockType ) { - const support = getBlockSupport( blockType, DIMENSIONS_SUPPORT_KEY ); - return !! ( true === support || support?.minHeight ); -} - -/** - * Checks if there is a current value in the minHeight block support attributes. - * - * @param {Object} props Block props. - * @return {boolean} Whether or not the block has a minHeight value set. - */ -export function hasMinHeightValue( props ) { - return props.attributes.style?.dimensions?.minHeight !== undefined; -} - -/** - * Resets the minHeight block support attributes. This can be used when disabling - * the padding support 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. - */ -export function resetMinHeight( { attributes = {}, setAttributes } ) { - const { style } = attributes; - - setAttributes( { - style: cleanEmptyObject( { - ...style, - dimensions: { - ...style?.dimensions, - minHeight: undefined, - }, - } ), - } ); -} - -/** - * Custom hook that checks if minHeight controls have been disabled. - * - * @param {string} name The name of the block. - * @return {boolean} Whether minHeight control is disabled. - */ -export function useIsMinHeightDisabled( { name: blockName } = {} ) { - const isDisabled = ! useSetting( 'dimensions.minHeight' ); - return ! hasMinHeightSupport( blockName ) || isDisabled; -} - -/** - * Inspector control panel containing the minHeight related configuration. - * - * @param {Object} props Block props. - * @return {WPElement} Edit component for height. - */ -export function MinHeightEdit( props ) { - const { - attributes: { style }, - setAttributes, - } = props; - - if ( useIsMinHeightDisabled( props ) ) { - return null; - } - - const onChange = ( next ) => { - const newStyle = { - ...style, - dimensions: { - ...style?.dimensions, - minHeight: next, - }, - }; - - setAttributes( { style: cleanEmptyObject( newStyle ) } ); - }; - - return ( - - ); -} diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js index ae6b3fb77649db..ea463b13132a13 100644 --- a/packages/block-editor/src/hooks/padding.js +++ b/packages/block-editor/src/hooks/padding.js @@ -1,176 +1,14 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { - Platform, - useState, - useRef, - useEffect, - useMemo, -} from '@wordpress/element'; -import { getBlockSupport } from '@wordpress/blocks'; -import { - __experimentalUseCustomUnits as useCustomUnits, - __experimentalBoxControl as BoxControl, -} from '@wordpress/components'; +import { useState, useRef, useEffect, useMemo } from '@wordpress/element'; import isShallowEqual from '@wordpress/is-shallow-equal'; /** * Internal dependencies */ -import useSetting from '../components/use-setting'; -import { - AXIAL_SIDES, - SPACING_SUPPORT_KEY, - useCustomSides, - useIsDimensionsSupportValid, -} from './dimensions'; -import { cleanEmptyObject } from './utils'; import BlockPopover from '../components/block-popover'; -import SpacingSizesControl from '../components/spacing-sizes-control'; import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils'; -/** - * Determines if there is padding support. - * - * @param {string|Object} blockType Block name or Block Type object. - * - * @return {boolean} Whether there is support. - */ -export function hasPaddingSupport( blockType ) { - const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY ); - return !! ( true === support || support?.padding ); -} - -/** - * Checks if there is a current value in the padding block support attributes. - * - * @param {Object} props Block props. - * @return {boolean} Whether or not the block has a padding value set. - */ -export function hasPaddingValue( props ) { - return props.attributes.style?.spacing?.padding !== undefined; -} - -/** - * Resets the padding block support attributes. This can be used when disabling - * the padding support 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. - */ -export function resetPadding( { attributes = {}, setAttributes } ) { - const { style } = attributes; - - setAttributes( { - style: cleanEmptyObject( { - ...style, - spacing: { - ...style?.spacing, - padding: undefined, - }, - } ), - } ); -} - -/** - * Custom hook that checks if padding settings have been disabled. - * - * @param {string} name The name of the block. - * - * @return {boolean} Whether padding setting is disabled. - */ -export function useIsPaddingDisabled( { name: blockName } = {} ) { - const isDisabled = ! useSetting( 'spacing.padding' ); - const isInvalid = ! useIsDimensionsSupportValid( blockName, 'padding' ); - - return ! hasPaddingSupport( blockName ) || isDisabled || isInvalid; -} - -/** - * Inspector control panel containing the padding related configuration - * - * @param {Object} props - * - * @return {WPElement} Padding edit element. - */ -export function PaddingEdit( props ) { - const { - name: blockName, - attributes: { style }, - setAttributes, - onMouseOver, - onMouseOut, - } = props; - - const spacingSizes = useSetting( 'spacing.spacingSizes' ); - - const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || [ - '%', - 'px', - 'em', - 'rem', - 'vw', - ], - } ); - const sides = useCustomSides( blockName, 'padding' ); - const splitOnAxis = - sides && sides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - - if ( useIsPaddingDisabled( props ) ) { - return null; - } - - const onChange = ( next ) => { - const newStyle = { - ...style, - spacing: { - ...style?.spacing, - padding: next, - }, - }; - - setAttributes( { - style: cleanEmptyObject( newStyle ), - } ); - }; - - return Platform.select( { - web: ( - <> - { ( ! spacingSizes || spacingSizes?.length === 0 ) && ( - - ) } - { spacingSizes?.length > 0 && ( - - ) } - - ), - native: null, - } ); -} export function PaddingVisualizer( { clientId, attributes, forceShow } ) { const padding = attributes?.style?.spacing?.padding; diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index 3cb949b6471152..c5d3c74852777f 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -16,12 +16,7 @@ import { 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 { useSetting } from '../components'; -import { cleanEmptyObject } from './utils'; -import { - overrideSettingsWithSupports, - useSupportedStyles, -} from '../components/global-styles/hooks'; +import { cleanEmptyObject, useBlockSettings } from './utils'; function omit( object, keys ) { return Object.fromEntries( @@ -107,58 +102,14 @@ function TypographyInspectorControl( { children, resetAllFilter } ) { ); } -function useBlockSettings( name ) { - const fontFamilies = useSetting( 'typography.fontFamilies' ); - const fontSizes = useSetting( 'typography.fontSizes' ); - const customFontSize = useSetting( 'typography.customFontSize' ); - const fontStyle = useSetting( 'typography.fontStyle' ); - const fontWeight = useSetting( 'typography.fontWeight' ); - const lineHeight = useSetting( 'typography.lineHeight' ); - const textDecoration = useSetting( 'typography.textDecoration' ); - const textTransform = useSetting( 'typography.textTransform' ); - const letterSpacing = useSetting( 'typography.letterSpacing' ); - const supports = useSupportedStyles( name, null ); - - return useMemo( () => { - const rawSettings = { - typography: { - fontFamilies: { - custom: fontFamilies, - }, - fontSizes: { - custom: fontSizes, - }, - customFontSize, - fontStyle, - fontWeight, - lineHeight, - textDecoration, - textTransform, - letterSpacing, - }, - }; - return overrideSettingsWithSupports( rawSettings, supports ); - }, [ - fontFamilies, - fontSizes, - customFontSize, - fontStyle, - fontWeight, - lineHeight, - textDecoration, - textTransform, - letterSpacing, - supports, - ] ); -} - export function TypographyPanel( { clientId, name, attributes, setAttributes, + __unstableParentLayout, } ) { - const settings = useBlockSettings( name ); + const settings = useBlockSettings( name, __unstableParentLayout ); const isEnabled = useHasTypographyPanel( settings ); const value = useMemo( () => { return attributesToStyle( { diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 855c065ec72f3a..87d666e7cb7695 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -7,6 +7,13 @@ import { isEmpty, mapValues, get } from 'lodash'; * WordPress dependencies */ import { getBlockSupport } from '@wordpress/blocks'; +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { useSetting } from '../components'; +import { useSettingsForBlockElement } from '../components/global-styles/hooks'; /** * Removed falsy values from nested object. @@ -177,3 +184,86 @@ export function shouldSkipSerialization( blockType, featureSet, feature ) { return skipSerialization; } + +/** + * Based on the block and its context, returns an object of all the block settings. + * This object can be passed as a prop to all the Styles UI components + * (TypographyPanel, DimensionsPanel...). + * + * @param {string} name Block name. + * @param {*} parentLayout Parent layout. + * + * @return {Object} Settings object. + */ +export function useBlockSettings( name, parentLayout ) { + const fontFamilies = useSetting( 'typography.fontFamilies' ); + const fontSizes = useSetting( 'typography.fontSizes' ); + const customFontSize = useSetting( 'typography.customFontSize' ); + const fontStyle = useSetting( 'typography.fontStyle' ); + const fontWeight = useSetting( 'typography.fontWeight' ); + const lineHeight = useSetting( 'typography.lineHeight' ); + const textDecoration = useSetting( 'typography.textDecoration' ); + const textTransform = useSetting( 'typography.textTransform' ); + const letterSpacing = useSetting( 'typography.letterSpacing' ); + const padding = useSetting( 'spacing.padding' ); + const margin = useSetting( 'spacing.margin' ); + const blockGap = useSetting( 'spacing.blockGap' ); + const spacingSizes = useSetting( 'spacing.spacingSizes' ); + const units = useSetting( 'spacing.units' ); + const minHeight = useSetting( 'dimensions.minHeight' ); + const layout = useSetting( 'layout' ); + + const rawSettings = useMemo( () => { + return { + typography: { + fontFamilies: { + custom: fontFamilies, + }, + fontSizes: { + custom: fontSizes, + }, + customFontSize, + fontStyle, + fontWeight, + lineHeight, + textDecoration, + textTransform, + letterSpacing, + }, + spacing: { + spacingSizes: { + custom: spacingSizes, + }, + padding, + margin, + blockGap, + units, + }, + dimensions: { + minHeight, + }, + layout, + parentLayout, + }; + }, [ + fontFamilies, + fontSizes, + customFontSize, + fontStyle, + fontWeight, + lineHeight, + textDecoration, + textTransform, + letterSpacing, + padding, + margin, + blockGap, + spacingSizes, + units, + minHeight, + layout, + parentLayout, + ] ); + + return useSettingsForBlockElement( rawSettings, name ); +} diff --git a/packages/edit-site/src/components/global-styles/context-menu.js b/packages/edit-site/src/components/global-styles/context-menu.js index 1aff63dd307140..fd9565412ede76 100644 --- a/packages/edit-site/src/components/global-styles/context-menu.js +++ b/packages/edit-site/src/components/global-styles/context-menu.js @@ -23,14 +23,12 @@ import { isRTL, __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ import { useHasBorderPanel } from './border-panel'; import { useHasColorPanel } from './color-utils'; -import { useHasDimensionsPanel } from './dimensions-panel'; import { useHasFilterPanel } from './filter-utils'; import { useHasVariationsPanel } from './variations-panel'; import { NavigationButtonAsItem } from './navigation-button'; @@ -38,27 +36,23 @@ import { IconWithCurrentColor } from './icon-with-current-color'; import { ScreenVariations } from './screen-variations'; import { useHasShadowControl } from './shadow-panel'; import { unlock } from '../../private-apis'; -import { useSupportedStyles } from './hooks'; const { + useHasDimensionsPanel, useHasTypographyPanel, useGlobalSetting, - overrideSettingsWithSupports, + useSettingsForBlockElement, } = unlock( blockEditorPrivateApis ); function ContextMenu( { name, parentMenu = '' } ) { const [ rawSettings ] = useGlobalSetting( '', name ); - const supports = useSupportedStyles( name ); - const settings = useMemo( - () => overrideSettingsWithSupports( rawSettings, supports ), - [ rawSettings, supports ] - ); + const settings = useSettingsForBlockElement( rawSettings, name ); const hasTypographyPanel = useHasTypographyPanel( settings ); const hasColorPanel = useHasColorPanel( name ); const hasBorderPanel = useHasBorderPanel( name ); const hasEffectsPanel = useHasShadowControl( name ); const hasFilterPanel = useHasFilterPanel( name ); - const hasDimensionsPanel = useHasDimensionsPanel( name ); + const hasDimensionsPanel = useHasDimensionsPanel( settings ); const hasLayoutPanel = hasDimensionsPanel; const hasVariationsPanel = useHasVariationsPanel( name, parentMenu ); diff --git a/packages/edit-site/src/components/global-styles/dimensions-panel.js b/packages/edit-site/src/components/global-styles/dimensions-panel.js index c0b4bae554bd66..7875591c5676f5 100644 --- a/packages/edit-site/src/components/global-styles/dimensions-panel.js +++ b/packages/edit-site/src/components/global-styles/dimensions-panel.js @@ -1,605 +1,71 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { - __experimentalToolsPanel as ToolsPanel, - __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalBoxControl as BoxControl, - __experimentalHStack as HStack, - __experimentalUnitControl as UnitControl, - __experimentalUseCustomUnits as useCustomUnits, - __experimentalView as View, -} from '@wordpress/components'; -import { - __experimentalUseCustomSides as useCustomSides, - HeightControl, - __experimentalSpacingSizesControl as SpacingSizesControl, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; -import { Icon, positionCenter, stretchWide } from '@wordpress/icons'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import { useSupportedStyles } from './hooks'; import { unlock } from '../../private-apis'; -const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorPrivateApis ); - -const AXIAL_SIDES = [ 'horizontal', 'vertical' ]; - -export function useHasDimensionsPanel( name ) { - const hasContentSize = useHasContentSize( name ); - const hasWideSize = useHasWideSize( name ); - const hasPadding = useHasPadding( name ); - const hasMargin = useHasMargin( name ); - const hasGap = useHasGap( name ); - const hasMinHeight = useHasMinHeight( name ); - - return ( - hasContentSize || - hasWideSize || - hasPadding || - hasMargin || - hasGap || - hasMinHeight - ); -} - -function useHasContentSize( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'layout.contentSize', name ); - - return settings && supports.includes( 'contentSize' ); -} +const { + useGlobalStyle, + useGlobalSetting, + useSettingsForBlockElement, + DimensionsPanel: StylesDimensionsPanel, +} = unlock( blockEditorPrivateApis ); -function useHasWideSize( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'layout.wideSize', name ); - - return settings && supports.includes( 'wideSize' ); -} - -function useHasPadding( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'spacing.padding', name ); - - return settings && supports.includes( 'padding' ); -} - -function useHasMargin( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'spacing.margin', name ); - - return settings && supports.includes( 'margin' ); -} - -function useHasGap( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'spacing.blockGap', name ); - - return settings && supports.includes( 'blockGap' ); -} - -function useHasMinHeight( name ) { - const supports = useSupportedStyles( name ); - const [ settings ] = useGlobalSetting( 'dimensions.minHeight', name ); - - return settings && supports.includes( 'minHeight' ); -} - -function useHasSpacingPresets() { - const [ settings ] = useGlobalSetting( 'spacing.spacingSizes' ); - const { custom, theme, default: defaultPresets } = settings || {}; - const presets = custom ?? theme ?? defaultPresets ?? []; - - return settings && presets.length > 0; -} - -function filterValuesBySides( values, sides ) { - if ( ! sides ) { - // If no custom side configuration all sides are opted into by default. - return values; +export default function DimensionsPanel( { name, variation = '' } ) { + let prefixParts = []; + if ( variation ) { + prefixParts = [ 'variations', variation ].concat( prefixParts ); } + const prefix = prefixParts.join( '.' ); - // Only include sides opted into within filtered values. - const filteredValues = {}; - sides.forEach( ( side ) => { - if ( side === 'vertical' ) { - filteredValues.top = values.top; - filteredValues.bottom = values.bottom; - } - if ( side === 'horizontal' ) { - filteredValues.left = values.left; - filteredValues.right = values.right; - } - filteredValues[ side ] = values[ side ]; + const [ style ] = useGlobalStyle( prefix, name, 'user', false ); + const [ inheritedStyle, setStyle ] = useGlobalStyle( prefix, name, 'all', { + shouldDecodeEncode: false, } ); + const [ rawSettings, setSettings ] = useGlobalSetting( '', name ); + const settings = useSettingsForBlockElement( rawSettings, name ); - return filteredValues; -} - -function splitStyleValue( value ) { - // Check for shorthand value (a string value). - if ( value && typeof value === 'string' ) { - // Convert to value for individual sides for BoxControl. + // These intermediary objects are needed because the "layout" property is stored + // in settings rather than styles. + const inheritedStyleWithLayout = useMemo( () => { return { - top: value, - right: value, - bottom: value, - left: value, + ...inheritedStyle, + layout: settings.layout, }; - } - - return value; -} + }, [ inheritedStyle, settings.layout ] ); -function splitGapValue( value ) { - // Check for shorthand value (a string value). - if ( value && typeof value === 'string' ) { - // If the value is a string, treat it as a single side (top) for the spacing controls. + const styleWithLayout = useMemo( () => { return { - top: value, + ...style, + layout: settings.layout, }; - } + }, [ style, settings.layout ] ); - if ( value ) { - return { - ...value, - right: value?.left, - bottom: value?.top, - }; - } + const onChange = ( newStyle ) => { + const updatedStyle = { ...newStyle }; + delete updatedStyle.layout; + setStyle( updatedStyle ); - return value; -} - -// Props for managing `layout.contentSize`. -function useContentSizeProps( name ) { - const [ contentSizeValue, setContentSizeValue ] = useGlobalSetting( - 'layout.contentSize', - name - ); - const [ userSetContentSizeValue ] = useGlobalSetting( - 'layout.contentSize', - name, - 'user' - ); - const hasUserSetContentSizeValue = () => !! userSetContentSizeValue; - const resetContentSizeValue = () => setContentSizeValue( '' ); - return { - contentSizeValue, - setContentSizeValue, - hasUserSetContentSizeValue, - resetContentSizeValue, - }; -} - -// Props for managing `layout.wideSize`. -function useWideSizeProps( name ) { - const [ wideSizeValue, setWideSizeValue ] = useGlobalSetting( - 'layout.wideSize', - name - ); - const [ userSetWideSizeValue ] = useGlobalSetting( - 'layout.wideSize', - name, - 'user' - ); - const hasUserSetWideSizeValue = () => !! userSetWideSizeValue; - const resetWideSizeValue = () => setWideSizeValue( '' ); - return { - wideSizeValue, - setWideSizeValue, - hasUserSetWideSizeValue, - resetWideSizeValue, - }; -} - -// Props for managing `spacing.padding`. -function usePaddingProps( name, variation = '' ) { - const prefix = variation ? `variations.${ variation }.` : ''; - const [ rawPadding, setRawPadding ] = useGlobalStyle( - prefix + 'spacing.padding', - name - ); - const paddingValues = splitStyleValue( rawPadding ); - const paddingSides = useCustomSides( name, 'padding' ); - const isAxialPadding = - paddingSides && - paddingSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - - const setPaddingValues = ( newPaddingValues ) => { - const padding = filterValuesBySides( newPaddingValues, paddingSides ); - setRawPadding( padding ); - }; - const resetPaddingValue = () => setPaddingValues( {} ); - const [ userSetPaddingValue ] = useGlobalStyle( - prefix + 'spacing.padding', - name, - 'user' - ); - // The `hasPaddingValue` check does not need a parsed value, as `userSetPaddingValue` will be `undefined` if not set. - const hasPaddingValue = () => !! userSetPaddingValue; - - return { - paddingValues, - paddingSides, - isAxialPadding, - setPaddingValues, - resetPaddingValue, - hasPaddingValue, - }; -} - -// Props for managing `spacing.margin`. -function useMarginProps( name, variation = '' ) { - const prefix = variation ? `variations.${ variation }.` : ''; - const [ rawMargin, setRawMargin ] = useGlobalStyle( - prefix + 'spacing.margin', - name - ); - const marginValues = splitStyleValue( rawMargin ); - const marginSides = useCustomSides( name, 'margin' ); - const isAxialMargin = - marginSides && - marginSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - - const setMarginValues = ( newMarginValues ) => { - const margin = filterValuesBySides( newMarginValues, marginSides ); - setRawMargin( margin ); - }; - const resetMarginValue = () => setMarginValues( {} ); - const hasMarginValue = () => - !! marginValues && Object.keys( marginValues ).length; - - return { - marginValues, - marginSides, - isAxialMargin, - setMarginValues, - resetMarginValue, - hasMarginValue, - }; -} - -// Props for managing `spacing.blockGap`. -function useBlockGapProps( name, variation = '' ) { - const prefix = variation ? `variations.${ variation }.` : ''; - const [ gapValue, setGapValue ] = useGlobalStyle( - prefix + 'spacing.blockGap', - name - ); - const gapValues = splitGapValue( gapValue ); - const gapSides = useCustomSides( name, 'blockGap' ); - const isAxialGap = - gapSides && gapSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); - const resetGapValue = () => setGapValue( undefined ); - const [ userSetGapValue ] = useGlobalStyle( - prefix + 'spacing.blockGap', - name, - 'user' - ); - const hasGapValue = () => !! userSetGapValue; - const setGapValues = ( nextBoxGapValue ) => { - if ( ! nextBoxGapValue ) { - setGapValue( null ); - } - // If axial gap is not enabled, treat the 'top' value as the shorthand gap value. - if ( ! isAxialGap && nextBoxGapValue?.hasOwnProperty( 'top' ) ) { - setGapValue( nextBoxGapValue.top ); - } else { - setGapValue( { - top: nextBoxGapValue?.top, - left: nextBoxGapValue?.left, + if ( newStyle.layout !== settings.layout ) { + setSettings( { + ...rawSettings, + layout: newStyle.layout, } ); } }; - return { - gapValue, - gapValues, - gapSides, - isAxialGap, - setGapValue, - setGapValues, - resetGapValue, - hasGapValue, - }; -} - -// Props for managing `dimensions.minHeight`. -function useMinHeightProps( name, variation = '' ) { - const prefix = variation ? `variations.${ variation }.` : ''; - const [ minHeightValue, setMinHeightValue ] = useGlobalStyle( - prefix + 'dimensions.minHeight', - name - ); - const resetMinHeightValue = () => setMinHeightValue( undefined ); - const hasMinHeightValue = () => !! minHeightValue; - return { - minHeightValue, - setMinHeightValue, - resetMinHeightValue, - hasMinHeightValue, - }; -} - -export default function DimensionsPanel( { name, variation = '' } ) { - const showContentSizeControl = useHasContentSize( name ); - const showWideSizeControl = useHasWideSize( name ); - const showPaddingControl = useHasPadding( name ); - const showMarginControl = useHasMargin( name ); - const showGapControl = useHasGap( name ); - const showMinHeightControl = useHasMinHeight( name ); - const showSpacingPresetsControl = useHasSpacingPresets(); - const units = useCustomUnits( { - availableUnits: useGlobalSetting( 'spacing.units', name )[ 0 ] || [ - '%', - 'px', - 'em', - 'rem', - 'vw', - ], - } ); - - // Props for managing `layout.contentSize`. - const { - contentSizeValue, - setContentSizeValue, - hasUserSetContentSizeValue, - resetContentSizeValue, - } = useContentSizeProps( name ); - - // Props for managing `layout.wideSize`. - const { - wideSizeValue, - setWideSizeValue, - hasUserSetWideSizeValue, - resetWideSizeValue, - } = useWideSizeProps( name ); - - // Props for managing `spacing.padding`. - const { - paddingValues, - paddingSides, - isAxialPadding, - setPaddingValues, - resetPaddingValue, - hasPaddingValue, - } = usePaddingProps( name, variation ); - - // Props for managing `spacing.margin`. - const { - marginValues, - marginSides, - isAxialMargin, - setMarginValues, - resetMarginValue, - hasMarginValue, - } = useMarginProps( name, variation ); - - // Props for managing `spacing.blockGap`. - const { - gapValue, - gapValues, - gapSides, - isAxialGap, - setGapValue, - setGapValues, - resetGapValue, - hasGapValue, - } = useBlockGapProps( name, variation ); - - // Props for managing `dimensions.minHeight`. - const { - minHeightValue, - setMinHeightValue, - resetMinHeightValue, - hasMinHeightValue, - } = useMinHeightProps( name, variation ); - - const resetAll = () => { - resetPaddingValue(); - resetMarginValue(); - resetGapValue(); - resetContentSizeValue(); - resetWideSizeValue(); - }; return ( - - { ( showContentSizeControl || showWideSizeControl ) && ( - - { __( 'Set the width of the main content area.' ) } - - ) } - { showContentSizeControl && ( - - - { - setContentSizeValue( nextContentSize ); - } } - units={ units } - /> - - - - - - ) } - { showWideSizeControl && ( - - - { - setWideSizeValue( nextWideSize ); - } } - units={ units } - /> - - - - - - ) } - { showPaddingControl && ( - - { ! showSpacingPresetsControl && ( - - ) } - { showSpacingPresetsControl && ( - - ) } - - ) } - { showMarginControl && ( - - { ! showSpacingPresetsControl && ( - - ) } - { showSpacingPresetsControl && ( - - ) } - - ) } - { showGapControl && ( - - { ! showSpacingPresetsControl && - ( isAxialGap ? ( - - ) : ( - - ) ) } - { showSpacingPresetsControl && ( - - ) } - - ) } - { showMinHeightControl && ( - - - - ) } - + ); } diff --git a/packages/edit-site/src/components/global-styles/screen-block-list.js b/packages/edit-site/src/components/global-styles/screen-block-list.js index 0bfbe96f23b604..07a6f8554af84a 100644 --- a/packages/edit-site/src/components/global-styles/screen-block-list.js +++ b/packages/edit-site/src/components/global-styles/screen-block-list.js @@ -22,17 +22,16 @@ import { speak } from '@wordpress/a11y'; */ import { useHasBorderPanel } from './border-panel'; import { useHasColorPanel } from './color-utils'; -import { useHasDimensionsPanel } from './dimensions-panel'; import { useHasVariationsPanel } from './variations-panel'; import ScreenHeader from './header'; import { NavigationButtonAsItem } from './navigation-button'; import { unlock } from '../../private-apis'; -import { useSupportedStyles } from './hooks'; const { + useHasDimensionsPanel, useHasTypographyPanel, useGlobalSetting, - overrideSettingsWithSupports, + useSettingsForBlockElement, } = unlock( blockEditorPrivateApis ); function useSortedBlockTypes() { @@ -60,15 +59,11 @@ function useSortedBlockTypes() { function BlockMenuItem( { block } ) { const [ rawSettings ] = useGlobalSetting( '', block.name ); - const supports = useSupportedStyles( block.name ); - const settings = useMemo( - () => overrideSettingsWithSupports( rawSettings, supports ), - [ rawSettings, supports ] - ); + const settings = useSettingsForBlockElement( rawSettings, block.name ); const hasTypographyPanel = useHasTypographyPanel( settings ); const hasColorPanel = useHasColorPanel( block.name ); const hasBorderPanel = useHasBorderPanel( block.name ); - const hasDimensionsPanel = useHasDimensionsPanel( block.name ); + const hasDimensionsPanel = useHasDimensionsPanel( settings ); const hasLayoutPanel = hasBorderPanel || hasDimensionsPanel; const hasVariationsPanel = useHasVariationsPanel( block.name ); const hasBlockMenuItem = diff --git a/packages/edit-site/src/components/global-styles/screen-layout.js b/packages/edit-site/src/components/global-styles/screen-layout.js index bae67366f1f0f0..02d28d3c9c6dac 100644 --- a/packages/edit-site/src/components/global-styles/screen-layout.js +++ b/packages/edit-site/src/components/global-styles/screen-layout.js @@ -2,17 +2,24 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; /** * Internal dependencies */ -import DimensionsPanel, { useHasDimensionsPanel } from './dimensions-panel'; +import DimensionsPanel from './dimensions-panel'; import ScreenHeader from './header'; import BlockPreviewPanel from './block-preview-panel'; import { getVariationClassName } from './utils'; +import { unlock } from '../../private-apis'; + +const { useHasDimensionsPanel, useGlobalSetting, useSettingsForBlockElement } = + unlock( blockEditorPrivateApis ); function ScreenLayout( { name, variation = '' } ) { - const hasDimensionsPanel = useHasDimensionsPanel( name ); + const [ rawSettings ] = useGlobalSetting( '', name ); + const settings = useSettingsForBlockElement( rawSettings, name ); + const hasDimensionsPanel = useHasDimensionsPanel( settings ); const variationClassName = getVariationClassName( variation ); return ( <> diff --git a/packages/edit-site/src/components/global-styles/typography-panel.js b/packages/edit-site/src/components/global-styles/typography-panel.js index da2429432d795d..ebdc59484f1821 100644 --- a/packages/edit-site/src/components/global-styles/typography-panel.js +++ b/packages/edit-site/src/components/global-styles/typography-panel.js @@ -2,18 +2,16 @@ * WordPress dependencies */ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ import { unlock } from '../../private-apis'; -import { useSupportedStyles } from './hooks'; const { useGlobalStyle, useGlobalSetting, - overrideSettingsWithSupports, + useSettingsForBlockElement, TypographyPanel: StylesTypographyPanel, } = unlock( blockEditorPrivateApis ); @@ -40,10 +38,10 @@ export default function TypographyPanel( { } ); const [ rawSettings ] = useGlobalSetting( '', name ); const usedElement = element === 'heading' ? headingLevel : element; - const supports = useSupportedStyles( name, usedElement ); - const settings = useMemo( - () => overrideSettingsWithSupports( rawSettings, supports ), - [ rawSettings, supports ] + const settings = useSettingsForBlockElement( + rawSettings, + name, + usedElement ); return (