@wordpress/components
Version:
UI components for WordPress.
328 lines (292 loc) • 12.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DEFAULT_UNIT = exports.CSS_UNITS = exports.ALL_CSS_UNITS = void 0;
exports.filterUnitsWithSettings = filterUnitsWithSettings;
exports.getAccessibleLabelForUnit = getAccessibleLabelForUnit;
exports.getParsedQuantityAndUnit = getParsedQuantityAndUnit;
exports.getUnitsWithCurrentUnit = getUnitsWithCurrentUnit;
exports.getValidParsedQuantityAndUnit = getValidParsedQuantityAndUnit;
exports.hasUnits = hasUnits;
exports.parseQuantityAndUnitFromRawValue = parseQuantityAndUnitFromRawValue;
exports.useCustomUnits = void 0;
var _i18n = require("@wordpress/i18n");
var _element = require("@wordpress/element");
/**
* WordPress dependencies
*/
const isWeb = _element.Platform.OS === 'web';
const allUnits = {
px: {
value: 'px',
label: isWeb ? 'px' : (0, _i18n.__)('Pixels (px)'),
a11yLabel: (0, _i18n.__)('Pixels (px)'),
step: 1
},
'%': {
value: '%',
label: isWeb ? '%' : (0, _i18n.__)('Percentage (%)'),
a11yLabel: (0, _i18n.__)('Percent (%)'),
step: 0.1
},
em: {
value: 'em',
label: isWeb ? 'em' : (0, _i18n.__)('Relative to parent font size (em)'),
a11yLabel: (0, _i18n._x)('ems', 'Relative to parent font size (em)'),
step: 0.01
},
rem: {
value: 'rem',
label: isWeb ? 'rem' : (0, _i18n.__)('Relative to root font size (rem)'),
a11yLabel: (0, _i18n._x)('rems', 'Relative to root font size (rem)'),
step: 0.01
},
vw: {
value: 'vw',
label: isWeb ? 'vw' : (0, _i18n.__)('Viewport width (vw)'),
a11yLabel: (0, _i18n.__)('Viewport width (vw)'),
step: 0.1
},
vh: {
value: 'vh',
label: isWeb ? 'vh' : (0, _i18n.__)('Viewport height (vh)'),
a11yLabel: (0, _i18n.__)('Viewport height (vh)'),
step: 0.1
},
vmin: {
value: 'vmin',
label: isWeb ? 'vmin' : (0, _i18n.__)('Viewport smallest dimension (vmin)'),
a11yLabel: (0, _i18n.__)('Viewport smallest dimension (vmin)'),
step: 0.1
},
vmax: {
value: 'vmax',
label: isWeb ? 'vmax' : (0, _i18n.__)('Viewport largest dimension (vmax)'),
a11yLabel: (0, _i18n.__)('Viewport largest dimension (vmax)'),
step: 0.1
},
ch: {
value: 'ch',
label: isWeb ? 'ch' : (0, _i18n.__)('Width of the zero (0) character (ch)'),
a11yLabel: (0, _i18n.__)('Width of the zero (0) character (ch)'),
step: 0.01
},
ex: {
value: 'ex',
label: isWeb ? 'ex' : (0, _i18n.__)('x-height of the font (ex)'),
a11yLabel: (0, _i18n.__)('x-height of the font (ex)'),
step: 0.01
},
cm: {
value: 'cm',
label: isWeb ? 'cm' : (0, _i18n.__)('Centimeters (cm)'),
a11yLabel: (0, _i18n.__)('Centimeters (cm)'),
step: 0.001
},
mm: {
value: 'mm',
label: isWeb ? 'mm' : (0, _i18n.__)('Millimeters (mm)'),
a11yLabel: (0, _i18n.__)('Millimeters (mm)'),
step: 0.1
},
in: {
value: 'in',
label: isWeb ? 'in' : (0, _i18n.__)('Inches (in)'),
a11yLabel: (0, _i18n.__)('Inches (in)'),
step: 0.001
},
pc: {
value: 'pc',
label: isWeb ? 'pc' : (0, _i18n.__)('Picas (pc)'),
a11yLabel: (0, _i18n.__)('Picas (pc)'),
step: 1
},
pt: {
value: 'pt',
label: isWeb ? 'pt' : (0, _i18n.__)('Points (pt)'),
a11yLabel: (0, _i18n.__)('Points (pt)'),
step: 1
}
};
/**
* An array of all available CSS length units.
*/
const ALL_CSS_UNITS = Object.values(allUnits);
/**
* Units of measurements. `a11yLabel` is used by screenreaders.
*/
exports.ALL_CSS_UNITS = ALL_CSS_UNITS;
const CSS_UNITS = [allUnits.px, allUnits['%'], allUnits.em, allUnits.rem, allUnits.vw, allUnits.vh];
exports.CSS_UNITS = CSS_UNITS;
const DEFAULT_UNIT = allUnits.px;
/**
* Handles legacy value + unit handling.
* This component use to manage both incoming value and units separately.
*
* Moving forward, ideally the value should be a string that contains both
* the value and unit, example: '10px'
*
* @param rawValue The raw value as a string (may or may not contain the unit)
* @param fallbackUnit The unit used as a fallback, if not unit is detected in the `value`
* @param allowedUnits Units to derive from.
* @return The extracted quantity and unit. The quantity can be `undefined` in case the raw value
* could not be parsed to a number correctly. The unit can be `undefined` in case the unit parse
* from the raw value could not be matched against the list of allowed units.
*/
exports.DEFAULT_UNIT = DEFAULT_UNIT;
function getParsedQuantityAndUnit(rawValue, fallbackUnit, allowedUnits) {
const initialValue = fallbackUnit ? `${rawValue !== null && rawValue !== void 0 ? rawValue : ''}${fallbackUnit}` : rawValue;
return parseQuantityAndUnitFromRawValue(initialValue, allowedUnits);
}
/**
* Checks if units are defined.
*
* @param units List of units.
* @return Whether the list actually contains any units.
*/
function hasUnits(units) {
// Although the `isArray` check shouldn't be necessary (given the signature of
// this typed function), it's better to stay on the side of caution, since
// this function may be called from un-typed environments.
return Array.isArray(units) && !!units.length;
}
/**
* Parses a quantity and unit from a raw string value, given a list of allowed
* units and otherwise falling back to the default unit.
*
* @param rawValue The raw value as a string (may or may not contain the unit)
* @param allowedUnits Units to derive from.
* @return The extracted quantity and unit. The quantity can be `undefined` in case the raw value
* could not be parsed to a number correctly. The unit can be `undefined` in case the unit parsed
* from the raw value could not be matched against the list of allowed units.
*/
function parseQuantityAndUnitFromRawValue(rawValue) {
var _trimmedValue, _unitMatch$;
let allowedUnits = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ALL_CSS_UNITS;
let trimmedValue;
let quantityToReturn;
if (typeof rawValue !== 'undefined' || rawValue === null) {
trimmedValue = `${rawValue}`.trim();
const parsedQuantity = parseFloat(trimmedValue);
quantityToReturn = !isFinite(parsedQuantity) ? undefined : parsedQuantity;
}
const unitMatch = (_trimmedValue = trimmedValue) === null || _trimmedValue === void 0 ? void 0 : _trimmedValue.match(/[\d.\-\+]*\s*(.*)/);
const matchedUnit = unitMatch === null || unitMatch === void 0 ? void 0 : (_unitMatch$ = unitMatch[1]) === null || _unitMatch$ === void 0 ? void 0 : _unitMatch$.toLowerCase();
let unitToReturn;
if (hasUnits(allowedUnits)) {
const match = allowedUnits.find(item => item.value === matchedUnit);
unitToReturn = match === null || match === void 0 ? void 0 : match.value;
} else {
unitToReturn = DEFAULT_UNIT.value;
}
return [quantityToReturn, unitToReturn];
}
/**
* Parses quantity and unit from a raw value. Validates parsed value, using fallback
* value if invalid.
*
* @param rawValue The next value.
* @param allowedUnits Units to derive from.
* @param fallbackQuantity The fallback quantity, used in case it's not possible to parse a valid quantity from the raw value.
* @param fallbackUnit The fallback unit, used in case it's not possible to parse a valid unit from the raw value.
* @return The extracted quantity and unit. The quantity can be `undefined` in case the raw value
* could not be parsed to a number correctly, and the `fallbackQuantity` was also `undefined`. The
* unit can be `undefined` only if the unit parsed from the raw value could not be matched against
* the list of allowed units, the `fallbackQuantity` is also `undefined` and the list of
* `allowedUnits` is passed empty.
*/
function getValidParsedQuantityAndUnit(rawValue, allowedUnits, fallbackQuantity, fallbackUnit) {
const [parsedQuantity, parsedUnit] = parseQuantityAndUnitFromRawValue(rawValue, allowedUnits); // The parsed value from `parseQuantityAndUnitFromRawValue` should now be
// either a real number or undefined. If undefined, use the fallback value.
const quantityToReturn = parsedQuantity !== null && parsedQuantity !== void 0 ? parsedQuantity : fallbackQuantity; // If no unit is parsed from the raw value, or if the fallback unit is not
// defined, use the first value from the list of allowed units as fallback.
let unitToReturn = parsedUnit || fallbackUnit;
if (!unitToReturn && hasUnits(allowedUnits)) {
unitToReturn = allowedUnits[0].value;
}
return [quantityToReturn, unitToReturn];
}
/**
* Takes a unit value and finds the matching accessibility label for the
* unit abbreviation.
*
* @param unit Unit value (example: `px`)
* @return a11y label for the unit abbreviation
*/
function getAccessibleLabelForUnit(unit) {
const match = ALL_CSS_UNITS.find(item => item.value === unit);
return match !== null && match !== void 0 && match.a11yLabel ? match === null || match === void 0 ? void 0 : match.a11yLabel : match === null || match === void 0 ? void 0 : match.value;
}
/**
* Filters available units based on values defined a list of allowed unit values.
*
* @param allowedUnitValues Collection of allowed unit value strings.
* @param availableUnits Collection of available unit objects.
* @return Filtered units.
*/
function filterUnitsWithSettings() {
let allowedUnitValues = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
let availableUnits = arguments.length > 1 ? arguments[1] : undefined;
// Although the `isArray` check shouldn't be necessary (given the signature of
// this typed function), it's better to stay on the side of caution, since
// this function may be called from un-typed environments.
return Array.isArray(availableUnits) ? availableUnits.filter(unit => allowedUnitValues.includes(unit.value)) : [];
}
/**
* Custom hook to retrieve and consolidate units setting from add_theme_support().
* TODO: ideally this hook shouldn't be needed
* https://github.com/WordPress/gutenberg/pull/31822#discussion_r633280823
*
* @param args An object containing units, settingPath & defaultUnits.
* @param args.units Collection of all potentially available units.
* @param args.availableUnits Collection of unit value strings for filtering available units.
* @param args.defaultValues Collection of default values for defined units. Example: `{ px: 350, em: 15 }`.
*
* @return Filtered list of units, with their default values updated following the `defaultValues`
* argument's property.
*/
const useCustomUnits = _ref => {
let {
units = ALL_CSS_UNITS,
availableUnits = [],
defaultValues
} = _ref;
const customUnitsToReturn = filterUnitsWithSettings(availableUnits, units);
if (defaultValues) {
customUnitsToReturn.forEach((unit, i) => {
if (defaultValues[unit.value]) {
const [parsedDefaultValue] = parseQuantityAndUnitFromRawValue(defaultValues[unit.value]);
customUnitsToReturn[i].default = parsedDefaultValue;
}
});
}
return customUnitsToReturn;
};
/**
* Get available units with the unit for the currently selected value
* prepended if it is not available in the list of units.
*
* This is useful to ensure that the current value's unit is always
* accurately displayed in the UI, even if the intention is to hide
* the availability of that unit.
*
* @param rawValue Selected value to parse.
* @param legacyUnit Legacy unit value, if rawValue needs it appended.
* @param units List of available units.
*
* @return A collection of units containing the unit for the current value.
*/
exports.useCustomUnits = useCustomUnits;
function getUnitsWithCurrentUnit(rawValue, legacyUnit) {
let units = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ALL_CSS_UNITS;
const unitsToReturn = Array.isArray(units) ? [...units] : [];
const [, currentUnit] = getParsedQuantityAndUnit(rawValue, legacyUnit, ALL_CSS_UNITS);
if (currentUnit && !unitsToReturn.some(unit => unit.value === currentUnit)) {
if (allUnits[currentUnit]) {
unitsToReturn.unshift(allUnits[currentUnit]);
}
}
return unitsToReturn;
}
//# sourceMappingURL=utils.js.map