diff --git a/packages/block-library/src/cover/block.json b/packages/block-library/src/cover/block.json index 29f1b17d7bb23..e2e544a2e49af 100644 --- a/packages/block-library/src/cover/block.json +++ b/packages/block-library/src/cover/block.json @@ -17,6 +17,10 @@ "type": "boolean", "default": false }, + "backgroundSize": { + "type": "string", + "default": "cover" + }, "dimRatio": { "type": "number", "default": 50 diff --git a/packages/block-library/src/cover/edit.js b/packages/block-library/src/cover/edit.js index ff9d9f8cd6eb4..27d5a9c495e9e 100644 --- a/packages/block-library/src/cover/edit.js +++ b/packages/block-library/src/cover/edit.js @@ -20,6 +20,9 @@ import { Spinner, ToggleControl, withNotices, + ButtonGroup, + SelectControl, + __experimentalUnitControl as BaseUnitControl, __experimentalBoxControl as BoxControl, } from '@wordpress/components'; import { compose, withInstanceId, useInstanceId } from '@wordpress/compose'; @@ -52,6 +55,7 @@ import { VIDEO_BACKGROUND_TYPE, COVER_MIN_HEIGHT, CSS_UNITS, + SIZE_OPTIONS, backgroundImageStyles, dimRatioToClass, isContentPositionCenter, @@ -82,11 +86,172 @@ function retrieveFastAverageColor() { return retrieveFastAverageColor.fastAverageColor; } -function CoverHeightInput( { +function CustomSizeControl( { value, onSelect } ) { + let initMode = value.search( /auto/ ); + if ( initMode < 1 ) { + initMode = 'both'; + } else if ( initMode === 0 ) { + initMode = 'width'; + } else { + initMode = 'height'; + } + + const [ currentMode, setMode ] = useState( initMode ); + + const customUnits = [ + { value: 'px', label: 'px', default: 0 }, + { value: '%', label: '%', default: 10 }, + ]; + + // Split and pick up values + units from the CSS inline. + let wh = + value && + value + .replace( /auto/, '50%' ) + .split( /(\d+|%|px|auto)/ ) + .filter( ( v ) => !! v && v !== ' ' ); + + // default values. + if ( wh.length < 2 ) { + wh = [ '50', '%', '50', '%' ]; + } + + function customSizeHandler( data ) { + const { mode, w, wu, h, hu } = data; + + if ( mode ) { + setMode( mode ); + } + + let inlineStyle = ''; + switch ( mode || currentMode ) { + case 'width': + inlineStyle = `${ w || wh[ 0 ] }${ wu || wh[ 1 ] } auto`; + break; + + case 'height': + inlineStyle = `auto ${ h || wh[ 2 ] }${ hu || wh[ 3 ] }`; + break; + + case 'both': + inlineStyle = + `${ w || wh[ 0 ] }${ wu || wh[ 1 ] } ` + + `${ h || wh[ 2 ] }${ hu || wh[ 3 ] }`; + break; + } + + onSelect( inlineStyle ); + } + + return ( + + + customSizeHandler( { mode: newMode } ) + } + labelPosition="top" + /> + +
+ { ( currentMode === 'width' || currentMode === 'both' ) && ( + customSizeHandler( { w } ) } + onUnitChange={ ( wu ) => customSizeHandler( { wu } ) } + customUnits={ false } + /> + ) } + + { ( currentMode === 'height' || currentMode === 'both' ) && ( + customSizeHandler( { h } ) } + onUnitChange={ ( hu ) => customSizeHandler( { hu } ) } + customUnits={ false } + /> + ) } +
+
+ ); +} + +/** + * Helper function to fetect if the given size is custom or not. + * + * @param {string} size - Background size + * @return {boolean} True if size is custom. Otherwise, False. + */ +export function isCustomSize( size ) { + return ( + SIZE_OPTIONS.map( ( opt ) => opt.slug ).indexOf( size ) < 0 || + size === 'custom' + ); +} + +function BackgroundSizeControl( { size = 'cover', onSelect } ) { + return ( + + + + { SIZE_OPTIONS.map( ( { slug, label, icon: sizeIcon } ) => ( +