Skip to content

Commit

Permalink
Spacer: add custom units for height and width (#36186)
Browse files Browse the repository at this point in the history
* Add width and height units and use the custom UnitControl

* Refactor out the ResizableSpacer and fix resizing in the canvas

* Correctly initialize width and height for horizontal spacer

* Handle min and max values for px

* Apply unit to the dimensions on the frontend

* Refactor out the controls

* Disable percentage units for Spacer

* Only output width or height styles as needed for orientation

* Correctly generate styles when width or height is set to 0

* Remove unnecessary parsing, interpolation

* Remove separate unit attributes and update type of height and width attrs

* Add block deprecation

* Update and add fixtures for deprecation

* Update snapshots

* Ensure that the unit is updated to px when resizing by dragging the handle

* Add mobile support for custom units
  • Loading branch information
stacimc committed Dec 23, 2021
1 parent 24bc4d7 commit c8f6ac3
Show file tree
Hide file tree
Showing 26 changed files with 526 additions and 131 deletions.
6 changes: 3 additions & 3 deletions packages/block-library/src/spacer/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
"textdomain": "default",
"attributes": {
"height": {
"type": "number",
"default": 100
"type": "string",
"default": "100px"
},
"width": {
"type": "number"
"type": "string"
}
},
"usesContext": [ "orientation" ],
Expand Down
108 changes: 108 additions & 0 deletions packages/block-library/src/spacer/controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { InspectorControls, useSetting } from '@wordpress/block-editor';
import {
BaseControl,
PanelBody,
__experimentalUseCustomUnits as useCustomUnits,
__experimentalUnitControl as UnitControl,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import { MAX_SPACER_SIZE } from './edit';

function DimensionInput( { label, onChange, isResizing, value = '' } ) {
const [ temporaryInput, setTemporaryInput ] = useState( null );

const inputId = useInstanceId( UnitControl, 'block-spacer-height-input' );

// In most contexts the spacer size cannot meaningfully be set to a
// percentage, since this is relative to the parent container. This
// unit is disabled from the UI.
const availableUnitSettings = useSetting( 'spacing.units' ).filter(
( availableUnit ) => availableUnit !== '%'
);

const units = useCustomUnits( {
availableUnits: availableUnitSettings || [
'px',
'em',
'rem',
'vw',
'vh',
],
defaultValues: { px: '100', em: '10', rem: '10', vw: '10', vh: '25' },
} );

const handleOnChange = ( unprocessedValue ) => {
setTemporaryInput( null );
onChange( unprocessedValue );
};

const handleOnBlur = () => {
if ( temporaryInput !== null ) {
setTemporaryInput( null );
}
};

const inputValue = temporaryInput !== null ? temporaryInput : value;

return (
<BaseControl label={ label } id={ inputId }>
<UnitControl
id={ inputId }
isResetValueOnUnitChange
min={ 0 }
max={ MAX_SPACER_SIZE }
onBlur={ handleOnBlur }
onChange={ handleOnChange }
style={ { maxWidth: 80 } }
value={ inputValue }
units={ units }
// Force the unit to update to `px` when the Spacer is being resized.
unit={ isResizing ? 'px' : undefined }
/>
</BaseControl>
);
}

export default function SpacerControls( {
setAttributes,
orientation,
height,
width,
isResizing,
} ) {
return (
<InspectorControls>
<PanelBody title={ __( 'Spacer settings' ) }>
{ orientation === 'horizontal' && (
<DimensionInput
label={ __( 'Width' ) }
value={ width }
onChange={ ( nextWidth ) =>
setAttributes( { width: nextWidth } )
}
isResizing={ isResizing }
/>
) }
{ orientation !== 'horizontal' && (
<DimensionInput
label={ __( 'Height' ) }
value={ height }
onChange={ ( nextHeight ) =>
setAttributes( { height: nextHeight } )
}
isResizing={ isResizing }
/>
) }
</PanelBody>
</InspectorControls>
);
}
82 changes: 82 additions & 0 deletions packages/block-library/src/spacer/controls.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* WordPress dependencies
*/
import {
PanelBody,
UnitControl,
getValueAndUnit,
__experimentalUseCustomUnits as useCustomUnits,
} from '@wordpress/components';
import { useCallback } from '@wordpress/element';
import { useSetting } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import styles from './style.scss';

const DEFAULT_VALUES = { px: '100', em: '10', rem: '10', vw: '10', vh: '25' };

function Controls( { attributes, context, setAttributes } ) {
const { orientation } = context;
const label = orientation !== 'horizontal' ? __( 'Height' ) : __( 'Width' );

const { height, width } = attributes;
const { valueToConvert, valueUnit: unit } =
getValueAndUnit( orientation !== 'horizontal' ? height : width ) || {};
const value = Number( valueToConvert );

const setNewDimensions = ( nextValue, nextUnit ) => {
const valueWithUnit = `${ nextValue }${ nextUnit }`;
if ( orientation === 'horizontal' ) {
setAttributes( { width: valueWithUnit } );
} else {
setAttributes( { height: valueWithUnit } );
}
};

const handleChange = useCallback(
( nextValue ) => {
setNewDimensions( nextValue, unit );
},
[ height, width ]
);

const handleUnitChange = useCallback(
( nextUnit ) => {
setNewDimensions( value, nextUnit );
},
[ height, width ]
);

const units = useCustomUnits( {
availableUnits: useSetting( 'spacing.units' ) || [
'px',
'em',
'rem',
'vw',
'vh',
],
defaultValues: DEFAULT_VALUES,
} );

return (
<>
<PanelBody title={ __( 'Dimensions' ) }>
<UnitControl
label={ label }
min={ 1 }
value={ value }
onChange={ handleChange }
onUnitChange={ handleUnitChange }
units={ units }
unit={ unit }
style={ styles.rangeCellContainer }
/>
</PanelBody>
</>
);
}

export default Controls;
41 changes: 41 additions & 0 deletions packages/block-library/src/spacer/deprecated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* WordPress dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';

const deprecated = [
{
attributes: {
height: {
type: 'number',
default: 100,
},
width: {
type: 'number',
},
},
migrate( attributes ) {
const { height, width } = attributes;
return {
...attributes,
width: width !== undefined ? `${ width }px` : undefined,
height: height !== undefined ? `${ height }px` : undefined,
};
},
save( { attributes } ) {
return (
<div
{ ...useBlockProps.save( {
style: {
height: attributes.height,
width: attributes.width,
},
'aria-hidden': true,
} ) }
/>
);
},
},
];

export default deprecated;
Loading

0 comments on commit c8f6ac3

Please sign in to comment.