@uiw/color-convert
Version:
Color Convert
444 lines (437 loc) • 10.6 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
var RGB_MAX = 255;
var HUE_MAX = 360;
var SV_MAX = 100;
/**
* ```js
* rgbaToHsva({ r: 255, g: 255, b: 255, a: 1 }) //=> { h: 0, s: 0, v: 100, a: 1 }
* ```
*/
export var rgbaToHsva = _ref => {
var {
r,
g,
b,
a
} = _ref;
var max = Math.max(r, g, b);
var delta = max - Math.min(r, g, b);
// prettier-ignore
var hh = delta ? max === r ? (g - b) / delta : max === g ? 2 + (b - r) / delta : 4 + (r - g) / delta : 0;
return {
h: 60 * (hh < 0 ? hh + 6 : hh),
s: max ? delta / max * SV_MAX : 0,
v: max / RGB_MAX * SV_MAX,
a
};
};
export var hsvaToHslString = hsva => {
var {
h,
s,
l
} = hsvaToHsla(hsva);
// return `hsl(${h}, ${s}%, ${l}%)`;
return "hsl(" + h + ", " + Math.round(s) + "%, " + Math.round(l) + "%)";
};
export var hsvaToHsvString = _ref2 => {
var {
h,
s,
v
} = _ref2;
return "hsv(" + h + ", " + s + "%, " + v + "%)";
};
export var hsvaToHsvaString = _ref3 => {
var {
h,
s,
v,
a
} = _ref3;
return "hsva(" + h + ", " + s + "%, " + v + "%, " + a + ")";
};
export var hsvaToHslaString = hsva => {
var {
h,
s,
l,
a
} = hsvaToHsla(hsva);
return "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")";
};
export var hslStringToHsla = str => {
var [h, s, l, a] = (str.match(/\d+/g) || []).map(Number);
return {
h,
s,
l,
a
};
};
export var hslaStringToHsva = hslString => {
var matcher = /hsla?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
var match = matcher.exec(hslString);
if (!match) return {
h: 0,
s: 0,
v: 0,
a: 1
};
return hslaToHsva({
h: parseHue(match[1], match[2]),
s: Number(match[3]),
l: Number(match[4]),
a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? 100 : 1)
});
};
export var hslStringToHsva = hslaStringToHsva;
export var hslaToHsva = _ref4 => {
var {
h,
s,
l,
a
} = _ref4;
s *= (l < 50 ? l : SV_MAX - l) / SV_MAX;
return {
h: h,
s: s > 0 ? 2 * s / (l + s) * SV_MAX : 0,
v: l + s,
a
};
};
export var hsvaToHsla = _ref5 => {
var {
h,
s,
v,
a
} = _ref5;
var hh = (200 - s) * v / SV_MAX;
return {
h,
s: hh > 0 && hh < 200 ? s * v / SV_MAX / (hh <= SV_MAX ? hh : 200 - hh) * SV_MAX : 0,
l: hh / 2,
a
};
};
export var hsvaStringToHsva = hsvString => {
var matcher = /hsva?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
var match = matcher.exec(hsvString);
if (!match) return {
h: 0,
s: 0,
v: 0,
a: 1
};
return {
h: parseHue(match[1], match[2]),
s: Number(match[3]),
v: Number(match[4]),
a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? SV_MAX : 1)
};
};
/**
* Valid CSS <angle> units.
* https://developer.mozilla.org/en-US/docs/Web/CSS/angle
*/
var angleUnits = {
grad: HUE_MAX / 400,
turn: HUE_MAX,
rad: HUE_MAX / (Math.PI * 2)
};
export var parseHue = function parseHue(value, unit) {
if (unit === void 0) {
unit = 'deg';
}
return Number(value) * (angleUnits[unit] || 1);
};
export var hsvStringToHsva = hsvaStringToHsva;
export var rgbaStringToHsva = rgbaString => {
var matcher = /rgba?\(?\s*(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
var match = matcher.exec(rgbaString);
if (!match) return {
h: 0,
s: 0,
v: 0,
a: 1
};
return rgbaToHsva({
r: Number(match[1]) / (match[2] ? SV_MAX / RGB_MAX : 1),
g: Number(match[3]) / (match[4] ? SV_MAX / RGB_MAX : 1),
b: Number(match[5]) / (match[6] ? SV_MAX / RGB_MAX : 1),
a: match[7] === undefined ? 1 : Number(match[7]) / (match[8] ? SV_MAX : 1)
});
};
export var rgbStringToHsva = rgbaStringToHsva;
/** Converts an RGBA color plus alpha transparency to hex */
export var rgbaToHex = _ref6 => {
var {
r,
g,
b
} = _ref6;
var bin = r << 16 | g << 8 | b;
return "#" + (h => new Array(7 - h.length).join('0') + h)(bin.toString(16));
};
export var rgbaToHexa = _ref7 => {
var {
r,
g,
b,
a
} = _ref7;
var alpha = typeof a === 'number' && (a * 255 | 1 << 8).toString(16).slice(1);
return "" + rgbaToHex({
r,
g,
b,
a
}) + (alpha ? alpha : '');
};
export var hexToHsva = hex => rgbaToHsva(hexToRgba(hex));
export var hexToRgba = hex => {
var htemp = hex.replace('#', '');
if (/^#?/.test(hex) && htemp.length === 3) {
hex = "#" + htemp.charAt(0) + htemp.charAt(0) + htemp.charAt(1) + htemp.charAt(1) + htemp.charAt(2) + htemp.charAt(2);
}
var reg = new RegExp("[A-Za-z0-9]{2}", 'g');
var [r, g, b = 0, a] = hex.match(reg).map(v => parseInt(v, 16));
return {
r,
g,
b,
a: (a != null ? a : 255) / RGB_MAX
};
};
/**
* Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV
* @param color HSVA color as an array [0-360, 0-1, 0-1, 0-1]
*/
export var hsvaToRgba = _ref8 => {
var {
h,
s,
v,
a
} = _ref8;
var _h = h / 60,
_s = s / SV_MAX,
_v = v / SV_MAX,
hi = Math.floor(_h) % 6;
var f = _h - Math.floor(_h),
_p = RGB_MAX * _v * (1 - _s),
_q = RGB_MAX * _v * (1 - _s * f),
_t = RGB_MAX * _v * (1 - _s * (1 - f));
_v *= RGB_MAX;
var rgba = {};
switch (hi) {
case 0:
rgba.r = _v;
rgba.g = _t;
rgba.b = _p;
break;
case 1:
rgba.r = _q;
rgba.g = _v;
rgba.b = _p;
break;
case 2:
rgba.r = _p;
rgba.g = _v;
rgba.b = _t;
break;
case 3:
rgba.r = _p;
rgba.g = _q;
rgba.b = _v;
break;
case 4:
rgba.r = _t;
rgba.g = _p;
rgba.b = _v;
break;
case 5:
rgba.r = _v;
rgba.g = _p;
rgba.b = _q;
break;
}
rgba.r = Math.round(rgba.r);
rgba.g = Math.round(rgba.g);
rgba.b = Math.round(rgba.b);
return _extends({}, rgba, {
a
});
};
export var hsvaToRgbString = hsva => {
var {
r,
g,
b
} = hsvaToRgba(hsva);
return "rgb(" + r + ", " + g + ", " + b + ")";
};
export var hsvaToRgbaString = hsva => {
var {
r,
g,
b,
a
} = hsvaToRgba(hsva);
return "rgba(" + r + ", " + g + ", " + b + ", " + a + ")";
};
export var rgbaToRgb = _ref9 => {
var {
r,
g,
b
} = _ref9;
return {
r,
g,
b
};
};
export var hslaToHsl = _ref10 => {
var {
h,
s,
l
} = _ref10;
return {
h,
s,
l
};
};
export var hsvaToHex = hsva => rgbaToHex(hsvaToRgba(hsva));
export var hsvaToHexa = hsva => rgbaToHexa(hsvaToRgba(hsva));
export var hsvaToHsv = _ref11 => {
var {
h,
s,
v
} = _ref11;
return {
h,
s,
v
};
};
export var hexToXY = hex => rgbToXY(rgbaToRgb(hexToRgba(hex)));
export var xyToHex = xy => rgbaToHex(_extends({}, xyToRgb(xy), {
a: 255
}));
/**
* Converts XY to RGB. Based on formula from https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/
* @param color XY color and brightness as an array [0-1, 0-1, 0-1]
*/
export var xyToRgb = _ref12 => {
var {
x,
y,
bri = 255
} = _ref12;
var red = x * 3.2406255 + y * -1.537208 + bri * -0.4986286;
var green = x * -0.9689307 + y * 1.8757561 + bri * 0.0415175;
var blue = x * 0.0557101 + y * -0.2040211 + bri * 1.0569959;
var translate = function translate(color) {
return color <= 0.0031308 ? 12.92 * color : 1.055 * Math.pow(color, 1 / 2.4) - 0.055;
};
return {
r: Math.round(255 * translate(red)),
g: Math.round(255 * translate(green)),
b: Math.round(255 * translate(blue))
};
};
/**
* Converts RGB to XY. Based on formula from https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/
* @param color RGB color as an array [0-255, 0-255, 0-255]
*/
export var rgbToXY = _ref13 => {
var {
r,
g,
b
} = _ref13;
var translateColor = function translateColor(color) {
return color <= 0.04045 ? color / 12.92 : Math.pow((color + 0.055) / 1.055, 2.4);
};
var red = translateColor(r / 255);
var green = translateColor(g / 255);
var blue = translateColor(b / 255);
var xyz = {};
xyz.x = red * 0.4124 + green * 0.3576 + blue * 0.1805;
xyz.y = red * 0.2126 + green * 0.7152 + blue * 0.0722;
xyz.bri = red * 0.0193 + green * 0.1192 + blue * 0.9505;
return xyz;
};
export var color = str => {
var rgb;
var hsl;
var hsv;
var rgba;
var hsla;
var hsva;
var xy;
var hex;
var hexa;
if (typeof str === 'string' && validHex(str)) {
hsva = hexToHsva(str);
hex = str;
} else if (typeof str !== 'string') {
hsva = str;
}
if (hsva) {
hsv = hsvaToHsv(hsva);
hsla = hsvaToHsla(hsva);
rgba = hsvaToRgba(hsva);
hexa = rgbaToHexa(rgba);
hex = hsvaToHex(hsva);
hsl = hslaToHsl(hsla);
rgb = rgbaToRgb(rgba);
xy = rgbToXY(rgb);
}
return {
rgb,
hsl,
hsv,
rgba,
hsla,
hsva,
hex,
hexa,
xy
};
};
export var getContrastingColor = str => {
if (!str) {
return '#ffffff';
}
var col = color(str);
var yiq = (col.rgb.r * 299 + col.rgb.g * 587 + col.rgb.b * 114) / 1000;
return yiq >= 128 ? '#000000' : '#ffffff';
};
export var equalColorObjects = (first, second) => {
if (first === second) return true;
for (var prop in first) {
// The following allows for a type-safe calling of this function (first & second have to be HSL, HSV, or RGB)
// with type-unsafe iterating over object keys. TS does not allow this without an index (`[key: string]: number`)
// on an object to define how iteration is normally done. To ensure extra keys are not allowed on our types,
// we must cast our object to unknown (as RGB demands `r` be a key, while `Record<string, x>` does not care if
// there is or not), and then as a type TS can iterate over.
if (first[prop] !== second[prop]) return false;
}
return true;
};
export var equalColorString = (first, second) => {
return first.replace(/\s/g, '') === second.replace(/\s/g, '');
};
export var equalHex = (first, second) => {
if (first.toLowerCase() === second.toLowerCase()) return true;
// To compare colors like `#FFF` and `ffffff` we convert them into RGB objects
return equalColorObjects(hexToRgba(first), hexToRgba(second));
};
export var validHex = hex => /^#?([A-Fa-f0-9]{3,4}){1,2}$/.test(hex);