@thednp/color-picker 0.0.1 → 0.0.2-alpha3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/css/color-picker.css +1 -1
- package/dist/css/color-picker.min.css +1 -1
- package/dist/css/color-picker.rtl.css +1 -1
- package/dist/css/color-picker.rtl.min.css +1 -1
- package/dist/js/color-esm.js +1167 -0
- package/dist/js/color-esm.min.js +2 -0
- package/dist/js/color-palette-esm.js +1238 -0
- package/dist/js/color-palette-esm.min.js +2 -0
- package/dist/js/color-palette.js +1246 -0
- package/dist/js/color-palette.min.js +2 -0
- package/dist/js/color-picker-element-esm.js +543 -671
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +545 -673
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +758 -878
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +760 -880
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1175 -0
- package/dist/js/color.min.js +2 -0
- package/package.json +22 -3
- package/src/js/color-palette.js +18 -14
- package/src/js/color-picker-element.js +47 -55
- package/src/js/color-picker.js +137 -325
- package/src/js/color.js +169 -185
- package/src/js/util/getColorMenu.js +12 -7
- package/src/js/util/setMarkup.js +122 -0
- package/src/js/util/version.js +6 -0
- package/types/cp.d.ts +64 -32
- package/types/source/types.d.ts +1 -1
- package/src/js/util/templates.js +0 -10
@@ -1,13 +1,13 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPickerElement v0.0.
|
2
|
+
* ColorPickerElement v0.0.2alpha3 (http://thednp.github.io/color-picker)
|
3
3
|
* Copyright 2022 © thednp
|
4
4
|
* Licensed under MIT (https://github.com/thednp/color-picker/blob/master/LICENSE)
|
5
5
|
*/
|
6
6
|
(function (global, factory) {
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
8
8
|
typeof define === 'function' && define.amd ? define(factory) :
|
9
|
-
(global = global || self, global.ColorPickerElement = factory());
|
10
|
-
}(this, (function () { 'use strict';
|
9
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ColorPickerElement = factory());
|
10
|
+
})(this, (function () { 'use strict';
|
11
11
|
|
12
12
|
/**
|
13
13
|
* Returns the `document` or the `#document` element.
|
@@ -88,14 +88,9 @@
|
|
88
88
|
const getAttribute = (element, attribute) => element.getAttribute(attribute);
|
89
89
|
|
90
90
|
/**
|
91
|
-
*
|
92
|
-
*
|
93
|
-
* @param {(Node | HTMLElement | Element | globalThis)=} node
|
94
|
-
* @returns {HTMLElement | HTMLHeadElement}
|
91
|
+
* A global namespace for `document.head`.
|
95
92
|
*/
|
96
|
-
|
97
|
-
return getDocument(node).head;
|
98
|
-
}
|
93
|
+
const { head: documentHead } = document;
|
99
94
|
|
100
95
|
/**
|
101
96
|
* Shortcut for `window.getComputedStyle(element).propertyName`
|
@@ -116,20 +111,21 @@
|
|
116
111
|
return property in computedStyle ? computedStyle[property] : '';
|
117
112
|
}
|
118
113
|
|
119
|
-
/**
|
120
|
-
* Shortcut for `Object.keys()` static method.
|
121
|
-
* @param {Record<string, any>} obj a target object
|
122
|
-
* @returns {string[]}
|
123
|
-
*/
|
124
|
-
const ObjectKeys = (obj) => Object.keys(obj);
|
125
|
-
|
126
114
|
/**
|
127
115
|
* Shortcut for multiple uses of `HTMLElement.style.propertyName` method.
|
128
116
|
* @param {HTMLElement | Element} element target element
|
129
117
|
* @param {Partial<CSSStyleDeclaration>} styles attribute value
|
130
118
|
*/
|
131
119
|
// @ts-ignore
|
132
|
-
const setElementStyle = (element, styles) => ObjectAssign(element.style, styles);
|
120
|
+
const setElementStyle = (element, styles) => { ObjectAssign(element.style, styles); };
|
121
|
+
|
122
|
+
/**
|
123
|
+
* Shortcut for `String.toLowerCase()`.
|
124
|
+
*
|
125
|
+
* @param {string} source input string
|
126
|
+
* @returns {string} lowercase output string
|
127
|
+
*/
|
128
|
+
const toLowerCase = (source) => source.toLowerCase();
|
133
129
|
|
134
130
|
/**
|
135
131
|
* A list of explicit default non-color values.
|
@@ -147,7 +143,7 @@
|
|
147
143
|
}
|
148
144
|
|
149
145
|
// Color supported formats
|
150
|
-
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', '
|
146
|
+
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsv', 'hwb'];
|
151
147
|
|
152
148
|
// Hue angles
|
153
149
|
const ANGLES = 'deg|rad|grad|turn';
|
@@ -169,10 +165,17 @@
|
|
169
165
|
// Add angles to the mix
|
170
166
|
const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
|
171
167
|
|
168
|
+
// Start & end
|
169
|
+
const START_MATCH = '(?:[\\s|\\(\\s|\\s\\(\\s]+)?';
|
170
|
+
const END_MATCH = '(?:[\\s|\\)\\s]+)?';
|
171
|
+
// Components separation
|
172
|
+
const SEP = '(?:[,|\\s]+)';
|
173
|
+
const SEP2 = '(?:[,|\\/\\s]*)?';
|
174
|
+
|
172
175
|
// Actual matching.
|
173
176
|
// Parentheses and commas are optional, but not required.
|
174
177
|
// Whitespace can take the place of commas or opening paren
|
175
|
-
const PERMISSIVE_MATCH =
|
178
|
+
const PERMISSIVE_MATCH = `${START_MATCH}(${CSS_UNIT2})${SEP}(${CSS_UNIT})${SEP}(${CSS_UNIT})${SEP2}(${CSS_UNIT})?${END_MATCH}`;
|
176
179
|
|
177
180
|
const matchers = {
|
178
181
|
CSS_UNIT: new RegExp(CSS_UNIT2),
|
@@ -205,23 +208,24 @@
|
|
205
208
|
return `${n}`.includes('%');
|
206
209
|
}
|
207
210
|
|
208
|
-
/**
|
209
|
-
* Check to see if string passed in is an angle
|
210
|
-
* @param {string} n testing string
|
211
|
-
* @returns {boolean} the query result
|
212
|
-
*/
|
213
|
-
function isAngle(n) {
|
214
|
-
return ANGLES.split('|').some((a) => `${n}`.includes(a));
|
215
|
-
}
|
216
|
-
|
217
211
|
/**
|
218
212
|
* Check to see if string passed is a web safe colour.
|
213
|
+
* @see https://stackoverflow.com/a/16994164
|
219
214
|
* @param {string} color a colour name, EG: *red*
|
220
215
|
* @returns {boolean} the query result
|
221
216
|
*/
|
222
217
|
function isColorName(color) {
|
223
|
-
|
224
|
-
|
218
|
+
if (nonColors.includes(color)
|
219
|
+
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
220
|
+
|
221
|
+
if (['black', 'white'].includes(color)) return true;
|
222
|
+
|
223
|
+
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
224
|
+
setElementStyle(documentHead, { color });
|
225
|
+
const computedColor = getElementStyle(documentHead, 'color');
|
226
|
+
setElementStyle(documentHead, { color: '' });
|
227
|
+
return computedColor !== c;
|
228
|
+
});
|
225
229
|
}
|
226
230
|
|
227
231
|
/**
|
@@ -242,15 +246,20 @@
|
|
242
246
|
*/
|
243
247
|
function bound01(N, max) {
|
244
248
|
let n = N;
|
245
|
-
if (isOnePointZero(n)) n = '100%';
|
246
249
|
|
247
|
-
|
250
|
+
if (typeof N === 'number'
|
251
|
+
&& Math.min(N, 0) === 0 // round values to 6 decimals Math.round(N * (10 ** 6)) / 10 ** 6
|
252
|
+
&& Math.max(N, 1) === 1) return N;
|
253
|
+
|
254
|
+
if (isOnePointZero(N)) n = '100%';
|
248
255
|
|
249
|
-
|
250
|
-
|
256
|
+
const processPercent = isPercentage(n);
|
257
|
+
n = max === 360
|
258
|
+
? parseFloat(n)
|
259
|
+
: Math.min(max, Math.max(0, parseFloat(n)));
|
251
260
|
|
252
261
|
// Automatically convert percentage into number
|
253
|
-
if (
|
262
|
+
if (processPercent) n = (n * max) / 100;
|
254
263
|
|
255
264
|
// Handle floating point rounding errors
|
256
265
|
if (Math.abs(n - max) < 0.000001) {
|
@@ -261,11 +270,11 @@
|
|
261
270
|
// If n is a hue given in degrees,
|
262
271
|
// wrap around out-of-range values into [0, 360] range
|
263
272
|
// then convert into [0, 1].
|
264
|
-
n = (n < 0 ? (n % max) + max : n % max) /
|
273
|
+
n = (n < 0 ? (n % max) + max : n % max) / max;
|
265
274
|
} else {
|
266
275
|
// If n not a hue given in degrees
|
267
276
|
// Convert into [0, 1] range if it isn't already.
|
268
|
-
n = (n % max) /
|
277
|
+
n = (n % max) / max;
|
269
278
|
}
|
270
279
|
return n;
|
271
280
|
}
|
@@ -300,7 +309,6 @@
|
|
300
309
|
* @returns {string}
|
301
310
|
*/
|
302
311
|
function getRGBFromName(name) {
|
303
|
-
const documentHead = getDocumentHead();
|
304
312
|
setElementStyle(documentHead, { color: name });
|
305
313
|
const colorName = getElementStyle(documentHead, 'color');
|
306
314
|
setElementStyle(documentHead, { color: '' });
|
@@ -346,15 +354,12 @@
|
|
346
354
|
/**
|
347
355
|
* Converts an RGB colour value to HSL.
|
348
356
|
*
|
349
|
-
* @param {number}
|
350
|
-
* @param {number}
|
351
|
-
* @param {number}
|
357
|
+
* @param {number} r Red component [0, 1]
|
358
|
+
* @param {number} g Green component [0, 1]
|
359
|
+
* @param {number} b Blue component [0, 1]
|
352
360
|
* @returns {CP.HSL} {h,s,l} object with [0, 1] ranged values
|
353
361
|
*/
|
354
|
-
function rgbToHsl(
|
355
|
-
const r = R / 255;
|
356
|
-
const g = G / 255;
|
357
|
-
const b = B / 255;
|
362
|
+
function rgbToHsl(r, g, b) {
|
358
363
|
const max = Math.max(r, g, b);
|
359
364
|
const min = Math.min(r, g, b);
|
360
365
|
let h = 0;
|
@@ -366,17 +371,10 @@
|
|
366
371
|
} else {
|
367
372
|
const d = max - min;
|
368
373
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
case g:
|
374
|
-
h = (b - r) / d + 2;
|
375
|
-
break;
|
376
|
-
case b:
|
377
|
-
h = (r - g) / d + 4;
|
378
|
-
break;
|
379
|
-
}
|
374
|
+
if (max === r) h = (g - b) / d + (g < b ? 6 : 0);
|
375
|
+
if (max === g) h = (b - r) / d + 2;
|
376
|
+
if (max === b) h = (r - g) / d + 4;
|
377
|
+
|
380
378
|
h /= 6;
|
381
379
|
}
|
382
380
|
return { h, s, l };
|
@@ -399,21 +397,46 @@
|
|
399
397
|
return p;
|
400
398
|
}
|
401
399
|
|
400
|
+
/**
|
401
|
+
* Converts an HSL colour value to RGB.
|
402
|
+
*
|
403
|
+
* @param {number} h Hue Angle [0, 1]
|
404
|
+
* @param {number} s Saturation [0, 1]
|
405
|
+
* @param {number} l Lightness Angle [0, 1]
|
406
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
407
|
+
*/
|
408
|
+
function hslToRgb(h, s, l) {
|
409
|
+
let r = 0;
|
410
|
+
let g = 0;
|
411
|
+
let b = 0;
|
412
|
+
|
413
|
+
if (s === 0) {
|
414
|
+
// achromatic
|
415
|
+
g = l;
|
416
|
+
b = l;
|
417
|
+
r = l;
|
418
|
+
} else {
|
419
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
420
|
+
const p = 2 * l - q;
|
421
|
+
r = hueToRgb(p, q, h + 1 / 3);
|
422
|
+
g = hueToRgb(p, q, h);
|
423
|
+
b = hueToRgb(p, q, h - 1 / 3);
|
424
|
+
}
|
425
|
+
|
426
|
+
return { r, g, b };
|
427
|
+
}
|
428
|
+
|
402
429
|
/**
|
403
430
|
* Returns an HWB colour object from an RGB colour object.
|
404
431
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
405
432
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
406
433
|
*
|
407
|
-
* @param {number}
|
408
|
-
* @param {number}
|
409
|
-
* @param {number}
|
434
|
+
* @param {number} r Red component [0, 1]
|
435
|
+
* @param {number} g Green [0, 1]
|
436
|
+
* @param {number} b Blue [0, 1]
|
410
437
|
* @return {CP.HWB} {h,w,b} object with [0, 1] ranged values
|
411
438
|
*/
|
412
|
-
function rgbToHwb(
|
413
|
-
const r = R / 255;
|
414
|
-
const g = G / 255;
|
415
|
-
const b = B / 255;
|
416
|
-
|
439
|
+
function rgbToHwb(r, g, b) {
|
417
440
|
let f = 0;
|
418
441
|
let i = 0;
|
419
442
|
const whiteness = Math.min(r, g, b);
|
@@ -443,50 +466,18 @@
|
|
443
466
|
* @param {number} H Hue Angle [0, 1]
|
444
467
|
* @param {number} W Whiteness [0, 1]
|
445
468
|
* @param {number} B Blackness [0, 1]
|
446
|
-
* @return {CP.RGB} {r,g,b} object with [0,
|
469
|
+
* @return {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
447
470
|
*
|
448
471
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
449
472
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
450
473
|
*/
|
451
474
|
function hwbToRgb(H, W, B) {
|
452
475
|
if (W + B >= 1) {
|
453
|
-
const gray =
|
476
|
+
const gray = W / (W + B);
|
454
477
|
return { r: gray, g: gray, b: gray };
|
455
478
|
}
|
456
479
|
let { r, g, b } = hslToRgb(H, 1, 0.5);
|
457
|
-
[r, g, b] = [r, g, b]
|
458
|
-
.map((v) => (v / 255) * (1 - W - B) + W)
|
459
|
-
.map((v) => v * 255);
|
460
|
-
|
461
|
-
return { r, g, b };
|
462
|
-
}
|
463
|
-
|
464
|
-
/**
|
465
|
-
* Converts an HSL colour value to RGB.
|
466
|
-
*
|
467
|
-
* @param {number} h Hue Angle [0, 1]
|
468
|
-
* @param {number} s Saturation [0, 1]
|
469
|
-
* @param {number} l Lightness Angle [0, 1]
|
470
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
471
|
-
*/
|
472
|
-
function hslToRgb(h, s, l) {
|
473
|
-
let r = 0;
|
474
|
-
let g = 0;
|
475
|
-
let b = 0;
|
476
|
-
|
477
|
-
if (s === 0) {
|
478
|
-
// achromatic
|
479
|
-
g = l;
|
480
|
-
b = l;
|
481
|
-
r = l;
|
482
|
-
} else {
|
483
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
484
|
-
const p = 2 * l - q;
|
485
|
-
r = hueToRgb(p, q, h + 1 / 3);
|
486
|
-
g = hueToRgb(p, q, h);
|
487
|
-
b = hueToRgb(p, q, h - 1 / 3);
|
488
|
-
}
|
489
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
480
|
+
[r, g, b] = [r, g, b].map((v) => v * (1 - W - B) + W);
|
490
481
|
|
491
482
|
return { r, g, b };
|
492
483
|
}
|
@@ -494,15 +485,12 @@
|
|
494
485
|
/**
|
495
486
|
* Converts an RGB colour value to HSV.
|
496
487
|
*
|
497
|
-
* @param {number}
|
498
|
-
* @param {number}
|
499
|
-
* @param {number}
|
488
|
+
* @param {number} r Red component [0, 1]
|
489
|
+
* @param {number} g Green [0, 1]
|
490
|
+
* @param {number} b Blue [0, 1]
|
500
491
|
* @returns {CP.HSV} {h,s,v} object with [0, 1] ranged values
|
501
492
|
*/
|
502
|
-
function rgbToHsv(
|
503
|
-
const r = R / 255;
|
504
|
-
const g = G / 255;
|
505
|
-
const b = B / 255;
|
493
|
+
function rgbToHsv(r, g, b) {
|
506
494
|
const max = Math.max(r, g, b);
|
507
495
|
const min = Math.min(r, g, b);
|
508
496
|
let h = 0;
|
@@ -512,17 +500,10 @@
|
|
512
500
|
if (max === min) {
|
513
501
|
h = 0; // achromatic
|
514
502
|
} else {
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
case g:
|
520
|
-
h = (b - r) / d + 2;
|
521
|
-
break;
|
522
|
-
case b:
|
523
|
-
h = (r - g) / d + 4;
|
524
|
-
break;
|
525
|
-
}
|
503
|
+
if (r === max) h = (g - b) / d + (g < b ? 6 : 0);
|
504
|
+
if (g === max) h = (b - r) / d + 2;
|
505
|
+
if (b === max) h = (r - g) / d + 4;
|
506
|
+
|
526
507
|
h /= 6;
|
527
508
|
}
|
528
509
|
return { h, s, v };
|
@@ -549,7 +530,7 @@
|
|
549
530
|
const r = [v, q, p, p, t, v][mod];
|
550
531
|
const g = [t, v, v, q, p, p][mod];
|
551
532
|
const b = [p, p, t, v, v, q][mod];
|
552
|
-
return { r
|
533
|
+
return { r, g, b };
|
553
534
|
}
|
554
535
|
|
555
536
|
/**
|
@@ -573,7 +554,7 @@
|
|
573
554
|
// Return a 3 character hex if possible
|
574
555
|
if (allow3Char && hex[0].charAt(0) === hex[0].charAt(1)
|
575
556
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
576
|
-
|
557
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)) {
|
577
558
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
|
578
559
|
}
|
579
560
|
|
@@ -601,51 +582,34 @@
|
|
601
582
|
// Return a 4 character hex if possible
|
602
583
|
if (allow4Char && hex[0].charAt(0) === hex[0].charAt(1)
|
603
584
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
604
|
-
|
605
|
-
|
585
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)
|
586
|
+
&& hex[3].charAt(0) === hex[3].charAt(1)) {
|
606
587
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
|
607
588
|
}
|
608
589
|
return hex.join('');
|
609
590
|
}
|
610
591
|
|
611
|
-
/**
|
612
|
-
* Returns a colour object corresponding to a given number.
|
613
|
-
* @param {number} color input number
|
614
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
615
|
-
*/
|
616
|
-
function numberInputToObject(color) {
|
617
|
-
/* eslint-disable no-bitwise */
|
618
|
-
return {
|
619
|
-
r: color >> 16,
|
620
|
-
g: (color & 0xff00) >> 8,
|
621
|
-
b: color & 0xff,
|
622
|
-
};
|
623
|
-
/* eslint-enable no-bitwise */
|
624
|
-
}
|
625
|
-
|
626
592
|
/**
|
627
593
|
* Permissive string parsing. Take in a number of formats, and output an object
|
628
594
|
* based on detected format. Returns {r,g,b} or {h,s,l} or {h,s,v}
|
629
595
|
* @param {string} input colour value in any format
|
630
|
-
* @returns {Record<string, (number | string)> | false} an object matching the RegExp
|
596
|
+
* @returns {Record<string, (number | string | boolean)> | false} an object matching the RegExp
|
631
597
|
*/
|
632
598
|
function stringInputToObject(input) {
|
633
|
-
let color = input.trim()
|
599
|
+
let color = toLowerCase(input.trim());
|
600
|
+
|
634
601
|
if (color.length === 0) {
|
635
602
|
return {
|
636
|
-
r: 0, g: 0, b: 0, a:
|
603
|
+
r: 0, g: 0, b: 0, a: 1,
|
637
604
|
};
|
638
605
|
}
|
639
|
-
|
606
|
+
|
640
607
|
if (isColorName(color)) {
|
641
608
|
color = getRGBFromName(color);
|
642
|
-
named = true;
|
643
609
|
} else if (nonColors.includes(color)) {
|
644
|
-
const
|
645
|
-
const rgb = isTransparent ? 0 : 255;
|
646
|
-
const a = isTransparent ? 0 : 1;
|
610
|
+
const a = color === 'transparent' ? 0 : 1;
|
647
611
|
return {
|
648
|
-
r:
|
612
|
+
r: 0, g: 0, b: 0, a, format: 'rgb', ok: true,
|
649
613
|
};
|
650
614
|
}
|
651
615
|
|
@@ -660,24 +624,28 @@
|
|
660
624
|
r: m1, g: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'rgb',
|
661
625
|
};
|
662
626
|
}
|
627
|
+
|
663
628
|
[, m1, m2, m3, m4] = matchers.hsl.exec(color) || [];
|
664
629
|
if (m1 && m2 && m3/* && m4 */) {
|
665
630
|
return {
|
666
631
|
h: m1, s: m2, l: m3, a: m4 !== undefined ? m4 : 1, format: 'hsl',
|
667
632
|
};
|
668
633
|
}
|
634
|
+
|
669
635
|
[, m1, m2, m3, m4] = matchers.hsv.exec(color) || [];
|
670
636
|
if (m1 && m2 && m3/* && m4 */) {
|
671
637
|
return {
|
672
638
|
h: m1, s: m2, v: m3, a: m4 !== undefined ? m4 : 1, format: 'hsv',
|
673
639
|
};
|
674
640
|
}
|
641
|
+
|
675
642
|
[, m1, m2, m3, m4] = matchers.hwb.exec(color) || [];
|
676
643
|
if (m1 && m2 && m3) {
|
677
644
|
return {
|
678
645
|
h: m1, w: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'hwb',
|
679
646
|
};
|
680
647
|
}
|
648
|
+
|
681
649
|
[, m1, m2, m3, m4] = matchers.hex8.exec(color) || [];
|
682
650
|
if (m1 && m2 && m3 && m4) {
|
683
651
|
return {
|
@@ -685,19 +653,20 @@
|
|
685
653
|
g: parseIntFromHex(m2),
|
686
654
|
b: parseIntFromHex(m3),
|
687
655
|
a: convertHexToDecimal(m4),
|
688
|
-
|
689
|
-
format: named ? 'rgb' : 'hex',
|
656
|
+
format: 'hex',
|
690
657
|
};
|
691
658
|
}
|
659
|
+
|
692
660
|
[, m1, m2, m3] = matchers.hex6.exec(color) || [];
|
693
661
|
if (m1 && m2 && m3) {
|
694
662
|
return {
|
695
663
|
r: parseIntFromHex(m1),
|
696
664
|
g: parseIntFromHex(m2),
|
697
665
|
b: parseIntFromHex(m3),
|
698
|
-
format:
|
666
|
+
format: 'hex',
|
699
667
|
};
|
700
668
|
}
|
669
|
+
|
701
670
|
[, m1, m2, m3, m4] = matchers.hex4.exec(color) || [];
|
702
671
|
if (m1 && m2 && m3 && m4) {
|
703
672
|
return {
|
@@ -705,19 +674,20 @@
|
|
705
674
|
g: parseIntFromHex(m2 + m2),
|
706
675
|
b: parseIntFromHex(m3 + m3),
|
707
676
|
a: convertHexToDecimal(m4 + m4),
|
708
|
-
|
709
|
-
format: named ? 'rgb' : 'hex',
|
677
|
+
format: 'hex',
|
710
678
|
};
|
711
679
|
}
|
680
|
+
|
712
681
|
[, m1, m2, m3] = matchers.hex3.exec(color) || [];
|
713
682
|
if (m1 && m2 && m3) {
|
714
683
|
return {
|
715
684
|
r: parseIntFromHex(m1 + m1),
|
716
685
|
g: parseIntFromHex(m2 + m2),
|
717
686
|
b: parseIntFromHex(m3 + m3),
|
718
|
-
format:
|
687
|
+
format: 'hex',
|
719
688
|
};
|
720
689
|
}
|
690
|
+
|
721
691
|
return false;
|
722
692
|
}
|
723
693
|
|
@@ -748,7 +718,9 @@
|
|
748
718
|
*/
|
749
719
|
function inputToRGB(input) {
|
750
720
|
let rgb = { r: 0, g: 0, b: 0 };
|
721
|
+
/** @type {*} */
|
751
722
|
let color = input;
|
723
|
+
/** @type {string | number} */
|
752
724
|
let a = 1;
|
753
725
|
let s = null;
|
754
726
|
let v = null;
|
@@ -759,58 +731,67 @@
|
|
759
731
|
let r = null;
|
760
732
|
let g = null;
|
761
733
|
let ok = false;
|
762
|
-
|
734
|
+
const inputFormat = typeof color === 'object' && color.format;
|
735
|
+
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
763
736
|
|
764
737
|
if (typeof input === 'string') {
|
765
|
-
// @ts-ignore -- this now is converted to object
|
766
738
|
color = stringInputToObject(input);
|
767
739
|
if (color) ok = true;
|
768
740
|
}
|
769
741
|
if (typeof color === 'object') {
|
770
742
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
771
743
|
({ r, g, b } = color);
|
772
|
-
// RGB values now are all in [0,
|
773
|
-
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255)
|
744
|
+
// RGB values now are all in [0, 1] range
|
745
|
+
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255));
|
774
746
|
rgb = { r, g, b };
|
775
747
|
ok = true;
|
776
|
-
format = 'rgb';
|
777
|
-
}
|
748
|
+
format = color.format || 'rgb';
|
749
|
+
}
|
750
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
778
751
|
({ h, s, v } = color);
|
779
|
-
h =
|
780
|
-
s =
|
781
|
-
v =
|
752
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
753
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
754
|
+
v = bound01(v, 100); // brightness can be `5%` or a [0, 1] value
|
782
755
|
rgb = hsvToRgb(h, s, v);
|
783
756
|
ok = true;
|
784
757
|
format = 'hsv';
|
785
|
-
}
|
758
|
+
}
|
759
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
|
786
760
|
({ h, s, l } = color);
|
787
|
-
h =
|
788
|
-
s =
|
789
|
-
l =
|
761
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
762
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
763
|
+
l = bound01(l, 100); // lightness can be `5%` or a [0, 1] value
|
790
764
|
rgb = hslToRgb(h, s, l);
|
791
765
|
ok = true;
|
792
766
|
format = 'hsl';
|
793
|
-
}
|
767
|
+
}
|
768
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
|
794
769
|
({ h, w, b } = color);
|
795
|
-
h =
|
796
|
-
w =
|
797
|
-
b =
|
770
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
771
|
+
w = bound01(w, 100); // whiteness can be `5%` or a [0, 1] value
|
772
|
+
b = bound01(b, 100); // blackness can be `5%` or a [0, 1] value
|
798
773
|
rgb = hwbToRgb(h, w, b);
|
799
774
|
ok = true;
|
800
775
|
format = 'hwb';
|
801
776
|
}
|
802
777
|
if (isValidCSSUnit(color.a)) {
|
803
|
-
a = color.a;
|
804
|
-
a = isPercentage(`${a}`) ? bound01(a, 100) : a;
|
778
|
+
a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
|
779
|
+
a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
|
805
780
|
}
|
806
781
|
}
|
782
|
+
if (typeof color === 'undefined') {
|
783
|
+
ok = true;
|
784
|
+
}
|
807
785
|
|
808
786
|
return {
|
809
|
-
ok,
|
810
|
-
format
|
811
|
-
r: Math.min(255, Math.max(rgb.r, 0)),
|
812
|
-
g: Math.min(255, Math.max(rgb.g, 0)),
|
813
|
-
b: Math.min(255, Math.max(rgb.b, 0)),
|
787
|
+
ok,
|
788
|
+
format,
|
789
|
+
// r: Math.min(255, Math.max(rgb.r, 0)),
|
790
|
+
// g: Math.min(255, Math.max(rgb.g, 0)),
|
791
|
+
// b: Math.min(255, Math.max(rgb.b, 0)),
|
792
|
+
r: rgb.r,
|
793
|
+
g: rgb.g,
|
794
|
+
b: rgb.b,
|
814
795
|
a: boundAlpha(a),
|
815
796
|
};
|
816
797
|
}
|
@@ -829,15 +810,13 @@
|
|
829
810
|
constructor(input, config) {
|
830
811
|
let color = input;
|
831
812
|
const configFormat = config && COLOR_FORMAT.includes(config)
|
832
|
-
? config : '
|
813
|
+
? config : '';
|
833
814
|
|
834
|
-
// If input is already a `Color`,
|
815
|
+
// If input is already a `Color`, clone its values
|
835
816
|
if (color instanceof Color) {
|
836
817
|
color = inputToRGB(color);
|
837
818
|
}
|
838
|
-
|
839
|
-
color = numberInputToObject(color);
|
840
|
-
}
|
819
|
+
|
841
820
|
const {
|
842
821
|
r, g, b, a, ok, format,
|
843
822
|
} = inputToRGB(color);
|
@@ -846,7 +825,7 @@
|
|
846
825
|
const self = this;
|
847
826
|
|
848
827
|
/** @type {CP.ColorInput} */
|
849
|
-
self.originalInput =
|
828
|
+
self.originalInput = input;
|
850
829
|
/** @type {number} */
|
851
830
|
self.r = r;
|
852
831
|
/** @type {number} */
|
@@ -887,24 +866,21 @@
|
|
887
866
|
let R = 0;
|
888
867
|
let G = 0;
|
889
868
|
let B = 0;
|
890
|
-
const rp = r / 255;
|
891
|
-
const rg = g / 255;
|
892
|
-
const rb = b / 255;
|
893
869
|
|
894
|
-
if (
|
895
|
-
R =
|
870
|
+
if (r <= 0.03928) {
|
871
|
+
R = r / 12.92;
|
896
872
|
} else {
|
897
|
-
R = ((
|
873
|
+
R = ((r + 0.055) / 1.055) ** 2.4;
|
898
874
|
}
|
899
|
-
if (
|
900
|
-
G =
|
875
|
+
if (g <= 0.03928) {
|
876
|
+
G = g / 12.92;
|
901
877
|
} else {
|
902
|
-
G = ((
|
878
|
+
G = ((g + 0.055) / 1.055) ** 2.4;
|
903
879
|
}
|
904
|
-
if (
|
905
|
-
B =
|
880
|
+
if (b <= 0.03928) {
|
881
|
+
B = b / 12.92;
|
906
882
|
} else {
|
907
|
-
B = ((
|
883
|
+
B = ((b + 0.055) / 1.055) ** 2.4;
|
908
884
|
}
|
909
885
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
|
910
886
|
}
|
@@ -914,7 +890,7 @@
|
|
914
890
|
* @returns {number} a number in the [0, 255] range
|
915
891
|
*/
|
916
892
|
get brightness() {
|
917
|
-
const { r, g, b } = this;
|
893
|
+
const { r, g, b } = this.toRgb();
|
918
894
|
return (r * 299 + g * 587 + b * 114) / 1000;
|
919
895
|
}
|
920
896
|
|
@@ -923,12 +899,14 @@
|
|
923
899
|
* @returns {CP.RGBA} an {r,g,b,a} object with [0, 255] ranged values
|
924
900
|
*/
|
925
901
|
toRgb() {
|
926
|
-
|
902
|
+
let {
|
927
903
|
r, g, b, a,
|
928
904
|
} = this;
|
929
905
|
|
906
|
+
[r, g, b] = [r, g, b].map((n) => roundPart(n * 255 * 100) / 100);
|
907
|
+
a = roundPart(a * 100) / 100;
|
930
908
|
return {
|
931
|
-
r, g, b, a
|
909
|
+
r, g, b, a,
|
932
910
|
};
|
933
911
|
}
|
934
912
|
|
@@ -1022,7 +1000,7 @@
|
|
1022
1000
|
toHsv() {
|
1023
1001
|
const {
|
1024
1002
|
r, g, b, a,
|
1025
|
-
} = this
|
1003
|
+
} = this;
|
1026
1004
|
const { h, s, v } = rgbToHsv(r, g, b);
|
1027
1005
|
|
1028
1006
|
return {
|
@@ -1037,7 +1015,7 @@
|
|
1037
1015
|
toHsl() {
|
1038
1016
|
const {
|
1039
1017
|
r, g, b, a,
|
1040
|
-
} = this
|
1018
|
+
} = this;
|
1041
1019
|
const { h, s, l } = rgbToHsl(r, g, b);
|
1042
1020
|
|
1043
1021
|
return {
|
@@ -1122,6 +1100,7 @@
|
|
1122
1100
|
*/
|
1123
1101
|
setAlpha(alpha) {
|
1124
1102
|
const self = this;
|
1103
|
+
if (typeof alpha !== 'number') return self;
|
1125
1104
|
self.a = boundAlpha(alpha);
|
1126
1105
|
return self;
|
1127
1106
|
}
|
@@ -1236,6 +1215,7 @@
|
|
1236
1215
|
isOnePointZero,
|
1237
1216
|
isPercentage,
|
1238
1217
|
isValidCSSUnit,
|
1218
|
+
isColorName,
|
1239
1219
|
pad2,
|
1240
1220
|
clamp01,
|
1241
1221
|
bound01,
|
@@ -1253,10 +1233,11 @@
|
|
1253
1233
|
hueToRgb,
|
1254
1234
|
hwbToRgb,
|
1255
1235
|
parseIntFromHex,
|
1256
|
-
numberInputToObject,
|
1257
1236
|
stringInputToObject,
|
1258
1237
|
inputToRGB,
|
1259
1238
|
roundPart,
|
1239
|
+
getElementStyle,
|
1240
|
+
setElementStyle,
|
1260
1241
|
ObjectAssign,
|
1261
1242
|
});
|
1262
1243
|
|
@@ -1386,24 +1367,6 @@
|
|
1386
1367
|
*/
|
1387
1368
|
const ariaValueNow = 'aria-valuenow';
|
1388
1369
|
|
1389
|
-
/**
|
1390
|
-
* A global namespace for aria-haspopup.
|
1391
|
-
* @type {string}
|
1392
|
-
*/
|
1393
|
-
const ariaHasPopup = 'aria-haspopup';
|
1394
|
-
|
1395
|
-
/**
|
1396
|
-
* A global namespace for aria-hidden.
|
1397
|
-
* @type {string}
|
1398
|
-
*/
|
1399
|
-
const ariaHidden = 'aria-hidden';
|
1400
|
-
|
1401
|
-
/**
|
1402
|
-
* A global namespace for aria-labelledby.
|
1403
|
-
* @type {string}
|
1404
|
-
*/
|
1405
|
-
const ariaLabelledBy = 'aria-labelledby';
|
1406
|
-
|
1407
1370
|
/**
|
1408
1371
|
* A global namespace for `ArrowDown` key.
|
1409
1372
|
* @type {string} e.which = 40 equivalent
|
@@ -1530,37 +1493,6 @@
|
|
1530
1493
|
*/
|
1531
1494
|
const focusoutEvent = 'focusout';
|
1532
1495
|
|
1533
|
-
// @ts-ignore
|
1534
|
-
const { userAgentData: uaDATA } = navigator;
|
1535
|
-
|
1536
|
-
/**
|
1537
|
-
* A global namespace for `userAgentData` object.
|
1538
|
-
*/
|
1539
|
-
const userAgentData = uaDATA;
|
1540
|
-
|
1541
|
-
const { userAgent: userAgentString } = navigator;
|
1542
|
-
|
1543
|
-
/**
|
1544
|
-
* A global namespace for `navigator.userAgent` string.
|
1545
|
-
*/
|
1546
|
-
const userAgent = userAgentString;
|
1547
|
-
|
1548
|
-
const mobileBrands = /iPhone|iPad|iPod|Android/i;
|
1549
|
-
let isMobileCheck = false;
|
1550
|
-
|
1551
|
-
if (userAgentData) {
|
1552
|
-
isMobileCheck = userAgentData.brands
|
1553
|
-
.some((/** @type {Record<String, any>} */x) => mobileBrands.test(x.brand));
|
1554
|
-
} else {
|
1555
|
-
isMobileCheck = mobileBrands.test(userAgent);
|
1556
|
-
}
|
1557
|
-
|
1558
|
-
/**
|
1559
|
-
* A global `boolean` for mobile detection.
|
1560
|
-
* @type {boolean}
|
1561
|
-
*/
|
1562
|
-
const isMobile = isMobileCheck;
|
1563
|
-
|
1564
1496
|
/**
|
1565
1497
|
* Returns the `document.documentElement` or the `<html>` element.
|
1566
1498
|
*
|
@@ -1745,30 +1677,6 @@
|
|
1745
1677
|
return lookUp.getElementsByClassName(selector);
|
1746
1678
|
}
|
1747
1679
|
|
1748
|
-
/**
|
1749
|
-
* This is a shortie for `document.createElementNS` method
|
1750
|
-
* which allows you to create a new `HTMLElement` for a given `tagName`
|
1751
|
-
* or based on an object with specific non-readonly attributes:
|
1752
|
-
* `id`, `className`, `textContent`, `style`, etc.
|
1753
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
1754
|
-
*
|
1755
|
-
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
1756
|
-
* @param {Record<string, string> | string} param `tagName` or object
|
1757
|
-
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
1758
|
-
*/
|
1759
|
-
function createElementNS(namespace, param) {
|
1760
|
-
if (typeof param === 'string') {
|
1761
|
-
return getDocument().createElementNS(namespace, param);
|
1762
|
-
}
|
1763
|
-
|
1764
|
-
const { tagName } = param;
|
1765
|
-
const attr = { ...param };
|
1766
|
-
const newElement = createElementNS(namespace, tagName);
|
1767
|
-
delete attr.tagName;
|
1768
|
-
ObjectAssign(newElement, attr);
|
1769
|
-
return newElement;
|
1770
|
-
}
|
1771
|
-
|
1772
1680
|
/**
|
1773
1681
|
* Shortcut for the `Element.dispatchEvent(Event)` method.
|
1774
1682
|
*
|
@@ -1886,12 +1794,11 @@
|
|
1886
1794
|
}
|
1887
1795
|
|
1888
1796
|
/**
|
1889
|
-
* Shortcut for `
|
1890
|
-
*
|
1891
|
-
* @
|
1892
|
-
* @returns {string} lowercase output string
|
1797
|
+
* Shortcut for `Object.keys()` static method.
|
1798
|
+
* @param {Record<string, any>} obj a target object
|
1799
|
+
* @returns {string[]}
|
1893
1800
|
*/
|
1894
|
-
const
|
1801
|
+
const ObjectKeys = (obj) => Object.keys(obj);
|
1895
1802
|
|
1896
1803
|
/**
|
1897
1804
|
* Utility to normalize component options.
|
@@ -1996,6 +1903,77 @@
|
|
1996
1903
|
*/
|
1997
1904
|
const removeAttribute = (element, attribute) => element.removeAttribute(attribute);
|
1998
1905
|
|
1906
|
+
/**
|
1907
|
+
* @class
|
1908
|
+
* Returns a color palette with a given set of parameters.
|
1909
|
+
* @example
|
1910
|
+
* new ColorPalette(0, 12, 10);
|
1911
|
+
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: Array<Color> }
|
1912
|
+
*/
|
1913
|
+
class ColorPalette {
|
1914
|
+
/**
|
1915
|
+
* The `hue` parameter is optional, which would be set to 0.
|
1916
|
+
* @param {number[]} args represeinting hue, hueSteps, lightSteps
|
1917
|
+
* * `args.hue` the starting Hue [0, 360]
|
1918
|
+
* * `args.hueSteps` Hue Steps Count [5, 24]
|
1919
|
+
* * `args.lightSteps` Lightness Steps Count [5, 12]
|
1920
|
+
*/
|
1921
|
+
constructor(...args) {
|
1922
|
+
let hue = 0;
|
1923
|
+
let hueSteps = 12;
|
1924
|
+
let lightSteps = 10;
|
1925
|
+
let lightnessArray = [0.5];
|
1926
|
+
|
1927
|
+
if (args.length === 3) {
|
1928
|
+
[hue, hueSteps, lightSteps] = args;
|
1929
|
+
} else if (args.length === 2) {
|
1930
|
+
[hueSteps, lightSteps] = args;
|
1931
|
+
if ([hueSteps, lightSteps].some((n) => n < 1)) {
|
1932
|
+
throw TypeError('ColorPalette: both arguments must be higher than 0.');
|
1933
|
+
}
|
1934
|
+
}
|
1935
|
+
|
1936
|
+
/** @type {*} */
|
1937
|
+
const colors = [];
|
1938
|
+
const hueStep = 360 / hueSteps;
|
1939
|
+
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
1940
|
+
const steps1To13 = [0.25, 0.2, 0.15, 0.11, 0.09, 0.075];
|
1941
|
+
const lightSets = [[1, 2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]];
|
1942
|
+
const closestSet = lightSets.find((set) => set.includes(lightSteps));
|
1943
|
+
|
1944
|
+
// find a lightStep that won't go beyond black and white
|
1945
|
+
// something within the [10-90] range of lightness
|
1946
|
+
const lightStep = closestSet
|
1947
|
+
? steps1To13[lightSets.indexOf(closestSet)]
|
1948
|
+
: (100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100);
|
1949
|
+
|
1950
|
+
// light tints
|
1951
|
+
for (let i = 1; i < half + 1; i += 1) {
|
1952
|
+
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i))];
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
// dark tints
|
1956
|
+
for (let i = 1; i < lightSteps - half; i += 1) {
|
1957
|
+
lightnessArray = [(0.5 - lightStep * (i)), ...lightnessArray];
|
1958
|
+
}
|
1959
|
+
|
1960
|
+
// feed `colors` Array
|
1961
|
+
for (let i = 0; i < hueSteps; i += 1) {
|
1962
|
+
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
1963
|
+
lightnessArray.forEach((l) => {
|
1964
|
+
colors.push(new Color({ h: currentHue, s: 1, l }));
|
1965
|
+
});
|
1966
|
+
}
|
1967
|
+
|
1968
|
+
this.hue = hue;
|
1969
|
+
this.hueSteps = hueSteps;
|
1970
|
+
this.lightSteps = lightSteps;
|
1971
|
+
this.colors = colors;
|
1972
|
+
}
|
1973
|
+
}
|
1974
|
+
|
1975
|
+
ObjectAssign(ColorPalette, { Color });
|
1976
|
+
|
1999
1977
|
/** @type {Record<string, string>} */
|
2000
1978
|
const colorPickerLabels = {
|
2001
1979
|
pickerLabel: 'Colour Picker',
|
@@ -2023,14 +2001,72 @@
|
|
2023
2001
|
*/
|
2024
2002
|
const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold', 'olive', 'yellow', 'lime', 'green', 'teal', 'cyan', 'blue', 'violet', 'magenta', 'pink'];
|
2025
2003
|
|
2004
|
+
const tabIndex = 'tabindex';
|
2005
|
+
|
2026
2006
|
/**
|
2027
|
-
*
|
2028
|
-
*
|
2029
|
-
* @
|
2030
|
-
|
2007
|
+
* Check if a string is valid JSON string.
|
2008
|
+
* @param {string} str the string input
|
2009
|
+
* @returns {boolean} the query result
|
2010
|
+
*/
|
2011
|
+
function isValidJSON(str) {
|
2012
|
+
try {
|
2013
|
+
JSON.parse(str);
|
2014
|
+
} catch (e) {
|
2015
|
+
return false;
|
2016
|
+
}
|
2017
|
+
return true;
|
2018
|
+
}
|
2019
|
+
|
2020
|
+
/**
|
2021
|
+
* Shortcut for `String.toUpperCase()`.
|
2022
|
+
*
|
2023
|
+
* @param {string} source input string
|
2024
|
+
* @returns {string} uppercase output string
|
2031
2025
|
*/
|
2032
2026
|
const toUpperCase = (source) => source.toUpperCase();
|
2033
2027
|
|
2028
|
+
/**
|
2029
|
+
* A global namespace for aria-haspopup.
|
2030
|
+
* @type {string}
|
2031
|
+
*/
|
2032
|
+
const ariaHasPopup = 'aria-haspopup';
|
2033
|
+
|
2034
|
+
/**
|
2035
|
+
* A global namespace for aria-hidden.
|
2036
|
+
* @type {string}
|
2037
|
+
*/
|
2038
|
+
const ariaHidden = 'aria-hidden';
|
2039
|
+
|
2040
|
+
/**
|
2041
|
+
* A global namespace for aria-labelledby.
|
2042
|
+
* @type {string}
|
2043
|
+
*/
|
2044
|
+
const ariaLabelledBy = 'aria-labelledby';
|
2045
|
+
|
2046
|
+
/**
|
2047
|
+
* This is a shortie for `document.createElementNS` method
|
2048
|
+
* which allows you to create a new `HTMLElement` for a given `tagName`
|
2049
|
+
* or based on an object with specific non-readonly attributes:
|
2050
|
+
* `id`, `className`, `textContent`, `style`, etc.
|
2051
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
2052
|
+
*
|
2053
|
+
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
2054
|
+
* @param {Record<string, string> | string} param `tagName` or object
|
2055
|
+
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
2056
|
+
*/
|
2057
|
+
function createElementNS(namespace, param) {
|
2058
|
+
if (typeof param === 'string') {
|
2059
|
+
return getDocument().createElementNS(namespace, param);
|
2060
|
+
}
|
2061
|
+
|
2062
|
+
const { tagName } = param;
|
2063
|
+
const attr = { ...param };
|
2064
|
+
const newElement = createElementNS(namespace, tagName);
|
2065
|
+
delete attr.tagName;
|
2066
|
+
ObjectAssign(newElement, attr);
|
2067
|
+
return newElement;
|
2068
|
+
}
|
2069
|
+
|
2034
2070
|
const vHidden = 'v-hidden';
|
2035
2071
|
|
2036
2072
|
/**
|
@@ -2110,8 +2146,6 @@
|
|
2110
2146
|
*/
|
2111
2147
|
const ariaValueMax = 'aria-valuemax';
|
2112
2148
|
|
2113
|
-
const tabIndex = 'tabindex';
|
2114
|
-
|
2115
2149
|
/**
|
2116
2150
|
* Returns all color controls for `ColorPicker`.
|
2117
2151
|
*
|
@@ -2219,75 +2253,6 @@
|
|
2219
2253
|
});
|
2220
2254
|
}
|
2221
2255
|
|
2222
|
-
/**
|
2223
|
-
* @class
|
2224
|
-
* Returns a color palette with a given set of parameters.
|
2225
|
-
* @example
|
2226
|
-
* new ColorPalette(0, 12, 10);
|
2227
|
-
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: array }
|
2228
|
-
*/
|
2229
|
-
class ColorPalette {
|
2230
|
-
/**
|
2231
|
-
* The `hue` parameter is optional, which would be set to 0.
|
2232
|
-
* @param {number[]} args represeinting hue, hueSteps, lightSteps
|
2233
|
-
* * `args.hue` the starting Hue [0, 360]
|
2234
|
-
* * `args.hueSteps` Hue Steps Count [5, 24]
|
2235
|
-
* * `args.lightSteps` Lightness Steps Count [5, 12]
|
2236
|
-
*/
|
2237
|
-
constructor(...args) {
|
2238
|
-
let hue = 0;
|
2239
|
-
let hueSteps = 12;
|
2240
|
-
let lightSteps = 10;
|
2241
|
-
let lightnessArray = [0.5];
|
2242
|
-
|
2243
|
-
if (args.length === 3) {
|
2244
|
-
[hue, hueSteps, lightSteps] = args;
|
2245
|
-
} else if (args.length === 2) {
|
2246
|
-
[hueSteps, lightSteps] = args;
|
2247
|
-
} else {
|
2248
|
-
throw TypeError('ColorPalette requires minimum 2 arguments');
|
2249
|
-
}
|
2250
|
-
|
2251
|
-
/** @type {string[]} */
|
2252
|
-
const colors = [];
|
2253
|
-
|
2254
|
-
const hueStep = 360 / hueSteps;
|
2255
|
-
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
2256
|
-
const estimatedStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
2257
|
-
|
2258
|
-
let lightStep = 0.25;
|
2259
|
-
lightStep = [4, 5].includes(lightSteps) ? 0.2 : lightStep;
|
2260
|
-
lightStep = [6, 7].includes(lightSteps) ? 0.15 : lightStep;
|
2261
|
-
lightStep = [8, 9].includes(lightSteps) ? 0.11 : lightStep;
|
2262
|
-
lightStep = [10, 11].includes(lightSteps) ? 0.09 : lightStep;
|
2263
|
-
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
2264
|
-
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
2265
|
-
|
2266
|
-
// light tints
|
2267
|
-
for (let i = 1; i < half + 1; i += 1) {
|
2268
|
-
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i))];
|
2269
|
-
}
|
2270
|
-
|
2271
|
-
// dark tints
|
2272
|
-
for (let i = 1; i < lightSteps - half; i += 1) {
|
2273
|
-
lightnessArray = [(0.5 - lightStep * (i)), ...lightnessArray];
|
2274
|
-
}
|
2275
|
-
|
2276
|
-
// feed `colors` Array
|
2277
|
-
for (let i = 0; i < hueSteps; i += 1) {
|
2278
|
-
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
2279
|
-
lightnessArray.forEach((l) => {
|
2280
|
-
colors.push(new Color({ h: currentHue, s: 1, l }).toHexString());
|
2281
|
-
});
|
2282
|
-
}
|
2283
|
-
|
2284
|
-
this.hue = hue;
|
2285
|
-
this.hueSteps = hueSteps;
|
2286
|
-
this.lightSteps = lightSteps;
|
2287
|
-
this.colors = colors;
|
2288
|
-
}
|
2289
|
-
}
|
2290
|
-
|
2291
2256
|
/**
|
2292
2257
|
* Returns a color-defaults with given values and class.
|
2293
2258
|
* @param {CP.ColorPicker} self
|
@@ -2321,7 +2286,8 @@
|
|
2321
2286
|
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2322
2287
|
const menuHeight = `${(rowCount || 1) * optionSize}rem`;
|
2323
2288
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2324
|
-
|
2289
|
+
/** @type {HTMLUListElement} */
|
2290
|
+
// @ts-ignore -- <UL> is an `HTMLElement`
|
2325
2291
|
const menu = createElement({
|
2326
2292
|
tagName: 'ul',
|
2327
2293
|
className: finalClass,
|
@@ -2329,7 +2295,7 @@
|
|
2329
2295
|
setAttribute(menu, 'role', 'listbox');
|
2330
2296
|
setAttribute(menu, ariaLabel, menuLabel);
|
2331
2297
|
|
2332
|
-
if (isScrollable) {
|
2298
|
+
if (isScrollable) {
|
2333
2299
|
setCSSProperties(menu, {
|
2334
2300
|
'--grid-item-size': `${optionSize}rem`,
|
2335
2301
|
'--grid-fit': fit,
|
@@ -2340,15 +2306,19 @@
|
|
2340
2306
|
}
|
2341
2307
|
|
2342
2308
|
colorsArray.forEach((x) => {
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2309
|
+
let [value, label] = typeof x === 'string' ? x.trim().split(':') : [];
|
2310
|
+
if (x instanceof Color) {
|
2311
|
+
value = x.toHexString();
|
2312
|
+
label = value;
|
2313
|
+
}
|
2314
|
+
const color = new Color(x instanceof Color ? x : value, format);
|
2315
|
+
const isActive = color.toString() === getAttribute(input, 'value');
|
2346
2316
|
const active = isActive ? ' active' : '';
|
2347
2317
|
|
2348
2318
|
const option = createElement({
|
2349
2319
|
tagName: 'li',
|
2350
2320
|
className: `color-option${active}`,
|
2351
|
-
innerText: `${label ||
|
2321
|
+
innerText: `${label || value}`,
|
2352
2322
|
});
|
2353
2323
|
|
2354
2324
|
setAttribute(option, tabIndex, '0');
|
@@ -2357,7 +2327,7 @@
|
|
2357
2327
|
setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
|
2358
2328
|
|
2359
2329
|
if (isOptionsMenu) {
|
2360
|
-
setElementStyle(option, { backgroundColor:
|
2330
|
+
setElementStyle(option, { backgroundColor: value });
|
2361
2331
|
}
|
2362
2332
|
|
2363
2333
|
menu.append(option);
|
@@ -2366,55 +2336,10 @@
|
|
2366
2336
|
}
|
2367
2337
|
|
2368
2338
|
/**
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
function isValidJSON(str) {
|
2374
|
-
try {
|
2375
|
-
JSON.parse(str);
|
2376
|
-
} catch (e) {
|
2377
|
-
return false;
|
2378
|
-
}
|
2379
|
-
return true;
|
2380
|
-
}
|
2381
|
-
|
2382
|
-
var version = "0.0.1";
|
2383
|
-
|
2384
|
-
// @ts-ignore
|
2385
|
-
|
2386
|
-
const Version = version;
|
2387
|
-
|
2388
|
-
// ColorPicker GC
|
2389
|
-
// ==============
|
2390
|
-
const colorPickerString = 'color-picker';
|
2391
|
-
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2392
|
-
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2393
|
-
const colorPickerDefaults = {
|
2394
|
-
componentLabels: colorPickerLabels,
|
2395
|
-
colorLabels: colorNames,
|
2396
|
-
format: 'rgb',
|
2397
|
-
colorPresets: false,
|
2398
|
-
colorKeywords: false,
|
2399
|
-
};
|
2400
|
-
|
2401
|
-
// ColorPicker Static Methods
|
2402
|
-
// ==========================
|
2403
|
-
|
2404
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2405
|
-
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2406
|
-
|
2407
|
-
/** @type {CP.InitCallback<ColorPicker>} */
|
2408
|
-
const initColorPicker = (element) => new ColorPicker(element);
|
2409
|
-
|
2410
|
-
// ColorPicker Private Methods
|
2411
|
-
// ===========================
|
2412
|
-
|
2413
|
-
/**
|
2414
|
-
* Generate HTML markup and update instance properties.
|
2415
|
-
* @param {ColorPicker} self
|
2416
|
-
*/
|
2417
|
-
function initCallback(self) {
|
2339
|
+
* Generate HTML markup and update instance properties.
|
2340
|
+
* @param {CP.ColorPicker} self
|
2341
|
+
*/
|
2342
|
+
function setMarkup(self) {
|
2418
2343
|
const {
|
2419
2344
|
input, parent, format, id, componentLabels, colorKeywords, colorPresets,
|
2420
2345
|
} = self;
|
@@ -2429,9 +2354,7 @@
|
|
2429
2354
|
self.color = new Color(color, format);
|
2430
2355
|
|
2431
2356
|
// set initial controls dimensions
|
2432
|
-
|
2433
|
-
const dropClass = isMobile ? ' mobile' : '';
|
2434
|
-
const formatString = format === 'hex' ? hexLabel : format.toUpperCase();
|
2357
|
+
const formatString = format === 'hex' ? hexLabel : toUpperCase(format);
|
2435
2358
|
|
2436
2359
|
const pickerBtn = createElement({
|
2437
2360
|
id: `picker-btn-${id}`,
|
@@ -2448,7 +2371,7 @@
|
|
2448
2371
|
|
2449
2372
|
const pickerDropdown = createElement({
|
2450
2373
|
tagName: 'div',
|
2451
|
-
className:
|
2374
|
+
className: 'color-dropdown picker',
|
2452
2375
|
});
|
2453
2376
|
setAttribute(pickerDropdown, ariaLabelledBy, `picker-btn-${id}`);
|
2454
2377
|
setAttribute(pickerDropdown, 'role', 'group');
|
@@ -2464,7 +2387,7 @@
|
|
2464
2387
|
if (colorKeywords || colorPresets) {
|
2465
2388
|
const presetsDropdown = createElement({
|
2466
2389
|
tagName: 'div',
|
2467
|
-
className:
|
2390
|
+
className: 'color-dropdown scrollable menu',
|
2468
2391
|
});
|
2469
2392
|
|
2470
2393
|
// color presets
|
@@ -2514,6 +2437,37 @@
|
|
2514
2437
|
setAttribute(input, tabIndex, '-1');
|
2515
2438
|
}
|
2516
2439
|
|
2440
|
+
var version = "0.0.2alpha3";
|
2441
|
+
|
2442
|
+
// @ts-ignore
|
2443
|
+
|
2444
|
+
const Version = version;
|
2445
|
+
|
2446
|
+
// ColorPicker GC
|
2447
|
+
// ==============
|
2448
|
+
const colorPickerString = 'color-picker';
|
2449
|
+
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2450
|
+
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2451
|
+
const colorPickerDefaults = {
|
2452
|
+
componentLabels: colorPickerLabels,
|
2453
|
+
colorLabels: colorNames,
|
2454
|
+
format: 'rgb',
|
2455
|
+
colorPresets: false,
|
2456
|
+
colorKeywords: false,
|
2457
|
+
};
|
2458
|
+
|
2459
|
+
// ColorPicker Static Methods
|
2460
|
+
// ==========================
|
2461
|
+
|
2462
|
+
/** @type {CP.GetInstance<ColorPicker>} */
|
2463
|
+
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2464
|
+
|
2465
|
+
/** @type {CP.InitCallback<ColorPicker>} */
|
2466
|
+
const initColorPicker = (element) => new ColorPicker(element);
|
2467
|
+
|
2468
|
+
// ColorPicker Private Methods
|
2469
|
+
// ===========================
|
2470
|
+
|
2517
2471
|
/**
|
2518
2472
|
* Add / remove `ColorPicker` main event listeners.
|
2519
2473
|
* @param {ColorPicker} self
|
@@ -2526,8 +2480,6 @@
|
|
2526
2480
|
fn(input, focusinEvent, self.showPicker);
|
2527
2481
|
fn(pickerToggle, mouseclickEvent, self.togglePicker);
|
2528
2482
|
|
2529
|
-
fn(input, keydownEvent, self.keyToggle);
|
2530
|
-
|
2531
2483
|
if (menuToggle) {
|
2532
2484
|
fn(menuToggle, mouseclickEvent, self.toggleMenu);
|
2533
2485
|
}
|
@@ -2565,8 +2517,7 @@
|
|
2565
2517
|
fn(doc, pointerEvents.move, self.pointerMove);
|
2566
2518
|
fn(doc, pointerEvents.up, self.pointerUp);
|
2567
2519
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2568
|
-
|
2569
|
-
fn(win, keyupEvent, self.handleDismiss);
|
2520
|
+
fn(doc, keyupEvent, self.handleDismiss);
|
2570
2521
|
}
|
2571
2522
|
|
2572
2523
|
/**
|
@@ -2650,7 +2601,7 @@
|
|
2650
2601
|
const input = querySelector(target);
|
2651
2602
|
|
2652
2603
|
// invalidate
|
2653
|
-
if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
|
2604
|
+
if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
|
2654
2605
|
self.input = input;
|
2655
2606
|
|
2656
2607
|
const parent = closest(input, colorPickerParentSelector);
|
@@ -2697,15 +2648,14 @@
|
|
2697
2648
|
});
|
2698
2649
|
|
2699
2650
|
// update and expose component labels
|
2700
|
-
const
|
2701
|
-
|
2702
|
-
? JSON.parse(componentLabels) : componentLabels || {};
|
2651
|
+
const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
|
2652
|
+
? JSON.parse(componentLabels) : componentLabels;
|
2703
2653
|
|
2704
2654
|
/** @type {Record<string, string>} */
|
2705
|
-
self.componentLabels = ObjectAssign(
|
2655
|
+
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2706
2656
|
|
2707
2657
|
/** @type {Color} */
|
2708
|
-
self.color = new Color('
|
2658
|
+
self.color = new Color(input.value || '#fff', format);
|
2709
2659
|
|
2710
2660
|
/** @type {CP.ColorFormats} */
|
2711
2661
|
self.format = format;
|
@@ -2714,7 +2664,7 @@
|
|
2714
2664
|
if (colorKeywords instanceof Array) {
|
2715
2665
|
self.colorKeywords = colorKeywords;
|
2716
2666
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2717
|
-
self.colorKeywords = colorKeywords.split(',');
|
2667
|
+
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2718
2668
|
}
|
2719
2669
|
|
2720
2670
|
// set colour presets
|
@@ -2743,11 +2693,10 @@
|
|
2743
2693
|
self.handleFocusOut = self.handleFocusOut.bind(self);
|
2744
2694
|
self.changeHandler = self.changeHandler.bind(self);
|
2745
2695
|
self.handleDismiss = self.handleDismiss.bind(self);
|
2746
|
-
self.keyToggle = self.keyToggle.bind(self);
|
2747
2696
|
self.handleKnobs = self.handleKnobs.bind(self);
|
2748
2697
|
|
2749
2698
|
// generate markup
|
2750
|
-
|
2699
|
+
setMarkup(self);
|
2751
2700
|
|
2752
2701
|
const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
|
2753
2702
|
// set main elements
|
@@ -2835,76 +2784,83 @@
|
|
2835
2784
|
return inputValue !== '' && new Color(inputValue).isValid;
|
2836
2785
|
}
|
2837
2786
|
|
2787
|
+
/** Returns the colour appearance, usually the closest colour name for the current value. */
|
2788
|
+
get appearance() {
|
2789
|
+
const {
|
2790
|
+
colorLabels, hsl, hsv, format,
|
2791
|
+
} = this;
|
2792
|
+
|
2793
|
+
const hue = roundPart(hsl.h * 360);
|
2794
|
+
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
2795
|
+
const saturation = roundPart(saturationSource * 100);
|
2796
|
+
const lightness = roundPart(hsl.l * 100);
|
2797
|
+
const hsvl = hsv.v * 100;
|
2798
|
+
|
2799
|
+
let colorName;
|
2800
|
+
|
2801
|
+
// determine color appearance
|
2802
|
+
if (lightness === 100 && saturation === 0) {
|
2803
|
+
colorName = colorLabels.white;
|
2804
|
+
} else if (lightness === 0) {
|
2805
|
+
colorName = colorLabels.black;
|
2806
|
+
} else if (saturation === 0) {
|
2807
|
+
colorName = colorLabels.grey;
|
2808
|
+
} else if (hue < 15 || hue >= 345) {
|
2809
|
+
colorName = colorLabels.red;
|
2810
|
+
} else if (hue >= 15 && hue < 45) {
|
2811
|
+
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
2812
|
+
} else if (hue >= 45 && hue < 75) {
|
2813
|
+
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
2814
|
+
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
2815
|
+
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
2816
|
+
colorName = isOlive ? colorLabels.olive : colorName;
|
2817
|
+
} else if (hue >= 75 && hue < 155) {
|
2818
|
+
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
2819
|
+
} else if (hue >= 155 && hue < 175) {
|
2820
|
+
colorName = colorLabels.teal;
|
2821
|
+
} else if (hue >= 175 && hue < 195) {
|
2822
|
+
colorName = colorLabels.cyan;
|
2823
|
+
} else if (hue >= 195 && hue < 255) {
|
2824
|
+
colorName = colorLabels.blue;
|
2825
|
+
} else if (hue >= 255 && hue < 270) {
|
2826
|
+
colorName = colorLabels.violet;
|
2827
|
+
} else if (hue >= 270 && hue < 295) {
|
2828
|
+
colorName = colorLabels.magenta;
|
2829
|
+
} else if (hue >= 295 && hue < 345) {
|
2830
|
+
colorName = colorLabels.pink;
|
2831
|
+
}
|
2832
|
+
return colorName;
|
2833
|
+
}
|
2834
|
+
|
2838
2835
|
/** Updates `ColorPicker` visuals. */
|
2839
2836
|
updateVisuals() {
|
2840
2837
|
const self = this;
|
2841
2838
|
const {
|
2842
|
-
|
2839
|
+
controlPositions, visuals,
|
2843
2840
|
} = self;
|
2844
2841
|
const [v1, v2, v3] = visuals;
|
2845
|
-
const {
|
2846
|
-
const hue =
|
2847
|
-
|
2848
|
-
: controlPositions.c2y / offsetHeight;
|
2849
|
-
// @ts-ignore - `hslToRgb` is assigned to `Color` as static method
|
2850
|
-
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
2842
|
+
const { offsetHeight } = v1;
|
2843
|
+
const hue = controlPositions.c2y / offsetHeight;
|
2844
|
+
const { r, g, b } = new Color({ h: hue, s: 1, l: 0.5 }).toRgb();
|
2851
2845
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2852
2846
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2853
2847
|
const roundA = roundPart((alpha * 100)) / 100;
|
2854
2848
|
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
setElementStyle(v2, { background: hueGradient });
|
2870
|
-
} else {
|
2871
|
-
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2872
|
-
const fill0 = new Color({
|
2873
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2874
|
-
}).saturate(-saturation).toRgbString();
|
2875
|
-
const fill1 = new Color({
|
2876
|
-
r: 255, g: 255, b: 0, a: alpha,
|
2877
|
-
}).saturate(-saturation).toRgbString();
|
2878
|
-
const fill2 = new Color({
|
2879
|
-
r: 0, g: 255, b: 0, a: alpha,
|
2880
|
-
}).saturate(-saturation).toRgbString();
|
2881
|
-
const fill3 = new Color({
|
2882
|
-
r: 0, g: 255, b: 255, a: alpha,
|
2883
|
-
}).saturate(-saturation).toRgbString();
|
2884
|
-
const fill4 = new Color({
|
2885
|
-
r: 0, g: 0, b: 255, a: alpha,
|
2886
|
-
}).saturate(-saturation).toRgbString();
|
2887
|
-
const fill5 = new Color({
|
2888
|
-
r: 255, g: 0, b: 255, a: alpha,
|
2889
|
-
}).saturate(-saturation).toRgbString();
|
2890
|
-
const fill6 = new Color({
|
2891
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2892
|
-
}).saturate(-saturation).toRgbString();
|
2893
|
-
const fillGradient = `linear-gradient(to right,
|
2894
|
-
${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
|
2895
|
-
${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
|
2896
|
-
const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
|
2897
|
-
linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
|
2898
|
-
|
2899
|
-
setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
|
2900
|
-
const {
|
2901
|
-
r: gr, g: gg, b: gb,
|
2902
|
-
} = new Color({ r, g, b }).greyscale().toRgb();
|
2849
|
+
const fill = new Color({
|
2850
|
+
h: hue, s: 1, l: 0.5, a: alpha,
|
2851
|
+
}).toRgbString();
|
2852
|
+
const hueGradient = `linear-gradient(
|
2853
|
+
rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
|
2854
|
+
rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
|
2855
|
+
rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
|
2856
|
+
rgb(255,0,0) 100%)`;
|
2857
|
+
setElementStyle(v1, {
|
2858
|
+
background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
|
2859
|
+
linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
|
2860
|
+
${whiteGrad}`,
|
2861
|
+
});
|
2862
|
+
setElementStyle(v2, { background: hueGradient });
|
2903
2863
|
|
2904
|
-
setElementStyle(v2, {
|
2905
|
-
background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
|
2906
|
-
});
|
2907
|
-
}
|
2908
2864
|
setElementStyle(v3, {
|
2909
2865
|
background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
|
2910
2866
|
});
|
@@ -2943,7 +2899,7 @@
|
|
2943
2899
|
const self = this;
|
2944
2900
|
const { activeElement } = getDocument(self.input);
|
2945
2901
|
|
2946
|
-
if ((
|
2902
|
+
if ((e.type === touchmoveEvent && self.dragElement)
|
2947
2903
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2948
2904
|
e.stopPropagation();
|
2949
2905
|
e.preventDefault();
|
@@ -3054,13 +3010,13 @@
|
|
3054
3010
|
const [v1, v2, v3] = visuals;
|
3055
3011
|
const [c1, c2, c3] = controlKnobs;
|
3056
3012
|
/** @type {HTMLElement} */
|
3057
|
-
const visual =
|
3058
|
-
? target : querySelector('.visual-control', target.parentElement);
|
3013
|
+
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3059
3014
|
const visualRect = getBoundingClientRect(visual);
|
3015
|
+
const html = getDocumentElement(v1);
|
3060
3016
|
const X = type === 'touchstart' ? touches[0].pageX : pageX;
|
3061
3017
|
const Y = type === 'touchstart' ? touches[0].pageY : pageY;
|
3062
|
-
const offsetX = X -
|
3063
|
-
const offsetY = Y -
|
3018
|
+
const offsetX = X - html.scrollLeft - visualRect.left;
|
3019
|
+
const offsetY = Y - html.scrollTop - visualRect.top;
|
3064
3020
|
|
3065
3021
|
if (target === v1 || target === c1) {
|
3066
3022
|
self.dragElement = visual;
|
@@ -3120,10 +3076,11 @@
|
|
3120
3076
|
if (!dragElement) return;
|
3121
3077
|
|
3122
3078
|
const controlRect = getBoundingClientRect(dragElement);
|
3123
|
-
const
|
3124
|
-
const
|
3125
|
-
const
|
3126
|
-
const
|
3079
|
+
const win = getDocumentElement(v1);
|
3080
|
+
const X = type === touchmoveEvent ? touches[0].pageX : pageX;
|
3081
|
+
const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
|
3082
|
+
const offsetX = X - win.scrollLeft - controlRect.left;
|
3083
|
+
const offsetY = Y - win.scrollTop - controlRect.top;
|
3127
3084
|
|
3128
3085
|
if (dragElement === v1) {
|
3129
3086
|
self.changeControl1(offsetX, offsetY);
|
@@ -3150,19 +3107,19 @@
|
|
3150
3107
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
3151
3108
|
e.preventDefault();
|
3152
3109
|
|
3153
|
-
const {
|
3110
|
+
const { controlKnobs, visuals } = self;
|
3154
3111
|
const { offsetWidth, offsetHeight } = visuals[0];
|
3155
3112
|
const [c1, c2, c3] = controlKnobs;
|
3156
3113
|
const { activeElement } = getDocument(c1);
|
3157
3114
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3158
|
-
const yRatio = offsetHeight /
|
3115
|
+
const yRatio = offsetHeight / 360;
|
3159
3116
|
|
3160
3117
|
if (currentKnob) {
|
3161
3118
|
let offsetX = 0;
|
3162
3119
|
let offsetY = 0;
|
3163
3120
|
|
3164
3121
|
if (target === c1) {
|
3165
|
-
const xRatio = offsetWidth /
|
3122
|
+
const xRatio = offsetWidth / 100;
|
3166
3123
|
|
3167
3124
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3168
3125
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
@@ -3212,7 +3169,7 @@
|
|
3212
3169
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3213
3170
|
if (activeElement === input) {
|
3214
3171
|
if (isNonColorValue) {
|
3215
|
-
colorSource = '
|
3172
|
+
colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
|
3216
3173
|
} else {
|
3217
3174
|
colorSource = currentValue;
|
3218
3175
|
}
|
@@ -3263,9 +3220,7 @@
|
|
3263
3220
|
changeControl1(X, Y) {
|
3264
3221
|
const self = this;
|
3265
3222
|
let [offsetX, offsetY] = [0, 0];
|
3266
|
-
const {
|
3267
|
-
format, controlPositions, visuals,
|
3268
|
-
} = self;
|
3223
|
+
const { controlPositions, visuals } = self;
|
3269
3224
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3270
3225
|
|
3271
3226
|
if (X > offsetWidth) offsetX = offsetWidth;
|
@@ -3274,29 +3229,19 @@
|
|
3274
3229
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3275
3230
|
else if (Y >= 0) offsetY = Y;
|
3276
3231
|
|
3277
|
-
const hue =
|
3278
|
-
? offsetX / offsetWidth
|
3279
|
-
: controlPositions.c2y / offsetHeight;
|
3232
|
+
const hue = controlPositions.c2y / offsetHeight;
|
3280
3233
|
|
3281
|
-
const saturation =
|
3282
|
-
? 1 - controlPositions.c2y / offsetHeight
|
3283
|
-
: offsetX / offsetWidth;
|
3234
|
+
const saturation = offsetX / offsetWidth;
|
3284
3235
|
|
3285
3236
|
const lightness = 1 - offsetY / offsetHeight;
|
3286
3237
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3287
3238
|
|
3288
|
-
const colorObject = format === 'hsl'
|
3289
|
-
? {
|
3290
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3291
|
-
}
|
3292
|
-
: {
|
3293
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3294
|
-
};
|
3295
|
-
|
3296
3239
|
// new color
|
3297
3240
|
const {
|
3298
3241
|
r, g, b, a,
|
3299
|
-
} = new Color(
|
3242
|
+
} = new Color({
|
3243
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3244
|
+
});
|
3300
3245
|
|
3301
3246
|
ObjectAssign(self.color, {
|
3302
3247
|
r, g, b, a,
|
@@ -3323,7 +3268,7 @@
|
|
3323
3268
|
changeControl2(Y) {
|
3324
3269
|
const self = this;
|
3325
3270
|
const {
|
3326
|
-
|
3271
|
+
controlPositions, visuals,
|
3327
3272
|
} = self;
|
3328
3273
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3329
3274
|
|
@@ -3332,26 +3277,17 @@
|
|
3332
3277
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3333
3278
|
else if (Y >= 0) offsetY = Y;
|
3334
3279
|
|
3335
|
-
const hue =
|
3336
|
-
|
3337
|
-
: offsetY / offsetHeight;
|
3338
|
-
const saturation = format === 'hsl'
|
3339
|
-
? 1 - offsetY / offsetHeight
|
3340
|
-
: controlPositions.c1x / offsetWidth;
|
3280
|
+
const hue = offsetY / offsetHeight;
|
3281
|
+
const saturation = controlPositions.c1x / offsetWidth;
|
3341
3282
|
const lightness = 1 - controlPositions.c1y / offsetHeight;
|
3342
3283
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3343
|
-
const colorObject = format === 'hsl'
|
3344
|
-
? {
|
3345
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3346
|
-
}
|
3347
|
-
: {
|
3348
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3349
|
-
};
|
3350
3284
|
|
3351
3285
|
// new color
|
3352
3286
|
const {
|
3353
3287
|
r, g, b, a,
|
3354
|
-
} = new Color(
|
3288
|
+
} = new Color({
|
3289
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3290
|
+
});
|
3355
3291
|
|
3356
3292
|
ObjectAssign(self.color, {
|
3357
3293
|
r, g, b, a,
|
@@ -3438,18 +3374,18 @@
|
|
3438
3374
|
setControlPositions() {
|
3439
3375
|
const self = this;
|
3440
3376
|
const {
|
3441
|
-
|
3377
|
+
visuals, color, hsv,
|
3442
3378
|
} = self;
|
3443
3379
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3444
3380
|
const alpha = color.a;
|
3445
|
-
const hue =
|
3381
|
+
const hue = hsv.h;
|
3446
3382
|
|
3447
|
-
const saturation =
|
3448
|
-
const lightness =
|
3383
|
+
const saturation = hsv.s;
|
3384
|
+
const lightness = hsv.v;
|
3449
3385
|
|
3450
|
-
self.controlPositions.c1x =
|
3386
|
+
self.controlPositions.c1x = saturation * offsetWidth;
|
3451
3387
|
self.controlPositions.c1y = (1 - lightness) * offsetHeight;
|
3452
|
-
self.controlPositions.c2y =
|
3388
|
+
self.controlPositions.c2y = hue * offsetHeight;
|
3453
3389
|
self.controlPositions.c3y = (1 - alpha) * offsetHeight;
|
3454
3390
|
}
|
3455
3391
|
|
@@ -3457,78 +3393,40 @@
|
|
3457
3393
|
updateAppearance() {
|
3458
3394
|
const self = this;
|
3459
3395
|
const {
|
3460
|
-
componentLabels,
|
3461
|
-
|
3396
|
+
componentLabels, color, parent,
|
3397
|
+
hsv, hex, format, controlKnobs,
|
3462
3398
|
} = self;
|
3463
3399
|
const {
|
3464
3400
|
appearanceLabel, hexLabel, valueLabel,
|
3465
3401
|
} = componentLabels;
|
3466
|
-
|
3402
|
+
let { r, g, b } = color.toRgb();
|
3467
3403
|
const [knob1, knob2, knob3] = controlKnobs;
|
3468
|
-
const hue = roundPart(
|
3404
|
+
const hue = roundPart(hsv.h * 360);
|
3469
3405
|
const alpha = color.a;
|
3470
|
-
const
|
3471
|
-
const
|
3472
|
-
const
|
3473
|
-
const hsvl = hsv.v * 100;
|
3474
|
-
let colorName;
|
3475
|
-
|
3476
|
-
// determine color appearance
|
3477
|
-
if (lightness === 100 && saturation === 0) {
|
3478
|
-
colorName = colorLabels.white;
|
3479
|
-
} else if (lightness === 0) {
|
3480
|
-
colorName = colorLabels.black;
|
3481
|
-
} else if (saturation === 0) {
|
3482
|
-
colorName = colorLabels.grey;
|
3483
|
-
} else if (hue < 15 || hue >= 345) {
|
3484
|
-
colorName = colorLabels.red;
|
3485
|
-
} else if (hue >= 15 && hue < 45) {
|
3486
|
-
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
3487
|
-
} else if (hue >= 45 && hue < 75) {
|
3488
|
-
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
3489
|
-
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
3490
|
-
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
3491
|
-
colorName = isOlive ? colorLabels.olive : colorName;
|
3492
|
-
} else if (hue >= 75 && hue < 155) {
|
3493
|
-
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
3494
|
-
} else if (hue >= 155 && hue < 175) {
|
3495
|
-
colorName = colorLabels.teal;
|
3496
|
-
} else if (hue >= 175 && hue < 195) {
|
3497
|
-
colorName = colorLabels.cyan;
|
3498
|
-
} else if (hue >= 195 && hue < 255) {
|
3499
|
-
colorName = colorLabels.blue;
|
3500
|
-
} else if (hue >= 255 && hue < 270) {
|
3501
|
-
colorName = colorLabels.violet;
|
3502
|
-
} else if (hue >= 270 && hue < 295) {
|
3503
|
-
colorName = colorLabels.magenta;
|
3504
|
-
} else if (hue >= 295 && hue < 345) {
|
3505
|
-
colorName = colorLabels.pink;
|
3506
|
-
}
|
3406
|
+
const saturation = roundPart(hsv.s * 100);
|
3407
|
+
const lightness = roundPart(hsv.v * 100);
|
3408
|
+
const colorName = self.appearance;
|
3507
3409
|
|
3508
3410
|
let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
|
3509
3411
|
|
3510
|
-
if (format === '
|
3511
|
-
colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
|
3512
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3513
|
-
setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
|
3514
|
-
setAttribute(knob1, ariaValueNow, `${hue}`);
|
3515
|
-
setAttribute(knob2, ariaValueText, `${saturation}%`);
|
3516
|
-
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3517
|
-
} else if (format === 'hwb') {
|
3412
|
+
if (format === 'hwb') {
|
3518
3413
|
const { hwb } = self;
|
3519
3414
|
const whiteness = roundPart(hwb.w * 100);
|
3520
3415
|
const blackness = roundPart(hwb.b * 100);
|
3521
3416
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3522
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3523
3417
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
3524
3418
|
setAttribute(knob1, ariaValueNow, `${whiteness}`);
|
3419
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3525
3420
|
setAttribute(knob2, ariaValueText, `${hue}%`);
|
3526
3421
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3527
3422
|
} else {
|
3423
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
3424
|
+
colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
|
3528
3425
|
colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
|
3529
|
-
|
3426
|
+
|
3530
3427
|
setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
|
3531
3428
|
setAttribute(knob1, ariaValueNow, `${lightness}`);
|
3429
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3532
3430
|
setAttribute(knob2, ariaValueText, `${hue}°`);
|
3533
3431
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3534
3432
|
}
|
@@ -3623,37 +3521,13 @@
|
|
3623
3521
|
}
|
3624
3522
|
}
|
3625
3523
|
|
3626
|
-
/**
|
3627
|
-
* The `Space` & `Enter` keys specific event listener.
|
3628
|
-
* Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
|
3629
|
-
* @param {KeyboardEvent} e
|
3630
|
-
* @this {ColorPicker}
|
3631
|
-
*/
|
3632
|
-
keyToggle(e) {
|
3633
|
-
const self = this;
|
3634
|
-
const { menuToggle } = self;
|
3635
|
-
const { activeElement } = getDocument(menuToggle);
|
3636
|
-
const { code } = e;
|
3637
|
-
|
3638
|
-
if ([keyEnter, keySpace].includes(code)) {
|
3639
|
-
if ((menuToggle && activeElement === menuToggle) || !activeElement) {
|
3640
|
-
e.preventDefault();
|
3641
|
-
if (!activeElement) {
|
3642
|
-
self.togglePicker(e);
|
3643
|
-
} else {
|
3644
|
-
self.toggleMenu();
|
3645
|
-
}
|
3646
|
-
}
|
3647
|
-
}
|
3648
|
-
}
|
3649
|
-
|
3650
3524
|
/**
|
3651
3525
|
* Toggle the `ColorPicker` dropdown visibility.
|
3652
|
-
* @param {Event} e
|
3526
|
+
* @param {Event=} e
|
3653
3527
|
* @this {ColorPicker}
|
3654
3528
|
*/
|
3655
3529
|
togglePicker(e) {
|
3656
|
-
e.preventDefault();
|
3530
|
+
if (e) e.preventDefault();
|
3657
3531
|
const self = this;
|
3658
3532
|
const { colorPicker } = self;
|
3659
3533
|
|
@@ -3674,8 +3548,13 @@
|
|
3674
3548
|
}
|
3675
3549
|
}
|
3676
3550
|
|
3677
|
-
/**
|
3678
|
-
|
3551
|
+
/**
|
3552
|
+
* Toggles the visibility of the `ColorPicker` presets menu.
|
3553
|
+
* @param {Event=} e
|
3554
|
+
* @this {ColorPicker}
|
3555
|
+
*/
|
3556
|
+
toggleMenu(e) {
|
3557
|
+
if (e) e.preventDefault();
|
3679
3558
|
const self = this;
|
3680
3559
|
const { colorMenu } = self;
|
3681
3560
|
|
@@ -3701,6 +3580,10 @@
|
|
3701
3580
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3702
3581
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3703
3582
|
|
3583
|
+
// if (!self.isValid) {
|
3584
|
+
self.value = self.color.toString(true);
|
3585
|
+
// }
|
3586
|
+
|
3704
3587
|
if (openDropdown) {
|
3705
3588
|
removeClass(openDropdown, 'show');
|
3706
3589
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
@@ -3714,9 +3597,6 @@
|
|
3714
3597
|
}, animationDuration);
|
3715
3598
|
}
|
3716
3599
|
|
3717
|
-
if (!self.isValid) {
|
3718
|
-
self.value = self.color.toString();
|
3719
|
-
}
|
3720
3600
|
if (!focusPrevented) {
|
3721
3601
|
focus(pickerToggle);
|
3722
3602
|
}
|
@@ -3765,90 +3645,82 @@
|
|
3765
3645
|
* `ColorPickerElement` Web Component.
|
3766
3646
|
* @example
|
3767
3647
|
* <label for="UNIQUE_ID">Label</label>
|
3768
|
-
* <color-picker
|
3769
|
-
* <input id="UNIQUE_ID"
|
3648
|
+
* <color-picker>
|
3649
|
+
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3770
3650
|
* </color-picker>
|
3651
|
+
* // or
|
3652
|
+
* <label for="UNIQUE_ID">Label</label>
|
3653
|
+
* <color-picker data-id="UNIQUE_ID" data-value="red" data-format="hex"></color-picker>
|
3771
3654
|
*/
|
3772
3655
|
class ColorPickerElement extends HTMLElement {
|
3773
3656
|
constructor() {
|
3774
3657
|
super();
|
3775
|
-
/** @type {boolean} */
|
3776
|
-
this.isDisconnected = true;
|
3777
3658
|
this.attachShadow({ mode: 'open' });
|
3778
3659
|
}
|
3779
3660
|
|
3780
3661
|
/**
|
3781
3662
|
* Returns the current color value.
|
3782
|
-
* @returns {string
|
3663
|
+
* @returns {string | undefined}
|
3783
3664
|
*/
|
3784
|
-
get value() { return this.input
|
3665
|
+
get value() { return this.input && this.input.value; }
|
3785
3666
|
|
3786
3667
|
connectedCallback() {
|
3787
|
-
if (this.
|
3788
|
-
if (this.isDisconnected) {
|
3789
|
-
this.isDisconnected = false;
|
3790
|
-
}
|
3791
|
-
return;
|
3792
|
-
}
|
3668
|
+
if (this.input) return;
|
3793
3669
|
|
3794
|
-
|
3670
|
+
let [input] = getElementsByTagName('input', this);
|
3671
|
+
const value = (input && getAttribute(input, 'value')) || getAttribute(this, 'data-value') || '#fff';
|
3672
|
+
const format = (input && getAttribute(input, 'format')) || getAttribute(this, 'data-format') || 'rgb';
|
3673
|
+
let id = (input && getAttribute(input, 'id')) || getAttribute(this, 'data-id');
|
3674
|
+
|
3675
|
+
if (!id) {
|
3676
|
+
id = `color-picker-${format}-${CPID}`;
|
3677
|
+
CPID += 1;
|
3678
|
+
}
|
3795
3679
|
|
3796
|
-
if (!
|
3797
|
-
|
3798
|
-
const value = getAttribute(this, 'data-value') || '#069';
|
3799
|
-
const format = getAttribute(this, 'data-format') || 'rgb';
|
3800
|
-
const newInput = createElement({
|
3680
|
+
if (!input) {
|
3681
|
+
input = createElement({
|
3801
3682
|
tagName: 'input',
|
3802
3683
|
type: 'text',
|
3803
3684
|
className: 'color-preview btn-appearance',
|
3804
3685
|
});
|
3805
|
-
let id = getAttribute(this, 'data-id');
|
3806
|
-
if (!id) {
|
3807
|
-
id = `color-picker-${format}-${CPID}`;
|
3808
|
-
CPID += 1;
|
3809
|
-
}
|
3810
3686
|
|
3811
|
-
|
3812
|
-
|
3813
|
-
setAttribute(
|
3814
|
-
setAttribute(
|
3815
|
-
setAttribute(
|
3816
|
-
|
3817
|
-
setAttribute(newInput, 'spellcheck', 'false');
|
3818
|
-
setAttribute(newInput, 'value', value);
|
3819
|
-
this.append(newInput);
|
3687
|
+
setAttribute(input, 'id', id);
|
3688
|
+
setAttribute(input, 'name', id);
|
3689
|
+
setAttribute(input, 'autocomplete', 'off');
|
3690
|
+
setAttribute(input, 'spellcheck', 'false');
|
3691
|
+
setAttribute(input, 'value', value);
|
3692
|
+
this.append(input);
|
3820
3693
|
}
|
3694
|
+
/** @type {HTMLInputElement} */
|
3695
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3696
|
+
this.input = input;
|
3821
3697
|
|
3822
|
-
|
3823
|
-
|
3824
|
-
if (input) {
|
3825
|
-
/** @type {HTMLInputElement} */
|
3826
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3827
|
-
this.input = input;
|
3828
|
-
|
3829
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3830
|
-
this.colorPicker = new ColorPicker(input);
|
3831
|
-
this.color = this.colorPicker.color;
|
3832
|
-
|
3833
|
-
if (this.shadowRoot) {
|
3834
|
-
this.shadowRoot.append(createElement('slot'));
|
3835
|
-
}
|
3698
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3699
|
+
this.colorPicker = new ColorPicker(input);
|
3836
3700
|
|
3837
|
-
|
3838
|
-
|
3701
|
+
// @ts-ignore - `shadowRoot` is defined in the constructor
|
3702
|
+
this.shadowRoot.append(createElement('slot'));
|
3839
3703
|
}
|
3840
3704
|
|
3705
|
+
/** @this {ColorPickerElement} */
|
3841
3706
|
disconnectedCallback() {
|
3842
|
-
|
3843
|
-
|
3707
|
+
const { input, colorPicker, shadowRoot } = this;
|
3708
|
+
if (colorPicker) colorPicker.dispose();
|
3709
|
+
if (input) input.remove();
|
3710
|
+
if (shadowRoot) shadowRoot.innerHTML = '';
|
3711
|
+
|
3712
|
+
ObjectAssign(this, {
|
3713
|
+
colorPicker: undefined,
|
3714
|
+
input: undefined,
|
3715
|
+
});
|
3844
3716
|
}
|
3845
3717
|
}
|
3846
3718
|
|
3847
3719
|
ObjectAssign(ColorPickerElement, {
|
3848
3720
|
Color,
|
3849
3721
|
ColorPicker,
|
3850
|
-
ColorPalette,
|
3851
|
-
getInstance:
|
3722
|
+
ColorPalette, // @ts-ignore
|
3723
|
+
getInstance: ColorPicker.getInstance,
|
3852
3724
|
Version,
|
3853
3725
|
});
|
3854
3726
|
|
@@ -3856,4 +3728,4 @@
|
|
3856
3728
|
|
3857
3729
|
return ColorPickerElement;
|
3858
3730
|
|
3859
|
-
}))
|
3731
|
+
}));
|