@thednp/color-picker 0.0.2-alpha1 → 0.0.2-alpha2

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,7 +27,6 @@ import keyupEvent from 'shorter-js/src/strings/keyupEvent';
27
27
  import resizeEvent from 'shorter-js/src/strings/resizeEvent';
28
28
  import focusoutEvent from 'shorter-js/src/strings/focusoutEvent';
29
29
 
30
- // import isMobile from 'shorter-js/src/boolean/isMobile';
31
30
  import getDocument from 'shorter-js/src/get/getDocument';
32
31
  import getDocumentElement from 'shorter-js/src/get/getDocumentElement';
33
32
  import getWindow from 'shorter-js/src/get/getWindow';
@@ -82,7 +81,7 @@ const colorPickerDefaults = {
82
81
  // ==========================
83
82
 
84
83
  /** @type {CP.GetInstance<ColorPicker>} */
85
- export const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
84
+ const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
86
85
 
87
86
  /** @type {CP.InitCallback<ColorPicker>} */
88
87
  const initColorPicker = (element) => new ColorPicker(element);
@@ -102,8 +101,6 @@ function toggleEvents(self, action) {
102
101
  fn(input, focusinEvent, self.showPicker);
103
102
  fn(pickerToggle, mouseclickEvent, self.togglePicker);
104
103
 
105
- fn(input, keydownEvent, self.keyToggle);
106
-
107
104
  if (menuToggle) {
108
105
  fn(menuToggle, mouseclickEvent, self.toggleMenu);
109
106
  }
@@ -141,8 +138,7 @@ function toggleEventsOnShown(self, action) {
141
138
  fn(doc, pointerEvents.move, self.pointerMove);
142
139
  fn(doc, pointerEvents.up, self.pointerUp);
143
140
  fn(parent, focusoutEvent, self.handleFocusOut);
144
- // @ts-ignore -- this is `Window`
145
- fn(win, keyupEvent, self.handleDismiss);
141
+ fn(doc, keyupEvent, self.handleDismiss);
146
142
  }
147
143
 
148
144
  /**
@@ -226,7 +222,7 @@ export default class ColorPicker {
226
222
  const input = querySelector(target);
227
223
 
228
224
  // invalidate
229
- if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
225
+ if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
230
226
  self.input = input;
231
227
 
232
228
  const parent = closest(input, colorPickerParentSelector);
@@ -273,15 +269,14 @@ export default class ColorPicker {
273
269
  });
274
270
 
275
271
  // update and expose component labels
276
- const tempLabels = ObjectAssign({}, colorPickerLabels);
277
- const jsonLabels = componentLabels && isValidJSON(componentLabels)
278
- ? JSON.parse(componentLabels) : componentLabels || {};
272
+ const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
273
+ ? JSON.parse(componentLabels) : componentLabels;
279
274
 
280
275
  /** @type {Record<string, string>} */
281
- self.componentLabels = ObjectAssign(tempLabels, jsonLabels);
276
+ self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
282
277
 
283
278
  /** @type {Color} */
284
- self.color = new Color('white', format);
279
+ self.color = new Color(input.value || '#fff', format);
285
280
 
286
281
  /** @type {CP.ColorFormats} */
287
282
  self.format = format;
@@ -290,7 +285,7 @@ export default class ColorPicker {
290
285
  if (colorKeywords instanceof Array) {
291
286
  self.colorKeywords = colorKeywords;
292
287
  } else if (typeof colorKeywords === 'string' && colorKeywords.length) {
293
- self.colorKeywords = colorKeywords.split(',');
288
+ self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
294
289
  }
295
290
 
296
291
  // set colour presets
@@ -319,7 +314,6 @@ export default class ColorPicker {
319
314
  self.handleFocusOut = self.handleFocusOut.bind(self);
320
315
  self.changeHandler = self.changeHandler.bind(self);
321
316
  self.handleDismiss = self.handleDismiss.bind(self);
322
- self.keyToggle = self.keyToggle.bind(self);
323
317
  self.handleKnobs = self.handleKnobs.bind(self);
324
318
 
325
319
  // generate markup
@@ -411,76 +405,83 @@ export default class ColorPicker {
411
405
  return inputValue !== '' && new Color(inputValue).isValid;
412
406
  }
413
407
 
408
+ /** Returns the colour appearance, usually the closest colour name for the current value. */
409
+ get appearance() {
410
+ const {
411
+ colorLabels, hsl, hsv, format,
412
+ } = this;
413
+
414
+ const hue = roundPart(hsl.h * 360);
415
+ const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
416
+ const saturation = roundPart(saturationSource * 100);
417
+ const lightness = roundPart(hsl.l * 100);
418
+ const hsvl = hsv.v * 100;
419
+
420
+ let colorName;
421
+
422
+ // determine color appearance
423
+ if (lightness === 100 && saturation === 0) {
424
+ colorName = colorLabels.white;
425
+ } else if (lightness === 0) {
426
+ colorName = colorLabels.black;
427
+ } else if (saturation === 0) {
428
+ colorName = colorLabels.grey;
429
+ } else if (hue < 15 || hue >= 345) {
430
+ colorName = colorLabels.red;
431
+ } else if (hue >= 15 && hue < 45) {
432
+ colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
433
+ } else if (hue >= 45 && hue < 75) {
434
+ const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
435
+ const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
436
+ colorName = isGold ? colorLabels.gold : colorLabels.yellow;
437
+ colorName = isOlive ? colorLabels.olive : colorName;
438
+ } else if (hue >= 75 && hue < 155) {
439
+ colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
440
+ } else if (hue >= 155 && hue < 175) {
441
+ colorName = colorLabels.teal;
442
+ } else if (hue >= 175 && hue < 195) {
443
+ colorName = colorLabels.cyan;
444
+ } else if (hue >= 195 && hue < 255) {
445
+ colorName = colorLabels.blue;
446
+ } else if (hue >= 255 && hue < 270) {
447
+ colorName = colorLabels.violet;
448
+ } else if (hue >= 270 && hue < 295) {
449
+ colorName = colorLabels.magenta;
450
+ } else if (hue >= 295 && hue < 345) {
451
+ colorName = colorLabels.pink;
452
+ }
453
+ return colorName;
454
+ }
455
+
414
456
  /** Updates `ColorPicker` visuals. */
415
457
  updateVisuals() {
416
458
  const self = this;
417
459
  const {
418
- format, controlPositions, visuals,
460
+ controlPositions, visuals,
419
461
  } = self;
420
462
  const [v1, v2, v3] = visuals;
421
- const { offsetWidth, offsetHeight } = v1;
422
- const hue = format === 'hsl'
423
- ? controlPositions.c1x / offsetWidth
424
- : controlPositions.c2y / offsetHeight;
425
- // @ts-ignore - `hslToRgb` is assigned to `Color` as static method
426
- const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
463
+ const { offsetHeight } = v1;
464
+ const hue = controlPositions.c2y / offsetHeight;
465
+ const { r, g, b } = new Color({ h: hue, s: 1, l: 0.5 }).toRgb();
427
466
  const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
428
467
  const alpha = 1 - controlPositions.c3y / offsetHeight;
429
468
  const roundA = roundPart((alpha * 100)) / 100;
430
469
 
431
- if (format !== 'hsl') {
432
- const fill = new Color({
433
- h: hue, s: 1, l: 0.5, a: alpha,
434
- }).toRgbString();
435
- const hueGradient = `linear-gradient(
436
- rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
437
- rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
438
- rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
439
- rgb(255,0,0) 100%)`;
440
- setElementStyle(v1, {
441
- background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
442
- linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
443
- ${whiteGrad}`,
444
- });
445
- setElementStyle(v2, { background: hueGradient });
446
- } else {
447
- const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
448
- const fill0 = new Color({
449
- r: 255, g: 0, b: 0, a: alpha,
450
- }).saturate(-saturation).toRgbString();
451
- const fill1 = new Color({
452
- r: 255, g: 255, b: 0, a: alpha,
453
- }).saturate(-saturation).toRgbString();
454
- const fill2 = new Color({
455
- r: 0, g: 255, b: 0, a: alpha,
456
- }).saturate(-saturation).toRgbString();
457
- const fill3 = new Color({
458
- r: 0, g: 255, b: 255, a: alpha,
459
- }).saturate(-saturation).toRgbString();
460
- const fill4 = new Color({
461
- r: 0, g: 0, b: 255, a: alpha,
462
- }).saturate(-saturation).toRgbString();
463
- const fill5 = new Color({
464
- r: 255, g: 0, b: 255, a: alpha,
465
- }).saturate(-saturation).toRgbString();
466
- const fill6 = new Color({
467
- r: 255, g: 0, b: 0, a: alpha,
468
- }).saturate(-saturation).toRgbString();
469
- const fillGradient = `linear-gradient(to right,
470
- ${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
471
- ${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
472
- const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
473
- linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
474
-
475
- setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
476
- const {
477
- r: gr, g: gg, b: gb,
478
- } = new Color({ r, g, b }).greyscale().toRgb();
470
+ const fill = new Color({
471
+ h: hue, s: 1, l: 0.5, a: alpha,
472
+ }).toRgbString();
473
+ const hueGradient = `linear-gradient(
474
+ rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
475
+ rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
476
+ rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
477
+ rgb(255,0,0) 100%)`;
478
+ setElementStyle(v1, {
479
+ background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
480
+ linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
481
+ ${whiteGrad}`,
482
+ });
483
+ setElementStyle(v2, { background: hueGradient });
479
484
 
480
- setElementStyle(v2, {
481
- background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
482
- });
483
- }
484
485
  setElementStyle(v3, {
485
486
  background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
486
487
  });
@@ -630,13 +631,13 @@ export default class ColorPicker {
630
631
  const [v1, v2, v3] = visuals;
631
632
  const [c1, c2, c3] = controlKnobs;
632
633
  /** @type {HTMLElement} */
633
- const visual = hasClass(target, 'visual-control')
634
- ? target : querySelector('.visual-control', target.parentElement);
634
+ const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
635
635
  const visualRect = getBoundingClientRect(visual);
636
+ const html = getDocumentElement(v1);
636
637
  const X = type === 'touchstart' ? touches[0].pageX : pageX;
637
638
  const Y = type === 'touchstart' ? touches[0].pageY : pageY;
638
- const offsetX = X - window.pageXOffset - visualRect.left;
639
- const offsetY = Y - window.pageYOffset - visualRect.top;
639
+ const offsetX = X - html.scrollLeft - visualRect.left;
640
+ const offsetY = Y - html.scrollTop - visualRect.top;
640
641
 
641
642
  if (target === v1 || target === c1) {
642
643
  self.dragElement = visual;
@@ -696,10 +697,11 @@ export default class ColorPicker {
696
697
  if (!dragElement) return;
697
698
 
698
699
  const controlRect = getBoundingClientRect(dragElement);
699
- const X = type === 'touchmove' ? touches[0].pageX : pageX;
700
- const Y = type === 'touchmove' ? touches[0].pageY : pageY;
701
- const offsetX = X - window.pageXOffset - controlRect.left;
702
- const offsetY = Y - window.pageYOffset - controlRect.top;
700
+ const win = getDocumentElement(v1);
701
+ const X = type === touchmoveEvent ? touches[0].pageX : pageX;
702
+ const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
703
+ const offsetX = X - win.scrollLeft - controlRect.left;
704
+ const offsetY = Y - win.scrollTop - controlRect.top;
703
705
 
704
706
  if (dragElement === v1) {
705
707
  self.changeControl1(offsetX, offsetY);
@@ -726,19 +728,19 @@ export default class ColorPicker {
726
728
  if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
727
729
  e.preventDefault();
728
730
 
729
- const { format, controlKnobs, visuals } = self;
731
+ const { controlKnobs, visuals } = self;
730
732
  const { offsetWidth, offsetHeight } = visuals[0];
731
733
  const [c1, c2, c3] = controlKnobs;
732
734
  const { activeElement } = getDocument(c1);
733
735
  const currentKnob = controlKnobs.find((x) => x === activeElement);
734
- const yRatio = offsetHeight / (format === 'hsl' ? 100 : 360);
736
+ const yRatio = offsetHeight / 360;
735
737
 
736
738
  if (currentKnob) {
737
739
  let offsetX = 0;
738
740
  let offsetY = 0;
739
741
 
740
742
  if (target === c1) {
741
- const xRatio = offsetWidth / (format === 'hsl' ? 360 : 100);
743
+ const xRatio = offsetWidth / 100;
742
744
 
743
745
  if ([keyArrowLeft, keyArrowRight].includes(code)) {
744
746
  self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
@@ -788,7 +790,7 @@ export default class ColorPicker {
788
790
  if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
789
791
  if (activeElement === input) {
790
792
  if (isNonColorValue) {
791
- colorSource = 'white';
793
+ colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
792
794
  } else {
793
795
  colorSource = currentValue;
794
796
  }
@@ -839,9 +841,7 @@ export default class ColorPicker {
839
841
  changeControl1(X, Y) {
840
842
  const self = this;
841
843
  let [offsetX, offsetY] = [0, 0];
842
- const {
843
- format, controlPositions, visuals,
844
- } = self;
844
+ const { controlPositions, visuals } = self;
845
845
  const { offsetHeight, offsetWidth } = visuals[0];
846
846
 
847
847
  if (X > offsetWidth) offsetX = offsetWidth;
@@ -850,29 +850,19 @@ export default class ColorPicker {
850
850
  if (Y > offsetHeight) offsetY = offsetHeight;
851
851
  else if (Y >= 0) offsetY = Y;
852
852
 
853
- const hue = format === 'hsl'
854
- ? offsetX / offsetWidth
855
- : controlPositions.c2y / offsetHeight;
853
+ const hue = controlPositions.c2y / offsetHeight;
856
854
 
857
- const saturation = format === 'hsl'
858
- ? 1 - controlPositions.c2y / offsetHeight
859
- : offsetX / offsetWidth;
855
+ const saturation = offsetX / offsetWidth;
860
856
 
861
857
  const lightness = 1 - offsetY / offsetHeight;
862
858
  const alpha = 1 - controlPositions.c3y / offsetHeight;
863
859
 
864
- const colorObject = format === 'hsl'
865
- ? {
866
- h: hue, s: saturation, l: lightness, a: alpha,
867
- }
868
- : {
869
- h: hue, s: saturation, v: lightness, a: alpha,
870
- };
871
-
872
860
  // new color
873
861
  const {
874
862
  r, g, b, a,
875
- } = new Color(colorObject);
863
+ } = new Color({
864
+ h: hue, s: saturation, v: lightness, a: alpha,
865
+ });
876
866
 
877
867
  ObjectAssign(self.color, {
878
868
  r, g, b, a,
@@ -899,7 +889,7 @@ export default class ColorPicker {
899
889
  changeControl2(Y) {
900
890
  const self = this;
901
891
  const {
902
- format, controlPositions, visuals,
892
+ controlPositions, visuals,
903
893
  } = self;
904
894
  const { offsetHeight, offsetWidth } = visuals[0];
905
895
 
@@ -908,26 +898,17 @@ export default class ColorPicker {
908
898
  if (Y > offsetHeight) offsetY = offsetHeight;
909
899
  else if (Y >= 0) offsetY = Y;
910
900
 
911
- const hue = format === 'hsl'
912
- ? controlPositions.c1x / offsetWidth
913
- : offsetY / offsetHeight;
914
- const saturation = format === 'hsl'
915
- ? 1 - offsetY / offsetHeight
916
- : controlPositions.c1x / offsetWidth;
901
+ const hue = offsetY / offsetHeight;
902
+ const saturation = controlPositions.c1x / offsetWidth;
917
903
  const lightness = 1 - controlPositions.c1y / offsetHeight;
918
904
  const alpha = 1 - controlPositions.c3y / offsetHeight;
919
- const colorObject = format === 'hsl'
920
- ? {
921
- h: hue, s: saturation, l: lightness, a: alpha,
922
- }
923
- : {
924
- h: hue, s: saturation, v: lightness, a: alpha,
925
- };
926
905
 
927
906
  // new color
928
907
  const {
929
908
  r, g, b, a,
930
- } = new Color(colorObject);
909
+ } = new Color({
910
+ h: hue, s: saturation, v: lightness, a: alpha,
911
+ });
931
912
 
932
913
  ObjectAssign(self.color, {
933
914
  r, g, b, a,
@@ -1014,18 +995,18 @@ export default class ColorPicker {
1014
995
  setControlPositions() {
1015
996
  const self = this;
1016
997
  const {
1017
- format, visuals, color, hsl, hsv,
998
+ visuals, color, hsv,
1018
999
  } = self;
1019
1000
  const { offsetHeight, offsetWidth } = visuals[0];
1020
1001
  const alpha = color.a;
1021
- const hue = hsl.h;
1002
+ const hue = hsv.h;
1022
1003
 
1023
- const saturation = format !== 'hsl' ? hsv.s : hsl.s;
1024
- const lightness = format !== 'hsl' ? hsv.v : hsl.l;
1004
+ const saturation = hsv.s;
1005
+ const lightness = hsv.v;
1025
1006
 
1026
- self.controlPositions.c1x = format !== 'hsl' ? saturation * offsetWidth : hue * offsetWidth;
1007
+ self.controlPositions.c1x = saturation * offsetWidth;
1027
1008
  self.controlPositions.c1y = (1 - lightness) * offsetHeight;
1028
- self.controlPositions.c2y = format !== 'hsl' ? hue * offsetHeight : (1 - saturation) * offsetHeight;
1009
+ self.controlPositions.c2y = hue * offsetHeight;
1029
1010
  self.controlPositions.c3y = (1 - alpha) * offsetHeight;
1030
1011
  }
1031
1012
 
@@ -1033,78 +1014,40 @@ export default class ColorPicker {
1033
1014
  updateAppearance() {
1034
1015
  const self = this;
1035
1016
  const {
1036
- componentLabels, colorLabels, color, parent,
1037
- hsl, hsv, hex, format, controlKnobs,
1017
+ componentLabels, color, parent,
1018
+ hsv, hex, format, controlKnobs,
1038
1019
  } = self;
1039
1020
  const {
1040
1021
  appearanceLabel, hexLabel, valueLabel,
1041
1022
  } = componentLabels;
1042
- const { r, g, b } = color.toRgb();
1023
+ let { r, g, b } = color.toRgb();
1043
1024
  const [knob1, knob2, knob3] = controlKnobs;
1044
- const hue = roundPart(hsl.h * 360);
1025
+ const hue = roundPart(hsv.h * 360);
1045
1026
  const alpha = color.a;
1046
- const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
1047
- const saturation = roundPart(saturationSource * 100);
1048
- const lightness = roundPart(hsl.l * 100);
1049
- const hsvl = hsv.v * 100;
1050
- let colorName;
1051
-
1052
- // determine color appearance
1053
- if (lightness === 100 && saturation === 0) {
1054
- colorName = colorLabels.white;
1055
- } else if (lightness === 0) {
1056
- colorName = colorLabels.black;
1057
- } else if (saturation === 0) {
1058
- colorName = colorLabels.grey;
1059
- } else if (hue < 15 || hue >= 345) {
1060
- colorName = colorLabels.red;
1061
- } else if (hue >= 15 && hue < 45) {
1062
- colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
1063
- } else if (hue >= 45 && hue < 75) {
1064
- const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
1065
- const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
1066
- colorName = isGold ? colorLabels.gold : colorLabels.yellow;
1067
- colorName = isOlive ? colorLabels.olive : colorName;
1068
- } else if (hue >= 75 && hue < 155) {
1069
- colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
1070
- } else if (hue >= 155 && hue < 175) {
1071
- colorName = colorLabels.teal;
1072
- } else if (hue >= 175 && hue < 195) {
1073
- colorName = colorLabels.cyan;
1074
- } else if (hue >= 195 && hue < 255) {
1075
- colorName = colorLabels.blue;
1076
- } else if (hue >= 255 && hue < 270) {
1077
- colorName = colorLabels.violet;
1078
- } else if (hue >= 270 && hue < 295) {
1079
- colorName = colorLabels.magenta;
1080
- } else if (hue >= 295 && hue < 345) {
1081
- colorName = colorLabels.pink;
1082
- }
1027
+ const saturation = roundPart(hsv.s * 100);
1028
+ const lightness = roundPart(hsv.v * 100);
1029
+ const colorName = self.appearance;
1083
1030
 
1084
1031
  let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
1085
1032
 
1086
- if (format === 'hsl') {
1087
- colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
1088
- setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1089
- setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
1090
- setAttribute(knob1, ariaValueNow, `${hue}`);
1091
- setAttribute(knob2, ariaValueText, `${saturation}%`);
1092
- setAttribute(knob2, ariaValueNow, `${saturation}`);
1093
- } else if (format === 'hwb') {
1033
+ if (format === 'hwb') {
1094
1034
  const { hwb } = self;
1095
1035
  const whiteness = roundPart(hwb.w * 100);
1096
1036
  const blackness = roundPart(hwb.b * 100);
1097
1037
  colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
1098
- setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1099
1038
  setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
1100
1039
  setAttribute(knob1, ariaValueNow, `${whiteness}`);
1040
+ setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1101
1041
  setAttribute(knob2, ariaValueText, `${hue}%`);
1102
1042
  setAttribute(knob2, ariaValueNow, `${hue}`);
1103
1043
  } else {
1044
+ [r, g, b] = [r, g, b].map(roundPart);
1045
+ colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
1104
1046
  colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
1105
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1047
+
1106
1048
  setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
1107
1049
  setAttribute(knob1, ariaValueNow, `${lightness}`);
1050
+ setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1108
1051
  setAttribute(knob2, ariaValueText, `${hue}°`);
1109
1052
  setAttribute(knob2, ariaValueNow, `${hue}`);
1110
1053
  }
@@ -1199,37 +1142,13 @@ export default class ColorPicker {
1199
1142
  }
1200
1143
  }
1201
1144
 
1202
- /**
1203
- * The `Space` & `Enter` keys specific event listener.
1204
- * Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
1205
- * @param {KeyboardEvent} e
1206
- * @this {ColorPicker}
1207
- */
1208
- keyToggle(e) {
1209
- const self = this;
1210
- const { menuToggle } = self;
1211
- const { activeElement } = getDocument(menuToggle);
1212
- const { code } = e;
1213
-
1214
- if ([keyEnter, keySpace].includes(code)) {
1215
- if ((menuToggle && activeElement === menuToggle) || !activeElement) {
1216
- e.preventDefault();
1217
- if (!activeElement) {
1218
- self.togglePicker(e);
1219
- } else {
1220
- self.toggleMenu();
1221
- }
1222
- }
1223
- }
1224
- }
1225
-
1226
1145
  /**
1227
1146
  * Toggle the `ColorPicker` dropdown visibility.
1228
- * @param {Event} e
1147
+ * @param {Event=} e
1229
1148
  * @this {ColorPicker}
1230
1149
  */
1231
1150
  togglePicker(e) {
1232
- e.preventDefault();
1151
+ if (e) e.preventDefault();
1233
1152
  const self = this;
1234
1153
  const { colorPicker } = self;
1235
1154
 
@@ -1250,8 +1169,13 @@ export default class ColorPicker {
1250
1169
  }
1251
1170
  }
1252
1171
 
1253
- /** Toggles the visibility of the `ColorPicker` presets menu. */
1254
- toggleMenu() {
1172
+ /**
1173
+ * Toggles the visibility of the `ColorPicker` presets menu.
1174
+ * @param {Event=} e
1175
+ * @this {ColorPicker}
1176
+ */
1177
+ toggleMenu(e) {
1178
+ if (e) e.preventDefault();
1255
1179
  const self = this;
1256
1180
  const { colorMenu } = self;
1257
1181
 
@@ -1277,6 +1201,10 @@ export default class ColorPicker {
1277
1201
  const relatedBtn = openPicker ? pickerToggle : menuToggle;
1278
1202
  const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
1279
1203
 
1204
+ // if (!self.isValid) {
1205
+ self.value = self.color.toString(true);
1206
+ // }
1207
+
1280
1208
  if (openDropdown) {
1281
1209
  removeClass(openDropdown, 'show');
1282
1210
  setAttribute(relatedBtn, ariaExpanded, 'false');
@@ -1290,9 +1218,6 @@ export default class ColorPicker {
1290
1218
  }, animationDuration);
1291
1219
  }
1292
1220
 
1293
- if (!self.isValid) {
1294
- self.value = self.color.toString();
1295
- }
1296
1221
  if (!focusPrevented) {
1297
1222
  focus(pickerToggle);
1298
1223
  }