@snack-uikit/color-picker 0.0.1-preview-364c0f5c.0

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 (53) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +201 -0
  3. package/README.md +24 -0
  4. package/dist/components/ColorPicker.d.ts +20 -0
  5. package/dist/components/ColorPicker.js +84 -0
  6. package/dist/components/index.d.ts +1 -0
  7. package/dist/components/index.js +1 -0
  8. package/dist/components/styles.module.css +61 -0
  9. package/dist/constants.d.ts +20 -0
  10. package/dist/constants.js +32 -0
  11. package/dist/helperComponents/FieldAlphaColor/FieldAlphaColor.d.ts +16 -0
  12. package/dist/helperComponents/FieldAlphaColor/FieldAlphaColor.js +8 -0
  13. package/dist/helperComponents/FieldAlphaColor/index.d.ts +1 -0
  14. package/dist/helperComponents/FieldAlphaColor/index.js +1 -0
  15. package/dist/helperComponents/FieldPrivate/FieldPrivate.d.ts +14 -0
  16. package/dist/helperComponents/FieldPrivate/FieldPrivate.js +30 -0
  17. package/dist/helperComponents/FieldPrivate/index.d.ts +1 -0
  18. package/dist/helperComponents/FieldPrivate/index.js +1 -0
  19. package/dist/helperComponents/FieldPrivate/styles.module.css +186 -0
  20. package/dist/helperComponents/index.d.ts +2 -0
  21. package/dist/helperComponents/index.js +2 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +2 -0
  24. package/dist/types.d.ts +12 -0
  25. package/dist/types.js +1 -0
  26. package/dist/utils/convert.d.ts +12 -0
  27. package/dist/utils/convert.js +172 -0
  28. package/dist/utils/index.d.ts +1 -0
  29. package/dist/utils/index.js +1 -0
  30. package/dist/utils/round.d.ts +1 -0
  31. package/dist/utils/round.js +1 -0
  32. package/dist/utils/typeGuards.d.ts +10 -0
  33. package/dist/utils/typeGuards.js +34 -0
  34. package/dist/utils/validate.d.ts +1 -0
  35. package/dist/utils/validate.js +10 -0
  36. package/package.json +49 -0
  37. package/src/components/ColorPicker.tsx +209 -0
  38. package/src/components/index.ts +1 -0
  39. package/src/components/styles.module.scss +82 -0
  40. package/src/constants.ts +45 -0
  41. package/src/helperComponents/FieldAlphaColor/FieldAlphaColor.tsx +26 -0
  42. package/src/helperComponents/FieldAlphaColor/index.ts +1 -0
  43. package/src/helperComponents/FieldPrivate/FieldPrivate.tsx +85 -0
  44. package/src/helperComponents/FieldPrivate/index.ts +1 -0
  45. package/src/helperComponents/FieldPrivate/styles.module.scss +136 -0
  46. package/src/helperComponents/index.ts +2 -0
  47. package/src/index.ts +2 -0
  48. package/src/types.ts +15 -0
  49. package/src/utils/convert.ts +229 -0
  50. package/src/utils/index.ts +1 -0
  51. package/src/utils/round.ts +2 -0
  52. package/src/utils/typeGuards.ts +47 -0
  53. package/src/utils/validate.ts +13 -0
@@ -0,0 +1,229 @@
1
+ /* eslint-disable no-param-reassign */
2
+ /* eslint-disable no-use-before-define */
3
+ /* eslint-disable @typescript-eslint/no-use-before-define */
4
+ import { HslaColor, HslColor, HsvaColor, HsvColor, RgbaColor, RgbColor } from 'react-colorful';
5
+
6
+ import { HSVA_REGEX, RGBA_REGEX } from '../constants';
7
+ import { Color, RawColor } from '../types';
8
+ import { round } from './round';
9
+ import {
10
+ isHslaColor,
11
+ isHslaString,
12
+ isHslColor,
13
+ isHsvaColor,
14
+ isHsvaString,
15
+ isHsvColor,
16
+ isRbgaString,
17
+ isRbgColor,
18
+ isRgbaColor,
19
+ } from './typeGuards';
20
+
21
+ /**
22
+ * Valid CSS <angle> units.
23
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/angle
24
+ */
25
+ const angleUnits: Record<string, number> = {
26
+ grad: 360 / 400,
27
+ turn: 360,
28
+ rad: 360 / (Math.PI * 2),
29
+ };
30
+
31
+ const hexToHsva = (hex: string): HsvaColor => rgbaToHsva(hexToRgba(hex));
32
+ export const hexToRgba = (hex: string): RgbaColor => {
33
+ if (hex[0] === '#') hex = hex.substring(1);
34
+
35
+ if (hex.length < 6) {
36
+ return {
37
+ r: parseInt(hex[0] + hex[0], 16),
38
+ g: parseInt(hex[1] + hex[1], 16),
39
+ b: parseInt(hex[2] + hex[2], 16),
40
+ a: hex.length === 4 ? round(parseInt(hex[3] + hex[3], 16) / 255, 2) : 1,
41
+ };
42
+ }
43
+
44
+ return {
45
+ r: parseInt(hex.substring(0, 2), 16),
46
+ g: parseInt(hex.substring(2, 4), 16),
47
+ b: parseInt(hex.substring(4, 6), 16),
48
+ a: hex.length === 8 ? round(parseInt(hex.substring(6, 8), 16) / 255, 2) : 1,
49
+ };
50
+ };
51
+
52
+ const parseHue = (value: string, unit = 'deg'): number => Number(value) * (angleUnits[unit] || 1);
53
+
54
+ const hslaStringToHsva = (hslString: string): HsvaColor => {
55
+ const matcher =
56
+ /hsla?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i;
57
+ const match = matcher.exec(hslString);
58
+
59
+ if (!match) return { h: 0, s: 0, v: 0, a: 1 };
60
+
61
+ return hslaToHsva({
62
+ h: parseHue(match[1], match[2]),
63
+ s: Number(match[3]),
64
+ l: Number(match[4]),
65
+ a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? 100 : 1),
66
+ });
67
+ };
68
+
69
+ const hslaToHsva = ({ h, s, l, a }: HslaColor): HsvaColor => {
70
+ s *= (l < 50 ? l : 100 - l) / 100;
71
+
72
+ return {
73
+ h: h,
74
+ s: s > 0 ? ((2 * s) / (l + s)) * 100 : 0,
75
+ v: l + s,
76
+ a,
77
+ };
78
+ };
79
+
80
+ const hsvaToHex = (hsva: HsvaColor): string => rgbaToHex(hsvaToRgba(hsva));
81
+
82
+ export const hsvaToHsla = ({ h, s, v, a }: HsvaColor): HslaColor => {
83
+ const hh = ((200 - s) * v) / 100;
84
+
85
+ return {
86
+ h: round(h),
87
+ s: round(hh > 0 && hh < 200 ? ((s * v) / 100 / (hh <= 100 ? hh : 200 - hh)) * 100 : 0),
88
+ l: round(hh / 2),
89
+ a: round(a, 2),
90
+ };
91
+ };
92
+
93
+ const hsvaToRgba = ({ h, s, v, a }: HsvaColor): RgbaColor => {
94
+ h = (h / 360) * 6;
95
+ s = s / 100;
96
+ v = v / 100;
97
+
98
+ const hh = Math.floor(h),
99
+ b = v * (1 - s),
100
+ c = v * (1 - (h - hh) * s),
101
+ d = v * (1 - (1 - h + hh) * s),
102
+ module = hh % 6;
103
+
104
+ return {
105
+ r: round([v, c, b, b, d, v][module] * 255),
106
+ g: round([d, v, v, c, b, b][module] * 255),
107
+ b: round([b, b, d, v, v, c][module] * 255),
108
+ a: round(a, 2),
109
+ };
110
+ };
111
+
112
+ const hsvaStringToHsva = (hsvString: string): HsvaColor => {
113
+ const matcher = HSVA_REGEX;
114
+ const match = matcher.exec(hsvString);
115
+
116
+ if (!match) return { h: 0, s: 0, v: 0, a: 1 };
117
+
118
+ return roundHsva({
119
+ h: parseHue(match[1], match[2]),
120
+ s: Number(match[3]),
121
+ v: Number(match[4]),
122
+ a: match[5] === undefined ? 1 : Number(match[5]) / (match[6] ? 100 : 1),
123
+ });
124
+ };
125
+
126
+ const rgbaStringToHsva = (rgbaString: string): HsvaColor => {
127
+ const matcher = RGBA_REGEX;
128
+ const match = matcher.exec(rgbaString);
129
+
130
+ if (!match) return { h: 0, s: 0, v: 0, a: 1 };
131
+
132
+ return rgbaToHsva({
133
+ r: Number(match[1]) / (match[2] ? 100 / 255 : 1),
134
+ g: Number(match[3]) / (match[4] ? 100 / 255 : 1),
135
+ b: Number(match[5]) / (match[6] ? 100 / 255 : 1),
136
+ a: match[7] === undefined ? 1 : Number(match[7]) / (match[8] ? 100 : 1),
137
+ });
138
+ };
139
+
140
+ const format = (number: number) => {
141
+ const hex = number.toString(16);
142
+ return hex.length < 2 ? '0' + hex : hex;
143
+ };
144
+
145
+ export const rgbaToHex = ({ r, g, b, a }: RgbaColor): string => {
146
+ const alphaHex = a < 1 ? format(round(a * 255)) : '';
147
+ return '#' + format(r) + format(g) + format(b) + alphaHex;
148
+ };
149
+
150
+ export const rgbaToHsva = ({ r, g, b, a }: RgbaColor): HsvaColor => {
151
+ const max = Math.max(r, g, b);
152
+ const delta = max - Math.min(r, g, b);
153
+
154
+ // prettier-ignore
155
+ // eslint-disable-next-line no-nested-ternary
156
+ const hh = delta
157
+ // eslint-disable-next-line no-nested-ternary
158
+ ? max === r
159
+ ? (g - b) / delta
160
+ : max === g
161
+ ? 2 + (b - r) / delta
162
+ : 4 + (r - g) / delta
163
+ : 0;
164
+
165
+ return {
166
+ h: round(60 * (hh < 0 ? hh + 6 : hh)),
167
+ s: round(max ? (delta / max) * 100 : 0),
168
+ v: round((max / 255) * 100),
169
+ a,
170
+ };
171
+ };
172
+
173
+ export const roundHsva = (hsva: HsvaColor): HsvaColor => ({
174
+ h: round(hsva.h),
175
+ s: round(hsva.s),
176
+ v: round(hsva.v),
177
+ a: round(hsva.a, 2),
178
+ });
179
+
180
+ export const rgbaToRgb = ({ r, g, b }: RgbaColor): RgbColor => ({ r, g, b });
181
+
182
+ export const hslaToHsl = ({ h, s, l }: HslaColor): HslColor => ({ h, s, l });
183
+
184
+ export const hsvaToHsv = (hsva: HsvaColor): HsvColor => {
185
+ const { h, s, v } = roundHsva(hsva);
186
+ return { h, s, v };
187
+ };
188
+
189
+ export function colorToHex(value: Color): string {
190
+ if (isHslColor(value) || isHslaColor(value)) {
191
+ return hsvaToHex(hslaToHsva({ a: 1, ...value }));
192
+ }
193
+
194
+ if (isRbgColor(value) || isRgbaColor(value)) {
195
+ return rgbaToHex({ a: 1, ...value });
196
+ }
197
+
198
+ if (isHsvColor(value) || isHsvaColor(value)) {
199
+ return hsvaToHex({ a: 1, ...value });
200
+ }
201
+
202
+ if (isHslaString(value)) {
203
+ return hsvaToHex(hslaStringToHsva(value));
204
+ }
205
+
206
+ if (isRbgaString(value)) {
207
+ return hsvaToHex(rgbaStringToHsva(value));
208
+ }
209
+
210
+ if (isHsvaString(value)) {
211
+ return hsvaToHex(hsvaStringToHsva(value));
212
+ }
213
+
214
+ return value;
215
+ }
216
+
217
+ export function colorToRawValue(value: Color): RawColor {
218
+ const hexColor = colorToHex(value);
219
+
220
+ return {
221
+ hex: hexColor,
222
+ rgb: rgbaToRgb(hexToRgba(hexColor)),
223
+ rgba: hexToRgba(hexColor),
224
+ hsv: hsvaToHsv(hexToHsva(hexColor)),
225
+ hsva: hexToHsva(hexColor),
226
+ hsl: hslaToHsl(hsvaToHsla(hexToHsva(hexColor))),
227
+ hsla: hsvaToHsla(hexToHsva(hexColor)),
228
+ };
229
+ }
@@ -0,0 +1 @@
1
+ export * from './convert';
@@ -0,0 +1,2 @@
1
+ export const round = (number: number, digits = 0, base = Math.pow(10, digits)): number =>
2
+ Math.round(base * number) / base;
@@ -0,0 +1,47 @@
1
+ import { HSLA_REGEX, HSVA_REGEX, RGBA_REGEX } from '../constants';
2
+ import { Color, HslaColor, HslColor, HsvaColor, HsvColor, RgbaColor, RgbColor } from '../types';
3
+
4
+ export function isRbgColor(value: Color): value is RgbColor {
5
+ return typeof value === 'object' && 'r' in value && 'g' in value && 'b' in value;
6
+ }
7
+
8
+ export function isRgbaColor(value: Color): value is RgbaColor {
9
+ return typeof value === 'object' && isRbgColor(value) && 'a' in value;
10
+ }
11
+
12
+ export function isHslColor(value: Color): value is HslColor {
13
+ return typeof value === 'object' && 'h' in value && 's' in value && 'l' in value;
14
+ }
15
+
16
+ export function isHslaColor(value: Color): value is HslaColor {
17
+ return typeof value === 'object' && isHslColor(value) && 'a' in value;
18
+ }
19
+
20
+ export function isHsvColor(value: Color): value is HsvColor {
21
+ return typeof value === 'object' && 'h' in value && 's' in value && 'v' in value;
22
+ }
23
+
24
+ export function isHsvaColor(value: Color): value is HsvaColor {
25
+ return typeof value === 'object' && isHsvColor(value) && 'a' in value;
26
+ }
27
+
28
+ export function isHslaString(value: string) {
29
+ const matcher = HSLA_REGEX;
30
+ const match = matcher.exec(value);
31
+
32
+ return Boolean(match);
33
+ }
34
+
35
+ export function isHsvaString(value: string) {
36
+ const matcher = HSVA_REGEX;
37
+ const match = matcher.exec(value);
38
+
39
+ return Boolean(match);
40
+ }
41
+
42
+ export function isRbgaString(value: string) {
43
+ const matcher = RGBA_REGEX;
44
+ const match = matcher.exec(value);
45
+
46
+ return Boolean(match);
47
+ }
@@ -0,0 +1,13 @@
1
+ const matcher = /^#?([0-9A-F]{3,8})$/i;
2
+
3
+ export const validHex = (value: string, alpha?: boolean): boolean => {
4
+ const match = matcher.exec(value);
5
+ const length = match ? match[1].length : 0;
6
+
7
+ return (
8
+ length === 3 || // '#rgb' format
9
+ length === 6 || // '#rrggbb' format
10
+ (Boolean(alpha) && length === 4) || // '#rgba' format
11
+ (Boolean(alpha) && length === 8) // '#rrggbbaa' format
12
+ );
13
+ };