style-value-types
Version:
Parsers, transformers and tests for special value types, eg: %, hex codes etc.
222 lines (209 loc) • 6.95 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const clamp = (min, max) => (v) => Math.max(Math.min(v, max), min);
const sanitize = (v) => (v % 1 ? Number(v.toFixed(5)) : v);
const floatRegex = /(-)?([\d]*\.?[\d])+/g;
const colorRegex = /(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))/gi;
const singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
function isString(v) {
return typeof v === 'string';
}
const number = {
test: (v) => typeof v === 'number',
parse: parseFloat,
transform: (v) => v,
};
const alpha = Object.assign(Object.assign({}, number), { transform: clamp(0, 1) });
const scale = Object.assign(Object.assign({}, number), { default: 1 });
const createUnitType = (unit) => ({
test: (v) => isString(v) && v.endsWith(unit) && v.split(' ').length === 1,
parse: parseFloat,
transform: (v) => `${v}${unit}`,
});
const degrees = createUnitType('deg');
const percent = createUnitType('%');
const px = createUnitType('px');
const vh = createUnitType('vh');
const vw = createUnitType('vw');
const progressPercentage = Object.assign(Object.assign({}, percent), { parse: (v) => percent.parse(v) / 100, transform: (v) => percent.transform(v * 100) });
const isColorString = (type, testProp) => (v) => {
return Boolean((isString(v) && singleColorRegex.test(v) && v.startsWith(type)) ||
(testProp && Object.prototype.hasOwnProperty.call(v, testProp)));
};
const splitColor = (aName, bName, cName) => (v) => {
if (!isString(v))
return v;
const [a, b, c, alpha] = v.match(floatRegex);
return {
[aName]: parseFloat(a),
[bName]: parseFloat(b),
[cName]: parseFloat(c),
alpha: alpha !== undefined ? parseFloat(alpha) : 1,
};
};
const hsla = {
test: isColorString('hsl', 'hue'),
parse: splitColor('hue', 'saturation', 'lightness'),
transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
return ('hsla(' +
Math.round(hue) +
', ' +
percent.transform(sanitize(saturation)) +
', ' +
percent.transform(sanitize(lightness)) +
', ' +
sanitize(alpha.transform(alpha$1)) +
')');
},
};
const clampRgbUnit = clamp(0, 255);
const rgbUnit = Object.assign(Object.assign({}, number), { transform: (v) => Math.round(clampRgbUnit(v)) });
const rgba = {
test: isColorString('rgb', 'red'),
parse: splitColor('red', 'green', 'blue'),
transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => 'rgba(' +
rgbUnit.transform(red) +
', ' +
rgbUnit.transform(green) +
', ' +
rgbUnit.transform(blue) +
', ' +
sanitize(alpha.transform(alpha$1)) +
')',
};
function parseHex(v) {
let r = '';
let g = '';
let b = '';
let a = '';
if (v.length > 5) {
r = v.substr(1, 2);
g = v.substr(3, 2);
b = v.substr(5, 2);
a = v.substr(7, 2);
}
else {
r = v.substr(1, 1);
g = v.substr(2, 1);
b = v.substr(3, 1);
a = v.substr(4, 1);
r += r;
g += g;
b += b;
a += a;
}
return {
red: parseInt(r, 16),
green: parseInt(g, 16),
blue: parseInt(b, 16),
alpha: a ? parseInt(a, 16) / 255 : 1,
};
}
const hex = {
test: isColorString('#'),
parse: parseHex,
transform: rgba.transform,
};
const color = {
test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
parse: (v) => {
if (rgba.test(v)) {
return rgba.parse(v);
}
else if (hsla.test(v)) {
return hsla.parse(v);
}
else {
return hex.parse(v);
}
},
transform: (v) => {
return isString(v)
? v
: v.hasOwnProperty('red')
? rgba.transform(v)
: hsla.transform(v);
},
};
const colorToken = '${c}';
const numberToken = '${n}';
function test(v) {
var _a, _b, _c, _d;
return (isNaN(v) &&
isString(v) &&
((_b = (_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = v.match(colorRegex)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) > 0);
}
function analyse(v) {
if (typeof v === 'number')
v = `${v}`;
const values = [];
let numColors = 0;
const colors = v.match(colorRegex);
if (colors) {
numColors = colors.length;
v = v.replace(colorRegex, colorToken);
values.push(...colors.map(color.parse));
}
const numbers = v.match(floatRegex);
if (numbers) {
v = v.replace(floatRegex, numberToken);
values.push(...numbers.map(number.parse));
}
return { values, numColors, tokenised: v };
}
function parse(v) {
return analyse(v).values;
}
function createTransformer(v) {
const { values, numColors, tokenised } = analyse(v);
const numValues = values.length;
return (v) => {
let output = tokenised;
for (let i = 0; i < numValues; i++) {
output = output.replace(i < numColors ? colorToken : numberToken, i < numColors ? color.transform(v[i]) : sanitize(v[i]));
}
return output;
};
}
const convertNumbersToZero = (v) => typeof v === 'number' ? 0 : v;
function getAnimatableNone(v) {
const parsed = parse(v);
const transformer = createTransformer(v);
return transformer(parsed.map(convertNumbersToZero));
}
const complex = { test, parse, createTransformer, getAnimatableNone };
const maxDefaults = new Set(['brightness', 'contrast', 'saturate', 'opacity']);
function applyDefaultFilter(v) {
let [name, value] = v.slice(0, -1).split('(');
if (name === 'drop-shadow')
return v;
const [number] = value.match(floatRegex) || [];
if (!number)
return v;
const unit = value.replace(number, '');
let defaultValue = maxDefaults.has(name) ? 1 : 0;
if (number !== value)
defaultValue *= 100;
return name + '(' + defaultValue + unit + ')';
}
const functionRegex = /([a-z-]*)\(.*?\)/g;
const filter = Object.assign(Object.assign({}, complex), { getAnimatableNone: (v) => {
const functions = v.match(functionRegex);
return functions ? functions.map(applyDefaultFilter).join(' ') : v;
} });
exports.alpha = alpha;
exports.color = color;
exports.complex = complex;
exports.degrees = degrees;
exports.filter = filter;
exports.hex = hex;
exports.hsla = hsla;
exports.number = number;
exports.percent = percent;
exports.progressPercentage = progressPercentage;
exports.px = px;
exports.rgbUnit = rgbUnit;
exports.rgba = rgba;
exports.scale = scale;
exports.vh = vh;
exports.vw = vw;