@wordpress/block-editor
Version:
120 lines (105 loc) • 3.47 kB
JavaScript
/**
* WordPress dependencies
*/
import { __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue } from '@wordpress/components';
/**
* Gets the (non-undefined) item with the highest occurrence within an array
* Based in part on: https://stackoverflow.com/a/20762713
*
* Undefined values are always sorted to the end by `sort`, so this function
* returns the first element, to always prioritize real values over undefined
* values.
*
* See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description
*
* @param {Array<any>} inputArray Array of items to check.
* @return {any} The item with the most occurrences.
*/
export function mode( inputArray ) {
const arr = [ ...inputArray ];
return arr
.sort(
( a, b ) =>
inputArray.filter( ( v ) => v === b ).length -
inputArray.filter( ( v ) => v === a ).length
)
.shift();
}
/**
* Returns the most common CSS unit from the current CSS unit selections.
*
* - If a single flat border radius is set, its unit will be used
* - If individual corner selections, the most common of those will be used
* - Failing any unit selections a default of 'px' is returned.
*
* @param {Object} selectedUnits Unit selections for flat radius & each corner.
* @return {string} Most common CSS unit from current selections. Default: `px`.
*/
export function getAllUnit( selectedUnits = {} ) {
const { flat, ...cornerUnits } = selectedUnits;
return (
flat || mode( Object.values( cornerUnits ).filter( Boolean ) ) || 'px'
);
}
/**
* Gets the 'all' input value and unit from values data.
*
* @param {Object|string} values Radius values.
* @return {string} A value + unit for the 'all' input.
*/
export function getAllValue( values = {} ) {
/**
* Border radius support was originally a single pixel value.
*
* To maintain backwards compatibility treat this case as the all value.
*/
if ( typeof values === 'string' ) {
return values;
}
const parsedQuantitiesAndUnits = Object.values( values ).map( ( value ) =>
parseQuantityAndUnitFromRawValue( value )
);
const allValues = parsedQuantitiesAndUnits.map(
( value ) => value[ 0 ] ?? ''
);
const allUnits = parsedQuantitiesAndUnits.map( ( value ) => value[ 1 ] );
const value = allValues.every( ( v ) => v === allValues[ 0 ] )
? allValues[ 0 ]
: '';
const unit = mode( allUnits );
const allValue = value === 0 || value ? `${ value }${ unit }` : undefined;
return allValue;
}
/**
* Checks to determine if values are mixed.
*
* @param {Object} values Radius values.
* @return {boolean} Whether values are mixed.
*/
export function hasMixedValues( values = {} ) {
const allValue = getAllValue( values );
const isMixed =
typeof values === 'string' ? false : isNaN( parseFloat( allValue ) );
return isMixed;
}
/**
* Checks to determine if values are defined.
*
* @param {Object} values Radius values.
* @return {boolean} Whether values are mixed.
*/
export function hasDefinedValues( values ) {
if ( ! values ) {
return false;
}
// A string value represents a shorthand value.
if ( typeof values === 'string' ) {
return true;
}
// An object represents longhand border radius values, if any are set
// flag values as being defined.
const filteredValues = Object.values( values ).filter( ( value ) => {
return !! value || value === 0;
} );
return !! filteredValues.length;
}