Skip to content

Commit

Permalink
Add height dimensions block support
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Aug 15, 2021
1 parent 462ba4f commit 433ce14
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 19 deletions.
18 changes: 14 additions & 4 deletions lib/block-supports/dimensions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ function gutenberg_register_dimensions_support( $block_type ) {
}

$has_dimensions_support = gutenberg_block_has_support( $block_type, array( '__experimentalDimensions' ), false );
// Future block supports such as height & width will be added here.

if ( $has_dimensions_support ) {
$block_type->attributes['style'] = array(
Expand All @@ -44,14 +43,24 @@ function gutenberg_register_dimensions_support( $block_type ) {
*
* @return array Block dimensions CSS classes and inline styles.
*/
function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) {
if ( gutenberg_skip_dimensions_serialization( $block_type ) ) {
return array();
}

$styles = array();

// Height support to be added in near future.
// Height.
$has_height_support = gutenberg_block_has_support( $block_type, array( '__experimentalDimensions', 'height' ), false );

if ( $has_height_support ) {
$height_value = _wp_array_get( $block_attributes, array( 'style', 'dimensions', 'height' ), null );

if ( null !== $height_value ) {
$styles[] = sprintf( 'height: %s;', $height_value );
}
}

// Width support to be added in near future.

return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
Expand All @@ -63,10 +72,11 @@ function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) {
*
* @param WP_Block_type $block_type Block type.
*
* @return boolean Whether to serialize spacing support styles & classes.
* @return boolean Whether to serialize dimensions support styles & classes.
*/
function gutenberg_skip_dimensions_serialization( $block_type ) {
$dimensions_support = _wp_array_get( $block_type->supports, array( '__experimentalDimensions' ), false );

return is_array( $dimensions_support ) &&
array_key_exists( '__experimentalSkipSerialization', $dimensions_support ) &&
$dimensions_support['__experimentalSkipSerialization'];
Expand Down
7 changes: 7 additions & 0 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class WP_Theme_JSON_Gutenberg {
'gradient' => null,
'text' => null,
),
'dimensions' => array(
'height' => null,
),
'spacing' => array(
'margin' => null,
'padding' => null,
Expand Down Expand Up @@ -93,6 +96,9 @@ class WP_Theme_JSON_Gutenberg {
'palette' => null,
),
'custom' => null,
'dimensions' => array(
'customHeight' => null,
),
'layout' => array(
'contentSize' => null,
'wideSize' => null,
Expand Down Expand Up @@ -221,6 +227,7 @@ class WP_Theme_JSON_Gutenberg {
'font-size' => array( 'typography', 'fontSize' ),
'font-style' => array( 'typography', 'fontStyle' ),
'font-weight' => array( 'typography', 'fontWeight' ),
'height' => array( 'dimensions', 'height' ),
'letter-spacing' => array( 'typography', 'letterSpacing' ),
'line-height' => array( 'typography', 'lineHeight' ),
'margin' => array( 'spacing', 'margin' ),
Expand Down
3 changes: 3 additions & 0 deletions lib/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@
}
]
},
"dimensions": {
"customHeight": false
},
"spacing": {
"customMargin": false,
"customPadding": false,
Expand Down
44 changes: 38 additions & 6 deletions packages/block-editor/src/hooks/dimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ import { getBlockSupport } from '@wordpress/blocks';
* Internal dependencies
*/
import InspectorControls from '../components/inspector-controls';
import {
HeightEdit,
hasHeightSupport,
hasHeightValue,
resetHeight,
useIsHeightDisabled,
} from './height';
import {
MarginEdit,
hasMarginSupport,
Expand All @@ -29,6 +36,7 @@ import {
} from './padding';
import { cleanEmptyObject } from './utils';

export const DIMENSIONS_SUPPORT_KEY = '__experimentalDimensions';
export const SPACING_SUPPORT_KEY = 'spacing';
export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ];
export const AXIAL_SIDES = [ 'vertical', 'horizontal' ];
Expand All @@ -37,19 +45,24 @@ export const AXIAL_SIDES = [ 'vertical', 'horizontal' ];
* Inspector controls for dimensions support.
*
* @param {Object} props Block props.
*
* @return {WPElement} Inspector controls for spacing support features.
* @return {WPElement} Inspector controls for dimensions support features.
*/
export function DimensionsPanel( props ) {
const isPaddingDisabled = useIsPaddingDisabled( props );
const isMarginDisabled = useIsMarginDisabled( props );
const isHeightDisabled = useIsHeightDisabled( props );
const isDisabled = useIsDimensionsDisabled( props );
const isSupported = hasDimensionsSupport( props.name );

if ( isDisabled || ! isSupported ) {
return null;
}

const defaultDimensionsControls = getBlockSupport( props.name, [
DIMENSIONS_SUPPORT_KEY,
'__experimentalDefaultControls',
] );

const defaultSpacingControls = getBlockSupport( props.name, [
SPACING_SUPPORT_KEY,
'__experimentalDefaultControls',
Expand All @@ -62,6 +75,10 @@ export function DimensionsPanel( props ) {
props.setAttributes( {
style: cleanEmptyObject( {
...style,
dimensions: {
...style?.dimensions,
height: undefined,
},
spacing: {
...style?.spacing,
margin: undefined,
Expand All @@ -78,6 +95,17 @@ export function DimensionsPanel( props ) {
header={ __( 'Dimensions' ) }
resetAll={ resetAll }
>
{ ! isHeightDisabled && (
<ToolsPanelItem
className="single-column"
hasValue={ () => hasHeightValue( props ) }
label={ __( 'Height' ) }
onDeselect={ () => resetHeight( props ) }
isShownByDefault={ defaultDimensionsControls?.height }
>
<HeightEdit { ...props } />
</ToolsPanelItem>
) }
{ ! isPaddingDisabled && (
<ToolsPanelItem
hasValue={ () => hasPaddingValue( props ) }
Expand Down Expand Up @@ -115,21 +143,25 @@ export function hasDimensionsSupport( blockName ) {
return false;
}

return hasPaddingSupport( blockName ) || hasMarginSupport( blockName );
return (
hasHeightSupport( blockName ) ||
hasPaddingSupport( blockName ) ||
hasMarginSupport( blockName )
);
}

/**
* Determines whether dimensions support has been disabled.
*
* @param {Object} props Block properties.
*
* @return {boolean} If spacing support is completely disabled.
* @return {boolean} If dimensions support is completely disabled.
*/
const useIsDimensionsDisabled = ( props = {} ) => {
const heightDisabled = useIsHeightDisabled( props );
const paddingDisabled = useIsPaddingDisabled( props );
const marginDisabled = useIsMarginDisabled( props );

return paddingDisabled && marginDisabled;
return heightDisabled && paddingDisabled && marginDisabled;
};

/**
Expand Down
121 changes: 121 additions & 0 deletions packages/block-editor/src/hooks/height.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';
import {
__experimentalUseCustomUnits as useCustomUnits,
__experimentalUnitControl as UnitControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import useSetting from '../components/use-setting';
import { DIMENSIONS_SUPPORT_KEY } from './dimensions';
import { cleanEmptyObject } from './utils';

/**
* Determines if there is height support.
*
* @param {string|Object} blockType Block name or Block Type object.
* @return {boolean} Whether there is support.
*/
export function hasHeightSupport( blockType ) {
const support = getBlockSupport( blockType, DIMENSIONS_SUPPORT_KEY );
return !! ( true === support || support?.height );
}

/**
* Checks if there is a current value in the height block support attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a height value set.
*/
export function hasHeightValue( props ) {
return props.attributes.style?.dimensions?.height !== undefined;
}

/**
* Resets the height block support attributes. This can be used when
* disabling the height support controls for a block via a progressive
* discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetHeight( { attributes = {}, setAttributes } ) {
const { style } = attributes;

setAttributes( {
style: cleanEmptyObject( {
...style,
dimensions: {
...style?.dimensions,
height: undefined,
},
} ),
} );
}

/**
* Custom hook that checks if height controls have been disabled.
*
* @param {string} name The name of the block.
* @return {boolean} Whether height control is disabled.
*/
export function useIsHeightDisabled( { name: blockName } = {} ) {
const isDisabled = ! useSetting( 'dimensions.customHeight' );
return ! hasHeightSupport( blockName ) || isDisabled;
}

/**
* Inspector control panel containing the height related configuration.
*
* @param {Object} props Block props.
* @return {WPElement} Edit component for height.
*/
export function HeightEdit( props ) {
const {
attributes: { style },
setAttributes,
} = props;

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

if ( useIsHeightDisabled( props ) ) {
return null;
}

const onChange = ( next ) => {
const newStyle = {
...style,
dimensions: {
...style?.dimensions,
height: next,
},
};

setAttributes( { style: cleanEmptyObject( newStyle ) } );
};

return (
<UnitControl
label={ __( 'Height' ) }
value={ style?.dimensions?.height }
units={ units }
onChange={ onChange }
min={ 0 }
/>
);
}
12 changes: 10 additions & 2 deletions packages/block-editor/src/hooks/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ import {
TYPOGRAPHY_SUPPORT_KEY,
TYPOGRAPHY_SUPPORT_KEYS,
} from './typography';
import { SPACING_SUPPORT_KEY, DimensionsPanel } from './dimensions';
import {
DIMENSIONS_SUPPORT_KEY,
SPACING_SUPPORT_KEY,
DimensionsPanel,
} from './dimensions';
import useDisplayBlockControls from '../components/use-display-block-controls';

const styleSupportKeys = [
...TYPOGRAPHY_SUPPORT_KEYS,
BORDER_SUPPORT_KEY,
COLOR_SUPPORT_KEY,
DIMENSIONS_SUPPORT_KEY,
SPACING_SUPPORT_KEY,
];

Expand Down Expand Up @@ -152,8 +157,11 @@ const skipSerializationPaths = {
[ `${ TYPOGRAPHY_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
TYPOGRAPHY_SUPPORT_KEY,
],
[ `${ DIMENSIONS_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
DIMENSIONS_SUPPORT_KEY,
],
[ `${ SPACING_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
'spacing',
SPACING_SUPPORT_KEY,
],
};

Expand Down
4 changes: 4 additions & 0 deletions packages/block-editor/src/hooks/test/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ describe( 'getInlineStyles', () => {
style: 'dotted',
color: '#21759b',
},
dimensions: {
height: '500px',
},
spacing: {
padding: { top: '10px' },
margin: { bottom: '15px' },
Expand All @@ -37,6 +40,7 @@ describe( 'getInlineStyles', () => {
color: 'red',
lineHeight: 1.5,
fontSize: 10,
height: '500px',
marginBottom: '15px',
paddingTop: '10px',
} );
Expand Down
4 changes: 4 additions & 0 deletions packages/blocks/src/api/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
value: [ 'typography', 'fontWeight' ],
support: [ 'typography', '__experimentalFontWeight' ],
},
height: {
value: [ 'dimensions', 'height' ],
support: [ '__experimentalDimensions', 'height' ],
},
lineHeight: {
value: [ 'typography', 'lineHeight' ],
support: [ 'typography', 'lineHeight' ],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,13 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {

const pickStyleKeys = ( treeToPickFrom ) =>
pickBy( treeToPickFrom, ( value, key ) =>
[ 'border', 'color', 'spacing', 'typography' ].includes( key )
[
'border',
'color',
'dimensions',
'spacing',
'typography',
].includes( key )
);

// Top-level.
Expand Down
Loading

0 comments on commit 433ce14

Please sign in to comment.