import { useState, useRef, useEffect, useMemo } from 'react'; import { Animated, StyleSheet, View } from 'react-native'; import type { IconProps } from './types'; import Icon, { styles as iconStyles } from './Icon'; type Props = IconProps; const CrossFadeIcon = ({ color, size, name, style, ...rest }: Omit) => { // const { animationScale: scale } = useComponentStyles('Icon', style); const { animationScale: scale } = iconStyles.root; const [currentIcon, setCurrentIcon] = useState(name); const [previousIcon, setPreviousIcon] = useState(null); const { current: fade } = useRef(new Animated.Value(1)); useEffect(() => { if (currentIcon !== name) { setPreviousIcon(() => currentIcon); setCurrentIcon(() => name); } }, [currentIcon, name]); useEffect(() => { if (previousIcon && previousIcon !== currentIcon) { fade.setValue(1); Animated.timing(fade, { duration: scale * 200, toValue: 0, useNativeDriver: true, }).start(); } }, [currentIcon, previousIcon, fade, scale]); const opacityPrev = fade; const opacityNext = previousIcon ? fade.interpolate({ inputRange: [0, 1], outputRange: [1, 0], }) : 1; const rotatePrev = fade.interpolate({ inputRange: [0, 1], outputRange: ['-90deg', '0deg'], }); const rotateNext = previousIcon ? fade.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '-180deg'], }) : '0deg'; const containerStyles = useMemo( () => [ styles.content, style, { height: size, width: size, }, ], [size, style], ); const prevIconStyles = useMemo( () => [ styles.icon, { opacity: opacityPrev, transform: [{ rotate: rotatePrev }], }, ], [opacityPrev, rotatePrev], ); const nextIconStyles = useMemo( () => [ styles.icon, { opacity: opacityNext, transform: [{ rotate: rotateNext }], }, ], [opacityNext, rotateNext], ); return ( {previousIcon ? ( ) : null} ); }; const styles = StyleSheet.create({ content: { alignItems: 'center', justifyContent: 'center', }, icon: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, }, }); export default CrossFadeIcon;