From a61f7d6e4381602a74134c6c51c64360281f5156 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 20 Oct 2022 11:15:30 +1300 Subject: [PATCH] Spacing visualizer: add option to trigger with mousover as well as value change (#44955) --- .../all-input-control.js | 4 ++ .../axial-input-controls.js | 4 ++ .../components/spacing-sizes-control/index.js | 4 ++ .../spacing-sizes-control/input-controls.js | 4 ++ .../spacing-input-control.js | 10 +++++ packages/block-editor/src/hooks/dimensions.js | 37 ++++++++++++++++--- packages/block-editor/src/hooks/margin.js | 33 ++++++++++------- packages/block-editor/src/hooks/padding.js | 35 ++++++++++-------- packages/components/CHANGELOG.md | 4 ++ packages/components/src/box-control/README.md | 14 +++++++ packages/components/src/box-control/index.js | 4 ++ .../src/custom-select-control/README.md | 14 +++++++ .../src/custom-select-control/index.js | 37 +++++++++++-------- 13 files changed, 154 insertions(+), 50 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js index 8f9509349c2a5a..f7f9686daee33a 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/all-input-control.js @@ -16,6 +16,8 @@ export default function AllInputControl( { spacingSizes, type, minimumCustomValue, + onMouseOver, + onMouseOut, } ) { const allValue = getAllRawValue( values ); const hasValues = isValuesDefined( values ); @@ -35,6 +37,8 @@ export default function AllInputControl( { isMixed={ isMixed } type={ type } minimumCustomValue={ minimumCustomValue } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ); } diff --git a/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js b/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js index 563b5950186962..3551e20ede7596 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js +++ b/packages/block-editor/src/components/spacing-sizes-control/axial-input-controls.js @@ -13,6 +13,8 @@ export default function AxialInputControls( { spacingSizes, type, minimumCustomValue, + onMouseOver, + onMouseOut, } ) { const createHandleOnChange = ( side ) => ( next ) => { if ( ! onChange ) { @@ -54,6 +56,8 @@ export default function AxialInputControls( { spacingSizes={ spacingSizes } type={ type } minimumCustomValue={ minimumCustomValue } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ); } ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index 7b016e7a08ee72..fb4ce2176b759d 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -29,6 +29,8 @@ export default function SpacingSizesControl( { splitOnAxis = false, useSelect, minimumCustomValue = 0, + onMouseOver, + onMouseOut, } ) { const spacingSizes = [ { name: 0, slug: '0', size: 0 }, @@ -70,6 +72,8 @@ export default function SpacingSizesControl( { useSelect, type: label, minimumCustomValue, + onMouseOver, + onMouseOut, }; return ( diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls.js index b8b71c22310b59..412dbad2030c99 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls.js @@ -11,6 +11,8 @@ export default function BoxInputControls( { spacingSizes, type, minimumCustomValue, + onMouseOver, + onMouseOut, } ) { // Filter sides if custom configuration provided, maintaining default order. const filteredSides = sides?.length @@ -38,6 +40,8 @@ export default function BoxInputControls( { spacingSizes={ spacingSizes } type={ type } minimumCustomValue={ minimumCustomValue } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ); } ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js index a6262873af553e..54d07e61c6d2b4 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js @@ -51,6 +51,8 @@ export default function SpacingInputControl( { isMixed = false, type, minimumCustomValue, + onMouseOver, + onMouseOut, } ) { // Treat value as a preset value if the passed in value matches the value of one of the spacingSizes. value = getPresetValueFromCustomValue( value, spacingSizes ); @@ -218,6 +220,8 @@ export default function SpacingInputControl( { { showCustomValueControl && ( <> onChange( getNewCustomValue( newSize ) ) } @@ -234,6 +238,8 @@ export default function SpacingInputControl( { /> @@ -293,6 +301,8 @@ export default function SpacingInputControl( { hideLabelFromVision={ true } __nextUnconstrainedWidth={ true } size={ '__unstable-large' } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ) } diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index 3eded40fc4a0ae..171080934213de 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -7,7 +7,7 @@ import classnames from 'classnames'; * WordPress dependencies */ import { __experimentalToolsPanelItem as ToolsPanelItem } from '@wordpress/components'; -import { Platform } from '@wordpress/element'; +import { Platform, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { getBlockSupport } from '@wordpress/blocks'; @@ -44,6 +44,13 @@ export const SPACING_SUPPORT_KEY = 'spacing'; export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ]; export const AXIAL_SIDES = [ 'vertical', 'horizontal' ]; +function useVisualizerMouseOver() { + const [ isMouseOver, setIsMouseOver ] = useState( false ); + const onMouseOver = () => setIsMouseOver( true ); + const onMouseOut = () => setIsMouseOver( false ); + return { isMouseOver, onMouseOver, onMouseOut }; +} + /** * Inspector controls for dimensions support. * @@ -58,6 +65,8 @@ export function DimensionsPanel( props ) { const isDisabled = useIsDimensionsDisabled( props ); const isSupported = hasDimensionsSupport( props.name ); const spacingSizes = useSetting( 'spacing.spacingSizes' ); + const paddingMouseOver = useVisualizerMouseOver(); + const marginMouseOver = useVisualizerMouseOver(); if ( isDisabled || ! isSupported ) { return null; @@ -96,7 +105,11 @@ export function DimensionsPanel( props ) { isShownByDefault={ defaultSpacingControls?.padding } panelId={ props.clientId } > - + ) } { ! isMarginDisabled && ( @@ -109,7 +122,11 @@ export function DimensionsPanel( props ) { isShownByDefault={ defaultSpacingControls?.margin } panelId={ props.clientId } > - + ) } { ! isGapDisabled && ( @@ -126,8 +143,18 @@ export function DimensionsPanel( props ) { ) } - { ! isPaddingDisabled && } - { ! isMarginDisabled && } + { ! isPaddingDisabled && ( + + ) } + { ! isMarginDisabled && ( + + ) } ); } diff --git a/packages/block-editor/src/hooks/margin.js b/packages/block-editor/src/hooks/margin.js index 0e60717486d2bc..d046685a23323a 100644 --- a/packages/block-editor/src/hooks/margin.js +++ b/packages/block-editor/src/hooks/margin.js @@ -29,7 +29,7 @@ import { import { cleanEmptyObject } from './utils'; import BlockPopover from '../components/block-popover'; import SpacingSizesControl from '../components/spacing-sizes-control'; -import { getCustomValueFromPreset } from '../components/spacing-sizes-control/utils'; +import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils'; /** * Determines if there is margin support. @@ -101,6 +101,8 @@ export function MarginEdit( props ) { name: blockName, attributes: { style }, setAttributes, + onMouseOver, + onMouseOut, } = props; const spacingSizes = useSetting( 'spacing.spacingSizes' ); @@ -148,6 +150,8 @@ export function MarginEdit( props ) { units={ units } allowReset={ false } splitOnAxis={ splitOnAxis } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ) } { spacingSizes?.length > 0 && ( @@ -159,6 +163,8 @@ export function MarginEdit( props ) { units={ units } allowReset={ false } splitOnAxis={ false } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ) } @@ -167,22 +173,21 @@ export function MarginEdit( props ) { } ); } -export function MarginVisualizer( { clientId, attributes } ) { +export function MarginVisualizer( { clientId, attributes, forceShow } ) { const margin = attributes?.style?.spacing?.margin; - const spacingSizes = useSetting( 'spacing.spacingSizes' ); const style = useMemo( () => { const marginTop = margin?.top - ? getCustomValueFromPreset( margin?.top, spacingSizes ) + ? getSpacingPresetCssVar( margin?.top ) : 0; const marginRight = margin?.right - ? getCustomValueFromPreset( margin?.right, spacingSizes ) + ? getSpacingPresetCssVar( margin?.right ) : 0; const marginBottom = margin?.bottom - ? getCustomValueFromPreset( margin?.bottom, spacingSizes ) + ? getSpacingPresetCssVar( margin?.bottom ) : 0; const marginLeft = margin?.left - ? getCustomValueFromPreset( margin?.left, spacingSizes ) + ? getSpacingPresetCssVar( margin?.left ) : 0; return { @@ -190,10 +195,10 @@ export function MarginVisualizer( { clientId, attributes } ) { borderRightWidth: marginRight, borderBottomWidth: marginBottom, borderLeftWidth: marginLeft, - top: marginTop !== 0 ? `calc(${ marginTop } * -1)` : 0, - right: marginRight !== 0 ? `calc(${ marginRight } * -1)` : 0, - bottom: marginBottom !== 0 ? `calc(${ marginBottom } * -1)` : 0, - left: marginLeft !== 0 ? `calc(${ marginLeft } * -1)` : 0, + top: marginTop ? `calc(${ marginTop } * -1)` : 0, + right: marginRight ? `calc(${ marginRight } * -1)` : 0, + bottom: marginBottom ? `calc(${ marginBottom } * -1)` : 0, + left: marginLeft ? `calc(${ marginLeft } * -1)` : 0, }; }, [ margin ] ); @@ -208,7 +213,7 @@ export function MarginVisualizer( { clientId, attributes } ) { }; useEffect( () => { - if ( ! isShallowEqual( margin, valueRef.current ) ) { + if ( ! isShallowEqual( margin, valueRef.current ) && ! forceShow ) { setIsActive( true ); valueRef.current = margin; @@ -220,9 +225,9 @@ export function MarginVisualizer( { clientId, attributes } ) { } return () => clearTimer(); - }, [ margin ] ); + }, [ margin, forceShow ] ); - if ( ! isActive ) { + if ( ! isActive && ! forceShow ) { return null; } diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js index 46015b1e164631..007bc799f9bf8f 100644 --- a/packages/block-editor/src/hooks/padding.js +++ b/packages/block-editor/src/hooks/padding.js @@ -29,10 +29,7 @@ import { import { cleanEmptyObject } from './utils'; import BlockPopover from '../components/block-popover'; import SpacingSizesControl from '../components/spacing-sizes-control'; -import { - getSpacingPresetCssVar, - isValueSpacingPreset, -} from '../components/spacing-sizes-control/utils'; +import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils'; /** * Determines if there is padding support. * @@ -103,6 +100,8 @@ export function PaddingEdit( props ) { name: blockName, attributes: { style }, setAttributes, + onMouseOver, + onMouseOut, } = props; const spacingSizes = useSetting( 'spacing.spacingSizes' ); @@ -150,6 +149,8 @@ export function PaddingEdit( props ) { units={ units } allowReset={ false } splitOnAxis={ splitOnAxis } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ) } { spacingSizes?.length > 0 && ( @@ -161,6 +162,8 @@ export function PaddingEdit( props ) { units={ units } allowReset={ false } splitOnAxis={ splitOnAxis } + onMouseOver={ onMouseOver } + onMouseOut={ onMouseOut } /> ) } @@ -169,22 +172,22 @@ export function PaddingEdit( props ) { } ); } -export function PaddingVisualizer( { clientId, attributes } ) { +export function PaddingVisualizer( { clientId, attributes, forceShow } ) { const padding = attributes?.style?.spacing?.padding; const style = useMemo( () => { return { - borderTopWidth: isValueSpacingPreset( padding?.top ) + borderTopWidth: padding?.top ? getSpacingPresetCssVar( padding?.top ) - : padding?.top, - borderRightWidth: isValueSpacingPreset( padding?.right ) + : 0, + borderRightWidth: padding?.right ? getSpacingPresetCssVar( padding?.right ) - : padding?.right, - borderBottomWidth: isValueSpacingPreset( padding?.bottom ) + : 0, + borderBottomWidth: padding?.bottom ? getSpacingPresetCssVar( padding?.bottom ) - : padding?.bottom, - borderLeftWidth: isValueSpacingPreset( padding?.left ) + : 0, + borderLeftWidth: padding?.left ? getSpacingPresetCssVar( padding?.left ) - : padding?.left, + : 0, }; }, [ padding ] ); @@ -199,7 +202,7 @@ export function PaddingVisualizer( { clientId, attributes } ) { }; useEffect( () => { - if ( ! isShallowEqual( padding, valueRef.current ) ) { + if ( ! isShallowEqual( padding, valueRef.current ) && ! forceShow ) { setIsActive( true ); valueRef.current = padding; @@ -211,9 +214,9 @@ export function PaddingVisualizer( { clientId, attributes } ) { } return () => clearTimer(); - }, [ padding ] ); + }, [ padding, forceShow ] ); - if ( ! isActive ) { + if ( ! isActive && ! forceShow ) { return null; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 18a230c301d46d..3f7325870704ed 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Feature + +- `BoxControl` & `CustomSelectControl`: Add `onMouseOver` and `onMouseOut` callback props to allow handling of these events by parent components ([#44955](https://github.com/WordPress/gutenberg/pull/44955)) + ## 21.3.0 (2022-10-19) ### Bug Fix diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index 8a704482cacd14..edf3993679033f 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -95,3 +95,17 @@ The `top`, `right`, `bottom`, and `left` box dimension values. - Type: `Object` - Required: No + +### onMouseOver + +A handler for onMouseOver events. + +- Type: `Function` +- Required: No + +### onMouseOut + +A handler for onMouseOut events. + +- Type: `Function` +- Required: No diff --git a/packages/components/src/box-control/index.js b/packages/components/src/box-control/index.js index f5e8e7428c8015..d8a0fdf4c67483 100644 --- a/packages/components/src/box-control/index.js +++ b/packages/components/src/box-control/index.js @@ -52,6 +52,8 @@ export default function BoxControl( { splitOnAxis = false, allowReset = true, resetValues = DEFAULT_VALUES, + onMouseOver, + onMouseOut, } ) { const [ values, setValues ] = useControlledState( valuesProp, { fallback: DEFAULT_VALUES, @@ -114,6 +116,8 @@ export default function BoxControl( { setSelectedUnits, sides, values: inputValues, + onMouseOver, + onMouseOut, }; return ( diff --git a/packages/components/src/custom-select-control/README.md b/packages/components/src/custom-select-control/README.md index c54e5a5e934e00..8144a7cfa59609 100644 --- a/packages/components/src/custom-select-control/README.md +++ b/packages/components/src/custom-select-control/README.md @@ -131,6 +131,20 @@ Start opting into the unconstrained width style that will become the default in - Required: No - Default: `false` +#### onMouseOver + +A handler for onMouseOver events. + +- Type: `Function` +- Required: No + +#### onMouseOut + +A handler for onMouseOut events. + +- Type: `Function` +- Required: No + ## Related components - Like this component, but implemented using a native `