@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.
@@ -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
  }