UNPKG

uniqolor

Version:

Generate unique and beautiful colors from any texts or numbers

367 lines (352 loc) 12.9 kB
/** * Generate unique and beautiful colors from any texts or numbers * @version v1.1.1 * @link https://github.com/dastoori/uniqolor#README * @author Rasool Dastoori * @license MIT License, http://www.opensource.org/licenses/MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.uniqolor = factory()); })(this, (function () { 'use strict'; function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var SATURATION_BOUND = [0, 100]; var LIGHTNESS_BOUND = [0, 100]; var pad2 = function pad2(str) { return "".concat(str.length === 1 ? '0' : '').concat(str); }; var clamp = function clamp(num, min, max) { return Math.max(Math.min(num, max), min); }; var random = function random(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; var randomExclude = function randomExclude(min, max, exclude) { var r = random(min, max); for (var i = 0; i < (exclude === null || exclude === void 0 ? void 0 : exclude.length); i++) { var value = exclude[i]; if ((value === null || value === void 0 ? void 0 : value.length) === 2 && r >= value[0] && r <= value[1]) { return randomExclude(min, max, exclude); } } return r; }; /** * Generate hashCode * @param {string} str * @return {number} */ var hashCode = function hashCode(str) { var len = str.length; var hash = 0; for (var i = 0; i < len; i++) { hash = (hash << 5) - hash + str.charCodeAt(i); hash &= hash; // Convert to 32bit integer } return hash; }; /** * Clamps `num` within the inclusive `range` bounds * @param {number} num * @param {number|Array} range * @return {number} */ var boundHashCode = function boundHashCode(num, range) { if (typeof range === 'number') { return range; } return num % Math.abs(range[1] - range[0]) + range[0]; }; /** * Sanitizing the `range` * @param {number|Array} range * @param {Array} bound * @return {number|Array} */ var sanitizeRange = function sanitizeRange(range, bound) { if (typeof range === 'number') { return clamp.apply(void 0, [Math.abs(range)].concat(_toConsumableArray(bound))); } if (range.length === 1 || range[0] === range[1]) { return clamp.apply(void 0, [Math.abs(range[0])].concat(_toConsumableArray(bound))); } return [Math.abs(clamp.apply(void 0, [range[0]].concat(_toConsumableArray(bound)))), clamp.apply(void 0, [Math.abs(range[1])].concat(_toConsumableArray(bound)))]; }; /** * @param {number} p * @param {number} q * @param {number} t * @return {number} */ var hueToRgb = function hueToRgb(p, q, t) { if (t < 0) { t += 1; } else 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; }; /** * Converts an HSL color to RGB * @param {number} h Hue * @param {number} s Saturation * @param {number} l Lightness * @return {Array} */ var hslToRgb = function hslToRgb(h, s, l) { var r; var g; var b; h /= 360; s /= 100; l /= 100; if (s === 0) { // achromatic r = g = b = l; } else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hueToRgb(p, q, h + 1 / 3); g = hueToRgb(p, q, h); b = hueToRgb(p, q, h - 1 / 3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; }; /** * Determines whether the RGB color is light or not * http://www.w3.org/TR/AERT#color-contrast * @param {number} r Red * @param {number} g Green * @param {number} b Blue * @param {number} differencePoint * @return {boolean} */ var rgbIsLight = function rgbIsLight(r, g, b, differencePoint) { return (r * 299 + g * 587 + b * 114) / 1000 >= differencePoint; }; // eslint-disable-line max-len /** * Converts an HSL color to string format * @param {number} h Hue * @param {number} s Saturation * @param {number} l Lightness * @return {string} */ var hslToString = function hslToString(h, s, l) { return "hsl(".concat(h, ", ").concat(s, "%, ").concat(l, "%)"); }; /** * Converts RGB color to string format * @param {number} r Red * @param {number} g Green * @param {number} b Blue * @param {string} format Color format * @return {string} */ var rgbFormat = function rgbFormat(r, g, b, format) { switch (format) { case 'rgb': return "rgb(".concat(r, ", ").concat(g, ", ").concat(b, ")"); case 'hex': default: return "#".concat(pad2(r.toString(16))).concat(pad2(g.toString(16))).concat(pad2(b.toString(16))); } }; /** * Generate unique color from `value` * @param {string|number} value * @param {Object} [options={}] * @param {string} [options.format='hex'] * The color format, it can be one of `hex`, `rgb` or `hsl` * @param {number|Array} [options.saturation=[50, 55]] * Determines the color saturation, it can be a number or a range between 0 and 100 * @param {number|Array} [options.lightness=[50, 60]] * Determines the color lightness, it can be a number or a range between 0 and 100 * @param {number} [options.differencePoint=130] * Determines the color brightness difference point. We use it to obtain the `isLight` value * in the output, it can be a number between 0 and 255 * @return {Object} * @example * * ```js * uniqolor('Hello world!') * // { color: "#5cc653", isLight: true } * * uniqolor('Hello world!', { format: 'rgb' }) * // { color: "rgb(92, 198, 83)", isLight: true } * * uniqolor('Hello world!', { * saturation: 30, * lightness: [70, 80], * }) * // { color: "#afd2ac", isLight: true } * * uniqolor('Hello world!', { * saturation: 30, * lightness: [70, 80], * differencePoint: 200, * }) * // { color: "#afd2ac", isLight: false } * ``` */ var uniqolor = function uniqolor(value) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$format = _ref.format, format = _ref$format === void 0 ? 'hex' : _ref$format, _ref$saturation = _ref.saturation, saturation = _ref$saturation === void 0 ? [50, 55] : _ref$saturation, _ref$lightness = _ref.lightness, lightness = _ref$lightness === void 0 ? [50, 60] : _ref$lightness, _ref$differencePoint = _ref.differencePoint, differencePoint = _ref$differencePoint === void 0 ? 130 : _ref$differencePoint; var hash = Math.abs(hashCode(String(value))); var h = boundHashCode(hash, [0, 360]); var s = boundHashCode(hash, sanitizeRange(saturation, SATURATION_BOUND)); var l = boundHashCode(hash, sanitizeRange(lightness, LIGHTNESS_BOUND)); var _hslToRgb = hslToRgb(h, s, l), _hslToRgb2 = _slicedToArray(_hslToRgb, 3), r = _hslToRgb2[0], g = _hslToRgb2[1], b = _hslToRgb2[2]; return { color: format === 'hsl' ? hslToString(h, s, l) : rgbFormat(r, g, b, format), isLight: rgbIsLight(r, g, b, differencePoint) }; }; /** * Generate random color * @param {Object} [options={}] * @param {string} [options.format='hex'] * The color format, it can be one of `hex`, `rgb` or `hsl` * @param {number|Array} [options.saturation=[50, 55]] * Determines the color saturation, it can be a number or a range between 0 and 100 * @param {number|Array} [options.lightness=[50, 60]] * Determines the color lightness, it can be a number or a range between 0 and 100 * @param {number} [options.differencePoint=130] * Determines the color brightness difference point. We use it to obtain the `isLight` value * in the output, it can be a number between 0 and 255 * @param {Array} [options.excludeHue] * Exclude certain hue ranges. For example to exclude red color range: `[[0, 20], [325, 359]]` * @return {Object} * @example * * ```js * // Generate random color * uniqolor.random() * // { color: "#644cc8", isLight: false } * * // Generate a random color with HSL format * uniqolor.random({ format: 'hsl' }) * // { color: "hsl(89, 55%, 60%)", isLight: true } * * // Generate a random color in specific saturation and lightness * uniqolor.random({ * saturation: 80, * lightness: [70, 80], * }) * // { color: "#c7b9da", isLight: true } * * // Generate a random color but exclude red color range * uniqolor.random({ * excludeHue: [[0, 20], [325, 359]], * }) * // {color: '#53caab', isLight: true} * ``` */ uniqolor.random = function () { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$format = _ref2.format, format = _ref2$format === void 0 ? 'hex' : _ref2$format, _ref2$saturation = _ref2.saturation, saturation = _ref2$saturation === void 0 ? [50, 55] : _ref2$saturation, _ref2$lightness = _ref2.lightness, lightness = _ref2$lightness === void 0 ? [50, 60] : _ref2$lightness, _ref2$differencePoint = _ref2.differencePoint, differencePoint = _ref2$differencePoint === void 0 ? 130 : _ref2$differencePoint, excludeHue = _ref2.excludeHue; saturation = sanitizeRange(saturation, SATURATION_BOUND); lightness = sanitizeRange(lightness, LIGHTNESS_BOUND); var h = excludeHue ? randomExclude(0, 359, excludeHue) : random(0, 359); var s = typeof saturation === 'number' ? saturation : random.apply(void 0, _toConsumableArray(saturation)); var l = typeof lightness === 'number' ? lightness : random.apply(void 0, _toConsumableArray(lightness)); var _hslToRgb3 = hslToRgb(h, s, l), _hslToRgb4 = _slicedToArray(_hslToRgb3, 3), r = _hslToRgb4[0], g = _hslToRgb4[1], b = _hslToRgb4[2]; return { color: format === 'hsl' ? hslToString(h, s, l) : rgbFormat(r, g, b, format), isLight: rgbIsLight(r, g, b, differencePoint) }; }; return uniqolor; }));