83445e8db16049210e59fe3f595ac6de81687eaaeff422e14bd23793a8c1dc2d244c1887caba13ed5c31bfebd51ce6063a5873d9449b6dc04e4ec7c018befd 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. import { numberInputToObject, rgbaToHex, rgbToHex, rgbToHsl, rgbToHsv } from './conversion.js';
  2. import { names } from './css-color-names.js';
  3. import { inputToRGB } from './format-input';
  4. import { bound01, boundAlpha, clamp01 } from './util.js';
  5. var TinyColor = /** @class */ (function () {
  6. function TinyColor(color, opts) {
  7. if (color === void 0) { color = ''; }
  8. if (opts === void 0) { opts = {}; }
  9. var _a;
  10. // If input is already a tinycolor, return itself
  11. if (color instanceof TinyColor) {
  12. // eslint-disable-next-line no-constructor-return
  13. return color;
  14. }
  15. if (typeof color === 'number') {
  16. color = numberInputToObject(color);
  17. }
  18. this.originalInput = color;
  19. var rgb = inputToRGB(color);
  20. this.originalInput = color;
  21. this.r = rgb.r;
  22. this.g = rgb.g;
  23. this.b = rgb.b;
  24. this.a = rgb.a;
  25. this.roundA = Math.round(100 * this.a) / 100;
  26. this.format = (_a = opts.format) !== null && _a !== void 0 ? _a : rgb.format;
  27. this.gradientType = opts.gradientType;
  28. // Don't let the range of [0,255] come back in [0,1].
  29. // Potentially lose a little bit of precision here, but will fix issues where
  30. // .5 gets interpreted as half of the total, instead of half of 1
  31. // If it was supposed to be 128, this was already taken care of by `inputToRgb`
  32. if (this.r < 1) {
  33. this.r = Math.round(this.r);
  34. }
  35. if (this.g < 1) {
  36. this.g = Math.round(this.g);
  37. }
  38. if (this.b < 1) {
  39. this.b = Math.round(this.b);
  40. }
  41. this.isValid = rgb.ok;
  42. }
  43. TinyColor.prototype.isDark = function () {
  44. return this.getBrightness() < 128;
  45. };
  46. TinyColor.prototype.isLight = function () {
  47. return !this.isDark();
  48. };
  49. /**
  50. * Returns the perceived brightness of the color, from 0-255.
  51. */
  52. TinyColor.prototype.getBrightness = function () {
  53. // http://www.w3.org/TR/AERT#color-contrast
  54. var rgb = this.toRgb();
  55. return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
  56. };
  57. /**
  58. * Returns the perceived luminance of a color, from 0-1.
  59. */
  60. TinyColor.prototype.getLuminance = function () {
  61. // http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
  62. var rgb = this.toRgb();
  63. var R;
  64. var G;
  65. var B;
  66. var RsRGB = rgb.r / 255;
  67. var GsRGB = rgb.g / 255;
  68. var BsRGB = rgb.b / 255;
  69. if (RsRGB <= 0.03928) {
  70. R = RsRGB / 12.92;
  71. }
  72. else {
  73. // eslint-disable-next-line prefer-exponentiation-operator
  74. R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
  75. }
  76. if (GsRGB <= 0.03928) {
  77. G = GsRGB / 12.92;
  78. }
  79. else {
  80. // eslint-disable-next-line prefer-exponentiation-operator
  81. G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
  82. }
  83. if (BsRGB <= 0.03928) {
  84. B = BsRGB / 12.92;
  85. }
  86. else {
  87. // eslint-disable-next-line prefer-exponentiation-operator
  88. B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
  89. }
  90. return 0.2126 * R + 0.7152 * G + 0.0722 * B;
  91. };
  92. /**
  93. * Returns the alpha value of a color, from 0-1.
  94. */
  95. TinyColor.prototype.getAlpha = function () {
  96. return this.a;
  97. };
  98. /**
  99. * Sets the alpha value on the current color.
  100. *
  101. * @param alpha - The new alpha value. The accepted range is 0-1.
  102. */
  103. TinyColor.prototype.setAlpha = function (alpha) {
  104. this.a = boundAlpha(alpha);
  105. this.roundA = Math.round(100 * this.a) / 100;
  106. return this;
  107. };
  108. /**
  109. * Returns whether the color is monochrome.
  110. */
  111. TinyColor.prototype.isMonochrome = function () {
  112. var s = this.toHsl().s;
  113. return s === 0;
  114. };
  115. /**
  116. * Returns the object as a HSVA object.
  117. */
  118. TinyColor.prototype.toHsv = function () {
  119. var hsv = rgbToHsv(this.r, this.g, this.b);
  120. return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this.a };
  121. };
  122. /**
  123. * Returns the hsva values interpolated into a string with the following format:
  124. * "hsva(xxx, xxx, xxx, xx)".
  125. */
  126. TinyColor.prototype.toHsvString = function () {
  127. var hsv = rgbToHsv(this.r, this.g, this.b);
  128. var h = Math.round(hsv.h * 360);
  129. var s = Math.round(hsv.s * 100);
  130. var v = Math.round(hsv.v * 100);
  131. return this.a === 1 ? "hsv(".concat(h, ", ").concat(s, "%, ").concat(v, "%)") : "hsva(".concat(h, ", ").concat(s, "%, ").concat(v, "%, ").concat(this.roundA, ")");
  132. };
  133. /**
  134. * Returns the object as a HSLA object.
  135. */
  136. TinyColor.prototype.toHsl = function () {
  137. var hsl = rgbToHsl(this.r, this.g, this.b);
  138. return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this.a };
  139. };
  140. /**
  141. * Returns the hsla values interpolated into a string with the following format:
  142. * "hsla(xxx, xxx, xxx, xx)".
  143. */
  144. TinyColor.prototype.toHslString = function () {
  145. var hsl = rgbToHsl(this.r, this.g, this.b);
  146. var h = Math.round(hsl.h * 360);
  147. var s = Math.round(hsl.s * 100);
  148. var l = Math.round(hsl.l * 100);
  149. return this.a === 1 ? "hsl(".concat(h, ", ").concat(s, "%, ").concat(l, "%)") : "hsla(".concat(h, ", ").concat(s, "%, ").concat(l, "%, ").concat(this.roundA, ")");
  150. };
  151. /**
  152. * Returns the hex value of the color.
  153. * @param allow3Char will shorten hex value to 3 char if possible
  154. */
  155. TinyColor.prototype.toHex = function (allow3Char) {
  156. if (allow3Char === void 0) { allow3Char = false; }
  157. return rgbToHex(this.r, this.g, this.b, allow3Char);
  158. };
  159. /**
  160. * Returns the hex value of the color -with a # prefixed.
  161. * @param allow3Char will shorten hex value to 3 char if possible
  162. */
  163. TinyColor.prototype.toHexString = function (allow3Char) {
  164. if (allow3Char === void 0) { allow3Char = false; }
  165. return '#' + this.toHex(allow3Char);
  166. };
  167. /**
  168. * Returns the hex 8 value of the color.
  169. * @param allow4Char will shorten hex value to 4 char if possible
  170. */
  171. TinyColor.prototype.toHex8 = function (allow4Char) {
  172. if (allow4Char === void 0) { allow4Char = false; }
  173. return rgbaToHex(this.r, this.g, this.b, this.a, allow4Char);
  174. };
  175. /**
  176. * Returns the hex 8 value of the color -with a # prefixed.
  177. * @param allow4Char will shorten hex value to 4 char if possible
  178. */
  179. TinyColor.prototype.toHex8String = function (allow4Char) {
  180. if (allow4Char === void 0) { allow4Char = false; }
  181. return '#' + this.toHex8(allow4Char);
  182. };
  183. /**
  184. * Returns the shorter hex value of the color depends on its alpha -with a # prefixed.
  185. * @param allowShortChar will shorten hex value to 3 or 4 char if possible
  186. */
  187. TinyColor.prototype.toHexShortString = function (allowShortChar) {
  188. if (allowShortChar === void 0) { allowShortChar = false; }
  189. return this.a === 1 ? this.toHexString(allowShortChar) : this.toHex8String(allowShortChar);
  190. };
  191. /**
  192. * Returns the object as a RGBA object.
  193. */
  194. TinyColor.prototype.toRgb = function () {
  195. return {
  196. r: Math.round(this.r),
  197. g: Math.round(this.g),
  198. b: Math.round(this.b),
  199. a: this.a,
  200. };
  201. };
  202. /**
  203. * Returns the RGBA values interpolated into a string with the following format:
  204. * "RGBA(xxx, xxx, xxx, xx)".
  205. */
  206. TinyColor.prototype.toRgbString = function () {
  207. var r = Math.round(this.r);
  208. var g = Math.round(this.g);
  209. var b = Math.round(this.b);
  210. return this.a === 1 ? "rgb(".concat(r, ", ").concat(g, ", ").concat(b, ")") : "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(this.roundA, ")");
  211. };
  212. /**
  213. * Returns the object as a RGBA object.
  214. */
  215. TinyColor.prototype.toPercentageRgb = function () {
  216. var fmt = function (x) { return "".concat(Math.round(bound01(x, 255) * 100), "%"); };
  217. return {
  218. r: fmt(this.r),
  219. g: fmt(this.g),
  220. b: fmt(this.b),
  221. a: this.a,
  222. };
  223. };
  224. /**
  225. * Returns the RGBA relative values interpolated into a string
  226. */
  227. TinyColor.prototype.toPercentageRgbString = function () {
  228. var rnd = function (x) { return Math.round(bound01(x, 255) * 100); };
  229. return this.a === 1
  230. ? "rgb(".concat(rnd(this.r), "%, ").concat(rnd(this.g), "%, ").concat(rnd(this.b), "%)")
  231. : "rgba(".concat(rnd(this.r), "%, ").concat(rnd(this.g), "%, ").concat(rnd(this.b), "%, ").concat(this.roundA, ")");
  232. };
  233. /**
  234. * The 'real' name of the color -if there is one.
  235. */
  236. TinyColor.prototype.toName = function () {
  237. if (this.a === 0) {
  238. return 'transparent';
  239. }
  240. if (this.a < 1) {
  241. return false;
  242. }
  243. var hex = '#' + rgbToHex(this.r, this.g, this.b, false);
  244. for (var _i = 0, _a = Object.entries(names); _i < _a.length; _i++) {
  245. var _b = _a[_i], key = _b[0], value = _b[1];
  246. if (hex === value) {
  247. return key;
  248. }
  249. }
  250. return false;
  251. };
  252. TinyColor.prototype.toString = function (format) {
  253. var formatSet = Boolean(format);
  254. format = format !== null && format !== void 0 ? format : this.format;
  255. var formattedString = false;
  256. var hasAlpha = this.a < 1 && this.a >= 0;
  257. var needsAlphaFormat = !formatSet && hasAlpha && (format.startsWith('hex') || format === 'name');
  258. if (needsAlphaFormat) {
  259. // Special case for "transparent", all other non-alpha formats
  260. // will return rgba when there is transparency.
  261. if (format === 'name' && this.a === 0) {
  262. return this.toName();
  263. }
  264. return this.toRgbString();
  265. }
  266. if (format === 'rgb') {
  267. formattedString = this.toRgbString();
  268. }
  269. if (format === 'prgb') {
  270. formattedString = this.toPercentageRgbString();
  271. }
  272. if (format === 'hex' || format === 'hex6') {
  273. formattedString = this.toHexString();
  274. }
  275. if (format === 'hex3') {
  276. formattedString = this.toHexString(true);
  277. }
  278. if (format === 'hex4') {
  279. formattedString = this.toHex8String(true);
  280. }
  281. if (format === 'hex8') {
  282. formattedString = this.toHex8String();
  283. }
  284. if (format === 'name') {
  285. formattedString = this.toName();
  286. }
  287. if (format === 'hsl') {
  288. formattedString = this.toHslString();
  289. }
  290. if (format === 'hsv') {
  291. formattedString = this.toHsvString();
  292. }
  293. return formattedString || this.toHexString();
  294. };
  295. TinyColor.prototype.toNumber = function () {
  296. return (Math.round(this.r) << 16) + (Math.round(this.g) << 8) + Math.round(this.b);
  297. };
  298. TinyColor.prototype.clone = function () {
  299. return new TinyColor(this.toString());
  300. };
  301. /**
  302. * Lighten the color a given amount. Providing 100 will always return white.
  303. * @param amount - valid between 1-100
  304. */
  305. TinyColor.prototype.lighten = function (amount) {
  306. if (amount === void 0) { amount = 10; }
  307. var hsl = this.toHsl();
  308. hsl.l += amount / 100;
  309. hsl.l = clamp01(hsl.l);
  310. return new TinyColor(hsl);
  311. };
  312. /**
  313. * Brighten the color a given amount, from 0 to 100.
  314. * @param amount - valid between 1-100
  315. */
  316. TinyColor.prototype.brighten = function (amount) {
  317. if (amount === void 0) { amount = 10; }
  318. var rgb = this.toRgb();
  319. rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100))));
  320. rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100))));
  321. rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100))));
  322. return new TinyColor(rgb);
  323. };
  324. /**
  325. * Darken the color a given amount, from 0 to 100.
  326. * Providing 100 will always return black.
  327. * @param amount - valid between 1-100
  328. */
  329. TinyColor.prototype.darken = function (amount) {
  330. if (amount === void 0) { amount = 10; }
  331. var hsl = this.toHsl();
  332. hsl.l -= amount / 100;
  333. hsl.l = clamp01(hsl.l);
  334. return new TinyColor(hsl);
  335. };
  336. /**
  337. * Mix the color with pure white, from 0 to 100.
  338. * Providing 0 will do nothing, providing 100 will always return white.
  339. * @param amount - valid between 1-100
  340. */
  341. TinyColor.prototype.tint = function (amount) {
  342. if (amount === void 0) { amount = 10; }
  343. return this.mix('white', amount);
  344. };
  345. /**
  346. * Mix the color with pure black, from 0 to 100.
  347. * Providing 0 will do nothing, providing 100 will always return black.
  348. * @param amount - valid between 1-100
  349. */
  350. TinyColor.prototype.shade = function (amount) {
  351. if (amount === void 0) { amount = 10; }
  352. return this.mix('black', amount);
  353. };
  354. /**
  355. * Desaturate the color a given amount, from 0 to 100.
  356. * Providing 100 will is the same as calling greyscale
  357. * @param amount - valid between 1-100
  358. */
  359. TinyColor.prototype.desaturate = function (amount) {
  360. if (amount === void 0) { amount = 10; }
  361. var hsl = this.toHsl();
  362. hsl.s -= amount / 100;
  363. hsl.s = clamp01(hsl.s);
  364. return new TinyColor(hsl);
  365. };
  366. /**
  367. * Saturate the color a given amount, from 0 to 100.
  368. * @param amount - valid between 1-100
  369. */
  370. TinyColor.prototype.saturate = function (amount) {
  371. if (amount === void 0) { amount = 10; }
  372. var hsl = this.toHsl();
  373. hsl.s += amount / 100;
  374. hsl.s = clamp01(hsl.s);
  375. return new TinyColor(hsl);
  376. };
  377. /**
  378. * Completely desaturates a color into greyscale.
  379. * Same as calling `desaturate(100)`
  380. */
  381. TinyColor.prototype.greyscale = function () {
  382. return this.desaturate(100);
  383. };
  384. /**
  385. * Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
  386. * Values outside of this range will be wrapped into this range.
  387. */
  388. TinyColor.prototype.spin = function (amount) {
  389. var hsl = this.toHsl();
  390. var hue = (hsl.h + amount) % 360;
  391. hsl.h = hue < 0 ? 360 + hue : hue;
  392. return new TinyColor(hsl);
  393. };
  394. /**
  395. * Mix the current color a given amount with another color, from 0 to 100.
  396. * 0 means no mixing (return current color).
  397. */
  398. TinyColor.prototype.mix = function (color, amount) {
  399. if (amount === void 0) { amount = 50; }
  400. var rgb1 = this.toRgb();
  401. var rgb2 = new TinyColor(color).toRgb();
  402. var p = amount / 100;
  403. var rgba = {
  404. r: (rgb2.r - rgb1.r) * p + rgb1.r,
  405. g: (rgb2.g - rgb1.g) * p + rgb1.g,
  406. b: (rgb2.b - rgb1.b) * p + rgb1.b,
  407. a: (rgb2.a - rgb1.a) * p + rgb1.a,
  408. };
  409. return new TinyColor(rgba);
  410. };
  411. TinyColor.prototype.analogous = function (results, slices) {
  412. if (results === void 0) { results = 6; }
  413. if (slices === void 0) { slices = 30; }
  414. var hsl = this.toHsl();
  415. var part = 360 / slices;
  416. var ret = [this];
  417. for (hsl.h = (hsl.h - ((part * results) >> 1) + 720) % 360; --results;) {
  418. hsl.h = (hsl.h + part) % 360;
  419. ret.push(new TinyColor(hsl));
  420. }
  421. return ret;
  422. };
  423. /**
  424. * taken from https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js
  425. */
  426. TinyColor.prototype.complement = function () {
  427. var hsl = this.toHsl();
  428. hsl.h = (hsl.h + 180) % 360;
  429. return new TinyColor(hsl);
  430. };
  431. TinyColor.prototype.monochromatic = function (results) {
  432. if (results === void 0) { results = 6; }
  433. var hsv = this.toHsv();
  434. var h = hsv.h;
  435. var s = hsv.s;
  436. var v = hsv.v;
  437. var res = [];
  438. var modification = 1 / results;
  439. while (results--) {
  440. res.push(new TinyColor({ h: h, s: s, v: v }));
  441. v = (v + modification) % 1;
  442. }
  443. return res;
  444. };
  445. TinyColor.prototype.splitcomplement = function () {
  446. var hsl = this.toHsl();
  447. var h = hsl.h;
  448. return [
  449. this,
  450. new TinyColor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
  451. new TinyColor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l }),
  452. ];
  453. };
  454. /**
  455. * Compute how the color would appear on a background
  456. */
  457. TinyColor.prototype.onBackground = function (background) {
  458. var fg = this.toRgb();
  459. var bg = new TinyColor(background).toRgb();
  460. var alpha = fg.a + bg.a * (1 - fg.a);
  461. return new TinyColor({
  462. r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / alpha,
  463. g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / alpha,
  464. b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / alpha,
  465. a: alpha,
  466. });
  467. };
  468. /**
  469. * Alias for `polyad(3)`
  470. */
  471. TinyColor.prototype.triad = function () {
  472. return this.polyad(3);
  473. };
  474. /**
  475. * Alias for `polyad(4)`
  476. */
  477. TinyColor.prototype.tetrad = function () {
  478. return this.polyad(4);
  479. };
  480. /**
  481. * Get polyad colors, like (for 1, 2, 3, 4, 5, 6, 7, 8, etc...)
  482. * monad, dyad, triad, tetrad, pentad, hexad, heptad, octad, etc...
  483. */
  484. TinyColor.prototype.polyad = function (n) {
  485. var hsl = this.toHsl();
  486. var h = hsl.h;
  487. var result = [this];
  488. var increment = 360 / n;
  489. for (var i = 1; i < n; i++) {
  490. result.push(new TinyColor({ h: (h + i * increment) % 360, s: hsl.s, l: hsl.l }));
  491. }
  492. return result;
  493. };
  494. /**
  495. * compare color vs current color
  496. */
  497. TinyColor.prototype.equals = function (color) {
  498. return this.toRgbString() === new TinyColor(color).toRgbString();
  499. };
  500. return TinyColor;
  501. }());
  502. export { TinyColor };
  503. // kept for backwards compatability with v1
  504. export function tinycolor(color, opts) {
  505. if (color === void 0) { color = ''; }
  506. if (opts === void 0) { opts = {}; }
  507. return new TinyColor(color, opts);
  508. }