diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js
index ce9316309e423..e042a2de83cac 100644
--- a/packages/block-editor/src/hooks/padding.js
+++ b/packages/block-editor/src/hooks/padding.js
@@ -37,7 +37,22 @@ export function PaddingEdit( props ) {
const onChange = ( next ) => {
const newStyle = {
...style,
- padding: next,
+ spacing: {
+ padding: next,
+ },
+ };
+
+ setAttributes( {
+ style: cleanEmptyObject( newStyle ),
+ } );
+ };
+
+ const onChangeShowVisualizer = ( next ) => {
+ const newStyle = {
+ ...style,
+ visualizers: {
+ padding: next,
+ },
};
setAttributes( {
@@ -49,8 +64,9 @@ export function PaddingEdit( props ) {
web: (
<>
@@ -61,8 +77,8 @@ export function PaddingEdit( props ) {
}
export const paddingStyleMappings = {
- paddingTop: [ 'padding', 'top' ],
- paddingRight: [ 'padding', 'right' ],
- paddingBottom: [ 'padding', 'bottom' ],
- paddingLeft: [ 'padding', 'left' ],
+ paddingTop: [ 'spacing', 'padding', 'top' ],
+ paddingRight: [ 'spacing', 'padding', 'right' ],
+ paddingBottom: [ 'spacing', 'padding', 'bottom' ],
+ paddingLeft: [ 'spacing', 'padding', 'left' ],
};
diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js
index f8fbf30c6b6e3..a3b101b86790a 100644
--- a/packages/block-editor/src/hooks/style.js
+++ b/packages/block-editor/src/hooks/style.js
@@ -74,11 +74,17 @@ export function getInlineStyles( styles = {} ) {
};
const output = {};
- Object.entries( mappings ).forEach( ( [ styleKey, objectKey ] ) => {
- if ( has( styles, objectKey ) ) {
- output[ styleKey ] = compileStyleValue( get( styles, objectKey ) );
+ Object.entries( mappings ).forEach(
+ ( [ styleKey, ...otherObjectKeys ] ) => {
+ const [ objectKeys ] = otherObjectKeys;
+
+ if ( has( styles, objectKeys ) ) {
+ output[ styleKey ] = compileStyleValue(
+ get( styles, objectKeys )
+ );
+ }
}
- } );
+ );
return output;
}
diff --git a/packages/block-library/src/cover/edit.js b/packages/block-library/src/cover/edit.js
index 076d0881cbe6e..6f2794da106b2 100644
--- a/packages/block-library/src/cover/edit.js
+++ b/packages/block-library/src/cover/edit.js
@@ -475,7 +475,10 @@ function CoverEdit( {
<>
{ controls }
-
+
{
diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md
index e4105871042dc..47d398243297f 100644
--- a/packages/components/src/box-control/README.md
+++ b/packages/components/src/box-control/README.md
@@ -111,7 +111,14 @@ Heading label for BoxControl.
### onChange
-A function that receives the values of the inputs.
+A callback function when an input value changes.
+
+- Type: `Function`
+- Required: Yes
+
+### onChangeShowVisualizer
+
+A callback function for visualizer changes, based on input hover interactions.
- Type: `Function`
- Required: Yes
diff --git a/packages/components/src/box-control/all-input-control.js b/packages/components/src/box-control/all-input-control.js
index 8a40dd47e6612..1f1260898505d 100644
--- a/packages/components/src/box-control/all-input-control.js
+++ b/packages/components/src/box-control/all-input-control.js
@@ -6,16 +6,19 @@ import { noop } from 'lodash';
* Internal dependencies
*/
import UnitControl from './unit-control';
-import { LABELS, getAllValue, isValuesMixed } from './utils';
+import { LABELS, getAllValue, isValuesMixed, isValuesDefined } from './utils';
export default function AllInputControl( {
onChange = noop,
onFocus = noop,
+ onHoverOn = noop,
+ onHoverOff = noop,
values,
...props
} ) {
const allValue = getAllValue( values );
- const isMixed = isValuesMixed( values );
+ const hasValues = isValuesDefined( values );
+ const isMixed = hasValues && isValuesMixed( values );
const allPlaceholder = isMixed ? LABELS.mixed : null;
@@ -34,6 +37,24 @@ export default function AllInputControl( {
onChange( nextValues );
};
+ const handleOnHoverOn = () => {
+ onHoverOn( {
+ top: true,
+ bottom: true,
+ left: true,
+ right: true,
+ } );
+ };
+
+ const handleOnHoverOff = () => {
+ onHoverOff( {
+ top: false,
+ bottom: false,
+ left: false,
+ right: false,
+ } );
+ };
+
return (
);
diff --git a/packages/components/src/box-control/index.js b/packages/components/src/box-control/index.js
index 387fd317563f3..f75a4aee4b77d 100644
--- a/packages/components/src/box-control/index.js
+++ b/packages/components/src/box-control/index.js
@@ -7,7 +7,7 @@ import { noop } from 'lodash';
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
-import { useState, useRef } from '@wordpress/element';
+import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
@@ -26,7 +26,12 @@ import {
Header,
HeaderControlWrapper,
} from './styles/box-control-styles';
-import { DEFAULT_VALUES, isValuesMixed } from './utils';
+import {
+ DEFAULT_VALUES,
+ DEFAULT_VISUALIZER_VALUES,
+ isValuesMixed,
+ isValuesDefined,
+} from './utils';
import { useControlledState } from '../utils/hooks';
const defaultInputProps = {
@@ -43,17 +48,21 @@ export default function BoxControl( {
id: idProp,
inputProps = defaultInputProps,
onChange = noop,
+ onChangeShowVisualizer = noop,
label = __( 'Box Control' ),
- values: valuesProp = DEFAULT_VALUES,
+ values: valuesProp,
units,
} ) {
const [ values, setValues ] = useControlledState( valuesProp );
+ const inputValues = values || DEFAULT_VALUES;
+ const hasInitialValue = isValuesDefined( valuesProp );
- const [ isDirty, setIsDirty ] = useState( false );
- const [ isLinked, setIsLinked ] = useState( ! isValuesMixed( values ) );
- const [ side, setSide ] = useState( isLinked ? 'all' : 'top' );
+ const [ isDirty, setIsDirty ] = useState( hasInitialValue );
+ const [ isLinked, setIsLinked ] = useState(
+ ! hasInitialValue || ! isValuesMixed( inputValues )
+ );
- const initialValuesRef = useRef( values );
+ const [ side, setSide ] = useState( isLinked ? 'all' : 'top' );
const id = useUniqueId( idProp );
const headingId = `${ id }-heading`;
@@ -73,8 +82,16 @@ export default function BoxControl( {
setIsDirty( true );
};
+ const handleOnHoverOn = ( next = {} ) => {
+ onChangeShowVisualizer( { ...DEFAULT_VISUALIZER_VALUES, ...next } );
+ };
+
+ const handleOnHoverOff = ( next = {} ) => {
+ onChangeShowVisualizer( { ...DEFAULT_VISUALIZER_VALUES, ...next } );
+ };
+
const handleOnReset = () => {
- const initialValues = initialValuesRef.current;
+ const initialValues = DEFAULT_VALUES;
onChange( initialValues );
setValues( initialValues );
@@ -85,9 +102,11 @@ export default function BoxControl( {
...inputProps,
onChange: handleOnChange,
onFocus: handleOnFocus,
+ onHoverOn: handleOnHoverOn,
+ onHoverOff: handleOnHoverOff,
isLinked,
units,
- values,
+ values: inputValues,
};
return (
diff --git a/packages/components/src/box-control/input-controls.js b/packages/components/src/box-control/input-controls.js
index 36242e1e2a0f2..0177052151273 100644
--- a/packages/components/src/box-control/input-controls.js
+++ b/packages/components/src/box-control/input-controls.js
@@ -13,6 +13,8 @@ import { LayoutContainer, Layout } from './styles/box-control-styles';
export default function BoxInputControls( {
onChange = noop,
onFocus = noop,
+ onHoverOn = noop,
+ onHoverOff = noop,
values,
...props
} ) {
@@ -20,6 +22,14 @@ export default function BoxInputControls( {
onFocus( event, { side } );
};
+ const createHandleOnHoverOn = ( side ) => () => {
+ onHoverOn( { [ side ]: true } );
+ };
+
+ const createHandleOnHoverOff = ( side ) => () => {
+ onHoverOff( { [ side ]: false } );
+ };
+
const handleOnChange = ( nextValues ) => {
onChange( nextValues );
};
@@ -69,6 +79,8 @@ export default function BoxInputControls( {
value={ top }
onChange={ createHandleOnChange( 'top' ) }
onFocus={ createHandleOnFocus( 'top' ) }
+ onHoverOn={ createHandleOnHoverOn( 'top' ) }
+ onHoverOff={ createHandleOnHoverOff( 'top' ) }
label={ LABELS.top }
/>
diff --git a/packages/components/src/box-control/stories/index.js b/packages/components/src/box-control/stories/index.js
index 47e8520eeb9fb..60205d435fb94 100644
--- a/packages/components/src/box-control/stories/index.js
+++ b/packages/components/src/box-control/stories/index.js
@@ -28,6 +28,8 @@ function DemoExample() {
left: '10px',
} );
+ const [ showVisualizer, setShowVisualizer ] = useState( {} );
+
return (
@@ -36,13 +38,17 @@ function DemoExample() {
label="Padding"
values={ values }
onChange={ setValues }
+ onChangeShowVisualizer={ setShowVisualizer }
/>
-
+
diff --git a/packages/components/src/box-control/unit-control.js b/packages/components/src/box-control/unit-control.js
index d5842da216884..1211452f7d315 100644
--- a/packages/components/src/box-control/unit-control.js
+++ b/packages/components/src/box-control/unit-control.js
@@ -1,3 +1,9 @@
+/**
+ * External dependencies
+ */
+import { noop } from 'lodash';
+import { useHover } from 'react-use-gesture';
+
/**
* Internal dependencies
*/
@@ -8,12 +14,22 @@ export default function BoxUnitControl( {
isFirst,
isLast,
isOnly,
+ onHoverOn = noop,
+ onHoverOff = noop,
label,
value,
...props
} ) {
+ const bindHoverGesture = useHover( ( { event, ...state } ) => {
+ if ( state.hovering ) {
+ onHoverOn( event, state );
+ } else {
+ onHoverOff( event, state );
+ }
+ } );
+
return (
-
+
-
+
{ children }
);
}
-function Sides( { values } ) {
+function Sides( { showValues = DEFAULT_VISUALIZER_VALUES, values } ) {
const { top, right, bottom, left } = values;
return (
<>
-
-
-
-
+
+
+
+
>
);
}
-function Top( { value } ) {
+function Top( { isVisible = false, value } ) {
const height = value;
const animationProps = useSideAnimation( height );
+ const isActive = animationProps.isActive || isVisible;
- return ;
+ return ;
}
-function Right( { value } ) {
+function Right( { isVisible = false, value } ) {
const width = value;
const animationProps = useSideAnimation( width );
+ const isActive = animationProps.isActive || isVisible;
- return ;
+ return ;
}
-function Bottom( { value } ) {
+function Bottom( { isVisible = false, value } ) {
const height = value;
const animationProps = useSideAnimation( height );
+ const isActive = animationProps.isActive || isVisible;
- return ;
+ return ;
}
-function Left( { value } ) {
+function Left( { isVisible = false, value } ) {
const width = value;
const animationProps = useSideAnimation( width );
+ const isActive = animationProps.isActive || isVisible;
- return ;
+ return ;
}
/**