@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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * ColorPicker v0.0.2alpha1 (http://thednp.github.io/color-picker)
2
+ * ColorPicker v0.0.2alpha2 (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
  */
@@ -837,6 +837,8 @@ function isColorName(color) {
837
837
  if (nonColors.includes(color)
838
838
  || ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
839
839
 
840
+ if (['black', 'white'].includes(color)) return true;
841
+
840
842
  return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
841
843
  setElementStyle(documentHead, { color });
842
844
  const computedColor = getElementStyle(documentHead, 'color');
@@ -863,6 +865,11 @@ function isValidCSSUnit(color) {
863
865
  */
864
866
  function bound01(N, max) {
865
867
  let n = N;
868
+
869
+ if (typeof N === 'number'
870
+ && Math.min(N, 0) === 0 // round values to 6 decimals Math.round(N * (10 ** 6)) / 10 ** 6
871
+ && Math.max(N, 1) === 1) return N;
872
+
866
873
  if (isOnePointZero(N)) n = '100%';
867
874
 
868
875
  const processPercent = isPercentage(n);
@@ -966,15 +973,12 @@ function pad2(c) {
966
973
  /**
967
974
  * Converts an RGB colour value to HSL.
968
975
  *
969
- * @param {number} R Red component [0, 255]
970
- * @param {number} G Green component [0, 255]
971
- * @param {number} B Blue component [0, 255]
976
+ * @param {number} r Red component [0, 1]
977
+ * @param {number} g Green component [0, 1]
978
+ * @param {number} b Blue component [0, 1]
972
979
  * @returns {CP.HSL} {h,s,l} object with [0, 1] ranged values
973
980
  */
974
- function rgbToHsl(R, G, B) {
975
- const r = R / 255;
976
- const g = G / 255;
977
- const b = B / 255;
981
+ function rgbToHsl(r, g, b) {
978
982
  const max = Math.max(r, g, b);
979
983
  const min = Math.min(r, g, b);
980
984
  let h = 0;
@@ -986,17 +990,10 @@ function rgbToHsl(R, G, B) {
986
990
  } else {
987
991
  const d = max - min;
988
992
  s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
989
- switch (max) {
990
- case r:
991
- h = (g - b) / d + (g < b ? 6 : 0);
992
- break;
993
- case g:
994
- h = (b - r) / d + 2;
995
- break;
996
- case b:
997
- h = (r - g) / d + 4;
998
- break;
999
- }
993
+ if (max === r) h = (g - b) / d + (g < b ? 6 : 0);
994
+ if (max === g) h = (b - r) / d + 2;
995
+ if (max === b) h = (r - g) / d + 4;
996
+
1000
997
  h /= 6;
1001
998
  }
1002
999
  return { h, s, l };
@@ -1025,7 +1022,7 @@ function hueToRgb(p, q, t) {
1025
1022
  * @param {number} h Hue Angle [0, 1]
1026
1023
  * @param {number} s Saturation [0, 1]
1027
1024
  * @param {number} l Lightness Angle [0, 1]
1028
- * @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
1025
+ * @returns {CP.RGB} {r,g,b} object with [0, 1] ranged values
1029
1026
  */
1030
1027
  function hslToRgb(h, s, l) {
1031
1028
  let r = 0;
@@ -1044,7 +1041,6 @@ function hslToRgb(h, s, l) {
1044
1041
  g = hueToRgb(p, q, h);
1045
1042
  b = hueToRgb(p, q, h - 1 / 3);
1046
1043
  }
1047
- [r, g, b] = [r, g, b].map((x) => x * 255);
1048
1044
 
1049
1045
  return { r, g, b };
1050
1046
  }
@@ -1054,16 +1050,12 @@ function hslToRgb(h, s, l) {
1054
1050
  * @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
1055
1051
  * @link http://alvyray.com/Papers/CG/hwb2rgb.htm
1056
1052
  *
1057
- * @param {number} R Red component [0, 255]
1058
- * @param {number} G Green [0, 255]
1059
- * @param {number} B Blue [0, 255]
1053
+ * @param {number} r Red component [0, 1]
1054
+ * @param {number} g Green [0, 1]
1055
+ * @param {number} b Blue [0, 1]
1060
1056
  * @return {CP.HWB} {h,w,b} object with [0, 1] ranged values
1061
1057
  */
1062
- function rgbToHwb(R, G, B) {
1063
- const r = R / 255;
1064
- const g = G / 255;
1065
- const b = B / 255;
1066
-
1058
+ function rgbToHwb(r, g, b) {
1067
1059
  let f = 0;
1068
1060
  let i = 0;
1069
1061
  const whiteness = Math.min(r, g, b);
@@ -1093,20 +1085,18 @@ function rgbToHwb(R, G, B) {
1093
1085
  * @param {number} H Hue Angle [0, 1]
1094
1086
  * @param {number} W Whiteness [0, 1]
1095
1087
  * @param {number} B Blackness [0, 1]
1096
- * @return {CP.RGB} {r,g,b} object with [0, 255] ranged values
1088
+ * @return {CP.RGB} {r,g,b} object with [0, 1] ranged values
1097
1089
  *
1098
1090
  * @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
1099
1091
  * @link http://alvyray.com/Papers/CG/hwb2rgb.htm
1100
1092
  */
1101
1093
  function hwbToRgb(H, W, B) {
1102
1094
  if (W + B >= 1) {
1103
- const gray = (W / (W + B)) * 255;
1095
+ const gray = W / (W + B);
1104
1096
  return { r: gray, g: gray, b: gray };
1105
1097
  }
1106
1098
  let { r, g, b } = hslToRgb(H, 1, 0.5);
1107
- [r, g, b] = [r, g, b]
1108
- .map((v) => (v / 255) * (1 - W - B) + W)
1109
- .map((v) => v * 255);
1099
+ [r, g, b] = [r, g, b].map((v) => v * (1 - W - B) + W);
1110
1100
 
1111
1101
  return { r, g, b };
1112
1102
  }
@@ -1114,15 +1104,12 @@ function hwbToRgb(H, W, B) {
1114
1104
  /**
1115
1105
  * Converts an RGB colour value to HSV.
1116
1106
  *
1117
- * @param {number} R Red component [0, 255]
1118
- * @param {number} G Green [0, 255]
1119
- * @param {number} B Blue [0, 255]
1107
+ * @param {number} r Red component [0, 1]
1108
+ * @param {number} g Green [0, 1]
1109
+ * @param {number} b Blue [0, 1]
1120
1110
  * @returns {CP.HSV} {h,s,v} object with [0, 1] ranged values
1121
1111
  */
1122
- function rgbToHsv(R, G, B) {
1123
- const r = R / 255;
1124
- const g = G / 255;
1125
- const b = B / 255;
1112
+ function rgbToHsv(r, g, b) {
1126
1113
  const max = Math.max(r, g, b);
1127
1114
  const min = Math.min(r, g, b);
1128
1115
  let h = 0;
@@ -1132,17 +1119,10 @@ function rgbToHsv(R, G, B) {
1132
1119
  if (max === min) {
1133
1120
  h = 0; // achromatic
1134
1121
  } else {
1135
- switch (max) {
1136
- case r:
1137
- h = (g - b) / d + (g < b ? 6 : 0);
1138
- break;
1139
- case g:
1140
- h = (b - r) / d + 2;
1141
- break;
1142
- case b:
1143
- h = (r - g) / d + 4;
1144
- break;
1145
- }
1122
+ if (r === max) h = (g - b) / d + (g < b ? 6 : 0);
1123
+ if (g === max) h = (b - r) / d + 2;
1124
+ if (b === max) h = (r - g) / d + 4;
1125
+
1146
1126
  h /= 6;
1147
1127
  }
1148
1128
  return { h, s, v };
@@ -1166,10 +1146,9 @@ function hsvToRgb(H, S, V) {
1166
1146
  const q = v * (1 - f * s);
1167
1147
  const t = v * (1 - (1 - f) * s);
1168
1148
  const mod = i % 6;
1169
- let r = [v, q, p, p, t, v][mod];
1170
- let g = [t, v, v, q, p, p][mod];
1171
- let b = [p, p, t, v, v, q][mod];
1172
- [r, g, b] = [r, g, b].map((n) => n * 255);
1149
+ const r = [v, q, p, p, t, v][mod];
1150
+ const g = [t, v, v, q, p, p][mod];
1151
+ const b = [p, p, t, v, v, q][mod];
1173
1152
  return { r, g, b };
1174
1153
  }
1175
1154
 
@@ -1237,15 +1216,15 @@ function rgbaToHex(r, g, b, a, allow4Char) {
1237
1216
  */
1238
1217
  function stringInputToObject(input) {
1239
1218
  let color = toLowerCase(input.trim());
1219
+
1240
1220
  if (color.length === 0) {
1241
1221
  return {
1242
1222
  r: 0, g: 0, b: 0, a: 1,
1243
1223
  };
1244
1224
  }
1245
- let named = false;
1225
+
1246
1226
  if (isColorName(color)) {
1247
1227
  color = getRGBFromName(color);
1248
- named = true;
1249
1228
  } else if (nonColors.includes(color)) {
1250
1229
  const a = color === 'transparent' ? 0 : 1;
1251
1230
  return {
@@ -1264,24 +1243,28 @@ function stringInputToObject(input) {
1264
1243
  r: m1, g: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'rgb',
1265
1244
  };
1266
1245
  }
1246
+
1267
1247
  [, m1, m2, m3, m4] = matchers.hsl.exec(color) || [];
1268
1248
  if (m1 && m2 && m3/* && m4 */) {
1269
1249
  return {
1270
1250
  h: m1, s: m2, l: m3, a: m4 !== undefined ? m4 : 1, format: 'hsl',
1271
1251
  };
1272
1252
  }
1253
+
1273
1254
  [, m1, m2, m3, m4] = matchers.hsv.exec(color) || [];
1274
1255
  if (m1 && m2 && m3/* && m4 */) {
1275
1256
  return {
1276
1257
  h: m1, s: m2, v: m3, a: m4 !== undefined ? m4 : 1, format: 'hsv',
1277
1258
  };
1278
1259
  }
1260
+
1279
1261
  [, m1, m2, m3, m4] = matchers.hwb.exec(color) || [];
1280
1262
  if (m1 && m2 && m3) {
1281
1263
  return {
1282
1264
  h: m1, w: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'hwb',
1283
1265
  };
1284
1266
  }
1267
+
1285
1268
  [, m1, m2, m3, m4] = matchers.hex8.exec(color) || [];
1286
1269
  if (m1 && m2 && m3 && m4) {
1287
1270
  return {
@@ -1289,18 +1272,20 @@ function stringInputToObject(input) {
1289
1272
  g: parseIntFromHex(m2),
1290
1273
  b: parseIntFromHex(m3),
1291
1274
  a: convertHexToDecimal(m4),
1292
- format: named ? 'rgb' : 'hex',
1275
+ format: 'hex',
1293
1276
  };
1294
1277
  }
1278
+
1295
1279
  [, m1, m2, m3] = matchers.hex6.exec(color) || [];
1296
1280
  if (m1 && m2 && m3) {
1297
1281
  return {
1298
1282
  r: parseIntFromHex(m1),
1299
1283
  g: parseIntFromHex(m2),
1300
1284
  b: parseIntFromHex(m3),
1301
- format: named ? 'rgb' : 'hex',
1285
+ format: 'hex',
1302
1286
  };
1303
1287
  }
1288
+
1304
1289
  [, m1, m2, m3, m4] = matchers.hex4.exec(color) || [];
1305
1290
  if (m1 && m2 && m3 && m4) {
1306
1291
  return {
@@ -1308,19 +1293,20 @@ function stringInputToObject(input) {
1308
1293
  g: parseIntFromHex(m2 + m2),
1309
1294
  b: parseIntFromHex(m3 + m3),
1310
1295
  a: convertHexToDecimal(m4 + m4),
1311
- // format: named ? 'rgb' : 'hex8',
1312
- format: named ? 'rgb' : 'hex',
1296
+ format: 'hex',
1313
1297
  };
1314
1298
  }
1299
+
1315
1300
  [, m1, m2, m3] = matchers.hex3.exec(color) || [];
1316
1301
  if (m1 && m2 && m3) {
1317
1302
  return {
1318
1303
  r: parseIntFromHex(m1 + m1),
1319
1304
  g: parseIntFromHex(m2 + m2),
1320
1305
  b: parseIntFromHex(m3 + m3),
1321
- format: named ? 'rgb' : 'hex',
1306
+ format: 'hex',
1322
1307
  };
1323
1308
  }
1309
+
1324
1310
  return false;
1325
1311
  }
1326
1312
 
@@ -1351,6 +1337,7 @@ function stringInputToObject(input) {
1351
1337
  */
1352
1338
  function inputToRGB(input) {
1353
1339
  let rgb = { r: 0, g: 0, b: 0 };
1340
+ /** @type {*} */
1354
1341
  let color = input;
1355
1342
  /** @type {string | number} */
1356
1343
  let a = 1;
@@ -1367,39 +1354,41 @@ function inputToRGB(input) {
1367
1354
  let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
1368
1355
 
1369
1356
  if (typeof input === 'string') {
1370
- // @ts-ignore -- this now is converted to object
1371
1357
  color = stringInputToObject(input);
1372
1358
  if (color) ok = true;
1373
1359
  }
1374
1360
  if (typeof color === 'object') {
1375
1361
  if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
1376
1362
  ({ r, g, b } = color);
1377
- // RGB values now are all in [0, 255] range
1378
- [r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255) * 255);
1363
+ // RGB values now are all in [0, 1] range
1364
+ [r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255));
1379
1365
  rgb = { r, g, b };
1380
1366
  ok = true;
1381
- format = 'rgb';
1382
- } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
1367
+ format = color.format || 'rgb';
1368
+ }
1369
+ if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
1383
1370
  ({ h, s, v } = color);
1384
- h = typeof h === 'number' ? h : bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1385
- s = typeof s === 'number' ? s : bound01(s, 100); // saturation can be `5%` or a [0, 1] value
1386
- v = typeof v === 'number' ? v : bound01(v, 100); // brightness can be `5%` or a [0, 1] value
1371
+ h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1372
+ s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
1373
+ v = bound01(v, 100); // brightness can be `5%` or a [0, 1] value
1387
1374
  rgb = hsvToRgb(h, s, v);
1388
1375
  ok = true;
1389
1376
  format = 'hsv';
1390
- } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
1377
+ }
1378
+ if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
1391
1379
  ({ h, s, l } = color);
1392
- h = typeof h === 'number' ? h : bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1393
- s = typeof s === 'number' ? s : bound01(s, 100); // saturation can be `5%` or a [0, 1] value
1394
- l = typeof l === 'number' ? l : bound01(l, 100); // lightness can be `5%` or a [0, 1] value
1380
+ h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1381
+ s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
1382
+ l = bound01(l, 100); // lightness can be `5%` or a [0, 1] value
1395
1383
  rgb = hslToRgb(h, s, l);
1396
1384
  ok = true;
1397
1385
  format = 'hsl';
1398
- } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
1386
+ }
1387
+ if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
1399
1388
  ({ h, w, b } = color);
1400
- h = typeof h === 'number' ? h : bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1401
- w = typeof w === 'number' ? w : bound01(w, 100); // whiteness can be `5%` or a [0, 1] value
1402
- b = typeof b === 'number' ? b : bound01(b, 100); // blackness can be `5%` or a [0, 1] value
1389
+ h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
1390
+ w = bound01(w, 100); // whiteness can be `5%` or a [0, 1] value
1391
+ b = bound01(b, 100); // blackness can be `5%` or a [0, 1] value
1403
1392
  rgb = hwbToRgb(h, w, b);
1404
1393
  ok = true;
1405
1394
  format = 'hwb';
@@ -1416,9 +1405,12 @@ function inputToRGB(input) {
1416
1405
  return {
1417
1406
  ok,
1418
1407
  format,
1419
- r: Math.min(255, Math.max(rgb.r, 0)),
1420
- g: Math.min(255, Math.max(rgb.g, 0)),
1421
- b: Math.min(255, Math.max(rgb.b, 0)),
1408
+ // r: Math.min(255, Math.max(rgb.r, 0)),
1409
+ // g: Math.min(255, Math.max(rgb.g, 0)),
1410
+ // b: Math.min(255, Math.max(rgb.b, 0)),
1411
+ r: rgb.r,
1412
+ g: rgb.g,
1413
+ b: rgb.b,
1422
1414
  a: boundAlpha(a),
1423
1415
  };
1424
1416
  }
@@ -1437,16 +1429,13 @@ class Color {
1437
1429
  constructor(input, config) {
1438
1430
  let color = input;
1439
1431
  const configFormat = config && COLOR_FORMAT.includes(config)
1440
- ? config : 'rgb';
1432
+ ? config : '';
1441
1433
 
1442
- // If input is already a `Color`, return itself
1434
+ // If input is already a `Color`, clone its values
1443
1435
  if (color instanceof Color) {
1444
1436
  color = inputToRGB(color);
1445
1437
  }
1446
- if (typeof color === 'number') {
1447
- const len = `${color}`.length;
1448
- color = `#${(len === 2 ? '0' : '00')}${color}`;
1449
- }
1438
+
1450
1439
  const {
1451
1440
  r, g, b, a, ok, format,
1452
1441
  } = inputToRGB(color);
@@ -1496,24 +1485,21 @@ class Color {
1496
1485
  let R = 0;
1497
1486
  let G = 0;
1498
1487
  let B = 0;
1499
- const rp = r / 255;
1500
- const rg = g / 255;
1501
- const rb = b / 255;
1502
1488
 
1503
- if (rp <= 0.03928) {
1504
- R = rp / 12.92;
1489
+ if (r <= 0.03928) {
1490
+ R = r / 12.92;
1505
1491
  } else {
1506
- R = ((rp + 0.055) / 1.055) ** 2.4;
1492
+ R = ((r + 0.055) / 1.055) ** 2.4;
1507
1493
  }
1508
- if (rg <= 0.03928) {
1509
- G = rg / 12.92;
1494
+ if (g <= 0.03928) {
1495
+ G = g / 12.92;
1510
1496
  } else {
1511
- G = ((rg + 0.055) / 1.055) ** 2.4;
1497
+ G = ((g + 0.055) / 1.055) ** 2.4;
1512
1498
  }
1513
- if (rb <= 0.03928) {
1514
- B = rb / 12.92;
1499
+ if (b <= 0.03928) {
1500
+ B = b / 12.92;
1515
1501
  } else {
1516
- B = ((rb + 0.055) / 1.055) ** 2.4;
1502
+ B = ((b + 0.055) / 1.055) ** 2.4;
1517
1503
  }
1518
1504
  return 0.2126 * R + 0.7152 * G + 0.0722 * B;
1519
1505
  }
@@ -1523,7 +1509,7 @@ class Color {
1523
1509
  * @returns {number} a number in the [0, 255] range
1524
1510
  */
1525
1511
  get brightness() {
1526
- const { r, g, b } = this;
1512
+ const { r, g, b } = this.toRgb();
1527
1513
  return (r * 299 + g * 587 + b * 114) / 1000;
1528
1514
  }
1529
1515
 
@@ -1532,12 +1518,14 @@ class Color {
1532
1518
  * @returns {CP.RGBA} an {r,g,b,a} object with [0, 255] ranged values
1533
1519
  */
1534
1520
  toRgb() {
1535
- const {
1521
+ let {
1536
1522
  r, g, b, a,
1537
1523
  } = this;
1538
1524
 
1525
+ [r, g, b] = [r, g, b].map((n) => roundPart(n * 255 * 100) / 100);
1526
+ a = roundPart(a * 100) / 100;
1539
1527
  return {
1540
- r, g, b, a: roundPart(a * 100) / 100,
1528
+ r, g, b, a,
1541
1529
  };
1542
1530
  }
1543
1531
 
@@ -1631,7 +1619,7 @@ class Color {
1631
1619
  toHsv() {
1632
1620
  const {
1633
1621
  r, g, b, a,
1634
- } = this.toRgb();
1622
+ } = this;
1635
1623
  const { h, s, v } = rgbToHsv(r, g, b);
1636
1624
 
1637
1625
  return {
@@ -1646,7 +1634,7 @@ class Color {
1646
1634
  toHsl() {
1647
1635
  const {
1648
1636
  r, g, b, a,
1649
- } = this.toRgb();
1637
+ } = this;
1650
1638
  const { h, s, l } = rgbToHsl(r, g, b);
1651
1639
 
1652
1640
  return {
@@ -1731,6 +1719,7 @@ class Color {
1731
1719
  */
1732
1720
  setAlpha(alpha) {
1733
1721
  const self = this;
1722
+ if (typeof alpha !== 'number') return self;
1734
1723
  self.a = boundAlpha(alpha);
1735
1724
  return self;
1736
1725
  }
@@ -1897,26 +1886,23 @@ class ColorPalette {
1897
1886
  } else if (args.length === 2) {
1898
1887
  [hueSteps, lightSteps] = args;
1899
1888
  if ([hueSteps, lightSteps].some((n) => n < 1)) {
1900
- throw TypeError('ColorPalette: when 2 arguments used, both must be larger than 0.');
1889
+ throw TypeError('ColorPalette: both arguments must be higher than 0.');
1901
1890
  }
1902
- } else {
1903
- throw TypeError('ColorPalette requires minimum 2 arguments');
1904
1891
  }
1905
1892
 
1906
- /** @type {Color[]} */
1893
+ /** @type {*} */
1907
1894
  const colors = [];
1908
-
1909
1895
  const hueStep = 360 / hueSteps;
1910
1896
  const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
1911
- const estimatedStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
1897
+ const steps1To13 = [0.25, 0.2, 0.15, 0.11, 0.09, 0.075];
1898
+ const lightSets = [[1, 2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]];
1899
+ const closestSet = lightSets.find((set) => set.includes(lightSteps));
1912
1900
 
1913
- let lightStep = 0.25;
1914
- lightStep = [4, 5].includes(lightSteps) ? 0.2 : lightStep;
1915
- lightStep = [6, 7].includes(lightSteps) ? 0.15 : lightStep;
1916
- lightStep = [8, 9].includes(lightSteps) ? 0.11 : lightStep;
1917
- lightStep = [10, 11].includes(lightSteps) ? 0.09 : lightStep;
1918
- lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
1919
- lightStep = lightSteps > 13 ? estimatedStep : lightStep;
1901
+ // find a lightStep that won't go beyond black and white
1902
+ // something within the [10-90] range of lightness
1903
+ const lightStep = closestSet
1904
+ ? steps1To13[lightSets.indexOf(closestSet)]
1905
+ : (100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100);
1920
1906
 
1921
1907
  // light tints
1922
1908
  for (let i = 1; i < half + 1; i += 1) {
@@ -2431,7 +2417,7 @@ function setMarkup(self) {
2431
2417
  setAttribute(input, tabIndex, '-1');
2432
2418
  }
2433
2419
 
2434
- var version = "0.0.2alpha1";
2420
+ var version = "0.0.2alpha2";
2435
2421
 
2436
2422
  // @ts-ignore
2437
2423
 
@@ -2474,8 +2460,6 @@ function toggleEvents(self, action) {
2474
2460
  fn(input, focusinEvent, self.showPicker);
2475
2461
  fn(pickerToggle, mouseclickEvent, self.togglePicker);
2476
2462
 
2477
- fn(input, keydownEvent, self.keyToggle);
2478
-
2479
2463
  if (menuToggle) {
2480
2464
  fn(menuToggle, mouseclickEvent, self.toggleMenu);
2481
2465
  }
@@ -2513,8 +2497,7 @@ function toggleEventsOnShown(self, action) {
2513
2497
  fn(doc, pointerEvents.move, self.pointerMove);
2514
2498
  fn(doc, pointerEvents.up, self.pointerUp);
2515
2499
  fn(parent, focusoutEvent, self.handleFocusOut);
2516
- // @ts-ignore -- this is `Window`
2517
- fn(win, keyupEvent, self.handleDismiss);
2500
+ fn(doc, keyupEvent, self.handleDismiss);
2518
2501
  }
2519
2502
 
2520
2503
  /**
@@ -2598,7 +2581,7 @@ class ColorPicker {
2598
2581
  const input = querySelector(target);
2599
2582
 
2600
2583
  // invalidate
2601
- if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
2584
+ if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
2602
2585
  self.input = input;
2603
2586
 
2604
2587
  const parent = closest(input, colorPickerParentSelector);
@@ -2645,15 +2628,14 @@ class ColorPicker {
2645
2628
  });
2646
2629
 
2647
2630
  // update and expose component labels
2648
- const tempLabels = ObjectAssign({}, colorPickerLabels);
2649
- const jsonLabels = componentLabels && isValidJSON(componentLabels)
2650
- ? JSON.parse(componentLabels) : componentLabels || {};
2631
+ const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
2632
+ ? JSON.parse(componentLabels) : componentLabels;
2651
2633
 
2652
2634
  /** @type {Record<string, string>} */
2653
- self.componentLabels = ObjectAssign(tempLabels, jsonLabels);
2635
+ self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
2654
2636
 
2655
2637
  /** @type {Color} */
2656
- self.color = new Color('white', format);
2638
+ self.color = new Color(input.value || '#fff', format);
2657
2639
 
2658
2640
  /** @type {CP.ColorFormats} */
2659
2641
  self.format = format;
@@ -2662,7 +2644,7 @@ class ColorPicker {
2662
2644
  if (colorKeywords instanceof Array) {
2663
2645
  self.colorKeywords = colorKeywords;
2664
2646
  } else if (typeof colorKeywords === 'string' && colorKeywords.length) {
2665
- self.colorKeywords = colorKeywords.split(',');
2647
+ self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
2666
2648
  }
2667
2649
 
2668
2650
  // set colour presets
@@ -2691,7 +2673,6 @@ class ColorPicker {
2691
2673
  self.handleFocusOut = self.handleFocusOut.bind(self);
2692
2674
  self.changeHandler = self.changeHandler.bind(self);
2693
2675
  self.handleDismiss = self.handleDismiss.bind(self);
2694
- self.keyToggle = self.keyToggle.bind(self);
2695
2676
  self.handleKnobs = self.handleKnobs.bind(self);
2696
2677
 
2697
2678
  // generate markup
@@ -2783,76 +2764,83 @@ class ColorPicker {
2783
2764
  return inputValue !== '' && new Color(inputValue).isValid;
2784
2765
  }
2785
2766
 
2767
+ /** Returns the colour appearance, usually the closest colour name for the current value. */
2768
+ get appearance() {
2769
+ const {
2770
+ colorLabels, hsl, hsv, format,
2771
+ } = this;
2772
+
2773
+ const hue = roundPart(hsl.h * 360);
2774
+ const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
2775
+ const saturation = roundPart(saturationSource * 100);
2776
+ const lightness = roundPart(hsl.l * 100);
2777
+ const hsvl = hsv.v * 100;
2778
+
2779
+ let colorName;
2780
+
2781
+ // determine color appearance
2782
+ if (lightness === 100 && saturation === 0) {
2783
+ colorName = colorLabels.white;
2784
+ } else if (lightness === 0) {
2785
+ colorName = colorLabels.black;
2786
+ } else if (saturation === 0) {
2787
+ colorName = colorLabels.grey;
2788
+ } else if (hue < 15 || hue >= 345) {
2789
+ colorName = colorLabels.red;
2790
+ } else if (hue >= 15 && hue < 45) {
2791
+ colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
2792
+ } else if (hue >= 45 && hue < 75) {
2793
+ const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
2794
+ const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
2795
+ colorName = isGold ? colorLabels.gold : colorLabels.yellow;
2796
+ colorName = isOlive ? colorLabels.olive : colorName;
2797
+ } else if (hue >= 75 && hue < 155) {
2798
+ colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
2799
+ } else if (hue >= 155 && hue < 175) {
2800
+ colorName = colorLabels.teal;
2801
+ } else if (hue >= 175 && hue < 195) {
2802
+ colorName = colorLabels.cyan;
2803
+ } else if (hue >= 195 && hue < 255) {
2804
+ colorName = colorLabels.blue;
2805
+ } else if (hue >= 255 && hue < 270) {
2806
+ colorName = colorLabels.violet;
2807
+ } else if (hue >= 270 && hue < 295) {
2808
+ colorName = colorLabels.magenta;
2809
+ } else if (hue >= 295 && hue < 345) {
2810
+ colorName = colorLabels.pink;
2811
+ }
2812
+ return colorName;
2813
+ }
2814
+
2786
2815
  /** Updates `ColorPicker` visuals. */
2787
2816
  updateVisuals() {
2788
2817
  const self = this;
2789
2818
  const {
2790
- format, controlPositions, visuals,
2819
+ controlPositions, visuals,
2791
2820
  } = self;
2792
2821
  const [v1, v2, v3] = visuals;
2793
- const { offsetWidth, offsetHeight } = v1;
2794
- const hue = format === 'hsl'
2795
- ? controlPositions.c1x / offsetWidth
2796
- : controlPositions.c2y / offsetHeight;
2797
- // @ts-ignore - `hslToRgb` is assigned to `Color` as static method
2798
- const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
2822
+ const { offsetHeight } = v1;
2823
+ const hue = controlPositions.c2y / offsetHeight;
2824
+ const { r, g, b } = new Color({ h: hue, s: 1, l: 0.5 }).toRgb();
2799
2825
  const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
2800
2826
  const alpha = 1 - controlPositions.c3y / offsetHeight;
2801
2827
  const roundA = roundPart((alpha * 100)) / 100;
2802
2828
 
2803
- if (format !== 'hsl') {
2804
- const fill = new Color({
2805
- h: hue, s: 1, l: 0.5, a: alpha,
2806
- }).toRgbString();
2807
- const hueGradient = `linear-gradient(
2808
- rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
2809
- rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
2810
- rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
2811
- rgb(255,0,0) 100%)`;
2812
- setElementStyle(v1, {
2813
- background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
2814
- linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
2815
- ${whiteGrad}`,
2816
- });
2817
- setElementStyle(v2, { background: hueGradient });
2818
- } else {
2819
- const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
2820
- const fill0 = new Color({
2821
- r: 255, g: 0, b: 0, a: alpha,
2822
- }).saturate(-saturation).toRgbString();
2823
- const fill1 = new Color({
2824
- r: 255, g: 255, b: 0, a: alpha,
2825
- }).saturate(-saturation).toRgbString();
2826
- const fill2 = new Color({
2827
- r: 0, g: 255, b: 0, a: alpha,
2828
- }).saturate(-saturation).toRgbString();
2829
- const fill3 = new Color({
2830
- r: 0, g: 255, b: 255, a: alpha,
2831
- }).saturate(-saturation).toRgbString();
2832
- const fill4 = new Color({
2833
- r: 0, g: 0, b: 255, a: alpha,
2834
- }).saturate(-saturation).toRgbString();
2835
- const fill5 = new Color({
2836
- r: 255, g: 0, b: 255, a: alpha,
2837
- }).saturate(-saturation).toRgbString();
2838
- const fill6 = new Color({
2839
- r: 255, g: 0, b: 0, a: alpha,
2840
- }).saturate(-saturation).toRgbString();
2841
- const fillGradient = `linear-gradient(to right,
2842
- ${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
2843
- ${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
2844
- const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
2845
- linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
2846
-
2847
- setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
2848
- const {
2849
- r: gr, g: gg, b: gb,
2850
- } = new Color({ r, g, b }).greyscale().toRgb();
2829
+ const fill = new Color({
2830
+ h: hue, s: 1, l: 0.5, a: alpha,
2831
+ }).toRgbString();
2832
+ const hueGradient = `linear-gradient(
2833
+ rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
2834
+ rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
2835
+ rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
2836
+ rgb(255,0,0) 100%)`;
2837
+ setElementStyle(v1, {
2838
+ background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
2839
+ linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
2840
+ ${whiteGrad}`,
2841
+ });
2842
+ setElementStyle(v2, { background: hueGradient });
2851
2843
 
2852
- setElementStyle(v2, {
2853
- background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
2854
- });
2855
- }
2856
2844
  setElementStyle(v3, {
2857
2845
  background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
2858
2846
  });
@@ -3002,13 +2990,13 @@ class ColorPicker {
3002
2990
  const [v1, v2, v3] = visuals;
3003
2991
  const [c1, c2, c3] = controlKnobs;
3004
2992
  /** @type {HTMLElement} */
3005
- const visual = hasClass(target, 'visual-control')
3006
- ? target : querySelector('.visual-control', target.parentElement);
2993
+ const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
3007
2994
  const visualRect = getBoundingClientRect(visual);
2995
+ const html = getDocumentElement(v1);
3008
2996
  const X = type === 'touchstart' ? touches[0].pageX : pageX;
3009
2997
  const Y = type === 'touchstart' ? touches[0].pageY : pageY;
3010
- const offsetX = X - window.pageXOffset - visualRect.left;
3011
- const offsetY = Y - window.pageYOffset - visualRect.top;
2998
+ const offsetX = X - html.scrollLeft - visualRect.left;
2999
+ const offsetY = Y - html.scrollTop - visualRect.top;
3012
3000
 
3013
3001
  if (target === v1 || target === c1) {
3014
3002
  self.dragElement = visual;
@@ -3068,10 +3056,11 @@ class ColorPicker {
3068
3056
  if (!dragElement) return;
3069
3057
 
3070
3058
  const controlRect = getBoundingClientRect(dragElement);
3071
- const X = type === 'touchmove' ? touches[0].pageX : pageX;
3072
- const Y = type === 'touchmove' ? touches[0].pageY : pageY;
3073
- const offsetX = X - window.pageXOffset - controlRect.left;
3074
- const offsetY = Y - window.pageYOffset - controlRect.top;
3059
+ const win = getDocumentElement(v1);
3060
+ const X = type === touchmoveEvent ? touches[0].pageX : pageX;
3061
+ const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
3062
+ const offsetX = X - win.scrollLeft - controlRect.left;
3063
+ const offsetY = Y - win.scrollTop - controlRect.top;
3075
3064
 
3076
3065
  if (dragElement === v1) {
3077
3066
  self.changeControl1(offsetX, offsetY);
@@ -3098,19 +3087,19 @@ class ColorPicker {
3098
3087
  if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
3099
3088
  e.preventDefault();
3100
3089
 
3101
- const { format, controlKnobs, visuals } = self;
3090
+ const { controlKnobs, visuals } = self;
3102
3091
  const { offsetWidth, offsetHeight } = visuals[0];
3103
3092
  const [c1, c2, c3] = controlKnobs;
3104
3093
  const { activeElement } = getDocument(c1);
3105
3094
  const currentKnob = controlKnobs.find((x) => x === activeElement);
3106
- const yRatio = offsetHeight / (format === 'hsl' ? 100 : 360);
3095
+ const yRatio = offsetHeight / 360;
3107
3096
 
3108
3097
  if (currentKnob) {
3109
3098
  let offsetX = 0;
3110
3099
  let offsetY = 0;
3111
3100
 
3112
3101
  if (target === c1) {
3113
- const xRatio = offsetWidth / (format === 'hsl' ? 360 : 100);
3102
+ const xRatio = offsetWidth / 100;
3114
3103
 
3115
3104
  if ([keyArrowLeft, keyArrowRight].includes(code)) {
3116
3105
  self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
@@ -3160,7 +3149,7 @@ class ColorPicker {
3160
3149
  if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
3161
3150
  if (activeElement === input) {
3162
3151
  if (isNonColorValue) {
3163
- colorSource = 'white';
3152
+ colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
3164
3153
  } else {
3165
3154
  colorSource = currentValue;
3166
3155
  }
@@ -3211,9 +3200,7 @@ class ColorPicker {
3211
3200
  changeControl1(X, Y) {
3212
3201
  const self = this;
3213
3202
  let [offsetX, offsetY] = [0, 0];
3214
- const {
3215
- format, controlPositions, visuals,
3216
- } = self;
3203
+ const { controlPositions, visuals } = self;
3217
3204
  const { offsetHeight, offsetWidth } = visuals[0];
3218
3205
 
3219
3206
  if (X > offsetWidth) offsetX = offsetWidth;
@@ -3222,29 +3209,19 @@ class ColorPicker {
3222
3209
  if (Y > offsetHeight) offsetY = offsetHeight;
3223
3210
  else if (Y >= 0) offsetY = Y;
3224
3211
 
3225
- const hue = format === 'hsl'
3226
- ? offsetX / offsetWidth
3227
- : controlPositions.c2y / offsetHeight;
3212
+ const hue = controlPositions.c2y / offsetHeight;
3228
3213
 
3229
- const saturation = format === 'hsl'
3230
- ? 1 - controlPositions.c2y / offsetHeight
3231
- : offsetX / offsetWidth;
3214
+ const saturation = offsetX / offsetWidth;
3232
3215
 
3233
3216
  const lightness = 1 - offsetY / offsetHeight;
3234
3217
  const alpha = 1 - controlPositions.c3y / offsetHeight;
3235
3218
 
3236
- const colorObject = format === 'hsl'
3237
- ? {
3238
- h: hue, s: saturation, l: lightness, a: alpha,
3239
- }
3240
- : {
3241
- h: hue, s: saturation, v: lightness, a: alpha,
3242
- };
3243
-
3244
3219
  // new color
3245
3220
  const {
3246
3221
  r, g, b, a,
3247
- } = new Color(colorObject);
3222
+ } = new Color({
3223
+ h: hue, s: saturation, v: lightness, a: alpha,
3224
+ });
3248
3225
 
3249
3226
  ObjectAssign(self.color, {
3250
3227
  r, g, b, a,
@@ -3271,7 +3248,7 @@ class ColorPicker {
3271
3248
  changeControl2(Y) {
3272
3249
  const self = this;
3273
3250
  const {
3274
- format, controlPositions, visuals,
3251
+ controlPositions, visuals,
3275
3252
  } = self;
3276
3253
  const { offsetHeight, offsetWidth } = visuals[0];
3277
3254
 
@@ -3280,26 +3257,17 @@ class ColorPicker {
3280
3257
  if (Y > offsetHeight) offsetY = offsetHeight;
3281
3258
  else if (Y >= 0) offsetY = Y;
3282
3259
 
3283
- const hue = format === 'hsl'
3284
- ? controlPositions.c1x / offsetWidth
3285
- : offsetY / offsetHeight;
3286
- const saturation = format === 'hsl'
3287
- ? 1 - offsetY / offsetHeight
3288
- : controlPositions.c1x / offsetWidth;
3260
+ const hue = offsetY / offsetHeight;
3261
+ const saturation = controlPositions.c1x / offsetWidth;
3289
3262
  const lightness = 1 - controlPositions.c1y / offsetHeight;
3290
3263
  const alpha = 1 - controlPositions.c3y / offsetHeight;
3291
- const colorObject = format === 'hsl'
3292
- ? {
3293
- h: hue, s: saturation, l: lightness, a: alpha,
3294
- }
3295
- : {
3296
- h: hue, s: saturation, v: lightness, a: alpha,
3297
- };
3298
3264
 
3299
3265
  // new color
3300
3266
  const {
3301
3267
  r, g, b, a,
3302
- } = new Color(colorObject);
3268
+ } = new Color({
3269
+ h: hue, s: saturation, v: lightness, a: alpha,
3270
+ });
3303
3271
 
3304
3272
  ObjectAssign(self.color, {
3305
3273
  r, g, b, a,
@@ -3386,18 +3354,18 @@ class ColorPicker {
3386
3354
  setControlPositions() {
3387
3355
  const self = this;
3388
3356
  const {
3389
- format, visuals, color, hsl, hsv,
3357
+ visuals, color, hsv,
3390
3358
  } = self;
3391
3359
  const { offsetHeight, offsetWidth } = visuals[0];
3392
3360
  const alpha = color.a;
3393
- const hue = hsl.h;
3361
+ const hue = hsv.h;
3394
3362
 
3395
- const saturation = format !== 'hsl' ? hsv.s : hsl.s;
3396
- const lightness = format !== 'hsl' ? hsv.v : hsl.l;
3363
+ const saturation = hsv.s;
3364
+ const lightness = hsv.v;
3397
3365
 
3398
- self.controlPositions.c1x = format !== 'hsl' ? saturation * offsetWidth : hue * offsetWidth;
3366
+ self.controlPositions.c1x = saturation * offsetWidth;
3399
3367
  self.controlPositions.c1y = (1 - lightness) * offsetHeight;
3400
- self.controlPositions.c2y = format !== 'hsl' ? hue * offsetHeight : (1 - saturation) * offsetHeight;
3368
+ self.controlPositions.c2y = hue * offsetHeight;
3401
3369
  self.controlPositions.c3y = (1 - alpha) * offsetHeight;
3402
3370
  }
3403
3371
 
@@ -3405,78 +3373,40 @@ class ColorPicker {
3405
3373
  updateAppearance() {
3406
3374
  const self = this;
3407
3375
  const {
3408
- componentLabels, colorLabels, color, parent,
3409
- hsl, hsv, hex, format, controlKnobs,
3376
+ componentLabels, color, parent,
3377
+ hsv, hex, format, controlKnobs,
3410
3378
  } = self;
3411
3379
  const {
3412
3380
  appearanceLabel, hexLabel, valueLabel,
3413
3381
  } = componentLabels;
3414
- const { r, g, b } = color.toRgb();
3382
+ let { r, g, b } = color.toRgb();
3415
3383
  const [knob1, knob2, knob3] = controlKnobs;
3416
- const hue = roundPart(hsl.h * 360);
3384
+ const hue = roundPart(hsv.h * 360);
3417
3385
  const alpha = color.a;
3418
- const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
3419
- const saturation = roundPart(saturationSource * 100);
3420
- const lightness = roundPart(hsl.l * 100);
3421
- const hsvl = hsv.v * 100;
3422
- let colorName;
3423
-
3424
- // determine color appearance
3425
- if (lightness === 100 && saturation === 0) {
3426
- colorName = colorLabels.white;
3427
- } else if (lightness === 0) {
3428
- colorName = colorLabels.black;
3429
- } else if (saturation === 0) {
3430
- colorName = colorLabels.grey;
3431
- } else if (hue < 15 || hue >= 345) {
3432
- colorName = colorLabels.red;
3433
- } else if (hue >= 15 && hue < 45) {
3434
- colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
3435
- } else if (hue >= 45 && hue < 75) {
3436
- const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
3437
- const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
3438
- colorName = isGold ? colorLabels.gold : colorLabels.yellow;
3439
- colorName = isOlive ? colorLabels.olive : colorName;
3440
- } else if (hue >= 75 && hue < 155) {
3441
- colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
3442
- } else if (hue >= 155 && hue < 175) {
3443
- colorName = colorLabels.teal;
3444
- } else if (hue >= 175 && hue < 195) {
3445
- colorName = colorLabels.cyan;
3446
- } else if (hue >= 195 && hue < 255) {
3447
- colorName = colorLabels.blue;
3448
- } else if (hue >= 255 && hue < 270) {
3449
- colorName = colorLabels.violet;
3450
- } else if (hue >= 270 && hue < 295) {
3451
- colorName = colorLabels.magenta;
3452
- } else if (hue >= 295 && hue < 345) {
3453
- colorName = colorLabels.pink;
3454
- }
3386
+ const saturation = roundPart(hsv.s * 100);
3387
+ const lightness = roundPart(hsv.v * 100);
3388
+ const colorName = self.appearance;
3455
3389
 
3456
3390
  let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
3457
3391
 
3458
- if (format === 'hsl') {
3459
- colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
3460
- setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
3461
- setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
3462
- setAttribute(knob1, ariaValueNow, `${hue}`);
3463
- setAttribute(knob2, ariaValueText, `${saturation}%`);
3464
- setAttribute(knob2, ariaValueNow, `${saturation}`);
3465
- } else if (format === 'hwb') {
3392
+ if (format === 'hwb') {
3466
3393
  const { hwb } = self;
3467
3394
  const whiteness = roundPart(hwb.w * 100);
3468
3395
  const blackness = roundPart(hwb.b * 100);
3469
3396
  colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
3470
- setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
3471
3397
  setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
3472
3398
  setAttribute(knob1, ariaValueNow, `${whiteness}`);
3399
+ setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
3473
3400
  setAttribute(knob2, ariaValueText, `${hue}%`);
3474
3401
  setAttribute(knob2, ariaValueNow, `${hue}`);
3475
3402
  } else {
3403
+ [r, g, b] = [r, g, b].map(roundPart);
3404
+ colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
3476
3405
  colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
3477
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
3406
+
3478
3407
  setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
3479
3408
  setAttribute(knob1, ariaValueNow, `${lightness}`);
3409
+ setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
3480
3410
  setAttribute(knob2, ariaValueText, `${hue}°`);
3481
3411
  setAttribute(knob2, ariaValueNow, `${hue}`);
3482
3412
  }
@@ -3571,37 +3501,13 @@ class ColorPicker {
3571
3501
  }
3572
3502
  }
3573
3503
 
3574
- /**
3575
- * The `Space` & `Enter` keys specific event listener.
3576
- * Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
3577
- * @param {KeyboardEvent} e
3578
- * @this {ColorPicker}
3579
- */
3580
- keyToggle(e) {
3581
- const self = this;
3582
- const { menuToggle } = self;
3583
- const { activeElement } = getDocument(menuToggle);
3584
- const { code } = e;
3585
-
3586
- if ([keyEnter, keySpace].includes(code)) {
3587
- if ((menuToggle && activeElement === menuToggle) || !activeElement) {
3588
- e.preventDefault();
3589
- if (!activeElement) {
3590
- self.togglePicker(e);
3591
- } else {
3592
- self.toggleMenu();
3593
- }
3594
- }
3595
- }
3596
- }
3597
-
3598
3504
  /**
3599
3505
  * Toggle the `ColorPicker` dropdown visibility.
3600
- * @param {Event} e
3506
+ * @param {Event=} e
3601
3507
  * @this {ColorPicker}
3602
3508
  */
3603
3509
  togglePicker(e) {
3604
- e.preventDefault();
3510
+ if (e) e.preventDefault();
3605
3511
  const self = this;
3606
3512
  const { colorPicker } = self;
3607
3513
 
@@ -3622,8 +3528,13 @@ class ColorPicker {
3622
3528
  }
3623
3529
  }
3624
3530
 
3625
- /** Toggles the visibility of the `ColorPicker` presets menu. */
3626
- toggleMenu() {
3531
+ /**
3532
+ * Toggles the visibility of the `ColorPicker` presets menu.
3533
+ * @param {Event=} e
3534
+ * @this {ColorPicker}
3535
+ */
3536
+ toggleMenu(e) {
3537
+ if (e) e.preventDefault();
3627
3538
  const self = this;
3628
3539
  const { colorMenu } = self;
3629
3540
 
@@ -3649,6 +3560,10 @@ class ColorPicker {
3649
3560
  const relatedBtn = openPicker ? pickerToggle : menuToggle;
3650
3561
  const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
3651
3562
 
3563
+ // if (!self.isValid) {
3564
+ self.value = self.color.toString(true);
3565
+ // }
3566
+
3652
3567
  if (openDropdown) {
3653
3568
  removeClass(openDropdown, 'show');
3654
3569
  setAttribute(relatedBtn, ariaExpanded, 'false');
@@ -3662,9 +3577,6 @@ class ColorPicker {
3662
3577
  }, animationDuration);
3663
3578
  }
3664
3579
 
3665
- if (!self.isValid) {
3666
- self.value = self.color.toString();
3667
- }
3668
3580
  if (!focusPrevented) {
3669
3581
  focus(pickerToggle);
3670
3582
  }