UNPKG

@wordpress/block-editor

Version:
146 lines (145 loc) 5.36 kB
// packages/block-editor/src/components/font-sizes/fluid-utils.js var DEFAULT_MAXIMUM_VIEWPORT_WIDTH = "1600px"; var DEFAULT_MINIMUM_VIEWPORT_WIDTH = "320px"; var DEFAULT_SCALE_FACTOR = 1; var DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MIN = 0.25; var DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MAX = 0.75; var DEFAULT_MINIMUM_FONT_SIZE_LIMIT = "14px"; function getComputedFluidTypographyValue({ minimumFontSize, maximumFontSize, fontSize, minimumViewportWidth = DEFAULT_MINIMUM_VIEWPORT_WIDTH, maximumViewportWidth = DEFAULT_MAXIMUM_VIEWPORT_WIDTH, scaleFactor = DEFAULT_SCALE_FACTOR, minimumFontSizeLimit }) { minimumFontSizeLimit = !!getTypographyValueAndUnit(minimumFontSizeLimit) ? minimumFontSizeLimit : DEFAULT_MINIMUM_FONT_SIZE_LIMIT; if (fontSize) { const fontSizeParsed = getTypographyValueAndUnit(fontSize); if (!fontSizeParsed?.unit) { return null; } const minimumFontSizeLimitParsed = getTypographyValueAndUnit( minimumFontSizeLimit, { coerceTo: fontSizeParsed.unit } ); if (!!minimumFontSizeLimitParsed?.value && !minimumFontSize && !maximumFontSize) { if (fontSizeParsed?.value <= minimumFontSizeLimitParsed?.value) { return null; } } if (!maximumFontSize) { maximumFontSize = `${fontSizeParsed.value}${fontSizeParsed.unit}`; } if (!minimumFontSize) { const fontSizeValueInPx = fontSizeParsed.unit === "px" ? fontSizeParsed.value : fontSizeParsed.value * 16; const minimumFontSizeFactor = Math.min( Math.max( 1 - 0.075 * Math.log2(fontSizeValueInPx), DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MIN ), DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MAX ); const calculatedMinimumFontSize = roundToPrecision( fontSizeParsed.value * minimumFontSizeFactor, 3 ); if (!!minimumFontSizeLimitParsed?.value && calculatedMinimumFontSize < minimumFontSizeLimitParsed?.value) { minimumFontSize = `${minimumFontSizeLimitParsed.value}${minimumFontSizeLimitParsed.unit}`; } else { minimumFontSize = `${calculatedMinimumFontSize}${fontSizeParsed.unit}`; } } } const minimumFontSizeParsed = getTypographyValueAndUnit(minimumFontSize); const fontSizeUnit = minimumFontSizeParsed?.unit || "rem"; const maximumFontSizeParsed = getTypographyValueAndUnit(maximumFontSize, { coerceTo: fontSizeUnit }); if (!minimumFontSizeParsed || !maximumFontSizeParsed) { return null; } const minimumFontSizeRem = getTypographyValueAndUnit(minimumFontSize, { coerceTo: "rem" }); const maximumViewportWidthParsed = getTypographyValueAndUnit( maximumViewportWidth, { coerceTo: fontSizeUnit } ); const minimumViewportWidthParsed = getTypographyValueAndUnit( minimumViewportWidth, { coerceTo: fontSizeUnit } ); if (!maximumViewportWidthParsed || !minimumViewportWidthParsed || !minimumFontSizeRem) { return null; } const linearDenominator = maximumViewportWidthParsed.value - minimumViewportWidthParsed.value; if (!linearDenominator) { return null; } const minViewportWidthOffsetValue = roundToPrecision( minimumViewportWidthParsed.value / 100, 3 ); const viewportWidthOffset = roundToPrecision(minViewportWidthOffsetValue, 3) + fontSizeUnit; const linearFactor = 100 * ((maximumFontSizeParsed.value - minimumFontSizeParsed.value) / linearDenominator); const linearFactorScaled = roundToPrecision( (linearFactor || 1) * scaleFactor, 3 ); const fluidTargetFontSize = `${minimumFontSizeRem.value}${minimumFontSizeRem.unit} + ((1vw - ${viewportWidthOffset}) * ${linearFactorScaled})`; return `clamp(${minimumFontSize}, ${fluidTargetFontSize}, ${maximumFontSize})`; } function getTypographyValueAndUnit(rawValue, options = {}) { if (typeof rawValue !== "string" && typeof rawValue !== "number") { return null; } if (isFinite(rawValue)) { rawValue = `${rawValue}px`; } const { coerceTo, rootSizeValue, acceptableUnits } = { coerceTo: "", // Default browser font size. Later we could inject some JS to compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`. rootSizeValue: 16, acceptableUnits: ["rem", "px", "em"], ...options }; const acceptableUnitsGroup = acceptableUnits?.join("|"); const regexUnits = new RegExp( `^(\\d*\\.?\\d+)(${acceptableUnitsGroup}){1,1}$` ); const matches = rawValue.match(regexUnits); if (!matches || matches.length < 3) { return null; } let [, value, unit] = matches; let returnValue = parseFloat(value); if ("px" === coerceTo && ("em" === unit || "rem" === unit)) { returnValue = returnValue * rootSizeValue; unit = coerceTo; } if ("px" === unit && ("em" === coerceTo || "rem" === coerceTo)) { returnValue = returnValue / rootSizeValue; unit = coerceTo; } if (("em" === coerceTo || "rem" === coerceTo) && ("em" === unit || "rem" === unit)) { unit = coerceTo; } return { value: roundToPrecision(returnValue, 3), unit }; } function roundToPrecision(value, digits = 3) { const base = Math.pow(10, digits); return Number.isFinite(value) ? parseFloat(Math.round(value * base) / base) : void 0; } export { getComputedFluidTypographyValue, getTypographyValueAndUnit, roundToPrecision }; //# sourceMappingURL=fluid-utils.js.map