Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BoxControl: Refactor and unify the different sides implementation #67626

Merged
merged 11 commits into from
Dec 10, 2024
Prev Previous commit
Next Next commit
Simplify merging logic
  • Loading branch information
youknowriad committed Dec 9, 2024
commit e06583a66606816d9e2e7d49a76ceeeacffd6a9a
4 changes: 2 additions & 2 deletions packages/components/src/box-control/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import {
DEFAULT_VALUES,
getInitialSide,
isValuesMixed,
isValueMixed,
isValuesDefined,
getAllowedSides,
} from './utils';
Expand Down Expand Up @@ -95,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' ] >(
Expand Down
12 changes: 4 additions & 8 deletions packages/components/src/box-control/input-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import {
CUSTOM_VALUE_SETTINGS,
getAllowedSides,
getAllValue,
getMergedValue,
isValueMixed,
isValuesDefined,
isValuesMixed,
LABELS,
} from './utils';
import {
Expand Down Expand Up @@ -125,16 +125,12 @@ export default function BoxInputControl( {
setSelectedUnits( newUnits );
};

const mergedValue = getAllValue(
values,
selectedUnits,
defaultValuesToModify
);
const mergedValue = getMergedValue( values, defaultValuesToModify );
const hasValues = isValuesDefined( values );
const isMixed =
hasValues &&
defaultValuesToModify.length > 1 &&
isValuesMixed( values, selectedUnits, defaultValuesToModify );
isValueMixed( values, defaultValuesToModify );
const mixedPlaceholder = isMixed ? __( 'Mixed' ) : undefined;
const [ parsedQuantity, parsedUnit ] =
parseQuantityAndUnitFromRawValue( mergedValue );
Expand Down
87 changes: 28 additions & 59 deletions packages/components/src/box-control/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import type {
BoxControlInputControlProps,
BoxControlProps,
Expand Down Expand Up @@ -83,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 ] ]
);
}

/**
Expand All @@ -151,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.
*
Expand Down