@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.
- package/CHANGELOG.md +5 -0
- package/LICENSE +201 -0
- package/README.md +24 -0
- package/dist/components/ColorPicker.d.ts +20 -0
- package/dist/components/ColorPicker.js +84 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/styles.module.css +61 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.js +32 -0
- package/dist/helperComponents/FieldAlphaColor/FieldAlphaColor.d.ts +16 -0
- package/dist/helperComponents/FieldAlphaColor/FieldAlphaColor.js +8 -0
- package/dist/helperComponents/FieldAlphaColor/index.d.ts +1 -0
- package/dist/helperComponents/FieldAlphaColor/index.js +1 -0
- package/dist/helperComponents/FieldPrivate/FieldPrivate.d.ts +14 -0
- package/dist/helperComponents/FieldPrivate/FieldPrivate.js +30 -0
- package/dist/helperComponents/FieldPrivate/index.d.ts +1 -0
- package/dist/helperComponents/FieldPrivate/index.js +1 -0
- package/dist/helperComponents/FieldPrivate/styles.module.css +186 -0
- package/dist/helperComponents/index.d.ts +2 -0
- package/dist/helperComponents/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.js +1 -0
- package/dist/utils/convert.d.ts +12 -0
- package/dist/utils/convert.js +172 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/round.d.ts +1 -0
- package/dist/utils/round.js +1 -0
- package/dist/utils/typeGuards.d.ts +10 -0
- package/dist/utils/typeGuards.js +34 -0
- package/dist/utils/validate.d.ts +1 -0
- package/dist/utils/validate.js +10 -0
- package/package.json +49 -0
- package/src/components/ColorPicker.tsx +209 -0
- package/src/components/index.ts +1 -0
- package/src/components/styles.module.scss +82 -0
- package/src/constants.ts +45 -0
- package/src/helperComponents/FieldAlphaColor/FieldAlphaColor.tsx +26 -0
- package/src/helperComponents/FieldAlphaColor/index.ts +1 -0
- package/src/helperComponents/FieldPrivate/FieldPrivate.tsx +85 -0
- package/src/helperComponents/FieldPrivate/index.ts +1 -0
- package/src/helperComponents/FieldPrivate/styles.module.scss +136 -0
- package/src/helperComponents/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/types.ts +15 -0
- package/src/utils/convert.ts +229 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/round.ts +2 -0
- package/src/utils/typeGuards.ts +47 -0
- 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,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
|
+
};
|