UNPKG

@iomechs/rn-color-palette

Version:
546 lines (452 loc) 12.3 kB
const RGB_MAX = 255; const HUE_MAX = 360; const SV_MAX = 100; let colorsys = (module.exports = {}); colorsys.rgb2Hsl = function(r, g, b) { if (typeof r === 'object') { const args = r; r = args.r; g = args.g; b = args.b; } // It converts [0,255] format, to [0,1] r = r === RGB_MAX ? 1 : (r % RGB_MAX) / parseFloat(RGB_MAX); g = g === RGB_MAX ? 1 : (g % RGB_MAX) / parseFloat(RGB_MAX); b = b === RGB_MAX ? 1 : (b % RGB_MAX) / parseFloat(RGB_MAX); var max = Math.max(r, g, b); var min = Math.min(r, g, b); var h, s, l = (max + min) / 2; if (max === min) { h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * HUE_MAX), s: Math.round(s * SV_MAX), l: Math.round(l * SV_MAX), }; }; colorsys.rgb_to_hsl = colorsys.rgbToHsl = colorsys.rgb2Hsl; colorsys.rgb2Hsv = function(r, g, b) { try { if (typeof r === 'object') { const args = r; r = args.r; g = args.g; b = args.b; } // It converts [0,255] format, to [0,1] r = r === RGB_MAX ? 1 : (r % RGB_MAX) / parseFloat(RGB_MAX); g = g === RGB_MAX ? 1 : (g % RGB_MAX) / parseFloat(RGB_MAX); b = b === RGB_MAX ? 1 : (b % RGB_MAX) / parseFloat(RGB_MAX); var max = Math.max(r, g, b); var min = Math.min(r, g, b); var h, s, v = max; var d = max - min; s = max === 0 ? 0 : d / max; if (max === min) { h = 0; // achromatic } else { switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * HUE_MAX), s: Math.round(s * SV_MAX), v: Math.round(v * SV_MAX), }; } catch (err) { console.log(err); } }; colorsys.rgb_to_hsv = colorsys.rgbToHsv = colorsys.rgb2Hsv; colorsys.hsl2Rgb = function(h, s, l) { if (typeof h === 'object') { const args = h; h = args.h; s = args.s; l = args.l; } var r, g, b; h = _normalizeAngle(h); h = h === HUE_MAX ? 1 : (h % HUE_MAX) / parseFloat(HUE_MAX); s = s === SV_MAX ? 1 : (s % SV_MAX) / parseFloat(SV_MAX); l = l === SV_MAX ? 1 : (l % SV_MAX) / parseFloat(SV_MAX); if (s === 0) { r = g = b = l; // achromatic } else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = _hue2Rgb(p, q, h + 1 / 3); g = _hue2Rgb(p, q, h); b = _hue2Rgb(p, q, h - 1 / 3); } return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX), }; }; colorsys.hsl_to_rgb = colorsys.hslToRgb = colorsys.hsl2Rgb; colorsys.hsv2Rgb = function(h, s, v) { if (typeof h === 'object') { const args = h; h = args.h; s = args.s; v = args.v; } h = _normalizeAngle(h); h = h === HUE_MAX ? 1 : ((h % HUE_MAX) / parseFloat(HUE_MAX)) * 6; s = s === SV_MAX ? 1 : (s % SV_MAX) / parseFloat(SV_MAX); v = v === SV_MAX ? 1 : (v % SV_MAX) / parseFloat(SV_MAX); var i = Math.floor(h); var f = h - i; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); var mod = i % 6; var r = [v, q, p, p, t, v][mod]; var g = [t, v, v, q, p, p][mod]; var b = [p, p, t, v, v, q][mod]; return { r: Math.floor(r * RGB_MAX), g: Math.floor(g * RGB_MAX), b: Math.floor(b * RGB_MAX), }; }; colorsys.hsv_to_rgb = colorsys.hsv2Rgb; colorsys.hsvToRgb = colorsys.hsv2Rgb; colorsys.rgb2Hex = function(r, g, b) { if (typeof r === 'object') { const args = r; r = args.r; g = args.g; b = args.b; } r = Math.round(r).toString(16); g = Math.round(g).toString(16); b = Math.round(b).toString(16); r = r.length === 1 ? '0' + r : r; g = g.length === 1 ? '0' + g : g; b = b.length === 1 ? '0' + b : b; return '#' + r + g + b; }; colorsys.rgb_to_hex = colorsys.rgbToHex = colorsys.rgb2Hex; colorsys.hex2Rgb = function(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16), } : null; }; colorsys.hex_to_rgb = colorsys.hexToRgb = colorsys.hex2Rgb; colorsys.hsv2Hex = function(h, s, v) { try { var rgb = colorsys.hsv2Rgb(h, s, v); return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b); } catch(err) { console.log(err); } }; colorsys.hsv_to_hex = colorsys.hsv2Hex; colorsys.hsvToHex = colorsys.hsv2Hex; colorsys.hex2Hsv = function(hex) { try { var rgb = colorsys.hex2Rgb(hex); return colorsys.rgb2Hsv(rgb.r, rgb.g, rgb.b); } catch(err) { console.log(err); } }; colorsys.hex_to_hsv = colorsys.hexToHsv = colorsys.hex2Hsv; colorsys.hsl2Hex = function(h, s, l) { try { var rgb = colorsys.hsl2Rgb(h, s, l); return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b); } catch(err) { console.log(err); } }; colorsys.hsl_to_hex = colorsys.hslToHex = colorsys.hsl2Hex; colorsys.hex2Hsl = function(hex) { try { var rgb = colorsys.hex2Rgb(hex); return colorsys.rgb2Hsl(rgb.r, rgb.g, rgb.b); } catch(err) { console.log(err); } }; colorsys.hex_to_hsl = colorsys.hexToHsl = colorsys.hex2Hsl; colorsys.rgb2Cmyk = function(r, g, b) { if (typeof r === 'object') { const args = r; r = args.r; g = args.g; b = args.b; } var rprim = r / 255; var gprim = g / 255; var bprim = b / 255; var k = 1 - Math.max(rprim, gprim, bprim); var c = (1 - rprim - k) / (1 - k); var m = (1 - gprim - k) / (1 - k); var y = (1 - bprim - k) / (1 - k); return { c: c.toFixed(3), m: m.toFixed(3), y: y.toFixed(3), k: k.toFixed(3), }; }; colorsys.rgb_to_cmyk = colorsys.rgbToCmyk = colorsys.rgb2Cmyk; colorsys.cmyk2Rgb = function(c, m, y, k) { if (typeof c === 'object') { const args = c; c = args.c; m = args.m; y = args.y; k = args.k; } var r = 255 * (1 - c) * (1 - k); var g = 255 * (1 - m) * (1 - k); var b = 255 * (1 - y) * (1 - k); return { r: Math.floor(r), g: Math.floor(g), b: Math.floor(b), }; }; colorsys.cmyk_to_rgb = colorsys.cmykToRgb = colorsys.cmyk2Rgb; colorsys.hsv2Hsl = function(h, s, v) { if (typeof h === 'object') { const args = h; h = args.h; s = args.s; v = args.v; } var l = ((2 - s) * v) / 2; if (l !== 0) { if (l === SV_MAX) { s = 0; } else if (l < SV_MAX / 2) { s = (s * v) / (l * 2); } else { s = (s * v) / (2 - l * 2); } } return {h: h, s: s, l: l}; }; colorsys.hsv_to_hsl = colorsys.hsvToHsl = colorsys.hsv2Hsl; colorsys.hsl2Hsv = function(h, s, l) { if (typeof h === 'object') { const args = h; h = args.h; s = args.s; l = args.l; } s = s * (l < 50 ? l : 100 - l); return { h: h, s: Math.floor((2 * s) / (l + s)), v: Math.floor(l + s), }; }; colorsys.hsl_to_hsv = colorsys.hslToHsv = colorsys.hsl2Hsv; /** * Parses values from a string into a javascript object * e.g: hsla(140, 30%, 40%, .5) => { h: 140, s: 30, l: 40, alpha: 0.5} */ colorsys.parseCss = function(cssString) { if (cssString.indexOf('#') > -1) { return colorsys.hex2Rgb(cssString); } const prefix = cssString.split('(')[0]; const args = cssString .split('(')[1] .split(')')[0] .split(','); // Use the prefix as an array [r, g, b, a] to parse the colours return prefix.split('').reduce(function(color, param, idx) { const nextColor = color; nextColor[param] = parseFloat(args[idx]); return nextColor; }, {}); }; colorsys.parse_css = colorsys.parseCss; colorsys.stringify = function(obj) { const prefix = Object.keys(obj).join(''); const values = Object.keys(obj).map(function(key) { var val = obj[key]; if (key === 's' || key === 'v' || key === 'l') { val = val + '%'; } return val; }); return prefix + '(' + values.join(', ') + ')'; }; // Google Assistant API uses this format in SmartHome Apps. Example => 'spectrumRGB': 16711680 colorsys.hex_to_decimal = colorsys.hexToDecimal = colorsys.hex2Decimal; colorsys.hex2Decimal = function(hexColor) { return parseInt(hexColor.replace('#', ''), 16); }; colorsys.decimal_to_hex = colorsys.decimalToHex = colorsys.decimal2Hex; colorsys.decimal2Hex = function(decimalColor) { const hexInBase16 = parseInt(decimalColor).toString(16); return `#${padWithZeros(hexInBase16)}`; }; // Will return a random hex colour colorsys.random = function() { const base = '000000'; const number = Math.floor(Math.random() * 16777215).toString(16); return '#' + (base + number).substr(-6); }; colorsys.rotateHue = function(hue, amount) { if (amount === void 0) { amount = 0; } const aux = typeof hue === 'object' ? (hue.h + amount) % 360 : (hue + amount) % 360; const nextHue = aux < 0 ? 360 + aux : aux; return typeof hue === 'object' ? Object.assign(hue, {h: nextHue}) : nextHue; }; colorsys.getColorEncoding = function(color) { if (typeof color === 'string') { try { colorsys.hex2Rgb(color); return 'hex'; } catch (err) { /* Silent catch */ } } if (typeof color !== 'object') { return 'unknown'; } // Now check that the sum of the components is still a number // And different than NaN (for that the boolean check) const c = color; if (c.r + c.g + c.b && typeof (c.r + c.g + c.b) === 'number') { return 'rgb'; } if (c.h + c.s + c.v && typeof (c.h + c.s + c.v) === 'number') { return 'hsv'; } if (c.h + c.s + c.l && typeof (c.h + c.s + c.l) === 'number') { return 'hsl'; } if (c.c + c.m + c.y + c.k && typeof (c.c + c.m + c.y + c.k) === 'number') { return 'cmyk'; } return 'unknown'; }; function _normalizeAngle(degrees) { return ((degrees % 360) + 360) % 360; } function _hue2Rgb(p, q, t) { if (t < 0) { t += 1; } if (t > 1) { t -= 1; } if (t < 1 / 6) { return p + (q - p) * 6 * t; } if (t < 1 / 2) { return q; } if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; } return p; } function padWithZeros(num) { var s = String(num); while (s.length < 6) { s = '0' + s; } return s; } // It's easier to change luminosity in HSL colorsys.any2Hsl = function(color) { const colorEncoding = colorsys.getColorEncoding(color); switch (colorEncoding) { case 'hsl': return color; case 'rgb': return colorsys.rgb2Hsl(color); case 'hex': return colorsys.hex2Hsl(color); case 'hsv': return colorsys.hsv2Hsl(color); case 'cmyk': return colorsys.rgb2Hsl(colorsys.cmyk2Rgb(color)); default: return 'unknown'; } }; // Aliases colorsys.any_to_hsl = colorsys.anyToHsl = colorsys.any2Hsl; // Will return the transforming to encode function // or undefined colorsys.getTransformEncodingFunction = function(color, desiredEncoding) { const originalEncoding = colorsys.getColorEncoding(color); return colorsys[originalEncoding + '_to_' + desiredEncoding]; }; // TODO: // Create darken / lighten methods with same input/output format colorsys.darken = function(color, percentage) { const encoding = colorsys.getColorEncoding(color); if (encoding === 'unknown') { return color; } // Missing transformation function between hsl and cmyk // Also, this algo is simple and precise if (encoding === 'cmyk') { const nextCmyk = color; nextCmyk.k = Math.min(100, 100 * percentage + nextCmyk.k); return nextCmyk; } const hsl = colorsys.any2Hsl(color); const nextHsl = {h: hsl.h, s: hsl.s, l: Math.round(hsl.l * (1 - percentage))}; const transformFn = encoding === 'hsl' ? c => c // If HSL return as incame : colorsys.getTransformEncodingFunction(nextHsl, encoding); if (typeof transformFn !== 'function') { return color; } return transformFn(nextHsl); }; export default colorsys;