import * as React from 'react'; import { Animated, StyleSheet, View } from 'react-native'; import { withTheme } from '../core/theming'; import isNativeAnimationSupported from '../utils/isNativeAnimationSupported'; import Icon, { IconSource, isEqualIcon, isValidIcon } from './Icon'; type Props = { /** * Icon to display for the `CrossFadeIcon`. */ source: IconSource; /** * Color of the icon. */ color: string; /** * Size of the icon. */ size: number; /** * @optional */ theme: ReactNativePaper.Theme; }; const CrossFadeIcon = ({ color, size, source, theme }: Props) => { const [currentIcon, setCurrentIcon] = React.useState( () => source ); const [previousIcon, setPreviousIcon] = React.useState( null ); const { current: fade } = React.useRef(new Animated.Value(1)); const { scale } = theme.animation; if (currentIcon !== source) { setPreviousIcon(() => currentIcon); setCurrentIcon(() => source); } React.useEffect(() => { if (isValidIcon(previousIcon) && !isEqualIcon(previousIcon, currentIcon)) { fade.setValue(1); Animated.timing(fade, { duration: scale * 200, toValue: 0, useNativeDriver: isNativeAnimationSupported(), }).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'; return ( {previousIcon ? ( ) : null} ); }; export default withTheme(CrossFadeIcon); const styles = StyleSheet.create({ content: { alignItems: 'center', justifyContent: 'center', }, icon: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, }, });