@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 {
|
|
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(
|
|
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 = (
|
|
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(
|
|
46
|
+
const [interpolatedColor, setInterpolatedColor] = useState(
|
|
47
|
+
!animatedConfig
|
|
48
|
+
? getInterpolatedColor(colors, progressPercentage)
|
|
49
|
+
: colors[0],
|
|
50
|
+
);
|
|
36
51
|
|
|
37
52
|
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
}, [
|
|
73
|
+
}, [progressPercentage, colors, animatedPercentage, animatedConfig]);
|
|
58
74
|
|
|
59
75
|
return interpolatedColor;
|
|
60
76
|
};
|
|
61
77
|
|
|
62
78
|
export const useColorAndPercentageInterpolation = (
|
|
63
79
|
colors,
|
|
64
|
-
|
|
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(
|
|
69
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
}, [
|
|
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
|
+
};
|