@thednp/color-picker 0.0.2-alpha5 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. package/README.md +21 -19
  2. package/dist/css/color-picker.css +82 -46
  3. package/dist/css/color-picker.min.css +2 -2
  4. package/dist/css/color-picker.rtl.css +82 -46
  5. package/dist/css/color-picker.rtl.min.css +2 -2
  6. package/dist/js/color-esm.js +2 -5
  7. package/dist/js/color-esm.min.js +1 -1
  8. package/dist/js/color-palette-esm.js +2 -5
  9. package/dist/js/color-palette-esm.min.js +1 -1
  10. package/dist/js/color-palette.js +2 -5
  11. package/dist/js/color-palette.min.js +1 -1
  12. package/dist/js/color-picker-element-esm.js +184 -189
  13. package/dist/js/color-picker-element-esm.min.js +2 -2
  14. package/dist/js/color-picker-element.js +184 -189
  15. package/dist/js/color-picker-element.min.js +2 -2
  16. package/dist/js/color-picker-esm.js +77 -134
  17. package/dist/js/color-picker-esm.min.js +2 -2
  18. package/dist/js/color-picker.js +77 -134
  19. package/dist/js/color-picker.min.js +2 -2
  20. package/dist/js/color.js +2 -5
  21. package/dist/js/color.min.js +1 -1
  22. package/package.json +20 -19
  23. package/src/js/color-picker-element.js +45 -37
  24. package/src/js/color-picker.js +46 -60
  25. package/src/js/color.js +1 -4
  26. package/src/js/index.js +5 -0
  27. package/src/js/util/getColorMenu.js +7 -8
  28. package/src/js/util/setMarkup.js +4 -7
  29. package/src/js/util/toggleCEAttr.js +70 -0
  30. package/src/js/util/version.js +0 -1
  31. package/src/js/version.js +0 -1
  32. package/src/scss/_variables.scss +7 -0
  33. package/src/scss/color-picker.scss +86 -45
  34. package/types/cp.d.ts +31 -17
  35. package/types/index.d.ts +0 -4
  36. package/types/source/source.ts +0 -1
  37. package/types/source/types.d.ts +8 -6
@@ -1,4 +1,4 @@
1
- import { addListener, removeListener } from 'event-listener.js';
1
+ import { addListener, removeListener } from '@thednp/event-listener/src/event-listener';
2
2
 
3
3
  import ariaDescription from 'shorter-js/src/strings/ariaDescription';
4
4
  import ariaSelected from 'shorter-js/src/strings/ariaSelected';
@@ -16,12 +16,12 @@ import focusinEvent from 'shorter-js/src/strings/focusinEvent';
16
16
  import mouseclickEvent from 'shorter-js/src/strings/mouseclickEvent';
17
17
  import keydownEvent from 'shorter-js/src/strings/keydownEvent';
18
18
  import changeEvent from 'shorter-js/src/strings/changeEvent';
19
- import touchstartEvent from 'shorter-js/src/strings/touchstartEvent';
19
+
20
20
  import touchmoveEvent from 'shorter-js/src/strings/touchmoveEvent';
21
- import touchendEvent from 'shorter-js/src/strings/touchendEvent';
22
- import mousedownEvent from 'shorter-js/src/strings/mousedownEvent';
23
- import mousemoveEvent from 'shorter-js/src/strings/mousemoveEvent';
24
- import mouseupEvent from 'shorter-js/src/strings/mouseupEvent';
21
+ import pointerdownEvent from 'shorter-js/src/strings/pointerdownEvent';
22
+ import pointermoveEvent from 'shorter-js/src/strings/pointermoveEvent';
23
+ import pointerupEvent from 'shorter-js/src/strings/pointerupEvent';
24
+
25
25
  import scrollEvent from 'shorter-js/src/strings/scrollEvent';
26
26
  import keyupEvent from 'shorter-js/src/strings/keyupEvent';
27
27
  import resizeEvent from 'shorter-js/src/strings/resizeEvent';
@@ -29,7 +29,6 @@ import focusoutEvent from 'shorter-js/src/strings/focusoutEvent';
29
29
 
30
30
  import getDocument from 'shorter-js/src/get/getDocument';
31
31
  import getDocumentElement from 'shorter-js/src/get/getDocumentElement';
32
- import getWindow from 'shorter-js/src/get/getWindow';
33
32
  import getElementStyle from 'shorter-js/src/get/getElementStyle';
34
33
  import getUID from 'shorter-js/src/get/getUID';
35
34
  import getBoundingClientRect from 'shorter-js/src/get/getBoundingClientRect';
@@ -80,7 +79,7 @@ const colorPickerDefaults = {
80
79
  // ColorPicker Static Methods
81
80
  // ==========================
82
81
 
83
- /** @type {CP.GetInstance<ColorPicker>} */
82
+ /** @type {CP.GetInstance<ColorPicker, HTMLInputElement>} */
84
83
  const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
85
84
 
86
85
  /** @type {CP.InitCallback<ColorPicker>} */
@@ -115,17 +114,12 @@ function toggleEventsOnShown(self, action) {
115
114
  const fn = action ? addListener : removeListener;
116
115
  const { input, colorMenu, parent } = self;
117
116
  const doc = getDocument(input);
118
- const win = getWindow(input);
119
- const pointerEvents = `on${touchstartEvent}` in doc
120
- ? { down: touchstartEvent, move: touchmoveEvent, up: touchendEvent }
121
- : { down: mousedownEvent, move: mousemoveEvent, up: mouseupEvent };
117
+ const win = doc.defaultView;
122
118
 
123
- fn(self.controls, pointerEvents.down, self.pointerDown);
119
+ fn(self.controls, pointerdownEvent, self.pointerDown);
124
120
  self.controlKnobs.forEach((x) => fn(x, keydownEvent, self.handleKnobs));
125
121
 
126
- // @ts-ignore -- this is `Window`
127
122
  fn(win, scrollEvent, self.handleScroll);
128
- // @ts-ignore -- this is `Window`
129
123
  fn(win, resizeEvent, self.update);
130
124
 
131
125
  [input, ...self.inputs].forEach((x) => fn(x, changeEvent, self.changeHandler));
@@ -135,8 +129,8 @@ function toggleEventsOnShown(self, action) {
135
129
  fn(colorMenu, keydownEvent, self.menuKeyHandler);
136
130
  }
137
131
 
138
- fn(doc, pointerEvents.move, self.pointerMove);
139
- fn(doc, pointerEvents.up, self.pointerUp);
132
+ fn(doc, pointermoveEvent, self.pointerMove);
133
+ fn(doc, pointerupEvent, self.pointerUp);
140
134
  fn(parent, focusoutEvent, self.handleFocusOut);
141
135
  fn(doc, keyupEvent, self.handleDismiss);
142
136
  }
@@ -155,6 +149,7 @@ function firePickerChange(self) {
155
149
  * @returns {void}
156
150
  */
157
151
  function removePosition(element) {
152
+ /* istanbul ignore else */
158
153
  if (element) {
159
154
  ['bottom', 'top'].forEach((x) => removeClass(element, x));
160
155
  }
@@ -218,7 +213,6 @@ export default class ColorPicker {
218
213
  constructor(target, config) {
219
214
  const self = this;
220
215
  /** @type {HTMLInputElement} */
221
- // @ts-ignore
222
216
  const input = querySelector(target);
223
217
 
224
218
  // invalidate
@@ -229,7 +223,6 @@ export default class ColorPicker {
229
223
  if (!parent) throw new TypeError('ColorPicker requires a specific markup to work.');
230
224
 
231
225
  /** @type {HTMLElement} */
232
- // @ts-ignore
233
226
  self.parent = parent;
234
227
 
235
228
  /** @type {number} */
@@ -257,6 +250,7 @@ export default class ColorPicker {
257
250
  } = normalizeOptions(this.isCE ? parent : input, colorPickerDefaults, config || {});
258
251
 
259
252
  let translatedColorLabels = colorNames;
253
+ /* istanbul ignore else */
260
254
  if (colorLabels instanceof Array && colorLabels.length === 17) {
261
255
  translatedColorLabels = colorLabels;
262
256
  } else if (colorLabels && colorLabels.split(',').length === 17) {
@@ -273,7 +267,7 @@ export default class ColorPicker {
273
267
  ? JSON.parse(componentLabels) : componentLabels;
274
268
 
275
269
  /** @type {Record<string, string>} */
276
- self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
270
+ self.componentLabels = ObjectAssign({ ...colorPickerLabels }, tempComponentLabels);
277
271
 
278
272
  /** @type {Color} */
279
273
  self.color = new Color(input.value || '#fff', format);
@@ -282,14 +276,14 @@ export default class ColorPicker {
282
276
  self.format = format;
283
277
 
284
278
  // set colour defaults
285
- if (colorKeywords instanceof Array) {
279
+ if (colorKeywords instanceof Array && colorKeywords.length) {
286
280
  self.colorKeywords = colorKeywords;
287
281
  } else if (typeof colorKeywords === 'string' && colorKeywords.length) {
288
282
  self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
289
283
  }
290
284
 
291
285
  // set colour presets
292
- if (colorPresets instanceof Array) {
286
+ if (colorPresets instanceof Array && colorPresets.length) {
293
287
  self.colorPresets = colorPresets;
294
288
  } else if (typeof colorPresets === 'string' && colorPresets.length) {
295
289
  if (isValidJSON(colorPresets)) {
@@ -322,26 +316,20 @@ export default class ColorPicker {
322
316
  const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
323
317
  // set main elements
324
318
  /** @type {HTMLElement} */
325
- // @ts-ignore
326
319
  self.pickerToggle = querySelector('.picker-toggle', parent);
327
320
  /** @type {HTMLElement} */
328
- // @ts-ignore
329
321
  self.menuToggle = querySelector('.menu-toggle', parent);
330
322
  /** @type {HTMLElement} */
331
- // @ts-ignore
332
323
  self.colorPicker = colorPicker;
333
324
  /** @type {HTMLElement} */
334
- // @ts-ignore
335
325
  self.colorMenu = colorMenu;
336
326
  /** @type {HTMLInputElement[]} */
337
- // @ts-ignore
338
327
  self.inputs = [...getElementsByClassName('color-input', parent)];
339
328
  const [controls] = getElementsByClassName('color-controls', parent);
340
329
  self.controls = controls;
341
330
  /** @type {(HTMLElement | Element)[]} */
342
331
  self.controlKnobs = [...getElementsByClassName('knob', controls)];
343
332
  /** @type {(HTMLElement)[]} */
344
- // @ts-ignore
345
333
  self.visuals = [...getElementsByClassName('visual-control', controls)];
346
334
 
347
335
  // update colour picker controls, inputs and visuals
@@ -420,6 +408,7 @@ export default class ColorPicker {
420
408
  let colorName;
421
409
 
422
410
  // determine color appearance
411
+ /* istanbul ignore else */
423
412
  if (lightness === 100 && saturation === 0) {
424
413
  colorName = colorLabels.white;
425
414
  } else if (lightness === 0) {
@@ -493,7 +482,6 @@ export default class ColorPicker {
493
482
  * @this {ColorPicker}
494
483
  */
495
484
  handleFocusOut({ relatedTarget }) {
496
- // @ts-ignore
497
485
  if (relatedTarget && !this.parent.contains(relatedTarget)) {
498
486
  this.hide(true);
499
487
  }
@@ -520,13 +508,14 @@ export default class ColorPicker {
520
508
  const self = this;
521
509
  const { activeElement } = getDocument(self.input);
522
510
 
523
- if ((e.type === touchmoveEvent && self.dragElement)
511
+ self.updateDropdownPosition();
512
+
513
+ /* istanbul ignore next */
514
+ if (([pointermoveEvent, touchmoveEvent].includes(e.type) && self.dragElement)
524
515
  || (activeElement && self.controlKnobs.includes(activeElement))) {
525
516
  e.stopPropagation();
526
517
  e.preventDefault();
527
518
  }
528
-
529
- self.updateDropdownPosition();
530
519
  }
531
520
 
532
521
  /**
@@ -536,7 +525,6 @@ export default class ColorPicker {
536
525
  */
537
526
  menuKeyHandler(e) {
538
527
  const { target, code } = e;
539
- // @ts-ignore
540
528
  const { previousElementSibling, nextElementSibling, parentElement } = target;
541
529
  const isColorOptionsMenu = parentElement && hasClass(parentElement, 'color-options');
542
530
  const allSiblings = [...parentElement.children];
@@ -575,20 +563,20 @@ export default class ColorPicker {
575
563
 
576
564
  /**
577
565
  * The `ColorPicker` click event listener for the colour menu presets / defaults.
578
- * @param {Partial<Event>} e
566
+ * @param {Event} e
579
567
  * @this {ColorPicker}
580
568
  */
581
569
  menuClickHandler(e) {
582
570
  const self = this;
583
- /** @type {*} */
584
571
  const { target } = e;
585
572
  const { colorMenu } = self;
586
573
  const newOption = (getAttribute(target, 'data-value') || '').trim();
587
574
  // invalidate for targets other than color options
588
575
  if (!newOption.length) return;
589
576
  const currentActive = querySelector('li.active', colorMenu);
590
- let newColor = nonColors.includes(newOption) ? 'white' : newOption;
591
- newColor = newOption === 'transparent' ? 'rgba(0,0,0,0)' : newOption;
577
+ let newColor = newOption;
578
+ newColor = nonColors.includes(newColor) ? 'white' : newColor;
579
+ newColor = newColor === 'transparent' ? 'rgba(0,0,0,0)' : newColor;
592
580
 
593
581
  const {
594
582
  r, g, b, a,
@@ -600,7 +588,9 @@ export default class ColorPicker {
600
588
 
601
589
  self.update();
602
590
 
591
+ /* istanbul ignore else */
603
592
  if (currentActive !== target) {
593
+ /* istanbul ignore else */
604
594
  if (currentActive) {
605
595
  removeClass(currentActive, 'active');
606
596
  removeAttribute(currentActive, ariaSelected);
@@ -618,15 +608,13 @@ export default class ColorPicker {
618
608
 
619
609
  /**
620
610
  * The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
621
- * @param {TouchEvent} e
611
+ * @param {PointerEvent} e
622
612
  * @this {ColorPicker}
623
613
  */
624
614
  pointerDown(e) {
625
615
  const self = this;
626
616
  /** @type {*} */
627
- const {
628
- type, target, touches, pageX, pageY,
629
- } = e;
617
+ const { target, pageX, pageY } = e;
630
618
  const { colorMenu, visuals, controlKnobs } = self;
631
619
  const [v1, v2, v3] = visuals;
632
620
  const [c1, c2, c3] = controlKnobs;
@@ -634,11 +622,10 @@ export default class ColorPicker {
634
622
  const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
635
623
  const visualRect = getBoundingClientRect(visual);
636
624
  const html = getDocumentElement(v1);
637
- const X = type === 'touchstart' ? touches[0].pageX : pageX;
638
- const Y = type === 'touchstart' ? touches[0].pageY : pageY;
639
- const offsetX = X - html.scrollLeft - visualRect.left;
640
- const offsetY = Y - html.scrollTop - visualRect.top;
625
+ const offsetX = pageX - html.scrollLeft - visualRect.left;
626
+ const offsetY = pageY - html.scrollTop - visualRect.top;
641
627
 
628
+ /* istanbul ignore else */
642
629
  if (target === v1 || target === c1) {
643
630
  self.dragElement = visual;
644
631
  self.changeControl1(offsetX, offsetY);
@@ -662,7 +649,7 @@ export default class ColorPicker {
662
649
 
663
650
  /**
664
651
  * The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
665
- * @param {TouchEvent} e
652
+ * @param {PointerEvent} e
666
653
  * @this {ColorPicker}
667
654
  */
668
655
  pointerUp({ target }) {
@@ -671,9 +658,8 @@ export default class ColorPicker {
671
658
  const doc = getDocument(parent);
672
659
  const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
673
660
  const selection = doc.getSelection();
674
- // @ts-ignore
661
+
675
662
  if (!self.dragElement && !selection.toString().length
676
- // @ts-ignore
677
663
  && !parent.contains(target)) {
678
664
  self.hide(currentOpen);
679
665
  }
@@ -683,25 +669,20 @@ export default class ColorPicker {
683
669
 
684
670
  /**
685
671
  * The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
686
- * @param {TouchEvent} e
672
+ * @param {PointerEvent} e
687
673
  */
688
674
  pointerMove(e) {
689
675
  const self = this;
690
676
  const { dragElement, visuals } = self;
691
677
  const [v1, v2, v3] = visuals;
692
- const {
693
- // @ts-ignore
694
- type, touches, pageX, pageY,
695
- } = e;
678
+ const { pageX, pageY } = e;
696
679
 
697
680
  if (!dragElement) return;
698
681
 
699
682
  const controlRect = getBoundingClientRect(dragElement);
700
683
  const win = getDocumentElement(v1);
701
- const X = type === touchmoveEvent ? touches[0].pageX : pageX;
702
- const Y = type === touchmoveEvent ? touches[0].pageY : pageY;
703
- const offsetX = X - win.scrollLeft - controlRect.left;
704
- const offsetY = Y - win.scrollTop - controlRect.top;
684
+ const offsetX = pageX - win.scrollLeft - controlRect.left;
685
+ const offsetY = pageY - win.scrollTop - controlRect.top;
705
686
 
706
687
  if (dragElement === v1) {
707
688
  self.changeControl1(offsetX, offsetY);
@@ -735,13 +716,16 @@ export default class ColorPicker {
735
716
  const currentKnob = controlKnobs.find((x) => x === activeElement);
736
717
  const yRatio = offsetHeight / 360;
737
718
 
719
+ /* istanbul ignore else */
738
720
  if (currentKnob) {
739
721
  let offsetX = 0;
740
722
  let offsetY = 0;
741
723
 
724
+ /* istanbul ignore else */
742
725
  if (target === c1) {
743
726
  const xRatio = offsetWidth / 100;
744
727
 
728
+ /* istanbul ignore else */
745
729
  if ([keyArrowLeft, keyArrowRight].includes(code)) {
746
730
  self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
747
731
  } else if ([keyArrowUp, keyArrowDown].includes(code)) {
@@ -787,6 +771,7 @@ export default class ColorPicker {
787
771
  const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
788
772
  const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
789
773
 
774
+ /* istanbul ignore else */
790
775
  if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
791
776
  if (activeElement === input) {
792
777
  if (isNonColorValue) {
@@ -1101,6 +1086,7 @@ export default class ColorPicker {
1101
1086
  const hue = roundPart(hsl.h * 360);
1102
1087
  let newColor;
1103
1088
 
1089
+ /* istanbul ignore else */
1104
1090
  if (format === 'hex') {
1105
1091
  newColor = self.color.toHexString(true);
1106
1092
  i1.value = self.hex;
@@ -1201,15 +1187,15 @@ export default class ColorPicker {
1201
1187
  const relatedBtn = openPicker ? pickerToggle : menuToggle;
1202
1188
  const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
1203
1189
 
1204
- // if (!self.isValid) {
1205
1190
  self.value = self.color.toString(true);
1206
- // }
1207
1191
 
1192
+ /* istanbul ignore else */
1208
1193
  if (openDropdown) {
1209
1194
  removeClass(openDropdown, 'show');
1210
1195
  setAttribute(relatedBtn, ariaExpanded, 'false');
1211
1196
  setTimeout(() => {
1212
1197
  removePosition(openDropdown);
1198
+ /* istanbul ignore else */
1213
1199
  if (!querySelector('.show', parent)) {
1214
1200
  removeClass(parent, 'open');
1215
1201
  toggleEventsOnShown(self);
@@ -1222,7 +1208,7 @@ export default class ColorPicker {
1222
1208
  focus(pickerToggle);
1223
1209
  }
1224
1210
  setAttribute(input, tabIndex, '-1');
1225
- if (menuToggle) {
1211
+ if (relatedBtn === menuToggle) {
1226
1212
  setAttribute(menuToggle, tabIndex, '-1');
1227
1213
  }
1228
1214
  }
package/src/js/color.js CHANGED
@@ -640,7 +640,7 @@ function inputToRGB(input) {
640
640
  format = 'hwb';
641
641
  }
642
642
  if (isValidCSSUnit(color.a)) {
643
- a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
643
+ a = color.a;
644
644
  a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
645
645
  }
646
646
  }
@@ -651,9 +651,6 @@ function inputToRGB(input) {
651
651
  return {
652
652
  ok,
653
653
  format,
654
- // r: Math.min(255, Math.max(rgb.r, 0)),
655
- // g: Math.min(255, Math.max(rgb.g, 0)),
656
- // b: Math.min(255, Math.max(rgb.b, 0)),
657
654
  r: rgb.r,
658
655
  g: rgb.g,
659
656
  b: rgb.b,
package/src/js/index.js CHANGED
@@ -1,3 +1,8 @@
1
+ /**
2
+ * A single import is required to add the `CP` namespace to `src` sources.
3
+ * @typedef {import("../../types/index")}
4
+ */
5
+
1
6
  import ColorPicker from './color-picker';
2
7
 
3
8
  export default ColorPicker;
@@ -23,17 +23,16 @@ export default function getColorMenu(self, colorsSource, menuClass) {
23
23
  const isOptionsMenu = menuClass === 'color-options';
24
24
  const isPalette = colorsSource instanceof ColorPalette;
25
25
  const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
26
- let colorsArray = isPalette ? colorsSource.colors : colorsSource;
27
- colorsArray = colorsArray instanceof Array ? colorsArray : [];
26
+ const colorsArray = isPalette ? colorsSource.colors : colorsSource;
28
27
  const colorsCount = colorsArray.length;
29
28
  const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
30
- const fit = lightSteps || [9, 10].find((x) => colorsCount > x * 2 && !(colorsCount % x)) || 5;
29
+ const fit = lightSteps || [9, 10].find((x) => colorsCount >= x * 2 && !(colorsCount % x)) || 5;
31
30
  const isMultiLine = isOptionsMenu && colorsCount > fit;
32
31
  let rowCountHover = 2;
33
- rowCountHover = isMultiLine && colorsCount >= fit * 2 ? 3 : rowCountHover;
34
- rowCountHover = colorsCount >= fit * 3 ? 4 : rowCountHover;
35
- rowCountHover = colorsCount >= fit * 4 ? 5 : rowCountHover;
36
- const rowCount = rowCountHover - (colorsCount < fit * 3 ? 1 : 2);
32
+ rowCountHover = isMultiLine && colorsCount > fit * 2 ? 3 : rowCountHover;
33
+ rowCountHover = isMultiLine && colorsCount > fit * 3 ? 4 : rowCountHover;
34
+ rowCountHover = isMultiLine && colorsCount > fit * 4 ? 5 : rowCountHover;
35
+ const rowCount = rowCountHover - (colorsCount <= fit * 3 ? 1 : 2);
37
36
  const isScrollable = isMultiLine && colorsCount > rowCount * fit;
38
37
  let finalClass = menuClass;
39
38
  finalClass += isScrollable ? ' scrollable' : '';
@@ -41,7 +40,7 @@ export default function getColorMenu(self, colorsSource, menuClass) {
41
40
  const gap = isMultiLine ? '1px' : '0.25rem';
42
41
  let optionSize = isMultiLine ? 1.75 : 2;
43
42
  optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
44
- const menuHeight = `${(rowCount || 1) * optionSize}rem`;
43
+ const menuHeight = `${rowCount * optionSize}rem`;
45
44
  const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
46
45
  /** @type {HTMLUListElement} */
47
46
  // @ts-ignore -- <UL> is an `HTMLElement`
@@ -17,7 +17,6 @@ import vHidden from './vHidden';
17
17
  import tabIndex from './tabindex';
18
18
 
19
19
  import Color from '../color';
20
- import ColorPalette from '../color-palette';
21
20
 
22
21
  /**
23
22
  * Generate HTML markup and update instance properties.
@@ -75,16 +74,14 @@ export default function setMarkup(self) {
75
74
  });
76
75
 
77
76
  // color presets
78
- if ((colorPresets instanceof Array && colorPresets.length)
79
- || (colorPresets instanceof ColorPalette && colorPresets.colors)) {
80
- const presetsMenu = getColorMenu(self, colorPresets, 'color-options');
81
- presetsDropdown.append(presetsMenu);
77
+ if (colorPresets) {
78
+ presetsDropdown.append(getColorMenu(self, colorPresets, 'color-options'));
82
79
  }
83
80
 
84
81
  // explicit defaults [reset, initial, inherit, transparent, currentColor]
82
+ // also custom defaults [default: #069, complementary: #930]
85
83
  if (colorKeywords && colorKeywords.length) {
86
- const keywordsMenu = getColorMenu(self, colorKeywords, 'color-defaults');
87
- presetsDropdown.append(keywordsMenu);
84
+ presetsDropdown.append(getColorMenu(self, colorKeywords, 'color-defaults'));
88
85
  }
89
86
 
90
87
  const presetsBtn = createElement({
@@ -0,0 +1,70 @@
1
+ import setAttribute from 'shorter-js/src/attr/setAttribute';
2
+ import removeAttribute from 'shorter-js/src/attr/removeAttribute';
3
+ import ObjectKeys from 'shorter-js/src/misc/ObjectKeys';
4
+
5
+ import ColorPalette from '../color-palette';
6
+ import colorNames from './colorNames';
7
+ import colorPickerLabels from './colorPickerLabels';
8
+
9
+ /**
10
+ * A small utility to toggle `ColorPickerElement` attributes
11
+ * when `connectedCallback` or `disconnectedCallback` methods
12
+ * are called and helps the instance keep its value and settings instact.
13
+ *
14
+ * @param {CP.ColorPickerElement} self ColorPickerElement instance
15
+ * @param {Function=} callback when `true`, attributes are added
16
+ *
17
+ * @example
18
+ * const attributes = [
19
+ * // essentials
20
+ * 'value', 'format',
21
+ * // presets menus
22
+ * 'color-presets', 'color-keywords',
23
+ * // labels
24
+ * 'color-labels', 'component-labels',
25
+ * ];
26
+ */
27
+ export default function toggleCEAttr(self, callback) {
28
+ if (callback) {
29
+ const { input, colorPicker } = self;
30
+
31
+ const {
32
+ value, format, colorPresets, colorKeywords, componentLabels, colorLabels,
33
+ } = colorPicker;
34
+
35
+ const { id, placeholder } = input;
36
+
37
+ setAttribute(self, 'data-id', id);
38
+ setAttribute(self, 'data-value', value);
39
+ setAttribute(self, 'data-format', format);
40
+ setAttribute(self, 'data-placeholder', placeholder);
41
+
42
+ if (ObjectKeys(colorPickerLabels).some((l) => colorPickerLabels[l] !== componentLabels[l])) {
43
+ setAttribute(self, 'data-component-labels', JSON.stringify(componentLabels));
44
+ }
45
+ if (!colorNames.every((c) => c === colorLabels[c])) {
46
+ setAttribute(self, 'data-color-labels', colorNames.map((n) => colorLabels[n]).join(','));
47
+ }
48
+ if (colorPresets instanceof ColorPalette) {
49
+ const { hue, hueSteps, lightSteps } = colorPresets;
50
+ setAttribute(self, 'data-color-presets', JSON.stringify({ hue, hueSteps, lightSteps }));
51
+ }
52
+ if (Array.isArray(colorPresets) && colorPresets.length) {
53
+ setAttribute(self, 'data-color-presets', colorPresets.join(','));
54
+ }
55
+ if (colorKeywords) {
56
+ setAttribute(self, 'data-color-keywords', colorKeywords.join(','));
57
+ }
58
+ setTimeout(callback, 0);
59
+ } else {
60
+ // keep id
61
+ // removeAttribute(self, 'data-id');
62
+ removeAttribute(self, 'data-value');
63
+ removeAttribute(self, 'data-format');
64
+ removeAttribute(self, 'data-placeholder');
65
+ removeAttribute(self, 'data-component-labels');
66
+ removeAttribute(self, 'data-color-labels');
67
+ removeAttribute(self, 'data-color-presets');
68
+ removeAttribute(self, 'data-color-keywords');
69
+ }
70
+ }
@@ -1,4 +1,3 @@
1
- // @ts-ignore
2
1
  import { version } from '../../../package.json';
3
2
 
4
3
  const Version = version;
package/src/js/version.js CHANGED
@@ -1,4 +1,3 @@
1
- // @ts-ignore
2
1
  import { version } from '../../package.json';
3
2
 
4
3
  const Version = version;
@@ -0,0 +1,7 @@
1
+ $transparency-levels: (
2
+ 15, 25, 33, 50, 75, 90
3
+ );
4
+
5
+ $dropdown-transition: transform .33s ease, opacity .33s ease;
6
+ $btn-transition: box-shadow .33s ease, border .33s ease;
7
+ $options-transition: height .33s ease;