91 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { memo } from 'react';
 | |
| 
 | |
| import { FormattedMessage, FormattedNumber } from 'react-intl';
 | |
| 
 | |
| import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers';
 | |
| 
 | |
| type ShortNumberRenderer = (
 | |
|   displayNumber: JSX.Element,
 | |
|   pluralReady: number,
 | |
| ) => JSX.Element;
 | |
| 
 | |
| interface ShortNumberProps {
 | |
|   value: number;
 | |
|   renderer?: ShortNumberRenderer;
 | |
|   children?: ShortNumberRenderer;
 | |
| }
 | |
| 
 | |
| export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({
 | |
|   value,
 | |
|   renderer,
 | |
|   children,
 | |
| }) => {
 | |
|   const shortNumber = toShortNumber(value);
 | |
|   const [, division] = shortNumber;
 | |
| 
 | |
|   if (children && renderer) {
 | |
|     console.warn(
 | |
|       'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.',
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   const customRenderer = children ?? renderer ?? null;
 | |
| 
 | |
|   const displayNumber = <ShortNumberCounter value={shortNumber} />;
 | |
| 
 | |
|   return (
 | |
|     customRenderer?.(displayNumber, pluralReady(value, division)) ??
 | |
|     displayNumber
 | |
|   );
 | |
| };
 | |
| export const ShortNumber = memo(ShortNumberRenderer);
 | |
| 
 | |
| interface ShortNumberCounterProps {
 | |
|   value: number[];
 | |
| }
 | |
| const ShortNumberCounter: React.FC<ShortNumberCounterProps> = ({ value }) => {
 | |
|   const [rawNumber, unit, maxFractionDigits = 0] = value;
 | |
| 
 | |
|   const count = (
 | |
|     <FormattedNumber
 | |
|       value={rawNumber}
 | |
|       maximumFractionDigits={maxFractionDigits}
 | |
|     />
 | |
|   );
 | |
| 
 | |
|   const values = { count, rawNumber };
 | |
| 
 | |
|   switch (unit) {
 | |
|     case DECIMAL_UNITS.THOUSAND: {
 | |
|       return (
 | |
|         <FormattedMessage
 | |
|           id='units.short.thousand'
 | |
|           defaultMessage='{count}K'
 | |
|           values={values}
 | |
|         />
 | |
|       );
 | |
|     }
 | |
|     case DECIMAL_UNITS.MILLION: {
 | |
|       return (
 | |
|         <FormattedMessage
 | |
|           id='units.short.million'
 | |
|           defaultMessage='{count}M'
 | |
|           values={values}
 | |
|         />
 | |
|       );
 | |
|     }
 | |
|     case DECIMAL_UNITS.BILLION: {
 | |
|       return (
 | |
|         <FormattedMessage
 | |
|           id='units.short.billion'
 | |
|           defaultMessage='{count}B'
 | |
|           values={values}
 | |
|         />
 | |
|       );
 | |
|     }
 | |
|     // Not sure if we should go farther - @Sasha-Sorokin
 | |
|     default:
 | |
|       return count;
 | |
|   }
 | |
| };
 |