Rewrite AnimatedNumber component with React hooks (#24559)
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							85b1b45820
						
					
				
				
					commit
					ab740f464a
				
			
							
								
								
									
										58
									
								
								app/javascript/mastodon/components/animated_number.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/javascript/mastodon/components/animated_number.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import React, { useCallback, useState } from 'react';
 | 
			
		||||
import ShortNumber from './short_number';
 | 
			
		||||
import { TransitionMotion, spring } from 'react-motion';
 | 
			
		||||
import { reduceMotion } from '../initial_state';
 | 
			
		||||
 | 
			
		||||
const obfuscatedCount = (count: number) => {
 | 
			
		||||
  if (count < 0) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  } else if (count <= 1) {
 | 
			
		||||
    return count;
 | 
			
		||||
  } else {
 | 
			
		||||
    return '1+';
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  value: number;
 | 
			
		||||
  obfuscate?: boolean;
 | 
			
		||||
}
 | 
			
		||||
export const AnimatedNumber: React.FC<Props> = ({
 | 
			
		||||
  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)}</> : <ShortNumber value={value} />;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const styles = [{
 | 
			
		||||
    key: `${value}`,
 | 
			
		||||
    data: value,
 | 
			
		||||
    style: { y: spring(0, { damping: 35, stiffness: 400 }) },
 | 
			
		||||
  }];
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <TransitionMotion styles={styles} willEnter={willEnter} willLeave={willLeave}>
 | 
			
		||||
      {items => (
 | 
			
		||||
        <span className='animated-number'>
 | 
			
		||||
          {items.map(({ key, data, style }) => (
 | 
			
		||||
            <span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}>{obfuscate ? obfuscatedCount(data) : <ShortNumber value={data} />}</span>
 | 
			
		||||
          ))}
 | 
			
		||||
        </span>
 | 
			
		||||
      )}
 | 
			
		||||
    </TransitionMotion>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default AnimatedNumber;
 | 
			
		||||
		Reference in New Issue
	
	Block a user