diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 60ef77d36242d1..af1b5428dcf09a 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -290,7 +290,7 @@ _Parameters_ _Returns_ -- `?string`: If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. Otherwise, an object with just the size value based on customFontSize is returned. +- `?Object`: If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. Otherwise, an object with just the size value based on customFontSize is returned. # **getFontSizeClass** @@ -304,6 +304,19 @@ _Returns_ - `string`: String with the class corresponding to the fontSize passed. The class is generated by appending 'has-' followed by fontSizeSlug in kebabCase and ending with '-font-size'. +# **getFontSizeObjectByValue** + +Returns the corresponding font size object for a given value. + +_Parameters_ + +- _fontSizes_ `Array`: Array of font size objects. +- _value_ `number`: Font size value. + +_Returns_ + +- `Object`: Font size object. + # **InnerBlocks** _Related_ diff --git a/packages/block-editor/src/components/font-sizes/index.js b/packages/block-editor/src/components/font-sizes/index.js index 931f9c2a89474d..55ef51a02aa4d5 100644 --- a/packages/block-editor/src/components/font-sizes/index.js +++ b/packages/block-editor/src/components/font-sizes/index.js @@ -1,3 +1,7 @@ -export { getFontSize, getFontSizeClass } from './utils'; +export { + getFontSize, + getFontSizeClass, + getFontSizeObjectByValue, +} from './utils'; export { default as FontSizePicker } from './font-size-picker'; export { default as withFontSizes } from './with-font-sizes'; diff --git a/packages/block-editor/src/components/font-sizes/utils.js b/packages/block-editor/src/components/font-sizes/utils.js index 17f3cfe680dc75..8604e9f287788a 100644 --- a/packages/block-editor/src/components/font-sizes/utils.js +++ b/packages/block-editor/src/components/font-sizes/utils.js @@ -11,7 +11,7 @@ import { find, kebabCase } from 'lodash'; * @param {?string} fontSizeAttribute Content of the font size attribute (slug). * @param {?number} customFontSizeAttribute Contents of the custom font size attribute (value). * - * @return {?string} If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. + * @return {?Object} If fontSizeAttribute is set and an equal slug is found in fontSizes it returns the font size object for that slug. * Otherwise, an object with just the size value based on customFontSize is returned. */ export const getFontSize = ( @@ -30,6 +30,25 @@ export const getFontSize = ( }; }; +/** + * Returns the corresponding font size object for a given value. + * + * @param {Array} fontSizes Array of font size objects. + * @param {number} value Font size value. + * + * @return {Object} Font size object. + */ +export function getFontSizeObjectByValue( fontSizes, value ) { + const fontSizeObject = find( fontSizes, { size: value } ); + if ( fontSizeObject ) { + return fontSizeObject; + } + + return { + size: value, + }; +} + /** * Returns a class based on fontSizeName. * diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index 05e5502a05972b..5e6cff33d41b14 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -8,7 +8,6 @@ import classnames from 'classnames'; */ import { addFilter } from '@wordpress/hooks'; import { hasBlockSupport } from '@wordpress/blocks'; -import { createHigherOrderComponent } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; @@ -115,75 +114,69 @@ export function addEditProps( settings ) { } /** - * Override the default edit UI to include new inspector controls for block - * color, if block defines support. + * Inspector control panel containing the color related configuration * - * @param {Function} BlockEdit Original component - * @return {Function} Wrapped component + * @param {Object} props + * + * @return {WPElement} Color edit element. */ -export const withBlockControls = createHigherOrderComponent( - ( BlockEdit ) => ( props ) => { - const { name: blockName } = props; - const colors = useSelect( ( select ) => { - return select( 'core/block-editor' ).getSettings().colors; - }, [] ); - - if ( ! hasBlockSupport( blockName, COLOR_SUPPORT_KEY ) ) { - return ; - } - const { style, textColor, backgroundColor } = props.attributes; - - const onChangeColor = ( name ) => ( value ) => { - const colorObject = getColorObjectByColorValue( colors, value ); - const attributeName = name + 'Color'; - const newStyle = { - ...style, - color: { - ...style?.color, - [ name ]: colorObject?.slug ? undefined : value, - }, - }; - const newNamedColor = colorObject?.slug - ? colorObject.slug - : undefined; - props.setAttributes( { - style: cleanEmptyObject( newStyle ), - [ attributeName ]: newNamedColor, - } ); +export function ColorEdit( props ) { + const { name: blockName } = props; + const colors = useSelect( ( select ) => { + return select( 'core/block-editor' ).getSettings().colors; + }, [] ); + + if ( ! hasBlockSupport( blockName, COLOR_SUPPORT_KEY ) ) { + return null; + } + const { style, textColor, backgroundColor } = props.attributes; + + const onChangeColor = ( name ) => ( value ) => { + const colorObject = getColorObjectByColorValue( colors, value ); + const attributeName = name + 'Color'; + const newStyle = { + ...style, + color: { + ...style?.color, + [ name ]: colorObject?.slug ? undefined : value, + }, }; + const newNamedColor = colorObject?.slug ? colorObject.slug : undefined; + props.setAttributes( { + style: cleanEmptyObject( newStyle ), + [ attributeName ]: newNamedColor, + } ); + }; - return [ - , - , - ]; - }, - 'withToolbarControls' -); + backgroundColor, + style?.color?.background + ).color, + }, + ] } + /> + ); +} addFilter( 'blocks.registerBlockType', @@ -202,9 +195,3 @@ addFilter( 'core/color/addEditProps', addEditProps ); - -addFilter( - 'editor.BlockEdit', - 'core/color/with-block-controls', - withBlockControls -); diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js new file mode 100644 index 00000000000000..5f13821ad75149 --- /dev/null +++ b/packages/block-editor/src/hooks/font-size.js @@ -0,0 +1,151 @@ +/** + * WordPress dependencies + */ +import { addFilter } from '@wordpress/hooks'; +import { hasBlockSupport } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; +import TokenList from '@wordpress/token-list'; + +/** + * Internal dependencies + */ +import { + getFontSize, + getFontSizeClass, + getFontSizeObjectByValue, + FontSizePicker, +} from '../components/font-sizes'; +import { cleanEmptyObject } from './utils'; + +export const FONT_SIZE_SUPPORT_KEY = '__experimentalFontSize'; + +/** + * Filters registered block settings, extending attributes to include + * `fontSize` and `fontWeight` attributes. + * + * @param {Object} settings Original block settings + * @return {Object} Filtered block settings + */ +function addAttributes( settings ) { + if ( ! hasBlockSupport( settings, FONT_SIZE_SUPPORT_KEY ) ) { + return settings; + } + + // Allow blocks to specify a default value if needed. + if ( ! settings.attributes.fontSize ) { + Object.assign( settings.attributes, { + fontSize: { + type: 'string', + }, + } ); + } + + return 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 + * @return {Object} Filtered props applied to save element + */ +function addSaveProps( props, blockType, attributes ) { + if ( ! hasBlockSupport( blockType, FONT_SIZE_SUPPORT_KEY ) ) { + return props; + } + + // Use TokenList to dedupe classes. + const classes = new TokenList( props.className ); + classes.add( getFontSizeClass( attributes.fontSize ) ); + const newClassName = classes.value; + props.className = newClassName ? newClassName : undefined; + + 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 + * + * @param {Object} props + * + * @return {WPElement} Font size edit element. + */ +export function FontSizeEdit( props ) { + const { + name: blockName, + attributes: { fontSize, style }, + setAttributes, + } = props; + + const { fontSizes } = useSelect( ( select ) => + select( 'core/block-editor' ).getSettings() + ); + + if ( ! hasBlockSupport( blockName, FONT_SIZE_SUPPORT_KEY ) ) { + return null; + } + + const fontSizeObject = getFontSize( + fontSizes, + fontSize, + style?.typography?.fontSize + ); + const onChange = ( value ) => { + const fontSizeSlug = getFontSizeObjectByValue( fontSizes, value ).slug; + + setAttributes( { + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + fontSize: fontSizeSlug ? undefined : value, + }, + } ), + fontSize: fontSizeSlug, + } ); + }; + + return ( + + ); +} + +addFilter( + 'blocks.registerBlockType', + 'core/font/addAttribute', + addAttributes +); + +addFilter( + 'blocks.getSaveContent.extraProps', + 'core/font/addSaveProps', + addSaveProps +); + +addFilter( 'blocks.registerBlockType', 'core/font/addEditProps', addEditProps ); diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 76897c09669214..5d9b2f5393a8dd 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -7,5 +7,6 @@ import './custom-class-name'; import './generated-class-name'; import './style'; import './color'; +import './font-size'; export { AlignmentHookSettingsProvider }; diff --git a/packages/block-editor/src/hooks/line-height.js b/packages/block-editor/src/hooks/line-height.js index f1e1220b6100ad..37734002571926 100644 --- a/packages/block-editor/src/hooks/line-height.js +++ b/packages/block-editor/src/hooks/line-height.js @@ -1,67 +1,53 @@ /** * WordPress dependencies */ -import { addFilter } from '@wordpress/hooks'; -import { hasBlockSupport } from '@wordpress/blocks'; -import { createHigherOrderComponent } from '@wordpress/compose'; -import { PanelBody } from '@wordpress/components'; import { Platform } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; +import { hasBlockSupport } from '@wordpress/blocks'; /** * Internal dependencies */ import LineHeightControl from '../components/line-height-control'; -import InspectorControls from '../components/inspector-controls'; import { cleanEmptyObject } from './utils'; -export const LINE_HEIGHT_SUPPRT_KEY = '__experimentalLineHeight'; +export const LINE_HEIGHT_SUPPORT_KEY = '__experimentalLineHeight'; /** - * Override the default edit UI to include new inspector controls for block - * color, if block defines support. + * Inspector control panel containing the line height related configuration + * + * @param {Object} props * - * @param {Function} BlockEdit Original component - * @return {Function} Wrapped component + * @return {WPElement} Line height edit element. */ -export const withBlockControls = createHigherOrderComponent( - ( BlockEdit ) => ( props ) => { - const { name: blockName } = props; - if ( ! hasBlockSupport( blockName, LINE_HEIGHT_SUPPRT_KEY ) ) { - return ; - } - const { style } = props.attributes; - const onChange = ( newLineHeightValue ) => { - const newStyle = { - ...style, - typography: { - lineHeight: newLineHeightValue, - }, - }; - props.setAttributes( { - style: cleanEmptyObject( newStyle ), - } ); +export function LineHeightEdit( props ) { + const { + name: blockName, + attributes: { style }, + } = props; + + if ( ! hasBlockSupport( blockName, LINE_HEIGHT_SUPPORT_KEY ) ) { + return null; + } + + const onChange = ( newLineHeightValue ) => { + const newStyle = { + ...style, + typography: { + ...style?.typography, + lineHeight: newLineHeightValue, + }, }; - const controls = Platform.select( { - web: ( - - - - - - ), - native: null, + props.setAttributes( { + style: cleanEmptyObject( newStyle ), } ); - return [ , controls ]; - }, - 'withToolbarControls' -); - -addFilter( - 'editor.BlockEdit', - 'core/color/with-block-controls', - withBlockControls -); + }; + return Platform.select( { + web: ( + + ), + native: null, + } ); +} diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index 9ffd3fd34d0ca7..156104d3022e43 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -1,21 +1,35 @@ /** * External dependencies */ -import { mapKeys, kebabCase, isObject, entries } from 'lodash'; +import { mapKeys, kebabCase, isObject, entries, identity } from 'lodash'; /** * WordPress dependencies */ import { addFilter } from '@wordpress/hooks'; import { hasBlockSupport } from '@wordpress/blocks'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { PanelBody } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { COLOR_SUPPORT_KEY } from './color'; -import { LINE_HEIGHT_SUPPRT_KEY } from './line-height'; - -const styleSupportKeys = [ COLOR_SUPPORT_KEY, LINE_HEIGHT_SUPPRT_KEY ]; +import InspectorControls from '../components/inspector-controls'; +import { COLOR_SUPPORT_KEY, ColorEdit } from './color'; +import { LINE_HEIGHT_SUPPORT_KEY, LineHeightEdit } from './line-height'; +import { FONT_SIZE_SUPPORT_KEY, FontSizeEdit } from './font-size'; + +const styleSupportKeys = [ + COLOR_SUPPORT_KEY, + LINE_HEIGHT_SUPPORT_KEY, + FONT_SIZE_SUPPORT_KEY, +]; + +const typographySupportKeys = [ + LINE_HEIGHT_SUPPORT_KEY, + FONT_SIZE_SUPPORT_KEY, +]; const hasStyleSupport = ( blockType ) => styleSupportKeys.some( ( key ) => hasBlockSupport( blockType, key ) ); @@ -30,11 +44,15 @@ const hasStyleSupport = ( blockType ) => export function getCSSVariables( styles = {} ) { const prefix = '--wp'; const token = '--'; + const valueFormatters = { + fontSize: ( value ) => ( value ? value + 'px' : value ), + }; const getNestedCSSVariables = ( config ) => { let result = {}; entries( config ).forEach( ( [ key, value ] ) => { if ( ! isObject( value ) ) { - result[ kebabCase( key ) ] = value; + const formatter = valueFormatters[ key ] || identity; + result[ kebabCase( key ) ] = formatter( value ); return; } @@ -127,6 +145,36 @@ export function addEditProps( settings ) { return settings; } +/** + * Override the default edit UI to include new inspector controls for + * all the custom styles configs. + * + * @param {Function} BlockEdit Original component + * @return {Function} Wrapped component + */ +export const withBlockControls = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const { name: blockName } = props; + const hasTypographySupport = typographySupportKeys.some( ( key ) => + hasBlockSupport( blockName, key ) + ); + + return [ + hasTypographySupport && ( + + + + + + + ), + , + , + ]; + }, + 'withToolbarControls' +); + addFilter( 'blocks.registerBlockType', 'core/style/addAttribute', @@ -144,3 +192,9 @@ addFilter( 'core/style/addEditProps', addEditProps ); + +addFilter( + 'editor.BlockEdit', + 'core/style/with-block-controls', + withBlockControls +); diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index dc3d4ef895c8e7..acd5e48f0f63e0 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -18,12 +18,6 @@ "placeholder": { "type": "string" }, - "fontSize": { - "type": "string" - }, - "customFontSize": { - "type": "number" - }, "direction": { "type": "string", "enum": [ diff --git a/packages/block-library/src/paragraph/deprecated.js b/packages/block-library/src/paragraph/deprecated.js index 923b2ed70a08c8..24896a034207d0 100644 --- a/packages/block-library/src/paragraph/deprecated.js +++ b/packages/block-library/src/paragraph/deprecated.js @@ -44,9 +44,6 @@ const blockAttributes = { fontSize: { type: 'string', }, - customFontSize: { - type: 'number', - }, direction: { type: 'string', enum: [ 'ltr', 'rtl' ], @@ -56,19 +53,33 @@ const blockAttributes = { }, }; -const migrateCustomColors = ( attributes ) => { - if ( ! attributes.customTextColor && ! attributes.customBackgroundColor ) { +const migrateCustomColorsAndFontSizes = ( attributes ) => { + if ( + ! attributes.customTextColor && + ! attributes.customBackgroundColor && + ! attributes.customFontSize + ) { return attributes; } - const style = { color: {} }; + const style = {}; + if ( attributes.customTextColor || attributes.customBackgroundColor ) { + style.color = {}; + } if ( attributes.customTextColor ) { style.color.text = attributes.customTextColor; } if ( attributes.customBackgroundColor ) { style.color.background = attributes.customBackgroundColor; } + if ( attributes.customFontSize ) { + style.typography = { fontSize: attributes.customFontSize }; + } return { - ...omit( attributes, [ 'customTextColor', 'customBackgroundColor' ] ), + ...omit( attributes, [ + 'customTextColor', + 'customBackgroundColor', + 'customFontSize', + ] ), style, }; }; @@ -84,8 +95,11 @@ const deprecated = [ customBackgroundColor: { type: 'string', }, + customFontSize: { + type: 'number', + }, }, - migrate: migrateCustomColors, + migrate: migrateCustomColorsAndFontSizes, save( { attributes } ) { const { align, @@ -146,8 +160,11 @@ const deprecated = [ customBackgroundColor: { type: 'string', }, + customFontSize: { + type: 'number', + }, }, - migrate: migrateCustomColors, + migrate: migrateCustomColorsAndFontSizes, save( { attributes } ) { const { align, @@ -208,11 +225,14 @@ const deprecated = [ customBackgroundColor: { type: 'string', }, + customFontSize: { + type: 'number', + }, width: { type: 'string', }, }, - migrate: migrateCustomColors, + migrate: migrateCustomColorsAndFontSizes, save( { attributes } ) { const { width, @@ -271,7 +291,7 @@ const deprecated = [ type: 'number', }, }, - [ 'customFontSize', 'style' ] + [ 'style' ] ), save( { attributes } ) { const { @@ -305,7 +325,7 @@ const deprecated = [ ); }, migrate( attributes ) { - return migrateCustomColors( + return migrateCustomColorsAndFontSizes( omit( { ...attributes, customFontSize: isFinite( attributes.fontSize ) diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index e09aecea77c810..bcae630f0e5ac9 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -11,14 +11,12 @@ import { PanelBody, ToggleControl, ToolbarGroup } from '@wordpress/components'; import { AlignmentToolbar, BlockControls, - FontSizePicker, InspectorControls, RichText, - withFontSizes, __experimentalBlock as Block, + getFontSize, } from '@wordpress/block-editor'; import { createBlock } from '@wordpress/blocks'; -import { compose } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; import { useEffect, useState, useRef } from '@wordpress/element'; import { formatLtr } from '@wordpress/icons'; @@ -74,21 +72,29 @@ function useDropCapMinimumHeight( isDropCap, deps ) { function ParagraphBlock( { attributes, - fontSize, mergeBlocks, onReplace, setAttributes, - setFontSize, } ) { - const { align, content, direction, dropCap, placeholder } = attributes; - + const { + align, + content, + direction, + dropCap, + placeholder, + fontSize, + style, + } = attributes; + const { fontSizes } = useSelect( ( select ) => + select( 'core/block-editor' ).getSettings() + ); const ref = useRef(); + const fontSizeObject = getFontSize( fontSizes, fontSize, style?.fontSize ); const dropCapMinimumHeight = useDropCapMinimumHeight( dropCap, [ - fontSize.size, + fontSizeObject.size, ] ); const styles = { - fontSize: fontSize.size ? `${ fontSize.size }px` : undefined, direction, minHeight: dropCapMinimumHeight, }; @@ -111,10 +117,6 @@ function ParagraphBlock( { - -

Paragraph to be made \\"small\\"

+" +

Paragraph to be made \\"small\\"

" `; diff --git a/packages/editor/src/editor-styles.scss b/packages/editor/src/editor-styles.scss index a7608813a5fcc2..8ecb29426d3c75 100644 --- a/packages/editor/src/editor-styles.scss +++ b/packages/editor/src/editor-styles.scss @@ -94,7 +94,6 @@ h6 { } p { - font-size: inherit; margin-top: $default-block-margin; margin-bottom: $default-block-margin; } diff --git a/storybook/stories/playground/editor-styles.scss b/storybook/stories/playground/editor-styles.scss index d920ea8de5ba04..9d94b0d1b5cae0 100644 --- a/storybook/stories/playground/editor-styles.scss +++ b/storybook/stories/playground/editor-styles.scss @@ -4,11 +4,6 @@ line-height: $editor-line-height; color: $dark-gray-900; - p { - font-size: inherit; - line-height: inherit; - } - ul, ol { margin: 0;