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.
@@ -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={[{ fontWeight: 'bold', padding: 0, height: '100%', width: '100%', textAlign: 'center' }, customStyle, 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 panelThumbeSize = useRef(thumbsSize);
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 = (color = { h: hue.current, s: saturation.current, b: brightness.current, a: alpha.current }) => {
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 = (color = { h: hue.current, s: saturation.current, b: brightness.current, a: alpha.current }) => {
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 = (color = { h: hue.current, s: saturation.current, b: brightness.current, a: alpha.current }) => {
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 = (color = { h: hue.current, s: saturation.current, b: brightness.current, a: alpha.current }) => {
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 = (color = { h: hue.current, s: saturation.current, b: brightness.current, a: alpha.current }) => {
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(() => ({ backgroundColor: previewColor.value }));
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(() => ({ backgroundColor: activeHue.value }));
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(() => ({ color: previewTextColor.value }));
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); // to update SV background color.
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
- // saturation
235
- saturationPanel_handlePos.value = withTiming(
236
- isRtl ? (s / SB_MAX) * width - width + panelThumbeSize.current / 2 : (s / SB_MAX) * width - panelThumbeSize.current / 2,
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
- // brightness
246
- brightnessPanel_handlePos.value = withTiming(width - (b / SB_MAX) * width - panelThumbeSize.current / 2, duration);
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
- // hue
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
- // opacity
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
- saturationPanel_handlePos,
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
- panelThumbeSize,
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 Panel({
407
+ export function Panel1({
335
408
  activeHueStyle,
336
409
  previewTextColor,
337
410
  previewColorWithoutOpacity,
338
- saturationPanel_handlePos,
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
- panelThumbeSize,
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
- panelThumbeSize.current = thumbSize;
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: saturationPanel_handlePos.value },
366
- { translateY: brightnessPanel_handlePos.value },
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
- saturationPanel_handlePos.value = isRtl ? percentX * width - width + thumbSize / 2 : percentX * width - thumbSize / 2;
391
- brightnessPanel_handlePos.value = percentY * width - thumbSize / 2;
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 source={PANEL_IMAGE} style={{ borderRadius: style.borderRadius ?? 5, width, height: width }} />
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={[styles.handle, { width: thumbSize, height: thumbSize, borderRadius: thumbSize / 2 }, panel_handleStyle]}
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={HUE_IMAGE} style={styles.sliderImage} />
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
- panelThumbeSize,
768
+ panel2ThumbeSize,
769
+ panel1ThumbeSize,
557
770
  setHandlesPos,
558
771
  updateSaturation,
559
772
  onGestureEventFinish,
560
- saturationPanel_handlePos,
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, { duration: 100 });
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
- saturationPanel_handlePos.value = isRtl
608
- ? (saturationX / SB_MAX) * width - width + panelThumbeSize.current / 2
609
- : (saturationX / SB_MAX) * width - panelThumbeSize.current / 2;
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={SATURATION_IMAGE} style={styles.sliderImage} />
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
- panelThumbeSize,
869
+ panel1ThumbeSize,
651
870
  setHandlesPos,
652
871
  updateBrightness,
653
872
  onGestureEventFinish,
654
- brightnessPanel_handlePos,
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, { duration: 100 });
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
- brightnessPanel_handlePos.value = width - (brightnessX / SB_MAX) * width - panelThumbeSize.current / 2;
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={BRIGHTNESS_IMAGE} style={styles.sliderImage} />
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={OPACITY_IMAGE} style={styles.sliderImage} />
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
- if (h === undefined) return { r: 0, g: 0, b: 0 };
8
-
9
- const chroma = (1 - Math.abs(2 * l - 1)) * s;
10
- let huePrime = h / 60;
11
- const secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1));
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 Panel: React.FunctionComponent<PanelProps>;
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 { Panel, Swatches, Preview, OpacitySlider, HueSlider, BrightnessSlider, SaturationSlider } from './ColorPicker.js';
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "reanimated-color-picker",
3
- "version": "0.0.13",
4
- "description": "",
3
+ "version": "0.0.16",
4
+ "description": "Pure JavaScript color picker for react-native",
5
5
  "main": "lib/index.js",
6
6
  "source": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
package/readme.md CHANGED
@@ -13,6 +13,8 @@
13
13
 
14
14
  ![Example_2](https://github.com/alabsi91/reanimated-color-picker/blob/main/images/example_2.png?raw=true)
15
15
 
16
+ ![Example_3](https://github.com/alabsi91/reanimated-color-picker/blob/main/images/example_3.png?raw=true)
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
- - [`<Panel />`](#small_orange_diamondpanel-).
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, { Panel, Swatches, Preview, OpacitySlider, HueSlider } from 'reanimated-color-picker';
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
- <Panel />
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:`<Panel />`
175
+ ### :small_orange_diamond:`<Panel1 />`
176
+
177
+ ![panel1](https://github.com/alabsi91/reanimated-color-picker/blob/main/images/panel1.png?raw=true)
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
- ![panel](https://github.com/alabsi91/reanimated-color-picker/blob/main/images/panel.png?raw=true)
190
+ ![panel2](https://github.com/alabsi91/reanimated-color-picker/blob/main/images/panel2.png?raw=true)
175
191
 
176
- - A square-shaped slider used for changing the color's brightness and saturation.
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
  | :-------- | :----: | :-----: | :---------------------------------------- |