@thednp/color-picker 2.0.2 → 2.0.4

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.
Files changed (55) hide show
  1. package/README.md +25 -14
  2. package/dist/css/color-picker.css +3 -6
  3. package/dist/css/color-picker.css.map +1 -0
  4. package/dist/css/color-picker.min.css +1 -2
  5. package/dist/css/color-picker.min.css.map +1 -0
  6. package/dist/css/color-picker.rtl.css +3 -6
  7. package/dist/css/color-picker.rtl.css.map +1 -0
  8. package/dist/css/color-picker.rtl.min.css +1 -2
  9. package/dist/css/color-picker.rtl.min.css.map +1 -0
  10. package/dist/js/color-picker.cjs +2 -2
  11. package/dist/js/color-picker.cjs.map +1 -1
  12. package/dist/js/color-picker.d.ts +307 -300
  13. package/dist/js/color-picker.js +2 -2
  14. package/dist/js/color-picker.js.map +1 -1
  15. package/dist/js/color-picker.mjs +390 -491
  16. package/dist/js/color-picker.mjs.map +1 -1
  17. package/package.json +40 -47
  18. package/.eslintrc.cjs +0 -199
  19. package/.lgtm.yml +0 -9
  20. package/.prettierrc.json +0 -15
  21. package/.stylelintrc.json +0 -236
  22. package/compile.cjs +0 -51
  23. package/dts.config.ts +0 -15
  24. package/src/scss/_variables.scss +0 -6
  25. package/src/scss/color-picker.rtl.scss +0 -27
  26. package/src/scss/color-picker.scss +0 -536
  27. package/src/ts/colorPalette.ts +0 -89
  28. package/src/ts/index.ts +0 -1237
  29. package/src/ts/interface/ColorNames.ts +0 -20
  30. package/src/ts/interface/colorPickerLabels.ts +0 -20
  31. package/src/ts/interface/colorPickerOptions.ts +0 -11
  32. package/src/ts/interface/paletteOptions.ts +0 -6
  33. package/src/ts/util/colorNames.ts +0 -21
  34. package/src/ts/util/colorPickerLabels.ts +0 -24
  35. package/src/ts/util/getColorControls.ts +0 -90
  36. package/src/ts/util/getColorForm.ts +0 -75
  37. package/src/ts/util/getColorMenu.ts +0 -83
  38. package/src/ts/util/isValidJSON.ts +0 -19
  39. package/src/ts/util/setMarkup.ts +0 -130
  40. package/src/ts/util/vHidden.ts +0 -2
  41. package/test/color-palette.test.ts +0 -137
  42. package/test/color-picker.test.ts +0 -705
  43. package/test/fixtures/colorNamesFrench.js +0 -3
  44. package/test/fixtures/componentLabelsFrench.js +0 -21
  45. package/test/fixtures/format.js +0 -3
  46. package/test/fixtures/getMarkup.js +0 -36
  47. package/test/fixtures/getRandomInt.js +0 -6
  48. package/test/fixtures/sampleWebcolors.js +0 -18
  49. package/test/fixtures/swipe.ts +0 -33
  50. package/test/fixtures/testSample.js +0 -8
  51. package/test/fixtures/write.ts +0 -37
  52. package/tsconfig.json +0 -47
  53. package/vite.config.mts +0 -27
  54. package/vitest.config-ui.ts +0 -26
  55. package/vitest.config.ts +0 -26
package/src/ts/index.ts DELETED
@@ -1,1237 +0,0 @@
1
- import {
2
- ariaDescription,
3
- ariaSelected,
4
- ariaValueNow,
5
- ariaValueText,
6
- ariaExpanded,
7
- keyArrowDown,
8
- keyArrowUp,
9
- keyArrowLeft,
10
- keyArrowRight,
11
- keyEnter,
12
- keySpace,
13
- keyEscape,
14
- focusinEvent,
15
- mouseclickEvent,
16
- keydownEvent,
17
- changeEvent,
18
- touchmoveEvent,
19
- pointerdownEvent,
20
- pointermoveEvent,
21
- pointerupEvent,
22
- tabindex,
23
- focusoutEvent,
24
- resizeEvent,
25
- keyupEvent,
26
- scrollEvent,
27
- dispatchEvent,
28
- getElementsByClassName,
29
- closest,
30
- querySelector,
31
- getElementTransitionDuration,
32
- getBoundingClientRect,
33
- getUID,
34
- getElementStyle,
35
- getDocumentElement,
36
- getDocument,
37
- ObjectAssign,
38
- ObjectFromEntries,
39
- Data,
40
- getInstance,
41
- setElementStyle,
42
- normalizeOptions,
43
- reflow,
44
- focus,
45
- hasClass,
46
- addClass,
47
- removeClass,
48
- setAttribute,
49
- getAttribute,
50
- removeAttribute,
51
- isArray,
52
- isString,
53
- getWindow,
54
- on,
55
- off,
56
- } from '@thednp/shorty';
57
-
58
- // ColorPicker Util
59
- // ================
60
- import Color from '@thednp/color';
61
- import type { RGBA, HWBA, HSLA, HSVA } from '@thednp/color';
62
-
63
- import ColorPalette from './colorPalette';
64
- import colorPickerLabels from './util/colorPickerLabels';
65
- import colorNames from './util/colorNames';
66
- import isValidJSON from './util/isValidJSON';
67
- import setMarkup from './util/setMarkup';
68
-
69
- import ColorPickerOptions from './interface/colorPickerOptions';
70
- import ColorPickerLabels from './interface/colorPickerLabels';
71
- import type ColorNames from './interface/ColorNames';
72
- import { version } from '../../package.json';
73
-
74
- // ColorPicker GC
75
- // ==============
76
- const colorPickerString = 'color-picker';
77
- const colorPickerSelector = `[data-function="${colorPickerString}"]`;
78
- const colorPickerParentSelector = `.${colorPickerString}`;
79
- const colorPickerDefaults: ColorPickerOptions = {
80
- componentLabels: colorPickerLabels,
81
- colorLabels: colorNames,
82
- format: 'rgb',
83
- colorPresets: false,
84
- colorKeywords: false,
85
- };
86
- const { roundPart, nonColors } = Color;
87
-
88
- // ColorPicker Static Methods
89
- // ==========================
90
- const getColorPickerInstance = (element: HTMLInputElement) => getInstance<ColorPicker>(element, colorPickerString);
91
- const initColorPicker = (element: HTMLInputElement) => new ColorPicker(element);
92
-
93
- // ColorPicker Private Methods
94
- // ===========================
95
-
96
- /**
97
- * Add / remove `ColorPicker` main event listeners.
98
- */
99
- const toggleEvents = (self: ColorPicker, action?: boolean) => {
100
- const fn = action ? on : off;
101
- const { input, pickerToggle, menuToggle } = self;
102
-
103
- fn(input, focusinEvent, self.showPicker);
104
- fn(pickerToggle, mouseclickEvent, self.togglePicker);
105
-
106
- if (menuToggle) {
107
- fn(menuToggle, mouseclickEvent, self.toggleMenu);
108
- }
109
- };
110
-
111
- /**
112
- * Add / remove `ColorPicker` event listeners active only when open.
113
- */
114
- const toggleEventsOnShown = (self: ColorPicker, action?: boolean) => {
115
- const fn = action ? on : off;
116
- const { input, colorMenu, parent } = self;
117
- const doc = getDocument(input);
118
- const win = getWindow(doc);
119
-
120
- fn(self.controls, pointerdownEvent, self.pointerDown);
121
- self.controlKnobs.forEach(x => fn(x, keydownEvent, self.handleKnobs));
122
-
123
- fn(win, scrollEvent, self.handleScroll);
124
- fn(win, resizeEvent, self.update);
125
-
126
- [input, ...self.inputs].forEach(x => fn(x, changeEvent, self.changeHandler));
127
-
128
- if (colorMenu) {
129
- fn(colorMenu, mouseclickEvent, self.menuClickHandler);
130
- fn(colorMenu, keydownEvent, self.menuKeyHandler);
131
- }
132
-
133
- fn(doc, pointermoveEvent, self.pointerMove);
134
- fn(doc, pointerupEvent, self.pointerUp);
135
- fn(parent, focusoutEvent, self.handleFocusOut);
136
- fn(doc, keyupEvent, self.handleDismiss);
137
- };
138
-
139
- /**
140
- * Triggers the `ColorPicker` original event.
141
- */
142
- const firePickerChange = (self: ColorPicker) => {
143
- dispatchEvent(self.input, new CustomEvent('colorpicker.change'));
144
- };
145
-
146
- /**
147
- * Hides a visible dropdown.
148
- */
149
- const removePosition = (element: HTMLElement) => {
150
- /* istanbul ignore else */
151
- if (element) {
152
- ['bottom', 'top'].forEach(x => removeClass(element, x));
153
- }
154
- };
155
-
156
- /**
157
- * Shows a `ColorPicker` dropdown and close the curent open dropdown.
158
- */
159
- const showDropdown = (self: ColorPicker, dropdown: HTMLElement) => {
160
- const { colorPicker, colorMenu, menuToggle, pickerToggle, parent } = self;
161
- const isPicker = dropdown === colorPicker;
162
- const openDropdown = isPicker ? colorMenu : colorPicker;
163
- const activeBtn = isPicker ? menuToggle : pickerToggle;
164
- const nextBtn = !isPicker ? menuToggle : pickerToggle;
165
-
166
- if (!hasClass(parent, 'open')) {
167
- addClass(parent, 'open');
168
- }
169
- if (openDropdown) {
170
- removeClass(openDropdown, 'show');
171
- removePosition(openDropdown);
172
- }
173
- addClass(dropdown, 'bottom');
174
- reflow(dropdown);
175
- addClass(dropdown, 'show');
176
-
177
- if (isPicker) self.update();
178
-
179
- if (!self.isOpen) {
180
- toggleEventsOnShown(self, true);
181
- self.updateDropdownPosition();
182
- self.isOpen = true;
183
- setAttribute(self.input, tabindex, '0');
184
- if (menuToggle) {
185
- setAttribute(menuToggle, tabindex, '0');
186
- }
187
- }
188
-
189
- setAttribute(nextBtn, ariaExpanded, 'true');
190
- if (activeBtn) {
191
- setAttribute(activeBtn, ariaExpanded, 'false');
192
- }
193
- };
194
-
195
- /**
196
- * Color Picker Web Component
197
- *
198
- * @see http://thednp.github.io/color-picker
199
- */
200
- export default class ColorPicker {
201
- // bring utils to staic
202
- public static Color = Color;
203
- public static ColorPalette = ColorPalette;
204
- public static getInstance = getColorPickerInstance;
205
- public static init = initColorPicker;
206
- public static selector = colorPickerSelector;
207
- // utils important for render
208
- public static roundPart = roundPart;
209
- public static setElementStyle = setElementStyle;
210
- public static setAttribute = setAttribute;
211
- public static getBoundingClientRect = getBoundingClientRect;
212
- public static version = version;
213
- public static colorNames = colorNames;
214
- public static colorPickerLabels = colorPickerLabels;
215
-
216
- id: number;
217
- input: HTMLInputElement;
218
- color: Color;
219
- format = 'rgb';
220
- parent: HTMLElement;
221
- dragElement: HTMLElement | undefined;
222
- isOpen = false;
223
- controlPositions: {
224
- c1x: number;
225
- c1y: number;
226
- c2y: number;
227
- c3y: number;
228
- };
229
- colorLabels: ColorNames = ObjectFromEntries(colorNames.map(c => [c, c])) as ColorNames;
230
- colorKeywords: string[] | false;
231
- colorPresets: ColorPalette | string[] | false;
232
- componentLabels: ColorPickerLabels;
233
- pickerToggle: HTMLElement;
234
- menuToggle: HTMLElement;
235
- colorPicker: HTMLElement;
236
- colorMenu: HTMLElement;
237
- controls: HTMLElement;
238
- inputs: HTMLInputElement[];
239
- controlKnobs: HTMLElement[];
240
- visuals: HTMLElement[];
241
-
242
- /**
243
- * Returns a new `ColorPicker` instance. The target of this constructor
244
- * must be an `HTMLInputElement`.
245
- *
246
- * @param target the target `<input>` element
247
- * @param config instance options
248
- */
249
- constructor(target: (HTMLElement & HTMLInputElement) | string, config?: Partial<ColorPickerOptions>) {
250
- const input = querySelector(target) as HTMLInputElement;
251
-
252
- // invalidate
253
- if (typeof target === 'undefined') throw new TypeError(`ColorPicker target not specified.`);
254
- if (isString(target) && !input) throw new TypeError(`ColorPicker target "${target}" cannot be found.`);
255
- this.input = input;
256
-
257
- const parent = closest(input, colorPickerParentSelector);
258
- if (!parent) throw new TypeError('ColorPicker requires a specific markup to work.');
259
-
260
- this.parent = parent;
261
- this.id = getUID(input, colorPickerString);
262
- this.dragElement = undefined;
263
- this.isOpen = false;
264
- this.controlPositions = {
265
- c1x: 0,
266
- c1y: 0,
267
- c2y: 0,
268
- c3y: 0,
269
- };
270
- // this.colorLabels = {};
271
- this.colorKeywords = false;
272
- this.colorPresets = false;
273
-
274
- // process options
275
- const { format, componentLabels, colorLabels, colorKeywords, colorPresets } = normalizeOptions(
276
- input,
277
- colorPickerDefaults,
278
- config || {},
279
- );
280
-
281
- let translatedColorLabels = colorNames;
282
- /* istanbul ignore else */
283
- if (isArray(colorLabels) && colorLabels.length === 17) {
284
- translatedColorLabels = colorLabels;
285
- } else if (isString(colorLabels) && colorLabels.split(',').length === 17) {
286
- translatedColorLabels = colorLabels.split(',');
287
- }
288
-
289
- // expose colour labels to all methods
290
- ObjectAssign(this.colorLabels, ObjectFromEntries(translatedColorLabels.map((c, i) => [colorNames[i], c])));
291
-
292
- // update and expose component labels
293
- const tempComponentLabels =
294
- isString(componentLabels) && isValidJSON(componentLabels)
295
- ? (JSON.parse(componentLabels) as ColorPickerLabels)
296
- : componentLabels;
297
- this.componentLabels = ObjectAssign({ ...colorPickerLabels }, tempComponentLabels);
298
- this.color = new Color(input.value || '#fff', format);
299
- this.format = format;
300
-
301
- // set colour defaults
302
- if (isArray(colorKeywords) && colorKeywords.length) {
303
- this.colorKeywords = colorKeywords;
304
- } else if (isString(colorKeywords) && colorKeywords.length) {
305
- this.colorKeywords = colorKeywords.split(',').map(x => x.trim());
306
- }
307
-
308
- // set colour presets
309
- if (isArray(colorPresets) && colorPresets.length) {
310
- this.colorPresets = colorPresets;
311
- } else if (colorPresets && isValidJSON(colorPresets)) {
312
- const { hue, hueSteps, lightSteps, saturation } = JSON.parse(colorPresets) as {
313
- hue: number;
314
- hueSteps: number;
315
- lightSteps: number;
316
- saturation: number;
317
- };
318
- this.colorPresets = new ColorPalette(hue, hueSteps, lightSteps, saturation);
319
- } else if (isString(colorPresets)) {
320
- this.colorPresets = colorPresets.split(',').map((x: string) => x.trim());
321
- }
322
-
323
- // generate markup
324
- setMarkup(this);
325
-
326
- const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
327
- // set main elements
328
- this.pickerToggle = querySelector('.picker-toggle', parent) as HTMLElement;
329
- this.menuToggle = querySelector('.menu-toggle', parent) as HTMLElement;
330
- this.colorPicker = colorPicker;
331
- this.colorMenu = colorMenu;
332
- this.inputs = [...getElementsByClassName('color-input', parent)] as HTMLInputElement[];
333
- const [controls] = getElementsByClassName('color-controls', parent);
334
- this.controls = controls;
335
- this.controlKnobs = [...getElementsByClassName('knob', controls)];
336
- this.visuals = [...getElementsByClassName('visual-control', controls)];
337
-
338
- // update colour picker controls, inputs and visuals
339
- this.update();
340
- // console.log(this)
341
-
342
- // add main events listeners
343
- toggleEvents(this, true);
344
-
345
- // set component data
346
- Data.set(input, colorPickerString, this);
347
- }
348
-
349
- /** Returns the current colour value */
350
- get value(): string {
351
- return this.input.value;
352
- }
353
-
354
- /**
355
- * Sets a new colour value.
356
- *
357
- * @param {string} v new colour value
358
- */
359
- set value(v: string) {
360
- this.input.value = v;
361
- }
362
-
363
- /** Check if the colour presets include any non-colour. */
364
- get hasNonColor(): boolean {
365
- return this.colorKeywords instanceof Array && this.colorKeywords.some(x => nonColors.includes(x));
366
- }
367
-
368
- /** Returns hexadecimal value of the current colour. */
369
- get hex(): string {
370
- return this.color.toHex(true);
371
- }
372
-
373
- /** Returns the current colour value in {h,s,v,a} object format. */
374
- get hsv(): HSVA {
375
- return this.color.toHsv();
376
- }
377
-
378
- /** Returns the current colour value in {h,s,l,a} object format. */
379
- get hsl(): HSLA {
380
- return this.color.toHsl();
381
- }
382
-
383
- /** Returns the current colour value in {h,w,b,a} object format. */
384
- get hwb(): HWBA {
385
- return this.color.toHwb();
386
- }
387
-
388
- /** Returns the current colour value in {r,g,b,a} object format. */
389
- get rgb(): RGBA {
390
- return this.color.toRgb();
391
- }
392
-
393
- /** Returns the current colour brightness. */
394
- get brightness(): number {
395
- return this.color.brightness;
396
- }
397
-
398
- /** Returns the current colour luminance. */
399
- get luminance(): number {
400
- return this.color.luminance;
401
- }
402
-
403
- /** Checks if the current colour requires a light text colour. */
404
- get isDark(): boolean {
405
- const { color, brightness } = this;
406
- return brightness < 120 && color.a > 0.33;
407
- }
408
-
409
- /** Checks if the current input value is a valid colour. */
410
- get isValid(): boolean {
411
- const inputValue = this.input.value;
412
- return inputValue !== '' && new Color(inputValue).isValid;
413
- }
414
-
415
- /** Returns the colour appearance, usually the closest colour name for the current value. */
416
- get appearance(): string {
417
- const { colorLabels, hsl, hsv, format } = this;
418
-
419
- const hue = roundPart(hsl.h * 360);
420
- const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
421
- const saturation = roundPart(saturationSource * 100);
422
- const lightness = roundPart(hsl.l * 100);
423
- const hsvl = hsv.v * 100;
424
-
425
- let colorName = 'black';
426
-
427
- // determine color appearance
428
- /* istanbul ignore else */
429
- if (lightness === 100 && saturation === 0) {
430
- colorName = colorLabels.white;
431
- } else if (lightness === 0) {
432
- colorName = colorLabels.black;
433
- } else if (saturation === 0) {
434
- colorName = colorLabels.grey;
435
- } else if (hue < 15 || hue >= 345) {
436
- colorName = colorLabels.red;
437
- } else if (hue >= 15 && hue < 45) {
438
- colorName = hsvl > 80 && saturation > 80 ? colorLabels.orange : colorLabels.brown;
439
- } else if (hue >= 45 && hue < 75) {
440
- const isGold = hue > 46 && hue < 54 && hsvl < 80 && saturation > 90;
441
- const isOlive = hue >= 54 && hue < 75 && hsvl < 80;
442
- colorName = isGold ? colorLabels.gold : colorLabels.yellow;
443
- colorName = isOlive ? colorLabels.olive : colorName;
444
- } else if (hue >= 75 && hue < 155) {
445
- colorName = hsvl < 68 ? colorLabels.green : colorLabels.lime;
446
- } else if (hue >= 155 && hue < 175) {
447
- colorName = colorLabels.teal;
448
- } else if (hue >= 175 && hue < 195) {
449
- colorName = colorLabels.cyan;
450
- } else if (hue >= 195 && hue < 255) {
451
- colorName = colorLabels.blue;
452
- } else if (hue >= 255 && hue < 270) {
453
- colorName = colorLabels.violet;
454
- } else if (hue >= 270 && hue < 295) {
455
- colorName = colorLabels.magenta;
456
- } else if (hue >= 295 && hue < 345) {
457
- colorName = colorLabels.pink;
458
- }
459
- return colorName;
460
- }
461
-
462
- /** Updates `ColorPicker` visuals. */
463
- updateVisuals(): void {
464
- const { controlPositions, visuals } = this;
465
- const [v1, v2, v3] = visuals;
466
- const { offsetHeight } = v1;
467
- const hue = controlPositions.c2y / offsetHeight;
468
- const { r, g, b } = new Color({ h: hue * 360, s: 100, l: 50 }).toRgb();
469
- const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
470
- const alpha = 1 - controlPositions.c3y / offsetHeight;
471
- const roundA = roundPart(alpha * 100) / 100;
472
-
473
- const fill = new Color({
474
- h: hue * 360,
475
- s: 100,
476
- l: 50,
477
- a: alpha,
478
- }).toRgbString();
479
- const hueGradient = `linear-gradient(
480
- rgb(255,0,0) 0%, rgb(255,255,0) 16.67%,
481
- rgb(0,255,0) 33.33%, rgb(0,255,255) 50%,
482
- rgb(0,0,255) 66.67%, rgb(255,0,255) 83.33%,
483
- rgb(255,0,0) 100%)`;
484
- setElementStyle(v1, {
485
- background: `linear-gradient(rgba(0,0,0,0) 0%, rgba(0,0,0,${roundA}) 100%),
486
- linear-gradient(to right, rgba(255,255,255,${roundA}) 0%, ${fill} 100%),
487
- ${whiteGrad}`,
488
- });
489
- setElementStyle(v2, { background: hueGradient });
490
-
491
- setElementStyle(v3, {
492
- background: `linear-gradient(rgba(${r},${g},${b},1) 0%,rgba(${r},${g},${b},0) 100%)`,
493
- });
494
- }
495
-
496
- /**
497
- * The `ColorPicker` *focusout* event listener when open.
498
- *
499
- * @param e
500
- * @this {ColorPicker}
501
- */
502
- handleFocusOut = ({ relatedTarget }: FocusEvent & { relatedTarget: HTMLElement }): void => {
503
- if (relatedTarget && !this.parent.contains(relatedTarget)) {
504
- this.hide(true);
505
- }
506
- };
507
-
508
- /**
509
- * The `ColorPicker` *keyup* event listener when open.
510
- *
511
- * @param e
512
- * @this {ColorPicker}
513
- */
514
- handleDismiss = ({ code }: KeyboardEvent): void => {
515
- if (this.isOpen && code === keyEscape) {
516
- this.hide();
517
- }
518
- };
519
-
520
- /**
521
- * The `ColorPicker` *scroll* event listener when open.
522
- *
523
- * @param e
524
- */
525
- handleScroll = (e: Event) => {
526
- const { activeElement } = getDocument(this.input);
527
-
528
- this.updateDropdownPosition();
529
-
530
- /* istanbul ignore next */
531
- if (
532
- ([pointermoveEvent, touchmoveEvent].includes(e.type) && this.dragElement) ||
533
- (activeElement && this.controlKnobs.includes(activeElement as HTMLElement))
534
- ) {
535
- e.stopPropagation();
536
- e.preventDefault();
537
- }
538
- };
539
-
540
- /**
541
- * The `ColorPicker` keyboard event listener for menu navigation.
542
- *
543
- * @param e
544
- */
545
- menuKeyHandler = (e: KeyboardEvent & { target: HTMLElement }) => {
546
- const { target, code } = e;
547
- const { previousElementSibling, nextElementSibling, parentElement } = target;
548
- const isColorOptionsMenu = parentElement && hasClass(parentElement, 'color-options');
549
- const allSiblings = parentElement ? [...parentElement.children] : [];
550
- // const columnsCount =
551
- // isColorOptionsMenu && getElementStyle(parentElement, 'grid-template-columns').split(' ').length;
552
- const columnsCount = isColorOptionsMenu && Number(getElementStyle(parentElement, '--grid-fit'));
553
- const currentIndex = allSiblings.indexOf(target);
554
- const previousElement = currentIndex > -1 && columnsCount && allSiblings[currentIndex - columnsCount];
555
- const nextElement = currentIndex > -1 && columnsCount && allSiblings[currentIndex + columnsCount];
556
-
557
- if ([keyArrowDown, keyArrowUp, keySpace].includes(code)) {
558
- // prevent scroll when navigating the menu via arrow keys / Space
559
- e.preventDefault();
560
- }
561
- if (isColorOptionsMenu) {
562
- if (previousElement && code === keyArrowUp) {
563
- focus(previousElement as HTMLElement);
564
- } else if (nextElement && code === keyArrowDown) {
565
- focus(nextElement as HTMLElement);
566
- } else if (previousElementSibling && code === keyArrowLeft) {
567
- focus(previousElementSibling as HTMLElement);
568
- } else if (nextElementSibling && code === keyArrowRight) {
569
- focus(nextElementSibling as HTMLElement);
570
- }
571
- } else if (previousElementSibling && [keyArrowLeft, keyArrowUp].includes(code)) {
572
- focus(previousElementSibling as HTMLElement);
573
- } else if (nextElementSibling && [keyArrowRight, keyArrowDown].includes(code)) {
574
- focus(nextElementSibling as HTMLElement);
575
- }
576
-
577
- if ([keyEnter, keySpace].includes(code)) {
578
- this.menuClickHandler(e);
579
- }
580
- };
581
-
582
- /**
583
- * The `ColorPicker` click event listener for the colour menu presets / defaults.
584
- *
585
- * @param e
586
- * @this {ColorPicker}
587
- */
588
- menuClickHandler = (e: Event) => {
589
- const { target } = e;
590
- const { colorMenu } = this;
591
- const newOption = (getAttribute(target as HTMLElement, 'data-value') || '').trim();
592
- // invalidate for targets other than color options
593
- if (!newOption.length) return;
594
- const currentActive = querySelector('li.active', colorMenu);
595
- let newColor = newOption;
596
- newColor = nonColors.includes(newColor) ? 'white' : newColor;
597
- newColor = newColor === 'transparent' ? 'rgba(0,0,0,0)' : newColor;
598
-
599
- const { r, g, b, a } = new Color(newColor);
600
-
601
- ObjectAssign(this.color, {
602
- r,
603
- g,
604
- b,
605
- a,
606
- });
607
-
608
- this.update();
609
-
610
- /* istanbul ignore else */
611
- if (currentActive !== target) {
612
- /* istanbul ignore else */
613
- if (currentActive) {
614
- removeClass(currentActive, 'active');
615
- removeAttribute(currentActive, ariaSelected);
616
- }
617
-
618
- addClass(target as HTMLElement, 'active');
619
- setAttribute(target as HTMLElement, ariaSelected, 'true');
620
-
621
- if (nonColors.includes(newOption)) {
622
- this.value = newOption;
623
- }
624
- firePickerChange(this);
625
- }
626
- };
627
-
628
- /**
629
- * The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
630
- *
631
- * @param e
632
- */
633
- pointerDown = (e: PointerEvent & { target: HTMLElement }) => {
634
- if (e.button !== 0) return;
635
- const { target, pageX, pageY } = e;
636
- const { colorMenu, visuals, controlKnobs } = this;
637
- const [v1, v2, v3] = visuals;
638
- const [c1, c2, c3] = controlKnobs;
639
- const visual = controlKnobs.includes(target) ? (target.previousElementSibling as HTMLElement) : target;
640
- const visualRect = getBoundingClientRect(visual);
641
- const html = getDocumentElement(v1);
642
- const offsetX = pageX - html.scrollLeft - visualRect.left;
643
- const offsetY = pageY - html.scrollTop - visualRect.top;
644
-
645
- /* istanbul ignore else */
646
- if (target === v1 || target === c1) {
647
- this.dragElement = visual;
648
- this.changeControl1(offsetX, offsetY);
649
- } else if (target === v2 || target === c2) {
650
- this.dragElement = visual;
651
- this.changeControl2(offsetY);
652
- } else if (target === v3 || target === c3) {
653
- this.dragElement = visual;
654
- this.changeAlpha(offsetY);
655
- }
656
-
657
- if (colorMenu) {
658
- const currentActive = querySelector('li.active', colorMenu);
659
- if (currentActive) {
660
- removeClass(currentActive, 'active');
661
- removeAttribute(currentActive, ariaSelected);
662
- }
663
- }
664
- e.preventDefault();
665
- };
666
-
667
- /**
668
- * The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
669
- *
670
- * @param e
671
- * @this
672
- */
673
- pointerUp = ({ target }: PointerEvent & { target: HTMLElement }) => {
674
- const { parent } = this;
675
- const doc = getDocument(parent);
676
- const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
677
- const selection = doc.getSelection();
678
-
679
- if (!this.dragElement && (!selection || !selection.toString().length) && !parent.contains(target)) {
680
- this.hide(currentOpen);
681
- }
682
-
683
- this.dragElement = undefined;
684
- };
685
-
686
- /**
687
- * The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
688
- *
689
- * @param {PointerEvent} e
690
- */
691
- pointerMove = (e: PointerEvent) => {
692
- const { dragElement, visuals } = this;
693
- const [v1, v2, v3] = visuals;
694
- const { pageX, pageY } = e;
695
-
696
- if (!dragElement) return;
697
-
698
- const controlRect = getBoundingClientRect(dragElement);
699
- const win = getDocumentElement(v1);
700
- const offsetX = pageX - win.scrollLeft - controlRect.left;
701
- const offsetY = pageY - win.scrollTop - controlRect.top;
702
-
703
- if (dragElement === v1) {
704
- this.changeControl1(offsetX, offsetY);
705
- }
706
-
707
- if (dragElement === v2) {
708
- this.changeControl2(offsetY);
709
- }
710
-
711
- if (dragElement === v3) {
712
- this.changeAlpha(offsetY);
713
- }
714
- };
715
-
716
- /**
717
- * The `ColorPicker` *keydown* event listener for control knobs.
718
- *
719
- * @param e
720
- */
721
- handleKnobs = (e: Event & { code: string }) => {
722
- const { target, code } = e;
723
-
724
- // only react to arrow buttons
725
- if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
726
- e.preventDefault();
727
-
728
- const { controlKnobs, visuals } = this;
729
- const { offsetWidth, offsetHeight } = visuals[0];
730
- const [c1, c2, c3] = controlKnobs;
731
- const { activeElement } = getDocument(c1);
732
- const currentKnob = controlKnobs.find(x => x === activeElement);
733
- const yRatio = offsetHeight / 360;
734
-
735
- /* istanbul ignore else */
736
- if (currentKnob) {
737
- let offsetX = 0;
738
- let offsetY = 0;
739
-
740
- /* istanbul ignore else */
741
- if (target === c1) {
742
- const xRatio = offsetWidth / 100;
743
-
744
- /* istanbul ignore else */
745
- if ([keyArrowLeft, keyArrowRight].includes(code)) {
746
- this.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
747
- } else if ([keyArrowUp, keyArrowDown].includes(code)) {
748
- this.controlPositions.c1y += code === keyArrowDown ? yRatio : -yRatio;
749
- }
750
-
751
- offsetX = this.controlPositions.c1x;
752
- offsetY = this.controlPositions.c1y;
753
- this.changeControl1(offsetX, offsetY);
754
- } else if (target === c2) {
755
- this.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code) ? yRatio : -yRatio;
756
-
757
- offsetY = this.controlPositions.c2y;
758
- this.changeControl2(offsetY);
759
- } else if (target === c3) {
760
- this.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code) ? yRatio : -yRatio;
761
-
762
- offsetY = this.controlPositions.c3y;
763
- this.changeAlpha(offsetY);
764
- }
765
- this.handleScroll(e);
766
- }
767
- };
768
-
769
- /** The event listener of the colour form inputs. */
770
- changeHandler = (): void => {
771
- let colorSource;
772
- const { inputs, format, value: currentValue, input, controlPositions, visuals } = this;
773
- const { activeElement } = getDocument(input);
774
- const { offsetHeight } = visuals[0];
775
- const [i1, , , i4] = inputs;
776
- const [v1, v2, v3, v4] =
777
- format === 'rgb'
778
- ? inputs.map(i => parseFloat(i.value) / (i === i4 ? 100 : 1))
779
- : inputs.map(i => parseFloat(i.value) / (i !== i1 ? 100 : 360));
780
- const isNonColorValue = this.hasNonColor && nonColors.includes(currentValue);
781
- const alpha = i4 ? v4 : 1 - controlPositions.c3y / offsetHeight;
782
-
783
- /* istanbul ignore else */
784
- if (activeElement === input || (activeElement && inputs.includes(activeElement as HTMLInputElement))) {
785
- if (activeElement === input) {
786
- if (isNonColorValue) {
787
- colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
788
- } else {
789
- colorSource = currentValue;
790
- }
791
- } else if (format === 'hex') {
792
- colorSource = i1.value;
793
- } else if (format === 'hsl') {
794
- colorSource = {
795
- h: v1,
796
- s: v2,
797
- l: v3,
798
- a: alpha,
799
- };
800
- } else if (format === 'hwb') {
801
- colorSource = {
802
- h: v1,
803
- w: v2,
804
- b: v3,
805
- a: alpha,
806
- };
807
- } else {
808
- colorSource = {
809
- r: v1,
810
- g: v2,
811
- b: v3,
812
- a: alpha,
813
- };
814
- }
815
-
816
- const { r, g, b, a } = new Color(colorSource);
817
-
818
- ObjectAssign(this.color, {
819
- r,
820
- g,
821
- b,
822
- a,
823
- });
824
- this.setControlPositions();
825
- this.updateAppearance();
826
- this.updateInputs();
827
- this.updateControls();
828
- this.updateVisuals();
829
-
830
- // set non-color keyword
831
- if (activeElement === input && isNonColorValue) {
832
- this.value = currentValue;
833
- }
834
- }
835
- };
836
-
837
- /**
838
- * Updates `ColorPicker` first control:
839
- * * `lightness` and `saturation` for HEX/RGB;
840
- * * `lightness` and `hue` for HSL.
841
- *
842
- * @param X the X component of the offset
843
- * @param Y the Y component of the offset
844
- */
845
- changeControl1(X: number, Y: number): void {
846
- let [offsetX, offsetY] = [0, 0];
847
- const { controlPositions, visuals } = this;
848
- const { offsetHeight, offsetWidth } = visuals[0];
849
-
850
- if (X > offsetWidth) offsetX = offsetWidth;
851
- else if (X >= 0) offsetX = X;
852
-
853
- if (Y > offsetHeight) offsetY = offsetHeight;
854
- else if (Y >= 0) offsetY = Y;
855
-
856
- const hue = controlPositions.c2y / offsetHeight;
857
-
858
- const saturation = offsetX / offsetWidth;
859
-
860
- const lightness = 1 - offsetY / offsetHeight;
861
- const alpha = 1 - controlPositions.c3y / offsetHeight;
862
-
863
- // new color
864
- const { r, g, b, a } = new Color({
865
- h: hue * 360,
866
- s: saturation * 100,
867
- v: lightness * 100,
868
- a: alpha,
869
- });
870
-
871
- ObjectAssign(this.color, {
872
- r,
873
- g,
874
- b,
875
- a,
876
- });
877
-
878
- // new positions
879
- this.controlPositions.c1x = offsetX;
880
- this.controlPositions.c1y = offsetY;
881
-
882
- // update color picker
883
- this.updateAppearance();
884
- this.updateInputs();
885
- this.updateControls();
886
- this.updateVisuals();
887
- }
888
-
889
- /**
890
- * Updates `ColorPicker` second control:
891
- * * `hue` for HEX/RGB/HWB;
892
- * * `saturation` for HSL.
893
- *
894
- * @param Y the Y offset
895
- */
896
- changeControl2(Y: number) {
897
- const { controlPositions, visuals } = this;
898
- const { offsetHeight, offsetWidth } = visuals[0];
899
-
900
- let offsetY = 0;
901
-
902
- if (Y > offsetHeight) offsetY = offsetHeight;
903
- else if (Y >= 0) offsetY = Y;
904
-
905
- const hue = offsetY / offsetHeight;
906
- const saturation = controlPositions.c1x / offsetWidth;
907
- const lightness = 1 - controlPositions.c1y / offsetHeight;
908
- const alpha = 1 - controlPositions.c3y / offsetHeight;
909
-
910
- // new color
911
- const { r, g, b, a } = new Color({
912
- h: hue * 360,
913
- s: saturation * 100,
914
- v: lightness * 100,
915
- a: alpha,
916
- });
917
-
918
- ObjectAssign(this.color, {
919
- r,
920
- g,
921
- b,
922
- a,
923
- });
924
-
925
- // new position
926
- this.controlPositions.c2y = offsetY;
927
- // update color picker
928
- this.updateAppearance();
929
- this.updateInputs();
930
- this.updateControls();
931
- this.updateVisuals();
932
- }
933
-
934
- /**
935
- * Updates `ColorPicker` last control,
936
- * the `alpha` channel.
937
- *
938
- * @param Y
939
- */
940
- changeAlpha(Y: number) {
941
- const { visuals } = this;
942
- const { offsetHeight } = visuals[0];
943
- let offsetY = 0;
944
-
945
- if (Y > offsetHeight) offsetY = offsetHeight;
946
- else if (Y >= 0) offsetY = Y;
947
-
948
- // update color alpha
949
- const alpha = 1 - offsetY / offsetHeight;
950
- this.color.setAlpha(alpha);
951
- // update position
952
- this.controlPositions.c3y = offsetY;
953
- // update color picker
954
- this.updateAppearance();
955
- this.updateInputs();
956
- this.updateControls();
957
- this.updateVisuals();
958
- }
959
-
960
- /**
961
- * Updates `ColorPicker` control positions on:
962
- * * initialization
963
- * * window resize
964
- */
965
- update = () => {
966
- this.updateDropdownPosition();
967
- this.updateAppearance();
968
- this.setControlPositions();
969
- this.updateInputs(true);
970
- this.updateControls();
971
- this.updateVisuals();
972
- };
973
-
974
- /** Updates the open dropdown position on *scroll* event. */
975
- updateDropdownPosition() {
976
- const { input, colorPicker, colorMenu } = this;
977
- const elRect = getBoundingClientRect(input);
978
- const { top, bottom } = elRect;
979
- const { offsetHeight: elHeight } = input;
980
- const windowHeight = getDocumentElement(input).clientHeight;
981
- const isPicker = hasClass(colorPicker, 'show');
982
- const dropdown = isPicker ? colorPicker : colorMenu;
983
- if (!dropdown) return;
984
- const { offsetHeight: dropHeight } = dropdown;
985
- const distanceBottom = windowHeight - bottom;
986
- const distanceTop = top;
987
- const bottomExceed = top + dropHeight + elHeight > windowHeight; // show
988
- const topExceed = top - dropHeight < 0; // show-top
989
-
990
- if ((hasClass(dropdown, 'bottom') || !topExceed) && distanceBottom < distanceTop && bottomExceed) {
991
- removeClass(dropdown, 'bottom');
992
- addClass(dropdown, 'top');
993
- } else {
994
- removeClass(dropdown, 'top');
995
- addClass(dropdown, 'bottom');
996
- }
997
- }
998
-
999
- /** Updates control knobs' positions. */
1000
- setControlPositions() {
1001
- const { visuals, color, hsv } = this;
1002
- const { offsetHeight, offsetWidth } = visuals[0];
1003
- const alpha = color.a;
1004
- const hue = hsv.h;
1005
-
1006
- const saturation = hsv.s;
1007
- const lightness = hsv.v;
1008
-
1009
- this.controlPositions.c1x = saturation * offsetWidth;
1010
- this.controlPositions.c1y = (1 - lightness) * offsetHeight;
1011
- this.controlPositions.c2y = hue * offsetHeight;
1012
- this.controlPositions.c3y = (1 - alpha) * offsetHeight;
1013
- }
1014
-
1015
- /** Update the visual appearance label and control knob labels. */
1016
- updateAppearance() {
1017
- const { componentLabels, color, parent, hsv, hex, format, controlKnobs } = this;
1018
- const { appearanceLabel, hexLabel, valueLabel } = componentLabels;
1019
- let { r, g, b } = color.toRgb();
1020
- const [knob1, knob2, knob3] = controlKnobs;
1021
- const hue = roundPart(hsv.h * 360);
1022
- const alpha = color.a;
1023
- const saturation = roundPart(hsv.s * 100);
1024
- const lightness = roundPart(hsv.v * 100);
1025
- const colorName = this.appearance;
1026
-
1027
- let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
1028
-
1029
- if (format === 'hwb') {
1030
- const { hwb } = this;
1031
- const whiteness = roundPart(hwb.w * 100);
1032
- const blackness = roundPart(hwb.b * 100);
1033
- colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
1034
- setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
1035
- setAttribute(knob1, ariaValueNow, `${whiteness}`);
1036
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1037
- setAttribute(knob2, ariaValueText, `${hue}%`);
1038
- setAttribute(knob2, ariaValueNow, `${hue}`);
1039
- } else {
1040
- [r, g, b] = [r, g, b].map(roundPart);
1041
- colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
1042
- colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
1043
-
1044
- setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
1045
- setAttribute(knob1, ariaValueNow, `${lightness}`);
1046
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1047
- setAttribute(knob2, ariaValueText, `${hue}°`);
1048
- setAttribute(knob2, ariaValueNow, `${hue}`);
1049
- }
1050
-
1051
- const alphaValue = roundPart(alpha * 100);
1052
- setAttribute(knob3, ariaValueText, `${alphaValue}%`);
1053
- setAttribute(knob3, ariaValueNow, `${alphaValue}`);
1054
-
1055
- // update the input backgroundColor
1056
- const newColor = color.toString();
1057
- setElementStyle(this.input, { backgroundColor: newColor });
1058
-
1059
- // toggle dark/light classes will also style the placeholder
1060
- // dark sets color white, light sets color black
1061
- // isDark ? '#000' : '#fff'
1062
- if (!this.isDark) {
1063
- if (hasClass(parent, 'txt-dark')) removeClass(parent, 'txt-dark');
1064
- if (!hasClass(parent, 'txt-light')) addClass(parent, 'txt-light');
1065
- } else {
1066
- if (hasClass(parent, 'txt-light')) removeClass(parent, 'txt-light');
1067
- if (!hasClass(parent, 'txt-dark')) addClass(parent, 'txt-dark');
1068
- }
1069
- }
1070
-
1071
- /** Updates the control knobs actual positions. */
1072
- updateControls() {
1073
- const { controlKnobs, controlPositions } = this;
1074
- let { c1x, c1y, c2y, c3y } = controlPositions;
1075
- const [control1, control2, control3] = controlKnobs;
1076
- // round control positions
1077
- [c1x, c1y, c2y, c3y] = [c1x, c1y, c2y, c3y].map(roundPart);
1078
-
1079
- setElementStyle(control1, {
1080
- transform: `translate3d(${c1x - 4}px,${c1y - 4}px,0)`,
1081
- });
1082
- setElementStyle(control2, { transform: `translate3d(0,${c2y - 4}px,0)` });
1083
- setElementStyle(control3, { transform: `translate3d(0,${c3y - 4}px,0)` });
1084
- }
1085
-
1086
- /**
1087
- * Updates all color form inputs.
1088
- *
1089
- * @param isPrevented when `true`, the component original event is prevented
1090
- */
1091
- updateInputs(isPrevented?: boolean) {
1092
- const { value: oldColor, format, inputs, color, hsl } = this;
1093
- const [i1, i2, i3, i4] = inputs;
1094
- const alpha = roundPart(color.a * 100);
1095
- const hue = roundPart(hsl.h * 360);
1096
- let newColor = color.toString();
1097
-
1098
- /* istanbul ignore else */
1099
- if (format === 'hex') {
1100
- newColor = this.color.toHexString(true);
1101
- i1.value = this.hex;
1102
- } else if (format === 'hsl') {
1103
- const lightness = roundPart(hsl.l * 100);
1104
- const saturation = roundPart(hsl.s * 100);
1105
- newColor = this.color.toHslString();
1106
- i1.value = `${hue}`;
1107
- i2.value = `${saturation}`;
1108
- i3.value = `${lightness}`;
1109
- i4.value = `${alpha}`;
1110
- } else if (format === 'hwb') {
1111
- const { w, b } = this.hwb;
1112
- const whiteness = roundPart(w * 100);
1113
- const blackness = roundPart(b * 100);
1114
-
1115
- newColor = this.color.toHwbString();
1116
- i1.value = `${hue}`;
1117
- i2.value = `${whiteness}`;
1118
- i3.value = `${blackness}`;
1119
- i4.value = `${alpha}`;
1120
- } else if (format === 'rgb') {
1121
- let { r, g, b } = this.rgb;
1122
- [r, g, b] = [r, g, b].map(roundPart);
1123
-
1124
- newColor = this.color.toRgbString();
1125
- i1.value = `${r}`;
1126
- i2.value = `${g}`;
1127
- i3.value = `${b}`;
1128
- i4.value = `${alpha}`;
1129
- }
1130
-
1131
- // update the color value
1132
- this.value = newColor;
1133
-
1134
- // don't trigger the custom event unless it's really changed
1135
- if (!isPrevented && newColor !== oldColor) {
1136
- firePickerChange(this);
1137
- }
1138
- }
1139
-
1140
- /**
1141
- * Toggle the `ColorPicker` dropdown visibility.
1142
- *
1143
- * @param e
1144
- */
1145
- togglePicker = (e?: Event) => {
1146
- if (e) e.preventDefault();
1147
- const { colorPicker } = this;
1148
-
1149
- if (this.isOpen && hasClass(colorPicker, 'show')) {
1150
- this.hide(true);
1151
- } else {
1152
- showDropdown(this, colorPicker);
1153
- }
1154
- };
1155
-
1156
- /** Shows the `ColorPicker` dropdown. */
1157
- showPicker = () => {
1158
- const { colorPicker } = this;
1159
-
1160
- if (!['top', 'bottom'].some(c => hasClass(colorPicker, c))) {
1161
- showDropdown(this, colorPicker);
1162
- }
1163
- };
1164
-
1165
- /**
1166
- * Toggles the visibility of the `ColorPicker` presets menu.
1167
- *
1168
- * @param e
1169
- * @this {ColorPicker}
1170
- */
1171
- toggleMenu = (e?: Event) => {
1172
- if (e) e.preventDefault();
1173
- const { colorMenu } = this;
1174
-
1175
- if (this.isOpen && hasClass(colorMenu, 'show')) {
1176
- this.hide(true);
1177
- } else {
1178
- showDropdown(this, colorMenu);
1179
- }
1180
- };
1181
-
1182
- /**
1183
- * Hides the currently open `ColorPicker` dropdown.
1184
- *
1185
- * @param {boolean=} focusPrevented
1186
- */
1187
- hide(focusPrevented?: boolean) {
1188
- if (this.isOpen) {
1189
- const { pickerToggle, menuToggle, colorPicker, colorMenu, parent, input } = this;
1190
- const openPicker = hasClass(colorPicker, 'show');
1191
- const openDropdown = openPicker ? colorPicker : colorMenu;
1192
- const relatedBtn = openPicker ? pickerToggle : menuToggle;
1193
- const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
1194
-
1195
- this.value = this.color.toString(true);
1196
-
1197
- /* istanbul ignore else */
1198
- if (openDropdown) {
1199
- removeClass(openDropdown, 'show');
1200
- setAttribute(relatedBtn, ariaExpanded, 'false');
1201
- setTimeout(() => {
1202
- removePosition(openDropdown);
1203
- /* istanbul ignore else */
1204
- if (!querySelector('.show', parent)) {
1205
- removeClass(parent, 'open');
1206
- toggleEventsOnShown(this);
1207
- this.isOpen = false;
1208
- }
1209
- }, animationDuration);
1210
- }
1211
-
1212
- if (!focusPrevented) {
1213
- focus(pickerToggle);
1214
- }
1215
- setAttribute(input, tabindex, '-1');
1216
- if (relatedBtn === menuToggle) {
1217
- setAttribute(menuToggle, tabindex, '-1');
1218
- }
1219
- }
1220
- }
1221
-
1222
- /** Removes `ColorPicker` from target `<input>`. */
1223
- dispose() {
1224
- const { input, parent } = this;
1225
- this.hide(true);
1226
- toggleEvents(this);
1227
- [...parent.children].forEach(el => {
1228
- if (el !== input) el.remove();
1229
- });
1230
-
1231
- removeAttribute(input, tabindex);
1232
- setElementStyle(input, { backgroundColor: '' });
1233
-
1234
- ['txt-light', 'txt-dark'].forEach(c => removeClass(parent, c));
1235
- Data.remove(input, colorPickerString);
1236
- }
1237
- }