diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js index 89491da44edce3..12d9412181d705 100644 --- a/packages/block-editor/src/hooks/font-size.js +++ b/packages/block-editor/src/hooks/font-size.js @@ -4,7 +4,6 @@ import { addFilter } from '@wordpress/hooks'; import { hasBlockSupport } from '@wordpress/blocks'; import TokenList from '@wordpress/token-list'; -import { select } from '@wordpress/data'; /** * Internal dependencies @@ -22,7 +21,6 @@ import { shouldSkipSerialization, } from './utils'; import { useSettings } from '../components/use-settings'; -import { store as blockEditorStore } from '../store'; import { getTypographyFontSizeValue, getFluidTypographyOptionsFromSettings, @@ -154,58 +152,61 @@ export function useIsFontSizeDisabled( { name: blockName } = {} ) { } function useBlockProps( { name, fontSize, style } ) { - const [ fontSizes ] = useSettings( 'typography.fontSizes' ); + const [ fontSizes, fluidTypographySettings, layoutSettings ] = useSettings( + 'typography.fontSizes', + 'typography.fluid', + 'layout' + ); - // Only add inline styles if the block supports font sizes, - // doesn't skip serialization of font sizes, - // doesn't already have an inline font size, - // and does have a class to extract the font size from. + /* + * Only add inline styles if the block supports font sizes, + * doesn't skip serialization of font sizes, + * and has either a custom font size or a preset font size. + */ if ( ! hasBlockSupport( name, FONT_SIZE_SUPPORT_KEY ) || shouldSkipSerialization( name, TYPOGRAPHY_SUPPORT_KEY, 'fontSize' ) || - ! fontSize + ( ! fontSize && ! style?.typography?.fontSize ) ) { return; } - let props = {}; + let props; + + if ( style?.typography?.fontSize ) { + const fluidSettings = getFluidTypographyOptionsFromSettings( { + typography: { + fluid: fluidTypographySettings, + }, + layout: layoutSettings, + } ); - if ( ! style?.typography?.fontSize ) { props = { style: { - fontSize: getFontSize( - fontSizes, - fontSize, - style?.typography?.fontSize - ).size, + fontSize: getTypographyFontSizeValue( + { size: style.typography.fontSize }, + fluidSettings + ), }, }; } - // 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 - ), + fontSize: getFontSize( + fontSizes, + fontSize, + style?.typography?.fontSize + ).size, }, }; } + if ( ! props ) { + return; + } + return addSaveProps( props, name, { fontSize } ); } diff --git a/packages/block-editor/src/hooks/test/font-size.js b/packages/block-editor/src/hooks/test/font-size.js new file mode 100644 index 00000000000000..11cd024bf8a285 --- /dev/null +++ b/packages/block-editor/src/hooks/test/font-size.js @@ -0,0 +1,164 @@ +/** + * External dependencies + */ +import { renderHook } from '@testing-library/react'; + +/** + * WordPress dependencies + */ +import { addFilter, removeFilter } from '@wordpress/hooks'; +import { + getBlockTypes, + registerBlockType, + unregisterBlockType, +} from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import _fontSize from '../font-size'; + +const noop = () => {}; + +function addUseSettingFilter( callback ) { + addFilter( + 'blockEditor.useSetting.before', + 'test/useSetting.before', + callback + ); +} + +describe( 'useBlockProps', () => { + const blockSettings = { + save: () => noop, + category: 'text', + title: 'font size title', + name: 'test/font-size', + supports: { + typography: { + fontSize: true, + }, + }, + }; + + afterEach( () => { + getBlockTypes().forEach( ( block ) => { + unregisterBlockType( block.name ); + } ); + removeFilter( + 'blockEditor.useSetting.before', + 'test/useSetting.before' + ); + } ); + + it( 'should return preset classname', () => { + registerBlockType( blockSettings.name, blockSettings ); + addUseSettingFilter( ( result, path ) => { + if ( 'typography.fontSizes' === path ) { + return [ + { + name: 'A larger font', + size: '32px', + slug: 'larger', + }, + ]; + } + + if ( 'typography.fluid' === path ) { + return false; + } + + if ( 'layout' === path ) { + return {}; + } + + return result; + } ); + + const { result } = renderHook( () => + _fontSize.useBlockProps( { + name: blockSettings.name, + fontSize: 'larger', + } ) + ); + const { style, className } = result.current; + expect( className ).toBe( 'has-larger-font-size' ); + expect( style.fontSize ).toBe( '32px' ); + + removeFilter( + 'blockEditor.useSetting.before', + 'test/useSetting.before' + ); + } ); + + it( 'should return custom font size', () => { + registerBlockType( blockSettings.name, blockSettings ); + addUseSettingFilter( ( result, path ) => { + if ( 'typography.fontSizes' === path ) { + return []; + } + + if ( 'typography.fluid' === path ) { + return false; + } + + if ( 'layout' === path ) { + return {}; + } + + return result; + } ); + + const { result } = renderHook( () => + _fontSize.useBlockProps( { + name: blockSettings.name, + style: { + typography: { + fontSize: '28px', + }, + }, + } ) + ); + const { style } = result.current; + expect( style.fontSize ).toBe( '28px' ); + + removeFilter( + 'blockEditor.useSetting.before', + 'test/useSetting.before' + ); + } ); + + it( 'should convert custom font sizes to fluid', () => { + registerBlockType( blockSettings.name, blockSettings ); + addUseSettingFilter( ( result, path ) => { + if ( 'typography.fontSizes' === path ) { + return []; + } + + if ( 'typography.fluid' === path ) { + return true; + } + + if ( 'layout' === path ) { + return {}; + } + + return result; + } ); + + const { result } = renderHook( () => + _fontSize.useBlockProps( { + name: blockSettings.name, + style: { + typography: { + fontSize: '28px', + }, + }, + } ) + ); + const { style } = result.current; + expect( style.fontSize ).toBe( + 'clamp(17.905px, 1.119rem + ((1vw - 3.2px) * 0.789), 28px)' + ); + } ); +} );