diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 249d4f3f65b936..6a7b2545c2e68c 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -40,6 +40,7 @@
- Upgraded `@ariakit/react` (v0.4.15) and `@ariakit/test` (v0.4.7) ([#67404](https://github.com/WordPress/gutenberg/pull/67404)).
- `ToolbarButton`: Set size to "compact" ([#67440](https://github.com/WordPress/gutenberg/pull/67440)).
- `SlotFill`: remove manual rerenders from the portal `Fill` component ([#67471](https://github.com/WordPress/gutenberg/pull/67471)).
+- `BoxControl`: Refactor internals to unify the different combinations of sides ([#67626](https://github.com/WordPress/gutenberg/pull/67626)).
### Bug Fixes
diff --git a/packages/components/src/box-control/all-input-control.tsx b/packages/components/src/box-control/all-input-control.tsx
deleted file mode 100644
index 0cfaea21915f6d..00000000000000
--- a/packages/components/src/box-control/all-input-control.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { useInstanceId } from '@wordpress/compose';
-/**
- * Internal dependencies
- */
-import type { UnitControlProps } from '../unit-control/types';
-import {
- FlexedRangeControl,
- StyledUnitControl,
-} from './styles/box-control-styles';
-import type { BoxControlInputControlProps } from './types';
-import { parseQuantityAndUnitFromRawValue } from '../unit-control';
-import {
- LABELS,
- applyValueToSides,
- getAllValue,
- isValuesMixed,
- isValuesDefined,
- CUSTOM_VALUE_SETTINGS,
-} from './utils';
-
-const noop = () => {};
-
-export default function AllInputControl( {
- __next40pxDefaultSize,
- onChange = noop,
- onFocus = noop,
- values,
- sides,
- selectedUnits,
- setSelectedUnits,
- ...props
-}: BoxControlInputControlProps ) {
- const inputId = useInstanceId( AllInputControl, 'box-control-input-all' );
-
- const allValue = getAllValue( values, selectedUnits, sides );
- const hasValues = isValuesDefined( values );
- const isMixed = hasValues && isValuesMixed( values, selectedUnits, sides );
- const allPlaceholder = isMixed ? LABELS.mixed : undefined;
-
- const [ parsedQuantity, parsedUnit ] =
- parseQuantityAndUnitFromRawValue( allValue );
-
- const handleOnFocus: React.FocusEventHandler< HTMLInputElement > = (
- event
- ) => {
- onFocus( event, { side: 'all' } );
- };
-
- const onValueChange = ( next?: string ) => {
- const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) );
- const nextValue = isNumeric ? next : undefined;
- const nextValues = applyValueToSides( values, nextValue, sides );
-
- onChange( nextValues );
- };
-
- const sliderOnChange = ( next?: number ) => {
- onValueChange(
- next !== undefined ? [ next, parsedUnit ].join( '' ) : undefined
- );
- };
-
- // Set selected unit so it can be used as fallback by unlinked controls
- // when individual sides do not have a value containing a unit.
- const handleOnUnitChange: UnitControlProps[ 'onUnitChange' ] = ( unit ) => {
- const newUnits = applyValueToSides( selectedUnits, unit, sides );
- setSelectedUnits( newUnits );
- };
-
- return (
- <>
-
-
-
- >
- );
-}
diff --git a/packages/components/src/box-control/axial-input-controls.tsx b/packages/components/src/box-control/axial-input-controls.tsx
deleted file mode 100644
index f8cbc5635c9b55..00000000000000
--- a/packages/components/src/box-control/axial-input-controls.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { useInstanceId } from '@wordpress/compose';
-/**
- * Internal dependencies
- */
-import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
-import Tooltip from '../tooltip';
-import { CUSTOM_VALUE_SETTINGS, LABELS } from './utils';
-import {
- FlexedBoxControlIcon,
- FlexedRangeControl,
- InputWrapper,
- StyledUnitControl,
-} from './styles/box-control-styles';
-import type { BoxControlInputControlProps } from './types';
-
-const groupedSides = [ 'vertical', 'horizontal' ] as const;
-type GroupedSide = ( typeof groupedSides )[ number ];
-
-export default function AxialInputControls( {
- __next40pxDefaultSize,
- onChange,
- onFocus,
- values,
- selectedUnits,
- setSelectedUnits,
- sides,
- ...props
-}: BoxControlInputControlProps ) {
- const generatedId = useInstanceId(
- AxialInputControls,
- `box-control-input`
- );
-
- const createHandleOnFocus =
- ( side: GroupedSide ) =>
- ( event: React.FocusEvent< HTMLInputElement > ) => {
- if ( ! onFocus ) {
- return;
- }
- onFocus( event, { side } );
- };
-
- const handleOnValueChange = ( side: GroupedSide, next?: string ) => {
- if ( ! onChange ) {
- return;
- }
- const nextValues = { ...values };
- const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) );
- const nextValue = isNumeric ? next : undefined;
-
- if ( side === 'vertical' ) {
- nextValues.top = nextValue;
- nextValues.bottom = nextValue;
- }
-
- if ( side === 'horizontal' ) {
- nextValues.left = nextValue;
- nextValues.right = nextValue;
- }
-
- onChange( nextValues );
- };
-
- const createHandleOnUnitChange =
- ( side: GroupedSide ) => ( next?: string ) => {
- const newUnits = { ...selectedUnits };
-
- if ( side === 'vertical' ) {
- newUnits.top = next;
- newUnits.bottom = next;
- }
-
- if ( side === 'horizontal' ) {
- newUnits.left = next;
- newUnits.right = next;
- }
-
- setSelectedUnits( newUnits );
- };
-
- // Filter sides if custom configuration provided, maintaining default order.
- const filteredSides = sides?.length
- ? groupedSides.filter( ( side ) => sides.includes( side ) )
- : groupedSides;
-
- return (
- <>
- { filteredSides.map( ( side ) => {
- const [ parsedQuantity, parsedUnit ] =
- parseQuantityAndUnitFromRawValue(
- side === 'vertical' ? values.top : values.left
- );
- const selectedUnit =
- side === 'vertical'
- ? selectedUnits.top
- : selectedUnits.left;
-
- const inputId = [ generatedId, side ].join( '-' );
-
- return (
-
-
-
-
- handleOnValueChange( side, newValue )
- }
- onUnitChange={ createHandleOnUnitChange(
- side
- ) }
- onFocus={ createHandleOnFocus( side ) }
- label={ LABELS[ side ] }
- hideLabelFromVision
- key={ side }
- />
-
-
- handleOnValueChange(
- side,
- newValue !== undefined
- ? [
- newValue,
- selectedUnit ?? parsedUnit,
- ].join( '' )
- : undefined
- )
- }
- min={ 0 }
- max={
- CUSTOM_VALUE_SETTINGS[ selectedUnit ?? 'px' ]
- ?.max ?? 10
- }
- step={
- CUSTOM_VALUE_SETTINGS[ selectedUnit ?? 'px' ]
- ?.step ?? 0.1
- }
- value={ parsedQuantity ?? 0 }
- withInputField={ false }
- />
-
- );
- } ) }
- >
- );
-}
diff --git a/packages/components/src/box-control/index.tsx b/packages/components/src/box-control/index.tsx
index 46cf2cd93a9444..279dfa55eafe38 100644
--- a/packages/components/src/box-control/index.tsx
+++ b/packages/components/src/box-control/index.tsx
@@ -9,13 +9,10 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies
*/
import { BaseControl } from '../base-control';
-import AllInputControl from './all-input-control';
-import InputControls from './input-controls';
-import AxialInputControls from './axial-input-controls';
+import InputControl from './input-control';
import LinkedButton from './linked-button';
import { Grid } from '../grid';
import {
- FlexedBoxControlIcon,
InputWrapper,
ResetButton,
LinkedButtonWrapper,
@@ -24,8 +21,9 @@ import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import {
DEFAULT_VALUES,
getInitialSide,
- isValuesMixed,
+ isValueMixed,
isValuesDefined,
+ getAllowedSides,
} from './utils';
import { useControlledState } from '../utils/hooks';
import type {
@@ -97,7 +95,7 @@ function BoxControl( {
const [ isDirty, setIsDirty ] = useState( hasInitialValue );
const [ isLinked, setIsLinked ] = useState(
- ! hasInitialValue || ! isValuesMixed( inputValues ) || hasOneSide
+ ! hasInitialValue || ! isValueMixed( inputValues ) || hasOneSide
);
const [ side, setSide ] = useState< BoxControlIconProps[ 'side' ] >(
@@ -162,6 +160,7 @@ function BoxControl( {
__next40pxDefaultSize,
size: undefined,
} );
+ const sidesToRender = getAllowedSides( sides );
return (
{ isLinked && (
-
-
+
) }
{ ! hasOneSide && (
@@ -189,12 +187,24 @@ function BoxControl( {
) }
- { ! isLinked && splitOnAxis && (
-
- ) }
- { ! isLinked && ! splitOnAxis && (
-
- ) }
+ { ! isLinked &&
+ splitOnAxis &&
+ [ 'vertical', 'horizontal' ].map( ( axis ) => (
+
+ ) ) }
+ { ! isLinked &&
+ ! splitOnAxis &&
+ Array.from( sidesToRender ).map( ( axis ) => (
+
+ ) ) }
{ allowReset && (
{};
+
+function getSidesToModify(
+ side: BoxControlInputControlProps[ 'side' ],
+ sides: BoxControlInputControlProps[ 'sides' ],
+ isAlt?: boolean
+) {
+ const allowedSides = getAllowedSides( sides );
+
+ let modifiedSides: ( keyof BoxControlValue )[] = [];
+ switch ( side ) {
+ case 'all':
+ modifiedSides = [ 'top', 'bottom', 'left', 'right' ];
+ break;
+ case 'horizontal':
+ modifiedSides = [ 'left', 'right' ];
+ break;
+ case 'vertical':
+ modifiedSides = [ 'top', 'bottom' ];
+ break;
+ default:
+ modifiedSides = [ side ];
+ }
+
+ if ( isAlt ) {
+ switch ( side ) {
+ case 'top':
+ modifiedSides.push( 'bottom' );
+ break;
+ case 'bottom':
+ modifiedSides.push( 'top' );
+ break;
+ case 'left':
+ modifiedSides.push( 'left' );
+ break;
+ case 'right':
+ modifiedSides.push( 'right' );
+ break;
+ }
+ }
+
+ return modifiedSides.filter( ( s ) => allowedSides.has( s ) );
+}
+
+export default function BoxInputControl( {
+ __next40pxDefaultSize,
+ onChange = noop,
+ onFocus = noop,
+ values,
+ selectedUnits,
+ setSelectedUnits,
+ sides,
+ side,
+ ...props
+}: BoxControlInputControlProps ) {
+ const defaultValuesToModify = getSidesToModify( side, sides );
+
+ const handleOnFocus = ( event: React.FocusEvent< HTMLInputElement > ) => {
+ onFocus( event, { side } );
+ };
+
+ const handleOnChange = ( nextValues: BoxControlValue ) => {
+ onChange( nextValues );
+ };
+
+ const handleOnValueChange = (
+ next?: string,
+ extra?: { event: React.SyntheticEvent< Element, Event > }
+ ) => {
+ const nextValues = { ...values };
+ const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) );
+ const nextValue = isNumeric ? next : undefined;
+ const modifiedSides = getSidesToModify(
+ side,
+ sides,
+ /**
+ * Supports changing pair sides. For example, holding the ALT key
+ * when changing the TOP will also update BOTTOM.
+ */
+ // @ts-expect-error - TODO: event.altKey is only present when the change event was
+ // triggered by a keyboard event. Should this feature be implemented differently so
+ // it also works with drag events?
+ !! extra?.event.altKey
+ );
+
+ modifiedSides.forEach( ( modifiedSide ) => {
+ nextValues[ modifiedSide ] = nextValue;
+ } );
+
+ handleOnChange( nextValues );
+ };
+
+ const handleOnUnitChange = ( next?: string ) => {
+ const newUnits = { ...selectedUnits };
+ defaultValuesToModify.forEach( ( modifiedSide ) => {
+ newUnits[ modifiedSide ] = next;
+ } );
+ setSelectedUnits( newUnits );
+ };
+
+ const mergedValue = getMergedValue( values, defaultValuesToModify );
+ const hasValues = isValuesDefined( values );
+ const isMixed =
+ hasValues &&
+ defaultValuesToModify.length > 1 &&
+ isValueMixed( values, defaultValuesToModify );
+ const [ parsedQuantity, parsedUnit ] =
+ parseQuantityAndUnitFromRawValue( mergedValue );
+ const computedUnit = hasValues
+ ? parsedUnit
+ : selectedUnits[ defaultValuesToModify[ 0 ] ];
+ const generatedId = useInstanceId( BoxInputControl, 'box-control-input' );
+ const inputId = [ generatedId, side ].join( '-' );
+ const isMixedUnit =
+ defaultValuesToModify.length > 1 &&
+ mergedValue === undefined &&
+ defaultValuesToModify.some(
+ ( s ) => selectedUnits[ s ] !== computedUnit
+ );
+ const usedValue =
+ mergedValue === undefined && computedUnit ? computedUnit : mergedValue;
+ const mixedPlaceholder = isMixed || isMixedUnit ? __( 'Mixed' ) : undefined;
+
+ return (
+
+
+
+
+
+
+ {
+ handleOnValueChange(
+ newValue !== undefined
+ ? [ newValue, computedUnit ].join( '' )
+ : undefined
+ );
+ } }
+ min={ 0 }
+ max={ CUSTOM_VALUE_SETTINGS[ computedUnit ?? 'px' ]?.max ?? 10 }
+ step={
+ CUSTOM_VALUE_SETTINGS[ computedUnit ?? 'px' ]?.step ?? 0.1
+ }
+ value={ parsedQuantity ?? 0 }
+ withInputField={ false }
+ />
+
+ );
+}
diff --git a/packages/components/src/box-control/input-controls.tsx b/packages/components/src/box-control/input-controls.tsx
deleted file mode 100644
index 8f4518d717dbed..00000000000000
--- a/packages/components/src/box-control/input-controls.tsx
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { useInstanceId } from '@wordpress/compose';
-/**
- * Internal dependencies
- */
-import Tooltip from '../tooltip';
-import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
-import { ALL_SIDES, CUSTOM_VALUE_SETTINGS, LABELS } from './utils';
-import {
- FlexedBoxControlIcon,
- FlexedRangeControl,
- InputWrapper,
- StyledUnitControl,
-} from './styles/box-control-styles';
-import type { BoxControlInputControlProps, BoxControlValue } from './types';
-
-const noop = () => {};
-
-export default function BoxInputControls( {
- __next40pxDefaultSize,
- onChange = noop,
- onFocus = noop,
- values,
- selectedUnits,
- setSelectedUnits,
- sides,
- ...props
-}: BoxControlInputControlProps ) {
- const generatedId = useInstanceId( BoxInputControls, 'box-control-input' );
-
- const createHandleOnFocus =
- ( side: keyof BoxControlValue ) =>
- ( event: React.FocusEvent< HTMLInputElement > ) => {
- onFocus( event, { side } );
- };
-
- const handleOnChange = ( nextValues: BoxControlValue ) => {
- onChange( nextValues );
- };
-
- const handleOnValueChange = (
- side: keyof BoxControlValue,
- next?: string,
- extra?: { event: React.SyntheticEvent< Element, Event > }
- ) => {
- const nextValues = { ...values };
- const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) );
- const nextValue = isNumeric ? next : undefined;
-
- nextValues[ side ] = nextValue;
-
- /**
- * Supports changing pair sides. For example, holding the ALT key
- * when changing the TOP will also update BOTTOM.
- */
- // @ts-expect-error - TODO: event.altKey is only present when the change event was
- // triggered by a keyboard event. Should this feature be implemented differently so
- // it also works with drag events?
- if ( extra?.event.altKey ) {
- switch ( side ) {
- case 'top':
- nextValues.bottom = nextValue;
- break;
- case 'bottom':
- nextValues.top = nextValue;
- break;
- case 'left':
- nextValues.right = nextValue;
- break;
- case 'right':
- nextValues.left = nextValue;
- break;
- }
- }
-
- handleOnChange( nextValues );
- };
-
- const createHandleOnUnitChange =
- ( side: keyof BoxControlValue ) => ( next?: string ) => {
- const newUnits = { ...selectedUnits };
- newUnits[ side ] = next;
- setSelectedUnits( newUnits );
- };
-
- // Filter sides if custom configuration provided, maintaining default order.
- const filteredSides = sides?.length
- ? ALL_SIDES.filter( ( side ) => sides.includes( side ) )
- : ALL_SIDES;
-
- return (
- <>
- { filteredSides.map( ( side ) => {
- const [ parsedQuantity, parsedUnit ] =
- parseQuantityAndUnitFromRawValue( values[ side ] );
-
- const computedUnit = values[ side ]
- ? parsedUnit
- : selectedUnits[ side ];
-
- const inputId = [ generatedId, side ].join( '-' );
-
- return (
-
-
-
-
- handleOnValueChange(
- side,
- nextValue,
- extra
- )
- }
- onUnitChange={ createHandleOnUnitChange(
- side
- ) }
- onFocus={ createHandleOnFocus( side ) }
- label={ LABELS[ side ] }
- hideLabelFromVision
- />
-
-
- {
- handleOnValueChange(
- side,
- newValue !== undefined
- ? [ newValue, computedUnit ].join( '' )
- : undefined
- );
- } }
- min={ 0 }
- max={
- CUSTOM_VALUE_SETTINGS[ computedUnit ?? 'px' ]
- ?.max ?? 10
- }
- step={
- CUSTOM_VALUE_SETTINGS[ computedUnit ?? 'px' ]
- ?.step ?? 0.1
- }
- value={ parsedQuantity ?? 0 }
- withInputField={ false }
- />
-
- );
- } ) }
- >
- );
-}
diff --git a/packages/components/src/box-control/types.ts b/packages/components/src/box-control/types.ts
index 16b69dfe70a64a..73de68d1bd513a 100644
--- a/packages/components/src/box-control/types.ts
+++ b/packages/components/src/box-control/types.ts
@@ -110,8 +110,16 @@ export type BoxControlInputControlProps = UnitControlPassthroughProps & {
) => void;
selectedUnits: BoxControlValue;
setSelectedUnits: React.Dispatch< React.SetStateAction< BoxControlValue > >;
- sides: BoxControlProps[ 'sides' ];
values: BoxControlValue;
+ /**
+ * Collection of sides to allow control of. If omitted or empty, all sides will be available.
+ */
+ sides: BoxControlProps[ 'sides' ];
+ /**
+ * Side represents the current side being rendered by the input.
+ * It can be a concrete side like: left, right, top, bottom or a combined one like: horizontal, vertical.
+ */
+ side: keyof typeof LABELS;
};
export type BoxControlIconProps = {
diff --git a/packages/components/src/box-control/utils.ts b/packages/components/src/box-control/utils.ts
index 73c7f4a6a46cfb..111451790e35d5 100644
--- a/packages/components/src/box-control/utils.ts
+++ b/packages/components/src/box-control/utils.ts
@@ -6,12 +6,13 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import type {
+ BoxControlInputControlProps,
BoxControlProps,
BoxControlValue,
CustomValueUnits,
} from './types';
+import deprecated from '@wordpress/deprecated';
export const CUSTOM_VALUE_SETTINGS: CustomValueUnits = {
px: { max: 300, step: 1 },
@@ -50,7 +51,6 @@ export const LABELS = {
bottom: __( 'Bottom side' ),
left: __( 'Left side' ),
right: __( 'Right side' ),
- mixed: __( 'Mixed' ),
vertical: __( 'Top and bottom sides' ),
horizontal: __( 'Left and right sides' ),
};
@@ -82,56 +82,46 @@ function mode< T >( arr: T[] ) {
}
/**
- * Gets the 'all' input value and unit from values data.
+ * Gets the merged input value and unit from values data.
*
* @param values Box values.
- * @param selectedUnits Box units.
* @param availableSides Available box sides to evaluate.
*
* @return A value + unit for the 'all' input.
*/
-export function getAllValue(
+export function getMergedValue(
values: BoxControlValue = {},
- selectedUnits?: BoxControlValue,
availableSides: BoxControlProps[ 'sides' ] = ALL_SIDES
) {
const sides = normalizeSides( availableSides );
- const parsedQuantitiesAndUnits = sides.map( ( side ) =>
- parseQuantityAndUnitFromRawValue( values[ side ] )
- );
- const allParsedQuantities = parsedQuantitiesAndUnits.map(
- ( value ) => value[ 0 ] ?? ''
- );
- const allParsedUnits = parsedQuantitiesAndUnits.map(
- ( value ) => value[ 1 ]
- );
-
- const commonQuantity = allParsedQuantities.every(
- ( v ) => v === allParsedQuantities[ 0 ]
- )
- ? allParsedQuantities[ 0 ]
- : '';
-
- /**
- * The typeof === 'number' check is important. On reset actions, the incoming value
- * may be null or an empty string.
- *
- * Also, the value may also be zero (0), which is considered a valid unit value.
- *
- * typeof === 'number' is more specific for these cases, rather than relying on a
- * simple truthy check.
- */
- let commonUnit;
- if ( typeof commonQuantity === 'number' ) {
- commonUnit = mode( allParsedUnits );
- } else {
- // Set meaningful unit selection if no commonQuantity and user has previously
- // selected units without assigning values while controls were unlinked.
- commonUnit =
- getAllUnitFallback( selectedUnits ) ?? mode( allParsedUnits );
+ if (
+ sides.every(
+ ( side: keyof BoxControlValue ) =>
+ values[ side ] === values[ sides[ 0 ] ]
+ )
+ ) {
+ return values[ sides[ 0 ] ];
}
- return [ commonQuantity, commonUnit ].join( '' );
+ return undefined;
+}
+
+/**
+ * Checks if the values are mixed.
+ *
+ * @param values Box values.
+ * @param availableSides Available box sides to evaluate.
+ * @return Whether the values are mixed.
+ */
+export function isValueMixed(
+ values: BoxControlValue = {},
+ availableSides: BoxControlProps[ 'sides' ] = ALL_SIDES
+) {
+ const sides = normalizeSides( availableSides );
+ return sides.some(
+ ( side: keyof BoxControlValue ) =>
+ values[ side ] !== values[ sides[ 0 ] ]
+ );
}
/**
@@ -150,26 +140,6 @@ export function getAllUnitFallback( selectedUnits?: BoxControlValue ) {
return mode( filteredUnits );
}
-/**
- * Checks to determine if values are mixed.
- *
- * @param values Box values.
- * @param selectedUnits Box units.
- * @param sides Available box sides to evaluate.
- *
- * @return Whether values are mixed.
- */
-export function isValuesMixed(
- values: BoxControlValue = {},
- selectedUnits?: BoxControlValue,
- sides: BoxControlProps[ 'sides' ] = ALL_SIDES
-) {
- const allValue = getAllValue( values, selectedUnits, sides );
- const isMixed = isNaN( parseFloat( allValue ) );
-
- return isMixed;
-}
-
/**
* Checks to determine if values are defined.
*
@@ -239,6 +209,8 @@ export function normalizeSides( sides: BoxControlProps[ 'sides' ] ) {
* Applies a value to an object representing top, right, bottom and left sides
* while taking into account any custom side configuration.
*
+ * @deprecated
+ *
* @param currentValues The current values for each side.
* @param newValue The value to apply to the sides object.
* @param sides Array defining valid sides.
@@ -250,6 +222,10 @@ export function applyValueToSides(
newValue?: string,
sides?: BoxControlProps[ 'sides' ]
): BoxControlValue {
+ deprecated( 'applyValueToSides', {
+ since: '6.8',
+ version: '7.0',
+ } );
const newValues = { ...currentValues };
if ( sides?.length ) {
@@ -270,3 +246,29 @@ export function applyValueToSides(
return newValues;
}
+
+/**
+ * Return the allowed sides based on the sides configuration.
+ *
+ * @param sides Sides configuration.
+ * @return Allowed sides.
+ */
+export function getAllowedSides(
+ sides: BoxControlInputControlProps[ 'sides' ]
+) {
+ const allowedSides: Set< keyof BoxControlValue > = new Set(
+ ! sides ? ALL_SIDES : []
+ );
+ sides?.forEach( ( allowedSide ) => {
+ if ( allowedSide === 'vertical' ) {
+ allowedSides.add( 'top' );
+ allowedSides.add( 'bottom' );
+ } else if ( allowedSide === 'horizontal' ) {
+ allowedSides.add( 'right' );
+ allowedSides.add( 'left' );
+ } else {
+ allowedSides.add( allowedSide );
+ }
+ } );
+ return allowedSides;
+}