@shoutem/ui 8.1.0-rc.1 → 8.1.1-rc.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.
@@ -2,20 +2,30 @@
2
2
  import React from 'react';
3
3
  import _ from 'lodash';
4
4
  import PropTypes from 'prop-types';
5
+ import { DEFAULT_PROGRESS_COLORS } from '../../const';
5
6
  import { useColorAndPercentageInterpolation } from '../../hooks';
6
- import { DEFAULT_PROGRESS_COLORS, PROGRESS_RING_DEFAULT_PROPS } from './const';
7
+ import { PROGRESS_RING_DEFAULT_PROPS } from './const';
7
8
  import ProgressRing from './ProgressRing';
8
9
 
9
10
  const AnimatedProgressRing = props => {
10
11
  const {
11
12
  progressPercentage = PROGRESS_RING_DEFAULT_PROPS.progressPercentage,
12
13
  progressColors = DEFAULT_PROGRESS_COLORS,
14
+ animationConfig = {
15
+ toValue: progressPercentage,
16
+ duration: 1000 * (progressPercentage / 100), // 100% will animate for 1s, 50% for 0.5s etc.
17
+ useNativeDriver: true,
18
+ },
13
19
  } = props;
14
20
 
15
21
  const {
16
22
  interpolatedColor,
17
23
  interpolatedPercentage,
18
- } = useColorAndPercentageInterpolation(progressColors, progressPercentage);
24
+ } = useColorAndPercentageInterpolation(
25
+ progressColors,
26
+ progressPercentage,
27
+ animationConfig,
28
+ );
19
29
 
20
30
  return (
21
31
  <ProgressRing
@@ -1,12 +1,3 @@
1
- export const DEFAULT_PROGRESS_COLORS = [
2
- '#FF0000', // Red
3
- '#FF4500', // Orange-Red
4
- '#FFA500', // Orange
5
- '#FFD700', // Yellow
6
- '#ADFF2F', // Yellow-Green
7
- '#90EE90', // Light Green
8
- ];
9
-
10
1
  export const PROGRESS_RING_DEFAULT_PROPS = {
11
2
  progressLineWidth: 10,
12
3
  backgroundLineWidth: 10,
package/const.js CHANGED
@@ -18,3 +18,12 @@ export {
18
18
  NOTCH_AREA_HEIGHT,
19
19
  STATUS_BAR_OFFSET,
20
20
  };
21
+
22
+ export const DEFAULT_PROGRESS_COLORS = [
23
+ '#FF0000', // Red
24
+ '#FF4500', // Orange-Red
25
+ '#FFA500', // Orange
26
+ '#FFD700', // Yellow
27
+ '#ADFF2F', // Yellow-Green
28
+ '#90EE90', // Light Green
29
+ ];
@@ -1,5 +1,8 @@
1
+ /* eslint-disable consistent-return */
2
+ /* eslint-disable no-bitwise */
1
3
  import { useEffect, useRef, useState } from 'react';
2
4
  import { Animated } from 'react-native';
5
+ import { DEFAULT_PROGRESS_COLORS } from '../const';
3
6
 
4
7
  const resolveInputRange = colors => {
5
8
  if (colors.length === 1) {
@@ -29,17 +32,30 @@ const resolveInterpolationRange = colors => {
29
32
  };
30
33
  };
31
34
 
32
- export const useColorInterpolation = (colors, progressPerecentage) => {
35
+ export const useColorInterpolation = (
36
+ colors,
37
+ progressPercentage,
38
+ animatedConfig = {
39
+ toValue: progressPercentage,
40
+ duration: 1000 * (progressPercentage / 100), // 100% will animate for 1s, 50% for 0.5s etc.
41
+ useNativeDriver: true,
42
+ },
43
+ ) => {
33
44
  const animatedPercentage = useRef(new Animated.Value(0)).current;
34
45
 
35
- const [interpolatedColor, setInterpolatedColor] = useState(colors[0]);
46
+ const [interpolatedColor, setInterpolatedColor] = useState(
47
+ !animatedConfig
48
+ ? getInterpolatedColor(colors, progressPercentage)
49
+ : colors[0],
50
+ );
36
51
 
37
52
  useEffect(() => {
38
- Animated.timing(animatedPercentage, {
39
- toValue: progressPerecentage,
40
- duration: 1000,
41
- useNativeDriver: false, // Color interpolation requires native driver to be false
42
- }).start();
53
+ if (!animatedConfig) {
54
+ setInterpolatedColor(getInterpolatedColor(colors, progressPercentage));
55
+ return;
56
+ }
57
+
58
+ Animated.timing(animatedPercentage, animatedConfig).start();
43
59
 
44
60
  // Listen to animatedPercentage value changes and update the interpolated color
45
61
  const listener = animatedPercentage.addListener(() => {
@@ -54,26 +70,38 @@ export const useColorInterpolation = (colors, progressPerecentage) => {
54
70
  return () => {
55
71
  animatedPercentage.removeListener(listener);
56
72
  };
57
- }, [progressPerecentage, colors, animatedPercentage]);
73
+ }, [progressPercentage, colors, animatedPercentage, animatedConfig]);
58
74
 
59
75
  return interpolatedColor;
60
76
  };
61
77
 
62
78
  export const useColorAndPercentageInterpolation = (
63
79
  colors,
64
- progressPerecentage,
80
+ progressPercentage,
81
+ animatedConfig = {
82
+ toValue: progressPercentage,
83
+ duration: 1000 * (progressPercentage / 100), // 100% will animate for 1s, 50% for 0.5s etc.
84
+ useNativeDriver: true,
85
+ },
65
86
  ) => {
66
87
  const animatedPercentage = useRef(new Animated.Value(0)).current;
67
88
 
68
- const [interpolatedColor, setInterpolatedColor] = useState(colors[0]);
69
- const [interpolatedPercentage, setInterpolatedPercentage] = useState(0);
89
+ const [interpolatedColor, setInterpolatedColor] = useState(
90
+ !animatedConfig
91
+ ? getInterpolatedColor(colors, progressPercentage)
92
+ : colors[0],
93
+ );
94
+ const [interpolatedPercentage, setInterpolatedPercentage] = useState(
95
+ !animatedConfig ? progressPercentage : 0,
96
+ );
70
97
 
71
98
  useEffect(() => {
72
- Animated.timing(animatedPercentage, {
73
- toValue: progressPerecentage,
74
- duration: 1000,
75
- useNativeDriver: false, // Color interpolation requires native driver to be false
76
- }).start();
99
+ if (!animatedConfig) {
100
+ setInterpolatedPercentage(progressPercentage);
101
+ return;
102
+ }
103
+
104
+ Animated.timing(animatedPercentage, animatedConfig).start();
77
105
 
78
106
  // Listen to animatedPercentage value changes and update the interpolated color
79
107
  const listener = animatedPercentage.addListener(({ value }) => {
@@ -89,7 +117,61 @@ export const useColorAndPercentageInterpolation = (
89
117
  return () => {
90
118
  animatedPercentage.removeListener(listener);
91
119
  };
92
- }, [progressPerecentage, colors, animatedPercentage]);
120
+ }, [progressPercentage, colors, animatedPercentage, animatedConfig]);
93
121
 
94
122
  return { interpolatedColor, interpolatedPercentage };
95
123
  };
124
+
125
+ /**
126
+ * Convert hex color to RGB array
127
+ */
128
+ const hexToRgb = hex => {
129
+ const bigint = parseInt(hex.replace('#', ''), 16);
130
+ return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
131
+ };
132
+
133
+ /**
134
+ * Convert RGB array to hex color
135
+ */
136
+ const rgbToHex = ([r, g, b]) => {
137
+ return `#${((1 << 24) + (r << 16) + (g << 8) + b)
138
+ .toString(16)
139
+ .slice(1)
140
+ .toUpperCase()}`;
141
+ };
142
+
143
+ /**
144
+ * Linearly interpolate between two numbers
145
+ */
146
+ const lerp = (a, b, t) => a + (b - a) * t;
147
+
148
+ /**
149
+ * Get interpolated color based on percentage
150
+ */
151
+ export const getInterpolatedColor = (
152
+ colors = DEFAULT_PROGRESS_COLORS,
153
+ percentage,
154
+ ) => {
155
+ const numColors = colors.length;
156
+
157
+ if (percentage <= 0) return colors[0];
158
+ if (percentage >= 100) return colors[numColors - 1];
159
+
160
+ const totalSegments = numColors - 1; // Total segments between colors
161
+ const segment = (percentage / 100) * totalSegments; // Determine segment index as float
162
+ const startIndex = Math.floor(segment); // Start color index
163
+ const endIndex = startIndex + 1; // End color index
164
+ const t = segment - startIndex; // Interpolation factor
165
+
166
+ const startColor = hexToRgb(colors[startIndex]);
167
+ const endColor = hexToRgb(colors[endIndex]);
168
+
169
+ // Interpolate each RGB component
170
+ const interpolatedColor = [
171
+ Math.round(lerp(startColor[0], endColor[0], t)),
172
+ Math.round(lerp(startColor[1], endColor[1], t)),
173
+ Math.round(lerp(startColor[2], endColor[2], t)),
174
+ ];
175
+
176
+ return rgbToHex(interpolatedColor);
177
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoutem/ui",
3
- "version": "8.1.0-rc.1",
3
+ "version": "8.1.1-rc.0",
4
4
  "description": "Styleable set of components for React Native applications",
5
5
  "scripts": {
6
6
  "lint": "eslint .",