@react-stately/color 3.0.0-beta.1 → 3.0.0-beta.5

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/dist/main.js CHANGED
@@ -5,10 +5,6 @@ var {
5
5
  useEffect
6
6
  } = require("react");
7
7
 
8
- var {
9
- useControlledState
10
- } = require("@react-stately/utils");
11
-
12
8
  var {
13
9
  useSliderState
14
10
  } = require("@react-stately/slider");
@@ -26,8 +22,10 @@ var {
26
22
  } = require("@internationalized/message");
27
23
 
28
24
  var {
29
- clamp
30
- } = require("@react-aria/utils");
25
+ clamp,
26
+ toFixedNumber,
27
+ useControlledState
28
+ } = require("@react-stately/utils");
31
29
 
32
30
  var _babelRuntimeHelpersInteropRequireDefault = $parcel$interopDefault(require("@babel/runtime/helpers/interopRequireDefault"));
33
31
 
@@ -287,6 +285,14 @@ class $b54655da051f787a04029ec3711$var$RGBColor extends $b54655da051f787a04029ec
287
285
  case 'rgba':
288
286
  return this;
289
287
 
288
+ case 'hsb':
289
+ case 'hsba':
290
+ return this.toHSB();
291
+
292
+ case 'hsl':
293
+ case 'hsla':
294
+ return this.toHSL();
295
+
290
296
  default:
291
297
  throw new Error('Unsupported color conversion: rgb -> ' + format);
292
298
  }
@@ -295,6 +301,85 @@ class $b54655da051f787a04029ec3711$var$RGBColor extends $b54655da051f787a04029ec
295
301
  toHexInt() {
296
302
  return this.red << 16 | this.green << 8 | this.blue;
297
303
  }
304
+ /**
305
+ * Converts an RGB color value to HSB.
306
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB.
307
+ * @returns An HSBColor object.
308
+ */
309
+
310
+
311
+ toHSB() {
312
+ const red = this.red / 255;
313
+ const green = this.green / 255;
314
+ const blue = this.blue / 255;
315
+ const min = Math.min(red, green, blue);
316
+ const brightness = Math.max(red, green, blue);
317
+ const chroma = brightness - min;
318
+ const saturation = brightness === 0 ? 0 : chroma / brightness;
319
+ let hue = 0; // achromatic
320
+
321
+ if (chroma !== 0) {
322
+ switch (brightness) {
323
+ case red:
324
+ hue = (green - blue) / chroma + (green < blue ? 6 : 0);
325
+ break;
326
+
327
+ case green:
328
+ hue = (blue - red) / chroma + 2;
329
+ break;
330
+
331
+ case blue:
332
+ hue = (red - green) / chroma + 4;
333
+ break;
334
+ }
335
+
336
+ hue /= 6;
337
+ }
338
+
339
+ return new $b54655da051f787a04029ec3711$var$HSBColor(toFixedNumber(hue * 360, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(brightness * 100, 2), this.alpha);
340
+ }
341
+ /**
342
+ * Converts an RGB color value to HSL.
343
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB.
344
+ * @returns An HSLColor object.
345
+ */
346
+
347
+
348
+ toHSL() {
349
+ const red = this.red / 255;
350
+ const green = this.green / 255;
351
+ const blue = this.blue / 255;
352
+ const min = Math.min(red, green, blue);
353
+ const max = Math.max(red, green, blue);
354
+ const lightness = (max + min) / 2;
355
+ const chroma = max - min;
356
+ let hue;
357
+ let saturation;
358
+
359
+ if (chroma === 0) {
360
+ hue = saturation = 0; // achromatic
361
+ } else {
362
+ saturation = chroma / (lightness < .5 ? max + min : 2 - max - min);
363
+
364
+ switch (max) {
365
+ case red:
366
+ hue = (green - blue) / chroma + (green < blue ? 6 : 0);
367
+ break;
368
+
369
+ case green:
370
+ hue = (blue - red) / chroma + 2;
371
+ break;
372
+
373
+ case blue:
374
+ hue = (red - green) / chroma + 4;
375
+ break;
376
+ }
377
+
378
+ hue /= 6;
379
+ }
380
+
381
+ return new $b54655da051f787a04029ec3711$var$HSLColor(toFixedNumber(hue * 360, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(lightness * 100, 2), this.alpha);
382
+ }
298
383
 
299
384
  clone() {
300
385
  return new $b54655da051f787a04029ec3711$var$RGBColor(this.red, this.green, this.blue, this.alpha);
@@ -349,6 +434,10 @@ class $b54655da051f787a04029ec3711$var$RGBColor extends $b54655da051f787a04029ec
349
434
  return new NumberFormatter(locale, options).format(value);
350
435
  }
351
436
 
437
+ getColorSpace() {
438
+ return 'rgb';
439
+ }
440
+
352
441
  } // X = <negative/positive number with/without decimal places>
353
442
  // before/after a comma, 0 or more whitespaces are allowed
354
443
  // - hsb(X, X%, X%)
@@ -382,11 +471,17 @@ class $b54655da051f787a04029ec3711$var$HSBColor extends $b54655da051f787a04029ec
382
471
  case 'css':
383
472
  return this.toHSL().toString('css');
384
473
 
474
+ case 'hex':
475
+ return this.toRGB().toString('hex');
476
+
477
+ case 'hexa':
478
+ return this.toRGB().toString('hexa');
479
+
385
480
  case 'hsb':
386
- return "hsb(" + this.hue + ", " + this.saturation + "%, " + this.brightness + "%)";
481
+ return "hsb(" + this.hue + ", " + toFixedNumber(this.saturation, 2) + "%, " + toFixedNumber(this.brightness, 2) + "%)";
387
482
 
388
483
  case 'hsba':
389
- return "hsba(" + this.hue + ", " + this.saturation + "%, " + this.brightness + "%, " + this.alpha + ")";
484
+ return "hsba(" + this.hue + ", " + toFixedNumber(this.saturation, 2) + "%, " + toFixedNumber(this.brightness, 2) + "%, " + this.alpha + ")";
390
485
 
391
486
  default:
392
487
  return this.toFormat(format).toString(format);
@@ -403,24 +498,49 @@ class $b54655da051f787a04029ec3711$var$HSBColor extends $b54655da051f787a04029ec
403
498
  case 'hsla':
404
499
  return this.toHSL();
405
500
 
501
+ case 'rgb':
502
+ case 'rgba':
503
+ return this.toRGB();
504
+
406
505
  default:
407
506
  throw new Error('Unsupported color conversion: hsb -> ' + format);
408
507
  }
409
508
  }
509
+ /**
510
+ * Converts a HSB color to HSL.
511
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_HSL.
512
+ * @returns An HSLColor object.
513
+ */
514
+
410
515
 
411
516
  toHSL() {
412
- // determine the lightness in the range [0,100]
413
- var l = (2 - this.saturation / 100) * this.brightness / 2; // store the HSL components
517
+ let saturation = this.saturation / 100;
518
+ let brightness = this.brightness / 100;
519
+ let lightness = brightness * (1 - saturation / 2);
520
+ saturation = lightness === 0 || lightness === 1 ? 0 : (brightness - lightness) / Math.min(lightness, 1 - lightness);
521
+ return new $b54655da051f787a04029ec3711$var$HSLColor(toFixedNumber(this.hue, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(lightness * 100, 2), this.alpha);
522
+ }
523
+ /**
524
+ * Converts a HSV color value to RGB.
525
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative.
526
+ * @returns An RGBColor object.
527
+ */
414
528
 
529
+
530
+ toRGB() {
415
531
  let hue = this.hue;
416
- let saturation = this.saturation * this.brightness / (l < 50 ? l * 2 : 200 - l * 2);
417
- let lightness = l; // correct a division-by-zero error
532
+ let saturation = this.saturation / 100;
533
+ let brightness = this.brightness / 100;
418
534
 
419
- if (isNaN(saturation)) {
420
- saturation = 0;
421
- }
535
+ let fn = function fn(n, k) {
536
+ if (k === void 0) {
537
+ k = (n + hue / 60) % 6;
538
+ }
539
+
540
+ return brightness - saturation * brightness * Math.max(Math.min(k, 4 - k, 1), 0);
541
+ };
422
542
 
423
- return new $b54655da051f787a04029ec3711$var$HSLColor(hue, saturation, lightness, this.alpha);
543
+ return new $b54655da051f787a04029ec3711$var$RGBColor(Math.round(fn(5) * 255), Math.round(fn(3) * 255), Math.round(fn(1) * 255), this.alpha);
424
544
  }
425
545
 
426
546
  clone() {
@@ -490,6 +610,10 @@ class $b54655da051f787a04029ec3711$var$HSBColor extends $b54655da051f787a04029ec
490
610
  return new NumberFormatter(locale, options).format(value);
491
611
  }
492
612
 
613
+ getColorSpace() {
614
+ return 'hsb';
615
+ }
616
+
493
617
  } // X = <negative/positive number with/without decimal places>
494
618
  // before/after a comma, 0 or more whitespaces are allowed
495
619
  // - hsl(X, X%, X%)
@@ -500,8 +624,7 @@ const $b54655da051f787a04029ec3711$var$HSL_REGEX = /hsl\(([-+]?\d+(?:.\d+)?\s*,\
500
624
 
501
625
  function $b54655da051f787a04029ec3711$var$mod(n, m) {
502
626
  return (n % m + m) % m;
503
- } // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
-
627
+ }
505
628
 
506
629
  class $b54655da051f787a04029ec3711$var$HSLColor extends $b54655da051f787a04029ec3711$var$Color {
507
630
  constructor(hue, saturation, lightness, alpha) {
@@ -510,8 +633,7 @@ class $b54655da051f787a04029ec3711$var$HSLColor extends $b54655da051f787a04029ec
510
633
  this.saturation = saturation;
511
634
  this.lightness = lightness;
512
635
  this.alpha = alpha;
513
- } // eslint-disable-next-line @typescript-eslint/no-unused-vars
514
-
636
+ }
515
637
 
516
638
  static parse(value) {
517
639
  let m;
@@ -526,12 +648,18 @@ class $b54655da051f787a04029ec3711$var$HSLColor extends $b54655da051f787a04029ec
526
648
 
527
649
  toString(format) {
528
650
  switch (format) {
651
+ case 'hex':
652
+ return this.toRGB().toString('hex');
653
+
654
+ case 'hexa':
655
+ return this.toRGB().toString('hexa');
656
+
529
657
  case 'hsl':
530
- return "hsl(" + this.hue + ", " + this.saturation + "%, " + this.lightness + "%)";
658
+ return "hsl(" + this.hue + ", " + toFixedNumber(this.saturation, 2) + "%, " + toFixedNumber(this.lightness, 2) + "%)";
531
659
 
532
660
  case 'css':
533
661
  case 'hsla':
534
- return "hsla(" + this.hue + ", " + this.saturation + "%, " + this.lightness + "%, " + this.alpha + ")";
662
+ return "hsla(" + this.hue + ", " + toFixedNumber(this.saturation, 2) + "%, " + toFixedNumber(this.lightness, 2) + "%, " + this.alpha + ")";
535
663
 
536
664
  default:
537
665
  return this.toFormat(format).toString(format);
@@ -544,10 +672,55 @@ class $b54655da051f787a04029ec3711$var$HSLColor extends $b54655da051f787a04029ec
544
672
  case 'hsla':
545
673
  return this;
546
674
 
675
+ case 'hsb':
676
+ case 'hsba':
677
+ return this.toHSB();
678
+
679
+ case 'rgb':
680
+ case 'rgba':
681
+ return this.toRGB();
682
+
547
683
  default:
548
684
  throw new Error('Unsupported color conversion: hsl -> ' + format);
549
685
  }
550
686
  }
687
+ /**
688
+ * Converts a HSL color to HSB.
689
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_HSV.
690
+ * @returns An HSBColor object.
691
+ */
692
+
693
+
694
+ toHSB() {
695
+ let saturation = this.saturation / 100;
696
+ let lightness = this.lightness / 100;
697
+ let brightness = lightness + saturation * Math.min(lightness, 1 - lightness);
698
+ saturation = brightness === 0 ? 0 : 2 * (1 - lightness / brightness);
699
+ return new $b54655da051f787a04029ec3711$var$HSBColor(toFixedNumber(this.hue, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(brightness * 100, 2), this.alpha);
700
+ }
701
+ /**
702
+ * Converts a HSL color to RGB.
703
+ * Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative.
704
+ * @returns An RGBColor object.
705
+ */
706
+
707
+
708
+ toRGB() {
709
+ let hue = this.hue;
710
+ let saturation = this.saturation / 100;
711
+ let lightness = this.lightness / 100;
712
+ let a = saturation * Math.min(lightness, 1 - lightness);
713
+
714
+ let fn = function fn(n, k) {
715
+ if (k === void 0) {
716
+ k = (n + hue / 30) % 12;
717
+ }
718
+
719
+ return lightness - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
720
+ };
721
+
722
+ return new $b54655da051f787a04029ec3711$var$RGBColor(Math.round(fn(0) * 255), Math.round(fn(8) * 255), Math.round(fn(4) * 255), this.alpha);
723
+ }
551
724
 
552
725
  clone() {
553
726
  return new $b54655da051f787a04029ec3711$var$HSLColor(this.hue, this.saturation, this.lightness, this.alpha);
@@ -616,6 +789,10 @@ class $b54655da051f787a04029ec3711$var$HSLColor extends $b54655da051f787a04029ec
616
789
  return new NumberFormatter(locale, options).format(value);
617
790
  }
618
791
 
792
+ getColorSpace() {
793
+ return 'hsl';
794
+ }
795
+
619
796
  }
620
797
 
621
798
  function $d78e953dd1c924c8b48953f9b24957b7$var$normalizeColor(v) {
@@ -778,6 +955,7 @@ function useColorWheelState(props) {
778
955
  let valueRef = useRef(value);
779
956
  valueRef.current = value;
780
957
  let [isDragging, setDragging] = useState(false);
958
+ let isDraggingRef = useRef(false).current;
781
959
  let hue = value.getChannelValue('hue');
782
960
 
783
961
  function setHue(v) {
@@ -789,7 +967,9 @@ function useColorWheelState(props) {
789
967
  v = $dba59c0b8a82682c07fa6f5c72e73481$var$roundToStep($dba59c0b8a82682c07fa6f5c72e73481$var$mod(v, 360), step);
790
968
 
791
969
  if (hue !== v) {
792
- setValue(value.withChannelValue('hue', v));
970
+ let color = value.withChannelValue('hue', v);
971
+ valueRef.current = color;
972
+ setValue(color);
793
973
  }
794
974
  }
795
975
 
@@ -845,13 +1025,14 @@ function useColorWheelState(props) {
845
1025
  },
846
1026
 
847
1027
  setDragging(isDragging) {
848
- setDragging(wasDragging => {
849
- if (onChangeEnd && !isDragging && wasDragging) {
850
- onChangeEnd(valueRef.current);
851
- }
1028
+ let wasDragging = isDraggingRef;
1029
+ isDraggingRef = isDragging;
852
1030
 
853
- return isDragging;
854
- });
1031
+ if (onChangeEnd && !isDragging && wasDragging) {
1032
+ onChangeEnd(valueRef.current);
1033
+ }
1034
+
1035
+ setDragging(isDragging);
855
1036
  },
856
1037
 
857
1038
  isDragging,
@@ -898,68 +1079,124 @@ function useColorFieldState(props) {
898
1079
  let initialValue = $b3b9a125af848b3d936c7c032125859$export$useColor(value);
899
1080
  let initialDefaultValue = $b3b9a125af848b3d936c7c032125859$export$useColor(defaultValue);
900
1081
  let [colorValue, setColorValue] = useControlledState(initialValue, initialDefaultValue, onChange);
901
- let initialInputValue = (value || defaultValue) && colorValue ? colorValue.toString('hex') : '';
902
- let [inputValue, setInputValue] = useState(initialInputValue);
903
- useEffect(() => {
904
- setInputValue(inputValue => {
905
- // Parse color from current inputValue.
906
- // Only update the input value if the parseColorValue is not equivalent.
907
- if (!inputValue.length && colorValue) {
908
- return colorValue.toString('hex');
909
- }
1082
+ let [inputValue, setInputValue] = useState(() => (value || defaultValue) && colorValue ? colorValue.toString('hex') : '');
910
1083
 
911
- try {
912
- let currentColor = parseColor(inputValue.startsWith('#') ? inputValue : "#" + inputValue);
1084
+ let safelySetColorValue = newColor => {
1085
+ if (typeof newColor === 'function') {
1086
+ setColorValue(prev => {
1087
+ let resolved = newColor(prev);
913
1088
 
914
- if (currentColor.toHexInt() !== (colorValue == null ? void 0 : colorValue.toHexInt())) {
915
- return colorValue ? colorValue.toString('hex') : '';
1089
+ if (!prev || !resolved) {
1090
+ return resolved;
916
1091
  }
917
- } catch (err) {// ignore
918
- }
919
1092
 
920
- return inputValue;
921
- });
922
- }, [inputValue, colorValue, setInputValue]);
1093
+ if (resolved.toHexInt() !== prev.toHexInt()) {
1094
+ return resolved;
1095
+ }
923
1096
 
924
- let increment = () => setColorValue(prevColor => $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(prevColor, step));
1097
+ return prev;
1098
+ });
1099
+ return;
1100
+ }
925
1101
 
926
- let decrement = () => setColorValue(prevColor => $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(prevColor, -step));
1102
+ if (!colorValue || !newColor) {
1103
+ setColorValue(newColor);
1104
+ return;
1105
+ }
927
1106
 
928
- let incrementToMax = () => setColorValue(prevColor => $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(prevColor, $f59de409cf55723659fabb2f46aaa7a$var$MAX_COLOR_INT));
1107
+ if (newColor.toHexInt() !== colorValue.toHexInt()) {
1108
+ setColorValue(newColor);
1109
+ return;
1110
+ }
1111
+ };
929
1112
 
930
- let decrementToMin = () => setColorValue(prevColor => $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(prevColor, -$f59de409cf55723659fabb2f46aaa7a$var$MAX_COLOR_INT));
1113
+ useEffect(() => {
1114
+ setInputValue(colorValue ? colorValue.toString('hex') : '');
1115
+ }, [colorValue, setInputValue]);
1116
+ let parsedValue = useMemo(() => {
1117
+ let color;
1118
+
1119
+ try {
1120
+ color = parseColor(inputValue.startsWith('#') ? inputValue : "#" + inputValue);
1121
+ } catch (err) {
1122
+ color = null;
1123
+ }
931
1124
 
932
- let setFieldInputValue = value => {
933
- var _value$match;
1125
+ return color;
1126
+ }, [parseColor, inputValue]);
1127
+ let parsed = useRef(null);
1128
+ parsed.current = parsedValue;
1129
+
1130
+ let commit = () => {
1131
+ // Set to empty state if input value is empty
1132
+ if (!inputValue.length) {
1133
+ safelySetColorValue(null);
1134
+ setInputValue(value === undefined ? '' : colorValue.toString('hex'));
1135
+ return;
1136
+ } // if it failed to parse, then reset input to formatted version of current number
1137
+
1138
+
1139
+ if (parsed.current == null) {
1140
+ setInputValue(colorValue ? colorValue.toString('hex') : '');
1141
+ return;
1142
+ }
934
1143
 
935
- value = (_value$match = value.match(/^#?[0-9a-f]{0,6}$/i)) == null ? void 0 : _value$match[0];
1144
+ safelySetColorValue(parsed.current); // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
936
1145
 
937
- if (value !== undefined) {
938
- if (!value.length && colorValue) {
939
- setColorValue(null);
940
- return;
1146
+ let newColorValue = '';
1147
+
1148
+ if (colorValue) {
1149
+ newColorValue = colorValue.toString('hex');
1150
+ }
1151
+
1152
+ setInputValue(newColorValue);
1153
+ };
1154
+
1155
+ let increment = () => {
1156
+ safelySetColorValue(prevColor => {
1157
+ let newValue = $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(parsed.current, step); // if we've arrived at the same value that was previously in the state, the
1158
+ // input value should be updated to match
1159
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
1160
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
1161
+
1162
+ if (newValue === prevColor) {
1163
+ setInputValue(newValue.toString('hex'));
941
1164
  }
942
1165
 
943
- try {
944
- let newColor = parseColor(value.startsWith('#') ? value : "#" + value);
945
- setColorValue(prevColor => {
946
- setInputValue(value);
947
- return prevColor && prevColor.toHexInt() === newColor.toHexInt() ? prevColor : newColor;
948
- });
949
- } catch (err) {
950
- setInputValue(value);
1166
+ return newValue;
1167
+ });
1168
+ };
1169
+
1170
+ let decrement = () => {
1171
+ safelySetColorValue(prevColor => {
1172
+ let newValue = $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(parsed.current, -step); // if we've arrived at the same value that was previously in the state, the
1173
+ // input value should be updated to match
1174
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
1175
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
1176
+
1177
+ if (newValue === prevColor) {
1178
+ setInputValue(newValue.toString('hex'));
951
1179
  }
952
- }
1180
+
1181
+ return newValue;
1182
+ });
953
1183
  };
954
1184
 
955
- let commit = () => {
956
- setInputValue(colorValue ? colorValue.toString('hex') : '');
1185
+ let incrementToMax = () => safelySetColorValue($f59de409cf55723659fabb2f46aaa7a$var$MAX_COLOR);
1186
+
1187
+ let decrementToMin = () => safelySetColorValue($f59de409cf55723659fabb2f46aaa7a$var$MIN_COLOR);
1188
+
1189
+ let validate = value => {
1190
+ var _value$match;
1191
+
1192
+ return value === '' || !!((_value$match = value.match(/^#?[0-9a-f]{0,6}$/i)) != null && _value$match[0]);
957
1193
  };
958
1194
 
959
1195
  return {
1196
+ validate,
960
1197
  colorValue,
961
1198
  inputValue,
962
- setInputValue: setFieldInputValue,
1199
+ setInputValue,
963
1200
  commit,
964
1201
  increment,
965
1202
  incrementToMax,
@@ -973,11 +1210,10 @@ exports.useColorFieldState = useColorFieldState;
973
1210
  function $f59de409cf55723659fabb2f46aaa7a$var$addColorValue(color, step) {
974
1211
  let newColor = color ? color : $f59de409cf55723659fabb2f46aaa7a$var$MIN_COLOR;
975
1212
  let colorInt = newColor.toHexInt();
976
- let newColorString = color ? color.toString('hex') : '';
977
1213
  let clampInt = Math.min(Math.max(colorInt + step, $f59de409cf55723659fabb2f46aaa7a$var$MIN_COLOR_INT), $f59de409cf55723659fabb2f46aaa7a$var$MAX_COLOR_INT);
978
1214
 
979
1215
  if (clampInt !== colorInt) {
980
- newColorString = "#" + clampInt.toString(16).padStart(6, '0').toUpperCase();
1216
+ let newColorString = "#" + clampInt.toString(16).padStart(6, '0').toUpperCase();
981
1217
  newColor = parseColor(newColorString);
982
1218
  }
983
1219