@thednp/color-picker 0.0.1 → 0.0.2-alpha3
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 +3 -1
- package/dist/css/color-picker.css +1 -1
- package/dist/css/color-picker.min.css +1 -1
- package/dist/css/color-picker.rtl.css +1 -1
- package/dist/css/color-picker.rtl.min.css +1 -1
- package/dist/js/color-esm.js +1167 -0
- package/dist/js/color-esm.min.js +2 -0
- package/dist/js/color-palette-esm.js +1238 -0
- package/dist/js/color-palette-esm.min.js +2 -0
- package/dist/js/color-palette.js +1246 -0
- package/dist/js/color-palette.min.js +2 -0
- package/dist/js/color-picker-element-esm.js +543 -671
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +545 -673
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +758 -878
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +760 -880
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1175 -0
- package/dist/js/color.min.js +2 -0
- package/package.json +22 -3
- package/src/js/color-palette.js +18 -14
- package/src/js/color-picker-element.js +47 -55
- package/src/js/color-picker.js +137 -325
- package/src/js/color.js +169 -185
- package/src/js/util/getColorMenu.js +12 -7
- package/src/js/util/setMarkup.js +122 -0
- package/src/js/util/version.js +6 -0
- package/types/cp.d.ts +64 -32
- package/types/source/types.d.ts +1 -1
- package/src/js/util/templates.js +0 -10
package/src/js/color-picker.js
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
import { addListener, removeListener } from 'event-listener.js';
|
2
2
|
|
3
3
|
import ariaDescription from 'shorter-js/src/strings/ariaDescription';
|
4
|
-
// import ariaLabel from 'shorter-js/src/strings/ariaLabel';
|
5
4
|
import ariaSelected from 'shorter-js/src/strings/ariaSelected';
|
6
5
|
import ariaExpanded from 'shorter-js/src/strings/ariaExpanded';
|
7
6
|
import ariaValueText from 'shorter-js/src/strings/ariaValueText';
|
8
7
|
import ariaValueNow from 'shorter-js/src/strings/ariaValueNow';
|
9
|
-
import ariaHasPopup from 'shorter-js/src/strings/ariaHasPopup';
|
10
|
-
import ariaHidden from 'shorter-js/src/strings/ariaHidden';
|
11
|
-
import ariaLabelledBy from 'shorter-js/src/strings/ariaLabelledBy';
|
12
8
|
import keyArrowDown from 'shorter-js/src/strings/keyArrowDown';
|
13
9
|
import keyArrowUp from 'shorter-js/src/strings/keyArrowUp';
|
14
10
|
import keyArrowLeft from 'shorter-js/src/strings/keyArrowLeft';
|
@@ -31,7 +27,6 @@ import keyupEvent from 'shorter-js/src/strings/keyupEvent';
|
|
31
27
|
import resizeEvent from 'shorter-js/src/strings/resizeEvent';
|
32
28
|
import focusoutEvent from 'shorter-js/src/strings/focusoutEvent';
|
33
29
|
|
34
|
-
import isMobile from 'shorter-js/src/boolean/isMobile';
|
35
30
|
import getDocument from 'shorter-js/src/get/getDocument';
|
36
31
|
import getDocumentElement from 'shorter-js/src/get/getDocumentElement';
|
37
32
|
import getWindow from 'shorter-js/src/get/getWindow';
|
@@ -42,8 +37,6 @@ import getElementTransitionDuration from 'shorter-js/src/get/getElementTransitio
|
|
42
37
|
import querySelector from 'shorter-js/src/selectors/querySelector';
|
43
38
|
import closest from 'shorter-js/src/selectors/closest';
|
44
39
|
import getElementsByClassName from 'shorter-js/src/selectors/getElementsByClassName';
|
45
|
-
import createElement from 'shorter-js/src/misc/createElement';
|
46
|
-
import createElementNS from 'shorter-js/src/misc/createElementNS';
|
47
40
|
import dispatchEvent from 'shorter-js/src/misc/dispatchEvent';
|
48
41
|
import ObjectAssign from 'shorter-js/src/misc/ObjectAssign';
|
49
42
|
import Data, { getInstance } from 'shorter-js/src/misc/data';
|
@@ -60,19 +53,16 @@ import removeAttribute from 'shorter-js/src/attr/removeAttribute';
|
|
60
53
|
|
61
54
|
// ColorPicker Util
|
62
55
|
// ================
|
56
|
+
import Color from './color';
|
57
|
+
import ColorPalette from './color-palette';
|
63
58
|
import colorPickerLabels from './util/colorPickerLabels';
|
64
59
|
import colorNames from './util/colorNames';
|
65
60
|
import nonColors from './util/nonColors';
|
66
|
-
import getColorForm from './util/getColorForm';
|
67
|
-
import getColorControls from './util/getColorControls';
|
68
|
-
import getColorMenu from './util/getColorMenu';
|
69
|
-
import vHidden from './util/vHidden';
|
70
61
|
import tabIndex from './util/tabindex';
|
71
62
|
import isValidJSON from './util/isValidJSON';
|
72
63
|
import roundPart from './util/roundPart';
|
73
|
-
import
|
74
|
-
import
|
75
|
-
import Version from './version';
|
64
|
+
import setMarkup from './util/setMarkup';
|
65
|
+
import Version from './util/version';
|
76
66
|
|
77
67
|
// ColorPicker GC
|
78
68
|
// ==============
|
@@ -91,7 +81,7 @@ const colorPickerDefaults = {
|
|
91
81
|
// ==========================
|
92
82
|
|
93
83
|
/** @type {CP.GetInstance<ColorPicker>} */
|
94
|
-
|
84
|
+
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
95
85
|
|
96
86
|
/** @type {CP.InitCallback<ColorPicker>} */
|
97
87
|
const initColorPicker = (element) => new ColorPicker(element);
|
@@ -99,110 +89,6 @@ const initColorPicker = (element) => new ColorPicker(element);
|
|
99
89
|
// ColorPicker Private Methods
|
100
90
|
// ===========================
|
101
91
|
|
102
|
-
/**
|
103
|
-
* Generate HTML markup and update instance properties.
|
104
|
-
* @param {ColorPicker} self
|
105
|
-
*/
|
106
|
-
function initCallback(self) {
|
107
|
-
const {
|
108
|
-
input, parent, format, id, componentLabels, colorKeywords, colorPresets,
|
109
|
-
} = self;
|
110
|
-
const colorValue = getAttribute(input, 'value') || '#fff';
|
111
|
-
|
112
|
-
const {
|
113
|
-
toggleLabel, pickerLabel, formatLabel, hexLabel,
|
114
|
-
} = componentLabels;
|
115
|
-
|
116
|
-
// update color
|
117
|
-
const color = nonColors.includes(colorValue) ? '#fff' : colorValue;
|
118
|
-
self.color = new Color(color, format);
|
119
|
-
|
120
|
-
// set initial controls dimensions
|
121
|
-
// make the controls smaller on mobile
|
122
|
-
const dropClass = isMobile ? ' mobile' : '';
|
123
|
-
const formatString = format === 'hex' ? hexLabel : format.toUpperCase();
|
124
|
-
|
125
|
-
const pickerBtn = createElement({
|
126
|
-
id: `picker-btn-${id}`,
|
127
|
-
tagName: 'button',
|
128
|
-
className: 'picker-toggle btn-appearance',
|
129
|
-
});
|
130
|
-
setAttribute(pickerBtn, ariaExpanded, 'false');
|
131
|
-
setAttribute(pickerBtn, ariaHasPopup, 'true');
|
132
|
-
pickerBtn.append(createElement({
|
133
|
-
tagName: 'span',
|
134
|
-
className: vHidden,
|
135
|
-
innerText: `${pickerLabel}. ${formatLabel}: ${formatString}`,
|
136
|
-
}));
|
137
|
-
|
138
|
-
const pickerDropdown = createElement({
|
139
|
-
tagName: 'div',
|
140
|
-
className: `color-dropdown picker${dropClass}`,
|
141
|
-
});
|
142
|
-
setAttribute(pickerDropdown, ariaLabelledBy, `picker-btn-${id}`);
|
143
|
-
setAttribute(pickerDropdown, 'role', 'group');
|
144
|
-
|
145
|
-
const colorControls = getColorControls(self);
|
146
|
-
const colorForm = getColorForm(self);
|
147
|
-
|
148
|
-
pickerDropdown.append(colorControls, colorForm);
|
149
|
-
input.before(pickerBtn);
|
150
|
-
parent.append(pickerDropdown);
|
151
|
-
|
152
|
-
// set colour key menu template
|
153
|
-
if (colorKeywords || colorPresets) {
|
154
|
-
const presetsDropdown = createElement({
|
155
|
-
tagName: 'div',
|
156
|
-
className: `color-dropdown scrollable menu${dropClass}`,
|
157
|
-
});
|
158
|
-
|
159
|
-
// color presets
|
160
|
-
if ((colorPresets instanceof Array && colorPresets.length)
|
161
|
-
|| (colorPresets instanceof ColorPalette && colorPresets.colors)) {
|
162
|
-
const presetsMenu = getColorMenu(self, colorPresets, 'color-options');
|
163
|
-
presetsDropdown.append(presetsMenu);
|
164
|
-
}
|
165
|
-
|
166
|
-
// explicit defaults [reset, initial, inherit, transparent, currentColor]
|
167
|
-
if (colorKeywords && colorKeywords.length) {
|
168
|
-
const keywordsMenu = getColorMenu(self, colorKeywords, 'color-defaults');
|
169
|
-
presetsDropdown.append(keywordsMenu);
|
170
|
-
}
|
171
|
-
|
172
|
-
const presetsBtn = createElement({
|
173
|
-
tagName: 'button',
|
174
|
-
className: 'menu-toggle btn-appearance',
|
175
|
-
});
|
176
|
-
setAttribute(presetsBtn, tabIndex, '-1');
|
177
|
-
setAttribute(presetsBtn, ariaExpanded, 'false');
|
178
|
-
setAttribute(presetsBtn, ariaHasPopup, 'true');
|
179
|
-
|
180
|
-
const xmlns = encodeURI('http://www.w3.org/2000/svg');
|
181
|
-
const presetsIcon = createElementNS(xmlns, { tagName: 'svg' });
|
182
|
-
setAttribute(presetsIcon, 'xmlns', xmlns);
|
183
|
-
setAttribute(presetsIcon, 'viewBox', '0 0 512 512');
|
184
|
-
setAttribute(presetsIcon, ariaHidden, 'true');
|
185
|
-
|
186
|
-
const path = createElementNS(xmlns, { tagName: 'path' });
|
187
|
-
setAttribute(path, 'd', 'M98,158l157,156L411,158l27,27L255,368L71,185L98,158z');
|
188
|
-
setAttribute(path, 'fill', '#fff');
|
189
|
-
presetsIcon.append(path);
|
190
|
-
presetsBtn.append(createElement({
|
191
|
-
tagName: 'span',
|
192
|
-
className: vHidden,
|
193
|
-
innerText: `${toggleLabel}`,
|
194
|
-
}), presetsIcon);
|
195
|
-
|
196
|
-
parent.append(presetsBtn, presetsDropdown);
|
197
|
-
}
|
198
|
-
|
199
|
-
// solve non-colors after settings save
|
200
|
-
if (colorKeywords && nonColors.includes(colorValue)) {
|
201
|
-
self.value = colorValue;
|
202
|
-
}
|
203
|
-
setAttribute(input, tabIndex, '-1');
|
204
|
-
}
|
205
|
-
|
206
92
|
/**
|
207
93
|
* Add / remove `ColorPicker` main event listeners.
|
208
94
|
* @param {ColorPicker} self
|
@@ -215,8 +101,6 @@ function toggleEvents(self, action) {
|
|
215
101
|
fn(input, focusinEvent, self.showPicker);
|
216
102
|
fn(pickerToggle, mouseclickEvent, self.togglePicker);
|
217
103
|
|
218
|
-
fn(input, keydownEvent, self.keyToggle);
|
219
|
-
|
220
104
|
if (menuToggle) {
|
221
105
|
fn(menuToggle, mouseclickEvent, self.toggleMenu);
|
222
106
|
}
|
@@ -254,8 +138,7 @@ function toggleEventsOnShown(self, action) {
|
|
254
138
|
fn(doc, pointerEvents.move, self.pointerMove);
|
255
139
|
fn(doc, pointerEvents.up, self.pointerUp);
|
256
140
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
257
|
-
|
258
|
-
fn(win, keyupEvent, self.handleDismiss);
|
141
|
+
fn(doc, keyupEvent, self.handleDismiss);
|
259
142
|
}
|
260
143
|
|
261
144
|
/**
|
@@ -339,7 +222,7 @@ export default class ColorPicker {
|
|
339
222
|
const input = querySelector(target);
|
340
223
|
|
341
224
|
// invalidate
|
342
|
-
if (!input) throw new TypeError(`ColorPicker target ${target} cannot be found.`);
|
225
|
+
if (!input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
|
343
226
|
self.input = input;
|
344
227
|
|
345
228
|
const parent = closest(input, colorPickerParentSelector);
|
@@ -386,15 +269,14 @@ export default class ColorPicker {
|
|
386
269
|
});
|
387
270
|
|
388
271
|
// update and expose component labels
|
389
|
-
const
|
390
|
-
|
391
|
-
? JSON.parse(componentLabels) : componentLabels || {};
|
272
|
+
const tempComponentLabels = componentLabels && isValidJSON(componentLabels)
|
273
|
+
? JSON.parse(componentLabels) : componentLabels;
|
392
274
|
|
393
275
|
/** @type {Record<string, string>} */
|
394
|
-
self.componentLabels = ObjectAssign(
|
276
|
+
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
395
277
|
|
396
278
|
/** @type {Color} */
|
397
|
-
self.color = new Color('
|
279
|
+
self.color = new Color(input.value || '#fff', format);
|
398
280
|
|
399
281
|
/** @type {CP.ColorFormats} */
|
400
282
|
self.format = format;
|
@@ -403,7 +285,7 @@ export default class ColorPicker {
|
|
403
285
|
if (colorKeywords instanceof Array) {
|
404
286
|
self.colorKeywords = colorKeywords;
|
405
287
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
406
|
-
self.colorKeywords = colorKeywords.split(',');
|
288
|
+
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
407
289
|
}
|
408
290
|
|
409
291
|
// set colour presets
|
@@ -432,11 +314,10 @@ export default class ColorPicker {
|
|
432
314
|
self.handleFocusOut = self.handleFocusOut.bind(self);
|
433
315
|
self.changeHandler = self.changeHandler.bind(self);
|
434
316
|
self.handleDismiss = self.handleDismiss.bind(self);
|
435
|
-
self.keyToggle = self.keyToggle.bind(self);
|
436
317
|
self.handleKnobs = self.handleKnobs.bind(self);
|
437
318
|
|
438
319
|
// generate markup
|
439
|
-
|
320
|
+
setMarkup(self);
|
440
321
|
|
441
322
|
const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
|
442
323
|
// set main elements
|
@@ -524,76 +405,83 @@ export default class ColorPicker {
|
|
524
405
|
return inputValue !== '' && new Color(inputValue).isValid;
|
525
406
|
}
|
526
407
|
|
408
|
+
/** Returns the colour appearance, usually the closest colour name for the current value. */
|
409
|
+
get appearance() {
|
410
|
+
const {
|
411
|
+
colorLabels, hsl, hsv, format,
|
412
|
+
} = this;
|
413
|
+
|
414
|
+
const hue = roundPart(hsl.h * 360);
|
415
|
+
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
416
|
+
const saturation = roundPart(saturationSource * 100);
|
417
|
+
const lightness = roundPart(hsl.l * 100);
|
418
|
+
const hsvl = hsv.v * 100;
|
419
|
+
|
420
|
+
let colorName;
|
421
|
+
|
422
|
+
// determine color appearance
|
423
|
+
if (lightness === 100 && saturation === 0) {
|
424
|
+
colorName = colorLabels.white;
|
425
|
+
} else if (lightness === 0) {
|
426
|
+
colorName = colorLabels.black;
|
427
|
+
} else if (saturation === 0) {
|
428
|
+
colorName = colorLabels.grey;
|
429
|
+
} else if (hue < 15 || hue >= 345) {
|
430
|
+
colorName = colorLabels.red;
|
431
|
+
} else if (hue >= 15 && hue < 45) {
|
432
|
+
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
433
|
+
} else if (hue >= 45 && hue < 75) {
|
434
|
+
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
435
|
+
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
436
|
+
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
437
|
+
colorName = isOlive ? colorLabels.olive : colorName;
|
438
|
+
} else if (hue >= 75 && hue < 155) {
|
439
|
+
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
440
|
+
} else if (hue >= 155 && hue < 175) {
|
441
|
+
colorName = colorLabels.teal;
|
442
|
+
} else if (hue >= 175 && hue < 195) {
|
443
|
+
colorName = colorLabels.cyan;
|
444
|
+
} else if (hue >= 195 && hue < 255) {
|
445
|
+
colorName = colorLabels.blue;
|
446
|
+
} else if (hue >= 255 && hue < 270) {
|
447
|
+
colorName = colorLabels.violet;
|
448
|
+
} else if (hue >= 270 && hue < 295) {
|
449
|
+
colorName = colorLabels.magenta;
|
450
|
+
} else if (hue >= 295 && hue < 345) {
|
451
|
+
colorName = colorLabels.pink;
|
452
|
+
}
|
453
|
+
return colorName;
|
454
|
+
}
|
455
|
+
|
527
456
|
/** Updates `ColorPicker` visuals. */
|
528
457
|
updateVisuals() {
|
529
458
|
const self = this;
|
530
459
|
const {
|
531
|
-
|
460
|
+
controlPositions, visuals,
|
532
461
|
} = self;
|
533
462
|
const [v1, v2, v3] = visuals;
|
534
|
-
const {
|
535
|
-
const hue =
|
536
|
-
|
537
|
-
: controlPositions.c2y / offsetHeight;
|
538
|
-
// @ts-ignore - `hslToRgb` is assigned to `Color` as static method
|
539
|
-
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
463
|
+
const { offsetHeight } = v1;
|
464
|
+
const hue = controlPositions.c2y / offsetHeight;
|
465
|
+
const { r, g, b } = new Color({ h: hue, s: 1, l: 0.5 }).toRgb();
|
540
466
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
541
467
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
542
468
|
const roundA = roundPart((alpha * 100)) / 100;
|
543
469
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
setElementStyle(v2, { background: hueGradient });
|
559
|
-
} else {
|
560
|
-
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
561
|
-
const fill0 = new Color({
|
562
|
-
r: 255, g: 0, b: 0, a: alpha,
|
563
|
-
}).saturate(-saturation).toRgbString();
|
564
|
-
const fill1 = new Color({
|
565
|
-
r: 255, g: 255, b: 0, a: alpha,
|
566
|
-
}).saturate(-saturation).toRgbString();
|
567
|
-
const fill2 = new Color({
|
568
|
-
r: 0, g: 255, b: 0, a: alpha,
|
569
|
-
}).saturate(-saturation).toRgbString();
|
570
|
-
const fill3 = new Color({
|
571
|
-
r: 0, g: 255, b: 255, a: alpha,
|
572
|
-
}).saturate(-saturation).toRgbString();
|
573
|
-
const fill4 = new Color({
|
574
|
-
r: 0, g: 0, b: 255, a: alpha,
|
575
|
-
}).saturate(-saturation).toRgbString();
|
576
|
-
const fill5 = new Color({
|
577
|
-
r: 255, g: 0, b: 255, a: alpha,
|
578
|
-
}).saturate(-saturation).toRgbString();
|
579
|
-
const fill6 = new Color({
|
580
|
-
r: 255, g: 0, b: 0, a: alpha,
|
581
|
-
}).saturate(-saturation).toRgbString();
|
582
|
-
const fillGradient = `linear-gradient(to right,
|
583
|
-
${fill0} 0%, ${fill1} 16.67%, ${fill2} 33.33%, ${fill3} 50%,
|
584
|
-
${fill4} 66.67%, ${fill5} 83.33%, ${fill6} 100%)`;
|
585
|
-
const lightGrad = `linear-gradient(rgba(255,255,255,${roundA}) 0%, rgba(255,255,255,0) 50%),
|
586
|
-
linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,${roundA}) 100%)`;
|
587
|
-
|
588
|
-
setElementStyle(v1, { background: `${lightGrad},${fillGradient},${whiteGrad}` });
|
589
|
-
const {
|
590
|
-
r: gr, g: gg, b: gb,
|
591
|
-
} = new Color({ r, g, b }).greyscale().toRgb();
|
470
|
+
const fill = new Color({
|
471
|
+
h: hue, s: 1, l: 0.5, a: alpha,
|
472
|
+
}).toRgbString();
|
473
|
+
const hueGradient = `linear-gradient(
|
474
|
+
rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
|
475
|
+
rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
|
476
|
+
rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
|
477
|
+
rgb(255,0,0) 100%)`;
|
478
|
+
setElementStyle(v1, {
|
479
|
+
background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
|
480
|
+
linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
|
481
|
+
${whiteGrad}`,
|
482
|
+
});
|
483
|
+
setElementStyle(v2, { background: hueGradient });
|
592
484
|
|
593
|
-
setElementStyle(v2, {
|
594
|
-
background: `linear-gradient(rgb(${r},${g},${b}) 0%, rgb(${gr},${gg},${gb}) 100%)`,
|
595
|
-
});
|
596
|
-
}
|
597
485
|
setElementStyle(v3, {
|
598
486
|
background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
|
599
487
|
});
|
@@ -632,7 +520,7 @@ export default class ColorPicker {
|
|
632
520
|
const self = this;
|
633
521
|
const { activeElement } = getDocument(self.input);
|
634
522
|
|
635
|
-
if ((
|
523
|
+
if ((e.type === touchmoveEvent && self.dragElement)
|
636
524
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
637
525
|
e.stopPropagation();
|
638
526
|
e.preventDefault();
|
@@ -743,13 +631,13 @@ export default class ColorPicker {
|
|
743
631
|
const [v1, v2, v3] = visuals;
|
744
632
|
const [c1, c2, c3] = controlKnobs;
|
745
633
|
/** @type {HTMLElement} */
|
746
|
-
const visual =
|
747
|
-
? target : querySelector('.visual-control', target.parentElement);
|
634
|
+
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
748
635
|
const visualRect = getBoundingClientRect(visual);
|
636
|
+
const html = getDocumentElement(v1);
|
749
637
|
const X = type === 'touchstart' ? touches[0].pageX : pageX;
|
750
638
|
const Y = type === 'touchstart' ? touches[0].pageY : pageY;
|
751
|
-
const offsetX = X -
|
752
|
-
const offsetY = Y -
|
639
|
+
const offsetX = X - html.scrollLeft - visualRect.left;
|
640
|
+
const offsetY = Y - html.scrollTop - visualRect.top;
|
753
641
|
|
754
642
|
if (target === v1 || target === c1) {
|
755
643
|
self.dragElement = visual;
|
@@ -809,10 +697,11 @@ export default class ColorPicker {
|
|
809
697
|
if (!dragElement) return;
|
810
698
|
|
811
699
|
const controlRect = getBoundingClientRect(dragElement);
|
812
|
-
const
|
813
|
-
const
|
814
|
-
const
|
815
|
-
const
|
700
|
+
const win = getDocumentElement(v1);
|
701
|
+
const X = type === touchmoveEvent ? touches[0].pageX : pageX;
|
702
|
+
const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
|
703
|
+
const offsetX = X - win.scrollLeft - controlRect.left;
|
704
|
+
const offsetY = Y - win.scrollTop - controlRect.top;
|
816
705
|
|
817
706
|
if (dragElement === v1) {
|
818
707
|
self.changeControl1(offsetX, offsetY);
|
@@ -839,19 +728,19 @@ export default class ColorPicker {
|
|
839
728
|
if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
|
840
729
|
e.preventDefault();
|
841
730
|
|
842
|
-
const {
|
731
|
+
const { controlKnobs, visuals } = self;
|
843
732
|
const { offsetWidth, offsetHeight } = visuals[0];
|
844
733
|
const [c1, c2, c3] = controlKnobs;
|
845
734
|
const { activeElement } = getDocument(c1);
|
846
735
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
847
|
-
const yRatio = offsetHeight /
|
736
|
+
const yRatio = offsetHeight / 360;
|
848
737
|
|
849
738
|
if (currentKnob) {
|
850
739
|
let offsetX = 0;
|
851
740
|
let offsetY = 0;
|
852
741
|
|
853
742
|
if (target === c1) {
|
854
|
-
const xRatio = offsetWidth /
|
743
|
+
const xRatio = offsetWidth / 100;
|
855
744
|
|
856
745
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
857
746
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
@@ -901,7 +790,7 @@ export default class ColorPicker {
|
|
901
790
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
902
791
|
if (activeElement === input) {
|
903
792
|
if (isNonColorValue) {
|
904
|
-
colorSource = '
|
793
|
+
colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
|
905
794
|
} else {
|
906
795
|
colorSource = currentValue;
|
907
796
|
}
|
@@ -952,9 +841,7 @@ export default class ColorPicker {
|
|
952
841
|
changeControl1(X, Y) {
|
953
842
|
const self = this;
|
954
843
|
let [offsetX, offsetY] = [0, 0];
|
955
|
-
const {
|
956
|
-
format, controlPositions, visuals,
|
957
|
-
} = self;
|
844
|
+
const { controlPositions, visuals } = self;
|
958
845
|
const { offsetHeight, offsetWidth } = visuals[0];
|
959
846
|
|
960
847
|
if (X > offsetWidth) offsetX = offsetWidth;
|
@@ -963,29 +850,19 @@ export default class ColorPicker {
|
|
963
850
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
964
851
|
else if (Y >= 0) offsetY = Y;
|
965
852
|
|
966
|
-
const hue =
|
967
|
-
? offsetX / offsetWidth
|
968
|
-
: controlPositions.c2y / offsetHeight;
|
853
|
+
const hue = controlPositions.c2y / offsetHeight;
|
969
854
|
|
970
|
-
const saturation =
|
971
|
-
? 1 - controlPositions.c2y / offsetHeight
|
972
|
-
: offsetX / offsetWidth;
|
855
|
+
const saturation = offsetX / offsetWidth;
|
973
856
|
|
974
857
|
const lightness = 1 - offsetY / offsetHeight;
|
975
858
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
976
859
|
|
977
|
-
const colorObject = format === 'hsl'
|
978
|
-
? {
|
979
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
980
|
-
}
|
981
|
-
: {
|
982
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
983
|
-
};
|
984
|
-
|
985
860
|
// new color
|
986
861
|
const {
|
987
862
|
r, g, b, a,
|
988
|
-
} = new Color(
|
863
|
+
} = new Color({
|
864
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
865
|
+
});
|
989
866
|
|
990
867
|
ObjectAssign(self.color, {
|
991
868
|
r, g, b, a,
|
@@ -1012,7 +889,7 @@ export default class ColorPicker {
|
|
1012
889
|
changeControl2(Y) {
|
1013
890
|
const self = this;
|
1014
891
|
const {
|
1015
|
-
|
892
|
+
controlPositions, visuals,
|
1016
893
|
} = self;
|
1017
894
|
const { offsetHeight, offsetWidth } = visuals[0];
|
1018
895
|
|
@@ -1021,26 +898,17 @@ export default class ColorPicker {
|
|
1021
898
|
if (Y > offsetHeight) offsetY = offsetHeight;
|
1022
899
|
else if (Y >= 0) offsetY = Y;
|
1023
900
|
|
1024
|
-
const hue =
|
1025
|
-
|
1026
|
-
: offsetY / offsetHeight;
|
1027
|
-
const saturation = format === 'hsl'
|
1028
|
-
? 1 - offsetY / offsetHeight
|
1029
|
-
: controlPositions.c1x / offsetWidth;
|
901
|
+
const hue = offsetY / offsetHeight;
|
902
|
+
const saturation = controlPositions.c1x / offsetWidth;
|
1030
903
|
const lightness = 1 - controlPositions.c1y / offsetHeight;
|
1031
904
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
1032
|
-
const colorObject = format === 'hsl'
|
1033
|
-
? {
|
1034
|
-
h: hue, s: saturation, l: lightness, a: alpha,
|
1035
|
-
}
|
1036
|
-
: {
|
1037
|
-
h: hue, s: saturation, v: lightness, a: alpha,
|
1038
|
-
};
|
1039
905
|
|
1040
906
|
// new color
|
1041
907
|
const {
|
1042
908
|
r, g, b, a,
|
1043
|
-
} = new Color(
|
909
|
+
} = new Color({
|
910
|
+
h: hue, s: saturation, v: lightness, a: alpha,
|
911
|
+
});
|
1044
912
|
|
1045
913
|
ObjectAssign(self.color, {
|
1046
914
|
r, g, b, a,
|
@@ -1127,18 +995,18 @@ export default class ColorPicker {
|
|
1127
995
|
setControlPositions() {
|
1128
996
|
const self = this;
|
1129
997
|
const {
|
1130
|
-
|
998
|
+
visuals, color, hsv,
|
1131
999
|
} = self;
|
1132
1000
|
const { offsetHeight, offsetWidth } = visuals[0];
|
1133
1001
|
const alpha = color.a;
|
1134
|
-
const hue =
|
1002
|
+
const hue = hsv.h;
|
1135
1003
|
|
1136
|
-
const saturation =
|
1137
|
-
const lightness =
|
1004
|
+
const saturation = hsv.s;
|
1005
|
+
const lightness = hsv.v;
|
1138
1006
|
|
1139
|
-
self.controlPositions.c1x =
|
1007
|
+
self.controlPositions.c1x = saturation * offsetWidth;
|
1140
1008
|
self.controlPositions.c1y = (1 - lightness) * offsetHeight;
|
1141
|
-
self.controlPositions.c2y =
|
1009
|
+
self.controlPositions.c2y = hue * offsetHeight;
|
1142
1010
|
self.controlPositions.c3y = (1 - alpha) * offsetHeight;
|
1143
1011
|
}
|
1144
1012
|
|
@@ -1146,78 +1014,40 @@ export default class ColorPicker {
|
|
1146
1014
|
updateAppearance() {
|
1147
1015
|
const self = this;
|
1148
1016
|
const {
|
1149
|
-
componentLabels,
|
1150
|
-
|
1017
|
+
componentLabels, color, parent,
|
1018
|
+
hsv, hex, format, controlKnobs,
|
1151
1019
|
} = self;
|
1152
1020
|
const {
|
1153
1021
|
appearanceLabel, hexLabel, valueLabel,
|
1154
1022
|
} = componentLabels;
|
1155
|
-
|
1023
|
+
let { r, g, b } = color.toRgb();
|
1156
1024
|
const [knob1, knob2, knob3] = controlKnobs;
|
1157
|
-
const hue = roundPart(
|
1025
|
+
const hue = roundPart(hsv.h * 360);
|
1158
1026
|
const alpha = color.a;
|
1159
|
-
const
|
1160
|
-
const
|
1161
|
-
const
|
1162
|
-
const hsvl = hsv.v * 100;
|
1163
|
-
let colorName;
|
1164
|
-
|
1165
|
-
// determine color appearance
|
1166
|
-
if (lightness === 100 && saturation === 0) {
|
1167
|
-
colorName = colorLabels.white;
|
1168
|
-
} else if (lightness === 0) {
|
1169
|
-
colorName = colorLabels.black;
|
1170
|
-
} else if (saturation === 0) {
|
1171
|
-
colorName = colorLabels.grey;
|
1172
|
-
} else if (hue < 15 || hue >= 345) {
|
1173
|
-
colorName = colorLabels.red;
|
1174
|
-
} else if (hue >= 15 && hue < 45) {
|
1175
|
-
colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
|
1176
|
-
} else if (hue >= 45 && hue < 75) {
|
1177
|
-
const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
|
1178
|
-
const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
|
1179
|
-
colorName = isGold ? colorLabels.gold : colorLabels.yellow;
|
1180
|
-
colorName = isOlive ? colorLabels.olive : colorName;
|
1181
|
-
} else if (hue >= 75 && hue < 155) {
|
1182
|
-
colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
|
1183
|
-
} else if (hue >= 155 && hue < 175) {
|
1184
|
-
colorName = colorLabels.teal;
|
1185
|
-
} else if (hue >= 175 && hue < 195) {
|
1186
|
-
colorName = colorLabels.cyan;
|
1187
|
-
} else if (hue >= 195 && hue < 255) {
|
1188
|
-
colorName = colorLabels.blue;
|
1189
|
-
} else if (hue >= 255 && hue < 270) {
|
1190
|
-
colorName = colorLabels.violet;
|
1191
|
-
} else if (hue >= 270 && hue < 295) {
|
1192
|
-
colorName = colorLabels.magenta;
|
1193
|
-
} else if (hue >= 295 && hue < 345) {
|
1194
|
-
colorName = colorLabels.pink;
|
1195
|
-
}
|
1027
|
+
const saturation = roundPart(hsv.s * 100);
|
1028
|
+
const lightness = roundPart(hsv.v * 100);
|
1029
|
+
const colorName = self.appearance;
|
1196
1030
|
|
1197
1031
|
let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
|
1198
1032
|
|
1199
|
-
if (format === '
|
1200
|
-
colorLabel = `HSL: ${hue}°, ${saturation}%, ${lightness}%`;
|
1201
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
1202
|
-
setAttribute(knob1, ariaValueText, `${hue}° & ${lightness}%`);
|
1203
|
-
setAttribute(knob1, ariaValueNow, `${hue}`);
|
1204
|
-
setAttribute(knob2, ariaValueText, `${saturation}%`);
|
1205
|
-
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
1206
|
-
} else if (format === 'hwb') {
|
1033
|
+
if (format === 'hwb') {
|
1207
1034
|
const { hwb } = self;
|
1208
1035
|
const whiteness = roundPart(hwb.w * 100);
|
1209
1036
|
const blackness = roundPart(hwb.b * 100);
|
1210
1037
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
1211
|
-
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
1212
1038
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
1213
1039
|
setAttribute(knob1, ariaValueNow, `${whiteness}`);
|
1040
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
1214
1041
|
setAttribute(knob2, ariaValueText, `${hue}%`);
|
1215
1042
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
1216
1043
|
} else {
|
1044
|
+
[r, g, b] = [r, g, b].map(roundPart);
|
1045
|
+
colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
|
1217
1046
|
colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
|
1218
|
-
|
1047
|
+
|
1219
1048
|
setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
|
1220
1049
|
setAttribute(knob1, ariaValueNow, `${lightness}`);
|
1050
|
+
setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
1221
1051
|
setAttribute(knob2, ariaValueText, `${hue}°`);
|
1222
1052
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
1223
1053
|
}
|
@@ -1312,37 +1142,13 @@ export default class ColorPicker {
|
|
1312
1142
|
}
|
1313
1143
|
}
|
1314
1144
|
|
1315
|
-
/**
|
1316
|
-
* The `Space` & `Enter` keys specific event listener.
|
1317
|
-
* Toggle visibility of the `ColorPicker` / the presets menu, showing one will hide the other.
|
1318
|
-
* @param {KeyboardEvent} e
|
1319
|
-
* @this {ColorPicker}
|
1320
|
-
*/
|
1321
|
-
keyToggle(e) {
|
1322
|
-
const self = this;
|
1323
|
-
const { menuToggle } = self;
|
1324
|
-
const { activeElement } = getDocument(menuToggle);
|
1325
|
-
const { code } = e;
|
1326
|
-
|
1327
|
-
if ([keyEnter, keySpace].includes(code)) {
|
1328
|
-
if ((menuToggle && activeElement === menuToggle) || !activeElement) {
|
1329
|
-
e.preventDefault();
|
1330
|
-
if (!activeElement) {
|
1331
|
-
self.togglePicker(e);
|
1332
|
-
} else {
|
1333
|
-
self.toggleMenu();
|
1334
|
-
}
|
1335
|
-
}
|
1336
|
-
}
|
1337
|
-
}
|
1338
|
-
|
1339
1145
|
/**
|
1340
1146
|
* Toggle the `ColorPicker` dropdown visibility.
|
1341
|
-
* @param {Event} e
|
1147
|
+
* @param {Event=} e
|
1342
1148
|
* @this {ColorPicker}
|
1343
1149
|
*/
|
1344
1150
|
togglePicker(e) {
|
1345
|
-
e.preventDefault();
|
1151
|
+
if (e) e.preventDefault();
|
1346
1152
|
const self = this;
|
1347
1153
|
const { colorPicker } = self;
|
1348
1154
|
|
@@ -1363,8 +1169,13 @@ export default class ColorPicker {
|
|
1363
1169
|
}
|
1364
1170
|
}
|
1365
1171
|
|
1366
|
-
/**
|
1367
|
-
|
1172
|
+
/**
|
1173
|
+
* Toggles the visibility of the `ColorPicker` presets menu.
|
1174
|
+
* @param {Event=} e
|
1175
|
+
* @this {ColorPicker}
|
1176
|
+
*/
|
1177
|
+
toggleMenu(e) {
|
1178
|
+
if (e) e.preventDefault();
|
1368
1179
|
const self = this;
|
1369
1180
|
const { colorMenu } = self;
|
1370
1181
|
|
@@ -1390,6 +1201,10 @@ export default class ColorPicker {
|
|
1390
1201
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
1391
1202
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
1392
1203
|
|
1204
|
+
// if (!self.isValid) {
|
1205
|
+
self.value = self.color.toString(true);
|
1206
|
+
// }
|
1207
|
+
|
1393
1208
|
if (openDropdown) {
|
1394
1209
|
removeClass(openDropdown, 'show');
|
1395
1210
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
@@ -1403,9 +1218,6 @@ export default class ColorPicker {
|
|
1403
1218
|
}, animationDuration);
|
1404
1219
|
}
|
1405
1220
|
|
1406
|
-
if (!self.isValid) {
|
1407
|
-
self.value = self.color.toString();
|
1408
|
-
}
|
1409
1221
|
if (!focusPrevented) {
|
1410
1222
|
focus(pickerToggle);
|
1411
1223
|
}
|