short_number.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { memo } from 'react';
  2. import { FormattedMessage, FormattedNumber } from 'react-intl';
  3. import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers';
  4. type ShortNumberRenderer = (
  5. displayNumber: JSX.Element,
  6. pluralReady: number,
  7. ) => JSX.Element;
  8. interface ShortNumberProps {
  9. value: number;
  10. renderer?: ShortNumberRenderer;
  11. children?: ShortNumberRenderer;
  12. }
  13. export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({
  14. value,
  15. renderer,
  16. children,
  17. }) => {
  18. const shortNumber = toShortNumber(value);
  19. const [, division] = shortNumber;
  20. if (children && renderer) {
  21. console.warn(
  22. '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.',
  23. );
  24. }
  25. const customRenderer = children ?? renderer ?? null;
  26. const displayNumber = <ShortNumberCounter value={shortNumber} />;
  27. return (
  28. customRenderer?.(displayNumber, pluralReady(value, division)) ??
  29. displayNumber
  30. );
  31. };
  32. export const ShortNumber = memo(ShortNumberRenderer);
  33. interface ShortNumberCounterProps {
  34. value: number[];
  35. }
  36. const ShortNumberCounter: React.FC<ShortNumberCounterProps> = ({ value }) => {
  37. const [rawNumber, unit, maxFractionDigits = 0] = value;
  38. const count = (
  39. <FormattedNumber
  40. value={rawNumber}
  41. maximumFractionDigits={maxFractionDigits}
  42. />
  43. );
  44. const values = { count, rawNumber };
  45. switch (unit) {
  46. case DECIMAL_UNITS.THOUSAND: {
  47. return (
  48. <FormattedMessage
  49. id='units.short.thousand'
  50. defaultMessage='{count}K'
  51. values={values}
  52. />
  53. );
  54. }
  55. case DECIMAL_UNITS.MILLION: {
  56. return (
  57. <FormattedMessage
  58. id='units.short.million'
  59. defaultMessage='{count}M'
  60. values={values}
  61. />
  62. );
  63. }
  64. case DECIMAL_UNITS.BILLION: {
  65. return (
  66. <FormattedMessage
  67. id='units.short.billion'
  68. defaultMessage='{count}B'
  69. values={values}
  70. />
  71. );
  72. }
  73. // Not sure if we should go farther - @Sasha-Sorokin
  74. default:
  75. return count;
  76. }
  77. };