@thednp/color-picker 2.0.1 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) 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 +423 -382
  16. package/dist/js/color-picker.mjs.map +1 -1
  17. package/package.json +39 -50
  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/cypress/e2e/color-palette.cy.ts +0 -128
  24. package/cypress/e2e/color-picker.cy.ts +0 -909
  25. package/cypress/fixtures/colorNamesFrench.js +0 -3
  26. package/cypress/fixtures/componentLabelsFrench.js +0 -21
  27. package/cypress/fixtures/format.js +0 -3
  28. package/cypress/fixtures/getMarkup.js +0 -35
  29. package/cypress/fixtures/getRandomInt.js +0 -6
  30. package/cypress/fixtures/sampleWebcolors.js +0 -18
  31. package/cypress/fixtures/testSample.js +0 -8
  32. package/cypress/plugins/esbuild-istanbul.ts +0 -50
  33. package/cypress/plugins/tsCompile.ts +0 -34
  34. package/cypress/support/commands.ts +0 -0
  35. package/cypress/support/e2e.ts +0 -21
  36. package/cypress/test.html +0 -23
  37. package/cypress.config.ts +0 -30
  38. package/dts.config.ts +0 -15
  39. package/src/scss/_variables.scss +0 -6
  40. package/src/scss/color-picker.rtl.scss +0 -27
  41. package/src/scss/color-picker.scss +0 -536
  42. package/src/ts/colorPalette.ts +0 -89
  43. package/src/ts/index.ts +0 -1236
  44. package/src/ts/interface/ColorNames.ts +0 -20
  45. package/src/ts/interface/colorPickerLabels.ts +0 -20
  46. package/src/ts/interface/colorPickerOptions.ts +0 -11
  47. package/src/ts/interface/paletteOptions.ts +0 -6
  48. package/src/ts/util/colorNames.ts +0 -21
  49. package/src/ts/util/colorPickerLabels.ts +0 -24
  50. package/src/ts/util/getColorControls.ts +0 -90
  51. package/src/ts/util/getColorForm.ts +0 -75
  52. package/src/ts/util/getColorMenu.ts +0 -83
  53. package/src/ts/util/isValidJSON.ts +0 -19
  54. package/src/ts/util/setMarkup.ts +0 -130
  55. package/src/ts/util/vHidden.ts +0 -2
  56. package/tsconfig.json +0 -29
  57. package/vite.config.mts +0 -35
package/src/ts/index.ts DELETED
@@ -1,1236 +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 as EventListener);
121
- self.controlKnobs.forEach(x => fn(x, keydownEvent, self.handleKnobs as EventListener));
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 as EventListener);
131
- }
132
-
133
- fn(doc, pointermoveEvent, self.pointerMove as EventListener);
134
- fn(doc, pointerupEvent, self.pointerUp as EventListener);
135
- fn(parent, focusoutEvent, self.handleFocusOut as EventListener);
136
- fn(doc, keyupEvent, self.handleDismiss as EventListener);
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, s: 1, l: 0.5 }).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,
475
- s: 1,
476
- l: 0.5,
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 currentIndex = allSiblings.indexOf(target);
553
- const previousElement = currentIndex > -1 && columnsCount && allSiblings[currentIndex - columnsCount];
554
- const nextElement = currentIndex > -1 && columnsCount && allSiblings[currentIndex + columnsCount];
555
-
556
- if ([keyArrowDown, keyArrowUp, keySpace].includes(code)) {
557
- // prevent scroll when navigating the menu via arrow keys / Space
558
- e.preventDefault();
559
- }
560
- if (isColorOptionsMenu) {
561
- if (previousElement && code === keyArrowUp) {
562
- focus(previousElement as HTMLElement);
563
- } else if (nextElement && code === keyArrowDown) {
564
- focus(nextElement as HTMLElement);
565
- } else if (previousElementSibling && code === keyArrowLeft) {
566
- focus(previousElementSibling as HTMLElement);
567
- } else if (nextElementSibling && code === keyArrowRight) {
568
- focus(nextElementSibling as HTMLElement);
569
- }
570
- } else if (previousElementSibling && [keyArrowLeft, keyArrowUp].includes(code)) {
571
- focus(previousElementSibling as HTMLElement);
572
- } else if (nextElementSibling && [keyArrowRight, keyArrowDown].includes(code)) {
573
- focus(nextElementSibling as HTMLElement);
574
- }
575
-
576
- if ([keyEnter, keySpace].includes(code)) {
577
- this.menuClickHandler(e);
578
- }
579
- };
580
-
581
- /**
582
- * The `ColorPicker` click event listener for the colour menu presets / defaults.
583
- *
584
- * @param e
585
- * @this {ColorPicker}
586
- */
587
- menuClickHandler = (e: Event) => {
588
- const { target } = e;
589
- const { colorMenu } = this;
590
- const newOption = (getAttribute(target as HTMLElement, 'data-value') || '').trim();
591
- // invalidate for targets other than color options
592
- if (!newOption.length) return;
593
- const currentActive = querySelector('li.active', colorMenu);
594
- let newColor = newOption;
595
- newColor = nonColors.includes(newColor) ? 'white' : newColor;
596
- newColor = newColor === 'transparent' ? 'rgba(0,0,0,0)' : newColor;
597
-
598
- const { r, g, b, a } = new Color(newColor);
599
-
600
- ObjectAssign(this.color, {
601
- r,
602
- g,
603
- b,
604
- a,
605
- });
606
-
607
- this.update();
608
-
609
- /* istanbul ignore else */
610
- if (currentActive !== target) {
611
- /* istanbul ignore else */
612
- if (currentActive) {
613
- removeClass(currentActive, 'active');
614
- removeAttribute(currentActive, ariaSelected);
615
- }
616
-
617
- addClass(target as HTMLElement, 'active');
618
- setAttribute(target as HTMLElement, ariaSelected, 'true');
619
-
620
- if (nonColors.includes(newOption)) {
621
- this.value = newOption;
622
- }
623
- firePickerChange(this);
624
- }
625
- };
626
-
627
- /**
628
- * The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
629
- *
630
- * @param e
631
- */
632
- pointerDown = (e: PointerEvent & { target: HTMLElement }) => {
633
- if (e.button !== 0) return;
634
- const { target, pageX, pageY } = e;
635
- const { colorMenu, visuals, controlKnobs } = this;
636
- const [v1, v2, v3] = visuals;
637
- const [c1, c2, c3] = controlKnobs;
638
- const visual = controlKnobs.includes(target) ? (target.previousElementSibling as HTMLElement) : target;
639
- const visualRect = getBoundingClientRect(visual);
640
- const html = getDocumentElement(v1);
641
- const offsetX = pageX - html.scrollLeft - visualRect.left;
642
- const offsetY = pageY - html.scrollTop - visualRect.top;
643
-
644
- /* istanbul ignore else */
645
- if (target === v1 || target === c1) {
646
- this.dragElement = visual;
647
- this.changeControl1(offsetX, offsetY);
648
- } else if (target === v2 || target === c2) {
649
- this.dragElement = visual;
650
- this.changeControl2(offsetY);
651
- } else if (target === v3 || target === c3) {
652
- this.dragElement = visual;
653
- this.changeAlpha(offsetY);
654
- }
655
-
656
- if (colorMenu) {
657
- const currentActive = querySelector('li.active', colorMenu);
658
- if (currentActive) {
659
- removeClass(currentActive, 'active');
660
- removeAttribute(currentActive, ariaSelected);
661
- }
662
- }
663
- e.preventDefault();
664
- };
665
-
666
- /**
667
- * The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
668
- *
669
- * @param e
670
- * @this
671
- */
672
- pointerUp = ({ target }: PointerEvent & { target: HTMLElement }) => {
673
- const { parent } = this;
674
- const doc = getDocument(parent);
675
- const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
676
- const selection = doc.getSelection();
677
-
678
- if (!this.dragElement && (!selection || !selection.toString().length) && !parent.contains(target)) {
679
- this.hide(currentOpen);
680
- }
681
-
682
- this.dragElement = undefined;
683
- };
684
-
685
- /**
686
- * The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
687
- *
688
- * @param {PointerEvent} e
689
- */
690
- pointerMove = (e: PointerEvent) => {
691
- const { dragElement, visuals } = this;
692
- const [v1, v2, v3] = visuals;
693
- const { pageX, pageY } = e;
694
-
695
- if (!dragElement) return;
696
-
697
- const controlRect = getBoundingClientRect(dragElement);
698
- const win = getDocumentElement(v1);
699
- const offsetX = pageX - win.scrollLeft - controlRect.left;
700
- const offsetY = pageY - win.scrollTop - controlRect.top;
701
-
702
- if (dragElement === v1) {
703
- this.changeControl1(offsetX, offsetY);
704
- }
705
-
706
- if (dragElement === v2) {
707
- this.changeControl2(offsetY);
708
- }
709
-
710
- if (dragElement === v3) {
711
- this.changeAlpha(offsetY);
712
- }
713
- };
714
-
715
- /**
716
- * The `ColorPicker` *keydown* event listener for control knobs.
717
- *
718
- * @param e
719
- */
720
- handleKnobs = (e: Event & { code: string }) => {
721
- const { target, code } = e;
722
-
723
- // only react to arrow buttons
724
- if (![keyArrowUp, keyArrowDown, keyArrowLeft, keyArrowRight].includes(code)) return;
725
- e.preventDefault();
726
-
727
- const { controlKnobs, visuals } = this;
728
- const { offsetWidth, offsetHeight } = visuals[0];
729
- const [c1, c2, c3] = controlKnobs;
730
- const { activeElement } = getDocument(c1);
731
- const currentKnob = controlKnobs.find(x => x === activeElement);
732
- const yRatio = offsetHeight / 360;
733
-
734
- /* istanbul ignore else */
735
- if (currentKnob) {
736
- let offsetX = 0;
737
- let offsetY = 0;
738
-
739
- /* istanbul ignore else */
740
- if (target === c1) {
741
- const xRatio = offsetWidth / 100;
742
-
743
- /* istanbul ignore else */
744
- if ([keyArrowLeft, keyArrowRight].includes(code)) {
745
- this.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
746
- } else if ([keyArrowUp, keyArrowDown].includes(code)) {
747
- this.controlPositions.c1y += code === keyArrowDown ? yRatio : -yRatio;
748
- }
749
-
750
- offsetX = this.controlPositions.c1x;
751
- offsetY = this.controlPositions.c1y;
752
- this.changeControl1(offsetX, offsetY);
753
- } else if (target === c2) {
754
- this.controlPositions.c2y += [keyArrowDown, keyArrowRight].includes(code) ? yRatio : -yRatio;
755
-
756
- offsetY = this.controlPositions.c2y;
757
- this.changeControl2(offsetY);
758
- } else if (target === c3) {
759
- this.controlPositions.c3y += [keyArrowDown, keyArrowRight].includes(code) ? yRatio : -yRatio;
760
-
761
- offsetY = this.controlPositions.c3y;
762
- this.changeAlpha(offsetY);
763
- }
764
- this.handleScroll(e);
765
- }
766
- };
767
-
768
- /** The event listener of the colour form inputs. */
769
- changeHandler = (): void => {
770
- let colorSource;
771
- const { inputs, format, value: currentValue, input, controlPositions, visuals } = this;
772
- const { activeElement } = getDocument(input);
773
- const { offsetHeight } = visuals[0];
774
- const [i1, , , i4] = inputs;
775
- const [v1, v2, v3, v4] =
776
- format === 'rgb'
777
- ? inputs.map(i => parseFloat(i.value) / (i === i4 ? 100 : 1))
778
- : inputs.map(i => parseFloat(i.value) / (i !== i1 ? 100 : 360));
779
- const isNonColorValue = this.hasNonColor && nonColors.includes(currentValue);
780
- const alpha = i4 ? v4 : 1 - controlPositions.c3y / offsetHeight;
781
-
782
- /* istanbul ignore else */
783
- if (activeElement === input || (activeElement && inputs.includes(activeElement as HTMLInputElement))) {
784
- if (activeElement === input) {
785
- if (isNonColorValue) {
786
- colorSource = currentValue === 'transparent' ? 'rgba(0,0,0,0)' : 'rgb(0,0,0)';
787
- } else {
788
- colorSource = currentValue;
789
- }
790
- } else if (format === 'hex') {
791
- colorSource = i1.value;
792
- } else if (format === 'hsl') {
793
- colorSource = {
794
- h: v1,
795
- s: v2,
796
- l: v3,
797
- a: alpha,
798
- };
799
- } else if (format === 'hwb') {
800
- colorSource = {
801
- h: v1,
802
- w: v2,
803
- b: v3,
804
- a: alpha,
805
- };
806
- } else {
807
- colorSource = {
808
- r: v1,
809
- g: v2,
810
- b: v3,
811
- a: alpha,
812
- };
813
- }
814
-
815
- const { r, g, b, a } = new Color(colorSource);
816
-
817
- ObjectAssign(this.color, {
818
- r,
819
- g,
820
- b,
821
- a,
822
- });
823
- this.setControlPositions();
824
- this.updateAppearance();
825
- this.updateInputs();
826
- this.updateControls();
827
- this.updateVisuals();
828
-
829
- // set non-color keyword
830
- if (activeElement === input && isNonColorValue) {
831
- this.value = currentValue;
832
- }
833
- }
834
- };
835
-
836
- /**
837
- * Updates `ColorPicker` first control:
838
- * * `lightness` and `saturation` for HEX/RGB;
839
- * * `lightness` and `hue` for HSL.
840
- *
841
- * @param X the X component of the offset
842
- * @param Y the Y component of the offset
843
- */
844
- changeControl1(X: number, Y: number): void {
845
- let [offsetX, offsetY] = [0, 0];
846
- const { controlPositions, visuals } = this;
847
- const { offsetHeight, offsetWidth } = visuals[0];
848
-
849
- if (X > offsetWidth) offsetX = offsetWidth;
850
- else if (X >= 0) offsetX = X;
851
-
852
- if (Y > offsetHeight) offsetY = offsetHeight;
853
- else if (Y >= 0) offsetY = Y;
854
-
855
- const hue = controlPositions.c2y / offsetHeight;
856
-
857
- const saturation = offsetX / offsetWidth;
858
-
859
- const lightness = 1 - offsetY / offsetHeight;
860
- const alpha = 1 - controlPositions.c3y / offsetHeight;
861
-
862
- // new color
863
- const { r, g, b, a } = new Color({
864
- h: hue,
865
- s: saturation,
866
- v: lightness,
867
- a: alpha,
868
- });
869
-
870
- ObjectAssign(this.color, {
871
- r,
872
- g,
873
- b,
874
- a,
875
- });
876
-
877
- // new positions
878
- this.controlPositions.c1x = offsetX;
879
- this.controlPositions.c1y = offsetY;
880
-
881
- // update color picker
882
- this.updateAppearance();
883
- this.updateInputs();
884
- this.updateControls();
885
- this.updateVisuals();
886
- }
887
-
888
- /**
889
- * Updates `ColorPicker` second control:
890
- * * `hue` for HEX/RGB/HWB;
891
- * * `saturation` for HSL.
892
- *
893
- * @param Y the Y offset
894
- */
895
- changeControl2(Y: number) {
896
- const { controlPositions, visuals } = this;
897
- const { offsetHeight, offsetWidth } = visuals[0];
898
-
899
- let offsetY = 0;
900
-
901
- if (Y > offsetHeight) offsetY = offsetHeight;
902
- else if (Y >= 0) offsetY = Y;
903
-
904
- const hue = offsetY / offsetHeight;
905
- const saturation = controlPositions.c1x / offsetWidth;
906
- const lightness = 1 - controlPositions.c1y / offsetHeight;
907
- const alpha = 1 - controlPositions.c3y / offsetHeight;
908
-
909
- // new color
910
- const { r, g, b, a } = new Color({
911
- h: hue,
912
- s: saturation,
913
- v: lightness,
914
- a: alpha,
915
- });
916
-
917
- ObjectAssign(this.color, {
918
- r,
919
- g,
920
- b,
921
- a,
922
- });
923
-
924
- // new position
925
- this.controlPositions.c2y = offsetY;
926
- // update color picker
927
- this.updateAppearance();
928
- this.updateInputs();
929
- this.updateControls();
930
- this.updateVisuals();
931
- }
932
-
933
- /**
934
- * Updates `ColorPicker` last control,
935
- * the `alpha` channel.
936
- *
937
- * @param Y
938
- */
939
- changeAlpha(Y: number) {
940
- const { visuals } = this;
941
- const { offsetHeight } = visuals[0];
942
- let offsetY = 0;
943
-
944
- if (Y > offsetHeight) offsetY = offsetHeight;
945
- else if (Y >= 0) offsetY = Y;
946
-
947
- // update color alpha
948
- const alpha = 1 - offsetY / offsetHeight;
949
- this.color.setAlpha(alpha);
950
- // update position
951
- this.controlPositions.c3y = offsetY;
952
- // update color picker
953
- this.updateAppearance();
954
- this.updateInputs();
955
- this.updateControls();
956
- this.updateVisuals();
957
- }
958
-
959
- /**
960
- * Updates `ColorPicker` control positions on:
961
- * * initialization
962
- * * window resize
963
- */
964
- update = () => {
965
- this.updateDropdownPosition();
966
- this.updateAppearance();
967
- this.setControlPositions();
968
- this.updateInputs(true);
969
- this.updateControls();
970
- this.updateVisuals();
971
- };
972
-
973
- /** Updates the open dropdown position on *scroll* event. */
974
- updateDropdownPosition() {
975
- const { input, colorPicker, colorMenu } = this;
976
- const elRect = getBoundingClientRect(input);
977
- const { top, bottom } = elRect;
978
- const { offsetHeight: elHeight } = input;
979
- const windowHeight = getDocumentElement(input).clientHeight;
980
- const isPicker = hasClass(colorPicker, 'show');
981
- const dropdown = isPicker ? colorPicker : colorMenu;
982
- if (!dropdown) return;
983
- const { offsetHeight: dropHeight } = dropdown;
984
- const distanceBottom = windowHeight - bottom;
985
- const distanceTop = top;
986
- const bottomExceed = top + dropHeight + elHeight > windowHeight; // show
987
- const topExceed = top - dropHeight < 0; // show-top
988
-
989
- if ((hasClass(dropdown, 'bottom') || !topExceed) && distanceBottom < distanceTop && bottomExceed) {
990
- removeClass(dropdown, 'bottom');
991
- addClass(dropdown, 'top');
992
- } else {
993
- removeClass(dropdown, 'top');
994
- addClass(dropdown, 'bottom');
995
- }
996
- }
997
-
998
- /** Updates control knobs' positions. */
999
- setControlPositions() {
1000
- const { visuals, color, hsv } = this;
1001
- const { offsetHeight, offsetWidth } = visuals[0];
1002
- const alpha = color.a;
1003
- const hue = hsv.h;
1004
-
1005
- const saturation = hsv.s;
1006
- const lightness = hsv.v;
1007
-
1008
- this.controlPositions.c1x = saturation * offsetWidth;
1009
- this.controlPositions.c1y = (1 - lightness) * offsetHeight;
1010
- this.controlPositions.c2y = hue * offsetHeight;
1011
- this.controlPositions.c3y = (1 - alpha) * offsetHeight;
1012
- }
1013
-
1014
- /** Update the visual appearance label and control knob labels. */
1015
- updateAppearance() {
1016
- const { componentLabels, color, parent, hsv, hex, format, controlKnobs } = this;
1017
- const { appearanceLabel, hexLabel, valueLabel } = componentLabels;
1018
- let { r, g, b } = color.toRgb();
1019
- const [knob1, knob2, knob3] = controlKnobs;
1020
- const hue = roundPart(hsv.h * 360);
1021
- const alpha = color.a;
1022
- const saturation = roundPart(hsv.s * 100);
1023
- const lightness = roundPart(hsv.v * 100);
1024
- const colorName = this.appearance;
1025
-
1026
- let colorLabel = `${hexLabel} ${hex.split('').join(' ')}`;
1027
-
1028
- if (format === 'hwb') {
1029
- const { hwb } = this;
1030
- const whiteness = roundPart(hwb.w * 100);
1031
- const blackness = roundPart(hwb.b * 100);
1032
- colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
1033
- setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
1034
- setAttribute(knob1, ariaValueNow, `${whiteness}`);
1035
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1036
- setAttribute(knob2, ariaValueText, `${hue}%`);
1037
- setAttribute(knob2, ariaValueNow, `${hue}`);
1038
- } else {
1039
- [r, g, b] = [r, g, b].map(roundPart);
1040
- colorLabel = format === 'hsl' ? `HSL: ${hue}°, ${saturation}%, ${lightness}%` : colorLabel;
1041
- colorLabel = format === 'rgb' ? `RGB: ${r}, ${g}, ${b}` : colorLabel;
1042
-
1043
- setAttribute(knob1, ariaValueText, `${lightness}% & ${saturation}%`);
1044
- setAttribute(knob1, ariaValueNow, `${lightness}`);
1045
- setAttribute(knob2, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
1046
- setAttribute(knob2, ariaValueText, `${hue}°`);
1047
- setAttribute(knob2, ariaValueNow, `${hue}`);
1048
- }
1049
-
1050
- const alphaValue = roundPart(alpha * 100);
1051
- setAttribute(knob3, ariaValueText, `${alphaValue}%`);
1052
- setAttribute(knob3, ariaValueNow, `${alphaValue}`);
1053
-
1054
- // update the input backgroundColor
1055
- const newColor = color.toString();
1056
- setElementStyle(this.input, { backgroundColor: newColor });
1057
-
1058
- // toggle dark/light classes will also style the placeholder
1059
- // dark sets color white, light sets color black
1060
- // isDark ? '#000' : '#fff'
1061
- if (!this.isDark) {
1062
- if (hasClass(parent, 'txt-dark')) removeClass(parent, 'txt-dark');
1063
- if (!hasClass(parent, 'txt-light')) addClass(parent, 'txt-light');
1064
- } else {
1065
- if (hasClass(parent, 'txt-light')) removeClass(parent, 'txt-light');
1066
- if (!hasClass(parent, 'txt-dark')) addClass(parent, 'txt-dark');
1067
- }
1068
- }
1069
-
1070
- /** Updates the control knobs actual positions. */
1071
- updateControls() {
1072
- const { controlKnobs, controlPositions } = this;
1073
- let { c1x, c1y, c2y, c3y } = controlPositions;
1074
- const [control1, control2, control3] = controlKnobs;
1075
- // round control positions
1076
- [c1x, c1y, c2y, c3y] = [c1x, c1y, c2y, c3y].map(roundPart);
1077
-
1078
- setElementStyle(control1, {
1079
- transform: `translate3d(${c1x - 4}px,${c1y - 4}px,0)`,
1080
- });
1081
- setElementStyle(control2, { transform: `translate3d(0,${c2y - 4}px,0)` });
1082
- setElementStyle(control3, { transform: `translate3d(0,${c3y - 4}px,0)` });
1083
- }
1084
-
1085
- /**
1086
- * Updates all color form inputs.
1087
- *
1088
- * @param isPrevented when `true`, the component original event is prevented
1089
- */
1090
- updateInputs(isPrevented?: boolean) {
1091
- const { value: oldColor, format, inputs, color, hsl } = this;
1092
- const [i1, i2, i3, i4] = inputs;
1093
- const alpha = roundPart(color.a * 100);
1094
- const hue = roundPart(hsl.h * 360);
1095
- let newColor = color.toString();
1096
-
1097
- /* istanbul ignore else */
1098
- if (format === 'hex') {
1099
- newColor = this.color.toHexString(true);
1100
- i1.value = this.hex;
1101
- } else if (format === 'hsl') {
1102
- const lightness = roundPart(hsl.l * 100);
1103
- const saturation = roundPart(hsl.s * 100);
1104
- newColor = this.color.toHslString();
1105
- i1.value = `${hue}`;
1106
- i2.value = `${saturation}`;
1107
- i3.value = `${lightness}`;
1108
- i4.value = `${alpha}`;
1109
- } else if (format === 'hwb') {
1110
- const { w, b } = this.hwb;
1111
- const whiteness = roundPart(w * 100);
1112
- const blackness = roundPart(b * 100);
1113
-
1114
- newColor = this.color.toHwbString();
1115
- i1.value = `${hue}`;
1116
- i2.value = `${whiteness}`;
1117
- i3.value = `${blackness}`;
1118
- i4.value = `${alpha}`;
1119
- } else if (format === 'rgb') {
1120
- let { r, g, b } = this.rgb;
1121
- [r, g, b] = [r, g, b].map(roundPart);
1122
-
1123
- newColor = this.color.toRgbString();
1124
- i1.value = `${r}`;
1125
- i2.value = `${g}`;
1126
- i3.value = `${b}`;
1127
- i4.value = `${alpha}`;
1128
- }
1129
-
1130
- // update the color value
1131
- this.value = newColor;
1132
-
1133
- // don't trigger the custom event unless it's really changed
1134
- if (!isPrevented && newColor !== oldColor) {
1135
- firePickerChange(this);
1136
- }
1137
- }
1138
-
1139
- /**
1140
- * Toggle the `ColorPicker` dropdown visibility.
1141
- *
1142
- * @param e
1143
- */
1144
- togglePicker = (e?: Event) => {
1145
- if (e) e.preventDefault();
1146
- const { colorPicker } = this;
1147
-
1148
- if (this.isOpen && hasClass(colorPicker, 'show')) {
1149
- this.hide(true);
1150
- } else {
1151
- showDropdown(this, colorPicker);
1152
- }
1153
- };
1154
-
1155
- /** Shows the `ColorPicker` dropdown. */
1156
- showPicker = () => {
1157
- const { colorPicker } = this;
1158
-
1159
- if (!['top', 'bottom'].some(c => hasClass(colorPicker, c))) {
1160
- showDropdown(this, colorPicker);
1161
- }
1162
- };
1163
-
1164
- /**
1165
- * Toggles the visibility of the `ColorPicker` presets menu.
1166
- *
1167
- * @param e
1168
- * @this {ColorPicker}
1169
- */
1170
- toggleMenu = (e?: Event) => {
1171
- if (e) e.preventDefault();
1172
- const { colorMenu } = this;
1173
-
1174
- if (this.isOpen && hasClass(colorMenu, 'show')) {
1175
- this.hide(true);
1176
- } else {
1177
- showDropdown(this, colorMenu);
1178
- }
1179
- };
1180
-
1181
- /**
1182
- * Hides the currently open `ColorPicker` dropdown.
1183
- *
1184
- * @param {boolean=} focusPrevented
1185
- */
1186
- hide(focusPrevented?: boolean) {
1187
- if (this.isOpen) {
1188
- const { pickerToggle, menuToggle, colorPicker, colorMenu, parent, input } = this;
1189
- const openPicker = hasClass(colorPicker, 'show');
1190
- const openDropdown = openPicker ? colorPicker : colorMenu;
1191
- const relatedBtn = openPicker ? pickerToggle : menuToggle;
1192
- const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
1193
-
1194
- this.value = this.color.toString(true);
1195
-
1196
- /* istanbul ignore else */
1197
- if (openDropdown) {
1198
- removeClass(openDropdown, 'show');
1199
- setAttribute(relatedBtn, ariaExpanded, 'false');
1200
- setTimeout(() => {
1201
- removePosition(openDropdown);
1202
- /* istanbul ignore else */
1203
- if (!querySelector('.show', parent)) {
1204
- removeClass(parent, 'open');
1205
- toggleEventsOnShown(this);
1206
- this.isOpen = false;
1207
- }
1208
- }, animationDuration);
1209
- }
1210
-
1211
- if (!focusPrevented) {
1212
- focus(pickerToggle);
1213
- }
1214
- setAttribute(input, tabindex, '-1');
1215
- if (relatedBtn === menuToggle) {
1216
- setAttribute(menuToggle, tabindex, '-1');
1217
- }
1218
- }
1219
- }
1220
-
1221
- /** Removes `ColorPicker` from target `<input>`. */
1222
- dispose() {
1223
- const { input, parent } = this;
1224
- this.hide(true);
1225
- toggleEvents(this);
1226
- [...parent.children].forEach(el => {
1227
- if (el !== input) el.remove();
1228
- });
1229
-
1230
- removeAttribute(input, tabindex);
1231
- setElementStyle(input, { backgroundColor: '' });
1232
-
1233
- ['txt-light', 'txt-dark'].forEach(c => removeClass(parent, c));
1234
- Data.remove(input, colorPickerString);
1235
- }
1236
- }