UNPKG

polychrome

Version:

A small library for parsing and manipulating colors

459 lines (380 loc) 12.8 kB
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