reanimated-color-picker 0.0.13 → 0.0.16
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/lib/ColorPicker.js +277 -56
- package/lib/ColorsConversionFormulas.js +12 -22
- package/lib/assets/{Background.png → Background1.png} +0 -0
- package/lib/assets/Background2.png +0 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +13 -4
- package/package.json +2 -2
- package/readme.md +22 -6
package/lib/ColorPicker.js
CHANGED
|
@@ -11,12 +11,6 @@ import Animated, {
|
|
|
11
11
|
} from 'react-native-reanimated';
|
|
12
12
|
import { ALPHA_HEX, COLOR_HSVA, CONTRAST_RATIO, HSL_HEX, HSL_RGB, HSV_HSL } from './ColorsConversionFormulas';
|
|
13
13
|
|
|
14
|
-
const PANEL_IMAGE = require('./assets/Background.png'),
|
|
15
|
-
OPACITY_IMAGE = require('./assets/Opacity.png'),
|
|
16
|
-
HUE_IMAGE = require('./assets/Hue.png'),
|
|
17
|
-
SATURATION_IMAGE = require('./assets/Saturation.png'),
|
|
18
|
-
BRIGHTNESS_IMAGE = require('./assets/Brightness.png');
|
|
19
|
-
|
|
20
14
|
const isRtl = I18nManager.isRTL,
|
|
21
15
|
HUE_MAX = 360,
|
|
22
16
|
SB_MAX = 100,
|
|
@@ -62,7 +56,17 @@ const ReText = props => {
|
|
|
62
56
|
underlineColorAndroid='transparent'
|
|
63
57
|
editable={false}
|
|
64
58
|
value={text.value}
|
|
65
|
-
style={[
|
|
59
|
+
style={[
|
|
60
|
+
{
|
|
61
|
+
fontWeight: 'bold',
|
|
62
|
+
padding: 0,
|
|
63
|
+
height: '100%',
|
|
64
|
+
width: '100%',
|
|
65
|
+
textAlign: 'center',
|
|
66
|
+
},
|
|
67
|
+
customStyle,
|
|
68
|
+
style,
|
|
69
|
+
]}
|
|
66
70
|
{...{ animatedProps }}
|
|
67
71
|
/>
|
|
68
72
|
);
|
|
@@ -82,7 +86,8 @@ export default function ColorPicker({
|
|
|
82
86
|
const initialColor = useRef(COLOR_HSVA(value));
|
|
83
87
|
const previewColorFormat = useRef('hex');
|
|
84
88
|
|
|
85
|
-
const
|
|
89
|
+
const panel1ThumbeSize = useRef(thumbsSize);
|
|
90
|
+
const panel2ThumbeSize = useRef(thumbsSize);
|
|
86
91
|
const hueThumbeSize = useRef(thumbsSize);
|
|
87
92
|
const brightnessThumbeSize = useRef(thumbsSize);
|
|
88
93
|
const saturationThumbeSize = useRef(thumbsSize);
|
|
@@ -97,11 +102,25 @@ export default function ColorPicker({
|
|
|
97
102
|
const { h, s, l } = HSV_HSL(color.h, color.s, color.b);
|
|
98
103
|
return `hsl(${h}, ${s}%, ${l}%)`;
|
|
99
104
|
};
|
|
100
|
-
const color_hsla = (
|
|
105
|
+
const color_hsla = (
|
|
106
|
+
color = {
|
|
107
|
+
h: hue.current,
|
|
108
|
+
s: saturation.current,
|
|
109
|
+
b: brightness.current,
|
|
110
|
+
a: alpha.current,
|
|
111
|
+
}
|
|
112
|
+
) => {
|
|
101
113
|
const { h, s, l } = HSV_HSL(color.h, color.s, color.b);
|
|
102
114
|
return `hsla(${h}, ${s}%, ${l}%, ${color.a / 100})`;
|
|
103
115
|
};
|
|
104
|
-
const color_hex = (
|
|
116
|
+
const color_hex = (
|
|
117
|
+
color = {
|
|
118
|
+
h: hue.current,
|
|
119
|
+
s: saturation.current,
|
|
120
|
+
b: brightness.current,
|
|
121
|
+
a: alpha.current,
|
|
122
|
+
}
|
|
123
|
+
) => {
|
|
105
124
|
const { h, s, l } = HSV_HSL(color.h, color.s, color.b);
|
|
106
125
|
return HSL_HEX(h, s, l) + (color.a === 100 ? '' : ALPHA_HEX(color.a));
|
|
107
126
|
};
|
|
@@ -110,7 +129,14 @@ export default function ColorPicker({
|
|
|
110
129
|
const { r, g, b } = HSL_RGB(h, s, l);
|
|
111
130
|
return `rgb(${r}, ${g}, ${b})`;
|
|
112
131
|
};
|
|
113
|
-
const color_rgba = (
|
|
132
|
+
const color_rgba = (
|
|
133
|
+
color = {
|
|
134
|
+
h: hue.current,
|
|
135
|
+
s: saturation.current,
|
|
136
|
+
b: brightness.current,
|
|
137
|
+
a: alpha.current,
|
|
138
|
+
}
|
|
139
|
+
) => {
|
|
114
140
|
const { h, s, l } = HSV_HSL(color.h, color.s, color.b);
|
|
115
141
|
const { r, g, b } = HSL_RGB(h, s, l);
|
|
116
142
|
return `rgba(${r}, ${g}, ${b}, ${color.a / 100})`;
|
|
@@ -118,11 +144,25 @@ export default function ColorPicker({
|
|
|
118
144
|
const color_hsv = (color = { h: hue.current, s: saturation.current, b: brightness.current }) => {
|
|
119
145
|
return `hsv(${color.h}, ${color.s}%, ${color.b}%)`;
|
|
120
146
|
};
|
|
121
|
-
const color_hsva = (
|
|
147
|
+
const color_hsva = (
|
|
148
|
+
color = {
|
|
149
|
+
h: hue.current,
|
|
150
|
+
s: saturation.current,
|
|
151
|
+
b: brightness.current,
|
|
152
|
+
a: alpha.current,
|
|
153
|
+
}
|
|
154
|
+
) => {
|
|
122
155
|
return `hsva(${color.h}, ${color.s}%, ${color.b}%, ${color.a / 100})`;
|
|
123
156
|
};
|
|
124
157
|
|
|
125
|
-
const returnedResults = (
|
|
158
|
+
const returnedResults = (
|
|
159
|
+
color = {
|
|
160
|
+
h: hue.current,
|
|
161
|
+
s: saturation.current,
|
|
162
|
+
b: brightness.current,
|
|
163
|
+
a: alpha.current,
|
|
164
|
+
}
|
|
165
|
+
) => {
|
|
126
166
|
return {
|
|
127
167
|
hex: color_hex(color),
|
|
128
168
|
rgb: color_rgb(color),
|
|
@@ -135,23 +175,33 @@ export default function ColorPicker({
|
|
|
135
175
|
};
|
|
136
176
|
|
|
137
177
|
const previewColor = useSharedValue(color_hex());
|
|
138
|
-
const previewColorStyle = useAnimatedStyle(() => ({
|
|
178
|
+
const previewColorStyle = useAnimatedStyle(() => ({
|
|
179
|
+
backgroundColor: previewColor.value,
|
|
180
|
+
}));
|
|
139
181
|
const previewColorWithoutOpacity = useAnimatedStyle(() => ({
|
|
140
182
|
backgroundColor: previewColor.value.length > 7 ? previewColor.value.substring(0, 7) : previewColor.value,
|
|
141
183
|
}));
|
|
142
184
|
const activeHue = useSharedValue(HSL_HEX(hue.current, 100, 50));
|
|
143
|
-
const activeHueStyle = useAnimatedStyle(() => ({
|
|
185
|
+
const activeHueStyle = useAnimatedStyle(() => ({
|
|
186
|
+
backgroundColor: activeHue.value,
|
|
187
|
+
}));
|
|
188
|
+
|
|
189
|
+
const saturationPanel1_handlePos = useSharedValue(0); // for saturation panle 1 adobe style
|
|
190
|
+
const brightnessPanel1_handlePos = useSharedValue(0); // for brightness panle 1 adobe style
|
|
191
|
+
|
|
192
|
+
const huePanel2_handlePos = useSharedValue(0); // for hue panle 2 windows style
|
|
193
|
+
const saturationPanel2_handlePos = useSharedValue(0); // for saturation panle 2 windows style
|
|
144
194
|
|
|
145
195
|
const hue_handlePos = useSharedValue(0); // for hue slider
|
|
146
|
-
const saturationPanel_handlePos = useSharedValue(0); // for saturation panle
|
|
147
196
|
const saturationSlider_handlePos = useSharedValue(0); // for saturation slider
|
|
148
|
-
const brightnessPanel_handlePos = useSharedValue(0); // for brightness panel
|
|
149
197
|
const brightnessSlider_handlePos = useSharedValue(0); // for brightness slider
|
|
150
198
|
const opacity_handlePos = useSharedValue(0); // for opacity slider
|
|
151
199
|
const previewTextColor = useSharedValue('#ffffff'); // for result text color
|
|
152
200
|
const previewText = useSharedValue(returnedResults()[previewColorFormat.current]); // for result text
|
|
153
201
|
|
|
154
|
-
const previewTextColorStyle = useAnimatedStyle(() => ({
|
|
202
|
+
const previewTextColorStyle = useAnimatedStyle(() => ({
|
|
203
|
+
color: previewTextColor.value,
|
|
204
|
+
}));
|
|
155
205
|
|
|
156
206
|
const onGestureEventFinish = () => {
|
|
157
207
|
onComplete?.(returnedResults());
|
|
@@ -194,6 +244,20 @@ export default function ColorPicker({
|
|
|
194
244
|
onChange?.(returnedResults());
|
|
195
245
|
};
|
|
196
246
|
|
|
247
|
+
const updateHS = (hueChannel, saturationChannel) => {
|
|
248
|
+
saturation.current = saturationChannel;
|
|
249
|
+
hue.current = hueChannel;
|
|
250
|
+
previewColor.value = color_hex(); // to update result color.
|
|
251
|
+
previewText.value = returnedResults()[previewColorFormat.current]; // update result text
|
|
252
|
+
// change result text color based on lightness
|
|
253
|
+
const contrast = CONTRAST_RATIO(hue.current, saturation.current, brightness.current, previewTextColor.value);
|
|
254
|
+
previewTextColor.value =
|
|
255
|
+
contrast < CONTRAST_RATIO_MIN ? (previewTextColor.value === '#ffffff' ? '#000000' : '#ffffff') : previewTextColor.value;
|
|
256
|
+
|
|
257
|
+
activeHue.value = HSL_HEX(hueChannel, 100, 50);
|
|
258
|
+
onChange?.(returnedResults());
|
|
259
|
+
};
|
|
260
|
+
|
|
197
261
|
const updateHue = hueChannel => {
|
|
198
262
|
hue.current = hueChannel;
|
|
199
263
|
previewColor.value = color_hex(); // to update result color.
|
|
@@ -203,7 +267,7 @@ export default function ColorPicker({
|
|
|
203
267
|
previewTextColor.value =
|
|
204
268
|
contrast < CONTRAST_RATIO_MIN ? (previewTextColor.value === '#ffffff' ? '#000000' : '#ffffff') : previewTextColor.value;
|
|
205
269
|
|
|
206
|
-
activeHue.value = HSL_HEX(hueChannel, 100, 50);
|
|
270
|
+
activeHue.value = HSL_HEX(hueChannel, 100, 50);
|
|
207
271
|
onChange?.(returnedResults());
|
|
208
272
|
};
|
|
209
273
|
|
|
@@ -231,33 +295,38 @@ export default function ColorPicker({
|
|
|
231
295
|
const contrast = CONTRAST_RATIO(hue.current, saturation.current, brightness.current, previewTextColor.value);
|
|
232
296
|
previewTextColor.value =
|
|
233
297
|
contrast < CONTRAST_RATIO_MIN ? (previewTextColor.value === '#ffffff' ? '#000000' : '#ffffff') : previewTextColor.value;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
isRtl ? (s / SB_MAX) * width - width +
|
|
298
|
+
//~ saturation
|
|
299
|
+
saturationPanel1_handlePos.value = withTiming(
|
|
300
|
+
isRtl ? (s / SB_MAX) * width - width + panel1ThumbeSize.current / 2 : (s / SB_MAX) * width - panel1ThumbeSize.current / 2,
|
|
237
301
|
duration
|
|
238
|
-
);
|
|
302
|
+
); // panel 1 adobe style
|
|
303
|
+
saturationPanel2_handlePos.value = withTiming(width - (s / SB_MAX) * width - panel2ThumbeSize.current / 2, duration); // panel 2 windows style
|
|
239
304
|
saturationSlider_handlePos.value = withTiming(
|
|
240
305
|
isRtl
|
|
241
306
|
? (s / SB_MAX) * width - width + saturationThumbeSize.current / 2
|
|
242
307
|
: (s / SB_MAX) * width - saturationThumbeSize.current / 2,
|
|
243
308
|
duration
|
|
244
309
|
);
|
|
245
|
-
|
|
246
|
-
|
|
310
|
+
//~ brightness
|
|
311
|
+
brightnessPanel1_handlePos.value = withTiming(width - (b / SB_MAX) * width - panel1ThumbeSize.current / 2, duration);
|
|
247
312
|
brightnessSlider_handlePos.value = withTiming(
|
|
248
313
|
isRtl
|
|
249
314
|
? (b / SB_MAX) * width - width + brightnessThumbeSize.current / 2
|
|
250
315
|
: (b / SB_MAX) * width - brightnessThumbeSize.current / 2,
|
|
251
316
|
duration
|
|
252
317
|
);
|
|
253
|
-
|
|
318
|
+
//~ hue
|
|
254
319
|
hue_handlePos.value = withTiming(
|
|
255
320
|
isRtl
|
|
256
321
|
? width - (h / HUE_MAX) * width - width + hueThumbeSize.current / 2
|
|
257
322
|
: width - (h / HUE_MAX) * width - hueThumbeSize.current / 2,
|
|
258
323
|
100
|
|
259
324
|
);
|
|
260
|
-
|
|
325
|
+
huePanel2_handlePos.value = withTiming(
|
|
326
|
+
isRtl ? (h / HUE_MAX) * width - width + panel2ThumbeSize.current / 2 : (h / HUE_MAX) * width - panel2ThumbeSize.current / 2,
|
|
327
|
+
duration
|
|
328
|
+
); // panel 2 windows style
|
|
329
|
+
//~ opacity
|
|
261
330
|
opacity_handlePos.value = withTiming(
|
|
262
331
|
isRtl
|
|
263
332
|
? (a / OPACITY_MAX) * width - width + opacityThumbeSize.current / 2
|
|
@@ -291,9 +360,11 @@ export default function ColorPicker({
|
|
|
291
360
|
previewColorFormat,
|
|
292
361
|
|
|
293
362
|
setHandlesPos,
|
|
294
|
-
|
|
363
|
+
saturationPanel1_handlePos,
|
|
364
|
+
brightnessPanel1_handlePos,
|
|
365
|
+
saturationPanel2_handlePos,
|
|
366
|
+
huePanel2_handlePos,
|
|
295
367
|
saturationSlider_handlePos,
|
|
296
|
-
brightnessPanel_handlePos,
|
|
297
368
|
brightnessSlider_handlePos,
|
|
298
369
|
hue_handlePos,
|
|
299
370
|
opacity_handlePos,
|
|
@@ -301,13 +372,15 @@ export default function ColorPicker({
|
|
|
301
372
|
updateSaturation,
|
|
302
373
|
updateBrightness,
|
|
303
374
|
updateSB,
|
|
375
|
+
updateHS,
|
|
304
376
|
updateOpacity,
|
|
305
377
|
updateHue,
|
|
306
378
|
|
|
307
379
|
tracksHeight,
|
|
308
380
|
thumbsSize,
|
|
309
381
|
|
|
310
|
-
|
|
382
|
+
panel1ThumbeSize,
|
|
383
|
+
panel2ThumbeSize,
|
|
311
384
|
saturationThumbeSize,
|
|
312
385
|
brightnessThumbeSize,
|
|
313
386
|
hueThumbeSize,
|
|
@@ -331,18 +404,20 @@ export default function ColorPicker({
|
|
|
331
404
|
return <GestureHandlerRootView style={[styles.wrapper, style]}>{ColorPickerModules}</GestureHandlerRootView>;
|
|
332
405
|
}
|
|
333
406
|
|
|
334
|
-
export function
|
|
407
|
+
export function Panel1({
|
|
335
408
|
activeHueStyle,
|
|
336
409
|
previewTextColor,
|
|
337
410
|
previewColorWithoutOpacity,
|
|
338
|
-
|
|
411
|
+
saturationPanel1_handlePos,
|
|
412
|
+
brightnessPanel1_handlePos,
|
|
413
|
+
saturationPanel2_handlePos,
|
|
339
414
|
saturationSlider_handlePos,
|
|
340
|
-
brightnessPanel_handlePos,
|
|
341
415
|
brightnessSlider_handlePos,
|
|
342
416
|
updateSB,
|
|
343
417
|
onGestureEventFinish,
|
|
344
418
|
setHandlesPos,
|
|
345
|
-
|
|
419
|
+
panel1ThumbeSize,
|
|
420
|
+
panel2ThumbeSize,
|
|
346
421
|
brightnessThumbeSize,
|
|
347
422
|
saturationThumbeSize,
|
|
348
423
|
width,
|
|
@@ -350,7 +425,7 @@ export function Panel({
|
|
|
350
425
|
thumbSize = thumbsSize, // by user
|
|
351
426
|
style = {}, // by user
|
|
352
427
|
}) {
|
|
353
|
-
|
|
428
|
+
panel1ThumbeSize.current = thumbSize;
|
|
354
429
|
|
|
355
430
|
useEffect(() => {
|
|
356
431
|
setHandlesPos();
|
|
@@ -362,8 +437,8 @@ export function Panel({
|
|
|
362
437
|
backgroundColor: previewTextColor.value === '#ffffff' ? '#ffffff50' : '#00000050',
|
|
363
438
|
borderColor: previewTextColor.value,
|
|
364
439
|
transform: [
|
|
365
|
-
{ translateX:
|
|
366
|
-
{ translateY:
|
|
440
|
+
{ translateX: saturationPanel1_handlePos.value },
|
|
441
|
+
{ translateY: brightnessPanel1_handlePos.value },
|
|
367
442
|
{ scale: scale_panelHandle.value },
|
|
368
443
|
],
|
|
369
444
|
}));
|
|
@@ -387,16 +462,20 @@ export function Panel({
|
|
|
387
462
|
const saturationX = Math.round(percentX * SB_MAX);
|
|
388
463
|
const brightnessY = Math.round(SB_MAX - percentY * SB_MAX);
|
|
389
464
|
|
|
390
|
-
|
|
391
|
-
|
|
465
|
+
saturationPanel1_handlePos.value = isRtl ? percentX * width - width + thumbSize / 2 : percentX * width - thumbSize / 2;
|
|
466
|
+
brightnessPanel1_handlePos.value = percentY * width - thumbSize / 2;
|
|
392
467
|
|
|
393
468
|
brightnessSlider_handlePos.value = isRtl
|
|
394
469
|
? (brightnessY / SB_MAX) * width - width + brightnessThumbeSize.current / 2
|
|
395
470
|
: (brightnessY / SB_MAX) * width - brightnessThumbeSize.current / 2;
|
|
471
|
+
|
|
396
472
|
saturationSlider_handlePos.value = isRtl
|
|
397
473
|
? (saturationX / SB_MAX) * width - width + saturationThumbeSize.current / 2
|
|
398
474
|
: (saturationX / SB_MAX) * width - saturationThumbeSize.current / 2;
|
|
399
475
|
|
|
476
|
+
// panel 2 windows style
|
|
477
|
+
saturationPanel2_handlePos.value = width - (saturationX / SB_MAX) * width - panel2ThumbeSize.current / 2;
|
|
478
|
+
|
|
400
479
|
runOnJS(updateSB)(saturationX, brightnessY);
|
|
401
480
|
},
|
|
402
481
|
onFinish: () => {
|
|
@@ -408,9 +487,135 @@ export function Panel({
|
|
|
408
487
|
return (
|
|
409
488
|
<PanGestureHandler onGestureEvent={panel_GestureEvent} minDist={0}>
|
|
410
489
|
<Animated.View style={[styles.panel_container, style, { width, height: width }, styles.override, activeHueStyle]}>
|
|
411
|
-
<Image
|
|
490
|
+
<Image
|
|
491
|
+
source={require('./assets/Background1.png')}
|
|
492
|
+
style={{
|
|
493
|
+
borderRadius: style.borderRadius ?? 5,
|
|
494
|
+
width,
|
|
495
|
+
height: width,
|
|
496
|
+
}}
|
|
497
|
+
/>
|
|
412
498
|
<Animated.View
|
|
413
|
-
style={[
|
|
499
|
+
style={[
|
|
500
|
+
styles.handle,
|
|
501
|
+
{
|
|
502
|
+
width: thumbSize,
|
|
503
|
+
height: thumbSize,
|
|
504
|
+
borderRadius: thumbSize / 2,
|
|
505
|
+
},
|
|
506
|
+
panel_handleStyle,
|
|
507
|
+
]}
|
|
508
|
+
>
|
|
509
|
+
<Animated.View style={[styles.handleInner, { borderRadius: thumbSize / 2 }, previewColorWithoutOpacity]} />
|
|
510
|
+
</Animated.View>
|
|
511
|
+
</Animated.View>
|
|
512
|
+
</PanGestureHandler>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export function Panel2({
|
|
517
|
+
previewTextColor,
|
|
518
|
+
previewColorWithoutOpacity,
|
|
519
|
+
saturationPanel1_handlePos,
|
|
520
|
+
saturationPanel2_handlePos,
|
|
521
|
+
huePanel2_handlePos,
|
|
522
|
+
hue_handlePos,
|
|
523
|
+
saturationSlider_handlePos,
|
|
524
|
+
onGestureEventFinish,
|
|
525
|
+
setHandlesPos,
|
|
526
|
+
panel1ThumbeSize,
|
|
527
|
+
panel2ThumbeSize,
|
|
528
|
+
hueThumbeSize,
|
|
529
|
+
saturationThumbeSize,
|
|
530
|
+
updateHS,
|
|
531
|
+
width,
|
|
532
|
+
thumbsSize,
|
|
533
|
+
thumbSize = thumbsSize, // by user
|
|
534
|
+
style = {}, // by user
|
|
535
|
+
}) {
|
|
536
|
+
panel2ThumbeSize.current = thumbSize;
|
|
537
|
+
|
|
538
|
+
useEffect(() => {
|
|
539
|
+
setHandlesPos();
|
|
540
|
+
}, []);
|
|
541
|
+
|
|
542
|
+
const scale_panelHandle = useSharedValue(1);
|
|
543
|
+
|
|
544
|
+
const panel_handleStyle = useAnimatedStyle(() => ({
|
|
545
|
+
backgroundColor: previewTextColor.value === '#ffffff' ? '#ffffff50' : '#00000050',
|
|
546
|
+
borderColor: previewTextColor.value,
|
|
547
|
+
transform: [
|
|
548
|
+
{ translateX: huePanel2_handlePos.value },
|
|
549
|
+
{ translateY: saturationPanel2_handlePos.value },
|
|
550
|
+
{ scale: scale_panelHandle.value },
|
|
551
|
+
],
|
|
552
|
+
}));
|
|
553
|
+
|
|
554
|
+
const panel_GestureEvent = useAnimatedGestureHandler({
|
|
555
|
+
onStart: (event, ctx) => {
|
|
556
|
+
ctx.x = event.x;
|
|
557
|
+
ctx.y = event.y;
|
|
558
|
+
scale_panelHandle.value = withTiming(HANDLES_SCALE, { duration: 100 });
|
|
559
|
+
},
|
|
560
|
+
onActive: (event, ctx) => {
|
|
561
|
+
const clamp = (v, max) => Math.min(Math.max(v, 0), max);
|
|
562
|
+
|
|
563
|
+
const x = event.translationX;
|
|
564
|
+
const y = event.translationY;
|
|
565
|
+
const posX = clamp(x + ctx.x, width);
|
|
566
|
+
const posY = clamp(y + ctx.y, width);
|
|
567
|
+
const percentX = posX / width;
|
|
568
|
+
const percentY = posY / width;
|
|
569
|
+
|
|
570
|
+
const hueX = Math.round(percentX * HUE_MAX);
|
|
571
|
+
const saturationY = Math.round(SB_MAX - percentY * SB_MAX);
|
|
572
|
+
|
|
573
|
+
huePanel2_handlePos.value = isRtl ? percentX * width - width + thumbSize / 2 : percentX * width - thumbSize / 2;
|
|
574
|
+
|
|
575
|
+
saturationPanel2_handlePos.value = percentY * width - thumbSize / 2;
|
|
576
|
+
|
|
577
|
+
hue_handlePos.value = isRtl
|
|
578
|
+
? width - (hueX / HUE_MAX) * width - width + hueThumbeSize.current / 2
|
|
579
|
+
: width - (hueX / HUE_MAX) * width - hueThumbeSize.current / 2;
|
|
580
|
+
|
|
581
|
+
saturationSlider_handlePos.value = isRtl
|
|
582
|
+
? (saturationY / SB_MAX) * width - width + saturationThumbeSize.current / 2
|
|
583
|
+
: (saturationY / SB_MAX) * width - saturationThumbeSize.current / 2;
|
|
584
|
+
|
|
585
|
+
// panel 1 adobe style
|
|
586
|
+
saturationPanel1_handlePos.value = isRtl
|
|
587
|
+
? (saturationY / SB_MAX) * width - width + panel1ThumbeSize.current / 2
|
|
588
|
+
: (saturationY / SB_MAX) * width - panel1ThumbeSize.current / 2;
|
|
589
|
+
|
|
590
|
+
runOnJS(updateHS)(hueX, saturationY);
|
|
591
|
+
},
|
|
592
|
+
onFinish: () => {
|
|
593
|
+
scale_panelHandle.value = withTiming(1, { duration: 100 });
|
|
594
|
+
runOnJS(onGestureEventFinish)();
|
|
595
|
+
},
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
return (
|
|
599
|
+
<PanGestureHandler onGestureEvent={panel_GestureEvent} minDist={0}>
|
|
600
|
+
<Animated.View style={[styles.panel_container, style, { width, height: width }, styles.override]}>
|
|
601
|
+
<Image
|
|
602
|
+
source={require('./assets/Background2.png')}
|
|
603
|
+
style={{
|
|
604
|
+
borderRadius: style.borderRadius ?? 5,
|
|
605
|
+
width,
|
|
606
|
+
height: width,
|
|
607
|
+
}}
|
|
608
|
+
/>
|
|
609
|
+
<Animated.View
|
|
610
|
+
style={[
|
|
611
|
+
styles.handle,
|
|
612
|
+
{
|
|
613
|
+
width: thumbSize,
|
|
614
|
+
height: thumbSize,
|
|
615
|
+
borderRadius: thumbSize / 2,
|
|
616
|
+
},
|
|
617
|
+
panel_handleStyle,
|
|
618
|
+
]}
|
|
414
619
|
>
|
|
415
620
|
<Animated.View style={[styles.handleInner, { borderRadius: thumbSize / 2 }, previewColorWithoutOpacity]} />
|
|
416
621
|
</Animated.View>
|
|
@@ -448,7 +653,7 @@ export function Preview({
|
|
|
448
653
|
<View style={[styles.preview, { width }, style]}>
|
|
449
654
|
{!hideInitialColor && (
|
|
450
655
|
<View style={[styles.previewChildren, { backgroundColor: value }]}>
|
|
451
|
-
{hideText && (
|
|
656
|
+
{!hideText && (
|
|
452
657
|
<Text style={[{ color: initialColorText.color }, { fontWeight: 'bold' }, textStyle]}>
|
|
453
658
|
{initialColorText.formated}
|
|
454
659
|
</Text>
|
|
@@ -469,8 +674,10 @@ export function HueSlider({
|
|
|
469
674
|
updateHue,
|
|
470
675
|
onGestureEventFinish,
|
|
471
676
|
hue_handlePos,
|
|
677
|
+
huePanel2_handlePos,
|
|
472
678
|
previewColorWithoutOpacity,
|
|
473
679
|
tracksHeight,
|
|
680
|
+
panel2ThumbeSize,
|
|
474
681
|
thumbsSize,
|
|
475
682
|
thumbSize = thumbsSize, // by user
|
|
476
683
|
ringColor = '#ffffff', // by user
|
|
@@ -514,6 +721,11 @@ export function HueSlider({
|
|
|
514
721
|
|
|
515
722
|
hue_handlePos.value = isRtl ? percent * width - width + thumbSize / 2 : percent * width - thumbSize / 2;
|
|
516
723
|
|
|
724
|
+
// panel 2 windows style
|
|
725
|
+
huePanel2_handlePos.value = isRtl
|
|
726
|
+
? (hueX / HUE_MAX) * width - width + panel2ThumbeSize.current / 2
|
|
727
|
+
: (hueX / HUE_MAX) * width - panel2ThumbeSize.current / 2;
|
|
728
|
+
|
|
517
729
|
runOnJS(updateHue)(hueX);
|
|
518
730
|
},
|
|
519
731
|
onFinish: () => {
|
|
@@ -528,7 +740,7 @@ export function HueSlider({
|
|
|
528
740
|
<PanGestureHandler onGestureEvent={HueGestureEvent} minDist={0}>
|
|
529
741
|
<Animated.View style={[{ position: 'relative', height: tracksHeight }, style, { width }, styles.override]}>
|
|
530
742
|
<View style={[styles.sliderImageContainer, { borderRadius: style.borderRadius ?? 5 }]}>
|
|
531
|
-
<Image source={
|
|
743
|
+
<Image source={require('./assets/Hue.png')} style={styles.sliderImage} />
|
|
532
744
|
</View>
|
|
533
745
|
<Animated.View
|
|
534
746
|
style={[
|
|
@@ -553,11 +765,13 @@ export function HueSlider({
|
|
|
553
765
|
export function SaturationSlider({
|
|
554
766
|
width,
|
|
555
767
|
saturationThumbeSize,
|
|
556
|
-
|
|
768
|
+
panel2ThumbeSize,
|
|
769
|
+
panel1ThumbeSize,
|
|
557
770
|
setHandlesPos,
|
|
558
771
|
updateSaturation,
|
|
559
772
|
onGestureEventFinish,
|
|
560
|
-
|
|
773
|
+
saturationPanel1_handlePos,
|
|
774
|
+
saturationPanel2_handlePos,
|
|
561
775
|
saturationSlider_handlePos,
|
|
562
776
|
previewColorWithoutOpacity,
|
|
563
777
|
tracksHeight,
|
|
@@ -592,7 +806,9 @@ export function SaturationSlider({
|
|
|
592
806
|
{
|
|
593
807
|
onStart: (event, ctx) => {
|
|
594
808
|
ctx.x = event.x;
|
|
595
|
-
scale_saturationHandle.value = withTiming(HANDLES_SCALE, {
|
|
809
|
+
scale_saturationHandle.value = withTiming(HANDLES_SCALE, {
|
|
810
|
+
duration: 100,
|
|
811
|
+
});
|
|
596
812
|
},
|
|
597
813
|
onActive: (event, ctx) => {
|
|
598
814
|
const clamp = (v, max) => Math.min(Math.max(v, 0), max);
|
|
@@ -604,9 +820,12 @@ export function SaturationSlider({
|
|
|
604
820
|
const saturationX = Math.round(percent * SB_MAX);
|
|
605
821
|
|
|
606
822
|
saturationSlider_handlePos.value = isRtl ? percent * width - width + thumbSize / 2 : percent * width - thumbSize / 2;
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
823
|
+
// panel 2 windows style
|
|
824
|
+
saturationPanel1_handlePos.value = isRtl
|
|
825
|
+
? (saturationX / SB_MAX) * width - width + panel1ThumbeSize.current / 2
|
|
826
|
+
: (saturationX / SB_MAX) * width - panel1ThumbeSize.current / 2;
|
|
827
|
+
// panel 2 windows style
|
|
828
|
+
saturationPanel2_handlePos.value = width - (saturationX / SB_MAX) * width - panel2ThumbeSize.current / 2;
|
|
610
829
|
|
|
611
830
|
runOnJS(updateSaturation)(saturationX);
|
|
612
831
|
},
|
|
@@ -622,7 +841,7 @@ export function SaturationSlider({
|
|
|
622
841
|
<PanGestureHandler onGestureEvent={SaturationGestureEvent} minDist={0}>
|
|
623
842
|
<Animated.View style={[{ position: 'relative', height: tracksHeight }, style, { width }, styles.override]}>
|
|
624
843
|
<Animated.View style={[styles.sliderImageContainer, { borderRadius: style.borderRadius ?? 5 }, activeHueStyle]}>
|
|
625
|
-
<Image source={
|
|
844
|
+
<Image source={require('./assets/Saturation.png')} style={styles.sliderImage} />
|
|
626
845
|
</Animated.View>
|
|
627
846
|
<Animated.View
|
|
628
847
|
style={[
|
|
@@ -647,11 +866,11 @@ export function SaturationSlider({
|
|
|
647
866
|
export function BrightnessSlider({
|
|
648
867
|
width,
|
|
649
868
|
brightnessThumbeSize,
|
|
650
|
-
|
|
869
|
+
panel1ThumbeSize,
|
|
651
870
|
setHandlesPos,
|
|
652
871
|
updateBrightness,
|
|
653
872
|
onGestureEventFinish,
|
|
654
|
-
|
|
873
|
+
brightnessPanel1_handlePos,
|
|
655
874
|
brightnessSlider_handlePos,
|
|
656
875
|
previewColorWithoutOpacity,
|
|
657
876
|
tracksHeight,
|
|
@@ -686,7 +905,9 @@ export function BrightnessSlider({
|
|
|
686
905
|
{
|
|
687
906
|
onStart: (event, ctx) => {
|
|
688
907
|
ctx.x = event.x;
|
|
689
|
-
scale_brightnessHandle.value = withTiming(HANDLES_SCALE, {
|
|
908
|
+
scale_brightnessHandle.value = withTiming(HANDLES_SCALE, {
|
|
909
|
+
duration: 100,
|
|
910
|
+
});
|
|
690
911
|
},
|
|
691
912
|
onActive: (event, ctx) => {
|
|
692
913
|
const clamp = (v, max) => Math.min(Math.max(v, 0), max);
|
|
@@ -698,7 +919,7 @@ export function BrightnessSlider({
|
|
|
698
919
|
const brightnessX = Math.round(percent * SB_MAX);
|
|
699
920
|
|
|
700
921
|
brightnessSlider_handlePos.value = isRtl ? percent * width - width + thumbSize / 2 : percent * width - thumbSize / 2;
|
|
701
|
-
|
|
922
|
+
brightnessPanel1_handlePos.value = width - (brightnessX / SB_MAX) * width - panel1ThumbeSize.current / 2;
|
|
702
923
|
|
|
703
924
|
runOnJS(updateBrightness)(brightnessX);
|
|
704
925
|
},
|
|
@@ -714,7 +935,7 @@ export function BrightnessSlider({
|
|
|
714
935
|
<PanGestureHandler onGestureEvent={BrightnessGestureEvent} minDist={0}>
|
|
715
936
|
<Animated.View style={[{ position: 'relative', height: tracksHeight }, style, { width }, styles.override]}>
|
|
716
937
|
<Animated.View style={[styles.sliderImageContainer, { borderRadius: style.borderRadius ?? 5 }, activeHueStyle]}>
|
|
717
|
-
<Image source={
|
|
938
|
+
<Image source={require('./assets/Brightness.png')} style={styles.sliderImage} />
|
|
718
939
|
</Animated.View>
|
|
719
940
|
<Animated.View
|
|
720
941
|
style={[
|
|
@@ -800,7 +1021,7 @@ export function OpacitySlider({
|
|
|
800
1021
|
<PanGestureHandler onGestureEvent={opacityGestureEvent} minDist={0}>
|
|
801
1022
|
<Animated.View style={[{ position: 'relative', height: tracksHeight }, style, { width }, styles.override]}>
|
|
802
1023
|
<Animated.View style={[styles.sliderImageContainer, { borderRadius: style.borderRadius ?? 5 }, activeHueStyle]}>
|
|
803
|
-
<Image source={
|
|
1024
|
+
<Image source={require('./assets/Opacity.png')} style={styles.sliderImage} />
|
|
804
1025
|
</Animated.View>
|
|
805
1026
|
<Animated.View
|
|
806
1027
|
style={[
|
|
@@ -3,25 +3,15 @@ import NamedColors from './NamedColors';
|
|
|
3
3
|
export const HSL_RGB = (h, s, l) => {
|
|
4
4
|
s /= 100;
|
|
5
5
|
l /= 100;
|
|
6
|
+
const k = n => (n + h / 30) % 12;
|
|
7
|
+
const a = s * Math.min(l, 1 - l);
|
|
8
|
+
const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
huePrime = Math.floor(huePrime);
|
|
13
|
-
|
|
14
|
-
let red = [0, 5].includes(huePrime) ? chroma : [1, 4].includes(huePrime) ? secondComponent : 0,
|
|
15
|
-
green = [1, 2].includes(huePrime) ? chroma : [0, 3].includes(huePrime) ? secondComponent : 0,
|
|
16
|
-
blue = [3, 4].includes(huePrime) ? chroma : [2, 5].includes(huePrime) ? secondComponent : 0;
|
|
17
|
-
|
|
18
|
-
const lightnessAdjustment = l - chroma / 2;
|
|
19
|
-
|
|
20
|
-
red += lightnessAdjustment;
|
|
21
|
-
green += lightnessAdjustment;
|
|
22
|
-
blue += lightnessAdjustment;
|
|
23
|
-
|
|
24
|
-
return { r: Math.abs(Math.round(red * 255)), g: Math.abs(Math.round(green * 255)), b: Math.abs(Math.round(blue * 255)) };
|
|
10
|
+
return {
|
|
11
|
+
r: Math.round(255 * f(0)),
|
|
12
|
+
g: Math.round(255 * f(8)),
|
|
13
|
+
b: Math.round(255 * f(4)),
|
|
14
|
+
};
|
|
25
15
|
};
|
|
26
16
|
|
|
27
17
|
export const ALPHA_HEX = number => {
|
|
@@ -157,7 +147,7 @@ export const COLOR_HSVA = colorStr => {
|
|
|
157
147
|
if (!match) throw new Error('Invalid HSL value');
|
|
158
148
|
const colorValues = match.split(',');
|
|
159
149
|
if (colorValues.length !== 3) throw new Error('Invalid HSL value');
|
|
160
|
-
const [h, s, l] = colorValues.map(v => +v);
|
|
150
|
+
const [h, s, l] = colorValues.map(v => +v.replace('%', '').replace('deg', ''));
|
|
161
151
|
if (isNaN(h) || isNaN(s) || isNaN(l)) throw new Error('Invalid HSL value');
|
|
162
152
|
return { ...HSL_HSV(h, s, l), a: 100 };
|
|
163
153
|
}
|
|
@@ -167,7 +157,7 @@ export const COLOR_HSVA = colorStr => {
|
|
|
167
157
|
if (!match) throw new Error('Invalid HSLA value');
|
|
168
158
|
const colorValues = match.split(',');
|
|
169
159
|
if (colorValues.length !== 4) throw new Error('Invalid HSLA value');
|
|
170
|
-
const [h, s, l, a] = colorValues.map(v => +v);
|
|
160
|
+
const [h, s, l, a] = colorValues.map(v => +v.replace('%', '').replace('deg', ''));
|
|
171
161
|
if (isNaN(h) || isNaN(s) || isNaN(l) || isNaN(a)) throw new Error('Invalid HSLA value');
|
|
172
162
|
return { ...HSL_HSV(h, s, l), a: Math.round(a * 100) };
|
|
173
163
|
}
|
|
@@ -177,7 +167,7 @@ export const COLOR_HSVA = colorStr => {
|
|
|
177
167
|
if (!match) throw new Error('Invalid HSV value');
|
|
178
168
|
const colorValues = match.split(',');
|
|
179
169
|
if (colorValues.length !== 3) throw new Error('Invalid HSV value');
|
|
180
|
-
const [h, s, b] = colorValues.map(n => +n);
|
|
170
|
+
const [h, s, b] = colorValues.map(n => +n.replace('%', '').replace('deg', ''));
|
|
181
171
|
if (isNaN(h) || isNaN(s) || isNaN(b)) throw new Error('Invalid HSV value');
|
|
182
172
|
return { h, s, b, a: 100 };
|
|
183
173
|
}
|
|
@@ -187,7 +177,7 @@ export const COLOR_HSVA = colorStr => {
|
|
|
187
177
|
if (!match) throw new Error('Invalid HSVA value');
|
|
188
178
|
const colorValues = match.split(',');
|
|
189
179
|
if (colorValues.length !== 4) throw new Error('Invalid HSVA value');
|
|
190
|
-
const [h, s, b, a] = colorValues.map(n => +n);
|
|
180
|
+
const [h, s, b, a] = colorValues.map(n => +n.replace('%', '').replace('deg', ''));
|
|
191
181
|
if (isNaN(h) || isNaN(s) || isNaN(b) || isNaN(a)) throw new Error('Invalid HSVA value');
|
|
192
182
|
return { h, s, b, a: Math.round(a * 100) };
|
|
193
183
|
}
|
|
File without changes
|
|
Binary file
|
package/lib/index.d.ts
CHANGED
|
@@ -147,7 +147,8 @@ interface OpacityProps {
|
|
|
147
147
|
|
|
148
148
|
declare const ColorPicker: React.FunctionComponent<ColorPickerProps>;
|
|
149
149
|
export declare const Preview: React.FunctionComponent<PreviewPorps>;
|
|
150
|
-
export declare const
|
|
150
|
+
export declare const Panel1: React.FunctionComponent<PanelProps>;
|
|
151
|
+
export declare const Panel2: React.FunctionComponent<PanelProps>;
|
|
151
152
|
export declare const HueSlider: React.FunctionComponent<HueProps>;
|
|
152
153
|
export declare const BrightnessSlider: React.FunctionComponent<BrightnessProps>;
|
|
153
154
|
export declare const SaturationSlider: React.FunctionComponent<SaturationProps>;
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import ColorPicker from './ColorPicker.js';
|
|
2
|
-
|
|
3
|
-
export default ColorPicker;
|
|
4
|
-
export {
|
|
1
|
+
import ColorPicker from './ColorPicker.js';
|
|
2
|
+
|
|
3
|
+
export default ColorPicker;
|
|
4
|
+
export {
|
|
5
|
+
Panel1,
|
|
6
|
+
Panel2,
|
|
7
|
+
Swatches,
|
|
8
|
+
Preview,
|
|
9
|
+
OpacitySlider,
|
|
10
|
+
HueSlider,
|
|
11
|
+
BrightnessSlider,
|
|
12
|
+
SaturationSlider,
|
|
13
|
+
} from './ColorPicker.js';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|

|
|
15
15
|
|
|
16
|
+

|
|
17
|
+
|
|
16
18
|
# :small_blue_diamond: Table of contents
|
|
17
19
|
|
|
18
20
|
- :one: [Prerequisites](#small_blue_diamondprerequisites).
|
|
@@ -26,7 +28,8 @@
|
|
|
26
28
|
- [ColorPicker Wrapper](#small_red_trianglecolorpicker-wrapper)
|
|
27
29
|
- [Built-in Components](#small_red_trianglebuilt-in-components)
|
|
28
30
|
- [`<Preview />`](#small_orange_diamondpreview-).
|
|
29
|
-
- [`<
|
|
31
|
+
- [`<Panel1 />`](#small_orange_diamondpanel1-).
|
|
32
|
+
- [`<Panel2 />`](#small_orange_diamondpanel2-).
|
|
30
33
|
- [`<HueSlider />`](#small_orange_diamondhueslider-).
|
|
31
34
|
- [`<SaturationSlider />`](#small_orange_diamondsaturationslider-).
|
|
32
35
|
- [`<BrightnessSlider />`](#small_orange_diamondbrightnessslider-).
|
|
@@ -65,7 +68,7 @@ npm i reanimated-color-picker
|
|
|
65
68
|
import React, { useState } from 'react';
|
|
66
69
|
import { Button, Modal, View } from 'react-native';
|
|
67
70
|
|
|
68
|
-
import ColorPicker, {
|
|
71
|
+
import ColorPicker, { Panel1, Swatches, Preview, OpacitySlider, HueSlider } from 'reanimated-color-picker';
|
|
69
72
|
|
|
70
73
|
export default function App() {
|
|
71
74
|
const [showModal, setShowModal] = useState(false);
|
|
@@ -82,7 +85,7 @@ export default function App() {
|
|
|
82
85
|
<Modal visible={showModal}>
|
|
83
86
|
<ColorPicker value='red' onComplete={onSelectColor}>
|
|
84
87
|
<Preview />
|
|
85
|
-
<
|
|
88
|
+
<Panel1 />
|
|
86
89
|
<HueSlider />
|
|
87
90
|
<OpacitySlider />
|
|
88
91
|
<Swatches />
|
|
@@ -169,11 +172,24 @@ export default function App() {
|
|
|
169
172
|
|
|
170
173
|
> **Note** some style properties will be overwritten.
|
|
171
174
|
|
|
172
|
-
### :small_orange_diamond:`<
|
|
175
|
+
### :small_orange_diamond:`<Panel1 />`
|
|
176
|
+
|
|
177
|
+

|
|
178
|
+
|
|
179
|
+
- A square-shaped slider (adobe style) used for changing the color's brightness and saturation.
|
|
180
|
+
|
|
181
|
+
| Property | Type | Default | Description |
|
|
182
|
+
| :-------- | :----: | :-----: | :---------------------------------------- |
|
|
183
|
+
| thumbSize | number | `35` | panel handle (thumb) size (height\*width) |
|
|
184
|
+
| style | object | / | panle container style |
|
|
185
|
+
|
|
186
|
+
> **Note** some style properties will be overwritten.
|
|
187
|
+
|
|
188
|
+
### :small_orange_diamond:`<Panel2 />`
|
|
173
189
|
|
|
174
|
-

|
|
175
191
|
|
|
176
|
-
- A square-shaped slider used for changing the color's
|
|
192
|
+
- A square-shaped slider (windows style) used for changing the color's hue and saturation.
|
|
177
193
|
|
|
178
194
|
| Property | Type | Default | Description |
|
|
179
195
|
| :-------- | :----: | :-----: | :---------------------------------------- |
|