import React, { useEffect, useRef } from 'react'; import { Animated, View } from 'react-native'; import { BadgeDotProps } from './types'; import styles from './styles'; const DURATION = 500; const BadgeDotAnimation = ({ size, style }: BadgeDotProps) => { // Refs for animated values const scaleAnim = useRef(new Animated.Value(1)).current; const waveScaleAnim = useRef(new Animated.Value(1)).current; const waveOpacityAnim = useRef(new Animated.Value(0)).current; const dotStyle = size === 'small' ? styles.dotAnimationSmall : styles.dotAnimation; const waveStyle = size === 'small' ? styles.waveSmall : styles.wave; useEffect(() => { // Infinite loop animation for the scale and wave effect const animation = Animated.loop( Animated.parallel([ // Dot pulse animation Animated.sequence([ Animated.spring(scaleAnim, { toValue: 1, // Scale up slightly friction: 5, // Controls the "bounciness" of the spring tension: 30, // Controls the "stiffness" of the spring useNativeDriver: true, }), Animated.spring(scaleAnim, { toValue: 1.1, friction: 5, tension: 30, useNativeDriver: true, }), ]), // Wave animation Animated.sequence([ Animated.timing(waveScaleAnim, { toValue: 2.5, duration: DURATION * 3, useNativeDriver: true, }), Animated.timing(waveScaleAnim, { toValue: 1, // Reset wave size duration: 0, useNativeDriver: true, }), ]), // Wave opacity animation Animated.sequence([ Animated.timing(waveOpacityAnim, { toValue: 0.3, // Wave becomes visible duration: DURATION * 2, useNativeDriver: true, }), Animated.timing(waveOpacityAnim, { toValue: 0, // Wave fades out duration: DURATION, useNativeDriver: true, }), ]), ]), ); animation.start(); return () => { animation.stop(); }; }, [scaleAnim, waveOpacityAnim, waveScaleAnim]); return ( {/* Wave Animation */} {/* Dot Animation */} ); }; export default BadgeDotAnimation;