gdp-color-picker 1.0.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/README.md +85 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.mjs +2 -0
- package/dist/index.modern.mjs.map +1 -0
- package/dist/index.module.js +2 -0
- package/dist/index.module.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +52 -0
- package/src/lib/ColorBoard.js +70 -0
- package/src/lib/ColorInput.js +140 -0
- package/src/lib/Sliders.js +86 -0
- package/src/lib/index.css +198 -0
- package/src/lib/index.js +113 -0
- package/src/lib/utils/color.js +216 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Clamps a value between min and max
|
|
4
|
+
* @param {number} value
|
|
5
|
+
* @param {number} min
|
|
6
|
+
* @param {number} max
|
|
7
|
+
*/
|
|
8
|
+
export function clamp(value, min, max) {
|
|
9
|
+
return Math.min(Math.max(value, min), max);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Converts HSV to RGB
|
|
14
|
+
* @param {number} h Hue 0-360
|
|
15
|
+
* @param {number} s Saturation 0-1
|
|
16
|
+
* @param {number} v Value 0-1
|
|
17
|
+
* @returns {{r: number, g: number, b: number}}
|
|
18
|
+
*/
|
|
19
|
+
export function hsvToRgb(h, s, v) {
|
|
20
|
+
h = ((h % 360) + 360) % 360; // Normalize hue
|
|
21
|
+
let r, g, b;
|
|
22
|
+
let i = Math.floor(h / 60);
|
|
23
|
+
let f = h / 60 - i;
|
|
24
|
+
let p = v * (1 - s);
|
|
25
|
+
let q = v * (1 - f * s);
|
|
26
|
+
let t = v * (1 - (1 - f) * s);
|
|
27
|
+
|
|
28
|
+
switch (i % 6) {
|
|
29
|
+
case 0: r = v; g = t; b = p; break;
|
|
30
|
+
case 1: r = q; g = v; b = p; break;
|
|
31
|
+
case 2: r = p; g = v; b = t; break;
|
|
32
|
+
case 3: r = p; g = q; b = v; break;
|
|
33
|
+
case 4: r = t; g = p; b = v; break;
|
|
34
|
+
case 5: r = v; g = p; b = q; break;
|
|
35
|
+
default: r = 0; g = 0; b = 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
r: Math.round(r * 255),
|
|
40
|
+
g: Math.round(g * 255),
|
|
41
|
+
b: Math.round(b * 255)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Converts RGB to HSV
|
|
47
|
+
* @param {number} r Red 0-255
|
|
48
|
+
* @param {number} g Green 0-255
|
|
49
|
+
* @param {number} b Blue 0-255
|
|
50
|
+
* @returns {{h: number, s: number, v: number}}
|
|
51
|
+
*/
|
|
52
|
+
export function rgbToHsv(r, g, b) {
|
|
53
|
+
r /= 255;
|
|
54
|
+
g /= 255;
|
|
55
|
+
b /= 255;
|
|
56
|
+
|
|
57
|
+
let max = Math.max(r, g, b);
|
|
58
|
+
let min = Math.min(r, g, b);
|
|
59
|
+
let h, s, v = max;
|
|
60
|
+
|
|
61
|
+
let d = max - min;
|
|
62
|
+
s = max === 0 ? 0 : d / max;
|
|
63
|
+
|
|
64
|
+
if (max === min) {
|
|
65
|
+
h = 0; // achromatic
|
|
66
|
+
} else {
|
|
67
|
+
switch (max) {
|
|
68
|
+
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
69
|
+
case g: h = (b - r) / d + 2; break;
|
|
70
|
+
case b: h = (r - g) / d + 4; break;
|
|
71
|
+
default: h = 0;
|
|
72
|
+
}
|
|
73
|
+
h /= 6;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
h: h * 360,
|
|
78
|
+
s: s,
|
|
79
|
+
v: v
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Converts RGB to Hex string
|
|
85
|
+
* @param {number} r
|
|
86
|
+
* @param {number} g
|
|
87
|
+
* @param {number} b
|
|
88
|
+
* @returns {string} Hex string (e.g., "#ff0000")
|
|
89
|
+
*/
|
|
90
|
+
export function rgbToHex(r, g, b) {
|
|
91
|
+
const toHex = (c) => {
|
|
92
|
+
const hex = Math.round(c).toString(16);
|
|
93
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
94
|
+
};
|
|
95
|
+
return "#" + toHex(r) + toHex(g) + toHex(b);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Converts Hex string to RGB
|
|
100
|
+
* @param {string} hex
|
|
101
|
+
* @returns {{r: number, g: number, b: number} | null}
|
|
102
|
+
*/
|
|
103
|
+
export function hexToRgb(hex) {
|
|
104
|
+
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
|
105
|
+
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
106
|
+
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
|
107
|
+
return r + r + g + g + b + b;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
111
|
+
return result ? {
|
|
112
|
+
r: parseInt(result[1], 16),
|
|
113
|
+
g: parseInt(result[2], 16),
|
|
114
|
+
b: parseInt(result[3], 16)
|
|
115
|
+
} : null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Parses a color string to HSV
|
|
120
|
+
* @param {string} color
|
|
121
|
+
* @returns {{h: number, s: number, v: number, a: number}}
|
|
122
|
+
*/
|
|
123
|
+
export function parseColor(color) {
|
|
124
|
+
if (!color) return { h: 0, s: 1, v: 1, a: 1 };
|
|
125
|
+
|
|
126
|
+
// Hex
|
|
127
|
+
if (color.startsWith('#')) {
|
|
128
|
+
const rgb = hexToRgb(color);
|
|
129
|
+
if (rgb) {
|
|
130
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
131
|
+
return { ...hsv, a: 1 };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// RGB/RGBA
|
|
136
|
+
const rgbaMatch = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);
|
|
137
|
+
if (rgbaMatch) {
|
|
138
|
+
const r = parseInt(rgbaMatch[1], 10);
|
|
139
|
+
const g = parseInt(rgbaMatch[2], 10);
|
|
140
|
+
const b = parseInt(rgbaMatch[3], 10);
|
|
141
|
+
const a = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : 1;
|
|
142
|
+
const hsv = rgbToHsv(r, g, b);
|
|
143
|
+
return { ...hsv, a };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Default fallback
|
|
147
|
+
return { h: 0, s: 1, v: 1, a: 1 };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Converts RGB to HSL
|
|
152
|
+
* @param {number} r Red 0-255
|
|
153
|
+
* @param {number} g Green 0-255
|
|
154
|
+
* @param {number} b Blue 0-255
|
|
155
|
+
* @returns {{h: number, s: number, l: number}}
|
|
156
|
+
*/
|
|
157
|
+
export function rgbToHsl(r, g, b) {
|
|
158
|
+
r /= 255;
|
|
159
|
+
g /= 255;
|
|
160
|
+
b /= 255;
|
|
161
|
+
|
|
162
|
+
let max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
163
|
+
let h, s, l = (max + min) / 2;
|
|
164
|
+
|
|
165
|
+
if (max === min) {
|
|
166
|
+
h = s = 0; // achromatic
|
|
167
|
+
} else {
|
|
168
|
+
let d = max - min;
|
|
169
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
170
|
+
switch (max) {
|
|
171
|
+
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
172
|
+
case g: h = (b - r) / d + 2; break;
|
|
173
|
+
case b: h = (r - g) / d + 4; break;
|
|
174
|
+
}
|
|
175
|
+
h /= 6;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return { h: h * 360, s: s, l: l };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Converts HSL to RGB
|
|
183
|
+
* @param {number} h Hue 0-360
|
|
184
|
+
* @param {number} s Saturation 0-1
|
|
185
|
+
* @param {number} l Lightness 0-1
|
|
186
|
+
* @returns {{r: number, g: number, b: number}}
|
|
187
|
+
*/
|
|
188
|
+
export function hslToRgb(h, s, l) {
|
|
189
|
+
let r, g, b;
|
|
190
|
+
|
|
191
|
+
if (s === 0) {
|
|
192
|
+
r = g = b = l; // achromatic
|
|
193
|
+
} else {
|
|
194
|
+
const hue2rgb = (p, q, t) => {
|
|
195
|
+
if (t < 0) t += 1;
|
|
196
|
+
if (t > 1) t -= 1;
|
|
197
|
+
if (t < 1/6) return p + (q - p) * 6 * t;
|
|
198
|
+
if (t < 1/2) return q;
|
|
199
|
+
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
200
|
+
return p;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
204
|
+
const p = 2 * l - q;
|
|
205
|
+
h /= 360;
|
|
206
|
+
r = hue2rgb(p, q, h + 1/3);
|
|
207
|
+
g = hue2rgb(p, q, h);
|
|
208
|
+
b = hue2rgb(p, q, h - 1/3);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
r: Math.round(r * 255),
|
|
213
|
+
g: Math.round(g * 255),
|
|
214
|
+
b: Math.round(b * 255)
|
|
215
|
+
};
|
|
216
|
+
}
|