UNPKG

12.4 kBJavaScriptView Raw
1"use strict";
2// https://github.com/imathis/hsl-picker/blob/master/assets/javascripts/modules/color.coffee
3const rHex3 = /^#[0-9a-f]{3}$/;
4const rHex6 = /^#[0-9a-f]{6}$/;
5const rRGB = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(0?\.?\d+)?\s*\)$/;
6const rHSL = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,?\s*(0?\.?\d+)?\s*\)$/;
7// https://www.w3.org/TR/css3-color/#svg-color
8const colorNames = {
9 aliceblue: { r: 240, g: 248, b: 255, a: 1 },
10 antiquewhite: { r: 250, g: 235, b: 215, a: 1 },
11 aqua: { r: 0, g: 255, b: 255, a: 1 },
12 aquamarine: { r: 127, g: 255, b: 212, a: 1 },
13 azure: { r: 240, g: 255, b: 255, a: 1 },
14 beige: { r: 245, g: 245, b: 220, a: 1 },
15 bisque: { r: 255, g: 228, b: 196, a: 1 },
16 black: { r: 0, g: 0, b: 0, a: 1 },
17 blanchedalmond: { r: 255, g: 235, b: 205, a: 1 },
18 blue: { r: 0, g: 0, b: 255, a: 1 },
19 blueviolet: { r: 138, g: 43, b: 226, a: 1 },
20 brown: { r: 165, g: 42, b: 42, a: 1 },
21 burlywood: { r: 222, g: 184, b: 135, a: 1 },
22 cadetblue: { r: 95, g: 158, b: 160, a: 1 },
23 chartreuse: { r: 127, g: 255, b: 0, a: 1 },
24 chocolate: { r: 210, g: 105, b: 30, a: 1 },
25 coral: { r: 255, g: 127, b: 80, a: 1 },
26 cornflowerblue: { r: 100, g: 149, b: 237, a: 1 },
27 cornsilk: { r: 255, g: 248, b: 220, a: 1 },
28 crimson: { r: 220, g: 20, b: 60, a: 1 },
29 cyan: { r: 0, g: 255, b: 255, a: 1 },
30 darkblue: { r: 0, g: 0, b: 139, a: 1 },
31 darkcyan: { r: 0, g: 139, b: 139, a: 1 },
32 darkgoldenrod: { r: 184, g: 134, b: 11, a: 1 },
33 darkgray: { r: 169, g: 169, b: 169, a: 1 },
34 darkgreen: { r: 0, g: 100, b: 0, a: 1 },
35 darkgrey: { r: 169, g: 169, b: 169, a: 1 },
36 darkkhaki: { r: 189, g: 183, b: 107, a: 1 },
37 darkmagenta: { r: 139, g: 0, b: 139, a: 1 },
38 darkolivegreen: { r: 85, g: 107, b: 47, a: 1 },
39 darkorange: { r: 255, g: 140, b: 0, a: 1 },
40 darkorchid: { r: 153, g: 50, b: 204, a: 1 },
41 darkred: { r: 139, g: 0, b: 0, a: 1 },
42 darksalmon: { r: 233, g: 150, b: 122, a: 1 },
43 darkseagreen: { r: 143, g: 188, b: 143, a: 1 },
44 darkslateblue: { r: 72, g: 61, b: 139, a: 1 },
45 darkslategray: { r: 47, g: 79, b: 79, a: 1 },
46 darkslategrey: { r: 47, g: 79, b: 79, a: 1 },
47 darkturquoise: { r: 0, g: 206, b: 209, a: 1 },
48 darkviolet: { r: 148, g: 0, b: 211, a: 1 },
49 deeppink: { r: 255, g: 20, b: 147, a: 1 },
50 deepskyblue: { r: 0, g: 191, b: 255, a: 1 },
51 dimgray: { r: 105, g: 105, b: 105, a: 1 },
52 dimgrey: { r: 105, g: 105, b: 105, a: 1 },
53 dodgerblue: { r: 30, g: 144, b: 255, a: 1 },
54 firebrick: { r: 178, g: 34, b: 34, a: 1 },
55 floralwhite: { r: 255, g: 250, b: 240, a: 1 },
56 forestgreen: { r: 34, g: 139, b: 34, a: 1 },
57 fuchsia: { r: 255, g: 0, b: 255, a: 1 },
58 gainsboro: { r: 220, g: 220, b: 220, a: 1 },
59 ghostwhite: { r: 248, g: 248, b: 255, a: 1 },
60 gold: { r: 255, g: 215, b: 0, a: 1 },
61 goldenrod: { r: 218, g: 165, b: 32, a: 1 },
62 gray: { r: 128, g: 128, b: 128, a: 1 },
63 green: { r: 0, g: 128, b: 0, a: 1 },
64 greenyellow: { r: 173, g: 255, b: 47, a: 1 },
65 grey: { r: 128, g: 128, b: 128, a: 1 },
66 honeydew: { r: 240, g: 255, b: 240, a: 1 },
67 hotpink: { r: 255, g: 105, b: 180, a: 1 },
68 indianred: { r: 205, g: 92, b: 92, a: 1 },
69 indigo: { r: 75, g: 0, b: 130, a: 1 },
70 ivory: { r: 255, g: 255, b: 240, a: 1 },
71 khaki: { r: 240, g: 230, b: 140, a: 1 },
72 lavender: { r: 230, g: 230, b: 250, a: 1 },
73 lavenderblush: { r: 255, g: 240, b: 245, a: 1 },
74 lawngreen: { r: 124, g: 252, b: 0, a: 1 },
75 lemonchiffon: { r: 255, g: 250, b: 205, a: 1 },
76 lightblue: { r: 173, g: 216, b: 230, a: 1 },
77 lightcoral: { r: 240, g: 128, b: 128, a: 1 },
78 lightcyan: { r: 224, g: 255, b: 255, a: 1 },
79 lightgoldenrodyellow: { r: 250, g: 250, b: 210, a: 1 },
80 lightgray: { r: 211, g: 211, b: 211, a: 1 },
81 lightgreen: { r: 144, g: 238, b: 144, a: 1 },
82 lightgrey: { r: 211, g: 211, b: 211, a: 1 },
83 lightpink: { r: 255, g: 182, b: 193, a: 1 },
84 lightsalmon: { r: 255, g: 160, b: 122, a: 1 },
85 lightseagreen: { r: 32, g: 178, b: 170, a: 1 },
86 lightskyblue: { r: 135, g: 206, b: 250, a: 1 },
87 lightslategray: { r: 119, g: 136, b: 153, a: 1 },
88 lightslategrey: { r: 119, g: 136, b: 153, a: 1 },
89 lightsteelblue: { r: 176, g: 196, b: 222, a: 1 },
90 lightyellow: { r: 255, g: 255, b: 224, a: 1 },
91 lime: { r: 0, g: 255, b: 0, a: 1 },
92 limegreen: { r: 50, g: 205, b: 50, a: 1 },
93 linen: { r: 250, g: 240, b: 230, a: 1 },
94 magenta: { r: 255, g: 0, b: 255, a: 1 },
95 maroon: { r: 128, g: 0, b: 0, a: 1 },
96 mediumaquamarine: { r: 102, g: 205, b: 170, a: 1 },
97 mediumblue: { r: 0, g: 0, b: 205, a: 1 },
98 mediumorchid: { r: 186, g: 85, b: 211, a: 1 },
99 mediumpurple: { r: 147, g: 112, b: 219, a: 1 },
100 mediumseagreen: { r: 60, g: 179, b: 113, a: 1 },
101 mediumslateblue: { r: 123, g: 104, b: 238, a: 1 },
102 mediumspringgreen: { r: 0, g: 250, b: 154, a: 1 },
103 mediumturquoise: { r: 72, g: 209, b: 204, a: 1 },
104 mediumvioletred: { r: 199, g: 21, b: 133, a: 1 },
105 midnightblue: { r: 25, g: 25, b: 112, a: 1 },
106 mintcream: { r: 245, g: 255, b: 250, a: 1 },
107 mistyrose: { r: 255, g: 228, b: 225, a: 1 },
108 moccasin: { r: 255, g: 228, b: 181, a: 1 },
109 navajowhite: { r: 255, g: 222, b: 173, a: 1 },
110 navy: { r: 0, g: 0, b: 128, a: 1 },
111 oldlace: { r: 253, g: 245, b: 230, a: 1 },
112 olive: { r: 128, g: 128, b: 0, a: 1 },
113 olivedrab: { r: 107, g: 142, b: 35, a: 1 },
114 orange: { r: 255, g: 165, b: 0, a: 1 },
115 orangered: { r: 255, g: 69, b: 0, a: 1 },
116 orchid: { r: 218, g: 112, b: 214, a: 1 },
117 palegoldenrod: { r: 238, g: 232, b: 170, a: 1 },
118 palegreen: { r: 152, g: 251, b: 152, a: 1 },
119 paleturquoise: { r: 175, g: 238, b: 238, a: 1 },
120 palevioletred: { r: 219, g: 112, b: 147, a: 1 },
121 papayawhip: { r: 255, g: 239, b: 213, a: 1 },
122 peachpuff: { r: 255, g: 218, b: 185, a: 1 },
123 peru: { r: 205, g: 133, b: 63, a: 1 },
124 pink: { r: 255, g: 192, b: 203, a: 1 },
125 plum: { r: 221, g: 160, b: 221, a: 1 },
126 powderblue: { r: 176, g: 224, b: 230, a: 1 },
127 purple: { r: 128, g: 0, b: 128, a: 1 },
128 red: { r: 255, g: 0, b: 0, a: 1 },
129 rosybrown: { r: 188, g: 143, b: 143, a: 1 },
130 royalblue: { r: 65, g: 105, b: 225, a: 1 },
131 saddlebrown: { r: 139, g: 69, b: 19, a: 1 },
132 salmon: { r: 250, g: 128, b: 114, a: 1 },
133 sandybrown: { r: 244, g: 164, b: 96, a: 1 },
134 seagreen: { r: 46, g: 139, b: 87, a: 1 },
135 seashell: { r: 255, g: 245, b: 238, a: 1 },
136 sienna: { r: 160, g: 82, b: 45, a: 1 },
137 silver: { r: 192, g: 192, b: 192, a: 1 },
138 skyblue: { r: 135, g: 206, b: 235, a: 1 },
139 slateblue: { r: 106, g: 90, b: 205, a: 1 },
140 slategray: { r: 112, g: 128, b: 144, a: 1 },
141 slategrey: { r: 112, g: 128, b: 144, a: 1 },
142 snow: { r: 255, g: 250, b: 250, a: 1 },
143 springgreen: { r: 0, g: 255, b: 127, a: 1 },
144 steelblue: { r: 70, g: 130, b: 180, a: 1 },
145 tan: { r: 210, g: 180, b: 140, a: 1 },
146 teal: { r: 0, g: 128, b: 128, a: 1 },
147 thistle: { r: 216, g: 191, b: 216, a: 1 },
148 tomato: { r: 255, g: 99, b: 71, a: 1 },
149 turquoise: { r: 64, g: 224, b: 208, a: 1 },
150 violet: { r: 238, g: 130, b: 238, a: 1 },
151 wheat: { r: 245, g: 222, b: 179, a: 1 },
152 white: { r: 255, g: 255, b: 255, a: 1 },
153 whitesmoke: { r: 245, g: 245, b: 245, a: 1 },
154 yellow: { r: 255, g: 255, b: 0, a: 1 },
155 yellowgreen: { r: 154, g: 205, b: 50, a: 1 }
156};
157const convertHue = (p, q, h) => {
158 if (h < 0)
159 h++;
160 if (h > 1)
161 h--;
162 let color;
163 if (h * 6 < 1) {
164 color = p + ((q - p) * h * 6);
165 }
166 else if (h * 2 < 1) {
167 color = q;
168 }
169 else if (h * 3 < 2) {
170 color = p + ((q - p) * ((2 / 3) - h) * 6);
171 }
172 else {
173 color = p;
174 }
175 return Math.round(color * 255);
176};
177const convertRGB = (value) => {
178 const str = value.toString(16);
179 if (value < 16)
180 return `0${str}`;
181 return str;
182};
183const mixValue = (a, b, ratio) => a + ((b - a) * ratio);
184class Color {
185 /**
186 * @param {string|{ r: number; g: number; b: number; a: number;}} color
187 */
188 constructor(color) {
189 if (typeof color === 'string') {
190 this._parse(color);
191 }
192 else if (color != null && typeof color === 'object') {
193 this.r = color.r | 0;
194 this.g = color.g | 0;
195 this.b = color.b | 0;
196 this.a = +color.a;
197 }
198 else {
199 throw new TypeError('color is required!');
200 }
201 if (this.r < 0 || this.r > 255
202 || this.g < 0 || this.g > 255
203 || this.b < 0 || this.b > 255
204 || this.a < 0 || this.a > 1) {
205 throw new RangeError(`{r: ${this.r}, g: ${this.g}, b: ${this.b}, a: ${this.a}} is invalid.`);
206 }
207 }
208 /**
209 * @param {string} color
210 */
211 _parse(color) {
212 color = color.toLowerCase();
213 if (Object.prototype.hasOwnProperty.call(colorNames, color)) {
214 const obj = colorNames[color];
215 this.r = obj.r;
216 this.g = obj.g;
217 this.b = obj.b;
218 this.a = obj.a;
219 return;
220 }
221 if (rHex3.test(color)) {
222 const txt = color.substring(1);
223 const code = parseInt(txt, 16);
224 this.r = ((code & 0xF00) >> 8) * 17;
225 this.g = ((code & 0xF0) >> 4) * 17;
226 this.b = (code & 0xF) * 17;
227 this.a = 1;
228 return;
229 }
230 if (rHex6.test(color)) {
231 const txt = color.substring(1);
232 const code = parseInt(txt, 16);
233 this.r = (code & 0xFF0000) >> 16;
234 this.g = (code & 0xFF00) >> 8;
235 this.b = code & 0xFF;
236 this.a = 1;
237 return;
238 }
239 let match = color.match(rRGB);
240 if (match) {
241 this.r = Number(match[1]) | 0;
242 this.g = Number(match[2]) | 0;
243 this.b = Number(match[3]) | 0;
244 this.a = match[4] ? +match[4] : 1;
245 return;
246 }
247 match = color.match(rHSL);
248 if (match) {
249 const h = +match[1] / 360;
250 const s = +match[2] / 100;
251 const l = +match[3] / 100;
252 this.a = match[4] ? +match[4] : 1;
253 if (!s) {
254 this.r = l * 255;
255 this.g = this.r;
256 this.b = this.r;
257 }
258 const q = l < 0.5 ? l * (1 + s) : l + s - (l * s);
259 const p = (2 * l) - q;
260 const rt = h + (1 / 3);
261 const gt = h;
262 const bt = h - (1 / 3);
263 this.r = convertHue(p, q, rt);
264 this.g = convertHue(p, q, gt);
265 this.b = convertHue(p, q, bt);
266 return;
267 }
268 throw new Error(`${color} is not a supported color format.`);
269 }
270 toString() {
271 if (this.a === 1) {
272 const r = convertRGB(this.r);
273 const g = convertRGB(this.g);
274 const b = convertRGB(this.b);
275 if (this.r % 17 || this.g % 17 || this.b % 17) {
276 return `#${r}${g}${b}`;
277 }
278 return `#${r[0]}${g[0]}${b[0]}`;
279 }
280 return `rgba(${this.r}, ${this.g}, ${this.b}, ${parseFloat(this.a.toFixed(2))})`;
281 }
282 /**
283 * @param {string|{ r: number; g: number; b: number; a: number;}} color
284 * @param {number} ratio
285 */
286 mix(color, ratio) {
287 if (ratio > 1 || ratio < 0) {
288 throw new RangeError('Valid numbers is only between 0 and 1.');
289 }
290 switch (ratio) {
291 case 0:
292 return new Color(this);
293 case 1:
294 return new Color(color);
295 }
296 return new Color({
297 r: Math.round(mixValue(this.r, color.r, ratio)),
298 g: Math.round(mixValue(this.g, color.g, ratio)),
299 b: Math.round(mixValue(this.b, color.b, ratio)),
300 a: mixValue(this.a, color.a, ratio)
301 });
302 }
303}
304module.exports = Color;
305//# sourceMappingURL=color.js.map
\No newline at end of file