@thednp/color-picker 0.0.1-alpha1 → 0.0.1

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 (41) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +63 -26
  3. package/dist/css/color-picker.css +504 -337
  4. package/dist/css/color-picker.min.css +2 -0
  5. package/dist/css/color-picker.rtl.css +529 -0
  6. package/dist/css/color-picker.rtl.min.css +2 -0
  7. package/dist/js/color-picker-element-esm.js +3851 -2
  8. package/dist/js/color-picker-element-esm.min.js +2 -0
  9. package/dist/js/color-picker-element.js +2086 -1278
  10. package/dist/js/color-picker-element.min.js +2 -2
  11. package/dist/js/color-picker-esm.js +3742 -0
  12. package/dist/js/color-picker-esm.min.js +2 -0
  13. package/dist/js/color-picker.js +2030 -1286
  14. package/dist/js/color-picker.min.js +2 -2
  15. package/package.json +18 -9
  16. package/src/js/color-palette.js +71 -0
  17. package/src/js/color-picker-element.js +62 -16
  18. package/src/js/color-picker.js +734 -618
  19. package/src/js/color.js +621 -358
  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 +26 -19
  25. package/src/js/util/getColorMenu.js +88 -0
  26. package/src/js/util/isValidJSON.js +13 -0
  27. package/src/js/util/nonColors.js +5 -0
  28. package/src/js/util/roundPart.js +9 -0
  29. package/src/js/util/setCSSProperties.js +12 -0
  30. package/src/js/util/tabindex.js +3 -0
  31. package/src/js/util/templates.js +1 -0
  32. package/src/scss/color-picker.rtl.scss +23 -0
  33. package/src/scss/color-picker.scss +449 -0
  34. package/types/cp.d.ts +263 -162
  35. package/types/index.d.ts +9 -2
  36. package/types/source/source.ts +2 -1
  37. package/types/source/types.d.ts +28 -5
  38. package/dist/js/color-picker.esm.js +0 -2998
  39. package/dist/js/color-picker.esm.min.js +0 -2
  40. package/src/js/util/getColorControl.js +0 -49
  41. 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
+ import tabIndex from './tabindex';
8
+
9
+ /**
10
+ * Returns all color controls for `ColorPicker`.
11
+ *
12
+ * @param {CP.ColorPicker} self the `ColorPicker` instance
13
+ * @returns {HTMLElement | Element} color controls
14
+ */
15
+ export default function getColorControls(self) {
16
+ const { format, componentLabels } = self;
17
+ const {
18
+ hueLabel, alphaLabel, lightnessLabel, saturationLabel,
19
+ whitenessLabel, blacknessLabel,
20
+ } = componentLabels;
21
+
22
+ const max1 = format === 'hsl' ? 360 : 100;
23
+ const max2 = format === 'hsl' ? 100 : 360;
24
+ const max3 = 100;
25
+
26
+ let ctrl1Label = format === 'hsl'
27
+ ? `${hueLabel} & ${lightnessLabel}`
28
+ : `${lightnessLabel} & ${saturationLabel}`;
29
+
30
+ ctrl1Label = format === 'hwb'
31
+ ? `${whitenessLabel} & ${blacknessLabel}`
32
+ : ctrl1Label;
33
+
34
+ const ctrl2Label = format === 'hsl'
35
+ ? `${saturationLabel}`
36
+ : `${hueLabel}`;
37
+
38
+ const colorControls = createElement({
39
+ tagName: 'div',
40
+ className: `color-controls ${format}`,
41
+ });
42
+
43
+ const colorPointer = 'color-pointer';
44
+ const colorSlider = 'color-slider';
45
+
46
+ const controls = [
47
+ {
48
+ i: 1,
49
+ c: colorPointer,
50
+ l: ctrl1Label,
51
+ min: 0,
52
+ max: max1,
53
+ },
54
+ {
55
+ i: 2,
56
+ c: colorSlider,
57
+ l: ctrl2Label,
58
+ min: 0,
59
+ max: max2,
60
+ },
61
+ {
62
+ i: 3,
63
+ c: colorSlider,
64
+ l: alphaLabel,
65
+ min: 0,
66
+ max: max3,
67
+ },
68
+ ];
69
+
70
+ controls.forEach((template) => {
71
+ const {
72
+ i, c, l, min, max,
73
+ } = template;
74
+ const control = createElement({
75
+ tagName: 'div',
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,44 @@ 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
+ });
55
62
  colorForm.append(cInputLabel, cInput);
56
63
  });
57
64
  return colorForm;
@@ -0,0 +1,88 @@
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 setCSSProperties from './setCSSProperties';
9
+ import tabIndex from './tabindex';
10
+ import Color from '../color';
11
+ import ColorPalette from '../color-palette';
12
+
13
+ /**
14
+ * Returns a color-defaults with given values and class.
15
+ * @param {CP.ColorPicker} self
16
+ * @param {CP.ColorPalette | string[]} colorsSource
17
+ * @param {string} menuClass
18
+ * @returns {HTMLElement | Element}
19
+ */
20
+ export default function getColorMenu(self, colorsSource, menuClass) {
21
+ const { input, format, componentLabels } = self;
22
+ const { defaultsLabel, presetsLabel } = componentLabels;
23
+ const isOptionsMenu = menuClass === 'color-options';
24
+ const isPalette = colorsSource instanceof ColorPalette;
25
+ const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
26
+ let colorsArray = isPalette ? colorsSource.colors : colorsSource;
27
+ colorsArray = colorsArray instanceof Array ? colorsArray : [];
28
+ const colorsCount = colorsArray.length;
29
+ const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
30
+ const fit = lightSteps || [9, 10].find((x) => colorsCount > x * 2 && !(colorsCount % x)) || 5;
31
+ const isMultiLine = isOptionsMenu && colorsCount > fit;
32
+ 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);
37
+ const isScrollable = isMultiLine && colorsCount > rowCount * fit;
38
+ let finalClass = menuClass;
39
+ finalClass += isScrollable ? ' scrollable' : '';
40
+ finalClass += isMultiLine ? ' multiline' : '';
41
+ const gap = isMultiLine ? '1px' : '0.25rem';
42
+ let optionSize = isMultiLine ? 1.75 : 2;
43
+ optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
44
+ const menuHeight = `${(rowCount || 1) * optionSize}rem`;
45
+ const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
46
+
47
+ const menu = createElement({
48
+ tagName: 'ul',
49
+ className: finalClass,
50
+ });
51
+ setAttribute(menu, 'role', 'listbox');
52
+ setAttribute(menu, ariaLabel, menuLabel);
53
+
54
+ if (isScrollable) { // @ts-ignore
55
+ setCSSProperties(menu, {
56
+ '--grid-item-size': `${optionSize}rem`,
57
+ '--grid-fit': fit,
58
+ '--grid-gap': gap,
59
+ '--grid-height': menuHeight,
60
+ '--grid-hover-height': menuHeightHover,
61
+ });
62
+ }
63
+
64
+ colorsArray.forEach((x) => {
65
+ const [value, label] = x.trim().split(':');
66
+ const xRealColor = new Color(value, format).toString();
67
+ const isActive = xRealColor === getAttribute(input, 'value');
68
+ const active = isActive ? ' active' : '';
69
+
70
+ const option = createElement({
71
+ tagName: 'li',
72
+ className: `color-option${active}`,
73
+ innerText: `${label || x}`,
74
+ });
75
+
76
+ setAttribute(option, tabIndex, '0');
77
+ setAttribute(option, 'data-value', `${value}`);
78
+ setAttribute(option, 'role', 'option');
79
+ setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
80
+
81
+ if (isOptionsMenu) {
82
+ setElementStyle(option, { backgroundColor: x });
83
+ }
84
+
85
+ menu.append(option);
86
+ });
87
+ return menu;
88
+ }
@@ -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;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Round colour components, for all formats except HEX.
3
+ * @param {number} v one of the colour components
4
+ * @returns {number} the rounded number
5
+ */
6
+ export default function roundPart(v) {
7
+ const floor = Math.floor(v);
8
+ return v - floor < 0.5 ? floor : Math.round(v);
9
+ }
@@ -0,0 +1,12 @@
1
+ import ObjectKeys from 'shorter-js/src/misc/ObjectKeys';
2
+
3
+ /**
4
+ * Helps setting CSS variables to the color-menu.
5
+ * @param {HTMLElement} element
6
+ * @param {Record<string,any>} props
7
+ */
8
+ export default function setCSSProperties(element, props) {
9
+ ObjectKeys(props).forEach((prop) => {
10
+ element.style.setProperty(prop, props[prop]);
11
+ });
12
+ }
@@ -0,0 +1,3 @@
1
+ const tabIndex = 'tabindex';
2
+
3
+ export default tabIndex;
@@ -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
+ }