@thednp/color-picker 0.0.2-alpha1 → 0.0.2-alpha4
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 +2 -1
- package/dist/js/color-esm.js +94 -105
- package/dist/js/color-esm.min.js +2 -2
- package/dist/js/color-palette-esm.js +105 -119
- package/dist/js/color-palette-esm.min.js +2 -2
- package/dist/js/color-palette.js +105 -119
- package/dist/js/color-palette.min.js +2 -2
- package/dist/js/color-picker-element-esm.js +279 -375
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +279 -375
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +235 -323
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +235 -323
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +94 -105
- package/dist/js/color.min.js +2 -2
- package/package.json +7 -4
- package/src/js/color-palette.js +10 -13
- package/src/js/color-picker-element.js +46 -54
- package/src/js/color-picker.js +131 -206
- package/src/js/color.js +93 -106
- package/types/cp.d.ts +31 -29
- package/types/source/types.d.ts +1 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPickerElement v0.0.
|
2
|
+
* ColorPickerElement v0.0.2alpha4 (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
|
*/
|
@@ -212,6 +212,8 @@ function isColorName(color) {
|
|
212
212
|
if (nonColors.includes(color)
|
213
213
|
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
214
214
|
|
215
|
+
if (['black', 'white'].includes(color)) return true;
|
216
|
+
|
215
217
|
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
216
218
|
setElementStyle(documentHead, { color });
|
217
219
|
const computedColor = getElementStyle(documentHead, 'color');
|
@@ -238,6 +240,11 @@ function isValidCSSUnit(color) {
|
|
238
240
|
*/
|
239
241
|
function bound01(N, max) {
|
240
242
|
let n = N;
|
243
|
+
|
244
|
+
if (typeof N === 'number'
|
245
|
+
&& Math.min(N, 0) === 0 // round values to 6 decimals Math.round(N * (10 ** 6)) / 10 ** 6
|
246
|
+
&& Math.max(N, 1) === 1) return N;
|
247
|
+
|
241
248
|
if (isOnePointZero(N)) n = '100%';
|
242
249
|
|
243
250
|
const processPercent = isPercentage(n);
|
@@ -341,15 +348,12 @@ function pad2(c) {
|
|
341
348
|
/**
|
342
349
|
* Converts an RGB colour value to HSL.
|
343
350
|
*
|
344
|
-
* @param {number}
|
345
|
-
* @param {number}
|
346
|
-
* @param {number}
|
351
|
+
* @param {number} r Red component [0, 1]
|
352
|
+
* @param {number} g Green component [0, 1]
|
353
|
+
* @param {number} b Blue component [0, 1]
|
347
354
|
* @returns {CP.HSL} {h,s,l} object with [0, 1] ranged values
|
348
355
|
*/
|
349
|
-
function rgbToHsl(
|
350
|
-
const r = R / 255;
|
351
|
-
const g = G / 255;
|
352
|
-
const b = B / 255;
|
356
|
+
function rgbToHsl(r, g, b) {
|
353
357
|
const max = Math.max(r, g, b);
|
354
358
|
const min = Math.min(r, g, b);
|
355
359
|
let h = 0;
|
@@ -361,17 +365,10 @@ function rgbToHsl(R, G, B) {
|
|
361
365
|
} else {
|
362
366
|
const d = max - min;
|
363
367
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
case g:
|
369
|
-
h = (b - r) / d + 2;
|
370
|
-
break;
|
371
|
-
case b:
|
372
|
-
h = (r - g) / d + 4;
|
373
|
-
break;
|
374
|
-
}
|
368
|
+
if (max === r) h = (g - b) / d + (g < b ? 6 : 0);
|
369
|
+
if (max === g) h = (b - r) / d + 2;
|
370
|
+
if (max === b) h = (r - g) / d + 4;
|
371
|
+
|
375
372
|
h /= 6;
|
376
373
|
}
|
377
374
|
return { h, s, l };
|
@@ -400,7 +397,7 @@ function hueToRgb(p, q, t) {
|
|
400
397
|
* @param {number} h Hue Angle [0, 1]
|
401
398
|
* @param {number} s Saturation [0, 1]
|
402
399
|
* @param {number} l Lightness Angle [0, 1]
|
403
|
-
* @returns {CP.RGB} {r,g,b} object with [0,
|
400
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
404
401
|
*/
|
405
402
|
function hslToRgb(h, s, l) {
|
406
403
|
let r = 0;
|
@@ -419,7 +416,6 @@ function hslToRgb(h, s, l) {
|
|
419
416
|
g = hueToRgb(p, q, h);
|
420
417
|
b = hueToRgb(p, q, h - 1 / 3);
|
421
418
|
}
|
422
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
423
419
|
|
424
420
|
return { r, g, b };
|
425
421
|
}
|
@@ -429,16 +425,12 @@ function hslToRgb(h, s, l) {
|
|
429
425
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
430
426
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
431
427
|
*
|
432
|
-
* @param {number}
|
433
|
-
* @param {number}
|
434
|
-
* @param {number}
|
428
|
+
* @param {number} r Red component [0, 1]
|
429
|
+
* @param {number} g Green [0, 1]
|
430
|
+
* @param {number} b Blue [0, 1]
|
435
431
|
* @return {CP.HWB} {h,w,b} object with [0, 1] ranged values
|
436
432
|
*/
|
437
|
-
function rgbToHwb(
|
438
|
-
const r = R / 255;
|
439
|
-
const g = G / 255;
|
440
|
-
const b = B / 255;
|
441
|
-
|
433
|
+
function rgbToHwb(r, g, b) {
|
442
434
|
let f = 0;
|
443
435
|
let i = 0;
|
444
436
|
const whiteness = Math.min(r, g, b);
|
@@ -468,20 +460,18 @@ function rgbToHwb(R, G, B) {
|
|
468
460
|
* @param {number} H Hue Angle [0, 1]
|
469
461
|
* @param {number} W Whiteness [0, 1]
|
470
462
|
* @param {number} B Blackness [0, 1]
|
471
|
-
* @return {CP.RGB} {r,g,b} object with [0,
|
463
|
+
* @return {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
472
464
|
*
|
473
465
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
474
466
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
475
467
|
*/
|
476
468
|
function hwbToRgb(H, W, B) {
|
477
469
|
if (W + B >= 1) {
|
478
|
-
const gray =
|
470
|
+
const gray = W / (W + B);
|
479
471
|
return { r: gray, g: gray, b: gray };
|
480
472
|
}
|
481
473
|
let { r, g, b } = hslToRgb(H, 1, 0.5);
|
482
|
-
[r, g, b] = [r, g, b]
|
483
|
-
.map((v) => (v / 255) * (1 - W - B) + W)
|
484
|
-
.map((v) => v * 255);
|
474
|
+
[r, g, b] = [r, g, b].map((v) => v * (1 - W - B) + W);
|
485
475
|
|
486
476
|
return { r, g, b };
|
487
477
|
}
|
@@ -489,15 +479,12 @@ function hwbToRgb(H, W, B) {
|
|
489
479
|
/**
|
490
480
|
* Converts an RGB colour value to HSV.
|
491
481
|
*
|
492
|
-
* @param {number}
|
493
|
-
* @param {number}
|
494
|
-
* @param {number}
|
482
|
+
* @param {number} r Red component [0, 1]
|
483
|
+
* @param {number} g Green [0, 1]
|
484
|
+
* @param {number} b Blue [0, 1]
|
495
485
|
* @returns {CP.HSV} {h,s,v} object with [0, 1] ranged values
|
496
486
|
*/
|
497
|
-
function rgbToHsv(
|
498
|
-
const r = R / 255;
|
499
|
-
const g = G / 255;
|
500
|
-
const b = B / 255;
|
487
|
+
function rgbToHsv(r, g, b) {
|
501
488
|
const max = Math.max(r, g, b);
|
502
489
|
const min = Math.min(r, g, b);
|
503
490
|
let h = 0;
|
@@ -507,17 +494,10 @@ function rgbToHsv(R, G, B) {
|
|
507
494
|
if (max === min) {
|
508
495
|
h = 0; // achromatic
|
509
496
|
} else {
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
case g:
|
515
|
-
h = (b - r) / d + 2;
|
516
|
-
break;
|
517
|
-
case b:
|
518
|
-
h = (r - g) / d + 4;
|
519
|
-
break;
|
520
|
-
}
|
497
|
+
if (r === max) h = (g - b) / d + (g < b ? 6 : 0);
|
498
|
+
if (g === max) h = (b - r) / d + 2;
|
499
|
+
if (b === max) h = (r - g) / d + 4;
|
500
|
+
|
521
501
|
h /= 6;
|
522
502
|
}
|
523
503
|
return { h, s, v };
|
@@ -541,10 +521,9 @@ function hsvToRgb(H, S, V) {
|
|
541
521
|
const q = v * (1 - f * s);
|
542
522
|
const t = v * (1 - (1 - f) * s);
|
543
523
|
const mod = i % 6;
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
[r, g, b] = [r, g, b].map((n) => n * 255);
|
524
|
+
const r = [v, q, p, p, t, v][mod];
|
525
|
+
const g = [t, v, v, q, p, p][mod];
|
526
|
+
const b = [p, p, t, v, v, q][mod];
|
548
527
|
return { r, g, b };
|
549
528
|
}
|
550
529
|
|
@@ -612,15 +591,15 @@ function rgbaToHex(r, g, b, a, allow4Char) {
|
|
612
591
|
*/
|
613
592
|
function stringInputToObject(input) {
|
614
593
|
let color = toLowerCase(input.trim());
|
594
|
+
|
615
595
|
if (color.length === 0) {
|
616
596
|
return {
|
617
597
|
r: 0, g: 0, b: 0, a: 1,
|
618
598
|
};
|
619
599
|
}
|
620
|
-
|
600
|
+
|
621
601
|
if (isColorName(color)) {
|
622
602
|
color = getRGBFromName(color);
|
623
|
-
named = true;
|
624
603
|
} else if (nonColors.includes(color)) {
|
625
604
|
const a = color === 'transparent' ? 0 : 1;
|
626
605
|
return {
|
@@ -639,24 +618,28 @@ function stringInputToObject(input) {
|
|
639
618
|
r: m1, g: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'rgb',
|
640
619
|
};
|
641
620
|
}
|
621
|
+
|
642
622
|
[, m1, m2, m3, m4] = matchers.hsl.exec(color) || [];
|
643
623
|
if (m1 && m2 && m3/* && m4 */) {
|
644
624
|
return {
|
645
625
|
h: m1, s: m2, l: m3, a: m4 !== undefined ? m4 : 1, format: 'hsl',
|
646
626
|
};
|
647
627
|
}
|
628
|
+
|
648
629
|
[, m1, m2, m3, m4] = matchers.hsv.exec(color) || [];
|
649
630
|
if (m1 && m2 && m3/* && m4 */) {
|
650
631
|
return {
|
651
632
|
h: m1, s: m2, v: m3, a: m4 !== undefined ? m4 : 1, format: 'hsv',
|
652
633
|
};
|
653
634
|
}
|
635
|
+
|
654
636
|
[, m1, m2, m3, m4] = matchers.hwb.exec(color) || [];
|
655
637
|
if (m1 && m2 && m3) {
|
656
638
|
return {
|
657
639
|
h: m1, w: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'hwb',
|
658
640
|
};
|
659
641
|
}
|
642
|
+
|
660
643
|
[, m1, m2, m3, m4] = matchers.hex8.exec(color) || [];
|
661
644
|
if (m1 && m2 && m3 && m4) {
|
662
645
|
return {
|
@@ -664,18 +647,20 @@ function stringInputToObject(input) {
|
|
664
647
|
g: parseIntFromHex(m2),
|
665
648
|
b: parseIntFromHex(m3),
|
666
649
|
a: convertHexToDecimal(m4),
|
667
|
-
format:
|
650
|
+
format: 'hex',
|
668
651
|
};
|
669
652
|
}
|
653
|
+
|
670
654
|
[, m1, m2, m3] = matchers.hex6.exec(color) || [];
|
671
655
|
if (m1 && m2 && m3) {
|
672
656
|
return {
|
673
657
|
r: parseIntFromHex(m1),
|
674
658
|
g: parseIntFromHex(m2),
|
675
659
|
b: parseIntFromHex(m3),
|
676
|
-
format:
|
660
|
+
format: 'hex',
|
677
661
|
};
|
678
662
|
}
|
663
|
+
|
679
664
|
[, m1, m2, m3, m4] = matchers.hex4.exec(color) || [];
|
680
665
|
if (m1 && m2 && m3 && m4) {
|
681
666
|
return {
|
@@ -683,19 +668,20 @@ function stringInputToObject(input) {
|
|
683
668
|
g: parseIntFromHex(m2 + m2),
|
684
669
|
b: parseIntFromHex(m3 + m3),
|
685
670
|
a: convertHexToDecimal(m4 + m4),
|
686
|
-
|
687
|
-
format: named ? 'rgb' : 'hex',
|
671
|
+
format: 'hex',
|
688
672
|
};
|
689
673
|
}
|
674
|
+
|
690
675
|
[, m1, m2, m3] = matchers.hex3.exec(color) || [];
|
691
676
|
if (m1 && m2 && m3) {
|
692
677
|
return {
|
693
678
|
r: parseIntFromHex(m1 + m1),
|
694
679
|
g: parseIntFromHex(m2 + m2),
|
695
680
|
b: parseIntFromHex(m3 + m3),
|
696
|
-
format:
|
681
|
+
format: 'hex',
|
697
682
|
};
|
698
683
|
}
|
684
|
+
|
699
685
|
return false;
|
700
686
|
}
|
701
687
|
|
@@ -726,6 +712,7 @@ function stringInputToObject(input) {
|
|
726
712
|
*/
|
727
713
|
function inputToRGB(input) {
|
728
714
|
let rgb = { r: 0, g: 0, b: 0 };
|
715
|
+
/** @type {*} */
|
729
716
|
let color = input;
|
730
717
|
/** @type {string | number} */
|
731
718
|
let a = 1;
|
@@ -742,39 +729,41 @@ function inputToRGB(input) {
|
|
742
729
|
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
743
730
|
|
744
731
|
if (typeof input === 'string') {
|
745
|
-
// @ts-ignore -- this now is converted to object
|
746
732
|
color = stringInputToObject(input);
|
747
733
|
if (color) ok = true;
|
748
734
|
}
|
749
735
|
if (typeof color === 'object') {
|
750
736
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
751
737
|
({ r, g, b } = color);
|
752
|
-
// RGB values now are all in [0,
|
753
|
-
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255)
|
738
|
+
// RGB values now are all in [0, 1] range
|
739
|
+
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255));
|
754
740
|
rgb = { r, g, b };
|
755
741
|
ok = true;
|
756
|
-
format = 'rgb';
|
757
|
-
}
|
742
|
+
format = color.format || 'rgb';
|
743
|
+
}
|
744
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
758
745
|
({ h, s, v } = color);
|
759
|
-
h =
|
760
|
-
s =
|
761
|
-
v =
|
746
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
747
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
748
|
+
v = bound01(v, 100); // brightness can be `5%` or a [0, 1] value
|
762
749
|
rgb = hsvToRgb(h, s, v);
|
763
750
|
ok = true;
|
764
751
|
format = 'hsv';
|
765
|
-
}
|
752
|
+
}
|
753
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
|
766
754
|
({ h, s, l } = color);
|
767
|
-
h =
|
768
|
-
s =
|
769
|
-
l =
|
755
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
756
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
757
|
+
l = bound01(l, 100); // lightness can be `5%` or a [0, 1] value
|
770
758
|
rgb = hslToRgb(h, s, l);
|
771
759
|
ok = true;
|
772
760
|
format = 'hsl';
|
773
|
-
}
|
761
|
+
}
|
762
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
|
774
763
|
({ h, w, b } = color);
|
775
|
-
h =
|
776
|
-
w =
|
777
|
-
b =
|
764
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
765
|
+
w = bound01(w, 100); // whiteness can be `5%` or a [0, 1] value
|
766
|
+
b = bound01(b, 100); // blackness can be `5%` or a [0, 1] value
|
778
767
|
rgb = hwbToRgb(h, w, b);
|
779
768
|
ok = true;
|
780
769
|
format = 'hwb';
|
@@ -791,9 +780,12 @@ function inputToRGB(input) {
|
|
791
780
|
return {
|
792
781
|
ok,
|
793
782
|
format,
|
794
|
-
r: Math.min(255, Math.max(rgb.r, 0)),
|
795
|
-
g: Math.min(255, Math.max(rgb.g, 0)),
|
796
|
-
b: Math.min(255, Math.max(rgb.b, 0)),
|
783
|
+
// r: Math.min(255, Math.max(rgb.r, 0)),
|
784
|
+
// g: Math.min(255, Math.max(rgb.g, 0)),
|
785
|
+
// b: Math.min(255, Math.max(rgb.b, 0)),
|
786
|
+
r: rgb.r,
|
787
|
+
g: rgb.g,
|
788
|
+
b: rgb.b,
|
797
789
|
a: boundAlpha(a),
|
798
790
|
};
|
799
791
|
}
|
@@ -812,16 +804,13 @@ class Color {
|
|
812
804
|
constructor(input, config) {
|
813
805
|
let color = input;
|
814
806
|
const configFormat = config && COLOR_FORMAT.includes(config)
|
815
|
-
? config : '
|
807
|
+
? config : '';
|
816
808
|
|
817
|
-
// If input is already a `Color`,
|
809
|
+
// If input is already a `Color`, clone its values
|
818
810
|
if (color instanceof Color) {
|
819
811
|
color = inputToRGB(color);
|
820
812
|
}
|
821
|
-
|
822
|
-
const len = `${color}`.length;
|
823
|
-
color = `#${(len === 2 ? '0' : '00')}${color}`;
|
824
|
-
}
|
813
|
+
|
825
814
|
const {
|
826
815
|
r, g, b, a, ok, format,
|
827
816
|
} = inputToRGB(color);
|
@@ -871,24 +860,21 @@ class Color {
|
|
871
860
|
let R = 0;
|
872
861
|
let G = 0;
|
873
862
|
let B = 0;
|
874
|
-
const rp = r / 255;
|
875
|
-
const rg = g / 255;
|
876
|
-
const rb = b / 255;
|
877
863
|
|
878
|
-
if (
|
879
|
-
R =
|
864
|
+
if (r <= 0.03928) {
|
865
|
+
R = r / 12.92;
|
880
866
|
} else {
|
881
|
-
R = ((
|
867
|
+
R = ((r + 0.055) / 1.055) ** 2.4;
|
882
868
|
}
|
883
|
-
if (
|
884
|
-
G =
|
869
|
+
if (g <= 0.03928) {
|
870
|
+
G = g / 12.92;
|
885
871
|
} else {
|
886
|
-
G = ((
|
872
|
+
G = ((g + 0.055) / 1.055) ** 2.4;
|
887
873
|
}
|
888
|
-
if (
|
889
|
-
B =
|
874
|
+
if (b <= 0.03928) {
|
875
|
+
B = b / 12.92;
|
890
876
|
} else {
|
891
|
-
B = ((
|
877
|
+
B = ((b + 0.055) / 1.055) ** 2.4;
|
892
878
|
}
|
893
879
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
|
894
880
|
}
|
@@ -898,7 +884,7 @@ class Color {
|
|
898
884
|
* @returns {number} a number in the [0, 255] range
|
899
885
|
*/
|
900
886
|
get brightness() {
|
901
|
-
const { r, g, b } = this;
|
887
|
+
const { r, g, b } = this.toRgb();
|
902
888
|
return (r * 299 + g * 587 + b * 114) / 1000;
|
903
889
|
}
|
904
890
|
|
@@ -907,12 +893,14 @@ class Color {
|
|
907
893
|
* @returns {CP.RGBA} an {r,g,b,a} object with [0, 255] ranged values
|
908
894
|
*/
|
909
895
|
toRgb() {
|
910
|
-
|
896
|
+
let {
|
911
897
|
r, g, b, a,
|
912
898
|
} = this;
|
913
899
|
|
900
|
+
[r, g, b] = [r, g, b].map((n) => roundPart(n * 255 * 100) / 100);
|
901
|
+
a = roundPart(a * 100) / 100;
|
914
902
|
return {
|
915
|
-
r, g, b, a
|
903
|
+
r, g, b, a,
|
916
904
|
};
|
917
905
|
}
|
918
906
|
|
@@ -1006,7 +994,7 @@ class Color {
|
|
1006
994
|
toHsv() {
|
1007
995
|
const {
|
1008
996
|
r, g, b, a,
|
1009
|
-
} = this
|
997
|
+
} = this;
|
1010
998
|
const { h, s, v } = rgbToHsv(r, g, b);
|
1011
999
|
|
1012
1000
|
return {
|
@@ -1021,7 +1009,7 @@ class Color {
|
|
1021
1009
|
toHsl() {
|
1022
1010
|
const {
|
1023
1011
|
r, g, b, a,
|
1024
|
-
} = this
|
1012
|
+
} = this;
|
1025
1013
|
const { h, s, l } = rgbToHsl(r, g, b);
|
1026
1014
|
|
1027
1015
|
return {
|
@@ -1106,6 +1094,7 @@ class Color {
|
|
1106
1094
|
*/
|
1107
1095
|
setAlpha(alpha) {
|
1108
1096
|
const self = this;
|
1097
|
+
if (typeof alpha !== 'number') return self;
|
1109
1098
|
self.a = boundAlpha(alpha);
|
1110
1099
|
return self;
|
1111
1100
|
}
|
@@ -1934,26 +1923,23 @@ class ColorPalette {
|
|
1934
1923
|
} else if (args.length === 2) {
|
1935
1924
|
[hueSteps, lightSteps] = args;
|
1936
1925
|
if ([hueSteps, lightSteps].some((n) => n < 1)) {
|
1937
|
-
throw TypeError('ColorPalette:
|
1926
|
+
throw TypeError('ColorPalette: both arguments must be higher than 0.');
|
1938
1927
|
}
|
1939
|
-
} else {
|
1940
|
-
throw TypeError('ColorPalette requires minimum 2 arguments');
|
1941
1928
|
}
|
1942
1929
|
|
1943
|
-
/** @type {
|
1930
|
+
/** @type {*} */
|
1944
1931
|
const colors = [];
|
1945
|
-
|
1946
1932
|
const hueStep = 360 / hueSteps;
|
1947
1933
|
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
1948
|
-
const
|
1934
|
+
const steps1To13 = [0.25, 0.2, 0.15, 0.11, 0.09, 0.075];
|
1935
|
+
const lightSets = [[1, 2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]];
|
1936
|
+
const closestSet = lightSets.find((set) => set.includes(lightSteps));
|
1949
1937
|
|
1950
|
-
|
1951
|
-
|
1952
|
-
lightStep =
|
1953
|
-
|
1954
|
-
|
1955
|
-
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
1956
|
-
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
1938
|
+
// find a lightStep that won't go beyond black and white
|
1939
|
+
// something within the [10-90] range of lightness
|
1940
|
+
const lightStep = closestSet
|
1941
|
+
? steps1To13[lightSets.indexOf(closestSet)]
|
1942
|
+
: (100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100);
|
1957
1943
|
|
1958
1944
|
// light tints
|
1959
1945
|
for (let i = 1; i < half + 1; i += 1) {
|
@@ -2445,7 +2431,7 @@ function setMarkup(self) {
|
|
2445
2431
|
setAttribute(input, tabIndex, '-1');
|
2446
2432
|
}
|
2447
2433
|
|
2448
|
-
var version = "0.0.
|
2434
|
+
var version = "0.0.2alpha4";
|
2449
2435
|
|
2450
2436
|
// @ts-ignore
|
2451
2437
|
|
@@ -2488,8 +2474,6 @@ function toggleEvents(self, action) {
|
|
2488
2474
|
fn(input, focusinEvent, self.showPicker);
|
2489
2475
|
fn(pickerToggle, mouseclickEvent, self.togglePicker);
|
2490
2476
|
|
2491
|
-
fn(input, keydownEvent, self.keyToggle);
|
2492
|
-
|
2493
2477
|
if (menuToggle) {
|
2494
2478
|
fn(menuToggle, mouseclickEvent, self.toggleMenu);
|
2495
2479
|
}
|
@@ -2527,8 +2511,7 @@ function toggleEventsOnShown(self, action) {
|
|
2527
2511
|
fn(doc, pointerEvents.move, self.pointerMove);
|
2528
2512
|
fn(doc, pointerEvents.up, self.pointerUp);
|
2529
2513
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2530
|
-
|
2531
|
-
fn(win, keyupEvent, self.handleDismiss);
|
2514
|
+
fn(doc, keyupEvent, self.handleDismiss);
|
2532
2515
|
}
|
2533
2516
|
|
2534
2517
|
/**
|
@@ -2612,7 +2595,7 @@ class ColorPicker {
|
|
2612
2595
|
const input = querySelector(target);
|
2613
2596
|
|
2614
2597
|
// invalidate
|
2615
|
-
if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
|
2598
|
+
if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
|
2616
2599
|
self.input = input;
|
2617
2600
|
|
2618
2601
|
const parent = closest(input, colorPickerParentSelector);
|
@@ -2659,15 +2642,14 @@ class ColorPicker {
|
|
2659
2642
|
});
|
2660
2643
|
|
2661
2644
|
// update and expose component labels
|
2662
|
-
const
|
2663
|
-
|
2664
|
-
? JSON.parse(componentLabels) : componentLabels || {};
|
2645
|
+
const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
|
2646
|
+
? JSON.parse(componentLabels) : componentLabels;
|
2665
2647
|
|
2666
2648
|
/** @type {Record<string, string>} */
|
2667
|
-
self.componentLabels = ObjectAssign(
|
2649
|
+
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2668
2650
|
|
2669
2651
|
/** @type {Color} */
|
2670
|
-
self.color = new Color('
|
2652
|
+
self.color = new Color(input.value || '#fff', format);
|
2671
2653
|
|
2672
2654
|
/** @type {CP.ColorFormats} */
|
2673
2655
|
self.format = format;
|
@@ -2676,7 +2658,7 @@ class ColorPicker {
|
|
2676
2658
|
if (colorKeywords instanceof Array) {
|
2677
2659
|
self.colorKeywords = colorKeywords;
|
2678
2660
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2679
|
-
self.colorKeywords = colorKeywords.split(',');
|
2661
|
+
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2680
2662
|
}
|
2681
2663
|
|
2682
2664
|
// set colour presets
|
@@ -2705,7 +2687,6 @@ class ColorPicker {
|
|
2705
2687
|
self.handleFocusOut = self.handleFocusOut.bind(self);
|
2706
2688
|
self.changeHandler = self.changeHandler.bind(self);
|
2707
2689
|
self.handleDismiss = self.handleDismiss.bind(self);
|
2708
|
-
self.keyToggle = self.keyToggle.bind(self);
|
2709
2690
|
self.handleKnobs = self.handleKnobs.bind(self);
|
2710
2691
|
|
2711
2692
|
// generate markup
|
@@ -2797,76 +2778,83 @@ class ColorPicker {
|
|
2797
2778
|
return inputValue !== '' && new Color(inputValue).isValid;
|
2798
2779
|
}
|
2799
2780
|
|
2781
|
+
/** Returns the colour appearance, usually the closest colour name for the current value. */
|
2782
|
+
get appearance() {
|
2783
|
+
const {
|
2784
|
+
colorLabels, hsl, hsv, format,
|
2785
|
+
} = this;
|
2786
|
+
|
2787
|
+
const hue = roundPart(hsl.h * 360);
|
2788
|
+
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
2789
|
+
const saturation = roundPart(saturationSource * 100);
|
2790
|
+
const lightness = roundPart(hsl.l * 100);
|
2791
|
+
const hsvl = hsv.v * 100;
|
2792
|
+
|
2793
|
+
let colorName;
|
2794
|
+
|
2795
|
+
// determine color appearance
|
2796
|
+
if (lightness === 100 && saturation === 0) {
|
2797
|
+
colorName = colorLabels.white;
|
2798
|
+
} else if (lightness === 0) {
|
2799
|
+
colorName = colorLabels.black;
|
2800
|
+
} else if (saturation === 0) {
|
2801
|
+
colorName = colorLabels.grey;
|
2802
|
+
} else if (hue < 15 || hue >= 345) {
|
2803
|
+
colorName = colorLabels.red;
|
2804
|
+
} else if (hue >= 15 && hue < 45) {
|
2805
|
+
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
2806
|
+
} else if (hue >= 45 && hue < 75) {
|
2807
|
+
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
2808
|
+
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
2809
|
+
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
2810
|
+
colorName = isOlive ? colorLabels.olive : colorName;
|
2811
|
+
} else if (hue >= 75 && hue < 155) {
|
2812
|
+
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
2813
|
+
} else if (hue >= 155 && hue < 175) {
|
2814
|
+
colorName = colorLabels.teal;
|
2815
|
+
} else if (hue >= 175 && hue < 195) {
|
2816
|
+
colorName = colorLabels.cyan;
|
2817
|
+
} else if (hue >= 195 && hue < 255) {
|
2818
|
+
colorName = colorLabels.blue;
|
2819
|
+
} else if (hue >= 255 && hue < 270) {
|
2820
|
+
colorName = colorLabels.violet;
|
2821
|
+
} else if (hue >= 270 && hue < 295) {
|
2822
|
+
colorName = colorLabels.magenta;
|
2823
|
+
} else if (hue >= 295 && hue < 345) {
|
2824
|
+
colorName = colorLabels.pink;
|
2825
|
+
}
|
2826
|
+
return colorName;
|
2827
|
+
}
|
2828
|
+
|
2800
2829
|
/** Updates `ColorPicker` visuals. */
|
2801
2830
|
updateVisuals() {
|
2802
2831
|
const self = this;
|
2803
2832
|
const {
|
2804
|
-
|
2833
|
+
controlPositions, visuals,
|
2805
2834
|
} = self;
|
2806
2835
|
const [v1, v2, v3] = visuals;
|
2807
|
-
const {
|
2808
|
-
const hue =
|
2809
|
-
|
2810
|
-
: controlPositions.c2y / offsetHeight;
|
2811
|
-
// @ts-ignore - `hslToRgb` is assigned to `Color` as static method
|
2812
|
-
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
2836
|
+
const { offsetHeight } = v1;
|
2837
|
+
const hue = controlPositions.c2y / offsetHeight;
|
2838
|
+
const { r, g, b } = new Color({ h: hue, s: 1, l: 0.5 }).toRgb();
|
2813
2839
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2814
2840
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2815
2841
|
const roundA = roundPart((alpha * 100)) / 100;
|
2816
2842
|
|
2817
|
-
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
setElementStyle(v2, { background: hueGradient });
|
2832
|
-
} else {
|
2833
|
-
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2834
|
-
const fill0 = new Color({
|
2835
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2836
|
-
}).saturate(-saturation).toRgbString();
|
2837
|
-
const fill1 = new Color({
|
2838
|
-
r: 255, g: 255, b: 0, a: alpha,
|
2839
|
-
}).saturate(-saturation).toRgbString();
|
2840
|
-
const fill2 = new Color({
|
2841
|
-
r: 0, g: 255, b: 0, a: alpha,
|
2842
|
-
}).saturate(-saturation).toRgbString();
|
2843
|
-
const fill3 = new Color({
|
2844
|
-
r: 0, g: 255, b: 255, a: alpha,
|
2845
|
-
}).saturate(-saturation).toRgbString();
|
2846
|
-
const fill4 = new Color({
|
2847
|
-
r: 0, g: 0, b: 255, a: alpha,
|
2848
|
-
}).saturate(-saturation).toRgbString();
|
2849
|
-
const fill5 = new Color({
|
2850
|
-
r: 255, g: 0, b: 255, a: alpha,
|
2851
|
-
}).saturate(-saturation).toRgbString();
|
2852
|
-
const fill6 = new Color({
|
2853
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2854
|
-
}).saturate(-saturation).toRgbString();
|
2855
|
-
const fillGradient = `linear-gradient(to right,
|
2856
|
-
${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
|
2857
|
-
${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
|
2858
|
-
const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
|
2859
|
-
linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
|
2860
|
-
|
2861
|
-
setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
|
2862
|
-
const {
|
2863
|
-
r: gr, g: gg, b: gb,
|
2864
|
-
} = new Color({ r, g, b }).greyscale().toRgb();
|
2843
|
+
const fill = new Color({
|
2844
|
+
h: hue, s: 1, l: 0.5, a: alpha,
|
2845
|
+
}).toRgbString();
|
2846
|
+
const hueGradient = `linear-gradient(
|
2847
|
+
rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
|
2848
|
+
rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
|
2849
|
+
rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
|
2850
|
+
rgb(255,0,0) 100%)`;
|
2851
|
+
setElementStyle(v1, {
|
2852
|
+
background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
|
2853
|
+
linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
|
2854
|
+
${whiteGrad}`,
|
2855
|
+
});
|
2856
|
+
setElementStyle(v2, { background: hueGradient });
|
2865
2857
|
|
2866
|
-
setElementStyle(v2, {
|
2867
|
-
background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
|
2868
|
-
});
|
2869
|
-
}
|
2870
2858
|
setElementStyle(v3, {
|
2871
2859
|
background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
|
2872
2860
|
});
|
@@ -3016,13 +3004,13 @@ class ColorPicker {
|
|
3016
3004
|
const [v1, v2, v3] = visuals;
|
3017
3005
|
const [c1, c2, c3] = controlKnobs;
|
3018
3006
|
/** @type {HTMLElement} */
|
3019
|
-
const visual =
|
3020
|
-
? target : querySelector('.visual-control', target.parentElement);
|
3007
|
+
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3021
3008
|
const visualRect = getBoundingClientRect(visual);
|
3009
|
+
const html = getDocumentElement(v1);
|
3022
3010
|
const X = type === 'touchstart' ? touches[0].pageX : pageX;
|
3023
3011
|
const Y = type === 'touchstart' ? touches[0].pageY : pageY;
|
3024
|
-
const offsetX = X -
|
3025
|
-
const offsetY = Y -
|
3012
|
+
const offsetX = X - html.scrollLeft - visualRect.left;
|
3013
|
+
const offsetY = Y - html.scrollTop - visualRect.top;
|
3026
3014
|
|
3027
3015
|
if (target === v1 || target === c1) {
|
3028
3016
|
self.dragElement = visual;
|
@@ -3082,10 +3070,11 @@ class ColorPicker {
|
|
3082
3070
|
if (!dragElement) return;
|
3083
3071
|
|
3084
3072
|
const controlRect = getBoundingClientRect(dragElement);
|
3085
|
-
const
|
3086
|
-
const
|
3087
|
-
const
|
3088
|
-
const
|
3073
|
+
const win = getDocumentElement(v1);
|
3074
|
+
const X = type === touchmoveEvent ? touches[0].pageX : pageX;
|
3075
|
+
const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
|
3076
|
+
const offsetX = X - win.scrollLeft - controlRect.left;
|
3077
|
+
const offsetY = Y - win.scrollTop - controlRect.top;
|
3089
3078
|
|
3090
3079
|
if (dragElement === v1) {
|
3091
3080
|
self.changeControl1(offsetX, offsetY);
|
@@ -3112,19 +3101,19 @@ class ColorPicker {
|
|
3112
3101
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
3113
3102
|
e.preventDefault();
|
3114
3103
|
|
3115
|
-
const {
|
3104
|
+
const { controlKnobs, visuals } = self;
|
3116
3105
|
const { offsetWidth, offsetHeight } = visuals[0];
|
3117
3106
|
const [c1, c2, c3] = controlKnobs;
|
3118
3107
|
const { activeElement } = getDocument(c1);
|
3119
3108
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3120
|
-
const yRatio = offsetHeight /
|
3109
|
+
const yRatio = offsetHeight / 360;
|
3121
3110
|
|
3122
3111
|
if (currentKnob) {
|
3123
3112
|
let offsetX = 0;
|
3124
3113
|
let offsetY = 0;
|
3125
3114
|
|
3126
3115
|
if (target === c1) {
|
3127
|
-
const xRatio = offsetWidth /
|
3116
|
+
const xRatio = offsetWidth / 100;
|
3128
3117
|
|
3129
3118
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3130
3119
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
@@ -3174,7 +3163,7 @@ class ColorPicker {
|
|
3174
3163
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3175
3164
|
if (activeElement === input) {
|
3176
3165
|
if (isNonColorValue) {
|
3177
|
-
colorSource = '
|
3166
|
+
colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
|
3178
3167
|
} else {
|
3179
3168
|
colorSource = currentValue;
|
3180
3169
|
}
|
@@ -3225,9 +3214,7 @@ class ColorPicker {
|
|
3225
3214
|
changeControl1(X, Y) {
|
3226
3215
|
const self = this;
|
3227
3216
|
let [offsetX, offsetY] = [0, 0];
|
3228
|
-
const {
|
3229
|
-
format, controlPositions, visuals,
|
3230
|
-
} = self;
|
3217
|
+
const { controlPositions, visuals } = self;
|
3231
3218
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3232
3219
|
|
3233
3220
|
if (X > offsetWidth) offsetX = offsetWidth;
|
@@ -3236,29 +3223,19 @@ class ColorPicker {
|
|
3236
3223
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3237
3224
|
else if (Y >= 0) offsetY = Y;
|
3238
3225
|
|
3239
|
-
const hue =
|
3240
|
-
? offsetX / offsetWidth
|
3241
|
-
: controlPositions.c2y / offsetHeight;
|
3226
|
+
const hue = controlPositions.c2y / offsetHeight;
|
3242
3227
|
|
3243
|
-
const saturation =
|
3244
|
-
? 1 - controlPositions.c2y / offsetHeight
|
3245
|
-
: offsetX / offsetWidth;
|
3228
|
+
const saturation = offsetX / offsetWidth;
|
3246
3229
|
|
3247
3230
|
const lightness = 1 - offsetY / offsetHeight;
|
3248
3231
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3249
3232
|
|
3250
|
-
const colorObject = format === 'hsl'
|
3251
|
-
? {
|
3252
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3253
|
-
}
|
3254
|
-
: {
|
3255
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3256
|
-
};
|
3257
|
-
|
3258
3233
|
// new color
|
3259
3234
|
const {
|
3260
3235
|
r, g, b, a,
|
3261
|
-
} = new Color(
|
3236
|
+
} = new Color({
|
3237
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3238
|
+
});
|
3262
3239
|
|
3263
3240
|
ObjectAssign(self.color, {
|
3264
3241
|
r, g, b, a,
|
@@ -3285,7 +3262,7 @@ class ColorPicker {
|
|
3285
3262
|
changeControl2(Y) {
|
3286
3263
|
const self = this;
|
3287
3264
|
const {
|
3288
|
-
|
3265
|
+
controlPositions, visuals,
|
3289
3266
|
} = self;
|
3290
3267
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3291
3268
|
|
@@ -3294,26 +3271,17 @@ class ColorPicker {
|
|
3294
3271
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3295
3272
|
else if (Y >= 0) offsetY = Y;
|
3296
3273
|
|
3297
|
-
const hue =
|
3298
|
-
|
3299
|
-
: offsetY / offsetHeight;
|
3300
|
-
const saturation = format === 'hsl'
|
3301
|
-
? 1 - offsetY / offsetHeight
|
3302
|
-
: controlPositions.c1x / offsetWidth;
|
3274
|
+
const hue = offsetY / offsetHeight;
|
3275
|
+
const saturation = controlPositions.c1x / offsetWidth;
|
3303
3276
|
const lightness = 1 - controlPositions.c1y / offsetHeight;
|
3304
3277
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3305
|
-
const colorObject = format === 'hsl'
|
3306
|
-
? {
|
3307
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3308
|
-
}
|
3309
|
-
: {
|
3310
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3311
|
-
};
|
3312
3278
|
|
3313
3279
|
// new color
|
3314
3280
|
const {
|
3315
3281
|
r, g, b, a,
|
3316
|
-
} = new Color(
|
3282
|
+
} = new Color({
|
3283
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3284
|
+
});
|
3317
3285
|
|
3318
3286
|
ObjectAssign(self.color, {
|
3319
3287
|
r, g, b, a,
|
@@ -3400,18 +3368,18 @@ class ColorPicker {
|
|
3400
3368
|
setControlPositions() {
|
3401
3369
|
const self = this;
|
3402
3370
|
const {
|
3403
|
-
|
3371
|
+
visuals, color, hsv,
|
3404
3372
|
} = self;
|
3405
3373
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3406
3374
|
const alpha = color.a;
|
3407
|
-
const hue =
|
3375
|
+
const hue = hsv.h;
|
3408
3376
|
|
3409
|
-
const saturation =
|
3410
|
-
const lightness =
|
3377
|
+
const saturation = hsv.s;
|
3378
|
+
const lightness = hsv.v;
|
3411
3379
|
|
3412
|
-
self.controlPositions.c1x =
|
3380
|
+
self.controlPositions.c1x = saturation * offsetWidth;
|
3413
3381
|
self.controlPositions.c1y = (1 - lightness) * offsetHeight;
|
3414
|
-
self.controlPositions.c2y =
|
3382
|
+
self.controlPositions.c2y = hue * offsetHeight;
|
3415
3383
|
self.controlPositions.c3y = (1 - alpha) * offsetHeight;
|
3416
3384
|
}
|
3417
3385
|
|
@@ -3419,78 +3387,40 @@ class ColorPicker {
|
|
3419
3387
|
updateAppearance() {
|
3420
3388
|
const self = this;
|
3421
3389
|
const {
|
3422
|
-
componentLabels,
|
3423
|
-
|
3390
|
+
componentLabels, color, parent,
|
3391
|
+
hsv, hex, format, controlKnobs,
|
3424
3392
|
} = self;
|
3425
3393
|
const {
|
3426
3394
|
appearanceLabel, hexLabel, valueLabel,
|
3427
3395
|
} = componentLabels;
|
3428
|
-
|
3396
|
+
let { r, g, b } = color.toRgb();
|
3429
3397
|
const [knob1, knob2, knob3] = controlKnobs;
|
3430
|
-
const hue = roundPart(
|
3398
|
+
const hue = roundPart(hsv.h * 360);
|
3431
3399
|
const alpha = color.a;
|
3432
|
-
const
|
3433
|
-
const
|
3434
|
-
const
|
3435
|
-
const hsvl = hsv.v * 100;
|
3436
|
-
let colorName;
|
3437
|
-
|
3438
|
-
// determine color appearance
|
3439
|
-
if (lightness === 100 && saturation === 0) {
|
3440
|
-
colorName = colorLabels.white;
|
3441
|
-
} else if (lightness === 0) {
|
3442
|
-
colorName = colorLabels.black;
|
3443
|
-
} else if (saturation === 0) {
|
3444
|
-
colorName = colorLabels.grey;
|
3445
|
-
} else if (hue < 15 || hue >= 345) {
|
3446
|
-
colorName = colorLabels.red;
|
3447
|
-
} else if (hue >= 15 && hue < 45) {
|
3448
|
-
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
3449
|
-
} else if (hue >= 45 && hue < 75) {
|
3450
|
-
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
3451
|
-
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
3452
|
-
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
3453
|
-
colorName = isOlive ? colorLabels.olive : colorName;
|
3454
|
-
} else if (hue >= 75 && hue < 155) {
|
3455
|
-
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
3456
|
-
} else if (hue >= 155 && hue < 175) {
|
3457
|
-
colorName = colorLabels.teal;
|
3458
|
-
} else if (hue >= 175 && hue < 195) {
|
3459
|
-
colorName = colorLabels.cyan;
|
3460
|
-
} else if (hue >= 195 && hue < 255) {
|
3461
|
-
colorName = colorLabels.blue;
|
3462
|
-
} else if (hue >= 255 && hue < 270) {
|
3463
|
-
colorName = colorLabels.violet;
|
3464
|
-
} else if (hue >= 270 && hue < 295) {
|
3465
|
-
colorName = colorLabels.magenta;
|
3466
|
-
} else if (hue >= 295 && hue < 345) {
|
3467
|
-
colorName = colorLabels.pink;
|
3468
|
-
}
|
3400
|
+
const saturation = roundPart(hsv.s * 100);
|
3401
|
+
const lightness = roundPart(hsv.v * 100);
|
3402
|
+
const colorName = self.appearance;
|
3469
3403
|
|
3470
3404
|
let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
|
3471
3405
|
|
3472
|
-
if (format === '
|
3473
|
-
colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
|
3474
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3475
|
-
setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
|
3476
|
-
setAttribute(knob1, ariaValueNow, `${hue}`);
|
3477
|
-
setAttribute(knob2, ariaValueText, `${saturation}%`);
|
3478
|
-
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3479
|
-
} else if (format === 'hwb') {
|
3406
|
+
if (format === 'hwb') {
|
3480
3407
|
const { hwb } = self;
|
3481
3408
|
const whiteness = roundPart(hwb.w * 100);
|
3482
3409
|
const blackness = roundPart(hwb.b * 100);
|
3483
3410
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3484
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3485
3411
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
3486
3412
|
setAttribute(knob1, ariaValueNow, `${whiteness}`);
|
3413
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3487
3414
|
setAttribute(knob2, ariaValueText, `${hue}%`);
|
3488
3415
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3489
3416
|
} else {
|
3417
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
3418
|
+
colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
|
3490
3419
|
colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
|
3491
|
-
|
3420
|
+
|
3492
3421
|
setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
|
3493
3422
|
setAttribute(knob1, ariaValueNow, `${lightness}`);
|
3423
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3494
3424
|
setAttribute(knob2, ariaValueText, `${hue}°`);
|
3495
3425
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3496
3426
|
}
|
@@ -3585,37 +3515,13 @@ class ColorPicker {
|
|
3585
3515
|
}
|
3586
3516
|
}
|
3587
3517
|
|
3588
|
-
/**
|
3589
|
-
* The `Space` & `Enter` keys specific event listener.
|
3590
|
-
* Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
|
3591
|
-
* @param {KeyboardEvent} e
|
3592
|
-
* @this {ColorPicker}
|
3593
|
-
*/
|
3594
|
-
keyToggle(e) {
|
3595
|
-
const self = this;
|
3596
|
-
const { menuToggle } = self;
|
3597
|
-
const { activeElement } = getDocument(menuToggle);
|
3598
|
-
const { code } = e;
|
3599
|
-
|
3600
|
-
if ([keyEnter, keySpace].includes(code)) {
|
3601
|
-
if ((menuToggle && activeElement === menuToggle) || !activeElement) {
|
3602
|
-
e.preventDefault();
|
3603
|
-
if (!activeElement) {
|
3604
|
-
self.togglePicker(e);
|
3605
|
-
} else {
|
3606
|
-
self.toggleMenu();
|
3607
|
-
}
|
3608
|
-
}
|
3609
|
-
}
|
3610
|
-
}
|
3611
|
-
|
3612
3518
|
/**
|
3613
3519
|
* Toggle the `ColorPicker` dropdown visibility.
|
3614
|
-
* @param {Event} e
|
3520
|
+
* @param {Event=} e
|
3615
3521
|
* @this {ColorPicker}
|
3616
3522
|
*/
|
3617
3523
|
togglePicker(e) {
|
3618
|
-
e.preventDefault();
|
3524
|
+
if (e) e.preventDefault();
|
3619
3525
|
const self = this;
|
3620
3526
|
const { colorPicker } = self;
|
3621
3527
|
|
@@ -3636,8 +3542,13 @@ class ColorPicker {
|
|
3636
3542
|
}
|
3637
3543
|
}
|
3638
3544
|
|
3639
|
-
/**
|
3640
|
-
|
3545
|
+
/**
|
3546
|
+
* Toggles the visibility of the `ColorPicker` presets menu.
|
3547
|
+
* @param {Event=} e
|
3548
|
+
* @this {ColorPicker}
|
3549
|
+
*/
|
3550
|
+
toggleMenu(e) {
|
3551
|
+
if (e) e.preventDefault();
|
3641
3552
|
const self = this;
|
3642
3553
|
const { colorMenu } = self;
|
3643
3554
|
|
@@ -3663,6 +3574,10 @@ class ColorPicker {
|
|
3663
3574
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3664
3575
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3665
3576
|
|
3577
|
+
// if (!self.isValid) {
|
3578
|
+
self.value = self.color.toString(true);
|
3579
|
+
// }
|
3580
|
+
|
3666
3581
|
if (openDropdown) {
|
3667
3582
|
removeClass(openDropdown, 'show');
|
3668
3583
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
@@ -3676,9 +3591,6 @@ class ColorPicker {
|
|
3676
3591
|
}, animationDuration);
|
3677
3592
|
}
|
3678
3593
|
|
3679
|
-
if (!self.isValid) {
|
3680
|
-
self.value = self.color.toString();
|
3681
|
-
}
|
3682
3594
|
if (!focusPrevented) {
|
3683
3595
|
focus(pickerToggle);
|
3684
3596
|
}
|
@@ -3727,90 +3639,82 @@ let CPID = 0;
|
|
3727
3639
|
* `ColorPickerElement` Web Component.
|
3728
3640
|
* @example
|
3729
3641
|
* <label for="UNIQUE_ID">Label</label>
|
3730
|
-
* <color-picker
|
3731
|
-
* <input id="UNIQUE_ID"
|
3642
|
+
* <color-picker>
|
3643
|
+
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3732
3644
|
* </color-picker>
|
3645
|
+
* // or
|
3646
|
+
* <label for="UNIQUE_ID">Label</label>
|
3647
|
+
* <color-picker data-id="UNIQUE_ID" data-value="red" data-format="hex"></color-picker>
|
3733
3648
|
*/
|
3734
3649
|
class ColorPickerElement extends HTMLElement {
|
3735
3650
|
constructor() {
|
3736
3651
|
super();
|
3737
|
-
/** @type {boolean} */
|
3738
|
-
this.isDisconnected = true;
|
3739
3652
|
this.attachShadow({ mode: 'open' });
|
3740
3653
|
}
|
3741
3654
|
|
3742
3655
|
/**
|
3743
3656
|
* Returns the current color value.
|
3744
|
-
* @returns {string
|
3657
|
+
* @returns {string | undefined}
|
3745
3658
|
*/
|
3746
|
-
get value() { return this.input
|
3659
|
+
get value() { return this.input && this.input.value; }
|
3747
3660
|
|
3748
3661
|
connectedCallback() {
|
3749
|
-
if (this.
|
3750
|
-
if (this.isDisconnected) {
|
3751
|
-
this.isDisconnected = false;
|
3752
|
-
}
|
3753
|
-
return;
|
3754
|
-
}
|
3662
|
+
if (this.input) return;
|
3755
3663
|
|
3756
|
-
|
3664
|
+
let [input] = getElementsByTagName('input', this);
|
3665
|
+
const value = (input && getAttribute(input, 'value')) || getAttribute(this, 'data-value') || '#fff';
|
3666
|
+
const format = (input && getAttribute(input, 'format')) || getAttribute(this, 'data-format') || 'rgb';
|
3667
|
+
let id = (input && getAttribute(input, 'id')) || getAttribute(this, 'data-id');
|
3668
|
+
|
3669
|
+
if (!id) {
|
3670
|
+
id = `color-picker-${format}-${CPID}`;
|
3671
|
+
CPID += 1;
|
3672
|
+
}
|
3757
3673
|
|
3758
|
-
if (!
|
3759
|
-
|
3760
|
-
const value = getAttribute(this, 'data-value') || '#069';
|
3761
|
-
const format = getAttribute(this, 'data-format') || 'rgb';
|
3762
|
-
const newInput = createElement({
|
3674
|
+
if (!input) {
|
3675
|
+
input = createElement({
|
3763
3676
|
tagName: 'input',
|
3764
3677
|
type: 'text',
|
3765
3678
|
className: 'color-preview btn-appearance',
|
3766
3679
|
});
|
3767
|
-
let id = getAttribute(this, 'data-id');
|
3768
|
-
if (!id) {
|
3769
|
-
id = `color-picker-${format}-${CPID}`;
|
3770
|
-
CPID += 1;
|
3771
|
-
}
|
3772
3680
|
|
3773
|
-
|
3774
|
-
|
3775
|
-
setAttribute(
|
3776
|
-
setAttribute(
|
3777
|
-
setAttribute(
|
3778
|
-
|
3779
|
-
setAttribute(newInput, 'spellcheck', 'false');
|
3780
|
-
setAttribute(newInput, 'value', value);
|
3781
|
-
this.append(newInput);
|
3681
|
+
setAttribute(input, 'id', id);
|
3682
|
+
setAttribute(input, 'name', id);
|
3683
|
+
setAttribute(input, 'autocomplete', 'off');
|
3684
|
+
setAttribute(input, 'spellcheck', 'false');
|
3685
|
+
setAttribute(input, 'value', value);
|
3686
|
+
this.append(input);
|
3782
3687
|
}
|
3688
|
+
/** @type {HTMLInputElement} */
|
3689
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3690
|
+
this.input = input;
|
3783
3691
|
|
3784
|
-
|
3785
|
-
|
3786
|
-
if (input) {
|
3787
|
-
/** @type {HTMLInputElement} */
|
3788
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3789
|
-
this.input = input;
|
3790
|
-
|
3791
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3792
|
-
this.colorPicker = new ColorPicker(input);
|
3793
|
-
this.color = this.colorPicker.color;
|
3794
|
-
|
3795
|
-
if (this.shadowRoot) {
|
3796
|
-
this.shadowRoot.append(createElement('slot'));
|
3797
|
-
}
|
3692
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3693
|
+
this.colorPicker = new ColorPicker(input);
|
3798
3694
|
|
3799
|
-
|
3800
|
-
|
3695
|
+
// @ts-ignore - `shadowRoot` is defined in the constructor
|
3696
|
+
this.shadowRoot.append(createElement('slot'));
|
3801
3697
|
}
|
3802
3698
|
|
3699
|
+
/** @this {ColorPickerElement} */
|
3803
3700
|
disconnectedCallback() {
|
3804
|
-
|
3805
|
-
|
3701
|
+
const { input, colorPicker, shadowRoot } = this;
|
3702
|
+
if (colorPicker) colorPicker.dispose();
|
3703
|
+
if (input) input.remove();
|
3704
|
+
if (shadowRoot) shadowRoot.innerHTML = '';
|
3705
|
+
|
3706
|
+
ObjectAssign(this, {
|
3707
|
+
colorPicker: undefined,
|
3708
|
+
input: undefined,
|
3709
|
+
});
|
3806
3710
|
}
|
3807
3711
|
}
|
3808
3712
|
|
3809
3713
|
ObjectAssign(ColorPickerElement, {
|
3810
3714
|
Color,
|
3811
3715
|
ColorPicker,
|
3812
|
-
ColorPalette,
|
3813
|
-
getInstance:
|
3716
|
+
ColorPalette, // @ts-ignore
|
3717
|
+
getInstance: ColorPicker.getInstance,
|
3814
3718
|
Version,
|
3815
3719
|
});
|
3816
3720
|
|