UNPKG

14.2 kBJavaScriptView Raw
1/*!
2 * Color Picker
3 *
4 * Pico.css - https://picocss.com
5 * Copyright 2019 - Licensed under MIT
6 */
7
8(function() {
9
10 /**
11 * Config
12 */
13
14 var colors = {
15 target: '#customization article[data-theme="generated"]', // Buttons inserted before target
16 selectorButton: '#customization button[data-color]', // Button selector in Dom
17 selectorTheme: '#customization', // Theme selector in Dom
18 styles: '',
19
20 // Source: https://material.io/design/color/the-color-system.html
21 system: {
22 "red": {
23 "50": "#ffebee",
24 "100": "#ffcdd2",
25 "200": "#ef9a9a",
26 "300": "#e57373",
27 "400": "#ef5350",
28 "500": "#f44336",
29 "600": "#e53935",
30 "700": "#d32f2f",
31 "800": "#c62828",
32 "900": "#b71c1c",
33 "a100": "#ff8a80",
34 "a200": "#ff5252",
35 "a400": "#ff1744",
36 "a700": "#d50000",
37 "inverse": "#FFF"
38 },
39 "pink": {
40 "50": "#fce4ec",
41 "100": "#f8bbd0",
42 "200": "#f48fb1",
43 "300": "#f06292",
44 "400": "#ec407a",
45 "500": "#e91e63",
46 "600": "#d81b60",
47 "700": "#c2185b",
48 "800": "#ad1457",
49 "900": "#880e4f",
50 "a100": "#ff80ab",
51 "a200": "#ff4081",
52 "a400": "#f50057",
53 "a700": "#c51162",
54 "inverse": "#FFF"
55 },
56 "purple": {
57 "50": "#f3e5f5",
58 "100": "#e1bee7",
59 "200": "#ce93d8",
60 "300": "#ba68c8",
61 "400": "#ab47bc",
62 "500": "#9c27b0",
63 "600": "#8e24aa",
64 "700": "#7b1fa2",
65 "800": "#6a1b9a",
66 "900": "#4a148c",
67 "a100": "#ea80fc",
68 "a200": "#e040fb",
69 "a400": "#d500f9",
70 "a700": "#aa00ff",
71 "inverse": "#FFF"
72 },
73 "deep-purple": {
74 "50": "#ede7f6",
75 "100": "#d1c4e9",
76 "200": "#b39ddb",
77 "300": "#9575cd",
78 "400": "#7e57c2",
79 "500": "#673ab7",
80 "600": "#5e35b1",
81 "700": "#512da8",
82 "800": "#4527a0",
83 "900": "#311b92",
84 "a100": "#b388ff",
85 "a200": "#7c4dff",
86 "a400": "#651fff",
87 "a700": "#6200ea",
88 "inverse": "#FFF"
89 },
90 "indigo": {
91 "50": "#e8eaf6",
92 "100": "#c5cae9",
93 "200": "#9fa8da",
94 "300": "#7986cb",
95 "400": "#5c6bc0",
96 "500": "#3f51b5",
97 "600": "#3949ab",
98 "700": "#303f9f",
99 "800": "#283593",
100 "900": "#1a237e",
101 "a100": "#8c9eff",
102 "a200": "#536dfe",
103 "a400": "#3d5afe",
104 "a700": "#304ffe",
105 "inverse": "#FFF"
106 },
107 "blue": {
108 "50": "#e3f2fd",
109 "100": "#bbdefb",
110 "200": "#90caf9",
111 "300": "#64b5f6",
112 "400": "#42a5f5",
113 "500": "#2196f3",
114 "600": "#1e88e5",
115 "700": "#1976d2",
116 "800": "#1565c0",
117 "900": "#0d47a1",
118 "a100": "#82b1ff",
119 "a200": "#448aff",
120 "a400": "#2979ff",
121 "a700": "#2962ff",
122 "inverse": "#FFF"
123 },
124 "light-blue": {
125 "50": "#e1f5fe",
126 "100": "#b3e5fc",
127 "200": "#81d4fa",
128 "300": "#4fc3f7",
129 "400": "#29b6f6",
130 "500": "#03a9f4",
131 "600": "#039be5",
132 "700": "#0288d1",
133 "800": "#0277bd",
134 "900": "#01579b",
135 "a100": "#80d8ff",
136 "a200": "#40c4ff",
137 "a400": "#00b0ff",
138 "a700": "#0091ea",
139 "inverse": "#FFF"
140 },
141 "cyan": {
142 "50": "#e0f7fa",
143 "100": "#b2ebf2",
144 "200": "#80deea",
145 "300": "#4dd0e1",
146 "400": "#26c6da",
147 "500": "#00bcd4",
148 "600": "#00acc1",
149 "700": "#0097a7",
150 "800": "#00838f",
151 "900": "#006064",
152 "a100": "#84ffff",
153 "a200": "#18ffff",
154 "a400": "#00e5ff",
155 "a700": "#00b8d4",
156 "inverse": "#FFF"
157 },
158 "teal": {
159 "50": "#e0f2f1",
160 "100": "#b2dfdb",
161 "200": "#80cbc4",
162 "300": "#4db6ac",
163 "400": "#26a69a",
164 "500": "#009688",
165 "600": "#00897b",
166 "700": "#00796b",
167 "800": "#00695c",
168 "900": "#004d40",
169 "a100": "#a7ffeb",
170 "a200": "#64ffda",
171 "a400": "#1de9b6",
172 "a700": "#00bfa5",
173 "inverse": "#FFF"
174 },
175 "green": {
176 "50": "#e8f5e9",
177 "100": "#c8e6c9",
178 "200": "#a5d6a7",
179 "300": "#81c784",
180 "400": "#66bb6a",
181 "500": "#4caf50",
182 "600": "#43a047",
183 "700": "#388e3c",
184 "800": "#2e7d32",
185 "900": "#1b5e20",
186 "a100": "#b9f6ca",
187 "a200": "#69f0ae",
188 "a400": "#00e676",
189 "a700": "#00c853",
190 "inverse": "#FFF"
191 },
192 "light-green": {
193 "50": "#f1f8e9",
194 "100": "#dcedc8",
195 "200": "#c5e1a5",
196 "300": "#aed581",
197 "400": "#9ccc65",
198 "500": "#8bc34a",
199 "600": "#7cb342",
200 "700": "#689f38",
201 "800": "#558b2f",
202 "900": "#33691e",
203 "a100": "#ccff90",
204 "a200": "#b2ff59",
205 "a400": "#76ff03",
206 "a700": "#64dd17",
207 "inverse": "#FFF"
208 },
209 "lime": {
210 "50": "#f9fbe7",
211 "100": "#f0f4c3",
212 "200": "#e6ee9c",
213 "300": "#dce775",
214 "400": "#d4e157",
215 "500": "#cddc39",
216 "600": "#c0ca33",
217 "700": "#afb42b",
218 "800": "#9e9d24",
219 "900": "#827717",
220 "a100": "#f4ff81",
221 "a200": "#eeff41",
222 "a400": "#c6ff00",
223 "a700": "#aeea00",
224 "inverse": "rgba(0, 0, 0, 0.75)"
225 },
226 "yellow": {
227 "50": "#fffde7",
228 "100": "#fff9c4",
229 "200": "#fff59d",
230 "300": "#fff176",
231 "400": "#ffee58",
232 "500": "#ffeb3b",
233 "600": "#fdd835",
234 "700": "#fbc02d",
235 "800": "#f9a825",
236 "900": "#f57f17",
237 "a100": "#ffff8d",
238 "a200": "#ffff00",
239 "a400": "#ffea00",
240 "a700": "#ffd600",
241 "inverse": "rgba(0, 0, 0, 0.75)"
242 },
243 "amber": {
244 "50": "#fff8e1",
245 "100": "#ffecb3",
246 "200": "#ffe082",
247 "300": "#ffd54f",
248 "400": "#ffca28",
249 "500": "#ffc107",
250 "600": "#ffb300",
251 "700": "#ffa000",
252 "800": "#ff8f00",
253 "900": "#ff6f00",
254 "a100": "#ffe57f",
255 "a200": "#ffd740",
256 "a400": "#ffc400",
257 "a700": "#ffab00",
258 "inverse": "rgba(0, 0, 0, 0.75)"
259 },
260 "orange": {
261 "50": "#fff3e0",
262 "100": "#ffe0b2",
263 "200": "#ffcc80",
264 "300": "#ffb74d",
265 "400": "#ffa726",
266 "500": "#ff9800",
267 "600": "#fb8c00",
268 "700": "#f57c00",
269 "800": "#ef6c00",
270 "900": "#e65100",
271 "a100": "#ffd180",
272 "a200": "#ffab40",
273 "a400": "#ff9100",
274 "a700": "#ff6d00",
275 "inverse": "#FFF"
276 },
277 "deep-orange": {
278 "50": "#fbe9e7",
279 "100": "#ffccbc",
280 "200": "#ffab91",
281 "300": "#ff8a65",
282 "400": "#ff7043",
283 "500": "#ff5722",
284 "600": "#f4511e",
285 "700": "#e64a19",
286 "800": "#d84315",
287 "900": "#bf360c",
288 "a100": "#ff9e80",
289 "a200": "#ff6e40",
290 "a400": "#ff3d00",
291 "a700": "#dd2c00",
292 "inverse": "#FFF"
293 },
294 /*"brown": {
295 "50": "#efebe9",
296 "100": "#d7ccc8",
297 "200": "#bcaaa4",
298 "300": "#a1887f",
299 "400": "#8d6e63",
300 "500": "#795548",
301 "600": "#6d4c41",
302 "700": "#5d4037",
303 "800": "#4e342e",
304 "900": "#3e2723",
305 "inverse": "#FFF"
306 },*/
307 "grey": {
308 "50": "#fafafa",
309 "100": "#f5f5f5",
310 "200": "#eeeeee",
311 "300": "#e0e0e0",
312 "400": "#bdbdbd",
313 "500": "#9e9e9e",
314 "600": "#757575",
315 "700": "#616161",
316 "800": "#424242",
317 "900": "#212121",
318 "inverse": "#FFF"
319 },
320 "blue-grey": {
321 "50": "#eceff1",
322 "100": "#cfd8dc",
323 "200": "#b0bec5",
324 "300": "#90a4ae",
325 "400": "#78909c",
326 "500": "#607d8b",
327 "600": "#546e7a",
328 "700": "#455a64",
329 "800": "#37474f",
330 "900": "#263238",
331 "inverse": "#FFF"
332 }
333 }
334 }
335
336
337
338 /**
339 * Init
340 */
341
342 generateButtons(colors.system);
343 pickColor('pink', colors.system['pink']);
344
345
346
347 /**
348 * Generate Buttons
349 *
350 * @param {object} data
351 */
352
353 function generateButtons(data) {
354
355 // Vars
356 var colorButtons = '';
357
358 // Colors
359 for (var color in data) {
360 if (data.hasOwnProperty(color)) {
361
362 // Buttons
363 colorButtons += '<button data-color="'+ color +'" aria-label="Activate '+ color +' theme"></button>';
364
365 // CSS Styles
366 colors.styles += 'button[data-color="'+ color +'"] {'
367 + 'background-color: '+ data[color]['600'] +'; '
368 + '}'
369
370 + '[data-theme="light"] button[data-color="'+ color +'"]:hover, '
371 + '[data-theme="light"] button[data-color="'+ color +'"]:active, '
372 + '[data-theme="light"] button[data-color="'+ color +'"]:focus {'
373 + 'background-color: '+ data[color]['700'] +'; '
374 + '}'
375
376 + '[data-theme="dark"] button[data-color="'+ color +'"]:hover, '
377 + '[data-theme="dark"] button[data-color="'+ color +'"]:active, '
378 + '[data-theme="dark"] button[data-color="'+ color +'"]:focus {'
379 + 'background-color: '+ data[color]['500'] +'; '
380 + '}';
381 }
382 }
383
384 // Insert buttons
385 var buttons = document.createElement('FIGURE');
386 buttons.innerHTML = colorButtons;
387 document.querySelector(colors.target).before(buttons);
388
389 // Buttons listeners
390 var buttonsAll = document.querySelectorAll(colors.selectorButton);
391 for (var i = 0; i < buttonsAll.length; i++) {
392 buttonsAll[i].addEventListener('click', function(event) {
393 buttonColor = event.target.getAttribute('data-color');
394 pickColor(buttonColor, data[buttonColor]);
395 }, false);
396 }
397
398 // Insert CSS Styles
399 var styles = document.createElement('STYLE');
400 styles.setAttribute('title', 'color-picker');
401 styles.innerHTML = colors.styles;
402 document.querySelector('head').appendChild(styles);
403 }
404
405
406
407 /**
408 * Pick Color
409 *
410 * @param {string} name
411 * @param {object} data
412 */
413
414 function pickColor(name, data) {
415
416 // Generate theme
417 generateTheme(name, data);
418
419 // Clear picked state
420 var buttonsAll = document.querySelectorAll(colors.selectorButton);
421 for (var i = 0; i < buttonsAll.length; i++) {
422 buttonsAll[i].removeAttribute("class");
423 }
424
425 // Set Picked state
426 var buttonPicked = document.querySelector(colors.selectorButton + '[data-color="' + name + '"]');
427 buttonPicked.setAttribute('class', 'picked');
428 }
429
430
431
432 /**
433 * Generate theme
434 *
435 * @param {string} name
436 * @param {object} data
437 */
438
439 function generateTheme(name, data) {
440
441 // Update name and colors in demo code
442 var swap = {
443 '.name' : name.charAt(0).toUpperCase() + name.substring(1) + ' ',
444 '.c500' : data[500],
445 '.c600' : data[600],
446 '.c700' : data[700],
447 '.c600-outline-light' : hexToRgbA(data[600], .125),
448 '.c600-outline-dark' : hexToRgbA(data[600], .25),
449 '.inverse' : data['inverse'],
450 }
451
452 Object.keys(swap).forEach(function(key) {
453 var target = document.querySelectorAll(colors.selectorTheme + ' ' + key);
454 for (var i = 0; i < target.length; ++i) {
455 target[i].innerHTML = swap[key];
456 }
457 });
458
459 // Update CSS Style
460 var generatedStyles = '[data-theme="generated"] {'
461 + '--h4:' + data[700] + ';'
462 + '--primary:' + data[600] + ';'
463 + '--primary-hover:' + data[700] + ';'
464 + '--primary-focus:' + hexToRgbA(data[600], .125) + ';'
465 + '--primary-inverse:' + data['inverse'] + ';'
466 + '}'
467
468 + '@media only screen and (prefers-color-scheme: dark) {'
469 + ':root:not([data-theme="light"]) [data-theme="generated"] {'
470 + '--h4:' + data[400] + ';'
471 + '--primary:' + data[600] + ';'
472 + '--primary-hover:' + data[500] + ';'
473 + '--primary-focus:' + hexToRgbA(data[600], .25) + ';'
474 + '--primary-inverse:' + data['inverse'] + ';'
475 + '}'
476 + '}'
477
478 + '[data-theme="dark"] [data-theme="generated"] {'
479 + '--h4:' + data[500] + ';'
480 + '--primary:' + data[600] + ';'
481 + '--primary-hover:' + data[500] + ';'
482 + '--primary-focus:' + hexToRgbA(data[600], .25) + ';'
483 + '--primary-inverse:' + data['inverse'] + ';'
484 + '}'
485
486 + '[data-theme="generated"] {'
487 + '--primary-border: var(--primary);'
488 + '--primary-hover-border: var(--primary-hover);'
489 + '--input-hover-border: var(--primary);'
490 + '--input-focus: var(--primary-focus);'
491 + '--input-inverse: var(--primary-inverse);'
492 + '}';
493
494 // Insert CSS Styles
495 document.querySelector('style[title="color-picker"]').innerHTML = colors.styles + generatedStyles;
496 }
497
498
499
500 /**
501 * Hexadecimal to Rgba
502 *
503 * @param {string} hex
504 * @param {number} alpha
505 * @return {rgba}
506 */
507
508 function hexToRgbA(hex, alpha) {
509 var c;
510 if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
511 c= hex.substring(1).split('');
512 if(c.length== 3) {
513 c= [c[0], c[0], c[1], c[1], c[2], c[2]];
514 }
515 c= '0x' + c.join('');
516 return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
517 }
518 throw new Error('Bad Hex');
519 }
520
521
522})();