import { useCallback, useState } from 'react'; import { TransitionMotion, spring } from 'react-motion'; import { reduceMotion } from '../initial_state'; import ShortNumber from './short_number'; const obfuscatedCount = (count: number) => { if (count < 0) { return 0; } else if (count <= 1) { return count; } else { return '1+'; } }; interface Props { value: number; obfuscate?: boolean; } export const AnimatedNumber: React.FC = ({ value, obfuscate }) => { const [previousValue, setPreviousValue] = useState(value); const [direction, setDirection] = useState<1 | -1>(1); if (previousValue !== value) { setPreviousValue(value); setDirection(value > previousValue ? 1 : -1); } const willEnter = useCallback(() => ({ y: -1 * direction }), [direction]); const willLeave = useCallback( () => ({ y: spring(1 * direction, { damping: 35, stiffness: 400 }) }), [direction] ); if (reduceMotion) { return obfuscate ? ( <>{obfuscatedCount(value)} ) : ( ); } const styles = [ { key: `${value}`, data: value, style: { y: spring(0, { damping: 35, stiffness: 400 }) }, }, ]; return ( {(items) => ( {items.map(({ key, data, style }) => ( 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)`, }} > {obfuscate ? ( obfuscatedCount(data as number) ) : ( )} ))} )} ); };