polychrome
Version:
A small library for parsing and manipulating colors
459 lines (380 loc) • 12.8 kB
JavaScript
var patterns = {
hex: /^#(?:[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
rgb: /^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),?\s*(\d?\.?\d+)?\)$/,
hsl: /^hsla?\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,?\s*(\d?\.?\d+)?\)$/,
};
var patterns$1 = Object.assign({}, patterns,
{asList: Object.keys(patterns).map(function (name) { return ({ name: name, regex: patterns[name] }); })});
var hexToRgb = function (red, green, blue) {
return [red, green, blue].map(function (value) { return parseInt(value, 16); });
};
var rgbToHex = function (red, green, blue) {
return [red, green, blue].map(function (value) { return ("0" + (parseInt(value, 10).toString(16))).toUpperCase().slice(-2); });
};
var rgbToHsl = function (red, green, blue, alpha) {
if ( alpha === void 0 ) alpha = 1;
var ref = [red, green, blue].map(function (value) { return value / 255; });
var r = ref[0];
var g = ref[1];
var b = ref[2];
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var delta = max - min;
var l = (max + min) / 2;
if (max === min) {
return [0, 0, Math.round(l * 100), alpha];
}
var s = l < 0.5 ? delta / (max + min) : delta / (2.0 - max - min);
var ref$1 = [r, g, b]
.map(function (channel) { return (((max - channel) / 6) + (delta / 2)) / delta; });
var rDelta = ref$1[0];
var gDelta = ref$1[1];
var bDelta = ref$1[2];
var h = 0;
switch (max) {
case r: h = bDelta - gDelta; break;
case g: h = (1 / 3) + rDelta - bDelta; break;
case b: h = (2 / 3) + gDelta - rDelta; break;
}
if (h < 0) { h += 1; }
if (h > 1) { h -= 1; }
return [ h * 360, s * 100, l * 100, alpha ].map(function (value) { return Math.round(value); });
};
var hslToRgb = function (hue, saturation, lightness, alpha) {
if ( alpha === void 0 ) alpha = 1;
var ref = [hue / 360, saturation / 100, lightness / 100];
var h = ref[0];
var s = ref[1];
var l = ref[2];
if (s == 0) {
return [l, l, l].map(function (v) { return Math.round(v * 255); }).concat(alpha);
}
var hue2rgb = function (p, q, t) {
if (t < 0) { t += 1; }
if (t > 1) { t -= 1; }
if ((t * 6) < 1) { return p + (q - p) * 6 * t; }
if ((t * 2) < 1) { return q; }
if ((t * 3) < 2) { return p + (q - p) * ((2/3) - t) * 6; }
return p;
};
var q = l < 0.5 ? l * (1 + s) : (l + s) - (l * s);
var p = 2 * l - q;
var r = hue2rgb(p, q, h + 1/3);
var g = hue2rgb(p, q, h);
var b = hue2rgb(p, q, h - 1/3);
return [r, g, b].map(function (v) { return Math.round(v * 255); }).concat(alpha);
};
var getAlphaModifier = function (alpha, percentage) {
var ratio = percentage / 100;
return alpha ? alpha * ratio : ratio;
};
var getPercentageModifier = function (value, percentage) {
return value ? value * (percentage / 100) : percentage;
};
var setLightness = function (color, percentage) {
if ( percentage === void 0 ) percentage = null;
if (percentage === null) { return color; }
var h = color.h;
var s = color.s;
var a = color.a;
var l = (percentage > 100) ? 100 : ((percentage < 0) ? 0 : percentage);
return make.fromHsl(h, s, l, a);
};
var lighten = function (color, percentage) {
if ( percentage === void 0 ) percentage = 10;
var l = color.l;
return setLightness(color, l + getPercentageModifier(l, percentage));
};
var darken = function (color, percentage) {
if ( percentage === void 0 ) percentage = 10;
var l = color.l;
return setLightness(color, l - getPercentageModifier(l, percentage));
};
var setAlpha = function (color, percentage) {
if ( percentage === void 0 ) percentage = null;
if (percentage === null) { return color; }
var h = color.h;
var s = color.s;
var l = color.l;
var a = (percentage > 100) ? 1 : ((percentage < 0) ? 0 : percentage / 100);
return make.fromHsl(h, s, l, a);
};
var fadeIn = function (color, percentage) {
if ( percentage === void 0 ) percentage = 50;
var a = color.a;
return setAlpha(color, (a + getAlphaModifier(a, percentage)) * 100);
};
var fadeOut = function (color, percentage) {
if ( percentage === void 0 ) percentage = 50;
var a = color.a;
return setAlpha(color, (a - getAlphaModifier(a, percentage)) * 100);
};
var setSaturation = function (color, percentage) {
if ( percentage === void 0 ) percentage = null;
if (percentage === null) { return color; }
var h = color.h;
var l = color.l;
var a = color.a;
var s = (percentage > 100) ? 100 : ((percentage < 0) ? 0 : percentage);
return make.fromHsl(h, s, l, a);
};
var saturate = function (color, percentage) {
if ( percentage === void 0 ) percentage = 10;
var s = color.s;
return setSaturation(color, s + getPercentageModifier(s, percentage));
};
var desaturate = function (color, percentage) {
if ( percentage === void 0 ) percentage = 10;
var s = color.s;
return setSaturation(color, s - getPercentageModifier(s, percentage));
};
var grayscale = function (color) { return setSaturation(color, 0); };
var setHue = function (color, hueValue) {
if (hueValue === null) { return color; }
var s = color.s;
var l = color.l;
var a = color.a;
return make.fromHsl(hueValue, s, l, a);
};
var spin = function (color, degrees) {
if ( degrees === void 0 ) degrees = 0;
var h = color.h;
var newHue = h + degrees;
return setHue(color, (newHue + 360) % 360);
};
var complimentary = function (color) { return spin(color, 180); };
var mix = function (color, secondColor) {
var mixingColor = (typeof secondColor === "string") ? parse(secondColor) : secondColor;
var r = color.r;
var g = color.g;
var b = color.b;
var a = color.a;
return make.fromRgb.apply(make, Object.keys({ r: r, g: g, b: b, a: a })
.map(function (channel) { return (color[channel] + mixingColor[channel]) / 2; })
);
};
var tint = function (color) { return mix(color, "#FFF"); };
var shade = function (color) { return mix(color, "#000"); };
/**
* https://en.m.wikipedia.org/wiki/Relative_luminance
*/
var relativeLuminance = function (color) {
var ref = [color.r, color.g, color.b].map(function (channel) {
var sRGB = channel / 255;
return sRGB <= 0.03928
? sRGB / 12.92
: Math.pow((sRGB + 0.055) / 1.055, 2.4);
});
var R = ref[0];
var G = ref[1];
var B = ref[2];
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
};
var contrast = function (color, dark, light) {
if ( dark === void 0 ) dark = parse("#000");
if ( light === void 0 ) light = parse("#FFF");
var baseColor = parse(color);
var darkColor = typeof dark === "string" ? parse(dark) : dark;
var lightColor = typeof light === "string" ? parse(light) : light;
var contrastColor = baseColor.luma < 128 ? lightColor : darkColor;
/**
* Calculate relative luminance and find ratio
* https://www.w3.org/TR/2016/NOTE-WCAG20-TECHS-20161007/G18
*/
var rLums = [ relativeLuminance(baseColor), relativeLuminance(contrastColor)];
var contrastRatio = (Math.max.apply(Math, rLums) + 0.05) / (Math.min.apply(Math, rLums) + 0.05);
if (contrastRatio >= 4.5) {
return contrastColor;
}
// TODO: Check to see either possible contrast color has a ratio of >= 4.5,
// regardless of the baseColor luma value
if (darkColor.l === 0 || lightColor.l === 100) {
return contrastColor;
}
return contrast(baseColor, darken(darkColor, 1), lighten(lightColor,1));
};
/**
* Based on the Y value in https://en.m.wikipedia.org/wiki/YIQ
* Used to calculate perceived brightness in accessibility W3C spec
* https://www.w3.org/TR/AERT#color-contrast
*/
var luma = function (r, g, b) { return (299 * r + 587 * g + 114 * b) / 1000; };
var makeColor = function (properties) {
var rHex = properties.rHex;
var gHex = properties.gHex;
var bHex = properties.bHex;
var r = properties.r;
var g = properties.g;
var b = properties.b;
var h = properties.h;
var s = properties.s;
var l = properties.l;
var a = properties.a; if ( a === void 0 ) a = 1;
var color = Object.assign({}, properties,
{hex: function hex() {
return ("#" + rHex + gHex + bHex);
},
rgb: function rgb() {
return (a < 1)
? ("rgba(" + r + "," + g + "," + b + "," + a + ")")
: ("rgb(" + r + "," + g + "," + b + ")")
;
},
hsl: function hsl() {
return (a < 1)
? ("hsla(" + h + "," + s + "%," + l + "%," + a + ")")
: ("hsl(" + h + "," + s + "%," + l + "%)")
;
},
luma: luma(r, g, b)});
return Object.assign({}, color,
{isDark: function isDark() {
return color.luma < 128;
},
isLight: function isLight() {
return color.luma >= 128;
},
setHue: function setHue$1(degrees) {
return setHue(color, degrees);
},
spin: function spin$1(degrees) {
return spin(color, degrees);
},
complimentary: function complimentary$1() {
return complimentary(color);
},
setLightness: function setLightness$1(percentage) {
return setLightness(color, percentage);
},
darken: function darken$1(percentage) {
return darken(color, percentage);
},
lighten: function lighten$1(percentage) {
return lighten(color, percentage);
},
setAlpha: function setAlpha$1(percentage) {
return setAlpha(color, percentage);
},
fadeIn: function fadeIn$1(percentage) {
return fadeIn(color, percentage);
},
fadeOut: function fadeOut$1(percentage) {
return fadeOut(color, percentage);
},
contrast: function contrast$1(dark, light) {
return contrast(color, dark, light);
},
setSaturation: function setSaturation$1(percentage) {
return setSaturation(color, percentage);
},
saturate: function saturate$1(percentage) {
return saturate(color, percentage);
},
desaturate: function desaturate$1(percentage) {
return desaturate(color, percentage);
},
grayscale: function grayscale$1() {
return grayscale(color);
},
mix: function mix$1(mixColor) {
return mix(color, mixColor);
},
shade: function shade$1() {
return shade(color);
},
tint: function tint$1() {
return tint(color);
}});
};
var make = {
fromHex: function fromHex(rHex, gHex, bHex) {
var ref = hexToRgb(rHex, gHex, bHex);
var r = ref[0];
var g = ref[1];
var b = ref[2];
var ref$1 = rgbToHsl(r, g, b);
var h = ref$1[0];
var s = ref$1[1];
var l = ref$1[2];
var a = ref$1[3];
return makeColor({
rHex: rHex, gHex: gHex, bHex: bHex,
r: r, g: g, b: b,
h: h, s: s, l: l, a: a,
});
},
fromRgb: function fromRgb(r, g, b, a) {
if ( a === void 0 ) a = 1;
var ref = rgbToHex(r, g, b);
var rHex = ref[0];
var gHex = ref[1];
var bHex = ref[2];
var ref$1 = rgbToHsl(r, g, b);
var h = ref$1[0];
var s = ref$1[1];
var l = ref$1[2];
return makeColor({
rHex: rHex, gHex: gHex, bHex: bHex,
r: r, g: g, b: b,
h: h, s: s, l: l, a: a,
});
},
fromHsl: function fromHsl(h, s, l, a) {
if ( a === void 0 ) a = 1;
var ref = hslToRgb(h, s, l);
var r = ref[0];
var g = ref[1];
var b = ref[2];
var ref$1 = rgbToHex(r, g, b);
var rHex = ref$1[0];
var gHex = ref$1[1];
var bHex = ref$1[2];
return makeColor({
rHex: rHex, gHex: gHex, bHex: bHex,
r: r, g: g, b: b,
h: h, s: s, l: l, a: a,
});
}
};
var parsers = {
hex: function hex(hexString) {
var hex = hexString.replace("#", "");
if (hex.length < 6) {
hex = hex.split("").map(function (char) { return char.concat(char); }).join("");
}
return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)];
},
rgb: function rgb(rgbString) {
var ref = rgbString.match(patterns$1.rgb).slice(1);
var r = ref[0];
var g = ref[1];
var b = ref[2];
var a = ref[3]; if ( a === void 0 ) a = 1;
return [parseInt(r), parseInt(g), parseInt(b), parseFloat(a)];
},
hsl: function hsl(hslString) {
var ref = hslString.match(patterns$1.hsl).slice(1);
var h = ref[0];
var s = ref[1];
var l = ref[2];
var a = ref[3]; if ( a === void 0 ) a = 1;
return [parseInt(h), parseInt(s), parseInt(l), parseFloat(a)];
},
};
var parse = function (color) {
if (!color) { return make.fromRgb(0,0,0); }
if (typeof color !== "string") { return color; }
var matchingPatterns = patterns$1.asList
.filter(function (pattern) { return color.match(pattern.regex); });
if (!matchingPatterns.length) {
throw new Error(("No matching color patterns found for " + color));
}
return matchingPatterns
.reduce(function (matches, ref) {
var name = ref.name;
return make[("from" + (name.charAt(0).toUpperCase()) + (name.slice(1)))].apply(make, parsers[name](color));
}, {})
;
};
export default parse;
//# sourceMappingURL=polychrome.es.js.map