tinycolor.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. // This file is autogenerated.
  2. // It's here at this path for backwards compatibility for links to it
  3. // but the npm package now exports both CJS and ESM.
  4. // See https://github.com/bgrins/TinyColor/ for instructions.
  5. (function (global, factory) {
  6. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  7. typeof define === 'function' && define.amd ? define(factory) :
  8. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.tinycolor = factory());
  9. })(this, (function () { 'use strict';
  10. function _typeof(obj) {
  11. "@babel/helpers - typeof";
  12. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
  13. return typeof obj;
  14. } : function (obj) {
  15. return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  16. }, _typeof(obj);
  17. }
  18. // https://github.com/bgrins/TinyColor
  19. // Brian Grinstead, MIT License
  20. var trimLeft = /^\s+/;
  21. var trimRight = /\s+$/;
  22. function tinycolor(color, opts) {
  23. color = color ? color : "";
  24. opts = opts || {};
  25. // If input is already a tinycolor, return itself
  26. if (color instanceof tinycolor) {
  27. return color;
  28. }
  29. // If we are called as a function, call using new instead
  30. if (!(this instanceof tinycolor)) {
  31. return new tinycolor(color, opts);
  32. }
  33. var rgb = inputToRGB(color);
  34. this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = Math.round(100 * this._a) / 100, this._format = opts.format || rgb.format;
  35. this._gradientType = opts.gradientType;
  36. // Don't let the range of [0,255] come back in [0,1].
  37. // Potentially lose a little bit of precision here, but will fix issues where
  38. // .5 gets interpreted as half of the total, instead of half of 1
  39. // If it was supposed to be 128, this was already taken care of by `inputToRgb`
  40. if (this._r < 1) this._r = Math.round(this._r);
  41. if (this._g < 1) this._g = Math.round(this._g);
  42. if (this._b < 1) this._b = Math.round(this._b);
  43. this._ok = rgb.ok;
  44. }
  45. tinycolor.prototype = {
  46. isDark: function isDark() {
  47. return this.getBrightness() < 128;
  48. },
  49. isLight: function isLight() {
  50. return !this.isDark();
  51. },
  52. isValid: function isValid() {
  53. return this._ok;
  54. },
  55. getOriginalInput: function getOriginalInput() {
  56. return this._originalInput;
  57. },
  58. getFormat: function getFormat() {
  59. return this._format;
  60. },
  61. getAlpha: function getAlpha() {
  62. return this._a;
  63. },
  64. getBrightness: function getBrightness() {
  65. //http://www.w3.org/TR/AERT#color-contrast
  66. var rgb = this.toRgb();
  67. return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
  68. },
  69. getLuminance: function getLuminance() {
  70. //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
  71. var rgb = this.toRgb();
  72. var RsRGB, GsRGB, BsRGB, R, G, B;
  73. RsRGB = rgb.r / 255;
  74. GsRGB = rgb.g / 255;
  75. BsRGB = rgb.b / 255;
  76. if (RsRGB <= 0.03928) R = RsRGB / 12.92;else R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
  77. if (GsRGB <= 0.03928) G = GsRGB / 12.92;else G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
  78. if (BsRGB <= 0.03928) B = BsRGB / 12.92;else B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
  79. return 0.2126 * R + 0.7152 * G + 0.0722 * B;
  80. },
  81. setAlpha: function setAlpha(value) {
  82. this._a = boundAlpha(value);
  83. this._roundA = Math.round(100 * this._a) / 100;
  84. return this;
  85. },
  86. toHsv: function toHsv() {
  87. var hsv = rgbToHsv(this._r, this._g, this._b);
  88. return {
  89. h: hsv.h * 360,
  90. s: hsv.s,
  91. v: hsv.v,
  92. a: this._a
  93. };
  94. },
  95. toHsvString: function toHsvString() {
  96. var hsv = rgbToHsv(this._r, this._g, this._b);
  97. var h = Math.round(hsv.h * 360),
  98. s = Math.round(hsv.s * 100),
  99. v = Math.round(hsv.v * 100);
  100. return this._a == 1 ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")";
  101. },
  102. toHsl: function toHsl() {
  103. var hsl = rgbToHsl(this._r, this._g, this._b);
  104. return {
  105. h: hsl.h * 360,
  106. s: hsl.s,
  107. l: hsl.l,
  108. a: this._a
  109. };
  110. },
  111. toHslString: function toHslString() {
  112. var hsl = rgbToHsl(this._r, this._g, this._b);
  113. var h = Math.round(hsl.h * 360),
  114. s = Math.round(hsl.s * 100),
  115. l = Math.round(hsl.l * 100);
  116. return this._a == 1 ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")";
  117. },
  118. toHex: function toHex(allow3Char) {
  119. return rgbToHex(this._r, this._g, this._b, allow3Char);
  120. },
  121. toHexString: function toHexString(allow3Char) {
  122. return "#" + this.toHex(allow3Char);
  123. },
  124. toHex8: function toHex8(allow4Char) {
  125. return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
  126. },
  127. toHex8String: function toHex8String(allow4Char) {
  128. return "#" + this.toHex8(allow4Char);
  129. },
  130. toRgb: function toRgb() {
  131. return {
  132. r: Math.round(this._r),
  133. g: Math.round(this._g),
  134. b: Math.round(this._b),
  135. a: this._a
  136. };
  137. },
  138. toRgbString: function toRgbString() {
  139. return this._a == 1 ? "rgb(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ")" : "rgba(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ", " + this._roundA + ")";
  140. },
  141. toPercentageRgb: function toPercentageRgb() {
  142. return {
  143. r: Math.round(bound01(this._r, 255) * 100) + "%",
  144. g: Math.round(bound01(this._g, 255) * 100) + "%",
  145. b: Math.round(bound01(this._b, 255) * 100) + "%",
  146. a: this._a
  147. };
  148. },
  149. toPercentageRgbString: function toPercentageRgbString() {
  150. return this._a == 1 ? "rgb(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%)" : "rgba(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
  151. },
  152. toName: function toName() {
  153. if (this._a === 0) {
  154. return "transparent";
  155. }
  156. if (this._a < 1) {
  157. return false;
  158. }
  159. return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
  160. },
  161. toFilter: function toFilter(secondColor) {
  162. var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a);
  163. var secondHex8String = hex8String;
  164. var gradientType = this._gradientType ? "GradientType = 1, " : "";
  165. if (secondColor) {
  166. var s = tinycolor(secondColor);
  167. secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a);
  168. }
  169. return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")";
  170. },
  171. toString: function toString(format) {
  172. var formatSet = !!format;
  173. format = format || this._format;
  174. var formattedString = false;
  175. var hasAlpha = this._a < 1 && this._a >= 0;
  176. var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name");
  177. if (needsAlphaFormat) {
  178. // Special case for "transparent", all other non-alpha formats
  179. // will return rgba when there is transparency.
  180. if (format === "name" && this._a === 0) {
  181. return this.toName();
  182. }
  183. return this.toRgbString();
  184. }
  185. if (format === "rgb") {
  186. formattedString = this.toRgbString();
  187. }
  188. if (format === "prgb") {
  189. formattedString = this.toPercentageRgbString();
  190. }
  191. if (format === "hex" || format === "hex6") {
  192. formattedString = this.toHexString();
  193. }
  194. if (format === "hex3") {
  195. formattedString = this.toHexString(true);
  196. }
  197. if (format === "hex4") {
  198. formattedString = this.toHex8String(true);
  199. }
  200. if (format === "hex8") {
  201. formattedString = this.toHex8String();
  202. }
  203. if (format === "name") {
  204. formattedString = this.toName();
  205. }
  206. if (format === "hsl") {
  207. formattedString = this.toHslString();
  208. }
  209. if (format === "hsv") {
  210. formattedString = this.toHsvString();
  211. }
  212. return formattedString || this.toHexString();
  213. },
  214. clone: function clone() {
  215. return tinycolor(this.toString());
  216. },
  217. _applyModification: function _applyModification(fn, args) {
  218. var color = fn.apply(null, [this].concat([].slice.call(args)));
  219. this._r = color._r;
  220. this._g = color._g;
  221. this._b = color._b;
  222. this.setAlpha(color._a);
  223. return this;
  224. },
  225. lighten: function lighten() {
  226. return this._applyModification(_lighten, arguments);
  227. },
  228. brighten: function brighten() {
  229. return this._applyModification(_brighten, arguments);
  230. },
  231. darken: function darken() {
  232. return this._applyModification(_darken, arguments);
  233. },
  234. desaturate: function desaturate() {
  235. return this._applyModification(_desaturate, arguments);
  236. },
  237. saturate: function saturate() {
  238. return this._applyModification(_saturate, arguments);
  239. },
  240. greyscale: function greyscale() {
  241. return this._applyModification(_greyscale, arguments);
  242. },
  243. spin: function spin() {
  244. return this._applyModification(_spin, arguments);
  245. },
  246. _applyCombination: function _applyCombination(fn, args) {
  247. return fn.apply(null, [this].concat([].slice.call(args)));
  248. },
  249. analogous: function analogous() {
  250. return this._applyCombination(_analogous, arguments);
  251. },
  252. complement: function complement() {
  253. return this._applyCombination(_complement, arguments);
  254. },
  255. monochromatic: function monochromatic() {
  256. return this._applyCombination(_monochromatic, arguments);
  257. },
  258. splitcomplement: function splitcomplement() {
  259. return this._applyCombination(_splitcomplement, arguments);
  260. },
  261. // Disabled until https://github.com/bgrins/TinyColor/issues/254
  262. // polyad: function (number) {
  263. // return this._applyCombination(polyad, [number]);
  264. // },
  265. triad: function triad() {
  266. return this._applyCombination(polyad, [3]);
  267. },
  268. tetrad: function tetrad() {
  269. return this._applyCombination(polyad, [4]);
  270. }
  271. };
  272. // If input is an object, force 1 into "1.0" to handle ratios properly
  273. // String input requires "1.0" as input, so 1 will be treated as 1
  274. tinycolor.fromRatio = function (color, opts) {
  275. if (_typeof(color) == "object") {
  276. var newColor = {};
  277. for (var i in color) {
  278. if (color.hasOwnProperty(i)) {
  279. if (i === "a") {
  280. newColor[i] = color[i];
  281. } else {
  282. newColor[i] = convertToPercentage(color[i]);
  283. }
  284. }
  285. }
  286. color = newColor;
  287. }
  288. return tinycolor(color, opts);
  289. };
  290. // Given a string or object, convert that input to RGB
  291. // Possible string inputs:
  292. //
  293. // "red"
  294. // "#f00" or "f00"
  295. // "#ff0000" or "ff0000"
  296. // "#ff000000" or "ff000000"
  297. // "rgb 255 0 0" or "rgb (255, 0, 0)"
  298. // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
  299. // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
  300. // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
  301. // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
  302. // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
  303. // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
  304. //
  305. function inputToRGB(color) {
  306. var rgb = {
  307. r: 0,
  308. g: 0,
  309. b: 0
  310. };
  311. var a = 1;
  312. var s = null;
  313. var v = null;
  314. var l = null;
  315. var ok = false;
  316. var format = false;
  317. if (typeof color == "string") {
  318. color = stringInputToObject(color);
  319. }
  320. if (_typeof(color) == "object") {
  321. if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
  322. rgb = rgbToRgb(color.r, color.g, color.b);
  323. ok = true;
  324. format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
  325. } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
  326. s = convertToPercentage(color.s);
  327. v = convertToPercentage(color.v);
  328. rgb = hsvToRgb(color.h, s, v);
  329. ok = true;
  330. format = "hsv";
  331. } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
  332. s = convertToPercentage(color.s);
  333. l = convertToPercentage(color.l);
  334. rgb = hslToRgb(color.h, s, l);
  335. ok = true;
  336. format = "hsl";
  337. }
  338. if (color.hasOwnProperty("a")) {
  339. a = color.a;
  340. }
  341. }
  342. a = boundAlpha(a);
  343. return {
  344. ok: ok,
  345. format: color.format || format,
  346. r: Math.min(255, Math.max(rgb.r, 0)),
  347. g: Math.min(255, Math.max(rgb.g, 0)),
  348. b: Math.min(255, Math.max(rgb.b, 0)),
  349. a: a
  350. };
  351. }
  352. // Conversion Functions
  353. // --------------------
  354. // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
  355. // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
  356. // `rgbToRgb`
  357. // Handle bounds / percentage checking to conform to CSS color spec
  358. // <http://www.w3.org/TR/css3-color/>
  359. // *Assumes:* r, g, b in [0, 255] or [0, 1]
  360. // *Returns:* { r, g, b } in [0, 255]
  361. function rgbToRgb(r, g, b) {
  362. return {
  363. r: bound01(r, 255) * 255,
  364. g: bound01(g, 255) * 255,
  365. b: bound01(b, 255) * 255
  366. };
  367. }
  368. // `rgbToHsl`
  369. // Converts an RGB color value to HSL.
  370. // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
  371. // *Returns:* { h, s, l } in [0,1]
  372. function rgbToHsl(r, g, b) {
  373. r = bound01(r, 255);
  374. g = bound01(g, 255);
  375. b = bound01(b, 255);
  376. var max = Math.max(r, g, b),
  377. min = Math.min(r, g, b);
  378. var h,
  379. s,
  380. l = (max + min) / 2;
  381. if (max == min) {
  382. h = s = 0; // achromatic
  383. } else {
  384. var d = max - min;
  385. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  386. switch (max) {
  387. case r:
  388. h = (g - b) / d + (g < b ? 6 : 0);
  389. break;
  390. case g:
  391. h = (b - r) / d + 2;
  392. break;
  393. case b:
  394. h = (r - g) / d + 4;
  395. break;
  396. }
  397. h /= 6;
  398. }
  399. return {
  400. h: h,
  401. s: s,
  402. l: l
  403. };
  404. }
  405. // `hslToRgb`
  406. // Converts an HSL color value to RGB.
  407. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
  408. // *Returns:* { r, g, b } in the set [0, 255]
  409. function hslToRgb(h, s, l) {
  410. var r, g, b;
  411. h = bound01(h, 360);
  412. s = bound01(s, 100);
  413. l = bound01(l, 100);
  414. function hue2rgb(p, q, t) {
  415. if (t < 0) t += 1;
  416. if (t > 1) t -= 1;
  417. if (t < 1 / 6) return p + (q - p) * 6 * t;
  418. if (t < 1 / 2) return q;
  419. if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
  420. return p;
  421. }
  422. if (s === 0) {
  423. r = g = b = l; // achromatic
  424. } else {
  425. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  426. var p = 2 * l - q;
  427. r = hue2rgb(p, q, h + 1 / 3);
  428. g = hue2rgb(p, q, h);
  429. b = hue2rgb(p, q, h - 1 / 3);
  430. }
  431. return {
  432. r: r * 255,
  433. g: g * 255,
  434. b: b * 255
  435. };
  436. }
  437. // `rgbToHsv`
  438. // Converts an RGB color value to HSV
  439. // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
  440. // *Returns:* { h, s, v } in [0,1]
  441. function rgbToHsv(r, g, b) {
  442. r = bound01(r, 255);
  443. g = bound01(g, 255);
  444. b = bound01(b, 255);
  445. var max = Math.max(r, g, b),
  446. min = Math.min(r, g, b);
  447. var h,
  448. s,
  449. v = max;
  450. var d = max - min;
  451. s = max === 0 ? 0 : d / max;
  452. if (max == min) {
  453. h = 0; // achromatic
  454. } else {
  455. switch (max) {
  456. case r:
  457. h = (g - b) / d + (g < b ? 6 : 0);
  458. break;
  459. case g:
  460. h = (b - r) / d + 2;
  461. break;
  462. case b:
  463. h = (r - g) / d + 4;
  464. break;
  465. }
  466. h /= 6;
  467. }
  468. return {
  469. h: h,
  470. s: s,
  471. v: v
  472. };
  473. }
  474. // `hsvToRgb`
  475. // Converts an HSV color value to RGB.
  476. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
  477. // *Returns:* { r, g, b } in the set [0, 255]
  478. function hsvToRgb(h, s, v) {
  479. h = bound01(h, 360) * 6;
  480. s = bound01(s, 100);
  481. v = bound01(v, 100);
  482. var i = Math.floor(h),
  483. f = h - i,
  484. p = v * (1 - s),
  485. q = v * (1 - f * s),
  486. t = v * (1 - (1 - f) * s),
  487. mod = i % 6,
  488. r = [v, q, p, p, t, v][mod],
  489. g = [t, v, v, q, p, p][mod],
  490. b = [p, p, t, v, v, q][mod];
  491. return {
  492. r: r * 255,
  493. g: g * 255,
  494. b: b * 255
  495. };
  496. }
  497. // `rgbToHex`
  498. // Converts an RGB color to hex
  499. // Assumes r, g, and b are contained in the set [0, 255]
  500. // Returns a 3 or 6 character hex
  501. function rgbToHex(r, g, b, allow3Char) {
  502. var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];
  503. // Return a 3 character hex if possible
  504. if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
  505. return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
  506. }
  507. return hex.join("");
  508. }
  509. // `rgbaToHex`
  510. // Converts an RGBA color plus alpha transparency to hex
  511. // Assumes r, g, b are contained in the set [0, 255] and
  512. // a in [0, 1]. Returns a 4 or 8 character rgba hex
  513. function rgbaToHex(r, g, b, a, allow4Char) {
  514. var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16)), pad2(convertDecimalToHex(a))];
  515. // Return a 4 character hex if possible
  516. if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) {
  517. return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
  518. }
  519. return hex.join("");
  520. }
  521. // `rgbaToArgbHex`
  522. // Converts an RGBA color to an ARGB Hex8 string
  523. // Rarely used, but required for "toFilter()"
  524. function rgbaToArgbHex(r, g, b, a) {
  525. var hex = [pad2(convertDecimalToHex(a)), pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];
  526. return hex.join("");
  527. }
  528. // `equals`
  529. // Can be called with any tinycolor input
  530. tinycolor.equals = function (color1, color2) {
  531. if (!color1 || !color2) return false;
  532. return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
  533. };
  534. tinycolor.random = function () {
  535. return tinycolor.fromRatio({
  536. r: Math.random(),
  537. g: Math.random(),
  538. b: Math.random()
  539. });
  540. };
  541. // Modification Functions
  542. // ----------------------
  543. // Thanks to less.js for some of the basics here
  544. // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
  545. function _desaturate(color, amount) {
  546. amount = amount === 0 ? 0 : amount || 10;
  547. var hsl = tinycolor(color).toHsl();
  548. hsl.s -= amount / 100;
  549. hsl.s = clamp01(hsl.s);
  550. return tinycolor(hsl);
  551. }
  552. function _saturate(color, amount) {
  553. amount = amount === 0 ? 0 : amount || 10;
  554. var hsl = tinycolor(color).toHsl();
  555. hsl.s += amount / 100;
  556. hsl.s = clamp01(hsl.s);
  557. return tinycolor(hsl);
  558. }
  559. function _greyscale(color) {
  560. return tinycolor(color).desaturate(100);
  561. }
  562. function _lighten(color, amount) {
  563. amount = amount === 0 ? 0 : amount || 10;
  564. var hsl = tinycolor(color).toHsl();
  565. hsl.l += amount / 100;
  566. hsl.l = clamp01(hsl.l);
  567. return tinycolor(hsl);
  568. }
  569. function _brighten(color, amount) {
  570. amount = amount === 0 ? 0 : amount || 10;
  571. var rgb = tinycolor(color).toRgb();
  572. rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100))));
  573. rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100))));
  574. rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100))));
  575. return tinycolor(rgb);
  576. }
  577. function _darken(color, amount) {
  578. amount = amount === 0 ? 0 : amount || 10;
  579. var hsl = tinycolor(color).toHsl();
  580. hsl.l -= amount / 100;
  581. hsl.l = clamp01(hsl.l);
  582. return tinycolor(hsl);
  583. }
  584. // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
  585. // Values outside of this range will be wrapped into this range.
  586. function _spin(color, amount) {
  587. var hsl = tinycolor(color).toHsl();
  588. var hue = (hsl.h + amount) % 360;
  589. hsl.h = hue < 0 ? 360 + hue : hue;
  590. return tinycolor(hsl);
  591. }
  592. // Combination Functions
  593. // ---------------------
  594. // Thanks to jQuery xColor for some of the ideas behind these
  595. // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
  596. function _complement(color) {
  597. var hsl = tinycolor(color).toHsl();
  598. hsl.h = (hsl.h + 180) % 360;
  599. return tinycolor(hsl);
  600. }
  601. function polyad(color, number) {
  602. if (isNaN(number) || number <= 0) {
  603. throw new Error("Argument to polyad must be a positive number");
  604. }
  605. var hsl = tinycolor(color).toHsl();
  606. var result = [tinycolor(color)];
  607. var step = 360 / number;
  608. for (var i = 1; i < number; i++) {
  609. result.push(tinycolor({
  610. h: (hsl.h + i * step) % 360,
  611. s: hsl.s,
  612. l: hsl.l
  613. }));
  614. }
  615. return result;
  616. }
  617. function _splitcomplement(color) {
  618. var hsl = tinycolor(color).toHsl();
  619. var h = hsl.h;
  620. return [tinycolor(color), tinycolor({
  621. h: (h + 72) % 360,
  622. s: hsl.s,
  623. l: hsl.l
  624. }), tinycolor({
  625. h: (h + 216) % 360,
  626. s: hsl.s,
  627. l: hsl.l
  628. })];
  629. }
  630. function _analogous(color, results, slices) {
  631. results = results || 6;
  632. slices = slices || 30;
  633. var hsl = tinycolor(color).toHsl();
  634. var part = 360 / slices;
  635. var ret = [tinycolor(color)];
  636. for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) {
  637. hsl.h = (hsl.h + part) % 360;
  638. ret.push(tinycolor(hsl));
  639. }
  640. return ret;
  641. }
  642. function _monochromatic(color, results) {
  643. results = results || 6;
  644. var hsv = tinycolor(color).toHsv();
  645. var h = hsv.h,
  646. s = hsv.s,
  647. v = hsv.v;
  648. var ret = [];
  649. var modification = 1 / results;
  650. while (results--) {
  651. ret.push(tinycolor({
  652. h: h,
  653. s: s,
  654. v: v
  655. }));
  656. v = (v + modification) % 1;
  657. }
  658. return ret;
  659. }
  660. // Utility Functions
  661. // ---------------------
  662. tinycolor.mix = function (color1, color2, amount) {
  663. amount = amount === 0 ? 0 : amount || 50;
  664. var rgb1 = tinycolor(color1).toRgb();
  665. var rgb2 = tinycolor(color2).toRgb();
  666. var p = amount / 100;
  667. var rgba = {
  668. r: (rgb2.r - rgb1.r) * p + rgb1.r,
  669. g: (rgb2.g - rgb1.g) * p + rgb1.g,
  670. b: (rgb2.b - rgb1.b) * p + rgb1.b,
  671. a: (rgb2.a - rgb1.a) * p + rgb1.a
  672. };
  673. return tinycolor(rgba);
  674. };
  675. // Readability Functions
  676. // ---------------------
  677. // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
  678. // `contrast`
  679. // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
  680. tinycolor.readability = function (color1, color2) {
  681. var c1 = tinycolor(color1);
  682. var c2 = tinycolor(color2);
  683. return (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) / (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05);
  684. };
  685. // `isReadable`
  686. // Ensure that foreground and background color combinations meet WCAG2 guidelines.
  687. // The third argument is an optional Object.
  688. // the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
  689. // the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
  690. // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
  691. // *Example*
  692. // tinycolor.isReadable("#000", "#111") => false
  693. // tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
  694. tinycolor.isReadable = function (color1, color2, wcag2) {
  695. var readability = tinycolor.readability(color1, color2);
  696. var wcag2Parms, out;
  697. out = false;
  698. wcag2Parms = validateWCAG2Parms(wcag2);
  699. switch (wcag2Parms.level + wcag2Parms.size) {
  700. case "AAsmall":
  701. case "AAAlarge":
  702. out = readability >= 4.5;
  703. break;
  704. case "AAlarge":
  705. out = readability >= 3;
  706. break;
  707. case "AAAsmall":
  708. out = readability >= 7;
  709. break;
  710. }
  711. return out;
  712. };
  713. // `mostReadable`
  714. // Given a base color and a list of possible foreground or background
  715. // colors for that base, returns the most readable color.
  716. // Optionally returns Black or White if the most readable color is unreadable.
  717. // *Example*
  718. // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
  719. // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff"
  720. // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
  721. // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
  722. tinycolor.mostReadable = function (baseColor, colorList, args) {
  723. var bestColor = null;
  724. var bestScore = 0;
  725. var readability;
  726. var includeFallbackColors, level, size;
  727. args = args || {};
  728. includeFallbackColors = args.includeFallbackColors;
  729. level = args.level;
  730. size = args.size;
  731. for (var i = 0; i < colorList.length; i++) {
  732. readability = tinycolor.readability(baseColor, colorList[i]);
  733. if (readability > bestScore) {
  734. bestScore = readability;
  735. bestColor = tinycolor(colorList[i]);
  736. }
  737. }
  738. if (tinycolor.isReadable(baseColor, bestColor, {
  739. level: level,
  740. size: size
  741. }) || !includeFallbackColors) {
  742. return bestColor;
  743. } else {
  744. args.includeFallbackColors = false;
  745. return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args);
  746. }
  747. };
  748. // Big List of Colors
  749. // ------------------
  750. // <https://www.w3.org/TR/css-color-4/#named-colors>
  751. var names = tinycolor.names = {
  752. aliceblue: "f0f8ff",
  753. antiquewhite: "faebd7",
  754. aqua: "0ff",
  755. aquamarine: "7fffd4",
  756. azure: "f0ffff",
  757. beige: "f5f5dc",
  758. bisque: "ffe4c4",
  759. black: "000",
  760. blanchedalmond: "ffebcd",
  761. blue: "00f",
  762. blueviolet: "8a2be2",
  763. brown: "a52a2a",
  764. burlywood: "deb887",
  765. burntsienna: "ea7e5d",
  766. cadetblue: "5f9ea0",
  767. chartreuse: "7fff00",
  768. chocolate: "d2691e",
  769. coral: "ff7f50",
  770. cornflowerblue: "6495ed",
  771. cornsilk: "fff8dc",
  772. crimson: "dc143c",
  773. cyan: "0ff",
  774. darkblue: "00008b",
  775. darkcyan: "008b8b",
  776. darkgoldenrod: "b8860b",
  777. darkgray: "a9a9a9",
  778. darkgreen: "006400",
  779. darkgrey: "a9a9a9",
  780. darkkhaki: "bdb76b",
  781. darkmagenta: "8b008b",
  782. darkolivegreen: "556b2f",
  783. darkorange: "ff8c00",
  784. darkorchid: "9932cc",
  785. darkred: "8b0000",
  786. darksalmon: "e9967a",
  787. darkseagreen: "8fbc8f",
  788. darkslateblue: "483d8b",
  789. darkslategray: "2f4f4f",
  790. darkslategrey: "2f4f4f",
  791. darkturquoise: "00ced1",
  792. darkviolet: "9400d3",
  793. deeppink: "ff1493",
  794. deepskyblue: "00bfff",
  795. dimgray: "696969",
  796. dimgrey: "696969",
  797. dodgerblue: "1e90ff",
  798. firebrick: "b22222",
  799. floralwhite: "fffaf0",
  800. forestgreen: "228b22",
  801. fuchsia: "f0f",
  802. gainsboro: "dcdcdc",
  803. ghostwhite: "f8f8ff",
  804. gold: "ffd700",
  805. goldenrod: "daa520",
  806. gray: "808080",
  807. green: "008000",
  808. greenyellow: "adff2f",
  809. grey: "808080",
  810. honeydew: "f0fff0",
  811. hotpink: "ff69b4",
  812. indianred: "cd5c5c",
  813. indigo: "4b0082",
  814. ivory: "fffff0",
  815. khaki: "f0e68c",
  816. lavender: "e6e6fa",
  817. lavenderblush: "fff0f5",
  818. lawngreen: "7cfc00",
  819. lemonchiffon: "fffacd",
  820. lightblue: "add8e6",
  821. lightcoral: "f08080",
  822. lightcyan: "e0ffff",
  823. lightgoldenrodyellow: "fafad2",
  824. lightgray: "d3d3d3",
  825. lightgreen: "90ee90",
  826. lightgrey: "d3d3d3",
  827. lightpink: "ffb6c1",
  828. lightsalmon: "ffa07a",
  829. lightseagreen: "20b2aa",
  830. lightskyblue: "87cefa",
  831. lightslategray: "789",
  832. lightslategrey: "789",
  833. lightsteelblue: "b0c4de",
  834. lightyellow: "ffffe0",
  835. lime: "0f0",
  836. limegreen: "32cd32",
  837. linen: "faf0e6",
  838. magenta: "f0f",
  839. maroon: "800000",
  840. mediumaquamarine: "66cdaa",
  841. mediumblue: "0000cd",
  842. mediumorchid: "ba55d3",
  843. mediumpurple: "9370db",
  844. mediumseagreen: "3cb371",
  845. mediumslateblue: "7b68ee",
  846. mediumspringgreen: "00fa9a",
  847. mediumturquoise: "48d1cc",
  848. mediumvioletred: "c71585",
  849. midnightblue: "191970",
  850. mintcream: "f5fffa",
  851. mistyrose: "ffe4e1",
  852. moccasin: "ffe4b5",
  853. navajowhite: "ffdead",
  854. navy: "000080",
  855. oldlace: "fdf5e6",
  856. olive: "808000",
  857. olivedrab: "6b8e23",
  858. orange: "ffa500",
  859. orangered: "ff4500",
  860. orchid: "da70d6",
  861. palegoldenrod: "eee8aa",
  862. palegreen: "98fb98",
  863. paleturquoise: "afeeee",
  864. palevioletred: "db7093",
  865. papayawhip: "ffefd5",
  866. peachpuff: "ffdab9",
  867. peru: "cd853f",
  868. pink: "ffc0cb",
  869. plum: "dda0dd",
  870. powderblue: "b0e0e6",
  871. purple: "800080",
  872. rebeccapurple: "663399",
  873. red: "f00",
  874. rosybrown: "bc8f8f",
  875. royalblue: "4169e1",
  876. saddlebrown: "8b4513",
  877. salmon: "fa8072",
  878. sandybrown: "f4a460",
  879. seagreen: "2e8b57",
  880. seashell: "fff5ee",
  881. sienna: "a0522d",
  882. silver: "c0c0c0",
  883. skyblue: "87ceeb",
  884. slateblue: "6a5acd",
  885. slategray: "708090",
  886. slategrey: "708090",
  887. snow: "fffafa",
  888. springgreen: "00ff7f",
  889. steelblue: "4682b4",
  890. tan: "d2b48c",
  891. teal: "008080",
  892. thistle: "d8bfd8",
  893. tomato: "ff6347",
  894. turquoise: "40e0d0",
  895. violet: "ee82ee",
  896. wheat: "f5deb3",
  897. white: "fff",
  898. whitesmoke: "f5f5f5",
  899. yellow: "ff0",
  900. yellowgreen: "9acd32"
  901. };
  902. // Make it easy to access colors via `hexNames[hex]`
  903. var hexNames = tinycolor.hexNames = flip(names);
  904. // Utilities
  905. // ---------
  906. // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
  907. function flip(o) {
  908. var flipped = {};
  909. for (var i in o) {
  910. if (o.hasOwnProperty(i)) {
  911. flipped[o[i]] = i;
  912. }
  913. }
  914. return flipped;
  915. }
  916. // Return a valid alpha value [0,1] with all invalid values being set to 1
  917. function boundAlpha(a) {
  918. a = parseFloat(a);
  919. if (isNaN(a) || a < 0 || a > 1) {
  920. a = 1;
  921. }
  922. return a;
  923. }
  924. // Take input from [0, n] and return it as [0, 1]
  925. function bound01(n, max) {
  926. if (isOnePointZero(n)) n = "100%";
  927. var processPercent = isPercentage(n);
  928. n = Math.min(max, Math.max(0, parseFloat(n)));
  929. // Automatically convert percentage into number
  930. if (processPercent) {
  931. n = parseInt(n * max, 10) / 100;
  932. }
  933. // Handle floating point rounding errors
  934. if (Math.abs(n - max) < 0.000001) {
  935. return 1;
  936. }
  937. // Convert into [0, 1] range if it isn't already
  938. return n % max / parseFloat(max);
  939. }
  940. // Force a number between 0 and 1
  941. function clamp01(val) {
  942. return Math.min(1, Math.max(0, val));
  943. }
  944. // Parse a base-16 hex value into a base-10 integer
  945. function parseIntFromHex(val) {
  946. return parseInt(val, 16);
  947. }
  948. // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
  949. // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
  950. function isOnePointZero(n) {
  951. return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1;
  952. }
  953. // Check to see if string passed in is a percentage
  954. function isPercentage(n) {
  955. return typeof n === "string" && n.indexOf("%") != -1;
  956. }
  957. // Force a hex value to have 2 characters
  958. function pad2(c) {
  959. return c.length == 1 ? "0" + c : "" + c;
  960. }
  961. // Replace a decimal with it's percentage value
  962. function convertToPercentage(n) {
  963. if (n <= 1) {
  964. n = n * 100 + "%";
  965. }
  966. return n;
  967. }
  968. // Converts a decimal to a hex value
  969. function convertDecimalToHex(d) {
  970. return Math.round(parseFloat(d) * 255).toString(16);
  971. }
  972. // Converts a hex value to a decimal
  973. function convertHexToDecimal(h) {
  974. return parseIntFromHex(h) / 255;
  975. }
  976. var matchers = function () {
  977. // <http://www.w3.org/TR/css3-values/#integers>
  978. var CSS_INTEGER = "[-\\+]?\\d+%?";
  979. // <http://www.w3.org/TR/css3-values/#number-value>
  980. var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
  981. // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
  982. var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
  983. // Actual matching.
  984. // Parentheses and commas are optional, but not required.
  985. // Whitespace can take the place of commas or opening paren
  986. var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  987. var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  988. return {
  989. CSS_UNIT: new RegExp(CSS_UNIT),
  990. rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
  991. rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
  992. hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
  993. hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
  994. hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
  995. hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
  996. hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
  997. hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
  998. hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
  999. hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
  1000. };
  1001. }();
  1002. // `isValidCSSUnit`
  1003. // Take in a single string / number and check to see if it looks like a CSS unit
  1004. // (see `matchers` above for definition).
  1005. function isValidCSSUnit(color) {
  1006. return !!matchers.CSS_UNIT.exec(color);
  1007. }
  1008. // `stringInputToObject`
  1009. // Permissive string parsing. Take in a number of formats, and output an object
  1010. // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
  1011. function stringInputToObject(color) {
  1012. color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase();
  1013. var named = false;
  1014. if (names[color]) {
  1015. color = names[color];
  1016. named = true;
  1017. } else if (color == "transparent") {
  1018. return {
  1019. r: 0,
  1020. g: 0,
  1021. b: 0,
  1022. a: 0,
  1023. format: "name"
  1024. };
  1025. }
  1026. // Try to match string input using regular expressions.
  1027. // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
  1028. // Just return an object and let the conversion functions handle that.
  1029. // This way the result will be the same whether the tinycolor is initialized with string or object.
  1030. var match;
  1031. if (match = matchers.rgb.exec(color)) {
  1032. return {
  1033. r: match[1],
  1034. g: match[2],
  1035. b: match[3]
  1036. };
  1037. }
  1038. if (match = matchers.rgba.exec(color)) {
  1039. return {
  1040. r: match[1],
  1041. g: match[2],
  1042. b: match[3],
  1043. a: match[4]
  1044. };
  1045. }
  1046. if (match = matchers.hsl.exec(color)) {
  1047. return {
  1048. h: match[1],
  1049. s: match[2],
  1050. l: match[3]
  1051. };
  1052. }
  1053. if (match = matchers.hsla.exec(color)) {
  1054. return {
  1055. h: match[1],
  1056. s: match[2],
  1057. l: match[3],
  1058. a: match[4]
  1059. };
  1060. }
  1061. if (match = matchers.hsv.exec(color)) {
  1062. return {
  1063. h: match[1],
  1064. s: match[2],
  1065. v: match[3]
  1066. };
  1067. }
  1068. if (match = matchers.hsva.exec(color)) {
  1069. return {
  1070. h: match[1],
  1071. s: match[2],
  1072. v: match[3],
  1073. a: match[4]
  1074. };
  1075. }
  1076. if (match = matchers.hex8.exec(color)) {
  1077. return {
  1078. r: parseIntFromHex(match[1]),
  1079. g: parseIntFromHex(match[2]),
  1080. b: parseIntFromHex(match[3]),
  1081. a: convertHexToDecimal(match[4]),
  1082. format: named ? "name" : "hex8"
  1083. };
  1084. }
  1085. if (match = matchers.hex6.exec(color)) {
  1086. return {
  1087. r: parseIntFromHex(match[1]),
  1088. g: parseIntFromHex(match[2]),
  1089. b: parseIntFromHex(match[3]),
  1090. format: named ? "name" : "hex"
  1091. };
  1092. }
  1093. if (match = matchers.hex4.exec(color)) {
  1094. return {
  1095. r: parseIntFromHex(match[1] + "" + match[1]),
  1096. g: parseIntFromHex(match[2] + "" + match[2]),
  1097. b: parseIntFromHex(match[3] + "" + match[3]),
  1098. a: convertHexToDecimal(match[4] + "" + match[4]),
  1099. format: named ? "name" : "hex8"
  1100. };
  1101. }
  1102. if (match = matchers.hex3.exec(color)) {
  1103. return {
  1104. r: parseIntFromHex(match[1] + "" + match[1]),
  1105. g: parseIntFromHex(match[2] + "" + match[2]),
  1106. b: parseIntFromHex(match[3] + "" + match[3]),
  1107. format: named ? "name" : "hex"
  1108. };
  1109. }
  1110. return false;
  1111. }
  1112. function validateWCAG2Parms(parms) {
  1113. // return valid WCAG2 parms for isReadable.
  1114. // If input parms are invalid, return {"level":"AA", "size":"small"}
  1115. var level, size;
  1116. parms = parms || {
  1117. level: "AA",
  1118. size: "small"
  1119. };
  1120. level = (parms.level || "AA").toUpperCase();
  1121. size = (parms.size || "small").toLowerCase();
  1122. if (level !== "AA" && level !== "AAA") {
  1123. level = "AA";
  1124. }
  1125. if (size !== "small" && size !== "large") {
  1126. size = "small";
  1127. }
  1128. return {
  1129. level: level,
  1130. size: size
  1131. };
  1132. }
  1133. return tinycolor;
  1134. }));