@thednp/color-picker 0.0.1-alpha2 → 0.0.2-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -15
- package/dist/css/color-picker.css +38 -15
- package/dist/css/color-picker.min.css +2 -2
- package/dist/css/color-picker.rtl.css +38 -15
- package/dist/css/color-picker.rtl.min.css +2 -2
- package/dist/js/color-esm.js +1178 -0
- package/dist/js/color-esm.min.js +2 -0
- package/dist/js/color-palette-esm.js +1252 -0
- package/dist/js/color-palette-esm.min.js +2 -0
- package/dist/js/color-palette.js +1260 -0
- package/dist/js/color-palette.min.js +2 -0
- package/dist/js/color-picker-element-esm.js +433 -424
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +435 -426
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +745 -739
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +747 -741
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1186 -0
- package/dist/js/color.min.js +2 -0
- package/package.json +19 -3
- package/src/js/color-palette.js +28 -12
- package/src/js/color-picker-element.js +8 -4
- package/src/js/color-picker.js +84 -172
- package/src/js/color.js +125 -131
- package/src/js/util/getColorControls.js +3 -3
- package/src/js/util/getColorForm.js +0 -1
- package/src/js/util/getColorMenu.js +31 -33
- package/src/js/util/roundPart.js +9 -0
- package/src/js/util/setCSSProperties.js +12 -0
- package/src/js/util/setMarkup.js +122 -0
- package/src/js/util/tabindex.js +3 -0
- package/src/js/util/version.js +6 -0
- package/src/scss/color-picker.scss +35 -16
- package/types/cp.d.ts +48 -20
- package/src/js/util/templates.js +0 -10
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPickerElement v0.0.
|
2
|
+
* ColorPickerElement v0.0.2alpha1 (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
|
*/
|
@@ -82,14 +82,9 @@ const setAttribute = (element, attribute, value) => element.setAttribute(attribu
|
|
82
82
|
const getAttribute = (element, attribute) => element.getAttribute(attribute);
|
83
83
|
|
84
84
|
/**
|
85
|
-
*
|
86
|
-
*
|
87
|
-
* @param {(Node | HTMLElement | Element | globalThis)=} node
|
88
|
-
* @returns {HTMLElement | HTMLHeadElement}
|
85
|
+
* A global namespace for `document.head`.
|
89
86
|
*/
|
90
|
-
|
91
|
-
return getDocument(node).head;
|
92
|
-
}
|
87
|
+
const { head: documentHead } = document;
|
93
88
|
|
94
89
|
/**
|
95
90
|
* Shortcut for `window.getComputedStyle(element).propertyName`
|
@@ -118,13 +113,31 @@ function getElementStyle(element, property) {
|
|
118
113
|
// @ts-ignore
|
119
114
|
const setElementStyle = (element, styles) => { ObjectAssign(element.style, styles); };
|
120
115
|
|
116
|
+
/**
|
117
|
+
* Shortcut for `String.toLowerCase()`.
|
118
|
+
*
|
119
|
+
* @param {string} source input string
|
120
|
+
* @returns {string} lowercase output string
|
121
|
+
*/
|
122
|
+
const toLowerCase = (source) => source.toLowerCase();
|
123
|
+
|
121
124
|
/**
|
122
125
|
* A list of explicit default non-color values.
|
123
126
|
*/
|
124
127
|
const nonColors = ['transparent', 'currentColor', 'inherit', 'revert', 'initial'];
|
125
128
|
|
129
|
+
/**
|
130
|
+
* Round colour components, for all formats except HEX.
|
131
|
+
* @param {number} v one of the colour components
|
132
|
+
* @returns {number} the rounded number
|
133
|
+
*/
|
134
|
+
function roundPart(v) {
|
135
|
+
const floor = Math.floor(v);
|
136
|
+
return v - floor < 0.5 ? floor : Math.round(v);
|
137
|
+
}
|
138
|
+
|
126
139
|
// Color supported formats
|
127
|
-
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', '
|
140
|
+
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsv', 'hwb'];
|
128
141
|
|
129
142
|
// Hue angles
|
130
143
|
const ANGLES = 'deg|rad|grad|turn';
|
@@ -146,10 +159,17 @@ const CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`;
|
|
146
159
|
// Add angles to the mix
|
147
160
|
const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
|
148
161
|
|
162
|
+
// Start & end
|
163
|
+
const START_MATCH = '(?:[\\s|\\(\\s|\\s\\(\\s]+)?';
|
164
|
+
const END_MATCH = '(?:[\\s|\\)\\s]+)?';
|
165
|
+
// Components separation
|
166
|
+
const SEP = '(?:[,|\\s]+)';
|
167
|
+
const SEP2 = '(?:[,|\\/\\s]*)?';
|
168
|
+
|
149
169
|
// Actual matching.
|
150
170
|
// Parentheses and commas are optional, but not required.
|
151
171
|
// Whitespace can take the place of commas or opening paren
|
152
|
-
const PERMISSIVE_MATCH =
|
172
|
+
const PERMISSIVE_MATCH = `${START_MATCH}(${CSS_UNIT2})${SEP}(${CSS_UNIT})${SEP}(${CSS_UNIT})${SEP2}(${CSS_UNIT})?${END_MATCH}`;
|
153
173
|
|
154
174
|
const matchers = {
|
155
175
|
CSS_UNIT: new RegExp(CSS_UNIT2),
|
@@ -182,23 +202,22 @@ function isPercentage(n) {
|
|
182
202
|
return `${n}`.includes('%');
|
183
203
|
}
|
184
204
|
|
185
|
-
/**
|
186
|
-
* Check to see if string passed in is an angle
|
187
|
-
* @param {string} n testing string
|
188
|
-
* @returns {boolean} the query result
|
189
|
-
*/
|
190
|
-
function isAngle(n) {
|
191
|
-
return ANGLES.split('|').some((a) => `${n}`.includes(a));
|
192
|
-
}
|
193
|
-
|
194
205
|
/**
|
195
206
|
* Check to see if string passed is a web safe colour.
|
207
|
+
* @see https://stackoverflow.com/a/16994164
|
196
208
|
* @param {string} color a colour name, EG: *red*
|
197
209
|
* @returns {boolean} the query result
|
198
210
|
*/
|
199
211
|
function isColorName(color) {
|
200
|
-
|
201
|
-
|
212
|
+
if (nonColors.includes(color)
|
213
|
+
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
214
|
+
|
215
|
+
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
216
|
+
setElementStyle(documentHead, { color });
|
217
|
+
const computedColor = getElementStyle(documentHead, 'color');
|
218
|
+
setElementStyle(documentHead, { color: '' });
|
219
|
+
return computedColor !== c;
|
220
|
+
});
|
202
221
|
}
|
203
222
|
|
204
223
|
/**
|
@@ -219,15 +238,15 @@ function isValidCSSUnit(color) {
|
|
219
238
|
*/
|
220
239
|
function bound01(N, max) {
|
221
240
|
let n = N;
|
222
|
-
if (isOnePointZero(
|
223
|
-
|
224
|
-
n = max === 360 ? n : Math.min(max, Math.max(0, parseFloat(n)));
|
241
|
+
if (isOnePointZero(N)) n = '100%';
|
225
242
|
|
226
|
-
|
227
|
-
|
243
|
+
const processPercent = isPercentage(n);
|
244
|
+
n = max === 360
|
245
|
+
? parseFloat(n)
|
246
|
+
: Math.min(max, Math.max(0, parseFloat(n)));
|
228
247
|
|
229
248
|
// Automatically convert percentage into number
|
230
|
-
if (
|
249
|
+
if (processPercent) n = (n * max) / 100;
|
231
250
|
|
232
251
|
// Handle floating point rounding errors
|
233
252
|
if (Math.abs(n - max) < 0.000001) {
|
@@ -238,11 +257,11 @@ function bound01(N, max) {
|
|
238
257
|
// If n is a hue given in degrees,
|
239
258
|
// wrap around out-of-range values into [0, 360] range
|
240
259
|
// then convert into [0, 1].
|
241
|
-
n = (n < 0 ? (n % max) + max : n % max) /
|
260
|
+
n = (n < 0 ? (n % max) + max : n % max) / max;
|
242
261
|
} else {
|
243
262
|
// If n not a hue given in degrees
|
244
263
|
// Convert into [0, 1] range if it isn't already.
|
245
|
-
n = (n % max) /
|
264
|
+
n = (n % max) / max;
|
246
265
|
}
|
247
266
|
return n;
|
248
267
|
}
|
@@ -277,7 +296,6 @@ function clamp01(v) {
|
|
277
296
|
* @returns {string}
|
278
297
|
*/
|
279
298
|
function getRGBFromName(name) {
|
280
|
-
const documentHead = getDocumentHead();
|
281
299
|
setElementStyle(documentHead, { color: name });
|
282
300
|
const colorName = getElementStyle(documentHead, 'color');
|
283
301
|
setElementStyle(documentHead, { color: '' });
|
@@ -290,7 +308,7 @@ function getRGBFromName(name) {
|
|
290
308
|
* @returns {string} - the hexadecimal value
|
291
309
|
*/
|
292
310
|
function convertDecimalToHex(d) {
|
293
|
-
return
|
311
|
+
return roundPart(d * 255).toString(16);
|
294
312
|
}
|
295
313
|
|
296
314
|
/**
|
@@ -376,6 +394,36 @@ function hueToRgb(p, q, t) {
|
|
376
394
|
return p;
|
377
395
|
}
|
378
396
|
|
397
|
+
/**
|
398
|
+
* Converts an HSL colour value to RGB.
|
399
|
+
*
|
400
|
+
* @param {number} h Hue Angle [0, 1]
|
401
|
+
* @param {number} s Saturation [0, 1]
|
402
|
+
* @param {number} l Lightness Angle [0, 1]
|
403
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
404
|
+
*/
|
405
|
+
function hslToRgb(h, s, l) {
|
406
|
+
let r = 0;
|
407
|
+
let g = 0;
|
408
|
+
let b = 0;
|
409
|
+
|
410
|
+
if (s === 0) {
|
411
|
+
// achromatic
|
412
|
+
g = l;
|
413
|
+
b = l;
|
414
|
+
r = l;
|
415
|
+
} else {
|
416
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
417
|
+
const p = 2 * l - q;
|
418
|
+
r = hueToRgb(p, q, h + 1 / 3);
|
419
|
+
g = hueToRgb(p, q, h);
|
420
|
+
b = hueToRgb(p, q, h - 1 / 3);
|
421
|
+
}
|
422
|
+
[r, g, b] = [r, g, b].map((x) => x * 255);
|
423
|
+
|
424
|
+
return { r, g, b };
|
425
|
+
}
|
426
|
+
|
379
427
|
/**
|
380
428
|
* Returns an HWB colour object from an RGB colour object.
|
381
429
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
@@ -438,36 +486,6 @@ function hwbToRgb(H, W, B) {
|
|
438
486
|
return { r, g, b };
|
439
487
|
}
|
440
488
|
|
441
|
-
/**
|
442
|
-
* Converts an HSL colour value to RGB.
|
443
|
-
*
|
444
|
-
* @param {number} h Hue Angle [0, 1]
|
445
|
-
* @param {number} s Saturation [0, 1]
|
446
|
-
* @param {number} l Lightness Angle [0, 1]
|
447
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
448
|
-
*/
|
449
|
-
function hslToRgb(h, s, l) {
|
450
|
-
let r = 0;
|
451
|
-
let g = 0;
|
452
|
-
let b = 0;
|
453
|
-
|
454
|
-
if (s === 0) {
|
455
|
-
// achromatic
|
456
|
-
g = l;
|
457
|
-
b = l;
|
458
|
-
r = l;
|
459
|
-
} else {
|
460
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
461
|
-
const p = 2 * l - q;
|
462
|
-
r = hueToRgb(p, q, h + 1 / 3);
|
463
|
-
g = hueToRgb(p, q, h);
|
464
|
-
b = hueToRgb(p, q, h - 1 / 3);
|
465
|
-
}
|
466
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
467
|
-
|
468
|
-
return { r, g, b };
|
469
|
-
}
|
470
|
-
|
471
489
|
/**
|
472
490
|
* Converts an RGB colour value to HSV.
|
473
491
|
*
|
@@ -523,10 +541,11 @@ function hsvToRgb(H, S, V) {
|
|
523
541
|
const q = v * (1 - f * s);
|
524
542
|
const t = v * (1 - (1 - f) * s);
|
525
543
|
const mod = i % 6;
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
544
|
+
let r = [v, q, p, p, t, v][mod];
|
545
|
+
let g = [t, v, v, q, p, p][mod];
|
546
|
+
let b = [p, p, t, v, v, q][mod];
|
547
|
+
[r, g, b] = [r, g, b].map((n) => n * 255);
|
548
|
+
return { r, g, b };
|
530
549
|
}
|
531
550
|
|
532
551
|
/**
|
@@ -542,15 +561,15 @@ function hsvToRgb(H, S, V) {
|
|
542
561
|
*/
|
543
562
|
function rgbToHex(r, g, b, allow3Char) {
|
544
563
|
const hex = [
|
545
|
-
pad2(
|
546
|
-
pad2(
|
547
|
-
pad2(
|
564
|
+
pad2(roundPart(r).toString(16)),
|
565
|
+
pad2(roundPart(g).toString(16)),
|
566
|
+
pad2(roundPart(b).toString(16)),
|
548
567
|
];
|
549
568
|
|
550
569
|
// Return a 3 character hex if possible
|
551
570
|
if (allow3Char && hex[0].charAt(0) === hex[0].charAt(1)
|
552
571
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
553
|
-
|
572
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)) {
|
554
573
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
|
555
574
|
}
|
556
575
|
|
@@ -569,48 +588,33 @@ function rgbToHex(r, g, b, allow3Char) {
|
|
569
588
|
*/
|
570
589
|
function rgbaToHex(r, g, b, a, allow4Char) {
|
571
590
|
const hex = [
|
572
|
-
pad2(
|
573
|
-
pad2(
|
574
|
-
pad2(
|
591
|
+
pad2(roundPart(r).toString(16)),
|
592
|
+
pad2(roundPart(g).toString(16)),
|
593
|
+
pad2(roundPart(b).toString(16)),
|
575
594
|
pad2(convertDecimalToHex(a)),
|
576
595
|
];
|
577
596
|
|
578
597
|
// Return a 4 character hex if possible
|
579
598
|
if (allow4Char && hex[0].charAt(0) === hex[0].charAt(1)
|
580
599
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
581
|
-
|
582
|
-
|
600
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)
|
601
|
+
&& hex[3].charAt(0) === hex[3].charAt(1)) {
|
583
602
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
|
584
603
|
}
|
585
604
|
return hex.join('');
|
586
605
|
}
|
587
606
|
|
588
|
-
/**
|
589
|
-
* Returns a colour object corresponding to a given number.
|
590
|
-
* @param {number} color input number
|
591
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
592
|
-
*/
|
593
|
-
function numberInputToObject(color) {
|
594
|
-
/* eslint-disable no-bitwise */
|
595
|
-
return {
|
596
|
-
r: color >> 16,
|
597
|
-
g: (color & 0xff00) >> 8,
|
598
|
-
b: color & 0xff,
|
599
|
-
};
|
600
|
-
/* eslint-enable no-bitwise */
|
601
|
-
}
|
602
|
-
|
603
607
|
/**
|
604
608
|
* Permissive string parsing. Take in a number of formats, and output an object
|
605
609
|
* based on detected format. Returns {r,g,b} or {h,s,l} or {h,s,v}
|
606
610
|
* @param {string} input colour value in any format
|
607
|
-
* @returns {Record<string, (number | string)> | false} an object matching the RegExp
|
611
|
+
* @returns {Record<string, (number | string | boolean)> | false} an object matching the RegExp
|
608
612
|
*/
|
609
613
|
function stringInputToObject(input) {
|
610
|
-
let color = input.trim()
|
614
|
+
let color = toLowerCase(input.trim());
|
611
615
|
if (color.length === 0) {
|
612
616
|
return {
|
613
|
-
r: 0, g: 0, b: 0, a:
|
617
|
+
r: 0, g: 0, b: 0, a: 1,
|
614
618
|
};
|
615
619
|
}
|
616
620
|
let named = false;
|
@@ -618,11 +622,9 @@ function stringInputToObject(input) {
|
|
618
622
|
color = getRGBFromName(color);
|
619
623
|
named = true;
|
620
624
|
} else if (nonColors.includes(color)) {
|
621
|
-
const
|
622
|
-
const rgb = isTransparent ? 0 : 255;
|
623
|
-
const a = isTransparent ? 0 : 1;
|
625
|
+
const a = color === 'transparent' ? 0 : 1;
|
624
626
|
return {
|
625
|
-
r:
|
627
|
+
r: 0, g: 0, b: 0, a, format: 'rgb', ok: true,
|
626
628
|
};
|
627
629
|
}
|
628
630
|
|
@@ -662,7 +664,6 @@ function stringInputToObject(input) {
|
|
662
664
|
g: parseIntFromHex(m2),
|
663
665
|
b: parseIntFromHex(m3),
|
664
666
|
a: convertHexToDecimal(m4),
|
665
|
-
// format: named ? 'rgb' : 'hex8',
|
666
667
|
format: named ? 'rgb' : 'hex',
|
667
668
|
};
|
668
669
|
}
|
@@ -726,6 +727,7 @@ function stringInputToObject(input) {
|
|
726
727
|
function inputToRGB(input) {
|
727
728
|
let rgb = { r: 0, g: 0, b: 0 };
|
728
729
|
let color = input;
|
730
|
+
/** @type {string | number} */
|
729
731
|
let a = 1;
|
730
732
|
let s = null;
|
731
733
|
let v = null;
|
@@ -733,8 +735,11 @@ function inputToRGB(input) {
|
|
733
735
|
let w = null;
|
734
736
|
let b = null;
|
735
737
|
let h = null;
|
738
|
+
let r = null;
|
739
|
+
let g = null;
|
736
740
|
let ok = false;
|
737
|
-
|
741
|
+
const inputFormat = typeof color === 'object' && color.format;
|
742
|
+
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
738
743
|
|
739
744
|
if (typeof input === 'string') {
|
740
745
|
// @ts-ignore -- this now is converted to object
|
@@ -743,7 +748,10 @@ function inputToRGB(input) {
|
|
743
748
|
}
|
744
749
|
if (typeof color === 'object') {
|
745
750
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
746
|
-
|
751
|
+
({ r, g, b } = color);
|
752
|
+
// RGB values now are all in [0, 255] range
|
753
|
+
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255) * 255);
|
754
|
+
rgb = { r, g, b };
|
747
755
|
ok = true;
|
748
756
|
format = 'rgb';
|
749
757
|
} else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
@@ -772,14 +780,17 @@ function inputToRGB(input) {
|
|
772
780
|
format = 'hwb';
|
773
781
|
}
|
774
782
|
if (isValidCSSUnit(color.a)) {
|
775
|
-
a = color.a;
|
776
|
-
a = isPercentage(`${a}`) ? bound01(a, 100) : a;
|
783
|
+
a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
|
784
|
+
a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
|
777
785
|
}
|
778
786
|
}
|
787
|
+
if (typeof color === 'undefined') {
|
788
|
+
ok = true;
|
789
|
+
}
|
779
790
|
|
780
791
|
return {
|
781
|
-
ok,
|
782
|
-
format
|
792
|
+
ok,
|
793
|
+
format,
|
783
794
|
r: Math.min(255, Math.max(rgb.r, 0)),
|
784
795
|
g: Math.min(255, Math.max(rgb.g, 0)),
|
785
796
|
b: Math.min(255, Math.max(rgb.b, 0)),
|
@@ -808,7 +819,8 @@ class Color {
|
|
808
819
|
color = inputToRGB(color);
|
809
820
|
}
|
810
821
|
if (typeof color === 'number') {
|
811
|
-
|
822
|
+
const len = `${color}`.length;
|
823
|
+
color = `#${(len === 2 ? '0' : '00')}${color}`;
|
812
824
|
}
|
813
825
|
const {
|
814
826
|
r, g, b, a, ok, format,
|
@@ -818,7 +830,7 @@ class Color {
|
|
818
830
|
const self = this;
|
819
831
|
|
820
832
|
/** @type {CP.ColorInput} */
|
821
|
-
self.originalInput =
|
833
|
+
self.originalInput = input;
|
822
834
|
/** @type {number} */
|
823
835
|
self.r = r;
|
824
836
|
/** @type {number} */
|
@@ -831,14 +843,6 @@ class Color {
|
|
831
843
|
self.ok = ok;
|
832
844
|
/** @type {CP.ColorFormats} */
|
833
845
|
self.format = configFormat || format;
|
834
|
-
|
835
|
-
// Don't let the range of [0,255] come back in [0,1].
|
836
|
-
// Potentially lose a little bit of precision here, but will fix issues where
|
837
|
-
// .5 gets interpreted as half of the total, instead of half of 1
|
838
|
-
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
|
839
|
-
if (r < 1) self.r = Math.round(r);
|
840
|
-
if (g < 1) self.g = Math.round(g);
|
841
|
-
if (b < 1) self.b = Math.round(b);
|
842
846
|
}
|
843
847
|
|
844
848
|
/**
|
@@ -854,7 +858,7 @@ class Color {
|
|
854
858
|
* @returns {boolean} the query result
|
855
859
|
*/
|
856
860
|
get isDark() {
|
857
|
-
return this.brightness <
|
861
|
+
return this.brightness < 120;
|
858
862
|
}
|
859
863
|
|
860
864
|
/**
|
@@ -906,13 +910,9 @@ class Color {
|
|
906
910
|
const {
|
907
911
|
r, g, b, a,
|
908
912
|
} = this;
|
909
|
-
const [R, G, B] = [r, g, b].map((x) => Math.round(x));
|
910
913
|
|
911
914
|
return {
|
912
|
-
r:
|
913
|
-
g: G,
|
914
|
-
b: B,
|
915
|
-
a: Math.round(a * 100) / 100,
|
915
|
+
r, g, b, a: roundPart(a * 100) / 100,
|
916
916
|
};
|
917
917
|
}
|
918
918
|
|
@@ -926,10 +926,11 @@ class Color {
|
|
926
926
|
const {
|
927
927
|
r, g, b, a,
|
928
928
|
} = this.toRgb();
|
929
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
929
930
|
|
930
931
|
return a === 1
|
931
|
-
? `rgb(${
|
932
|
-
: `rgba(${
|
932
|
+
? `rgb(${R}, ${G}, ${B})`
|
933
|
+
: `rgba(${R}, ${G}, ${B}, ${a})`;
|
933
934
|
}
|
934
935
|
|
935
936
|
/**
|
@@ -942,9 +943,10 @@ class Color {
|
|
942
943
|
const {
|
943
944
|
r, g, b, a,
|
944
945
|
} = this.toRgb();
|
945
|
-
const
|
946
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
947
|
+
const A = a === 1 ? '' : ` / ${roundPart(a * 100)}%`;
|
946
948
|
|
947
|
-
return `rgb(${
|
949
|
+
return `rgb(${R} ${G} ${B}${A})`;
|
948
950
|
}
|
949
951
|
|
950
952
|
/**
|
@@ -1037,10 +1039,10 @@ class Color {
|
|
1037
1039
|
let {
|
1038
1040
|
h, s, l, a,
|
1039
1041
|
} = this.toHsl();
|
1040
|
-
h =
|
1041
|
-
s =
|
1042
|
-
l =
|
1043
|
-
a =
|
1042
|
+
h = roundPart(h * 360);
|
1043
|
+
s = roundPart(s * 100);
|
1044
|
+
l = roundPart(l * 100);
|
1045
|
+
a = roundPart(a * 100) / 100;
|
1044
1046
|
|
1045
1047
|
return a === 1
|
1046
1048
|
? `hsl(${h}, ${s}%, ${l}%)`
|
@@ -1057,11 +1059,11 @@ class Color {
|
|
1057
1059
|
let {
|
1058
1060
|
h, s, l, a,
|
1059
1061
|
} = this.toHsl();
|
1060
|
-
h =
|
1061
|
-
s =
|
1062
|
-
l =
|
1063
|
-
a =
|
1064
|
-
const A = a < 100 ? ` / ${
|
1062
|
+
h = roundPart(h * 360);
|
1063
|
+
s = roundPart(s * 100);
|
1064
|
+
l = roundPart(l * 100);
|
1065
|
+
a = roundPart(a * 100);
|
1066
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
1065
1067
|
|
1066
1068
|
return `hsl(${h}deg ${s}% ${l}%${A})`;
|
1067
1069
|
}
|
@@ -1088,11 +1090,11 @@ class Color {
|
|
1088
1090
|
let {
|
1089
1091
|
h, w, b, a,
|
1090
1092
|
} = this.toHwb();
|
1091
|
-
h =
|
1092
|
-
w =
|
1093
|
-
b =
|
1094
|
-
a =
|
1095
|
-
const A = a < 100 ? ` / ${
|
1093
|
+
h = roundPart(h * 360);
|
1094
|
+
w = roundPart(w * 100);
|
1095
|
+
b = roundPart(b * 100);
|
1096
|
+
a = roundPart(a * 100);
|
1097
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
1096
1098
|
|
1097
1099
|
return `hwb(${h}deg ${w}% ${b}%${A})`;
|
1098
1100
|
}
|
@@ -1218,6 +1220,7 @@ ObjectAssign(Color, {
|
|
1218
1220
|
isOnePointZero,
|
1219
1221
|
isPercentage,
|
1220
1222
|
isValidCSSUnit,
|
1223
|
+
isColorName,
|
1221
1224
|
pad2,
|
1222
1225
|
clamp01,
|
1223
1226
|
bound01,
|
@@ -1235,9 +1238,11 @@ ObjectAssign(Color, {
|
|
1235
1238
|
hueToRgb,
|
1236
1239
|
hwbToRgb,
|
1237
1240
|
parseIntFromHex,
|
1238
|
-
numberInputToObject,
|
1239
1241
|
stringInputToObject,
|
1240
1242
|
inputToRGB,
|
1243
|
+
roundPart,
|
1244
|
+
getElementStyle,
|
1245
|
+
setElementStyle,
|
1241
1246
|
ObjectAssign,
|
1242
1247
|
});
|
1243
1248
|
|
@@ -1367,24 +1372,6 @@ const ariaValueText = 'aria-valuetext';
|
|
1367
1372
|
*/
|
1368
1373
|
const ariaValueNow = 'aria-valuenow';
|
1369
1374
|
|
1370
|
-
/**
|
1371
|
-
* A global namespace for aria-haspopup.
|
1372
|
-
* @type {string}
|
1373
|
-
*/
|
1374
|
-
const ariaHasPopup = 'aria-haspopup';
|
1375
|
-
|
1376
|
-
/**
|
1377
|
-
* A global namespace for aria-hidden.
|
1378
|
-
* @type {string}
|
1379
|
-
*/
|
1380
|
-
const ariaHidden = 'aria-hidden';
|
1381
|
-
|
1382
|
-
/**
|
1383
|
-
* A global namespace for aria-labelledby.
|
1384
|
-
* @type {string}
|
1385
|
-
*/
|
1386
|
-
const ariaLabelledBy = 'aria-labelledby';
|
1387
|
-
|
1388
1375
|
/**
|
1389
1376
|
* A global namespace for `ArrowDown` key.
|
1390
1377
|
* @type {string} e.which = 40 equivalent
|
@@ -1511,37 +1498,6 @@ const resizeEvent = 'resize';
|
|
1511
1498
|
*/
|
1512
1499
|
const focusoutEvent = 'focusout';
|
1513
1500
|
|
1514
|
-
// @ts-ignore
|
1515
|
-
const { userAgentData: uaDATA } = navigator;
|
1516
|
-
|
1517
|
-
/**
|
1518
|
-
* A global namespace for `userAgentData` object.
|
1519
|
-
*/
|
1520
|
-
const userAgentData = uaDATA;
|
1521
|
-
|
1522
|
-
const { userAgent: userAgentString } = navigator;
|
1523
|
-
|
1524
|
-
/**
|
1525
|
-
* A global namespace for `navigator.userAgent` string.
|
1526
|
-
*/
|
1527
|
-
const userAgent = userAgentString;
|
1528
|
-
|
1529
|
-
const mobileBrands = /iPhone|iPad|iPod|Android/i;
|
1530
|
-
let isMobileCheck = false;
|
1531
|
-
|
1532
|
-
if (userAgentData) {
|
1533
|
-
isMobileCheck = userAgentData.brands
|
1534
|
-
.some((/** @type {Record<String, any>} */x) => mobileBrands.test(x.brand));
|
1535
|
-
} else {
|
1536
|
-
isMobileCheck = mobileBrands.test(userAgent);
|
1537
|
-
}
|
1538
|
-
|
1539
|
-
/**
|
1540
|
-
* A global `boolean` for mobile detection.
|
1541
|
-
* @type {boolean}
|
1542
|
-
*/
|
1543
|
-
const isMobile = isMobileCheck;
|
1544
|
-
|
1545
1501
|
/**
|
1546
1502
|
* Returns the `document.documentElement` or the `<html>` element.
|
1547
1503
|
*
|
@@ -1726,30 +1682,6 @@ function getElementsByClassName(selector, parent) {
|
|
1726
1682
|
return lookUp.getElementsByClassName(selector);
|
1727
1683
|
}
|
1728
1684
|
|
1729
|
-
/**
|
1730
|
-
* This is a shortie for `document.createElementNS` method
|
1731
|
-
* which allows you to create a new `HTMLElement` for a given `tagName`
|
1732
|
-
* or based on an object with specific non-readonly attributes:
|
1733
|
-
* `id`, `className`, `textContent`, `style`, etc.
|
1734
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
1735
|
-
*
|
1736
|
-
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
1737
|
-
* @param {Record<string, string> | string} param `tagName` or object
|
1738
|
-
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
1739
|
-
*/
|
1740
|
-
function createElementNS(namespace, param) {
|
1741
|
-
if (typeof param === 'string') {
|
1742
|
-
return getDocument().createElementNS(namespace, param);
|
1743
|
-
}
|
1744
|
-
|
1745
|
-
const { tagName } = param;
|
1746
|
-
const attr = { ...param };
|
1747
|
-
const newElement = createElementNS(namespace, tagName);
|
1748
|
-
delete attr.tagName;
|
1749
|
-
ObjectAssign(newElement, attr);
|
1750
|
-
return newElement;
|
1751
|
-
}
|
1752
|
-
|
1753
1685
|
/**
|
1754
1686
|
* Shortcut for the `Element.dispatchEvent(Event)` method.
|
1755
1687
|
*
|
@@ -1873,14 +1805,6 @@ function normalizeValue(value) {
|
|
1873
1805
|
*/
|
1874
1806
|
const ObjectKeys = (obj) => Object.keys(obj);
|
1875
1807
|
|
1876
|
-
/**
|
1877
|
-
* Shortcut for `String.toLowerCase()`.
|
1878
|
-
*
|
1879
|
-
* @param {string} source input string
|
1880
|
-
* @returns {string} lowercase output string
|
1881
|
-
*/
|
1882
|
-
const toLowerCase = (source) => source.toLowerCase();
|
1883
|
-
|
1884
1808
|
/**
|
1885
1809
|
* Utility to normalize component options.
|
1886
1810
|
*
|
@@ -1984,6 +1908,80 @@ function removeClass(element, classNAME) {
|
|
1984
1908
|
*/
|
1985
1909
|
const removeAttribute = (element, attribute) => element.removeAttribute(attribute);
|
1986
1910
|
|
1911
|
+
/**
|
1912
|
+
* @class
|
1913
|
+
* Returns a color palette with a given set of parameters.
|
1914
|
+
* @example
|
1915
|
+
* new ColorPalette(0, 12, 10);
|
1916
|
+
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: Array<Color> }
|
1917
|
+
*/
|
1918
|
+
class ColorPalette {
|
1919
|
+
/**
|
1920
|
+
* The `hue` parameter is optional, which would be set to 0.
|
1921
|
+
* @param {number[]} args represeinting hue, hueSteps, lightSteps
|
1922
|
+
* * `args.hue` the starting Hue [0, 360]
|
1923
|
+
* * `args.hueSteps` Hue Steps Count [5, 24]
|
1924
|
+
* * `args.lightSteps` Lightness Steps Count [5, 12]
|
1925
|
+
*/
|
1926
|
+
constructor(...args) {
|
1927
|
+
let hue = 0;
|
1928
|
+
let hueSteps = 12;
|
1929
|
+
let lightSteps = 10;
|
1930
|
+
let lightnessArray = [0.5];
|
1931
|
+
|
1932
|
+
if (args.length === 3) {
|
1933
|
+
[hue, hueSteps, lightSteps] = args;
|
1934
|
+
} else if (args.length === 2) {
|
1935
|
+
[hueSteps, lightSteps] = args;
|
1936
|
+
if ([hueSteps, lightSteps].some((n) => n < 1)) {
|
1937
|
+
throw TypeError('ColorPalette: when 2 arguments used, both must be larger than 0.');
|
1938
|
+
}
|
1939
|
+
} else {
|
1940
|
+
throw TypeError('ColorPalette requires minimum 2 arguments');
|
1941
|
+
}
|
1942
|
+
|
1943
|
+
/** @type {Color[]} */
|
1944
|
+
const colors = [];
|
1945
|
+
|
1946
|
+
const hueStep = 360 / hueSteps;
|
1947
|
+
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
1948
|
+
const estimatedStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
1949
|
+
|
1950
|
+
let lightStep = 0.25;
|
1951
|
+
lightStep = [4, 5].includes(lightSteps) ? 0.2 : lightStep;
|
1952
|
+
lightStep = [6, 7].includes(lightSteps) ? 0.15 : lightStep;
|
1953
|
+
lightStep = [8, 9].includes(lightSteps) ? 0.11 : lightStep;
|
1954
|
+
lightStep = [10, 11].includes(lightSteps) ? 0.09 : lightStep;
|
1955
|
+
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
1956
|
+
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
1957
|
+
|
1958
|
+
// light tints
|
1959
|
+
for (let i = 1; i < half + 1; i += 1) {
|
1960
|
+
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i))];
|
1961
|
+
}
|
1962
|
+
|
1963
|
+
// dark tints
|
1964
|
+
for (let i = 1; i < lightSteps - half; i += 1) {
|
1965
|
+
lightnessArray = [(0.5 - lightStep * (i)), ...lightnessArray];
|
1966
|
+
}
|
1967
|
+
|
1968
|
+
// feed `colors` Array
|
1969
|
+
for (let i = 0; i < hueSteps; i += 1) {
|
1970
|
+
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
1971
|
+
lightnessArray.forEach((l) => {
|
1972
|
+
colors.push(new Color({ h: currentHue, s: 1, l }));
|
1973
|
+
});
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
this.hue = hue;
|
1977
|
+
this.hueSteps = hueSteps;
|
1978
|
+
this.lightSteps = lightSteps;
|
1979
|
+
this.colors = colors;
|
1980
|
+
}
|
1981
|
+
}
|
1982
|
+
|
1983
|
+
ObjectAssign(ColorPalette, { Color });
|
1984
|
+
|
1987
1985
|
/** @type {Record<string, string>} */
|
1988
1986
|
const colorPickerLabels = {
|
1989
1987
|
pickerLabel: 'Colour Picker',
|
@@ -2011,6 +2009,22 @@ const colorPickerLabels = {
|
|
2011
2009
|
*/
|
2012
2010
|
const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold', 'olive', 'yellow', 'lime', 'green', 'teal', 'cyan', 'blue', 'violet', 'magenta', 'pink'];
|
2013
2011
|
|
2012
|
+
const tabIndex = 'tabindex';
|
2013
|
+
|
2014
|
+
/**
|
2015
|
+
* Check if a string is valid JSON string.
|
2016
|
+
* @param {string} str the string input
|
2017
|
+
* @returns {boolean} the query result
|
2018
|
+
*/
|
2019
|
+
function isValidJSON(str) {
|
2020
|
+
try {
|
2021
|
+
JSON.parse(str);
|
2022
|
+
} catch (e) {
|
2023
|
+
return false;
|
2024
|
+
}
|
2025
|
+
return true;
|
2026
|
+
}
|
2027
|
+
|
2014
2028
|
/**
|
2015
2029
|
* Shortcut for `String.toUpperCase()`.
|
2016
2030
|
*
|
@@ -2019,6 +2033,48 @@ const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold',
|
|
2019
2033
|
*/
|
2020
2034
|
const toUpperCase = (source) => source.toUpperCase();
|
2021
2035
|
|
2036
|
+
/**
|
2037
|
+
* A global namespace for aria-haspopup.
|
2038
|
+
* @type {string}
|
2039
|
+
*/
|
2040
|
+
const ariaHasPopup = 'aria-haspopup';
|
2041
|
+
|
2042
|
+
/**
|
2043
|
+
* A global namespace for aria-hidden.
|
2044
|
+
* @type {string}
|
2045
|
+
*/
|
2046
|
+
const ariaHidden = 'aria-hidden';
|
2047
|
+
|
2048
|
+
/**
|
2049
|
+
* A global namespace for aria-labelledby.
|
2050
|
+
* @type {string}
|
2051
|
+
*/
|
2052
|
+
const ariaLabelledBy = 'aria-labelledby';
|
2053
|
+
|
2054
|
+
/**
|
2055
|
+
* This is a shortie for `document.createElementNS` method
|
2056
|
+
* which allows you to create a new `HTMLElement` for a given `tagName`
|
2057
|
+
* or based on an object with specific non-readonly attributes:
|
2058
|
+
* `id`, `className`, `textContent`, `style`, etc.
|
2059
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
2060
|
+
*
|
2061
|
+
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
2062
|
+
* @param {Record<string, string> | string} param `tagName` or object
|
2063
|
+
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
2064
|
+
*/
|
2065
|
+
function createElementNS(namespace, param) {
|
2066
|
+
if (typeof param === 'string') {
|
2067
|
+
return getDocument().createElementNS(namespace, param);
|
2068
|
+
}
|
2069
|
+
|
2070
|
+
const { tagName } = param;
|
2071
|
+
const attr = { ...param };
|
2072
|
+
const newElement = createElementNS(namespace, tagName);
|
2073
|
+
delete attr.tagName;
|
2074
|
+
ObjectAssign(newElement, attr);
|
2075
|
+
return newElement;
|
2076
|
+
}
|
2077
|
+
|
2022
2078
|
const vHidden = 'v-hidden';
|
2023
2079
|
|
2024
2080
|
/**
|
@@ -2075,7 +2131,6 @@ function getColorForm(self) {
|
|
2075
2131
|
max,
|
2076
2132
|
step,
|
2077
2133
|
});
|
2078
|
-
// }
|
2079
2134
|
colorForm.append(cInputLabel, cInput);
|
2080
2135
|
});
|
2081
2136
|
return colorForm;
|
@@ -2164,10 +2219,8 @@ function getColorControls(self) {
|
|
2164
2219
|
const {
|
2165
2220
|
i, c, l, min, max,
|
2166
2221
|
} = template;
|
2167
|
-
// const hidden = i === 2 && format === 'hwb' ? ' v-hidden' : '';
|
2168
2222
|
const control = createElement({
|
2169
2223
|
tagName: 'div',
|
2170
|
-
// className: `color-control${hidden}`,
|
2171
2224
|
className: 'color-control',
|
2172
2225
|
});
|
2173
2226
|
setAttribute(control, 'role', 'presentation');
|
@@ -2187,7 +2240,7 @@ function getColorControls(self) {
|
|
2187
2240
|
|
2188
2241
|
setAttribute(knob, ariaLabel, l);
|
2189
2242
|
setAttribute(knob, 'role', 'slider');
|
2190
|
-
setAttribute(knob,
|
2243
|
+
setAttribute(knob, tabIndex, '0');
|
2191
2244
|
setAttribute(knob, ariaValueMin, `${min}`);
|
2192
2245
|
setAttribute(knob, ariaValueMax, `${max}`);
|
2193
2246
|
control.append(knob);
|
@@ -2198,64 +2251,14 @@ function getColorControls(self) {
|
|
2198
2251
|
}
|
2199
2252
|
|
2200
2253
|
/**
|
2201
|
-
*
|
2202
|
-
*
|
2203
|
-
* @
|
2204
|
-
* new ColorPalette(0, 12, 10);
|
2205
|
-
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: array }
|
2254
|
+
* Helps setting CSS variables to the color-menu.
|
2255
|
+
* @param {HTMLElement} element
|
2256
|
+
* @param {Record<string,any>} props
|
2206
2257
|
*/
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
* * `args.hue` the starting Hue [0, 360]
|
2212
|
-
* * `args.hueSteps` Hue Steps Count [5, 13]
|
2213
|
-
* * `args.lightSteps` Lightness Steps Count [8, 10]
|
2214
|
-
*/
|
2215
|
-
constructor(...args) {
|
2216
|
-
let hue = 0;
|
2217
|
-
let hueSteps = 12;
|
2218
|
-
let lightSteps = 10;
|
2219
|
-
let lightnessArray = [0.5];
|
2220
|
-
|
2221
|
-
if (args.length === 3) {
|
2222
|
-
[hue, hueSteps, lightSteps] = args;
|
2223
|
-
} else if (args.length === 2) {
|
2224
|
-
[hueSteps, lightSteps] = args;
|
2225
|
-
} else {
|
2226
|
-
throw TypeError('The ColorPalette requires minimum 2 arguments');
|
2227
|
-
}
|
2228
|
-
|
2229
|
-
/** @type {string[]} */
|
2230
|
-
const colors = [];
|
2231
|
-
|
2232
|
-
const hueStep = 360 / hueSteps;
|
2233
|
-
const lightStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
2234
|
-
const half = Math.round((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
2235
|
-
|
2236
|
-
// light tints
|
2237
|
-
for (let i = 0; i < half; i += 1) {
|
2238
|
-
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i + 1))];
|
2239
|
-
}
|
2240
|
-
|
2241
|
-
// dark tints
|
2242
|
-
for (let i = 0; i < lightSteps - half - 1; i += 1) {
|
2243
|
-
lightnessArray = [(0.5 - lightStep * (i + 1)), ...lightnessArray];
|
2244
|
-
}
|
2245
|
-
|
2246
|
-
// feed `colors` Array
|
2247
|
-
for (let i = 0; i < hueSteps; i += 1) {
|
2248
|
-
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
2249
|
-
lightnessArray.forEach((l) => {
|
2250
|
-
colors.push(new Color({ h: currentHue, s: 1, l }).toHexString());
|
2251
|
-
});
|
2252
|
-
}
|
2253
|
-
|
2254
|
-
this.hue = hue;
|
2255
|
-
this.hueSteps = hueSteps;
|
2256
|
-
this.lightSteps = lightSteps;
|
2257
|
-
this.colors = colors;
|
2258
|
-
}
|
2258
|
+
function setCSSProperties(element, props) {
|
2259
|
+
ObjectKeys(props).forEach((prop) => {
|
2260
|
+
element.style.setProperty(prop, props[prop]);
|
2261
|
+
});
|
2259
2262
|
}
|
2260
2263
|
|
2261
2264
|
/**
|
@@ -2275,68 +2278,64 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2275
2278
|
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2276
2279
|
const colorsCount = colorsArray.length;
|
2277
2280
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2278
|
-
|
2279
|
-
|| Math.max(...[5, 6, 7, 8, 9, 10].filter((x) => colorsCount > (x * 2) && !(colorsCount % x)));
|
2280
|
-
fit = Number.isFinite(fit) ? fit : 5;
|
2281
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount > x * 2 && !(colorsCount % x)) || 5;
|
2281
2282
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2282
|
-
let rowCountHover =
|
2283
|
-
rowCountHover = isMultiLine && colorsCount
|
2284
|
-
rowCountHover = colorsCount >=
|
2285
|
-
rowCountHover = colorsCount >=
|
2286
|
-
|
2287
|
-
const
|
2288
|
-
const isScrollable = isMultiLine && colorsCount > rowCountHover * fit;
|
2283
|
+
let rowCountHover = 2;
|
2284
|
+
rowCountHover = isMultiLine && colorsCount >= fit * 2 ? 3 : rowCountHover;
|
2285
|
+
rowCountHover = colorsCount >= fit * 3 ? 4 : rowCountHover;
|
2286
|
+
rowCountHover = colorsCount >= fit * 4 ? 5 : rowCountHover;
|
2287
|
+
const rowCount = rowCountHover - (colorsCount < fit * 3 ? 1 : 2);
|
2288
|
+
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2289
2289
|
let finalClass = menuClass;
|
2290
2290
|
finalClass += isScrollable ? ' scrollable' : '';
|
2291
2291
|
finalClass += isMultiLine ? ' multiline' : '';
|
2292
2292
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2293
2293
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2294
|
-
optionSize =
|
2294
|
+
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2295
2295
|
const menuHeight = `${(rowCount || 1) * optionSize}rem`;
|
2296
2296
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2297
|
+
/** @type {HTMLUListElement} */
|
2298
|
+
// @ts-ignore -- <UL> is an `HTMLElement`
|
2300
2299
|
const menu = createElement({
|
2301
2300
|
tagName: 'ul',
|
2302
2301
|
className: finalClass,
|
2303
2302
|
});
|
2304
2303
|
setAttribute(menu, 'role', 'listbox');
|
2305
|
-
setAttribute(menu, ariaLabel,
|
2306
|
-
|
2307
|
-
if (
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
};
|
2316
|
-
setElementStyle(menu, menuStyle);
|
2304
|
+
setAttribute(menu, ariaLabel, menuLabel);
|
2305
|
+
|
2306
|
+
if (isScrollable) {
|
2307
|
+
setCSSProperties(menu, {
|
2308
|
+
'--grid-item-size': `${optionSize}rem`,
|
2309
|
+
'--grid-fit': fit,
|
2310
|
+
'--grid-gap': gap,
|
2311
|
+
'--grid-height': menuHeight,
|
2312
|
+
'--grid-hover-height': menuHeightHover,
|
2313
|
+
});
|
2317
2314
|
}
|
2318
2315
|
|
2319
2316
|
colorsArray.forEach((x) => {
|
2320
|
-
|
2321
|
-
|
2322
|
-
|
2317
|
+
let [value, label] = typeof x === 'string' ? x.trim().split(':') : [];
|
2318
|
+
if (x instanceof Color) {
|
2319
|
+
value = x.toHexString();
|
2320
|
+
label = value;
|
2321
|
+
}
|
2322
|
+
const color = new Color(x instanceof Color ? x : value, format);
|
2323
|
+
const isActive = color.toString() === getAttribute(input, 'value');
|
2323
2324
|
const active = isActive ? ' active' : '';
|
2324
2325
|
|
2325
2326
|
const option = createElement({
|
2326
2327
|
tagName: 'li',
|
2327
2328
|
className: `color-option${active}`,
|
2328
|
-
innerText: `${label ||
|
2329
|
+
innerText: `${label || value}`,
|
2329
2330
|
});
|
2330
2331
|
|
2331
|
-
setAttribute(option,
|
2332
|
+
setAttribute(option, tabIndex, '0');
|
2332
2333
|
setAttribute(option, 'data-value', `${value}`);
|
2333
2334
|
setAttribute(option, 'role', 'option');
|
2334
2335
|
setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
|
2335
2336
|
|
2336
2337
|
if (isOptionsMenu) {
|
2337
|
-
setElementStyle(option, {
|
2338
|
-
width: `${optionSize}rem`, height: `${optionSize}rem`, backgroundColor: x,
|
2339
|
-
});
|
2338
|
+
setElementStyle(option, { backgroundColor: value });
|
2340
2339
|
}
|
2341
2340
|
|
2342
2341
|
menu.append(option);
|
@@ -2345,55 +2344,10 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2345
2344
|
}
|
2346
2345
|
|
2347
2346
|
/**
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
function isValidJSON(str) {
|
2353
|
-
try {
|
2354
|
-
JSON.parse(str);
|
2355
|
-
} catch (e) {
|
2356
|
-
return false;
|
2357
|
-
}
|
2358
|
-
return true;
|
2359
|
-
}
|
2360
|
-
|
2361
|
-
var version = "0.0.1alpha2";
|
2362
|
-
|
2363
|
-
// @ts-ignore
|
2364
|
-
|
2365
|
-
const Version = version;
|
2366
|
-
|
2367
|
-
// ColorPicker GC
|
2368
|
-
// ==============
|
2369
|
-
const colorPickerString = 'color-picker';
|
2370
|
-
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2371
|
-
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2372
|
-
const colorPickerDefaults = {
|
2373
|
-
componentLabels: colorPickerLabels,
|
2374
|
-
colorLabels: colorNames,
|
2375
|
-
format: 'rgb',
|
2376
|
-
colorPresets: undefined,
|
2377
|
-
colorKeywords: nonColors,
|
2378
|
-
};
|
2379
|
-
|
2380
|
-
// ColorPicker Static Methods
|
2381
|
-
// ==========================
|
2382
|
-
|
2383
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2384
|
-
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2385
|
-
|
2386
|
-
/** @type {CP.InitCallback<ColorPicker>} */
|
2387
|
-
const initColorPicker = (element) => new ColorPicker(element);
|
2388
|
-
|
2389
|
-
// ColorPicker Private Methods
|
2390
|
-
// ===========================
|
2391
|
-
|
2392
|
-
/**
|
2393
|
-
* Generate HTML markup and update instance properties.
|
2394
|
-
* @param {ColorPicker} self
|
2395
|
-
*/
|
2396
|
-
function initCallback(self) {
|
2347
|
+
* Generate HTML markup and update instance properties.
|
2348
|
+
* @param {CP.ColorPicker} self
|
2349
|
+
*/
|
2350
|
+
function setMarkup(self) {
|
2397
2351
|
const {
|
2398
2352
|
input, parent, format, id, componentLabels, colorKeywords, colorPresets,
|
2399
2353
|
} = self;
|
@@ -2408,9 +2362,7 @@ function initCallback(self) {
|
|
2408
2362
|
self.color = new Color(color, format);
|
2409
2363
|
|
2410
2364
|
// set initial controls dimensions
|
2411
|
-
|
2412
|
-
const dropClass = isMobile ? ' mobile' : '';
|
2413
|
-
const formatString = format === 'hex' ? hexLabel : format.toUpperCase();
|
2365
|
+
const formatString = format === 'hex' ? hexLabel : toUpperCase(format);
|
2414
2366
|
|
2415
2367
|
const pickerBtn = createElement({
|
2416
2368
|
id: `picker-btn-${id}`,
|
@@ -2427,7 +2379,7 @@ function initCallback(self) {
|
|
2427
2379
|
|
2428
2380
|
const pickerDropdown = createElement({
|
2429
2381
|
tagName: 'div',
|
2430
|
-
className:
|
2382
|
+
className: 'color-dropdown picker',
|
2431
2383
|
});
|
2432
2384
|
setAttribute(pickerDropdown, ariaLabelledBy, `picker-btn-${id}`);
|
2433
2385
|
setAttribute(pickerDropdown, 'role', 'group');
|
@@ -2443,7 +2395,7 @@ function initCallback(self) {
|
|
2443
2395
|
if (colorKeywords || colorPresets) {
|
2444
2396
|
const presetsDropdown = createElement({
|
2445
2397
|
tagName: 'div',
|
2446
|
-
className:
|
2398
|
+
className: 'color-dropdown scrollable menu',
|
2447
2399
|
});
|
2448
2400
|
|
2449
2401
|
// color presets
|
@@ -2463,7 +2415,7 @@ function initCallback(self) {
|
|
2463
2415
|
tagName: 'button',
|
2464
2416
|
className: 'menu-toggle btn-appearance',
|
2465
2417
|
});
|
2466
|
-
setAttribute(presetsBtn,
|
2418
|
+
setAttribute(presetsBtn, tabIndex, '-1');
|
2467
2419
|
setAttribute(presetsBtn, ariaExpanded, 'false');
|
2468
2420
|
setAttribute(presetsBtn, ariaHasPopup, 'true');
|
2469
2421
|
|
@@ -2490,9 +2442,40 @@ function initCallback(self) {
|
|
2490
2442
|
if (colorKeywords && nonColors.includes(colorValue)) {
|
2491
2443
|
self.value = colorValue;
|
2492
2444
|
}
|
2493
|
-
setAttribute(input,
|
2445
|
+
setAttribute(input, tabIndex, '-1');
|
2494
2446
|
}
|
2495
2447
|
|
2448
|
+
var version = "0.0.2alpha1";
|
2449
|
+
|
2450
|
+
// @ts-ignore
|
2451
|
+
|
2452
|
+
const Version = version;
|
2453
|
+
|
2454
|
+
// ColorPicker GC
|
2455
|
+
// ==============
|
2456
|
+
const colorPickerString = 'color-picker';
|
2457
|
+
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2458
|
+
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2459
|
+
const colorPickerDefaults = {
|
2460
|
+
componentLabels: colorPickerLabels,
|
2461
|
+
colorLabels: colorNames,
|
2462
|
+
format: 'rgb',
|
2463
|
+
colorPresets: false,
|
2464
|
+
colorKeywords: false,
|
2465
|
+
};
|
2466
|
+
|
2467
|
+
// ColorPicker Static Methods
|
2468
|
+
// ==========================
|
2469
|
+
|
2470
|
+
/** @type {CP.GetInstance<ColorPicker>} */
|
2471
|
+
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2472
|
+
|
2473
|
+
/** @type {CP.InitCallback<ColorPicker>} */
|
2474
|
+
const initColorPicker = (element) => new ColorPicker(element);
|
2475
|
+
|
2476
|
+
// ColorPicker Private Methods
|
2477
|
+
// ===========================
|
2478
|
+
|
2496
2479
|
/**
|
2497
2480
|
* Add / remove `ColorPicker` main event listeners.
|
2498
2481
|
* @param {ColorPicker} self
|
@@ -2591,8 +2574,19 @@ function showDropdown(self, dropdown) {
|
|
2591
2574
|
addClass(dropdown, 'bottom');
|
2592
2575
|
reflow(dropdown);
|
2593
2576
|
addClass(dropdown, 'show');
|
2577
|
+
|
2594
2578
|
if (isPicker) self.update();
|
2595
|
-
|
2579
|
+
|
2580
|
+
if (!self.isOpen) {
|
2581
|
+
toggleEventsOnShown(self, true);
|
2582
|
+
self.updateDropdownPosition();
|
2583
|
+
self.isOpen = true;
|
2584
|
+
setAttribute(self.input, tabIndex, '0');
|
2585
|
+
if (menuToggle) {
|
2586
|
+
setAttribute(menuToggle, tabIndex, '0');
|
2587
|
+
}
|
2588
|
+
}
|
2589
|
+
|
2596
2590
|
setAttribute(nextBtn, ariaExpanded, 'true');
|
2597
2591
|
if (activeBtn) {
|
2598
2592
|
setAttribute(activeBtn, ariaExpanded, 'false');
|
@@ -2715,7 +2709,7 @@ class ColorPicker {
|
|
2715
2709
|
self.handleKnobs = self.handleKnobs.bind(self);
|
2716
2710
|
|
2717
2711
|
// generate markup
|
2718
|
-
|
2712
|
+
setMarkup(self);
|
2719
2713
|
|
2720
2714
|
const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
|
2721
2715
|
// set main elements
|
@@ -2762,7 +2756,7 @@ class ColorPicker {
|
|
2762
2756
|
set value(v) { this.input.value = v; }
|
2763
2757
|
|
2764
2758
|
/** Check if the colour presets include any non-colour. */
|
2765
|
-
get
|
2759
|
+
get hasNonColor() {
|
2766
2760
|
return this.colorKeywords instanceof Array
|
2767
2761
|
&& this.colorKeywords.some((x) => nonColors.includes(x));
|
2768
2762
|
}
|
@@ -2818,7 +2812,7 @@ class ColorPicker {
|
|
2818
2812
|
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
2819
2813
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2820
2814
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2821
|
-
const roundA =
|
2815
|
+
const roundA = roundPart((alpha * 100)) / 100;
|
2822
2816
|
|
2823
2817
|
if (format !== 'hsl') {
|
2824
2818
|
const fill = new Color({
|
@@ -2836,7 +2830,7 @@ class ColorPicker {
|
|
2836
2830
|
});
|
2837
2831
|
setElementStyle(v2, { background: hueGradient });
|
2838
2832
|
} else {
|
2839
|
-
const saturation =
|
2833
|
+
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2840
2834
|
const fill0 = new Color({
|
2841
2835
|
r: 255, g: 0, b: 0, a: alpha,
|
2842
2836
|
}).saturate(-saturation).toRgbString();
|
@@ -2911,7 +2905,7 @@ class ColorPicker {
|
|
2911
2905
|
const self = this;
|
2912
2906
|
const { activeElement } = getDocument(self.input);
|
2913
2907
|
|
2914
|
-
if ((
|
2908
|
+
if ((e.type === touchmoveEvent && self.dragElement)
|
2915
2909
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2916
2910
|
e.stopPropagation();
|
2917
2911
|
e.preventDefault();
|
@@ -2991,12 +2985,12 @@ class ColorPicker {
|
|
2991
2985
|
|
2992
2986
|
self.update();
|
2993
2987
|
|
2994
|
-
if (currentActive) {
|
2995
|
-
removeClass(currentActive, 'active');
|
2996
|
-
removeAttribute(currentActive, ariaSelected);
|
2997
|
-
}
|
2998
|
-
|
2999
2988
|
if (currentActive !== target) {
|
2989
|
+
if (currentActive) {
|
2990
|
+
removeClass(currentActive, 'active');
|
2991
|
+
removeAttribute(currentActive, ariaSelected);
|
2992
|
+
}
|
2993
|
+
|
3000
2994
|
addClass(target, 'active');
|
3001
2995
|
setAttribute(target, ariaSelected, 'true');
|
3002
2996
|
|
@@ -3118,30 +3112,41 @@ class ColorPicker {
|
|
3118
3112
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
3119
3113
|
e.preventDefault();
|
3120
3114
|
|
3121
|
-
const { controlKnobs } = self;
|
3115
|
+
const { format, controlKnobs, visuals } = self;
|
3116
|
+
const { offsetWidth, offsetHeight } = visuals[0];
|
3122
3117
|
const [c1, c2, c3] = controlKnobs;
|
3123
3118
|
const { activeElement } = getDocument(c1);
|
3124
3119
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3120
|
+
const yRatio = offsetHeight / (format === 'hsl' ? 100 : 360);
|
3125
3121
|
|
3126
3122
|
if (currentKnob) {
|
3127
3123
|
let offsetX = 0;
|
3128
3124
|
let offsetY = 0;
|
3125
|
+
|
3129
3126
|
if (target === c1) {
|
3127
|
+
const xRatio = offsetWidth / (format === 'hsl' ? 360 : 100);
|
3128
|
+
|
3130
3129
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3131
|
-
self.controlPositions.c1x += code === keyArrowRight ?
|
3130
|
+
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
3132
3131
|
} else if ([keyArrowUp, keyArrowDown].includes(code)) {
|
3133
|
-
self.controlPositions.c1y += code === keyArrowDown ?
|
3132
|
+
self.controlPositions.c1y += code === keyArrowDown ? yRatio : -yRatio;
|
3134
3133
|
}
|
3135
3134
|
|
3136
3135
|
offsetX = self.controlPositions.c1x;
|
3137
3136
|
offsetY = self.controlPositions.c1y;
|
3138
3137
|
self.changeControl1(offsetX, offsetY);
|
3139
3138
|
} else if (target === c2) {
|
3140
|
-
self.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code)
|
3139
|
+
self.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code)
|
3140
|
+
? yRatio
|
3141
|
+
: -yRatio;
|
3142
|
+
|
3141
3143
|
offsetY = self.controlPositions.c2y;
|
3142
3144
|
self.changeControl2(offsetY);
|
3143
3145
|
} else if (target === c3) {
|
3144
|
-
self.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code)
|
3146
|
+
self.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code)
|
3147
|
+
? yRatio
|
3148
|
+
: -yRatio;
|
3149
|
+
|
3145
3150
|
offsetY = self.controlPositions.c3y;
|
3146
3151
|
self.changeAlpha(offsetY);
|
3147
3152
|
}
|
@@ -3163,7 +3168,7 @@ class ColorPicker {
|
|
3163
3168
|
const [v1, v2, v3, v4] = format === 'rgb'
|
3164
3169
|
? inputs.map((i) => parseFloat(i.value) / (i === i4 ? 100 : 1))
|
3165
3170
|
: inputs.map((i) => parseFloat(i.value) / (i !== i1 ? 100 : 360));
|
3166
|
-
const isNonColorValue = self.
|
3171
|
+
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3167
3172
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3168
3173
|
|
3169
3174
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
@@ -3422,11 +3427,11 @@ class ColorPicker {
|
|
3422
3427
|
} = componentLabels;
|
3423
3428
|
const { r, g, b } = color.toRgb();
|
3424
3429
|
const [knob1, knob2, knob3] = controlKnobs;
|
3425
|
-
const hue =
|
3430
|
+
const hue = roundPart(hsl.h * 360);
|
3426
3431
|
const alpha = color.a;
|
3427
3432
|
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
3428
|
-
const saturation =
|
3429
|
-
const lightness =
|
3433
|
+
const saturation = roundPart(saturationSource * 100);
|
3434
|
+
const lightness = roundPart(hsl.l * 100);
|
3430
3435
|
const hsvl = hsv.v * 100;
|
3431
3436
|
let colorName;
|
3432
3437
|
|
@@ -3473,8 +3478,8 @@ class ColorPicker {
|
|
3473
3478
|
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3474
3479
|
} else if (format === 'hwb') {
|
3475
3480
|
const { hwb } = self;
|
3476
|
-
const whiteness =
|
3477
|
-
const blackness =
|
3481
|
+
const whiteness = roundPart(hwb.w * 100);
|
3482
|
+
const blackness = roundPart(hwb.b * 100);
|
3478
3483
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3479
3484
|
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3480
3485
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
@@ -3490,7 +3495,7 @@ class ColorPicker {
|
|
3490
3495
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3491
3496
|
}
|
3492
3497
|
|
3493
|
-
const alphaValue =
|
3498
|
+
const alphaValue = roundPart(alpha * 100);
|
3494
3499
|
setAttribute(knob3, ariaValueText, `${alphaValue}%`);
|
3495
3500
|
setAttribute(knob3, ariaValueNow, `${alphaValue}`);
|
3496
3501
|
|
@@ -3513,10 +3518,16 @@ class ColorPicker {
|
|
3513
3518
|
/** Updates the control knobs actual positions. */
|
3514
3519
|
updateControls() {
|
3515
3520
|
const { controlKnobs, controlPositions } = this;
|
3521
|
+
let {
|
3522
|
+
c1x, c1y, c2y, c3y,
|
3523
|
+
} = controlPositions;
|
3516
3524
|
const [control1, control2, control3] = controlKnobs;
|
3517
|
-
|
3518
|
-
|
3519
|
-
|
3525
|
+
// round control positions
|
3526
|
+
[c1x, c1y, c2y, c3y] = [c1x, c1y, c2y, c3y].map(roundPart);
|
3527
|
+
|
3528
|
+
setElementStyle(control1, { transform: `translate3d(${c1x - 4}px,${c1y - 4}px,0)` });
|
3529
|
+
setElementStyle(control2, { transform: `translate3d(0,${c2y - 4}px,0)` });
|
3530
|
+
setElementStyle(control3, { transform: `translate3d(0,${c3y - 4}px,0)` });
|
3520
3531
|
}
|
3521
3532
|
|
3522
3533
|
/**
|
@@ -3529,16 +3540,16 @@ class ColorPicker {
|
|
3529
3540
|
value: oldColor, format, inputs, color, hsl,
|
3530
3541
|
} = self;
|
3531
3542
|
const [i1, i2, i3, i4] = inputs;
|
3532
|
-
const alpha =
|
3533
|
-
const hue =
|
3543
|
+
const alpha = roundPart(color.a * 100);
|
3544
|
+
const hue = roundPart(hsl.h * 360);
|
3534
3545
|
let newColor;
|
3535
3546
|
|
3536
3547
|
if (format === 'hex') {
|
3537
3548
|
newColor = self.color.toHexString(true);
|
3538
3549
|
i1.value = self.hex;
|
3539
3550
|
} else if (format === 'hsl') {
|
3540
|
-
const lightness =
|
3541
|
-
const saturation =
|
3551
|
+
const lightness = roundPart(hsl.l * 100);
|
3552
|
+
const saturation = roundPart(hsl.s * 100);
|
3542
3553
|
newColor = self.color.toHslString();
|
3543
3554
|
i1.value = `${hue}`;
|
3544
3555
|
i2.value = `${saturation}`;
|
@@ -3546,8 +3557,8 @@ class ColorPicker {
|
|
3546
3557
|
i4.value = `${alpha}`;
|
3547
3558
|
} else if (format === 'hwb') {
|
3548
3559
|
const { w, b } = self.hwb;
|
3549
|
-
const whiteness =
|
3550
|
-
const blackness =
|
3560
|
+
const whiteness = roundPart(w * 100);
|
3561
|
+
const blackness = roundPart(b * 100);
|
3551
3562
|
|
3552
3563
|
newColor = self.color.toHwbString();
|
3553
3564
|
i1.value = `${hue}`;
|
@@ -3555,7 +3566,8 @@ class ColorPicker {
|
|
3555
3566
|
i3.value = `${blackness}`;
|
3556
3567
|
i4.value = `${alpha}`;
|
3557
3568
|
} else if (format === 'rgb') {
|
3558
|
-
|
3569
|
+
let { r, g, b } = self.rgb;
|
3570
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
3559
3571
|
|
3560
3572
|
newColor = self.color.toRgbString();
|
3561
3573
|
i1.value = `${r}`;
|
@@ -3619,7 +3631,7 @@ class ColorPicker {
|
|
3619
3631
|
const self = this;
|
3620
3632
|
const { colorPicker } = self;
|
3621
3633
|
|
3622
|
-
if (!hasClass(colorPicker,
|
3634
|
+
if (!['top', 'bottom'].some((c) => hasClass(colorPicker, c))) {
|
3623
3635
|
showDropdown(self, colorPicker);
|
3624
3636
|
}
|
3625
3637
|
}
|
@@ -3636,21 +3648,6 @@ class ColorPicker {
|
|
3636
3648
|
}
|
3637
3649
|
}
|
3638
3650
|
|
3639
|
-
/** Shows the `ColorPicker` dropdown or the presets menu. */
|
3640
|
-
show() {
|
3641
|
-
const self = this;
|
3642
|
-
const { menuToggle } = self;
|
3643
|
-
if (!self.isOpen) {
|
3644
|
-
toggleEventsOnShown(self, true);
|
3645
|
-
self.updateDropdownPosition();
|
3646
|
-
self.isOpen = true;
|
3647
|
-
setAttribute(self.input, 'tabindex', '0');
|
3648
|
-
if (menuToggle) {
|
3649
|
-
setAttribute(menuToggle, 'tabindex', '0');
|
3650
|
-
}
|
3651
|
-
}
|
3652
|
-
}
|
3653
|
-
|
3654
3651
|
/**
|
3655
3652
|
* Hides the currently open `ColorPicker` dropdown.
|
3656
3653
|
* @param {boolean=} focusPrevented
|
@@ -3685,9 +3682,9 @@ class ColorPicker {
|
|
3685
3682
|
if (!focusPrevented) {
|
3686
3683
|
focus(pickerToggle);
|
3687
3684
|
}
|
3688
|
-
setAttribute(input,
|
3685
|
+
setAttribute(input, tabIndex, '-1');
|
3689
3686
|
if (menuToggle) {
|
3690
|
-
setAttribute(menuToggle,
|
3687
|
+
setAttribute(menuToggle, tabIndex, '-1');
|
3691
3688
|
}
|
3692
3689
|
}
|
3693
3690
|
}
|
@@ -3701,7 +3698,10 @@ class ColorPicker {
|
|
3701
3698
|
[...parent.children].forEach((el) => {
|
3702
3699
|
if (el !== input) el.remove();
|
3703
3700
|
});
|
3701
|
+
|
3702
|
+
removeAttribute(input, tabIndex);
|
3704
3703
|
setElementStyle(input, { backgroundColor: '' });
|
3704
|
+
|
3705
3705
|
['txt-light', 'txt-dark'].forEach((c) => removeClass(parent, c));
|
3706
3706
|
Data.remove(input, colorPickerString);
|
3707
3707
|
}
|
@@ -3709,10 +3709,16 @@ class ColorPicker {
|
|
3709
3709
|
|
3710
3710
|
ObjectAssign(ColorPicker, {
|
3711
3711
|
Color,
|
3712
|
+
ColorPalette,
|
3712
3713
|
Version,
|
3713
3714
|
getInstance: getColorPickerInstance,
|
3714
3715
|
init: initColorPicker,
|
3715
3716
|
selector: colorPickerSelector,
|
3717
|
+
// utils important for render
|
3718
|
+
roundPart,
|
3719
|
+
setElementStyle,
|
3720
|
+
setAttribute,
|
3721
|
+
getBoundingClientRect,
|
3716
3722
|
});
|
3717
3723
|
|
3718
3724
|
let CPID = 0;
|
@@ -3720,8 +3726,9 @@ let CPID = 0;
|
|
3720
3726
|
/**
|
3721
3727
|
* `ColorPickerElement` Web Component.
|
3722
3728
|
* @example
|
3723
|
-
* <
|
3724
|
-
*
|
3729
|
+
* <label for="UNIQUE_ID">Label</label>
|
3730
|
+
* <color-picker data-format="hex" data-value="#075">
|
3731
|
+
* <input id="UNIQUE_ID" type="text" class="color-preview btn-appearance">
|
3725
3732
|
* </color-picker>
|
3726
3733
|
*/
|
3727
3734
|
class ColorPickerElement extends HTMLElement {
|
@@ -3802,9 +3809,11 @@ class ColorPickerElement extends HTMLElement {
|
|
3802
3809
|
ObjectAssign(ColorPickerElement, {
|
3803
3810
|
Color,
|
3804
3811
|
ColorPicker,
|
3812
|
+
ColorPalette,
|
3813
|
+
getInstance: getColorPickerInstance,
|
3805
3814
|
Version,
|
3806
3815
|
});
|
3807
3816
|
|
3808
3817
|
customElements.define('color-picker', ColorPickerElement);
|
3809
3818
|
|
3810
|
-
export default
|
3819
|
+
export { ColorPickerElement as default };
|