vuetify
Version:
Vue Material Component Framework
234 lines (230 loc) • 6.08 kB
JavaScript
// Utilities
import { consoleWarn } from "./console.mjs";
import { chunk, padEnd } from "./helpers.mjs";
import * as sRGB from "./color/transformSRGB.mjs";
import * as CIELAB from "./color/transformCIELAB.mjs"; // Types
export function isCssColor(color) {
return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
}
export function parseColor(color) {
if (typeof color === 'number') {
if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
// int can't have opacity
consoleWarn(`'${color}' is not a valid hex color`);
}
return {
r: (color & 0xFF0000) >> 16,
g: (color & 0xFF00) >> 8,
b: color & 0xFF
};
} else if (typeof color === 'string') {
let hex = color.startsWith('#') ? color.slice(1) : color;
if ([3, 4].includes(hex.length)) {
hex = hex.split('').map(char => char + char).join('');
} else if (![6, 8].includes(hex.length)) {
consoleWarn(`'${color}' is not a valid hex(a) color`);
}
const int = parseInt(hex, 16);
if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
consoleWarn(`'${color}' is not a valid hex(a) color`);
}
return HexToRGB(hex);
} else {
throw new TypeError(`Colors can only be numbers or strings, recieved ${color == null ? color : color.constructor.name} instead`);
}
}
export function RGBToInt(color) {
return (color.r << 16) + (color.g << 8) + color.b;
}
export function classToHex(color, colors, currentTheme) {
const [colorName, colorModifier] = color.toString().trim().replace('-', '').split(' ', 2);
let hexColor = '';
if (colorName && colorName in colors) {
if (colorModifier && colorModifier in colors[colorName]) {
hexColor = colors[colorName][colorModifier];
} else if ('base' in colors[colorName]) {
hexColor = colors[colorName].base;
}
} else if (colorName && colorName in currentTheme) {
hexColor = currentTheme[colorName];
}
return hexColor;
}
/** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
export function HSVtoRGB(hsva) {
const {
h,
s,
v,
a
} = hsva;
const f = n => {
const k = (n + h / 60) % 6;
return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
};
const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
return {
r: rgb[0],
g: rgb[1],
b: rgb[2],
a
};
}
/** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
export function RGBtoHSV(rgba) {
if (!rgba) return {
h: 0,
s: 1,
v: 1,
a: 1
};
const r = rgba.r / 255;
const g = rgba.g / 255;
const b = rgba.b / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0;
if (max !== min) {
if (max === r) {
h = 60 * (0 + (g - b) / (max - min));
} else if (max === g) {
h = 60 * (2 + (b - r) / (max - min));
} else if (max === b) {
h = 60 * (4 + (r - g) / (max - min));
}
}
if (h < 0) h = h + 360;
const s = max === 0 ? 0 : (max - min) / max;
const hsv = [h, s, max];
return {
h: hsv[0],
s: hsv[1],
v: hsv[2],
a: rgba.a
};
}
export function HSVtoHSL(hsva) {
const {
h,
s,
v,
a
} = hsva;
const l = v - v * s / 2;
const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
return {
h,
s: sprime,
l,
a
};
}
export function HSLtoHSV(hsl) {
const {
h,
s,
l,
a
} = hsl;
const v = l + s * Math.min(l, 1 - l);
const sprime = v === 0 ? 0 : 2 - 2 * l / v;
return {
h,
s: sprime,
v,
a
};
}
export function RGBtoCSS(_ref) {
let {
r,
g,
b,
a
} = _ref;
return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
}
export function HSVtoCSS(hsva) {
return RGBtoCSS(HSVtoRGB(hsva));
}
function toHex(v) {
const h = Math.round(v).toString(16);
return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
}
export function RGBtoHex(_ref2) {
let {
r,
g,
b,
a
} = _ref2;
return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
}
export function HexToRGB(hex) {
hex = parseHex(hex);
let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
a = a === undefined ? a : a / 255;
return {
r,
g,
b,
a
};
}
export function HexToHSV(hex) {
const rgb = HexToRGB(hex);
return RGBtoHSV(rgb);
}
export function HSVtoHex(hsva) {
return RGBtoHex(HSVtoRGB(hsva));
}
export function parseHex(hex) {
if (hex.startsWith('#')) {
hex = hex.slice(1);
}
hex = hex.replace(/([^0-9a-f])/gi, 'F');
if (hex.length === 3 || hex.length === 4) {
hex = hex.split('').map(x => x + x).join('');
}
if (hex.length !== 6) {
hex = padEnd(padEnd(hex, 6), 8, 'F');
}
return hex;
}
export function parseGradient(gradient, colors, currentTheme) {
return gradient.replace(/([a-z]+(\s[a-z]+-[1-5])?)(?=$|,)/gi, x => {
return classToHex(x, colors, currentTheme) || x;
}).replace(/(rgba\()#[0-9a-f]+(?=,)/gi, x => {
return 'rgba(' + Object.values(HexToRGB(parseHex(x.replace(/rgba\(/, '')))).slice(0, 3).join(',');
});
}
export function lighten(value, amount) {
const lab = CIELAB.fromXYZ(sRGB.toXYZ(value));
lab[0] = lab[0] + amount * 10;
return sRGB.fromXYZ(CIELAB.toXYZ(lab));
}
export function darken(value, amount) {
const lab = CIELAB.fromXYZ(sRGB.toXYZ(value));
lab[0] = lab[0] - amount * 10;
return sRGB.fromXYZ(CIELAB.toXYZ(lab));
}
/**
* Calculate the relative luminance of a given color
* @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
*/
export function getLuma(color) {
const rgb = parseColor(color);
return sRGB.toXYZ(rgb)[1];
}
/**
* Returns the contrast ratio (1-21) between two colors.
* @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
*/
export function getContrast(first, second) {
const l1 = getLuma(first);
const l2 = getLuma(second);
const light = Math.max(l1, l2);
const dark = Math.min(l1, l2);
return (light + 0.05) / (dark + 0.05);
}
//# sourceMappingURL=colorUtils.mjs.map