@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
|
*/
|
@@ -218,6 +218,8 @@
|
|
218
218
|
if (nonColors.includes(color)
|
219
219
|
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
220
220
|
|
221
|
+
if (['black', 'white'].includes(color)) return true;
|
222
|
+
|
221
223
|
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
222
224
|
setElementStyle(documentHead, { color });
|
223
225
|
const computedColor = getElementStyle(documentHead, 'color');
|
@@ -244,6 +246,11 @@
|
|
244
246
|
*/
|
245
247
|
function bound01(N, max) {
|
246
248
|
let n = N;
|
249
|
+
|
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
|
+
|
247
254
|
if (isOnePointZero(N)) n = '100%';
|
248
255
|
|
249
256
|
const processPercent = isPercentage(n);
|
@@ -347,15 +354,12 @@
|
|
347
354
|
/**
|
348
355
|
* Converts an RGB colour value to HSL.
|
349
356
|
*
|
350
|
-
* @param {number}
|
351
|
-
* @param {number}
|
352
|
-
* @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]
|
353
360
|
* @returns {CP.HSL} {h,s,l} object with [0, 1] ranged values
|
354
361
|
*/
|
355
|
-
function rgbToHsl(
|
356
|
-
const r = R / 255;
|
357
|
-
const g = G / 255;
|
358
|
-
const b = B / 255;
|
362
|
+
function rgbToHsl(r, g, b) {
|
359
363
|
const max = Math.max(r, g, b);
|
360
364
|
const min = Math.min(r, g, b);
|
361
365
|
let h = 0;
|
@@ -367,17 +371,10 @@
|
|
367
371
|
} else {
|
368
372
|
const d = max - min;
|
369
373
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
case g:
|
375
|
-
h = (b - r) / d + 2;
|
376
|
-
break;
|
377
|
-
case b:
|
378
|
-
h = (r - g) / d + 4;
|
379
|
-
break;
|
380
|
-
}
|
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
|
+
|
381
378
|
h /= 6;
|
382
379
|
}
|
383
380
|
return { h, s, l };
|
@@ -406,7 +403,7 @@
|
|
406
403
|
* @param {number} h Hue Angle [0, 1]
|
407
404
|
* @param {number} s Saturation [0, 1]
|
408
405
|
* @param {number} l Lightness Angle [0, 1]
|
409
|
-
* @returns {CP.RGB} {r,g,b} object with [0,
|
406
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
410
407
|
*/
|
411
408
|
function hslToRgb(h, s, l) {
|
412
409
|
let r = 0;
|
@@ -425,7 +422,6 @@
|
|
425
422
|
g = hueToRgb(p, q, h);
|
426
423
|
b = hueToRgb(p, q, h - 1 / 3);
|
427
424
|
}
|
428
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
429
425
|
|
430
426
|
return { r, g, b };
|
431
427
|
}
|
@@ -435,16 +431,12 @@
|
|
435
431
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
436
432
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
437
433
|
*
|
438
|
-
* @param {number}
|
439
|
-
* @param {number}
|
440
|
-
* @param {number}
|
434
|
+
* @param {number} r Red component [0, 1]
|
435
|
+
* @param {number} g Green [0, 1]
|
436
|
+
* @param {number} b Blue [0, 1]
|
441
437
|
* @return {CP.HWB} {h,w,b} object with [0, 1] ranged values
|
442
438
|
*/
|
443
|
-
function rgbToHwb(
|
444
|
-
const r = R / 255;
|
445
|
-
const g = G / 255;
|
446
|
-
const b = B / 255;
|
447
|
-
|
439
|
+
function rgbToHwb(r, g, b) {
|
448
440
|
let f = 0;
|
449
441
|
let i = 0;
|
450
442
|
const whiteness = Math.min(r, g, b);
|
@@ -474,20 +466,18 @@
|
|
474
466
|
* @param {number} H Hue Angle [0, 1]
|
475
467
|
* @param {number} W Whiteness [0, 1]
|
476
468
|
* @param {number} B Blackness [0, 1]
|
477
|
-
* @return {CP.RGB} {r,g,b} object with [0,
|
469
|
+
* @return {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
478
470
|
*
|
479
471
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
480
472
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
481
473
|
*/
|
482
474
|
function hwbToRgb(H, W, B) {
|
483
475
|
if (W + B >= 1) {
|
484
|
-
const gray =
|
476
|
+
const gray = W / (W + B);
|
485
477
|
return { r: gray, g: gray, b: gray };
|
486
478
|
}
|
487
479
|
let { r, g, b } = hslToRgb(H, 1, 0.5);
|
488
|
-
[r, g, b] = [r, g, b]
|
489
|
-
.map((v) => (v / 255) * (1 - W - B) + W)
|
490
|
-
.map((v) => v * 255);
|
480
|
+
[r, g, b] = [r, g, b].map((v) => v * (1 - W - B) + W);
|
491
481
|
|
492
482
|
return { r, g, b };
|
493
483
|
}
|
@@ -495,15 +485,12 @@
|
|
495
485
|
/**
|
496
486
|
* Converts an RGB colour value to HSV.
|
497
487
|
*
|
498
|
-
* @param {number}
|
499
|
-
* @param {number}
|
500
|
-
* @param {number}
|
488
|
+
* @param {number} r Red component [0, 1]
|
489
|
+
* @param {number} g Green [0, 1]
|
490
|
+
* @param {number} b Blue [0, 1]
|
501
491
|
* @returns {CP.HSV} {h,s,v} object with [0, 1] ranged values
|
502
492
|
*/
|
503
|
-
function rgbToHsv(
|
504
|
-
const r = R / 255;
|
505
|
-
const g = G / 255;
|
506
|
-
const b = B / 255;
|
493
|
+
function rgbToHsv(r, g, b) {
|
507
494
|
const max = Math.max(r, g, b);
|
508
495
|
const min = Math.min(r, g, b);
|
509
496
|
let h = 0;
|
@@ -513,17 +500,10 @@
|
|
513
500
|
if (max === min) {
|
514
501
|
h = 0; // achromatic
|
515
502
|
} else {
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
case g:
|
521
|
-
h = (b - r) / d + 2;
|
522
|
-
break;
|
523
|
-
case b:
|
524
|
-
h = (r - g) / d + 4;
|
525
|
-
break;
|
526
|
-
}
|
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
|
+
|
527
507
|
h /= 6;
|
528
508
|
}
|
529
509
|
return { h, s, v };
|
@@ -547,10 +527,9 @@
|
|
547
527
|
const q = v * (1 - f * s);
|
548
528
|
const t = v * (1 - (1 - f) * s);
|
549
529
|
const mod = i % 6;
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
[r, g, b] = [r, g, b].map((n) => n * 255);
|
530
|
+
const r = [v, q, p, p, t, v][mod];
|
531
|
+
const g = [t, v, v, q, p, p][mod];
|
532
|
+
const b = [p, p, t, v, v, q][mod];
|
554
533
|
return { r, g, b };
|
555
534
|
}
|
556
535
|
|
@@ -618,15 +597,15 @@
|
|
618
597
|
*/
|
619
598
|
function stringInputToObject(input) {
|
620
599
|
let color = toLowerCase(input.trim());
|
600
|
+
|
621
601
|
if (color.length === 0) {
|
622
602
|
return {
|
623
603
|
r: 0, g: 0, b: 0, a: 1,
|
624
604
|
};
|
625
605
|
}
|
626
|
-
|
606
|
+
|
627
607
|
if (isColorName(color)) {
|
628
608
|
color = getRGBFromName(color);
|
629
|
-
named = true;
|
630
609
|
} else if (nonColors.includes(color)) {
|
631
610
|
const a = color === 'transparent' ? 0 : 1;
|
632
611
|
return {
|
@@ -645,24 +624,28 @@
|
|
645
624
|
r: m1, g: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'rgb',
|
646
625
|
};
|
647
626
|
}
|
627
|
+
|
648
628
|
[, m1, m2, m3, m4] = matchers.hsl.exec(color) || [];
|
649
629
|
if (m1 && m2 && m3/* && m4 */) {
|
650
630
|
return {
|
651
631
|
h: m1, s: m2, l: m3, a: m4 !== undefined ? m4 : 1, format: 'hsl',
|
652
632
|
};
|
653
633
|
}
|
634
|
+
|
654
635
|
[, m1, m2, m3, m4] = matchers.hsv.exec(color) || [];
|
655
636
|
if (m1 && m2 && m3/* && m4 */) {
|
656
637
|
return {
|
657
638
|
h: m1, s: m2, v: m3, a: m4 !== undefined ? m4 : 1, format: 'hsv',
|
658
639
|
};
|
659
640
|
}
|
641
|
+
|
660
642
|
[, m1, m2, m3, m4] = matchers.hwb.exec(color) || [];
|
661
643
|
if (m1 && m2 && m3) {
|
662
644
|
return {
|
663
645
|
h: m1, w: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'hwb',
|
664
646
|
};
|
665
647
|
}
|
648
|
+
|
666
649
|
[, m1, m2, m3, m4] = matchers.hex8.exec(color) || [];
|
667
650
|
if (m1 && m2 && m3 && m4) {
|
668
651
|
return {
|
@@ -670,18 +653,20 @@
|
|
670
653
|
g: parseIntFromHex(m2),
|
671
654
|
b: parseIntFromHex(m3),
|
672
655
|
a: convertHexToDecimal(m4),
|
673
|
-
format:
|
656
|
+
format: 'hex',
|
674
657
|
};
|
675
658
|
}
|
659
|
+
|
676
660
|
[, m1, m2, m3] = matchers.hex6.exec(color) || [];
|
677
661
|
if (m1 && m2 && m3) {
|
678
662
|
return {
|
679
663
|
r: parseIntFromHex(m1),
|
680
664
|
g: parseIntFromHex(m2),
|
681
665
|
b: parseIntFromHex(m3),
|
682
|
-
format:
|
666
|
+
format: 'hex',
|
683
667
|
};
|
684
668
|
}
|
669
|
+
|
685
670
|
[, m1, m2, m3, m4] = matchers.hex4.exec(color) || [];
|
686
671
|
if (m1 && m2 && m3 && m4) {
|
687
672
|
return {
|
@@ -689,19 +674,20 @@
|
|
689
674
|
g: parseIntFromHex(m2 + m2),
|
690
675
|
b: parseIntFromHex(m3 + m3),
|
691
676
|
a: convertHexToDecimal(m4 + m4),
|
692
|
-
|
693
|
-
format: named ? 'rgb' : 'hex',
|
677
|
+
format: 'hex',
|
694
678
|
};
|
695
679
|
}
|
680
|
+
|
696
681
|
[, m1, m2, m3] = matchers.hex3.exec(color) || [];
|
697
682
|
if (m1 && m2 && m3) {
|
698
683
|
return {
|
699
684
|
r: parseIntFromHex(m1 + m1),
|
700
685
|
g: parseIntFromHex(m2 + m2),
|
701
686
|
b: parseIntFromHex(m3 + m3),
|
702
|
-
format:
|
687
|
+
format: 'hex',
|
703
688
|
};
|
704
689
|
}
|
690
|
+
|
705
691
|
return false;
|
706
692
|
}
|
707
693
|
|
@@ -732,6 +718,7 @@
|
|
732
718
|
*/
|
733
719
|
function inputToRGB(input) {
|
734
720
|
let rgb = { r: 0, g: 0, b: 0 };
|
721
|
+
/** @type {*} */
|
735
722
|
let color = input;
|
736
723
|
/** @type {string | number} */
|
737
724
|
let a = 1;
|
@@ -748,39 +735,41 @@
|
|
748
735
|
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
749
736
|
|
750
737
|
if (typeof input === 'string') {
|
751
|
-
// @ts-ignore -- this now is converted to object
|
752
738
|
color = stringInputToObject(input);
|
753
739
|
if (color) ok = true;
|
754
740
|
}
|
755
741
|
if (typeof color === 'object') {
|
756
742
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
757
743
|
({ r, g, b } = color);
|
758
|
-
// RGB values now are all in [0,
|
759
|
-
[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));
|
760
746
|
rgb = { r, g, b };
|
761
747
|
ok = true;
|
762
|
-
format = 'rgb';
|
763
|
-
}
|
748
|
+
format = color.format || 'rgb';
|
749
|
+
}
|
750
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
764
751
|
({ h, s, v } = color);
|
765
|
-
h =
|
766
|
-
s =
|
767
|
-
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
|
768
755
|
rgb = hsvToRgb(h, s, v);
|
769
756
|
ok = true;
|
770
757
|
format = 'hsv';
|
771
|
-
}
|
758
|
+
}
|
759
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
|
772
760
|
({ h, s, l } = color);
|
773
|
-
h =
|
774
|
-
s =
|
775
|
-
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
|
776
764
|
rgb = hslToRgb(h, s, l);
|
777
765
|
ok = true;
|
778
766
|
format = 'hsl';
|
779
|
-
}
|
767
|
+
}
|
768
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
|
780
769
|
({ h, w, b } = color);
|
781
|
-
h =
|
782
|
-
w =
|
783
|
-
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
|
784
773
|
rgb = hwbToRgb(h, w, b);
|
785
774
|
ok = true;
|
786
775
|
format = 'hwb';
|
@@ -797,9 +786,12 @@
|
|
797
786
|
return {
|
798
787
|
ok,
|
799
788
|
format,
|
800
|
-
r: Math.min(255, Math.max(rgb.r, 0)),
|
801
|
-
g: Math.min(255, Math.max(rgb.g, 0)),
|
802
|
-
b: Math.min(255, Math.max(rgb.b, 0)),
|
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,
|
803
795
|
a: boundAlpha(a),
|
804
796
|
};
|
805
797
|
}
|
@@ -818,16 +810,13 @@
|
|
818
810
|
constructor(input, config) {
|
819
811
|
let color = input;
|
820
812
|
const configFormat = config && COLOR_FORMAT.includes(config)
|
821
|
-
? config : '
|
813
|
+
? config : '';
|
822
814
|
|
823
|
-
// If input is already a `Color`,
|
815
|
+
// If input is already a `Color`, clone its values
|
824
816
|
if (color instanceof Color) {
|
825
817
|
color = inputToRGB(color);
|
826
818
|
}
|
827
|
-
|
828
|
-
const len = `${color}`.length;
|
829
|
-
color = `#${(len === 2 ? '0' : '00')}${color}`;
|
830
|
-
}
|
819
|
+
|
831
820
|
const {
|
832
821
|
r, g, b, a, ok, format,
|
833
822
|
} = inputToRGB(color);
|
@@ -877,24 +866,21 @@
|
|
877
866
|
let R = 0;
|
878
867
|
let G = 0;
|
879
868
|
let B = 0;
|
880
|
-
const rp = r / 255;
|
881
|
-
const rg = g / 255;
|
882
|
-
const rb = b / 255;
|
883
869
|
|
884
|
-
if (
|
885
|
-
R =
|
870
|
+
if (r <= 0.03928) {
|
871
|
+
R = r / 12.92;
|
886
872
|
} else {
|
887
|
-
R = ((
|
873
|
+
R = ((r + 0.055) / 1.055) ** 2.4;
|
888
874
|
}
|
889
|
-
if (
|
890
|
-
G =
|
875
|
+
if (g <= 0.03928) {
|
876
|
+
G = g / 12.92;
|
891
877
|
} else {
|
892
|
-
G = ((
|
878
|
+
G = ((g + 0.055) / 1.055) ** 2.4;
|
893
879
|
}
|
894
|
-
if (
|
895
|
-
B =
|
880
|
+
if (b <= 0.03928) {
|
881
|
+
B = b / 12.92;
|
896
882
|
} else {
|
897
|
-
B = ((
|
883
|
+
B = ((b + 0.055) / 1.055) ** 2.4;
|
898
884
|
}
|
899
885
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
|
900
886
|
}
|
@@ -904,7 +890,7 @@
|
|
904
890
|
* @returns {number} a number in the [0, 255] range
|
905
891
|
*/
|
906
892
|
get brightness() {
|
907
|
-
const { r, g, b } = this;
|
893
|
+
const { r, g, b } = this.toRgb();
|
908
894
|
return (r * 299 + g * 587 + b * 114) / 1000;
|
909
895
|
}
|
910
896
|
|
@@ -913,12 +899,14 @@
|
|
913
899
|
* @returns {CP.RGBA} an {r,g,b,a} object with [0, 255] ranged values
|
914
900
|
*/
|
915
901
|
toRgb() {
|
916
|
-
|
902
|
+
let {
|
917
903
|
r, g, b, a,
|
918
904
|
} = this;
|
919
905
|
|
906
|
+
[r, g, b] = [r, g, b].map((n) => roundPart(n * 255 * 100) / 100);
|
907
|
+
a = roundPart(a * 100) / 100;
|
920
908
|
return {
|
921
|
-
r, g, b, a
|
909
|
+
r, g, b, a,
|
922
910
|
};
|
923
911
|
}
|
924
912
|
|
@@ -1012,7 +1000,7 @@
|
|
1012
1000
|
toHsv() {
|
1013
1001
|
const {
|
1014
1002
|
r, g, b, a,
|
1015
|
-
} = this
|
1003
|
+
} = this;
|
1016
1004
|
const { h, s, v } = rgbToHsv(r, g, b);
|
1017
1005
|
|
1018
1006
|
return {
|
@@ -1027,7 +1015,7 @@
|
|
1027
1015
|
toHsl() {
|
1028
1016
|
const {
|
1029
1017
|
r, g, b, a,
|
1030
|
-
} = this
|
1018
|
+
} = this;
|
1031
1019
|
const { h, s, l } = rgbToHsl(r, g, b);
|
1032
1020
|
|
1033
1021
|
return {
|
@@ -1112,6 +1100,7 @@
|
|
1112
1100
|
*/
|
1113
1101
|
setAlpha(alpha) {
|
1114
1102
|
const self = this;
|
1103
|
+
if (typeof alpha !== 'number') return self;
|
1115
1104
|
self.a = boundAlpha(alpha);
|
1116
1105
|
return self;
|
1117
1106
|
}
|
@@ -1940,26 +1929,23 @@
|
|
1940
1929
|
} else if (args.length === 2) {
|
1941
1930
|
[hueSteps, lightSteps] = args;
|
1942
1931
|
if ([hueSteps, lightSteps].some((n) => n < 1)) {
|
1943
|
-
throw TypeError('ColorPalette:
|
1932
|
+
throw TypeError('ColorPalette: both arguments must be higher than 0.');
|
1944
1933
|
}
|
1945
|
-
} else {
|
1946
|
-
throw TypeError('ColorPalette requires minimum 2 arguments');
|
1947
1934
|
}
|
1948
1935
|
|
1949
|
-
/** @type {
|
1936
|
+
/** @type {*} */
|
1950
1937
|
const colors = [];
|
1951
|
-
|
1952
1938
|
const hueStep = 360 / hueSteps;
|
1953
1939
|
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
1954
|
-
const
|
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));
|
1955
1943
|
|
1956
|
-
|
1957
|
-
|
1958
|
-
lightStep =
|
1959
|
-
|
1960
|
-
|
1961
|
-
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
1962
|
-
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
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);
|
1963
1949
|
|
1964
1950
|
// light tints
|
1965
1951
|
for (let i = 1; i < half + 1; i += 1) {
|
@@ -2451,7 +2437,7 @@
|
|
2451
2437
|
setAttribute(input, tabIndex, '-1');
|
2452
2438
|
}
|
2453
2439
|
|
2454
|
-
var version = "0.0.
|
2440
|
+
var version = "0.0.2alpha4";
|
2455
2441
|
|
2456
2442
|
// @ts-ignore
|
2457
2443
|
|
@@ -2494,8 +2480,6 @@
|
|
2494
2480
|
fn(input, focusinEvent, self.showPicker);
|
2495
2481
|
fn(pickerToggle, mouseclickEvent, self.togglePicker);
|
2496
2482
|
|
2497
|
-
fn(input, keydownEvent, self.keyToggle);
|
2498
|
-
|
2499
2483
|
if (menuToggle) {
|
2500
2484
|
fn(menuToggle, mouseclickEvent, self.toggleMenu);
|
2501
2485
|
}
|
@@ -2533,8 +2517,7 @@
|
|
2533
2517
|
fn(doc, pointerEvents.move, self.pointerMove);
|
2534
2518
|
fn(doc, pointerEvents.up, self.pointerUp);
|
2535
2519
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2536
|
-
|
2537
|
-
fn(win, keyupEvent, self.handleDismiss);
|
2520
|
+
fn(doc, keyupEvent, self.handleDismiss);
|
2538
2521
|
}
|
2539
2522
|
|
2540
2523
|
/**
|
@@ -2618,7 +2601,7 @@
|
|
2618
2601
|
const input = querySelector(target);
|
2619
2602
|
|
2620
2603
|
// invalidate
|
2621
|
-
if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
|
2604
|
+
if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
|
2622
2605
|
self.input = input;
|
2623
2606
|
|
2624
2607
|
const parent = closest(input, colorPickerParentSelector);
|
@@ -2665,15 +2648,14 @@
|
|
2665
2648
|
});
|
2666
2649
|
|
2667
2650
|
// update and expose component labels
|
2668
|
-
const
|
2669
|
-
|
2670
|
-
? JSON.parse(componentLabels) : componentLabels || {};
|
2651
|
+
const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
|
2652
|
+
? JSON.parse(componentLabels) : componentLabels;
|
2671
2653
|
|
2672
2654
|
/** @type {Record<string, string>} */
|
2673
|
-
self.componentLabels = ObjectAssign(
|
2655
|
+
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2674
2656
|
|
2675
2657
|
/** @type {Color} */
|
2676
|
-
self.color = new Color('
|
2658
|
+
self.color = new Color(input.value || '#fff', format);
|
2677
2659
|
|
2678
2660
|
/** @type {CP.ColorFormats} */
|
2679
2661
|
self.format = format;
|
@@ -2682,7 +2664,7 @@
|
|
2682
2664
|
if (colorKeywords instanceof Array) {
|
2683
2665
|
self.colorKeywords = colorKeywords;
|
2684
2666
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2685
|
-
self.colorKeywords = colorKeywords.split(',');
|
2667
|
+
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2686
2668
|
}
|
2687
2669
|
|
2688
2670
|
// set colour presets
|
@@ -2711,7 +2693,6 @@
|
|
2711
2693
|
self.handleFocusOut = self.handleFocusOut.bind(self);
|
2712
2694
|
self.changeHandler = self.changeHandler.bind(self);
|
2713
2695
|
self.handleDismiss = self.handleDismiss.bind(self);
|
2714
|
-
self.keyToggle = self.keyToggle.bind(self);
|
2715
2696
|
self.handleKnobs = self.handleKnobs.bind(self);
|
2716
2697
|
|
2717
2698
|
// generate markup
|
@@ -2803,76 +2784,83 @@
|
|
2803
2784
|
return inputValue !== '' && new Color(inputValue).isValid;
|
2804
2785
|
}
|
2805
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
|
+
|
2806
2835
|
/** Updates `ColorPicker` visuals. */
|
2807
2836
|
updateVisuals() {
|
2808
2837
|
const self = this;
|
2809
2838
|
const {
|
2810
|
-
|
2839
|
+
controlPositions, visuals,
|
2811
2840
|
} = self;
|
2812
2841
|
const [v1, v2, v3] = visuals;
|
2813
|
-
const {
|
2814
|
-
const hue =
|
2815
|
-
|
2816
|
-
: controlPositions.c2y / offsetHeight;
|
2817
|
-
// @ts-ignore - `hslToRgb` is assigned to `Color` as static method
|
2818
|
-
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();
|
2819
2845
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2820
2846
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2821
2847
|
const roundA = roundPart((alpha * 100)) / 100;
|
2822
2848
|
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
setElementStyle(v2, { background: hueGradient });
|
2838
|
-
} else {
|
2839
|
-
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2840
|
-
const fill0 = new Color({
|
2841
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2842
|
-
}).saturate(-saturation).toRgbString();
|
2843
|
-
const fill1 = new Color({
|
2844
|
-
r: 255, g: 255, b: 0, a: alpha,
|
2845
|
-
}).saturate(-saturation).toRgbString();
|
2846
|
-
const fill2 = new Color({
|
2847
|
-
r: 0, g: 255, b: 0, a: alpha,
|
2848
|
-
}).saturate(-saturation).toRgbString();
|
2849
|
-
const fill3 = new Color({
|
2850
|
-
r: 0, g: 255, b: 255, a: alpha,
|
2851
|
-
}).saturate(-saturation).toRgbString();
|
2852
|
-
const fill4 = new Color({
|
2853
|
-
r: 0, g: 0, b: 255, a: alpha,
|
2854
|
-
}).saturate(-saturation).toRgbString();
|
2855
|
-
const fill5 = new Color({
|
2856
|
-
r: 255, g: 0, b: 255, a: alpha,
|
2857
|
-
}).saturate(-saturation).toRgbString();
|
2858
|
-
const fill6 = new Color({
|
2859
|
-
r: 255, g: 0, b: 0, a: alpha,
|
2860
|
-
}).saturate(-saturation).toRgbString();
|
2861
|
-
const fillGradient = `linear-gradient(to right,
|
2862
|
-
${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
|
2863
|
-
${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
|
2864
|
-
const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
|
2865
|
-
linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
|
2866
|
-
|
2867
|
-
setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
|
2868
|
-
const {
|
2869
|
-
r: gr, g: gg, b: gb,
|
2870
|
-
} = 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 });
|
2871
2863
|
|
2872
|
-
setElementStyle(v2, {
|
2873
|
-
background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
|
2874
|
-
});
|
2875
|
-
}
|
2876
2864
|
setElementStyle(v3, {
|
2877
2865
|
background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
|
2878
2866
|
});
|
@@ -3022,13 +3010,13 @@
|
|
3022
3010
|
const [v1, v2, v3] = visuals;
|
3023
3011
|
const [c1, c2, c3] = controlKnobs;
|
3024
3012
|
/** @type {HTMLElement} */
|
3025
|
-
const visual =
|
3026
|
-
? target : querySelector('.visual-control', target.parentElement);
|
3013
|
+
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3027
3014
|
const visualRect = getBoundingClientRect(visual);
|
3015
|
+
const html = getDocumentElement(v1);
|
3028
3016
|
const X = type === 'touchstart' ? touches[0].pageX : pageX;
|
3029
3017
|
const Y = type === 'touchstart' ? touches[0].pageY : pageY;
|
3030
|
-
const offsetX = X -
|
3031
|
-
const offsetY = Y -
|
3018
|
+
const offsetX = X - html.scrollLeft - visualRect.left;
|
3019
|
+
const offsetY = Y - html.scrollTop - visualRect.top;
|
3032
3020
|
|
3033
3021
|
if (target === v1 || target === c1) {
|
3034
3022
|
self.dragElement = visual;
|
@@ -3088,10 +3076,11 @@
|
|
3088
3076
|
if (!dragElement) return;
|
3089
3077
|
|
3090
3078
|
const controlRect = getBoundingClientRect(dragElement);
|
3091
|
-
const
|
3092
|
-
const
|
3093
|
-
const
|
3094
|
-
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;
|
3095
3084
|
|
3096
3085
|
if (dragElement === v1) {
|
3097
3086
|
self.changeControl1(offsetX, offsetY);
|
@@ -3118,19 +3107,19 @@
|
|
3118
3107
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
3119
3108
|
e.preventDefault();
|
3120
3109
|
|
3121
|
-
const {
|
3110
|
+
const { controlKnobs, visuals } = self;
|
3122
3111
|
const { offsetWidth, offsetHeight } = visuals[0];
|
3123
3112
|
const [c1, c2, c3] = controlKnobs;
|
3124
3113
|
const { activeElement } = getDocument(c1);
|
3125
3114
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3126
|
-
const yRatio = offsetHeight /
|
3115
|
+
const yRatio = offsetHeight / 360;
|
3127
3116
|
|
3128
3117
|
if (currentKnob) {
|
3129
3118
|
let offsetX = 0;
|
3130
3119
|
let offsetY = 0;
|
3131
3120
|
|
3132
3121
|
if (target === c1) {
|
3133
|
-
const xRatio = offsetWidth /
|
3122
|
+
const xRatio = offsetWidth / 100;
|
3134
3123
|
|
3135
3124
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3136
3125
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
@@ -3180,7 +3169,7 @@
|
|
3180
3169
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3181
3170
|
if (activeElement === input) {
|
3182
3171
|
if (isNonColorValue) {
|
3183
|
-
colorSource = '
|
3172
|
+
colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
|
3184
3173
|
} else {
|
3185
3174
|
colorSource = currentValue;
|
3186
3175
|
}
|
@@ -3231,9 +3220,7 @@
|
|
3231
3220
|
changeControl1(X, Y) {
|
3232
3221
|
const self = this;
|
3233
3222
|
let [offsetX, offsetY] = [0, 0];
|
3234
|
-
const {
|
3235
|
-
format, controlPositions, visuals,
|
3236
|
-
} = self;
|
3223
|
+
const { controlPositions, visuals } = self;
|
3237
3224
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3238
3225
|
|
3239
3226
|
if (X > offsetWidth) offsetX = offsetWidth;
|
@@ -3242,29 +3229,19 @@
|
|
3242
3229
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3243
3230
|
else if (Y >= 0) offsetY = Y;
|
3244
3231
|
|
3245
|
-
const hue =
|
3246
|
-
? offsetX / offsetWidth
|
3247
|
-
: controlPositions.c2y / offsetHeight;
|
3232
|
+
const hue = controlPositions.c2y / offsetHeight;
|
3248
3233
|
|
3249
|
-
const saturation =
|
3250
|
-
? 1 - controlPositions.c2y / offsetHeight
|
3251
|
-
: offsetX / offsetWidth;
|
3234
|
+
const saturation = offsetX / offsetWidth;
|
3252
3235
|
|
3253
3236
|
const lightness = 1 - offsetY / offsetHeight;
|
3254
3237
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3255
3238
|
|
3256
|
-
const colorObject = format === 'hsl'
|
3257
|
-
? {
|
3258
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3259
|
-
}
|
3260
|
-
: {
|
3261
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3262
|
-
};
|
3263
|
-
|
3264
3239
|
// new color
|
3265
3240
|
const {
|
3266
3241
|
r, g, b, a,
|
3267
|
-
} = new Color(
|
3242
|
+
} = new Color({
|
3243
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3244
|
+
});
|
3268
3245
|
|
3269
3246
|
ObjectAssign(self.color, {
|
3270
3247
|
r, g, b, a,
|
@@ -3291,7 +3268,7 @@
|
|
3291
3268
|
changeControl2(Y) {
|
3292
3269
|
const self = this;
|
3293
3270
|
const {
|
3294
|
-
|
3271
|
+
controlPositions, visuals,
|
3295
3272
|
} = self;
|
3296
3273
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3297
3274
|
|
@@ -3300,26 +3277,17 @@
|
|
3300
3277
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
3301
3278
|
else if (Y >= 0) offsetY = Y;
|
3302
3279
|
|
3303
|
-
const hue =
|
3304
|
-
|
3305
|
-
: offsetY / offsetHeight;
|
3306
|
-
const saturation = format === 'hsl'
|
3307
|
-
? 1 - offsetY / offsetHeight
|
3308
|
-
: controlPositions.c1x / offsetWidth;
|
3280
|
+
const hue = offsetY / offsetHeight;
|
3281
|
+
const saturation = controlPositions.c1x / offsetWidth;
|
3309
3282
|
const lightness = 1 - controlPositions.c1y / offsetHeight;
|
3310
3283
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
3311
|
-
const colorObject = format === 'hsl'
|
3312
|
-
? {
|
3313
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
3314
|
-
}
|
3315
|
-
: {
|
3316
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
3317
|
-
};
|
3318
3284
|
|
3319
3285
|
// new color
|
3320
3286
|
const {
|
3321
3287
|
r, g, b, a,
|
3322
|
-
} = new Color(
|
3288
|
+
} = new Color({
|
3289
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
3290
|
+
});
|
3323
3291
|
|
3324
3292
|
ObjectAssign(self.color, {
|
3325
3293
|
r, g, b, a,
|
@@ -3406,18 +3374,18 @@
|
|
3406
3374
|
setControlPositions() {
|
3407
3375
|
const self = this;
|
3408
3376
|
const {
|
3409
|
-
|
3377
|
+
visuals, color, hsv,
|
3410
3378
|
} = self;
|
3411
3379
|
const { offsetHeight, offsetWidth } = visuals[0];
|
3412
3380
|
const alpha = color.a;
|
3413
|
-
const hue =
|
3381
|
+
const hue = hsv.h;
|
3414
3382
|
|
3415
|
-
const saturation =
|
3416
|
-
const lightness =
|
3383
|
+
const saturation = hsv.s;
|
3384
|
+
const lightness = hsv.v;
|
3417
3385
|
|
3418
|
-
self.controlPositions.c1x =
|
3386
|
+
self.controlPositions.c1x = saturation * offsetWidth;
|
3419
3387
|
self.controlPositions.c1y = (1 - lightness) * offsetHeight;
|
3420
|
-
self.controlPositions.c2y =
|
3388
|
+
self.controlPositions.c2y = hue * offsetHeight;
|
3421
3389
|
self.controlPositions.c3y = (1 - alpha) * offsetHeight;
|
3422
3390
|
}
|
3423
3391
|
|
@@ -3425,78 +3393,40 @@
|
|
3425
3393
|
updateAppearance() {
|
3426
3394
|
const self = this;
|
3427
3395
|
const {
|
3428
|
-
componentLabels,
|
3429
|
-
|
3396
|
+
componentLabels, color, parent,
|
3397
|
+
hsv, hex, format, controlKnobs,
|
3430
3398
|
} = self;
|
3431
3399
|
const {
|
3432
3400
|
appearanceLabel, hexLabel, valueLabel,
|
3433
3401
|
} = componentLabels;
|
3434
|
-
|
3402
|
+
let { r, g, b } = color.toRgb();
|
3435
3403
|
const [knob1, knob2, knob3] = controlKnobs;
|
3436
|
-
const hue = roundPart(
|
3404
|
+
const hue = roundPart(hsv.h * 360);
|
3437
3405
|
const alpha = color.a;
|
3438
|
-
const
|
3439
|
-
const
|
3440
|
-
const
|
3441
|
-
const hsvl = hsv.v * 100;
|
3442
|
-
let colorName;
|
3443
|
-
|
3444
|
-
// determine color appearance
|
3445
|
-
if (lightness === 100 && saturation === 0) {
|
3446
|
-
colorName = colorLabels.white;
|
3447
|
-
} else if (lightness === 0) {
|
3448
|
-
colorName = colorLabels.black;
|
3449
|
-
} else if (saturation === 0) {
|
3450
|
-
colorName = colorLabels.grey;
|
3451
|
-
} else if (hue < 15 || hue >= 345) {
|
3452
|
-
colorName = colorLabels.red;
|
3453
|
-
} else if (hue >= 15 && hue < 45) {
|
3454
|
-
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
3455
|
-
} else if (hue >= 45 && hue < 75) {
|
3456
|
-
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
3457
|
-
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
3458
|
-
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
3459
|
-
colorName = isOlive ? colorLabels.olive : colorName;
|
3460
|
-
} else if (hue >= 75 && hue < 155) {
|
3461
|
-
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
3462
|
-
} else if (hue >= 155 && hue < 175) {
|
3463
|
-
colorName = colorLabels.teal;
|
3464
|
-
} else if (hue >= 175 && hue < 195) {
|
3465
|
-
colorName = colorLabels.cyan;
|
3466
|
-
} else if (hue >= 195 && hue < 255) {
|
3467
|
-
colorName = colorLabels.blue;
|
3468
|
-
} else if (hue >= 255 && hue < 270) {
|
3469
|
-
colorName = colorLabels.violet;
|
3470
|
-
} else if (hue >= 270 && hue < 295) {
|
3471
|
-
colorName = colorLabels.magenta;
|
3472
|
-
} else if (hue >= 295 && hue < 345) {
|
3473
|
-
colorName = colorLabels.pink;
|
3474
|
-
}
|
3406
|
+
const saturation = roundPart(hsv.s * 100);
|
3407
|
+
const lightness = roundPart(hsv.v * 100);
|
3408
|
+
const colorName = self.appearance;
|
3475
3409
|
|
3476
3410
|
let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
|
3477
3411
|
|
3478
|
-
if (format === '
|
3479
|
-
colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
|
3480
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3481
|
-
setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
|
3482
|
-
setAttribute(knob1, ariaValueNow, `${hue}`);
|
3483
|
-
setAttribute(knob2, ariaValueText, `${saturation}%`);
|
3484
|
-
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3485
|
-
} else if (format === 'hwb') {
|
3412
|
+
if (format === 'hwb') {
|
3486
3413
|
const { hwb } = self;
|
3487
3414
|
const whiteness = roundPart(hwb.w * 100);
|
3488
3415
|
const blackness = roundPart(hwb.b * 100);
|
3489
3416
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3490
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3491
3417
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
3492
3418
|
setAttribute(knob1, ariaValueNow, `${whiteness}`);
|
3419
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3493
3420
|
setAttribute(knob2, ariaValueText, `${hue}%`);
|
3494
3421
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3495
3422
|
} else {
|
3423
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
3424
|
+
colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
|
3496
3425
|
colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
|
3497
|
-
|
3426
|
+
|
3498
3427
|
setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
|
3499
3428
|
setAttribute(knob1, ariaValueNow, `${lightness}`);
|
3429
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3500
3430
|
setAttribute(knob2, ariaValueText, `${hue}°`);
|
3501
3431
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3502
3432
|
}
|
@@ -3591,37 +3521,13 @@
|
|
3591
3521
|
}
|
3592
3522
|
}
|
3593
3523
|
|
3594
|
-
/**
|
3595
|
-
* The `Space` & `Enter` keys specific event listener.
|
3596
|
-
* Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
|
3597
|
-
* @param {KeyboardEvent} e
|
3598
|
-
* @this {ColorPicker}
|
3599
|
-
*/
|
3600
|
-
keyToggle(e) {
|
3601
|
-
const self = this;
|
3602
|
-
const { menuToggle } = self;
|
3603
|
-
const { activeElement } = getDocument(menuToggle);
|
3604
|
-
const { code } = e;
|
3605
|
-
|
3606
|
-
if ([keyEnter, keySpace].includes(code)) {
|
3607
|
-
if ((menuToggle && activeElement === menuToggle) || !activeElement) {
|
3608
|
-
e.preventDefault();
|
3609
|
-
if (!activeElement) {
|
3610
|
-
self.togglePicker(e);
|
3611
|
-
} else {
|
3612
|
-
self.toggleMenu();
|
3613
|
-
}
|
3614
|
-
}
|
3615
|
-
}
|
3616
|
-
}
|
3617
|
-
|
3618
3524
|
/**
|
3619
3525
|
* Toggle the `ColorPicker` dropdown visibility.
|
3620
|
-
* @param {Event} e
|
3526
|
+
* @param {Event=} e
|
3621
3527
|
* @this {ColorPicker}
|
3622
3528
|
*/
|
3623
3529
|
togglePicker(e) {
|
3624
|
-
e.preventDefault();
|
3530
|
+
if (e) e.preventDefault();
|
3625
3531
|
const self = this;
|
3626
3532
|
const { colorPicker } = self;
|
3627
3533
|
|
@@ -3642,8 +3548,13 @@
|
|
3642
3548
|
}
|
3643
3549
|
}
|
3644
3550
|
|
3645
|
-
/**
|
3646
|
-
|
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();
|
3647
3558
|
const self = this;
|
3648
3559
|
const { colorMenu } = self;
|
3649
3560
|
|
@@ -3669,6 +3580,10 @@
|
|
3669
3580
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3670
3581
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3671
3582
|
|
3583
|
+
// if (!self.isValid) {
|
3584
|
+
self.value = self.color.toString(true);
|
3585
|
+
// }
|
3586
|
+
|
3672
3587
|
if (openDropdown) {
|
3673
3588
|
removeClass(openDropdown, 'show');
|
3674
3589
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
@@ -3682,9 +3597,6 @@
|
|
3682
3597
|
}, animationDuration);
|
3683
3598
|
}
|
3684
3599
|
|
3685
|
-
if (!self.isValid) {
|
3686
|
-
self.value = self.color.toString();
|
3687
|
-
}
|
3688
3600
|
if (!focusPrevented) {
|
3689
3601
|
focus(pickerToggle);
|
3690
3602
|
}
|
@@ -3733,90 +3645,82 @@
|
|
3733
3645
|
* `ColorPickerElement` Web Component.
|
3734
3646
|
* @example
|
3735
3647
|
* <label for="UNIQUE_ID">Label</label>
|
3736
|
-
* <color-picker
|
3737
|
-
* <input id="UNIQUE_ID"
|
3648
|
+
* <color-picker>
|
3649
|
+
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3738
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>
|
3739
3654
|
*/
|
3740
3655
|
class ColorPickerElement extends HTMLElement {
|
3741
3656
|
constructor() {
|
3742
3657
|
super();
|
3743
|
-
/** @type {boolean} */
|
3744
|
-
this.isDisconnected = true;
|
3745
3658
|
this.attachShadow({ mode: 'open' });
|
3746
3659
|
}
|
3747
3660
|
|
3748
3661
|
/**
|
3749
3662
|
* Returns the current color value.
|
3750
|
-
* @returns {string
|
3663
|
+
* @returns {string | undefined}
|
3751
3664
|
*/
|
3752
|
-
get value() { return this.input
|
3665
|
+
get value() { return this.input && this.input.value; }
|
3753
3666
|
|
3754
3667
|
connectedCallback() {
|
3755
|
-
if (this.
|
3756
|
-
if (this.isDisconnected) {
|
3757
|
-
this.isDisconnected = false;
|
3758
|
-
}
|
3759
|
-
return;
|
3760
|
-
}
|
3668
|
+
if (this.input) return;
|
3761
3669
|
|
3762
|
-
|
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
|
+
}
|
3763
3679
|
|
3764
|
-
if (!
|
3765
|
-
|
3766
|
-
const value = getAttribute(this, 'data-value') || '#069';
|
3767
|
-
const format = getAttribute(this, 'data-format') || 'rgb';
|
3768
|
-
const newInput = createElement({
|
3680
|
+
if (!input) {
|
3681
|
+
input = createElement({
|
3769
3682
|
tagName: 'input',
|
3770
3683
|
type: 'text',
|
3771
3684
|
className: 'color-preview btn-appearance',
|
3772
3685
|
});
|
3773
|
-
let id = getAttribute(this, 'data-id');
|
3774
|
-
if (!id) {
|
3775
|
-
id = `color-picker-${format}-${CPID}`;
|
3776
|
-
CPID += 1;
|
3777
|
-
}
|
3778
3686
|
|
3779
|
-
|
3780
|
-
|
3781
|
-
setAttribute(
|
3782
|
-
setAttribute(
|
3783
|
-
setAttribute(
|
3784
|
-
|
3785
|
-
setAttribute(newInput, 'spellcheck', 'false');
|
3786
|
-
setAttribute(newInput, 'value', value);
|
3787
|
-
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);
|
3788
3693
|
}
|
3694
|
+
/** @type {HTMLInputElement} */
|
3695
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3696
|
+
this.input = input;
|
3789
3697
|
|
3790
|
-
|
3791
|
-
|
3792
|
-
if (input) {
|
3793
|
-
/** @type {HTMLInputElement} */
|
3794
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3795
|
-
this.input = input;
|
3796
|
-
|
3797
|
-
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3798
|
-
this.colorPicker = new ColorPicker(input);
|
3799
|
-
this.color = this.colorPicker.color;
|
3800
|
-
|
3801
|
-
if (this.shadowRoot) {
|
3802
|
-
this.shadowRoot.append(createElement('slot'));
|
3803
|
-
}
|
3698
|
+
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3699
|
+
this.colorPicker = new ColorPicker(input);
|
3804
3700
|
|
3805
|
-
|
3806
|
-
|
3701
|
+
// @ts-ignore - `shadowRoot` is defined in the constructor
|
3702
|
+
this.shadowRoot.append(createElement('slot'));
|
3807
3703
|
}
|
3808
3704
|
|
3705
|
+
/** @this {ColorPickerElement} */
|
3809
3706
|
disconnectedCallback() {
|
3810
|
-
|
3811
|
-
|
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
|
+
});
|
3812
3716
|
}
|
3813
3717
|
}
|
3814
3718
|
|
3815
3719
|
ObjectAssign(ColorPickerElement, {
|
3816
3720
|
Color,
|
3817
3721
|
ColorPicker,
|
3818
|
-
ColorPalette,
|
3819
|
-
getInstance:
|
3722
|
+
ColorPalette, // @ts-ignore
|
3723
|
+
getInstance: ColorPicker.getInstance,
|
3820
3724
|
Version,
|
3821
3725
|
});
|
3822
3726
|
|