@wordpress/block-library
Version:
Block library for the WordPress editor.
177 lines (164 loc) • 5.24 kB
JavaScript
/**
* Returns a column width attribute value rounded to standard precision.
* Returns `undefined` if the value is not a valid finite number.
*
* @param {?number} value Raw value.
*
* @return {number} Value rounded to standard precision.
*/
export const toWidthPrecision = ( value ) => {
const unitlessValue = parseFloat( value );
return Number.isFinite( unitlessValue )
? parseFloat( unitlessValue.toFixed( 2 ) )
: undefined;
};
/**
* Returns an effective width for a given block. An effective width is equal to
* its attribute value if set, or a computed value assuming equal distribution.
*
* @param {WPBlock} block Block object.
* @param {number} totalBlockCount Total number of blocks in Columns.
*
* @return {number} Effective column width.
*/
export function getEffectiveColumnWidth( block, totalBlockCount ) {
const { width = 100 / totalBlockCount } = block.attributes;
return toWidthPrecision( width );
}
/**
* Returns the total width occupied by the given set of column blocks.
*
* @param {WPBlock[]} blocks Block objects.
* @param {?number} totalBlockCount Total number of blocks in Columns.
* Defaults to number of blocks passed.
*
* @return {number} Total width occupied by blocks.
*/
export function getTotalColumnsWidth(
blocks,
totalBlockCount = blocks.length
) {
return blocks.reduce(
( sum, block ) =>
sum + getEffectiveColumnWidth( block, totalBlockCount ),
0
);
}
/**
* Returns an object of `clientId` → `width` of effective column widths.
*
* @param {WPBlock[]} blocks Block objects.
* @param {?number} totalBlockCount Total number of blocks in Columns.
* Defaults to number of blocks passed.
*
* @return {Object<string,number>} Column widths.
*/
export function getColumnWidths( blocks, totalBlockCount = blocks.length ) {
return blocks.reduce( ( accumulator, block ) => {
const width = getEffectiveColumnWidth( block, totalBlockCount );
return Object.assign( accumulator, { [ block.clientId ]: width } );
}, {} );
}
/**
* Returns an object of `clientId` → `width` of column widths as redistributed
* proportional to their current widths, constrained or expanded to fit within
* the given available width.
*
* @param {WPBlock[]} blocks Block objects.
* @param {number} availableWidth Maximum width to fit within.
* @param {?number} totalBlockCount Total number of blocks in Columns.
* Defaults to number of blocks passed.
*
* @return {Object<string,number>} Redistributed column widths.
*/
export function getRedistributedColumnWidths(
blocks,
availableWidth,
totalBlockCount = blocks.length
) {
const totalWidth = getTotalColumnsWidth( blocks, totalBlockCount );
return Object.fromEntries(
Object.entries( getColumnWidths( blocks, totalBlockCount ) ).map(
( [ clientId, width ] ) => {
const newWidth = ( availableWidth * width ) / totalWidth;
return [ clientId, toWidthPrecision( newWidth ) ];
}
)
);
}
/**
* Returns true if column blocks within the provided set are assigned with
* explicit widths, or false otherwise.
*
* @param {WPBlock[]} blocks Block objects.
*
* @return {boolean} Whether columns have explicit widths.
*/
export function hasExplicitPercentColumnWidths( blocks ) {
return blocks.every( ( block ) => {
const blockWidth = block.attributes.width;
return Number.isFinite(
blockWidth?.endsWith?.( '%' )
? parseFloat( blockWidth )
: blockWidth
);
} );
}
/**
* Returns a copy of the given set of blocks with new widths assigned from the
* provided object of redistributed column widths.
*
* @param {WPBlock[]} blocks Block objects.
* @param {Object<string,number>} widths Redistributed column widths.
*
* @return {WPBlock[]} blocks Mapped block objects.
*/
export function getMappedColumnWidths( blocks, widths ) {
return blocks.map( ( block ) => ( {
...block,
attributes: {
...block.attributes,
width: `${ widths[ block.clientId ] }%`,
},
} ) );
}
/**
* Returns an array with columns widths values, parsed or no depends on `withParsing` flag.
*
* @param {WPBlock[]} blocks Block objects.
* @param {?boolean} withParsing Whether value has to be parsed.
*
* @return {Array<number,string>} Column widths.
*/
export function getWidths( blocks, withParsing = true ) {
return blocks.map( ( innerColumn ) => {
const innerColumnWidth =
innerColumn.attributes.width || 100 / blocks.length;
return withParsing ? parseFloat( innerColumnWidth ) : innerColumnWidth;
} );
}
/**
* Returns a column width with unit.
*
* @param {string} width Column width.
* @param {string} unit Column width unit.
*
* @return {string} Column width with unit.
*/
export function getWidthWithUnit( width, unit ) {
width = 0 > parseFloat( width ) ? '0' : width;
if ( isPercentageUnit( unit ) ) {
width = Math.min( width, 100 );
}
return `${ width }${ unit }`;
}
/**
* Returns a boolean whether passed unit is percentage
*
* @param {string} unit Column width unit.
*
* @return {boolean} Whether unit is '%'.
*/
export function isPercentageUnit( unit ) {
return unit === '%';
}