diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index b1a97237ab630d..b38dcf3ef1f2ec 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -54,10 +54,18 @@ function mergeWrapperProps( propsA, propsB ) { ...propsB, }; - if ( propsA?.className && propsB?.className ) { + // May be set to undefined, so check if the property is set! + if ( + propsA?.hasOwnProperty( 'className' ) && + propsB?.hasOwnProperty( 'className' ) + ) { newProps.className = classnames( propsA.className, propsB.className ); } - if ( propsA?.style && propsB?.style ) { + + if ( + propsA?.hasOwnProperty( 'style' ) && + propsB?.hasOwnProperty( 'style' ) + ) { newProps.style = { ...propsA.style, ...propsB.style }; } diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js index 6ac4dd2360fb08..c6947eeaa18e38 100644 --- a/packages/block-editor/src/hooks/border.js +++ b/packages/block-editor/src/hooks/border.js @@ -258,16 +258,16 @@ function addAttributes( settings ) { /** * Override props assigned to save component to inject border color. * - * @param {Object} props Additional props applied to save element. - * @param {Object} blockType Block type definition. - * @param {Object} attributes Block's attributes. + * @param {Object} props Additional props applied to save element. + * @param {Object|string} blockNameOrType Block type definition. + * @param {Object} attributes Block's attributes. * * @return {Object} Filtered props to apply to save element. */ -function addSaveProps( props, blockType, attributes ) { +function addSaveProps( props, blockNameOrType, attributes ) { if ( - ! hasBorderSupport( blockType, 'color' ) || - shouldSkipSerialization( blockType, BORDER_SUPPORT_KEY, 'color' ) + ! hasBorderSupport( blockNameOrType, 'color' ) || + shouldSkipSerialization( blockNameOrType, BORDER_SUPPORT_KEY, 'color' ) ) { return props; } @@ -300,36 +300,6 @@ export function getBorderClasses( attributes ) { } ); } -/** - * Filters the registered block settings to apply border color styles and - * classnames to the block edit wrapper. - * - * @param {Object} settings Original block settings. - * - * @return {Object} Filtered block settings. - */ -function addEditProps( settings ) { - if ( - ! hasBorderSupport( settings, 'color' ) || - shouldSkipSerialization( settings, BORDER_SUPPORT_KEY, 'color' ) - ) { - return settings; - } - - const existingGetEditWrapperProps = settings.getEditWrapperProps; - settings.getEditWrapperProps = ( attributes ) => { - let props = {}; - - if ( existingGetEditWrapperProps ) { - props = existingGetEditWrapperProps( attributes ); - } - - return addSaveProps( props, settings, attributes ); - }; - - return settings; -} - function useBlockProps( { name, borderColor, style } ) { const { colors } = useMultipleOriginColorsAndGradients(); @@ -369,7 +339,11 @@ function useBlockProps( { name, borderColor, style } ) { borderLeftColor: borderLeftColor || borderColorValue, }; - return { style: cleanEmptyObject( extraStyles ) || {} }; + return addSaveProps( + { style: cleanEmptyObject( extraStyles ) || {} }, + name, + { borderColor, style } + ); } export default { @@ -391,9 +365,3 @@ addFilter( 'core/border/addSaveProps', addSaveProps ); - -addFilter( - 'blocks.registerBlockType', - 'core/border/addEditProps', - addEditProps -); diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index f259ff9c9c0865..db6c3dc8fd86ce 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -36,8 +36,8 @@ import { store as blockEditorStore } from '../store'; export const COLOR_SUPPORT_KEY = 'color'; -const hasColorSupport = ( blockType ) => { - const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY ); +const hasColorSupport = ( blockNameOrType ) => { + const colorSupport = getBlockSupport( blockNameOrType, COLOR_SUPPORT_KEY ); return ( colorSupport && ( colorSupport.link === true || @@ -61,8 +61,8 @@ const hasLinkColorSupport = ( blockType ) => { ); }; -const hasGradientSupport = ( blockType ) => { - const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY ); +const hasGradientSupport = ( blockNameOrType ) => { + const colorSupport = getBlockSupport( blockNameOrType, COLOR_SUPPORT_KEY ); return ( colorSupport !== null && @@ -126,27 +126,31 @@ function addAttributes( settings ) { /** * Override props assigned to save component to inject colors classnames. * - * @param {Object} props Additional props applied to save element. - * @param {Object} blockType Block type. - * @param {Object} attributes Block attributes. + * @param {Object} props Additional props applied to save element. + * @param {Object|string} blockNameOrType Block type. + * @param {Object} attributes Block attributes. * * @return {Object} Filtered props applied to save element. */ -export function addSaveProps( props, blockType, attributes ) { +export function addSaveProps( props, blockNameOrType, attributes ) { if ( - ! hasColorSupport( blockType ) || - shouldSkipSerialization( blockType, COLOR_SUPPORT_KEY ) + ! hasColorSupport( blockNameOrType ) || + shouldSkipSerialization( blockNameOrType, COLOR_SUPPORT_KEY ) ) { return props; } - const hasGradient = hasGradientSupport( blockType ); + const hasGradient = hasGradientSupport( blockNameOrType ); // I'd have preferred to avoid the "style" attribute usage here const { backgroundColor, textColor, gradient, style } = attributes; const shouldSerialize = ( feature ) => - ! shouldSkipSerialization( blockType, COLOR_SUPPORT_KEY, feature ); + ! shouldSkipSerialization( + blockNameOrType, + COLOR_SUPPORT_KEY, + feature + ); // Primary color classes must come before the `has-text-color`, // `has-background` and `has-link-color` classes to maintain backwards @@ -192,33 +196,6 @@ export function addSaveProps( props, blockType, attributes ) { return props; } -/** - * Filters registered block settings to extend the block edit wrapper - * to apply the desired styles and classnames properly. - * - * @param {Object} settings Original block settings. - * - * @return {Object} Filtered block settings. - */ -export function addEditProps( settings ) { - if ( - ! hasColorSupport( settings ) || - shouldSkipSerialization( settings, COLOR_SUPPORT_KEY ) - ) { - return settings; - } - const existingGetEditWrapperProps = settings.getEditWrapperProps; - settings.getEditWrapperProps = ( attributes ) => { - let props = {}; - if ( existingGetEditWrapperProps ) { - props = existingGetEditWrapperProps( attributes ); - } - return addSaveProps( props, settings, attributes ); - }; - - return settings; -} - function styleToAttributes( style ) { const textColorValue = style?.color?.text; const textColorSlug = textColorValue?.startsWith( 'var:preset|color|' ) @@ -364,7 +341,13 @@ function ColorEditPure( { clientId, name, setAttributes, settings } ) { // and not the whole attributes object. export const ColorEdit = pure( ColorEditPure ); -function useBlockProps( { name, backgroundColor, textColor } ) { +function useBlockProps( { + name, + backgroundColor, + textColor, + gradient, + style, +} ) { const [ userPalette, themePalette, defaultPalette ] = useSettings( 'color.palette.custom', 'color.palette.theme', @@ -406,12 +389,17 @@ function useBlockProps( { name, backgroundColor, textColor } ) { )?.color; } - return { style: extraStyles }; + return addSaveProps( { style: extraStyles }, name, { + textColor, + backgroundColor, + gradient, + style, + } ); } export default { useBlockProps, - attributeKeys: [ 'backgroundColor', 'textColor' ], + attributeKeys: [ 'backgroundColor', 'textColor', 'gradient', 'style' ], hasSupport: hasColorSupport, }; @@ -455,12 +443,6 @@ addFilter( addSaveProps ); -addFilter( - 'blocks.registerBlockType', - 'core/color/addEditProps', - addEditProps -); - addFilter( 'blocks.switchToBlockType.transformedBlock', 'core/color/addTransforms', diff --git a/packages/block-editor/src/hooks/font-family.js b/packages/block-editor/src/hooks/font-family.js index 0988b285564d3e..36266d59adcf2c 100644 --- a/packages/block-editor/src/hooks/font-family.js +++ b/packages/block-editor/src/hooks/font-family.js @@ -74,31 +74,18 @@ function addSaveProps( props, blockType, attributes ) { return props; } -/** - * Filters registered block settings to expand the block edit wrapper - * by applying the desired styles and classnames. - * - * @param {Object} settings Original block settings. - * - * @return {Object} Filtered block settings. - */ -function addEditProps( settings ) { - if ( ! hasBlockSupport( settings, FONT_FAMILY_SUPPORT_KEY ) ) { - return settings; - } - - const existingGetEditWrapperProps = settings.getEditWrapperProps; - settings.getEditWrapperProps = ( attributes ) => { - let props = {}; - if ( existingGetEditWrapperProps ) { - props = existingGetEditWrapperProps( attributes ); - } - return addSaveProps( props, settings, attributes ); - }; - - return settings; +function useBlockProps( { name, fontFamily } ) { + return addSaveProps( {}, name, { fontFamily } ); } +export default { + useBlockProps, + attributeKeys: [ 'fontFamily' ], + hasSupport( name ) { + return hasBlockSupport( name, FONT_FAMILY_SUPPORT_KEY ); + }, +}; + /** * Resets the font family block support attribute. This can be used when * disabling the font family support controls for a block via a progressive @@ -122,9 +109,3 @@ addFilter( 'core/fontFamily/addSaveProps', addSaveProps ); - -addFilter( - 'blocks.registerBlockType', - 'core/fontFamily/addEditProps', - addEditProps -); diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js index a7ef79f0d4f2bf..b30fcc82d99463 100644 --- a/packages/block-editor/src/hooks/font-size.js +++ b/packages/block-editor/src/hooks/font-size.js @@ -58,19 +58,23 @@ function addAttributes( settings ) { /** * Override props assigned to save component to inject font size. * - * @param {Object} props Additional props applied to save element. - * @param {Object} blockType Block type. - * @param {Object} attributes Block attributes. + * @param {Object} props Additional props applied to save element. + * @param {Object} blockNameOrType Block type. + * @param {Object} attributes Block attributes. * * @return {Object} Filtered props applied to save element. */ -function addSaveProps( props, blockType, attributes ) { - if ( ! hasBlockSupport( blockType, FONT_SIZE_SUPPORT_KEY ) ) { +function addSaveProps( props, blockNameOrType, attributes ) { + if ( ! hasBlockSupport( blockNameOrType, FONT_SIZE_SUPPORT_KEY ) ) { return props; } if ( - shouldSkipSerialization( blockType, TYPOGRAPHY_SUPPORT_KEY, 'fontSize' ) + shouldSkipSerialization( + blockNameOrType, + TYPOGRAPHY_SUPPORT_KEY, + 'fontSize' + ) ) { return props; } @@ -84,31 +88,6 @@ function addSaveProps( props, blockType, attributes ) { return props; } -/** - * Filters registered block settings to expand the block edit wrapper - * by applying the desired styles and classnames. - * - * @param {Object} settings Original block settings. - * - * @return {Object} Filtered block settings. - */ -function addEditProps( settings ) { - if ( ! hasBlockSupport( settings, FONT_SIZE_SUPPORT_KEY ) ) { - return settings; - } - - const existingGetEditWrapperProps = settings.getEditWrapperProps; - settings.getEditWrapperProps = ( attributes ) => { - let props = {}; - if ( existingGetEditWrapperProps ) { - props = existingGetEditWrapperProps( attributes ); - } - return addSaveProps( props, settings, attributes ); - }; - - return settings; -} - /** * Inspector control panel containing the font size related configuration * @@ -184,19 +163,50 @@ function useBlockProps( { name, fontSize, style } ) { if ( ! hasBlockSupport( name, FONT_SIZE_SUPPORT_KEY ) || shouldSkipSerialization( name, TYPOGRAPHY_SUPPORT_KEY, 'fontSize' ) || - ! fontSize || - style?.typography?.fontSize + ! fontSize ) { return; } - const fontSizeValue = getFontSize( - fontSizes, - fontSize, - style?.typography?.fontSize - ).size; + let props = {}; + + if ( ! style?.typography?.fontSize ) { + props = { + style: { + fontSize: getFontSize( + fontSizes, + fontSize, + style?.typography?.fontSize + ).size, + }, + }; + } - return { style: { fontSize: fontSizeValue } }; + // TODO: This sucks! We should be using useSetting( 'typography.fluid' ) + // or even useSelect( blockEditorStore ). We can't do either here + // because getEditWrapperProps is a plain JavaScript function called by + // BlockListBlock and not a React component rendered within + // BlockListContext.Provider. If we set fontSize using editor. + // BlockListBlock instead of using getEditWrapperProps then the value is + // clobbered when the core/style/addEditProps filter runs. + + // TODO: We can do the thing above now. + const fluidTypographySettings = getFluidTypographyOptionsFromSettings( + select( blockEditorStore ).getSettings().__experimentalFeatures + ); + + if ( fontSize ) { + props = { + style: { + fontSize: getTypographyFontSizeValue( + { size: fontSize }, + fluidTypographySettings + ), + }, + }; + } + + return addSaveProps( props, name, { fontSize } ); } export default { @@ -229,70 +239,6 @@ function addTransforms( result, source, index, results ) { ); } -/** - * Allow custom font sizes to appear fluid when fluid typography is enabled at - * the theme level. - * - * Adds a custom getEditWrapperProps() callback to all block types that support - * font sizes. Then, if fluid typography is enabled, this callback will swap any - * custom font size in style.fontSize with a fluid font size (i.e. one that uses - * clamp()). - * - * It's important that this hook runs after 'core/style/addEditProps' sets - * style.fontSize as otherwise fontSize will be overwritten. - * - * @param {Object} blockType Block settings object. - */ -function addEditPropsForFluidCustomFontSizes( blockType ) { - if ( - ! hasBlockSupport( blockType, FONT_SIZE_SUPPORT_KEY ) || - shouldSkipSerialization( blockType, TYPOGRAPHY_SUPPORT_KEY, 'fontSize' ) - ) { - return blockType; - } - - const existingGetEditWrapperProps = blockType.getEditWrapperProps; - - blockType.getEditWrapperProps = ( attributes ) => { - const wrapperProps = existingGetEditWrapperProps - ? existingGetEditWrapperProps( attributes ) - : {}; - - const fontSize = wrapperProps?.style?.fontSize; - - // TODO: This sucks! We should be using useSetting( 'typography.fluid' ) - // or even useSelect( blockEditorStore ). We can't do either here - // because getEditWrapperProps is a plain JavaScript function called by - // BlockListBlock and not a React component rendered within - // BlockListContext.Provider. If we set fontSize using editor. - // BlockListBlock instead of using getEditWrapperProps then the value is - // clobbered when the core/style/addEditProps filter runs. - const fluidTypographySettings = getFluidTypographyOptionsFromSettings( - select( blockEditorStore ).getSettings().__experimentalFeatures - ); - const newFontSize = fontSize - ? getTypographyFontSizeValue( - { size: fontSize }, - fluidTypographySettings - ) - : null; - - if ( newFontSize === null ) { - return wrapperProps; - } - - return { - ...wrapperProps, - style: { - ...wrapperProps?.style, - fontSize: newFontSize, - }, - }; - }; - - return blockType; -} - addFilter( 'blocks.registerBlockType', 'core/font/addAttribute', @@ -305,19 +251,8 @@ addFilter( addSaveProps ); -addFilter( 'blocks.registerBlockType', 'core/font/addEditProps', addEditProps ); - addFilter( 'blocks.switchToBlockType.transformedBlock', 'core/font-size/addTransforms', addTransforms ); - -addFilter( - 'blocks.registerBlockType', - 'core/font-size/addEditPropsForFluidCustomFontSizes', - addEditPropsForFluidCustomFontSizes, - // Run after 'core/style/addEditProps' so that the style object has already - // been translated into inline CSS. - 11 -); diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 506f2a50a83a73..ec0dba5efb2b69 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -13,7 +13,7 @@ import style from './style'; import './settings'; import color from './color'; import duotone from './duotone'; -import './font-family'; +import fontFamily from './font-family'; import fontSize from './font-size'; import border from './border'; import position from './position'; @@ -41,8 +41,10 @@ createBlockEditFilter( ); createBlockListBlockFilter( [ align, + style, color, duotone, + fontFamily, fontSize, border, position, diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 935e8260fa89f6..b6098969bebb5e 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -269,20 +269,20 @@ export function omitStyle( style, paths, preserveReference = false ) { /** * Override props assigned to save component to inject the CSS variables definition. * - * @param {Object} props Additional props applied to save element. - * @param {Object} blockType Block type. - * @param {Object} attributes Block attributes. - * @param {?Record} skipPaths An object of keys and paths to skip serialization. + * @param {Object} props Additional props applied to save element. + * @param {Object|string} blockNameOrType Block type. + * @param {Object} attributes Block attributes. + * @param {?Record} skipPaths An object of keys and paths to skip serialization. * * @return {Object} Filtered props applied to save element. */ export function addSaveProps( props, - blockType, + blockNameOrType, attributes, skipPaths = skipSerializationPathsSave ) { - if ( ! hasStyleSupport( blockType ) ) { + if ( ! hasStyleSupport( blockNameOrType ) ) { return props; } @@ -290,7 +290,7 @@ export function addSaveProps( Object.entries( skipPaths ).forEach( ( [ indicator, path ] ) => { const skipSerialization = skipSerializationPathsSaveChecks[ indicator ] || - getBlockSupport( blockType, indicator ); + getBlockSupport( blockNameOrType, indicator ); if ( skipSerialization === true ) { style = omitStyle( style, path ); @@ -312,37 +312,6 @@ export function addSaveProps( return props; } -/** - * Filters registered block settings to extend the block edit wrapper - * to apply the desired styles and classnames properly. - * - * @param {Object} settings Original block settings. - * - * @return {Object}.Filtered block settings. - */ -export function addEditProps( settings ) { - if ( ! hasStyleSupport( settings ) ) { - return settings; - } - - const existingGetEditWrapperProps = settings.getEditWrapperProps; - settings.getEditWrapperProps = ( attributes ) => { - let props = {}; - if ( existingGetEditWrapperProps ) { - props = existingGetEditWrapperProps( attributes ); - } - - return addSaveProps( - props, - settings, - attributes, - skipSerializationPathsEdit - ); - }; - - return settings; -} - function BlockStyleControls( { clientId, name, @@ -472,7 +441,13 @@ function useBlockProps( { name, style } ) { }, [ baseElementSelector, blockElementStyles, name ] ); useStyleOverride( { css: styles } ); - return { className: blockElementsContainerIdentifier }; + + return addSaveProps( + { className: blockElementsContainerIdentifier }, + name, + { style }, + skipSerializationPathsEdit + ); } addFilter( @@ -486,9 +461,3 @@ addFilter( 'core/style/addSaveProps', addSaveProps ); - -addFilter( - 'blocks.registerBlockType', - 'core/style/addEditProps', - addEditProps -); diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index c6076b822545a9..49617013dc1153 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -112,14 +112,18 @@ export function transformStyles( * Check whether serialization of specific block support feature or set should * be skipped. * - * @param {string|Object} blockType Block name or block type object. - * @param {string} featureSet Name of block support feature set. - * @param {string} feature Name of the individual feature to check. + * @param {string|Object} blockNameOrType Block name or block type object. + * @param {string} featureSet Name of block support feature set. + * @param {string} feature Name of the individual feature to check. * * @return {boolean} Whether serialization should occur. */ -export function shouldSkipSerialization( blockType, featureSet, feature ) { - const support = getBlockSupport( blockType, featureSet ); +export function shouldSkipSerialization( + blockNameOrType, + featureSet, + feature +) { + const support = getBlockSupport( blockNameOrType, featureSet ); const skipSerialization = support?.__experimentalSkipSerialization; if ( Array.isArray( skipSerialization ) ) {