@wordpress/block-editor
Version:
167 lines (147 loc) • 5.03 kB
JavaScript
/**
* Internal dependencies
*/
import { getFontStylesAndWeights } from '../../utils/get-font-styles-and-weights';
/**
* Returns an object of merged font families and the font faces from the selected font family
* based on the theme.json settings object and the currently selected font family.
*
* @param {Object} settings Theme.json settings.
* @param {string} selectedFontFamily Decoded font family string.
* @return {Object} Merged font families and font faces from the selected font family.
*/
export function getMergedFontFamiliesAndFontFamilyFaces(
settings,
selectedFontFamily
) {
const fontFamiliesFromSettings = settings?.typography?.fontFamilies;
const fontFamilies = [ 'default', 'theme', 'custom' ].flatMap(
( key ) => fontFamiliesFromSettings?.[ key ] ?? []
);
const fontFamilyFaces =
fontFamilies.find(
( family ) => family.fontFamily === selectedFontFamily
)?.fontFace ?? [];
return { fontFamilies, fontFamilyFaces };
}
/**
* Returns the nearest font weight value from the available font weight list based on the new font weight.
* The nearest font weight is the one with the smallest difference from the new font weight.
*
* @param {Array} availableFontWeights Array of available font weights.
* @param {string} newFontWeightValue New font weight value.
* @return {string} Nearest font weight.
*/
export function findNearestFontWeight(
availableFontWeights,
newFontWeightValue
) {
newFontWeightValue =
'number' === typeof newFontWeightValue
? newFontWeightValue.toString()
: newFontWeightValue;
if ( ! newFontWeightValue || typeof newFontWeightValue !== 'string' ) {
return '';
}
if ( ! availableFontWeights || availableFontWeights.length === 0 ) {
return newFontWeightValue;
}
const nearestFontWeight = availableFontWeights?.reduce(
( nearest, { value: fw } ) => {
const currentDiff = Math.abs(
parseInt( fw ) - parseInt( newFontWeightValue )
);
const nearestDiff = Math.abs(
parseInt( nearest ) - parseInt( newFontWeightValue )
);
return currentDiff < nearestDiff ? fw : nearest;
},
availableFontWeights[ 0 ]?.value
);
return nearestFontWeight;
}
/**
* Returns the nearest font style based on the new font style.
* Defaults to an empty string if the new font style is not valid or available.
*
* @param {Array} availableFontStyles Array of available font weights.
* @param {string} newFontStyleValue New font style value.
* @return {string} Nearest font style or an empty string.
*/
export function findNearestFontStyle( availableFontStyles, newFontStyleValue ) {
if ( typeof newFontStyleValue !== 'string' || ! newFontStyleValue ) {
return '';
}
const validStyles = [ 'normal', 'italic', 'oblique' ];
if ( ! validStyles.includes( newFontStyleValue ) ) {
return '';
}
if (
! availableFontStyles ||
availableFontStyles.length === 0 ||
availableFontStyles.find(
( style ) => style.value === newFontStyleValue
)
) {
return newFontStyleValue;
}
if (
newFontStyleValue === 'oblique' &&
! availableFontStyles.find( ( style ) => style.value === 'oblique' )
) {
return 'italic';
}
return '';
}
/**
* Returns the nearest font style and weight based on the available font family faces and the new font style and weight.
*
* @param {Array} fontFamilyFaces Array of available font family faces.
* @param {string} fontStyle New font style. Defaults to previous value.
* @param {string} fontWeight New font weight. Defaults to previous value.
* @return {Object} Nearest font style and font weight.
*/
export function findNearestStyleAndWeight(
fontFamilyFaces,
fontStyle,
fontWeight
) {
let nearestFontStyle = fontStyle;
let nearestFontWeight = fontWeight;
const { fontStyles, fontWeights, combinedStyleAndWeightOptions } =
getFontStylesAndWeights( fontFamilyFaces );
// Check if the new font style and weight are available in the font family faces.
const hasFontStyle = fontStyles?.some(
( { value: fs } ) => fs === fontStyle
);
const hasFontWeight = fontWeights?.some(
( { value: fw } ) => fw?.toString() === fontWeight?.toString()
);
if ( ! hasFontStyle ) {
/*
* Default to italic if oblique is not available.
* Or find the nearest font style based on the nearest font weight.
*/
nearestFontStyle = fontStyle
? findNearestFontStyle( fontStyles, fontStyle )
: combinedStyleAndWeightOptions?.find(
( option ) =>
option.style.fontWeight ===
findNearestFontWeight( fontWeights, fontWeight )
)?.style?.fontStyle;
}
if ( ! hasFontWeight ) {
/*
* Find the nearest font weight based on available weights.
* Or find the nearest font weight based on the nearest font style.
*/
nearestFontWeight = fontWeight
? findNearestFontWeight( fontWeights, fontWeight )
: combinedStyleAndWeightOptions?.find(
( option ) =>
option.style.fontStyle ===
( nearestFontStyle || fontStyle )
)?.style?.fontWeight;
}
return { nearestFontStyle, nearestFontWeight };
}