import React, { useEffect } from "react"; import { StyleSheet, View } from "react-native"; import Svg, { G, Circle, Defs, LinearGradient, Stop } from "react-native-svg"; import Animated, { useSharedValue, withTiming, useAnimatedProps, withDelay, runOnJS, } from "react-native-reanimated"; import { CircularProgressWithChildProps } from "./types"; const AnimatedCircle = Animated.createAnimatedComponent(Circle); const CircularProgressWithChild: React.FC = ({ value, initialValue = 0, circleBackgroundColor = "transparent", radius = 60, duration = 500, delay = 0, maxValue = 100, strokeLinecap = "round", onAnimationComplete = () => {}, activeStrokeColor = "#2ecc71", activeStrokeSecondaryColor = "", activeStrokeWidth = 10, inActiveStrokeColor = "rgba(0,0,0,0.3)", inActiveStrokeWidth = 10, inActiveStrokeOpacity = 1, children, clockwise = true, }: CircularProgressWithChildProps) => { const animatedValue = useSharedValue(initialValue); const viewBox = radius + Math.max(activeStrokeWidth, inActiveStrokeWidth); const circleCircumference = 2 * Math.PI * radius; const animatedCircleProps = useAnimatedProps(() => { let biggestValue = Math.max(initialValue, maxValue); biggestValue = biggestValue <= 0 ? 1 : biggestValue; const maxPercentage: number = clockwise ? (100 * animatedValue.value) / biggestValue : (100 * -animatedValue.value) / biggestValue; return { strokeDashoffset: circleCircumference - (circleCircumference * maxPercentage) / 100, }; }); useEffect(() => { animatedValue.value = withDelay( delay, withTiming(value, { duration }, (isFinished) => { if (isFinished) { runOnJS(onAnimationComplete)?.(); } }) ); }, [value]); return ( {activeStrokeSecondaryColor ? ( ) : null} {children} ); }; export const styles = StyleSheet.create({ valueContainer: { flex: 1, alignItems: "center", justifyContent: "center", }, }); export default CircularProgressWithChild;