@thednp/color-picker 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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 +369 -332
  16. package/dist/js/color-picker.mjs.map +1 -1
  17. package/package.json +36 -44
  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
- }