@thednp/color-picker 0.0.1-alpha1 → 0.0.1-alpha2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +40 -19
  3. package/dist/css/color-picker.css +481 -337
  4. package/dist/css/color-picker.min.css +2 -0
  5. package/dist/css/color-picker.rtl.css +506 -0
  6. package/dist/css/color-picker.rtl.min.css +2 -0
  7. package/dist/js/color-picker-element-esm.js +3810 -2
  8. package/dist/js/color-picker-element-esm.min.js +2 -0
  9. package/dist/js/color-picker-element.js +2009 -1242
  10. package/dist/js/color-picker-element.min.js +2 -2
  11. package/dist/js/color-picker-esm.js +3704 -0
  12. package/dist/js/color-picker-esm.min.js +2 -0
  13. package/dist/js/color-picker.js +1962 -1256
  14. package/dist/js/color-picker.min.js +2 -2
  15. package/package.json +18 -9
  16. package/src/js/color-palette.js +62 -0
  17. package/src/js/color-picker-element.js +55 -13
  18. package/src/js/color-picker.js +686 -595
  19. package/src/js/color.js +615 -349
  20. package/src/js/index.js +0 -9
  21. package/src/js/util/colorNames.js +2 -152
  22. package/src/js/util/colorPickerLabels.js +22 -0
  23. package/src/js/util/getColorControls.js +103 -0
  24. package/src/js/util/getColorForm.js +27 -19
  25. package/src/js/util/getColorMenu.js +95 -0
  26. package/src/js/util/isValidJSON.js +13 -0
  27. package/src/js/util/nonColors.js +5 -0
  28. package/src/js/util/templates.js +1 -0
  29. package/src/scss/color-picker.rtl.scss +23 -0
  30. package/src/scss/color-picker.scss +430 -0
  31. package/types/cp.d.ts +263 -160
  32. package/types/index.d.ts +9 -2
  33. package/types/source/source.ts +2 -1
  34. package/types/source/types.d.ts +28 -5
  35. package/dist/js/color-picker.esm.js +0 -2998
  36. package/dist/js/color-picker.esm.min.js +0 -2
  37. package/src/js/util/getColorControl.js +0 -49
  38. package/src/js/util/init.js +0 -14
package/src/js/index.js CHANGED
@@ -1,12 +1,3 @@
1
- import querySelectorAll from 'shorter-js/src/selectors/querySelectorAll';
2
1
  import ColorPicker from './color-picker';
3
2
 
4
- function initCallBack() {
5
- const { init, selector } = ColorPicker;
6
- [...querySelectorAll(selector)].forEach(init);
7
- }
8
-
9
- if (document.body) initCallBack();
10
- else document.addEventListener('DOMContentLoaded', initCallBack, { once: true });
11
-
12
3
  export default ColorPicker;
@@ -1,156 +1,6 @@
1
1
  /**
2
- * A complete list of web safe colors.
3
- * @see https://github.com/bahamas10/css-color-names/blob/master/css-color-names.json
2
+ * A list of 17 color names used for WAI-ARIA compliance.
4
3
  * @type {string[]}
5
4
  */
6
- const colorNames = [
7
- 'aliceblue',
8
- 'antiquewhite',
9
- 'aqua',
10
- 'aquamarine',
11
- 'azure',
12
- 'beige',
13
- 'bisque',
14
- 'black',
15
- 'blanchedalmond',
16
- 'blue',
17
- 'blueviolet',
18
- 'brown',
19
- 'burlywood',
20
- 'cadetblue',
21
- 'chartreuse',
22
- 'chocolate',
23
- 'coral',
24
- 'cornflowerblue',
25
- 'cornsilk',
26
- 'crimson',
27
- 'cyan',
28
- 'darkblue',
29
- 'darkcyan',
30
- 'darkgoldenrod',
31
- 'darkgray',
32
- 'darkgreen',
33
- 'darkgrey',
34
- 'darkkhaki',
35
- 'darkmagenta',
36
- 'darkolivegreen',
37
- 'darkorange',
38
- 'darkorchid',
39
- 'darkred',
40
- 'darksalmon',
41
- 'darkseagreen',
42
- 'darkslateblue',
43
- 'darkslategray',
44
- 'darkslategrey',
45
- 'darkturquoise',
46
- 'darkviolet',
47
- 'deeppink',
48
- 'deepskyblue',
49
- 'dimgray',
50
- 'dimgrey',
51
- 'dodgerblue',
52
- 'firebrick',
53
- 'floralwhite',
54
- 'forestgreen',
55
- 'fuchsia',
56
- 'gainsboro',
57
- 'ghostwhite',
58
- 'goldenrod',
59
- 'gold',
60
- 'gray',
61
- 'green',
62
- 'greenyellow',
63
- 'grey',
64
- 'honeydew',
65
- 'hotpink',
66
- 'indianred',
67
- 'indigo',
68
- 'ivory',
69
- 'khaki',
70
- 'lavenderblush',
71
- 'lavender',
72
- 'lawngreen',
73
- 'lemonchiffon',
74
- 'lightblue',
75
- 'lightcoral',
76
- 'lightcyan',
77
- 'lightgoldenrodyellow',
78
- 'lightgray',
79
- 'lightgreen',
80
- 'lightgrey',
81
- 'lightpink',
82
- 'lightsalmon',
83
- 'lightseagreen',
84
- 'lightskyblue',
85
- 'lightslategray',
86
- 'lightslategrey',
87
- 'lightsteelblue',
88
- 'lightyellow',
89
- 'lime',
90
- 'limegreen',
91
- 'linen',
92
- 'magenta',
93
- 'maroon',
94
- 'mediumaquamarine',
95
- 'mediumblue',
96
- 'mediumorchid',
97
- 'mediumpurple',
98
- 'mediumseagreen',
99
- 'mediumslateblue',
100
- 'mediumspringgreen',
101
- 'mediumturquoise',
102
- 'mediumvioletred',
103
- 'midnightblue',
104
- 'mintcream',
105
- 'mistyrose',
106
- 'moccasin',
107
- 'navajowhite',
108
- 'navy',
109
- 'oldlace',
110
- 'olive',
111
- 'olivedrab',
112
- 'orange',
113
- 'orangered',
114
- 'orchid',
115
- 'palegoldenrod',
116
- 'palegreen',
117
- 'paleturquoise',
118
- 'palevioletred',
119
- 'papayawhip',
120
- 'peachpuff',
121
- 'peru',
122
- 'pink',
123
- 'plum',
124
- 'powderblue',
125
- 'purple',
126
- 'rebeccapurple',
127
- 'red',
128
- 'rosybrown',
129
- 'royalblue',
130
- 'saddlebrown',
131
- 'salmon',
132
- 'sandybrown',
133
- 'seagreen',
134
- 'seashell',
135
- 'sienna',
136
- 'silver',
137
- 'skyblue',
138
- 'slateblue',
139
- 'slategray',
140
- 'slategrey',
141
- 'snow',
142
- 'springgreen',
143
- 'steelblue',
144
- 'tan',
145
- 'teal',
146
- 'thistle',
147
- 'tomato',
148
- 'turquoise',
149
- 'violet',
150
- 'wheat',
151
- 'white',
152
- 'whitesmoke',
153
- 'yellow',
154
- 'yellowgreen',
155
- ];
5
+ const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold', 'olive', 'yellow', 'lime', 'green', 'teal', 'cyan', 'blue', 'violet', 'magenta', 'pink'];
156
6
  export default colorNames;
@@ -0,0 +1,22 @@
1
+ /** @type {Record<string, string>} */
2
+ const colorPickerLabels = {
3
+ pickerLabel: 'Colour Picker',
4
+ appearanceLabel: 'Colour Appearance',
5
+ valueLabel: 'Colour Value',
6
+ toggleLabel: 'Select Colour',
7
+ presetsLabel: 'Colour Presets',
8
+ defaultsLabel: 'Colour Defaults',
9
+ formatLabel: 'Format',
10
+ alphaLabel: 'Alpha',
11
+ hexLabel: 'Hexadecimal',
12
+ hueLabel: 'Hue',
13
+ whitenessLabel: 'Whiteness',
14
+ blacknessLabel: 'Blackness',
15
+ saturationLabel: 'Saturation',
16
+ lightnessLabel: 'Lightness',
17
+ redLabel: 'Red',
18
+ greenLabel: 'Green',
19
+ blueLabel: 'Blue',
20
+ };
21
+
22
+ export default colorPickerLabels;
@@ -0,0 +1,103 @@
1
+ import ariaLabel from 'shorter-js/src/strings/ariaLabel';
2
+ import ariaValueMin from 'shorter-js/src/strings/ariaValueMin';
3
+ import ariaValueMax from 'shorter-js/src/strings/ariaValueMax';
4
+ import createElement from 'shorter-js/src/misc/createElement';
5
+ import setAttribute from 'shorter-js/src/attr/setAttribute';
6
+
7
+ /**
8
+ * Returns all color controls for `ColorPicker`.
9
+ *
10
+ * @param {CP.ColorPicker} self the `ColorPicker` instance
11
+ * @returns {HTMLElement | Element} color controls
12
+ */
13
+ export default function getColorControls(self) {
14
+ const { format, componentLabels } = self;
15
+ const {
16
+ hueLabel, alphaLabel, lightnessLabel, saturationLabel,
17
+ whitenessLabel, blacknessLabel,
18
+ } = componentLabels;
19
+
20
+ const max1 = format === 'hsl' ? 360 : 100;
21
+ const max2 = format === 'hsl' ? 100 : 360;
22
+ const max3 = 100;
23
+
24
+ let ctrl1Label = format === 'hsl'
25
+ ? `${hueLabel} & ${lightnessLabel}`
26
+ : `${lightnessLabel} & ${saturationLabel}`;
27
+
28
+ ctrl1Label = format === 'hwb'
29
+ ? `${whitenessLabel} & ${blacknessLabel}`
30
+ : ctrl1Label;
31
+
32
+ const ctrl2Label = format === 'hsl'
33
+ ? `${saturationLabel}`
34
+ : `${hueLabel}`;
35
+
36
+ const colorControls = createElement({
37
+ tagName: 'div',
38
+ className: `color-controls ${format}`,
39
+ });
40
+
41
+ const colorPointer = 'color-pointer';
42
+ const colorSlider = 'color-slider';
43
+
44
+ const controls = [
45
+ {
46
+ i: 1,
47
+ c: colorPointer,
48
+ l: ctrl1Label,
49
+ min: 0,
50
+ max: max1,
51
+ },
52
+ {
53
+ i: 2,
54
+ c: colorSlider,
55
+ l: ctrl2Label,
56
+ min: 0,
57
+ max: max2,
58
+ },
59
+ {
60
+ i: 3,
61
+ c: colorSlider,
62
+ l: alphaLabel,
63
+ min: 0,
64
+ max: max3,
65
+ },
66
+ ];
67
+
68
+ controls.forEach((template) => {
69
+ const {
70
+ i, c, l, min, max,
71
+ } = template;
72
+ // const hidden = i === 2 && format === 'hwb' ? ' v-hidden' : '';
73
+ const control = createElement({
74
+ tagName: 'div',
75
+ // className: `color-control${hidden}`,
76
+ className: 'color-control',
77
+ });
78
+ setAttribute(control, 'role', 'presentation');
79
+
80
+ control.append(
81
+ createElement({
82
+ tagName: 'div',
83
+ className: `visual-control visual-control${i}`,
84
+ }),
85
+ );
86
+
87
+ const knob = createElement({
88
+ tagName: 'div',
89
+ className: `${c} knob`,
90
+ ariaLive: 'polite',
91
+ });
92
+
93
+ setAttribute(knob, ariaLabel, l);
94
+ setAttribute(knob, 'role', 'slider');
95
+ setAttribute(knob, 'tabindex', '0');
96
+ setAttribute(knob, ariaValueMin, `${min}`);
97
+ setAttribute(knob, ariaValueMax, `${max}`);
98
+ control.append(knob);
99
+ colorControls.append(control);
100
+ });
101
+
102
+ return colorControls;
103
+ }
@@ -6,12 +6,13 @@ import toUpperCase from 'shorter-js/src/misc/toUpperCase';
6
6
  import vHidden from './vHidden';
7
7
 
8
8
  /**
9
- * Returns the color form.
9
+ * Returns the color form for `ColorPicker`.
10
+ *
10
11
  * @param {CP.ColorPicker} self the `ColorPicker` instance
11
- * @returns {HTMLElement | Element}
12
+ * @returns {HTMLElement | Element} a new `<div>` element with color component `<input>`
12
13
  */
13
14
  export default function getColorForm(self) {
14
- const { format, id } = self;
15
+ const { format, id, componentLabels } = self;
15
16
  const colorForm = createElement({
16
17
  tagName: 'div',
17
18
  className: `color-form ${format}`,
@@ -20,38 +21,45 @@ export default function getColorForm(self) {
20
21
  let components = ['hex'];
21
22
  if (format === 'rgb') components = ['red', 'green', 'blue', 'alpha'];
22
23
  else if (format === 'hsl') components = ['hue', 'saturation', 'lightness', 'alpha'];
24
+ else if (format === 'hwb') components = ['hue', 'whiteness', 'blackness', 'alpha'];
23
25
 
24
26
  components.forEach((c) => {
25
27
  const [C] = format === 'hex' ? ['#'] : toUpperCase(c).split('');
26
28
  const cID = `color_${format}_${c}_${id}`;
29
+ const formatLabel = componentLabels[`${c}Label`];
27
30
  const cInputLabel = createElement({ tagName: 'label' });
28
31
  setAttribute(cInputLabel, 'for', cID);
29
32
  cInputLabel.append(
30
33
  createElement({ tagName: 'span', ariaHidden: 'true', innerText: `${C}:` }),
31
- createElement({ tagName: 'span', className: vHidden, innerText: `${c}` }),
34
+ createElement({ tagName: 'span', className: vHidden, innerText: formatLabel }),
32
35
  );
33
36
  const cInput = createElement({
34
37
  tagName: 'input',
35
- id: cID, // name: cID,
38
+ id: cID,
39
+ // name: cID, - prevent saving the value to a form
36
40
  type: format === 'hex' ? 'text' : 'number',
37
- value: c === 'alpha' ? '1' : '0',
41
+ value: c === 'alpha' ? '100' : '0',
38
42
  className: `color-input ${c}`,
39
- autocomplete: 'off',
40
- spellcheck: 'false',
41
43
  });
42
- if (format !== 'hex') {
43
- // alpha
44
- let max = '1';
45
- let step = '0.01';
46
- if (c !== 'alpha') {
47
- if (format === 'rgb') { max = '255'; step = '1'; } else if (c === 'hue') { max = '360'; step = '1'; } else { max = '100'; step = '1'; }
44
+ setAttribute(cInput, 'autocomplete', 'off');
45
+ setAttribute(cInput, 'spellcheck', 'false');
46
+
47
+ // alpha
48
+ let max = '100';
49
+ let step = '1';
50
+ if (c !== 'alpha') {
51
+ if (format === 'rgb') {
52
+ max = '255'; step = '1';
53
+ } else if (c === 'hue') {
54
+ max = '360'; step = '1';
48
55
  }
49
- ObjectAssign(cInput, {
50
- min: '0',
51
- max,
52
- step,
53
- });
54
56
  }
57
+ ObjectAssign(cInput, {
58
+ min: '0',
59
+ max,
60
+ step,
61
+ });
62
+ // }
55
63
  colorForm.append(cInputLabel, cInput);
56
64
  });
57
65
  return colorForm;
@@ -0,0 +1,95 @@
1
+ import ariaLabel from 'shorter-js/src/strings/ariaLabel';
2
+ import ariaSelected from 'shorter-js/src/strings/ariaSelected';
3
+ import setAttribute from 'shorter-js/src/attr/setAttribute';
4
+ import getAttribute from 'shorter-js/src/attr/getAttribute';
5
+ import createElement from 'shorter-js/src/misc/createElement';
6
+ import setElementStyle from 'shorter-js/src/misc/setElementStyle';
7
+
8
+ import Color from '../color';
9
+ import ColorPalette from '../color-palette';
10
+
11
+ /**
12
+ * Returns a color-defaults with given values and class.
13
+ * @param {CP.ColorPicker} self
14
+ * @param {CP.ColorPalette | string[]} colorsSource
15
+ * @param {string} menuClass
16
+ * @returns {HTMLElement | Element}
17
+ */
18
+ export default function getColorMenu(self, colorsSource, menuClass) {
19
+ const { input, format, componentLabels } = self;
20
+ const { defaultsLabel, presetsLabel } = componentLabels;
21
+ const isOptionsMenu = menuClass === 'color-options';
22
+ const isPalette = colorsSource instanceof ColorPalette;
23
+ const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
24
+ let colorsArray = isPalette ? colorsSource.colors : colorsSource;
25
+ colorsArray = colorsArray instanceof Array ? colorsArray : [];
26
+ const colorsCount = colorsArray.length;
27
+ const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
28
+ let fit = lightSteps
29
+ || Math.max(...[5, 6, 7, 8, 9, 10].filter((x) => colorsCount > (x * 2) && !(colorsCount % x)));
30
+ fit = Number.isFinite(fit) ? fit : 5;
31
+ const isMultiLine = isOptionsMenu && colorsCount > fit;
32
+ let rowCountHover = 1;
33
+ rowCountHover = isMultiLine && colorsCount < 27 ? 2 : rowCountHover;
34
+ rowCountHover = colorsCount >= 27 ? 3 : rowCountHover;
35
+ rowCountHover = colorsCount >= 36 ? 4 : rowCountHover;
36
+ rowCountHover = colorsCount >= 45 ? 5 : rowCountHover;
37
+ const rowCount = rowCountHover - (colorsCount < 27 ? 1 : 2);
38
+ const isScrollable = isMultiLine && colorsCount > rowCountHover * fit;
39
+ let finalClass = menuClass;
40
+ finalClass += isScrollable ? ' scrollable' : '';
41
+ finalClass += isMultiLine ? ' multiline' : '';
42
+ const gap = isMultiLine ? '1px' : '0.25rem';
43
+ let optionSize = isMultiLine ? 1.75 : 2;
44
+ optionSize = !(colorsCount % 10) && isMultiLine ? 1.5 : optionSize;
45
+ const menuHeight = `${(rowCount || 1) * optionSize}rem`;
46
+ const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
47
+ const gridTemplateColumns = `repeat(${fit}, ${optionSize}rem)`;
48
+ const gridTemplateRows = `repeat(auto-fill, ${optionSize}rem)`;
49
+
50
+ const menu = createElement({
51
+ tagName: 'ul',
52
+ className: finalClass,
53
+ });
54
+ setAttribute(menu, 'role', 'listbox');
55
+ setAttribute(menu, ariaLabel, `${menuLabel}`);
56
+
57
+ if (isOptionsMenu) {
58
+ if (isScrollable) {
59
+ const styleText = 'this.style.height=';
60
+ setAttribute(menu, 'onmouseout', `${styleText}'${menuHeight}'`);
61
+ setAttribute(menu, 'onmouseover', `${styleText}'${menuHeightHover}'`);
62
+ }
63
+ const menuStyle = {
64
+ height: isScrollable ? menuHeight : '', gridTemplateColumns, gridTemplateRows, gap,
65
+ };
66
+ setElementStyle(menu, menuStyle);
67
+ }
68
+
69
+ colorsArray.forEach((x) => {
70
+ const [value, label] = x.trim().split(':');
71
+ const xRealColor = new Color(value, format).toString();
72
+ const isActive = xRealColor === getAttribute(input, 'value');
73
+ const active = isActive ? ' active' : '';
74
+
75
+ const option = createElement({
76
+ tagName: 'li',
77
+ className: `color-option${active}`,
78
+ innerText: `${label || x}`,
79
+ });
80
+
81
+ setAttribute(option, 'tabindex', '0');
82
+ setAttribute(option, 'data-value', `${value}`);
83
+ setAttribute(option, 'role', 'option');
84
+ setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
85
+
86
+ if (isOptionsMenu) {
87
+ setElementStyle(option, {
88
+ width: `${optionSize}rem`, height: `${optionSize}rem`, backgroundColor: x,
89
+ });
90
+ }
91
+
92
+ menu.append(option);
93
+ });
94
+ return menu;
95
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Check if a string is valid JSON string.
3
+ * @param {string} str the string input
4
+ * @returns {boolean} the query result
5
+ */
6
+ export default function isValidJSON(str) {
7
+ try {
8
+ JSON.parse(str);
9
+ } catch (e) {
10
+ return false;
11
+ }
12
+ return true;
13
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * A list of explicit default non-color values.
3
+ */
4
+ const nonColors = ['transparent', 'currentColor', 'inherit', 'revert', 'initial'];
5
+ export default nonColors;
@@ -1,3 +1,4 @@
1
+ /** A future project to allow using custom `ColorPicker` templates */
1
2
  const templates = {
2
3
  control: {
3
4
  tagName: 'div',
@@ -0,0 +1,23 @@
1
+ @import "color-picker";
2
+
3
+ [dir="rtl"] {
4
+ .color-preview { text-align: right; }
5
+
6
+ .menu-toggle {
7
+ right: auto; left: 0;
8
+ border-radius: .25rem 0 0 .25rem;
9
+ }
10
+ .color-dropdown.picker {
11
+ right: 0; left: auto;
12
+ }
13
+ .color-dropdown.menu {
14
+ right: auto; left: 0;
15
+ }
16
+ .color-control + .color-control {
17
+ margin-right: .5rem;
18
+ margin-left: 0;
19
+ }
20
+ .color-options.scrollable {
21
+ margin: 0 0 0 -.5rem;
22
+ }
23
+ }