import * as React from "react"; import { Animated } from "react-native"; import { DefaultTheme, ThemeContext } from "styled-components"; import styled from "styled-components/native"; import Icon, { isValidIcon, isEqualIcon } from "./SvgIcon"; const CrossFadeIconWrapperView = styled.View({ alignItems: "center", justifyContent: "center", }); type Props = { /** * Icon to display for the `CrossFadeIcon`. */ icon: React.ReactElement; /** * Color of the icon. */ color: string; /** * Size of the icon. */ size: number; /** * @optional */ theme?: DefaultTheme; }; const CrossFadeIcon = ({ color, size, icon }: Props) => { const theme = React.useContext(ThemeContext); const [currentIcon, setCurrentIcon] = React.useState( () => icon ); const [previousIcon, setPreviousIcon] = React.useState( null ); const { current: fade } = React.useRef(new Animated.Value(1)); const { scale } = theme.animation; if (currentIcon !== icon) { setPreviousIcon(() => currentIcon); setCurrentIcon(() => icon); } React.useEffect(() => { if (isValidIcon(previousIcon) && !isEqualIcon(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"; return ( {previousIcon ? ( ) : null} ); }; export default CrossFadeIcon;