Skip to content

Commit

Permalink
Add gap block support feature based on #32571
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewserong committed Aug 11, 2021
1 parent 5a610d4 commit 054eb5d
Show file tree
Hide file tree
Showing 10 changed files with 331 additions and 33 deletions.
13 changes: 13 additions & 0 deletions lib/block-supports/dimensions.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) {

$has_padding_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'padding' ), false );
$has_margin_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'margin' ), false );
$has_gap_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'gap' ), false );
$styles = array();

if ( $has_padding_support ) {
Expand All @@ -89,6 +90,18 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) {
}
}

if ( $has_gap_support ) {
$gap_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'gap' ), null );

if ( is_array( $gap_value ) ) {
foreach ( $gap_value as $key => $value ) {
$styles[] = sprintf( '--wp--theme--block-%s-gap: %s', $key, $value );
}
} elseif ( null !== $gap_value ) {
$styles[] = sprintf( '--wp--theme--block-: %s', $gap_value );
}
}

return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
}

Expand Down
63 changes: 34 additions & 29 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class WP_Theme_JSON_Gutenberg {
'text' => null,
),
'spacing' => array(
'gap' => null,
'margin' => null,
'padding' => null,
),
Expand Down Expand Up @@ -98,6 +99,7 @@ class WP_Theme_JSON_Gutenberg {
'wideSize' => null,
),
'spacing' => array(
'customGap' => null,
'customMargin' => null,
'customPadding' => null,
'units' => null,
Expand Down Expand Up @@ -206,35 +208,38 @@ class WP_Theme_JSON_Gutenberg {
* path to the value in theme.json & block attributes.
*/
const PROPERTIES_METADATA = array(
'background' => array( 'color', 'gradient' ),
'background-color' => array( 'color', 'background' ),
'border-radius' => array( 'border', 'radius' ),
'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
'border-color' => array( 'border', 'color' ),
'border-width' => array( 'border', 'width' ),
'border-style' => array( 'border', 'style' ),
'color' => array( 'color', 'text' ),
'font-family' => array( 'typography', 'fontFamily' ),
'font-size' => array( 'typography', 'fontSize' ),
'font-style' => array( 'typography', 'fontStyle' ),
'font-weight' => array( 'typography', 'fontWeight' ),
'letter-spacing' => array( 'typography', 'letterSpacing' ),
'line-height' => array( 'typography', 'lineHeight' ),
'margin' => array( 'spacing', 'margin' ),
'margin-top' => array( 'spacing', 'margin', 'top' ),
'margin-right' => array( 'spacing', 'margin', 'right' ),
'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
'margin-left' => array( 'spacing', 'margin', 'left' ),
'padding' => array( 'spacing', 'padding' ),
'padding-top' => array( 'spacing', 'padding', 'top' ),
'padding-right' => array( 'spacing', 'padding', 'right' ),
'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
'padding-left' => array( 'spacing', 'padding', 'left' ),
'text-decoration' => array( 'typography', 'textDecoration' ),
'text-transform' => array( 'typography', 'textTransform' ),
'background' => array( 'color', 'gradient' ),
'background-color' => array( 'color', 'background' ),
'border-radius' => array( 'border', 'radius' ),
'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
'border-color' => array( 'border', 'color' ),
'border-width' => array( 'border', 'width' ),
'border-style' => array( 'border', 'style' ),
'color' => array( 'color', 'text' ),
'font-family' => array( 'typography', 'fontFamily' ),
'font-size' => array( 'typography', 'fontSize' ),
'font-style' => array( 'typography', 'fontStyle' ),
'font-weight' => array( 'typography', 'fontWeight' ),
'--wp--theme--block-gap' => array( 'spacing', 'gap' ),
'--wp--theme--block-column-gap' => array( 'spacing', 'gap', 'column' ),
'--wp--theme--block-row-gap' => array( 'spacing', 'gap', 'row' ),
'letter-spacing' => array( 'typography', 'letterSpacing' ),
'line-height' => array( 'typography', 'lineHeight' ),
'margin' => array( 'spacing', 'margin' ),
'margin-top' => array( 'spacing', 'margin', 'top' ),
'margin-right' => array( 'spacing', 'margin', 'right' ),
'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
'margin-left' => array( 'spacing', 'margin', 'left' ),
'padding' => array( 'spacing', 'padding' ),
'padding-top' => array( 'spacing', 'padding', 'top' ),
'padding-right' => array( 'spacing', 'padding', 'right' ),
'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
'padding-left' => array( 'spacing', 'padding', 'left' ),
'text-decoration' => array( 'typography', 'textDecoration' ),
'text-transform' => array( 'typography', 'textTransform' ),
);

const ELEMENTS = array(
Expand Down
3 changes: 3 additions & 0 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ function gutenberg_safe_style_attrs( $attrs ) {
$attrs[] = 'border-top-right-radius';
$attrs[] = 'border-bottom-right-radius';
$attrs[] = 'border-bottom-left-radius';
$attrs[] = 'gap';
$attrs[] = 'column-gap';
$attrs[] = 'row-gap';

return $attrs;
}
Expand Down
1 change: 1 addition & 0 deletions lib/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@
]
},
"spacing": {
"customGap": false,
"customMargin": false,
"customPadding": false,
"units": [ "px", "em", "rem", "vh", "vw", "%" ]
Expand Down
28 changes: 26 additions & 2 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 {
GapEdit,
hasGapSupport,
hasGapValue,
resetGap,
useIsGapDisabled,
} from './gap';
import {
MarginEdit,
hasMarginSupport,
Expand All @@ -39,6 +46,7 @@ export const SPACING_SUPPORT_KEY = 'spacing';
* @return {WPElement} Inspector controls for spacing support features.
*/
export function DimensionsPanel( props ) {
const isGapDisabled = useIsGapDisabled( props );
const isPaddingDisabled = useIsPaddingDisabled( props );
const isMarginDisabled = useIsMarginDisabled( props );
const isDisabled = useIsDimensionsDisabled( props );
Expand All @@ -62,6 +70,7 @@ export function DimensionsPanel( props ) {
...style,
spacing: {
...style?.spacing,
gap: undefined,
margin: undefined,
padding: undefined,
},
Expand Down Expand Up @@ -96,6 +105,16 @@ export function DimensionsPanel( props ) {
<MarginEdit { ...props } />
</ToolsPanelItem>
) }
{ ! isGapDisabled && (
<ToolsPanelItem
hasValue={ () => hasGapValue( props ) }
label={ __( 'Gap' ) }
onDeselect={ () => resetGap( props ) }
isShownByDefault={ defaultSpacingControls?.gap }
>
<GapEdit { ...props } />
</ToolsPanelItem>
) }
</ToolsPanel>
</InspectorControls>
);
Expand All @@ -113,7 +132,11 @@ export function hasDimensionsSupport( blockName ) {
return false;
}

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

/**
Expand All @@ -124,10 +147,11 @@ export function hasDimensionsSupport( blockName ) {
* @return {boolean} If spacing support is completely disabled.
*/
const useIsDimensionsDisabled = ( props = {} ) => {
const gapDisabled = useIsGapDisabled( props );
const paddingDisabled = useIsPaddingDisabled( props );
const marginDisabled = useIsMarginDisabled( props );

return paddingDisabled && marginDisabled;
return gapDisabled && paddingDisabled && marginDisabled;
};

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

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

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

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

/**
* Resets the gap block support attribute. This can be used when disabling
* the gap 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 resetGap( { attributes = {}, setAttributes } ) {
const { style } = attributes;

setAttributes( {
style: {
...style,
spacing: {
...style?.spacing,
gap: undefined,
},
},
} );
}

/**
* Custom hook that checks if gap settings have been disabled.
*
* @param {string} name The name of the block.
* @return {boolean} Whether the gap setting is disabled.
*/
export function useIsGapDisabled( { name: blockName } = {} ) {
const isDisabled = ! useSetting( 'spacing.customGap' );
return ! hasGapSupport( blockName ) || isDisabled;
}

/**
* Inspector control panel containing the gap related configuration
*
* @param {Object} props
*
* @return {WPElement} Gap edit element.
*/
export function GapEdit( props ) {
const {
name: blockName,
attributes: { style },
setAttributes,
} = props;

const units = useCustomUnits( {
availableUnits: useSetting( 'spacing.units' ) || [
'%',
'px',
'em',
'rem',
'vw',
],
} );
const sides = useCustomSides( blockName, 'gap' );

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

const onChange = ( next ) => {
const newStyle = {
...style,
spacing: {
...style?.spacing,
gap: { row: next?.top, column: next?.left },
},
};

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

const onChangeShowVisualizer = ( next ) => {
const newStyle = {
...style,
visualizers: {
gap: { row: next?.top, column: next?.left },
},
};

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

const boxValues = {
top: style?.spacing?.gap?.row,
right: style?.spacing?.gap?.column,
bottom: style?.spacing?.gap?.row,
left: style?.spacing?.gap?.column,
};

return Platform.select( {
web: (
<>
<BoxControl
values={ boxValues }
onChange={ onChange }
onChangeShowVisualizer={ onChangeShowVisualizer }
label={ __( 'Gap' ) }
sides={ sides }
units={ units }
allowReset={ false }
splitOnAxis={ true }
/>
</>
),
native: null,
} );
}
Loading

0 comments on commit 054eb5d

Please sign in to comment.