@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,13 +1,13 @@
|
|
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
|
*/
|
6
6
|
(function (global, factory) {
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
8
8
|
typeof define === 'function' && define.amd ? define(factory) :
|
9
|
-
(global = global || self, global.ColorPickerElement = factory());
|
10
|
-
}(this, (function () { 'use strict';
|
9
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ColorPickerElement = factory());
|
10
|
+
})(this, (function () { 'use strict';
|
11
11
|
|
12
12
|
/**
|
13
13
|
* Returns the `document` or the `#document` element.
|
@@ -88,14 +88,9 @@
|
|
88
88
|
const getAttribute = (element, attribute) => element.getAttribute(attribute);
|
89
89
|
|
90
90
|
/**
|
91
|
-
*
|
92
|
-
*
|
93
|
-
* @param {(Node | HTMLElement | Element | globalThis)=} node
|
94
|
-
* @returns {HTMLElement | HTMLHeadElement}
|
91
|
+
* A global namespace for `document.head`.
|
95
92
|
*/
|
96
|
-
|
97
|
-
return getDocument(node).head;
|
98
|
-
}
|
93
|
+
const { head: documentHead } = document;
|
99
94
|
|
100
95
|
/**
|
101
96
|
* Shortcut for `window.getComputedStyle(element).propertyName`
|
@@ -124,13 +119,31 @@
|
|
124
119
|
// @ts-ignore
|
125
120
|
const setElementStyle = (element, styles) => { ObjectAssign(element.style, styles); };
|
126
121
|
|
122
|
+
/**
|
123
|
+
* Shortcut for `String.toLowerCase()`.
|
124
|
+
*
|
125
|
+
* @param {string} source input string
|
126
|
+
* @returns {string} lowercase output string
|
127
|
+
*/
|
128
|
+
const toLowerCase = (source) => source.toLowerCase();
|
129
|
+
|
127
130
|
/**
|
128
131
|
* A list of explicit default non-color values.
|
129
132
|
*/
|
130
133
|
const nonColors = ['transparent', 'currentColor', 'inherit', 'revert', 'initial'];
|
131
134
|
|
135
|
+
/**
|
136
|
+
* Round colour components, for all formats except HEX.
|
137
|
+
* @param {number} v one of the colour components
|
138
|
+
* @returns {number} the rounded number
|
139
|
+
*/
|
140
|
+
function roundPart(v) {
|
141
|
+
const floor = Math.floor(v);
|
142
|
+
return v - floor < 0.5 ? floor : Math.round(v);
|
143
|
+
}
|
144
|
+
|
132
145
|
// Color supported formats
|
133
|
-
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', '
|
146
|
+
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsv', 'hwb'];
|
134
147
|
|
135
148
|
// Hue angles
|
136
149
|
const ANGLES = 'deg|rad|grad|turn';
|
@@ -152,10 +165,17 @@
|
|
152
165
|
// Add angles to the mix
|
153
166
|
const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
|
154
167
|
|
168
|
+
// Start & end
|
169
|
+
const START_MATCH = '(?:[\\s|\\(\\s|\\s\\(\\s]+)?';
|
170
|
+
const END_MATCH = '(?:[\\s|\\)\\s]+)?';
|
171
|
+
// Components separation
|
172
|
+
const SEP = '(?:[,|\\s]+)';
|
173
|
+
const SEP2 = '(?:[,|\\/\\s]*)?';
|
174
|
+
|
155
175
|
// Actual matching.
|
156
176
|
// Parentheses and commas are optional, but not required.
|
157
177
|
// Whitespace can take the place of commas or opening paren
|
158
|
-
const PERMISSIVE_MATCH =
|
178
|
+
const PERMISSIVE_MATCH = `${START_MATCH}(${CSS_UNIT2})${SEP}(${CSS_UNIT})${SEP}(${CSS_UNIT})${SEP2}(${CSS_UNIT})?${END_MATCH}`;
|
159
179
|
|
160
180
|
const matchers = {
|
161
181
|
CSS_UNIT: new RegExp(CSS_UNIT2),
|
@@ -188,23 +208,22 @@
|
|
188
208
|
return `${n}`.includes('%');
|
189
209
|
}
|
190
210
|
|
191
|
-
/**
|
192
|
-
* Check to see if string passed in is an angle
|
193
|
-
* @param {string} n testing string
|
194
|
-
* @returns {boolean} the query result
|
195
|
-
*/
|
196
|
-
function isAngle(n) {
|
197
|
-
return ANGLES.split('|').some((a) => `${n}`.includes(a));
|
198
|
-
}
|
199
|
-
|
200
211
|
/**
|
201
212
|
* Check to see if string passed is a web safe colour.
|
213
|
+
* @see https://stackoverflow.com/a/16994164
|
202
214
|
* @param {string} color a colour name, EG: *red*
|
203
215
|
* @returns {boolean} the query result
|
204
216
|
*/
|
205
217
|
function isColorName(color) {
|
206
|
-
|
207
|
-
|
218
|
+
if (nonColors.includes(color)
|
219
|
+
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
220
|
+
|
221
|
+
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
222
|
+
setElementStyle(documentHead, { color });
|
223
|
+
const computedColor = getElementStyle(documentHead, 'color');
|
224
|
+
setElementStyle(documentHead, { color: '' });
|
225
|
+
return computedColor !== c;
|
226
|
+
});
|
208
227
|
}
|
209
228
|
|
210
229
|
/**
|
@@ -225,15 +244,15 @@
|
|
225
244
|
*/
|
226
245
|
function bound01(N, max) {
|
227
246
|
let n = N;
|
228
|
-
if (isOnePointZero(
|
229
|
-
|
230
|
-
n = max === 360 ? n : Math.min(max, Math.max(0, parseFloat(n)));
|
247
|
+
if (isOnePointZero(N)) n = '100%';
|
231
248
|
|
232
|
-
|
233
|
-
|
249
|
+
const processPercent = isPercentage(n);
|
250
|
+
n = max === 360
|
251
|
+
? parseFloat(n)
|
252
|
+
: Math.min(max, Math.max(0, parseFloat(n)));
|
234
253
|
|
235
254
|
// Automatically convert percentage into number
|
236
|
-
if (
|
255
|
+
if (processPercent) n = (n * max) / 100;
|
237
256
|
|
238
257
|
// Handle floating point rounding errors
|
239
258
|
if (Math.abs(n - max) < 0.000001) {
|
@@ -244,11 +263,11 @@
|
|
244
263
|
// If n is a hue given in degrees,
|
245
264
|
// wrap around out-of-range values into [0, 360] range
|
246
265
|
// then convert into [0, 1].
|
247
|
-
n = (n < 0 ? (n % max) + max : n % max) /
|
266
|
+
n = (n < 0 ? (n % max) + max : n % max) / max;
|
248
267
|
} else {
|
249
268
|
// If n not a hue given in degrees
|
250
269
|
// Convert into [0, 1] range if it isn't already.
|
251
|
-
n = (n % max) /
|
270
|
+
n = (n % max) / max;
|
252
271
|
}
|
253
272
|
return n;
|
254
273
|
}
|
@@ -283,7 +302,6 @@
|
|
283
302
|
* @returns {string}
|
284
303
|
*/
|
285
304
|
function getRGBFromName(name) {
|
286
|
-
const documentHead = getDocumentHead();
|
287
305
|
setElementStyle(documentHead, { color: name });
|
288
306
|
const colorName = getElementStyle(documentHead, 'color');
|
289
307
|
setElementStyle(documentHead, { color: '' });
|
@@ -296,7 +314,7 @@
|
|
296
314
|
* @returns {string} - the hexadecimal value
|
297
315
|
*/
|
298
316
|
function convertDecimalToHex(d) {
|
299
|
-
return
|
317
|
+
return roundPart(d * 255).toString(16);
|
300
318
|
}
|
301
319
|
|
302
320
|
/**
|
@@ -382,6 +400,36 @@
|
|
382
400
|
return p;
|
383
401
|
}
|
384
402
|
|
403
|
+
/**
|
404
|
+
* Converts an HSL colour value to RGB.
|
405
|
+
*
|
406
|
+
* @param {number} h Hue Angle [0, 1]
|
407
|
+
* @param {number} s Saturation [0, 1]
|
408
|
+
* @param {number} l Lightness Angle [0, 1]
|
409
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
410
|
+
*/
|
411
|
+
function hslToRgb(h, s, l) {
|
412
|
+
let r = 0;
|
413
|
+
let g = 0;
|
414
|
+
let b = 0;
|
415
|
+
|
416
|
+
if (s === 0) {
|
417
|
+
// achromatic
|
418
|
+
g = l;
|
419
|
+
b = l;
|
420
|
+
r = l;
|
421
|
+
} else {
|
422
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
423
|
+
const p = 2 * l - q;
|
424
|
+
r = hueToRgb(p, q, h + 1 / 3);
|
425
|
+
g = hueToRgb(p, q, h);
|
426
|
+
b = hueToRgb(p, q, h - 1 / 3);
|
427
|
+
}
|
428
|
+
[r, g, b] = [r, g, b].map((x) => x * 255);
|
429
|
+
|
430
|
+
return { r, g, b };
|
431
|
+
}
|
432
|
+
|
385
433
|
/**
|
386
434
|
* Returns an HWB colour object from an RGB colour object.
|
387
435
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
@@ -444,36 +492,6 @@
|
|
444
492
|
return { r, g, b };
|
445
493
|
}
|
446
494
|
|
447
|
-
/**
|
448
|
-
* Converts an HSL colour value to RGB.
|
449
|
-
*
|
450
|
-
* @param {number} h Hue Angle [0, 1]
|
451
|
-
* @param {number} s Saturation [0, 1]
|
452
|
-
* @param {number} l Lightness Angle [0, 1]
|
453
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
454
|
-
*/
|
455
|
-
function hslToRgb(h, s, l) {
|
456
|
-
let r = 0;
|
457
|
-
let g = 0;
|
458
|
-
let b = 0;
|
459
|
-
|
460
|
-
if (s === 0) {
|
461
|
-
// achromatic
|
462
|
-
g = l;
|
463
|
-
b = l;
|
464
|
-
r = l;
|
465
|
-
} else {
|
466
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
467
|
-
const p = 2 * l - q;
|
468
|
-
r = hueToRgb(p, q, h + 1 / 3);
|
469
|
-
g = hueToRgb(p, q, h);
|
470
|
-
b = hueToRgb(p, q, h - 1 / 3);
|
471
|
-
}
|
472
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
473
|
-
|
474
|
-
return { r, g, b };
|
475
|
-
}
|
476
|
-
|
477
495
|
/**
|
478
496
|
* Converts an RGB colour value to HSV.
|
479
497
|
*
|
@@ -529,10 +547,11 @@
|
|
529
547
|
const q = v * (1 - f * s);
|
530
548
|
const t = v * (1 - (1 - f) * s);
|
531
549
|
const mod = i % 6;
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
550
|
+
let r = [v, q, p, p, t, v][mod];
|
551
|
+
let g = [t, v, v, q, p, p][mod];
|
552
|
+
let b = [p, p, t, v, v, q][mod];
|
553
|
+
[r, g, b] = [r, g, b].map((n) => n * 255);
|
554
|
+
return { r, g, b };
|
536
555
|
}
|
537
556
|
|
538
557
|
/**
|
@@ -548,15 +567,15 @@
|
|
548
567
|
*/
|
549
568
|
function rgbToHex(r, g, b, allow3Char) {
|
550
569
|
const hex = [
|
551
|
-
pad2(
|
552
|
-
pad2(
|
553
|
-
pad2(
|
570
|
+
pad2(roundPart(r).toString(16)),
|
571
|
+
pad2(roundPart(g).toString(16)),
|
572
|
+
pad2(roundPart(b).toString(16)),
|
554
573
|
];
|
555
574
|
|
556
575
|
// Return a 3 character hex if possible
|
557
576
|
if (allow3Char && hex[0].charAt(0) === hex[0].charAt(1)
|
558
577
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
559
|
-
|
578
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)) {
|
560
579
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
|
561
580
|
}
|
562
581
|
|
@@ -575,48 +594,33 @@
|
|
575
594
|
*/
|
576
595
|
function rgbaToHex(r, g, b, a, allow4Char) {
|
577
596
|
const hex = [
|
578
|
-
pad2(
|
579
|
-
pad2(
|
580
|
-
pad2(
|
597
|
+
pad2(roundPart(r).toString(16)),
|
598
|
+
pad2(roundPart(g).toString(16)),
|
599
|
+
pad2(roundPart(b).toString(16)),
|
581
600
|
pad2(convertDecimalToHex(a)),
|
582
601
|
];
|
583
602
|
|
584
603
|
// Return a 4 character hex if possible
|
585
604
|
if (allow4Char && hex[0].charAt(0) === hex[0].charAt(1)
|
586
605
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
587
|
-
|
588
|
-
|
606
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)
|
607
|
+
&& hex[3].charAt(0) === hex[3].charAt(1)) {
|
589
608
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
|
590
609
|
}
|
591
610
|
return hex.join('');
|
592
611
|
}
|
593
612
|
|
594
|
-
/**
|
595
|
-
* Returns a colour object corresponding to a given number.
|
596
|
-
* @param {number} color input number
|
597
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
598
|
-
*/
|
599
|
-
function numberInputToObject(color) {
|
600
|
-
/* eslint-disable no-bitwise */
|
601
|
-
return {
|
602
|
-
r: color >> 16,
|
603
|
-
g: (color & 0xff00) >> 8,
|
604
|
-
b: color & 0xff,
|
605
|
-
};
|
606
|
-
/* eslint-enable no-bitwise */
|
607
|
-
}
|
608
|
-
|
609
613
|
/**
|
610
614
|
* Permissive string parsing. Take in a number of formats, and output an object
|
611
615
|
* based on detected format. Returns {r,g,b} or {h,s,l} or {h,s,v}
|
612
616
|
* @param {string} input colour value in any format
|
613
|
-
* @returns {Record<string, (number | string)> | false} an object matching the RegExp
|
617
|
+
* @returns {Record<string, (number | string | boolean)> | false} an object matching the RegExp
|
614
618
|
*/
|
615
619
|
function stringInputToObject(input) {
|
616
|
-
let color = input.trim()
|
620
|
+
let color = toLowerCase(input.trim());
|
617
621
|
if (color.length === 0) {
|
618
622
|
return {
|
619
|
-
r: 0, g: 0, b: 0, a:
|
623
|
+
r: 0, g: 0, b: 0, a: 1,
|
620
624
|
};
|
621
625
|
}
|
622
626
|
let named = false;
|
@@ -624,11 +628,9 @@
|
|
624
628
|
color = getRGBFromName(color);
|
625
629
|
named = true;
|
626
630
|
} else if (nonColors.includes(color)) {
|
627
|
-
const
|
628
|
-
const rgb = isTransparent ? 0 : 255;
|
629
|
-
const a = isTransparent ? 0 : 1;
|
631
|
+
const a = color === 'transparent' ? 0 : 1;
|
630
632
|
return {
|
631
|
-
r:
|
633
|
+
r: 0, g: 0, b: 0, a, format: 'rgb', ok: true,
|
632
634
|
};
|
633
635
|
}
|
634
636
|
|
@@ -668,7 +670,6 @@
|
|
668
670
|
g: parseIntFromHex(m2),
|
669
671
|
b: parseIntFromHex(m3),
|
670
672
|
a: convertHexToDecimal(m4),
|
671
|
-
// format: named ? 'rgb' : 'hex8',
|
672
673
|
format: named ? 'rgb' : 'hex',
|
673
674
|
};
|
674
675
|
}
|
@@ -732,6 +733,7 @@
|
|
732
733
|
function inputToRGB(input) {
|
733
734
|
let rgb = { r: 0, g: 0, b: 0 };
|
734
735
|
let color = input;
|
736
|
+
/** @type {string | number} */
|
735
737
|
let a = 1;
|
736
738
|
let s = null;
|
737
739
|
let v = null;
|
@@ -739,8 +741,11 @@
|
|
739
741
|
let w = null;
|
740
742
|
let b = null;
|
741
743
|
let h = null;
|
744
|
+
let r = null;
|
745
|
+
let g = null;
|
742
746
|
let ok = false;
|
743
|
-
|
747
|
+
const inputFormat = typeof color === 'object' && color.format;
|
748
|
+
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
744
749
|
|
745
750
|
if (typeof input === 'string') {
|
746
751
|
// @ts-ignore -- this now is converted to object
|
@@ -749,7 +754,10 @@
|
|
749
754
|
}
|
750
755
|
if (typeof color === 'object') {
|
751
756
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
752
|
-
|
757
|
+
({ r, g, b } = color);
|
758
|
+
// RGB values now are all in [0, 255] range
|
759
|
+
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255) * 255);
|
760
|
+
rgb = { r, g, b };
|
753
761
|
ok = true;
|
754
762
|
format = 'rgb';
|
755
763
|
} else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
@@ -778,14 +786,17 @@
|
|
778
786
|
format = 'hwb';
|
779
787
|
}
|
780
788
|
if (isValidCSSUnit(color.a)) {
|
781
|
-
a = color.a;
|
782
|
-
a = isPercentage(`${a}`) ? bound01(a, 100) : a;
|
789
|
+
a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
|
790
|
+
a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
|
783
791
|
}
|
784
792
|
}
|
793
|
+
if (typeof color === 'undefined') {
|
794
|
+
ok = true;
|
795
|
+
}
|
785
796
|
|
786
797
|
return {
|
787
|
-
ok,
|
788
|
-
format
|
798
|
+
ok,
|
799
|
+
format,
|
789
800
|
r: Math.min(255, Math.max(rgb.r, 0)),
|
790
801
|
g: Math.min(255, Math.max(rgb.g, 0)),
|
791
802
|
b: Math.min(255, Math.max(rgb.b, 0)),
|
@@ -814,7 +825,8 @@
|
|
814
825
|
color = inputToRGB(color);
|
815
826
|
}
|
816
827
|
if (typeof color === 'number') {
|
817
|
-
|
828
|
+
const len = `${color}`.length;
|
829
|
+
color = `#${(len === 2 ? '0' : '00')}${color}`;
|
818
830
|
}
|
819
831
|
const {
|
820
832
|
r, g, b, a, ok, format,
|
@@ -824,7 +836,7 @@
|
|
824
836
|
const self = this;
|
825
837
|
|
826
838
|
/** @type {CP.ColorInput} */
|
827
|
-
self.originalInput =
|
839
|
+
self.originalInput = input;
|
828
840
|
/** @type {number} */
|
829
841
|
self.r = r;
|
830
842
|
/** @type {number} */
|
@@ -837,14 +849,6 @@
|
|
837
849
|
self.ok = ok;
|
838
850
|
/** @type {CP.ColorFormats} */
|
839
851
|
self.format = configFormat || format;
|
840
|
-
|
841
|
-
// Don't let the range of [0,255] come back in [0,1].
|
842
|
-
// Potentially lose a little bit of precision here, but will fix issues where
|
843
|
-
// .5 gets interpreted as half of the total, instead of half of 1
|
844
|
-
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
|
845
|
-
if (r < 1) self.r = Math.round(r);
|
846
|
-
if (g < 1) self.g = Math.round(g);
|
847
|
-
if (b < 1) self.b = Math.round(b);
|
848
852
|
}
|
849
853
|
|
850
854
|
/**
|
@@ -860,7 +864,7 @@
|
|
860
864
|
* @returns {boolean} the query result
|
861
865
|
*/
|
862
866
|
get isDark() {
|
863
|
-
return this.brightness <
|
867
|
+
return this.brightness < 120;
|
864
868
|
}
|
865
869
|
|
866
870
|
/**
|
@@ -912,13 +916,9 @@
|
|
912
916
|
const {
|
913
917
|
r, g, b, a,
|
914
918
|
} = this;
|
915
|
-
const [R, G, B] = [r, g, b].map((x) => Math.round(x));
|
916
919
|
|
917
920
|
return {
|
918
|
-
r:
|
919
|
-
g: G,
|
920
|
-
b: B,
|
921
|
-
a: Math.round(a * 100) / 100,
|
921
|
+
r, g, b, a: roundPart(a * 100) / 100,
|
922
922
|
};
|
923
923
|
}
|
924
924
|
|
@@ -932,10 +932,11 @@
|
|
932
932
|
const {
|
933
933
|
r, g, b, a,
|
934
934
|
} = this.toRgb();
|
935
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
935
936
|
|
936
937
|
return a === 1
|
937
|
-
? `rgb(${
|
938
|
-
: `rgba(${
|
938
|
+
? `rgb(${R}, ${G}, ${B})`
|
939
|
+
: `rgba(${R}, ${G}, ${B}, ${a})`;
|
939
940
|
}
|
940
941
|
|
941
942
|
/**
|
@@ -948,9 +949,10 @@
|
|
948
949
|
const {
|
949
950
|
r, g, b, a,
|
950
951
|
} = this.toRgb();
|
951
|
-
const
|
952
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
953
|
+
const A = a === 1 ? '' : ` / ${roundPart(a * 100)}%`;
|
952
954
|
|
953
|
-
return `rgb(${
|
955
|
+
return `rgb(${R} ${G} ${B}${A})`;
|
954
956
|
}
|
955
957
|
|
956
958
|
/**
|
@@ -1043,10 +1045,10 @@
|
|
1043
1045
|
let {
|
1044
1046
|
h, s, l, a,
|
1045
1047
|
} = this.toHsl();
|
1046
|
-
h =
|
1047
|
-
s =
|
1048
|
-
l =
|
1049
|
-
a =
|
1048
|
+
h = roundPart(h * 360);
|
1049
|
+
s = roundPart(s * 100);
|
1050
|
+
l = roundPart(l * 100);
|
1051
|
+
a = roundPart(a * 100) / 100;
|
1050
1052
|
|
1051
1053
|
return a === 1
|
1052
1054
|
? `hsl(${h}, ${s}%, ${l}%)`
|
@@ -1063,11 +1065,11 @@
|
|
1063
1065
|
let {
|
1064
1066
|
h, s, l, a,
|
1065
1067
|
} = this.toHsl();
|
1066
|
-
h =
|
1067
|
-
s =
|
1068
|
-
l =
|
1069
|
-
a =
|
1070
|
-
const A = a < 100 ? ` / ${
|
1068
|
+
h = roundPart(h * 360);
|
1069
|
+
s = roundPart(s * 100);
|
1070
|
+
l = roundPart(l * 100);
|
1071
|
+
a = roundPart(a * 100);
|
1072
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
1071
1073
|
|
1072
1074
|
return `hsl(${h}deg ${s}% ${l}%${A})`;
|
1073
1075
|
}
|
@@ -1094,11 +1096,11 @@
|
|
1094
1096
|
let {
|
1095
1097
|
h, w, b, a,
|
1096
1098
|
} = this.toHwb();
|
1097
|
-
h =
|
1098
|
-
w =
|
1099
|
-
b =
|
1100
|
-
a =
|
1101
|
-
const A = a < 100 ? ` / ${
|
1099
|
+
h = roundPart(h * 360);
|
1100
|
+
w = roundPart(w * 100);
|
1101
|
+
b = roundPart(b * 100);
|
1102
|
+
a = roundPart(a * 100);
|
1103
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
1102
1104
|
|
1103
1105
|
return `hwb(${h}deg ${w}% ${b}%${A})`;
|
1104
1106
|
}
|
@@ -1224,6 +1226,7 @@
|
|
1224
1226
|
isOnePointZero,
|
1225
1227
|
isPercentage,
|
1226
1228
|
isValidCSSUnit,
|
1229
|
+
isColorName,
|
1227
1230
|
pad2,
|
1228
1231
|
clamp01,
|
1229
1232
|
bound01,
|
@@ -1241,9 +1244,11 @@
|
|
1241
1244
|
hueToRgb,
|
1242
1245
|
hwbToRgb,
|
1243
1246
|
parseIntFromHex,
|
1244
|
-
numberInputToObject,
|
1245
1247
|
stringInputToObject,
|
1246
1248
|
inputToRGB,
|
1249
|
+
roundPart,
|
1250
|
+
getElementStyle,
|
1251
|
+
setElementStyle,
|
1247
1252
|
ObjectAssign,
|
1248
1253
|
});
|
1249
1254
|
|
@@ -1373,24 +1378,6 @@
|
|
1373
1378
|
*/
|
1374
1379
|
const ariaValueNow = 'aria-valuenow';
|
1375
1380
|
|
1376
|
-
/**
|
1377
|
-
* A global namespace for aria-haspopup.
|
1378
|
-
* @type {string}
|
1379
|
-
*/
|
1380
|
-
const ariaHasPopup = 'aria-haspopup';
|
1381
|
-
|
1382
|
-
/**
|
1383
|
-
* A global namespace for aria-hidden.
|
1384
|
-
* @type {string}
|
1385
|
-
*/
|
1386
|
-
const ariaHidden = 'aria-hidden';
|
1387
|
-
|
1388
|
-
/**
|
1389
|
-
* A global namespace for aria-labelledby.
|
1390
|
-
* @type {string}
|
1391
|
-
*/
|
1392
|
-
const ariaLabelledBy = 'aria-labelledby';
|
1393
|
-
|
1394
1381
|
/**
|
1395
1382
|
* A global namespace for `ArrowDown` key.
|
1396
1383
|
* @type {string} e.which = 40 equivalent
|
@@ -1517,37 +1504,6 @@
|
|
1517
1504
|
*/
|
1518
1505
|
const focusoutEvent = 'focusout';
|
1519
1506
|
|
1520
|
-
// @ts-ignore
|
1521
|
-
const { userAgentData: uaDATA } = navigator;
|
1522
|
-
|
1523
|
-
/**
|
1524
|
-
* A global namespace for `userAgentData` object.
|
1525
|
-
*/
|
1526
|
-
const userAgentData = uaDATA;
|
1527
|
-
|
1528
|
-
const { userAgent: userAgentString } = navigator;
|
1529
|
-
|
1530
|
-
/**
|
1531
|
-
* A global namespace for `navigator.userAgent` string.
|
1532
|
-
*/
|
1533
|
-
const userAgent = userAgentString;
|
1534
|
-
|
1535
|
-
const mobileBrands = /iPhone|iPad|iPod|Android/i;
|
1536
|
-
let isMobileCheck = false;
|
1537
|
-
|
1538
|
-
if (userAgentData) {
|
1539
|
-
isMobileCheck = userAgentData.brands
|
1540
|
-
.some((/** @type {Record<String, any>} */x) => mobileBrands.test(x.brand));
|
1541
|
-
} else {
|
1542
|
-
isMobileCheck = mobileBrands.test(userAgent);
|
1543
|
-
}
|
1544
|
-
|
1545
|
-
/**
|
1546
|
-
* A global `boolean` for mobile detection.
|
1547
|
-
* @type {boolean}
|
1548
|
-
*/
|
1549
|
-
const isMobile = isMobileCheck;
|
1550
|
-
|
1551
1507
|
/**
|
1552
1508
|
* Returns the `document.documentElement` or the `<html>` element.
|
1553
1509
|
*
|
@@ -1732,30 +1688,6 @@
|
|
1732
1688
|
return lookUp.getElementsByClassName(selector);
|
1733
1689
|
}
|
1734
1690
|
|
1735
|
-
/**
|
1736
|
-
* This is a shortie for `document.createElementNS` method
|
1737
|
-
* which allows you to create a new `HTMLElement` for a given `tagName`
|
1738
|
-
* or based on an object with specific non-readonly attributes:
|
1739
|
-
* `id`, `className`, `textContent`, `style`, etc.
|
1740
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
1741
|
-
*
|
1742
|
-
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
1743
|
-
* @param {Record<string, string> | string} param `tagName` or object
|
1744
|
-
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
1745
|
-
*/
|
1746
|
-
function createElementNS(namespace, param) {
|
1747
|
-
if (typeof param === 'string') {
|
1748
|
-
return getDocument().createElementNS(namespace, param);
|
1749
|
-
}
|
1750
|
-
|
1751
|
-
const { tagName } = param;
|
1752
|
-
const attr = { ...param };
|
1753
|
-
const newElement = createElementNS(namespace, tagName);
|
1754
|
-
delete attr.tagName;
|
1755
|
-
ObjectAssign(newElement, attr);
|
1756
|
-
return newElement;
|
1757
|
-
}
|
1758
|
-
|
1759
1691
|
/**
|
1760
1692
|
* Shortcut for the `Element.dispatchEvent(Event)` method.
|
1761
1693
|
*
|
@@ -1879,14 +1811,6 @@
|
|
1879
1811
|
*/
|
1880
1812
|
const ObjectKeys = (obj) => Object.keys(obj);
|
1881
1813
|
|
1882
|
-
/**
|
1883
|
-
* Shortcut for `String.toLowerCase()`.
|
1884
|
-
*
|
1885
|
-
* @param {string} source input string
|
1886
|
-
* @returns {string} lowercase output string
|
1887
|
-
*/
|
1888
|
-
const toLowerCase = (source) => source.toLowerCase();
|
1889
|
-
|
1890
1814
|
/**
|
1891
1815
|
* Utility to normalize component options.
|
1892
1816
|
*
|
@@ -1990,6 +1914,80 @@
|
|
1990
1914
|
*/
|
1991
1915
|
const removeAttribute = (element, attribute) => element.removeAttribute(attribute);
|
1992
1916
|
|
1917
|
+
/**
|
1918
|
+
* @class
|
1919
|
+
* Returns a color palette with a given set of parameters.
|
1920
|
+
* @example
|
1921
|
+
* new ColorPalette(0, 12, 10);
|
1922
|
+
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: Array<Color> }
|
1923
|
+
*/
|
1924
|
+
class ColorPalette {
|
1925
|
+
/**
|
1926
|
+
* The `hue` parameter is optional, which would be set to 0.
|
1927
|
+
* @param {number[]} args represeinting hue, hueSteps, lightSteps
|
1928
|
+
* * `args.hue` the starting Hue [0, 360]
|
1929
|
+
* * `args.hueSteps` Hue Steps Count [5, 24]
|
1930
|
+
* * `args.lightSteps` Lightness Steps Count [5, 12]
|
1931
|
+
*/
|
1932
|
+
constructor(...args) {
|
1933
|
+
let hue = 0;
|
1934
|
+
let hueSteps = 12;
|
1935
|
+
let lightSteps = 10;
|
1936
|
+
let lightnessArray = [0.5];
|
1937
|
+
|
1938
|
+
if (args.length === 3) {
|
1939
|
+
[hue, hueSteps, lightSteps] = args;
|
1940
|
+
} else if (args.length === 2) {
|
1941
|
+
[hueSteps, lightSteps] = args;
|
1942
|
+
if ([hueSteps, lightSteps].some((n) => n < 1)) {
|
1943
|
+
throw TypeError('ColorPalette: when 2 arguments used, both must be larger than 0.');
|
1944
|
+
}
|
1945
|
+
} else {
|
1946
|
+
throw TypeError('ColorPalette requires minimum 2 arguments');
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
/** @type {Color[]} */
|
1950
|
+
const colors = [];
|
1951
|
+
|
1952
|
+
const hueStep = 360 / hueSteps;
|
1953
|
+
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
1954
|
+
const estimatedStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
1955
|
+
|
1956
|
+
let lightStep = 0.25;
|
1957
|
+
lightStep = [4, 5].includes(lightSteps) ? 0.2 : lightStep;
|
1958
|
+
lightStep = [6, 7].includes(lightSteps) ? 0.15 : lightStep;
|
1959
|
+
lightStep = [8, 9].includes(lightSteps) ? 0.11 : lightStep;
|
1960
|
+
lightStep = [10, 11].includes(lightSteps) ? 0.09 : lightStep;
|
1961
|
+
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
1962
|
+
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
1963
|
+
|
1964
|
+
// light tints
|
1965
|
+
for (let i = 1; i < half + 1; i += 1) {
|
1966
|
+
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i))];
|
1967
|
+
}
|
1968
|
+
|
1969
|
+
// dark tints
|
1970
|
+
for (let i = 1; i < lightSteps - half; i += 1) {
|
1971
|
+
lightnessArray = [(0.5 - lightStep * (i)), ...lightnessArray];
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
// feed `colors` Array
|
1975
|
+
for (let i = 0; i < hueSteps; i += 1) {
|
1976
|
+
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
1977
|
+
lightnessArray.forEach((l) => {
|
1978
|
+
colors.push(new Color({ h: currentHue, s: 1, l }));
|
1979
|
+
});
|
1980
|
+
}
|
1981
|
+
|
1982
|
+
this.hue = hue;
|
1983
|
+
this.hueSteps = hueSteps;
|
1984
|
+
this.lightSteps = lightSteps;
|
1985
|
+
this.colors = colors;
|
1986
|
+
}
|
1987
|
+
}
|
1988
|
+
|
1989
|
+
ObjectAssign(ColorPalette, { Color });
|
1990
|
+
|
1993
1991
|
/** @type {Record<string, string>} */
|
1994
1992
|
const colorPickerLabels = {
|
1995
1993
|
pickerLabel: 'Colour Picker',
|
@@ -2017,6 +2015,22 @@
|
|
2017
2015
|
*/
|
2018
2016
|
const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold', 'olive', 'yellow', 'lime', 'green', 'teal', 'cyan', 'blue', 'violet', 'magenta', 'pink'];
|
2019
2017
|
|
2018
|
+
const tabIndex = 'tabindex';
|
2019
|
+
|
2020
|
+
/**
|
2021
|
+
* Check if a string is valid JSON string.
|
2022
|
+
* @param {string} str the string input
|
2023
|
+
* @returns {boolean} the query result
|
2024
|
+
*/
|
2025
|
+
function isValidJSON(str) {
|
2026
|
+
try {
|
2027
|
+
JSON.parse(str);
|
2028
|
+
} catch (e) {
|
2029
|
+
return false;
|
2030
|
+
}
|
2031
|
+
return true;
|
2032
|
+
}
|
2033
|
+
|
2020
2034
|
/**
|
2021
2035
|
* Shortcut for `String.toUpperCase()`.
|
2022
2036
|
*
|
@@ -2025,6 +2039,48 @@
|
|
2025
2039
|
*/
|
2026
2040
|
const toUpperCase = (source) => source.toUpperCase();
|
2027
2041
|
|
2042
|
+
/**
|
2043
|
+
* A global namespace for aria-haspopup.
|
2044
|
+
* @type {string}
|
2045
|
+
*/
|
2046
|
+
const ariaHasPopup = 'aria-haspopup';
|
2047
|
+
|
2048
|
+
/**
|
2049
|
+
* A global namespace for aria-hidden.
|
2050
|
+
* @type {string}
|
2051
|
+
*/
|
2052
|
+
const ariaHidden = 'aria-hidden';
|
2053
|
+
|
2054
|
+
/**
|
2055
|
+
* A global namespace for aria-labelledby.
|
2056
|
+
* @type {string}
|
2057
|
+
*/
|
2058
|
+
const ariaLabelledBy = 'aria-labelledby';
|
2059
|
+
|
2060
|
+
/**
|
2061
|
+
* This is a shortie for `document.createElementNS` method
|
2062
|
+
* which allows you to create a new `HTMLElement` for a given `tagName`
|
2063
|
+
* or based on an object with specific non-readonly attributes:
|
2064
|
+
* `id`, `className`, `textContent`, `style`, etc.
|
2065
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
2066
|
+
*
|
2067
|
+
* @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
|
2068
|
+
* @param {Record<string, string> | string} param `tagName` or object
|
2069
|
+
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
2070
|
+
*/
|
2071
|
+
function createElementNS(namespace, param) {
|
2072
|
+
if (typeof param === 'string') {
|
2073
|
+
return getDocument().createElementNS(namespace, param);
|
2074
|
+
}
|
2075
|
+
|
2076
|
+
const { tagName } = param;
|
2077
|
+
const attr = { ...param };
|
2078
|
+
const newElement = createElementNS(namespace, tagName);
|
2079
|
+
delete attr.tagName;
|
2080
|
+
ObjectAssign(newElement, attr);
|
2081
|
+
return newElement;
|
2082
|
+
}
|
2083
|
+
|
2028
2084
|
const vHidden = 'v-hidden';
|
2029
2085
|
|
2030
2086
|
/**
|
@@ -2081,7 +2137,6 @@
|
|
2081
2137
|
max,
|
2082
2138
|
step,
|
2083
2139
|
});
|
2084
|
-
// }
|
2085
2140
|
colorForm.append(cInputLabel, cInput);
|
2086
2141
|
});
|
2087
2142
|
return colorForm;
|
@@ -2170,10 +2225,8 @@
|
|
2170
2225
|
const {
|
2171
2226
|
i, c, l, min, max,
|
2172
2227
|
} = template;
|
2173
|
-
// const hidden = i === 2 && format === 'hwb' ? ' v-hidden' : '';
|
2174
2228
|
const control = createElement({
|
2175
2229
|
tagName: 'div',
|
2176
|
-
// className: `color-control${hidden}`,
|
2177
2230
|
className: 'color-control',
|
2178
2231
|
});
|
2179
2232
|
setAttribute(control, 'role', 'presentation');
|
@@ -2193,7 +2246,7 @@
|
|
2193
2246
|
|
2194
2247
|
setAttribute(knob, ariaLabel, l);
|
2195
2248
|
setAttribute(knob, 'role', 'slider');
|
2196
|
-
setAttribute(knob,
|
2249
|
+
setAttribute(knob, tabIndex, '0');
|
2197
2250
|
setAttribute(knob, ariaValueMin, `${min}`);
|
2198
2251
|
setAttribute(knob, ariaValueMax, `${max}`);
|
2199
2252
|
control.append(knob);
|
@@ -2204,64 +2257,14 @@
|
|
2204
2257
|
}
|
2205
2258
|
|
2206
2259
|
/**
|
2207
|
-
*
|
2208
|
-
*
|
2209
|
-
* @
|
2210
|
-
* new ColorPalette(0, 12, 10);
|
2211
|
-
* // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: array }
|
2260
|
+
* Helps setting CSS variables to the color-menu.
|
2261
|
+
* @param {HTMLElement} element
|
2262
|
+
* @param {Record<string,any>} props
|
2212
2263
|
*/
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
* * `args.hue` the starting Hue [0, 360]
|
2218
|
-
* * `args.hueSteps` Hue Steps Count [5, 13]
|
2219
|
-
* * `args.lightSteps` Lightness Steps Count [8, 10]
|
2220
|
-
*/
|
2221
|
-
constructor(...args) {
|
2222
|
-
let hue = 0;
|
2223
|
-
let hueSteps = 12;
|
2224
|
-
let lightSteps = 10;
|
2225
|
-
let lightnessArray = [0.5];
|
2226
|
-
|
2227
|
-
if (args.length === 3) {
|
2228
|
-
[hue, hueSteps, lightSteps] = args;
|
2229
|
-
} else if (args.length === 2) {
|
2230
|
-
[hueSteps, lightSteps] = args;
|
2231
|
-
} else {
|
2232
|
-
throw TypeError('The ColorPalette requires minimum 2 arguments');
|
2233
|
-
}
|
2234
|
-
|
2235
|
-
/** @type {string[]} */
|
2236
|
-
const colors = [];
|
2237
|
-
|
2238
|
-
const hueStep = 360 / hueSteps;
|
2239
|
-
const lightStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
2240
|
-
const half = Math.round((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
2241
|
-
|
2242
|
-
// light tints
|
2243
|
-
for (let i = 0; i < half; i += 1) {
|
2244
|
-
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i + 1))];
|
2245
|
-
}
|
2246
|
-
|
2247
|
-
// dark tints
|
2248
|
-
for (let i = 0; i < lightSteps - half - 1; i += 1) {
|
2249
|
-
lightnessArray = [(0.5 - lightStep * (i + 1)), ...lightnessArray];
|
2250
|
-
}
|
2251
|
-
|
2252
|
-
// feed `colors` Array
|
2253
|
-
for (let i = 0; i < hueSteps; i += 1) {
|
2254
|
-
const currentHue = ((hue + i * hueStep) % 360) / 360;
|
2255
|
-
lightnessArray.forEach((l) => {
|
2256
|
-
colors.push(new Color({ h: currentHue, s: 1, l }).toHexString());
|
2257
|
-
});
|
2258
|
-
}
|
2259
|
-
|
2260
|
-
this.hue = hue;
|
2261
|
-
this.hueSteps = hueSteps;
|
2262
|
-
this.lightSteps = lightSteps;
|
2263
|
-
this.colors = colors;
|
2264
|
-
}
|
2264
|
+
function setCSSProperties(element, props) {
|
2265
|
+
ObjectKeys(props).forEach((prop) => {
|
2266
|
+
element.style.setProperty(prop, props[prop]);
|
2267
|
+
});
|
2265
2268
|
}
|
2266
2269
|
|
2267
2270
|
/**
|
@@ -2281,68 +2284,64 @@
|
|
2281
2284
|
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2282
2285
|
const colorsCount = colorsArray.length;
|
2283
2286
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2284
|
-
|
2285
|
-
|| Math.max(...[5, 6, 7, 8, 9, 10].filter((x) => colorsCount > (x * 2) && !(colorsCount % x)));
|
2286
|
-
fit = Number.isFinite(fit) ? fit : 5;
|
2287
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount > x * 2 && !(colorsCount % x)) || 5;
|
2287
2288
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2288
|
-
let rowCountHover =
|
2289
|
-
rowCountHover = isMultiLine && colorsCount
|
2290
|
-
rowCountHover = colorsCount >=
|
2291
|
-
rowCountHover = colorsCount >=
|
2292
|
-
|
2293
|
-
const
|
2294
|
-
const isScrollable = isMultiLine && colorsCount > rowCountHover * fit;
|
2289
|
+
let rowCountHover = 2;
|
2290
|
+
rowCountHover = isMultiLine && colorsCount >= fit * 2 ? 3 : rowCountHover;
|
2291
|
+
rowCountHover = colorsCount >= fit * 3 ? 4 : rowCountHover;
|
2292
|
+
rowCountHover = colorsCount >= fit * 4 ? 5 : rowCountHover;
|
2293
|
+
const rowCount = rowCountHover - (colorsCount < fit * 3 ? 1 : 2);
|
2294
|
+
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2295
2295
|
let finalClass = menuClass;
|
2296
2296
|
finalClass += isScrollable ? ' scrollable' : '';
|
2297
2297
|
finalClass += isMultiLine ? ' multiline' : '';
|
2298
2298
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2299
2299
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2300
|
-
optionSize =
|
2300
|
+
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2301
2301
|
const menuHeight = `${(rowCount || 1) * optionSize}rem`;
|
2302
2302
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2303
|
+
/** @type {HTMLUListElement} */
|
2304
|
+
// @ts-ignore -- <UL> is an `HTMLElement`
|
2306
2305
|
const menu = createElement({
|
2307
2306
|
tagName: 'ul',
|
2308
2307
|
className: finalClass,
|
2309
2308
|
});
|
2310
2309
|
setAttribute(menu, 'role', 'listbox');
|
2311
|
-
setAttribute(menu, ariaLabel,
|
2312
|
-
|
2313
|
-
if (
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
};
|
2322
|
-
setElementStyle(menu, menuStyle);
|
2310
|
+
setAttribute(menu, ariaLabel, menuLabel);
|
2311
|
+
|
2312
|
+
if (isScrollable) {
|
2313
|
+
setCSSProperties(menu, {
|
2314
|
+
'--grid-item-size': `${optionSize}rem`,
|
2315
|
+
'--grid-fit': fit,
|
2316
|
+
'--grid-gap': gap,
|
2317
|
+
'--grid-height': menuHeight,
|
2318
|
+
'--grid-hover-height': menuHeightHover,
|
2319
|
+
});
|
2323
2320
|
}
|
2324
2321
|
|
2325
2322
|
colorsArray.forEach((x) => {
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2323
|
+
let [value, label] = typeof x === 'string' ? x.trim().split(':') : [];
|
2324
|
+
if (x instanceof Color) {
|
2325
|
+
value = x.toHexString();
|
2326
|
+
label = value;
|
2327
|
+
}
|
2328
|
+
const color = new Color(x instanceof Color ? x : value, format);
|
2329
|
+
const isActive = color.toString() === getAttribute(input, 'value');
|
2329
2330
|
const active = isActive ? ' active' : '';
|
2330
2331
|
|
2331
2332
|
const option = createElement({
|
2332
2333
|
tagName: 'li',
|
2333
2334
|
className: `color-option${active}`,
|
2334
|
-
innerText: `${label ||
|
2335
|
+
innerText: `${label || value}`,
|
2335
2336
|
});
|
2336
2337
|
|
2337
|
-
setAttribute(option,
|
2338
|
+
setAttribute(option, tabIndex, '0');
|
2338
2339
|
setAttribute(option, 'data-value', `${value}`);
|
2339
2340
|
setAttribute(option, 'role', 'option');
|
2340
2341
|
setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
|
2341
2342
|
|
2342
2343
|
if (isOptionsMenu) {
|
2343
|
-
setElementStyle(option, {
|
2344
|
-
width: `${optionSize}rem`, height: `${optionSize}rem`, backgroundColor: x,
|
2345
|
-
});
|
2344
|
+
setElementStyle(option, { backgroundColor: value });
|
2346
2345
|
}
|
2347
2346
|
|
2348
2347
|
menu.append(option);
|
@@ -2351,55 +2350,10 @@
|
|
2351
2350
|
}
|
2352
2351
|
|
2353
2352
|
/**
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
function isValidJSON(str) {
|
2359
|
-
try {
|
2360
|
-
JSON.parse(str);
|
2361
|
-
} catch (e) {
|
2362
|
-
return false;
|
2363
|
-
}
|
2364
|
-
return true;
|
2365
|
-
}
|
2366
|
-
|
2367
|
-
var version = "0.0.1alpha2";
|
2368
|
-
|
2369
|
-
// @ts-ignore
|
2370
|
-
|
2371
|
-
const Version = version;
|
2372
|
-
|
2373
|
-
// ColorPicker GC
|
2374
|
-
// ==============
|
2375
|
-
const colorPickerString = 'color-picker';
|
2376
|
-
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2377
|
-
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2378
|
-
const colorPickerDefaults = {
|
2379
|
-
componentLabels: colorPickerLabels,
|
2380
|
-
colorLabels: colorNames,
|
2381
|
-
format: 'rgb',
|
2382
|
-
colorPresets: undefined,
|
2383
|
-
colorKeywords: nonColors,
|
2384
|
-
};
|
2385
|
-
|
2386
|
-
// ColorPicker Static Methods
|
2387
|
-
// ==========================
|
2388
|
-
|
2389
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2390
|
-
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2391
|
-
|
2392
|
-
/** @type {CP.InitCallback<ColorPicker>} */
|
2393
|
-
const initColorPicker = (element) => new ColorPicker(element);
|
2394
|
-
|
2395
|
-
// ColorPicker Private Methods
|
2396
|
-
// ===========================
|
2397
|
-
|
2398
|
-
/**
|
2399
|
-
* Generate HTML markup and update instance properties.
|
2400
|
-
* @param {ColorPicker} self
|
2401
|
-
*/
|
2402
|
-
function initCallback(self) {
|
2353
|
+
* Generate HTML markup and update instance properties.
|
2354
|
+
* @param {CP.ColorPicker} self
|
2355
|
+
*/
|
2356
|
+
function setMarkup(self) {
|
2403
2357
|
const {
|
2404
2358
|
input, parent, format, id, componentLabels, colorKeywords, colorPresets,
|
2405
2359
|
} = self;
|
@@ -2414,9 +2368,7 @@
|
|
2414
2368
|
self.color = new Color(color, format);
|
2415
2369
|
|
2416
2370
|
// set initial controls dimensions
|
2417
|
-
|
2418
|
-
const dropClass = isMobile ? ' mobile' : '';
|
2419
|
-
const formatString = format === 'hex' ? hexLabel : format.toUpperCase();
|
2371
|
+
const formatString = format === 'hex' ? hexLabel : toUpperCase(format);
|
2420
2372
|
|
2421
2373
|
const pickerBtn = createElement({
|
2422
2374
|
id: `picker-btn-${id}`,
|
@@ -2433,7 +2385,7 @@
|
|
2433
2385
|
|
2434
2386
|
const pickerDropdown = createElement({
|
2435
2387
|
tagName: 'div',
|
2436
|
-
className:
|
2388
|
+
className: 'color-dropdown picker',
|
2437
2389
|
});
|
2438
2390
|
setAttribute(pickerDropdown, ariaLabelledBy, `picker-btn-${id}`);
|
2439
2391
|
setAttribute(pickerDropdown, 'role', 'group');
|
@@ -2449,7 +2401,7 @@
|
|
2449
2401
|
if (colorKeywords || colorPresets) {
|
2450
2402
|
const presetsDropdown = createElement({
|
2451
2403
|
tagName: 'div',
|
2452
|
-
className:
|
2404
|
+
className: 'color-dropdown scrollable menu',
|
2453
2405
|
});
|
2454
2406
|
|
2455
2407
|
// color presets
|
@@ -2469,7 +2421,7 @@
|
|
2469
2421
|
tagName: 'button',
|
2470
2422
|
className: 'menu-toggle btn-appearance',
|
2471
2423
|
});
|
2472
|
-
setAttribute(presetsBtn,
|
2424
|
+
setAttribute(presetsBtn, tabIndex, '-1');
|
2473
2425
|
setAttribute(presetsBtn, ariaExpanded, 'false');
|
2474
2426
|
setAttribute(presetsBtn, ariaHasPopup, 'true');
|
2475
2427
|
|
@@ -2496,9 +2448,40 @@
|
|
2496
2448
|
if (colorKeywords && nonColors.includes(colorValue)) {
|
2497
2449
|
self.value = colorValue;
|
2498
2450
|
}
|
2499
|
-
setAttribute(input,
|
2451
|
+
setAttribute(input, tabIndex, '-1');
|
2500
2452
|
}
|
2501
2453
|
|
2454
|
+
var version = "0.0.2alpha1";
|
2455
|
+
|
2456
|
+
// @ts-ignore
|
2457
|
+
|
2458
|
+
const Version = version;
|
2459
|
+
|
2460
|
+
// ColorPicker GC
|
2461
|
+
// ==============
|
2462
|
+
const colorPickerString = 'color-picker';
|
2463
|
+
const colorPickerSelector = `[data-function="${colorPickerString}"]`;
|
2464
|
+
const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
|
2465
|
+
const colorPickerDefaults = {
|
2466
|
+
componentLabels: colorPickerLabels,
|
2467
|
+
colorLabels: colorNames,
|
2468
|
+
format: 'rgb',
|
2469
|
+
colorPresets: false,
|
2470
|
+
colorKeywords: false,
|
2471
|
+
};
|
2472
|
+
|
2473
|
+
// ColorPicker Static Methods
|
2474
|
+
// ==========================
|
2475
|
+
|
2476
|
+
/** @type {CP.GetInstance<ColorPicker>} */
|
2477
|
+
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2478
|
+
|
2479
|
+
/** @type {CP.InitCallback<ColorPicker>} */
|
2480
|
+
const initColorPicker = (element) => new ColorPicker(element);
|
2481
|
+
|
2482
|
+
// ColorPicker Private Methods
|
2483
|
+
// ===========================
|
2484
|
+
|
2502
2485
|
/**
|
2503
2486
|
* Add / remove `ColorPicker` main event listeners.
|
2504
2487
|
* @param {ColorPicker} self
|
@@ -2597,8 +2580,19 @@
|
|
2597
2580
|
addClass(dropdown, 'bottom');
|
2598
2581
|
reflow(dropdown);
|
2599
2582
|
addClass(dropdown, 'show');
|
2583
|
+
|
2600
2584
|
if (isPicker) self.update();
|
2601
|
-
|
2585
|
+
|
2586
|
+
if (!self.isOpen) {
|
2587
|
+
toggleEventsOnShown(self, true);
|
2588
|
+
self.updateDropdownPosition();
|
2589
|
+
self.isOpen = true;
|
2590
|
+
setAttribute(self.input, tabIndex, '0');
|
2591
|
+
if (menuToggle) {
|
2592
|
+
setAttribute(menuToggle, tabIndex, '0');
|
2593
|
+
}
|
2594
|
+
}
|
2595
|
+
|
2602
2596
|
setAttribute(nextBtn, ariaExpanded, 'true');
|
2603
2597
|
if (activeBtn) {
|
2604
2598
|
setAttribute(activeBtn, ariaExpanded, 'false');
|
@@ -2721,7 +2715,7 @@
|
|
2721
2715
|
self.handleKnobs = self.handleKnobs.bind(self);
|
2722
2716
|
|
2723
2717
|
// generate markup
|
2724
|
-
|
2718
|
+
setMarkup(self);
|
2725
2719
|
|
2726
2720
|
const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
|
2727
2721
|
// set main elements
|
@@ -2768,7 +2762,7 @@
|
|
2768
2762
|
set value(v) { this.input.value = v; }
|
2769
2763
|
|
2770
2764
|
/** Check if the colour presets include any non-colour. */
|
2771
|
-
get
|
2765
|
+
get hasNonColor() {
|
2772
2766
|
return this.colorKeywords instanceof Array
|
2773
2767
|
&& this.colorKeywords.some((x) => nonColors.includes(x));
|
2774
2768
|
}
|
@@ -2824,7 +2818,7 @@
|
|
2824
2818
|
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
2825
2819
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2826
2820
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2827
|
-
const roundA =
|
2821
|
+
const roundA = roundPart((alpha * 100)) / 100;
|
2828
2822
|
|
2829
2823
|
if (format !== 'hsl') {
|
2830
2824
|
const fill = new Color({
|
@@ -2842,7 +2836,7 @@
|
|
2842
2836
|
});
|
2843
2837
|
setElementStyle(v2, { background: hueGradient });
|
2844
2838
|
} else {
|
2845
|
-
const saturation =
|
2839
|
+
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2846
2840
|
const fill0 = new Color({
|
2847
2841
|
r: 255, g: 0, b: 0, a: alpha,
|
2848
2842
|
}).saturate(-saturation).toRgbString();
|
@@ -2917,7 +2911,7 @@
|
|
2917
2911
|
const self = this;
|
2918
2912
|
const { activeElement } = getDocument(self.input);
|
2919
2913
|
|
2920
|
-
if ((
|
2914
|
+
if ((e.type === touchmoveEvent && self.dragElement)
|
2921
2915
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2922
2916
|
e.stopPropagation();
|
2923
2917
|
e.preventDefault();
|
@@ -2997,12 +2991,12 @@
|
|
2997
2991
|
|
2998
2992
|
self.update();
|
2999
2993
|
|
3000
|
-
if (currentActive) {
|
3001
|
-
removeClass(currentActive, 'active');
|
3002
|
-
removeAttribute(currentActive, ariaSelected);
|
3003
|
-
}
|
3004
|
-
|
3005
2994
|
if (currentActive !== target) {
|
2995
|
+
if (currentActive) {
|
2996
|
+
removeClass(currentActive, 'active');
|
2997
|
+
removeAttribute(currentActive, ariaSelected);
|
2998
|
+
}
|
2999
|
+
|
3006
3000
|
addClass(target, 'active');
|
3007
3001
|
setAttribute(target, ariaSelected, 'true');
|
3008
3002
|
|
@@ -3124,30 +3118,41 @@
|
|
3124
3118
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
3125
3119
|
e.preventDefault();
|
3126
3120
|
|
3127
|
-
const { controlKnobs } = self;
|
3121
|
+
const { format, controlKnobs, visuals } = self;
|
3122
|
+
const { offsetWidth, offsetHeight } = visuals[0];
|
3128
3123
|
const [c1, c2, c3] = controlKnobs;
|
3129
3124
|
const { activeElement } = getDocument(c1);
|
3130
3125
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3126
|
+
const yRatio = offsetHeight / (format === 'hsl' ? 100 : 360);
|
3131
3127
|
|
3132
3128
|
if (currentKnob) {
|
3133
3129
|
let offsetX = 0;
|
3134
3130
|
let offsetY = 0;
|
3131
|
+
|
3135
3132
|
if (target === c1) {
|
3133
|
+
const xRatio = offsetWidth / (format === 'hsl' ? 360 : 100);
|
3134
|
+
|
3136
3135
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3137
|
-
self.controlPositions.c1x += code === keyArrowRight ?
|
3136
|
+
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
3138
3137
|
} else if ([keyArrowUp, keyArrowDown].includes(code)) {
|
3139
|
-
self.controlPositions.c1y += code === keyArrowDown ?
|
3138
|
+
self.controlPositions.c1y += code === keyArrowDown ? yRatio : -yRatio;
|
3140
3139
|
}
|
3141
3140
|
|
3142
3141
|
offsetX = self.controlPositions.c1x;
|
3143
3142
|
offsetY = self.controlPositions.c1y;
|
3144
3143
|
self.changeControl1(offsetX, offsetY);
|
3145
3144
|
} else if (target === c2) {
|
3146
|
-
self.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code)
|
3145
|
+
self.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code)
|
3146
|
+
? yRatio
|
3147
|
+
: -yRatio;
|
3148
|
+
|
3147
3149
|
offsetY = self.controlPositions.c2y;
|
3148
3150
|
self.changeControl2(offsetY);
|
3149
3151
|
} else if (target === c3) {
|
3150
|
-
self.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code)
|
3152
|
+
self.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code)
|
3153
|
+
? yRatio
|
3154
|
+
: -yRatio;
|
3155
|
+
|
3151
3156
|
offsetY = self.controlPositions.c3y;
|
3152
3157
|
self.changeAlpha(offsetY);
|
3153
3158
|
}
|
@@ -3169,7 +3174,7 @@
|
|
3169
3174
|
const [v1, v2, v3, v4] = format === 'rgb'
|
3170
3175
|
? inputs.map((i) => parseFloat(i.value) / (i === i4 ? 100 : 1))
|
3171
3176
|
: inputs.map((i) => parseFloat(i.value) / (i !== i1 ? 100 : 360));
|
3172
|
-
const isNonColorValue = self.
|
3177
|
+
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3173
3178
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3174
3179
|
|
3175
3180
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
@@ -3428,11 +3433,11 @@
|
|
3428
3433
|
} = componentLabels;
|
3429
3434
|
const { r, g, b } = color.toRgb();
|
3430
3435
|
const [knob1, knob2, knob3] = controlKnobs;
|
3431
|
-
const hue =
|
3436
|
+
const hue = roundPart(hsl.h * 360);
|
3432
3437
|
const alpha = color.a;
|
3433
3438
|
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
3434
|
-
const saturation =
|
3435
|
-
const lightness =
|
3439
|
+
const saturation = roundPart(saturationSource * 100);
|
3440
|
+
const lightness = roundPart(hsl.l * 100);
|
3436
3441
|
const hsvl = hsv.v * 100;
|
3437
3442
|
let colorName;
|
3438
3443
|
|
@@ -3479,8 +3484,8 @@
|
|
3479
3484
|
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3480
3485
|
} else if (format === 'hwb') {
|
3481
3486
|
const { hwb } = self;
|
3482
|
-
const whiteness =
|
3483
|
-
const blackness =
|
3487
|
+
const whiteness = roundPart(hwb.w * 100);
|
3488
|
+
const blackness = roundPart(hwb.b * 100);
|
3484
3489
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3485
3490
|
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3486
3491
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
@@ -3496,7 +3501,7 @@
|
|
3496
3501
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3497
3502
|
}
|
3498
3503
|
|
3499
|
-
const alphaValue =
|
3504
|
+
const alphaValue = roundPart(alpha * 100);
|
3500
3505
|
setAttribute(knob3, ariaValueText, `${alphaValue}%`);
|
3501
3506
|
setAttribute(knob3, ariaValueNow, `${alphaValue}`);
|
3502
3507
|
|
@@ -3519,10 +3524,16 @@
|
|
3519
3524
|
/** Updates the control knobs actual positions. */
|
3520
3525
|
updateControls() {
|
3521
3526
|
const { controlKnobs, controlPositions } = this;
|
3527
|
+
let {
|
3528
|
+
c1x, c1y, c2y, c3y,
|
3529
|
+
} = controlPositions;
|
3522
3530
|
const [control1, control2, control3] = controlKnobs;
|
3523
|
-
|
3524
|
-
|
3525
|
-
|
3531
|
+
// round control positions
|
3532
|
+
[c1x, c1y, c2y, c3y] = [c1x, c1y, c2y, c3y].map(roundPart);
|
3533
|
+
|
3534
|
+
setElementStyle(control1, { transform: `translate3d(${c1x - 4}px,${c1y - 4}px,0)` });
|
3535
|
+
setElementStyle(control2, { transform: `translate3d(0,${c2y - 4}px,0)` });
|
3536
|
+
setElementStyle(control3, { transform: `translate3d(0,${c3y - 4}px,0)` });
|
3526
3537
|
}
|
3527
3538
|
|
3528
3539
|
/**
|
@@ -3535,16 +3546,16 @@
|
|
3535
3546
|
value: oldColor, format, inputs, color, hsl,
|
3536
3547
|
} = self;
|
3537
3548
|
const [i1, i2, i3, i4] = inputs;
|
3538
|
-
const alpha =
|
3539
|
-
const hue =
|
3549
|
+
const alpha = roundPart(color.a * 100);
|
3550
|
+
const hue = roundPart(hsl.h * 360);
|
3540
3551
|
let newColor;
|
3541
3552
|
|
3542
3553
|
if (format === 'hex') {
|
3543
3554
|
newColor = self.color.toHexString(true);
|
3544
3555
|
i1.value = self.hex;
|
3545
3556
|
} else if (format === 'hsl') {
|
3546
|
-
const lightness =
|
3547
|
-
const saturation =
|
3557
|
+
const lightness = roundPart(hsl.l * 100);
|
3558
|
+
const saturation = roundPart(hsl.s * 100);
|
3548
3559
|
newColor = self.color.toHslString();
|
3549
3560
|
i1.value = `${hue}`;
|
3550
3561
|
i2.value = `${saturation}`;
|
@@ -3552,8 +3563,8 @@
|
|
3552
3563
|
i4.value = `${alpha}`;
|
3553
3564
|
} else if (format === 'hwb') {
|
3554
3565
|
const { w, b } = self.hwb;
|
3555
|
-
const whiteness =
|
3556
|
-
const blackness =
|
3566
|
+
const whiteness = roundPart(w * 100);
|
3567
|
+
const blackness = roundPart(b * 100);
|
3557
3568
|
|
3558
3569
|
newColor = self.color.toHwbString();
|
3559
3570
|
i1.value = `${hue}`;
|
@@ -3561,7 +3572,8 @@
|
|
3561
3572
|
i3.value = `${blackness}`;
|
3562
3573
|
i4.value = `${alpha}`;
|
3563
3574
|
} else if (format === 'rgb') {
|
3564
|
-
|
3575
|
+
let { r, g, b } = self.rgb;
|
3576
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
3565
3577
|
|
3566
3578
|
newColor = self.color.toRgbString();
|
3567
3579
|
i1.value = `${r}`;
|
@@ -3625,7 +3637,7 @@
|
|
3625
3637
|
const self = this;
|
3626
3638
|
const { colorPicker } = self;
|
3627
3639
|
|
3628
|
-
if (!hasClass(colorPicker,
|
3640
|
+
if (!['top', 'bottom'].some((c) => hasClass(colorPicker, c))) {
|
3629
3641
|
showDropdown(self, colorPicker);
|
3630
3642
|
}
|
3631
3643
|
}
|
@@ -3642,21 +3654,6 @@
|
|
3642
3654
|
}
|
3643
3655
|
}
|
3644
3656
|
|
3645
|
-
/** Shows the `ColorPicker` dropdown or the presets menu. */
|
3646
|
-
show() {
|
3647
|
-
const self = this;
|
3648
|
-
const { menuToggle } = self;
|
3649
|
-
if (!self.isOpen) {
|
3650
|
-
toggleEventsOnShown(self, true);
|
3651
|
-
self.updateDropdownPosition();
|
3652
|
-
self.isOpen = true;
|
3653
|
-
setAttribute(self.input, 'tabindex', '0');
|
3654
|
-
if (menuToggle) {
|
3655
|
-
setAttribute(menuToggle, 'tabindex', '0');
|
3656
|
-
}
|
3657
|
-
}
|
3658
|
-
}
|
3659
|
-
|
3660
3657
|
/**
|
3661
3658
|
* Hides the currently open `ColorPicker` dropdown.
|
3662
3659
|
* @param {boolean=} focusPrevented
|
@@ -3691,9 +3688,9 @@
|
|
3691
3688
|
if (!focusPrevented) {
|
3692
3689
|
focus(pickerToggle);
|
3693
3690
|
}
|
3694
|
-
setAttribute(input,
|
3691
|
+
setAttribute(input, tabIndex, '-1');
|
3695
3692
|
if (menuToggle) {
|
3696
|
-
setAttribute(menuToggle,
|
3693
|
+
setAttribute(menuToggle, tabIndex, '-1');
|
3697
3694
|
}
|
3698
3695
|
}
|
3699
3696
|
}
|
@@ -3707,7 +3704,10 @@
|
|
3707
3704
|
[...parent.children].forEach((el) => {
|
3708
3705
|
if (el !== input) el.remove();
|
3709
3706
|
});
|
3707
|
+
|
3708
|
+
removeAttribute(input, tabIndex);
|
3710
3709
|
setElementStyle(input, { backgroundColor: '' });
|
3710
|
+
|
3711
3711
|
['txt-light', 'txt-dark'].forEach((c) => removeClass(parent, c));
|
3712
3712
|
Data.remove(input, colorPickerString);
|
3713
3713
|
}
|
@@ -3715,10 +3715,16 @@
|
|
3715
3715
|
|
3716
3716
|
ObjectAssign(ColorPicker, {
|
3717
3717
|
Color,
|
3718
|
+
ColorPalette,
|
3718
3719
|
Version,
|
3719
3720
|
getInstance: getColorPickerInstance,
|
3720
3721
|
init: initColorPicker,
|
3721
3722
|
selector: colorPickerSelector,
|
3723
|
+
// utils important for render
|
3724
|
+
roundPart,
|
3725
|
+
setElementStyle,
|
3726
|
+
setAttribute,
|
3727
|
+
getBoundingClientRect,
|
3722
3728
|
});
|
3723
3729
|
|
3724
3730
|
let CPID = 0;
|
@@ -3726,8 +3732,9 @@
|
|
3726
3732
|
/**
|
3727
3733
|
* `ColorPickerElement` Web Component.
|
3728
3734
|
* @example
|
3729
|
-
* <
|
3730
|
-
*
|
3735
|
+
* <label for="UNIQUE_ID">Label</label>
|
3736
|
+
* <color-picker data-format="hex" data-value="#075">
|
3737
|
+
* <input id="UNIQUE_ID" type="text" class="color-preview btn-appearance">
|
3731
3738
|
* </color-picker>
|
3732
3739
|
*/
|
3733
3740
|
class ColorPickerElement extends HTMLElement {
|
@@ -3808,6 +3815,8 @@
|
|
3808
3815
|
ObjectAssign(ColorPickerElement, {
|
3809
3816
|
Color,
|
3810
3817
|
ColorPicker,
|
3818
|
+
ColorPalette,
|
3819
|
+
getInstance: getColorPickerInstance,
|
3811
3820
|
Version,
|
3812
3821
|
});
|
3813
3822
|
|
@@ -3815,4 +3824,4 @@
|
|
3815
3824
|
|
3816
3825
|
return ColorPickerElement;
|
3817
3826
|
|
3818
|
-
}))
|
3827
|
+
}));
|