123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import React from 'react';
- import PropTypes from 'prop-types';
- import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers';
- import { FormattedMessage, FormattedNumber } from 'react-intl';
- // @ts-check
- /**
- * @callback ShortNumberRenderer
- * @param {JSX.Element} displayNumber Number to display
- * @param {number} pluralReady Number used for pluralization
- * @returns {JSX.Element} Final render of number
- */
- /**
- * @typedef {object} ShortNumberProps
- * @property {number} value Number to display in short variant
- * @property {ShortNumberRenderer} [renderer]
- * Custom renderer for numbers, provided as a prop. If another renderer
- * passed as a child of this component, this prop won't be used.
- * @property {ShortNumberRenderer} [children]
- * Custom renderer for numbers, provided as a child. If another renderer
- * passed as a prop of this component, this one will be used instead.
- */
- /**
- * Component that renders short big number to a shorter version
- *
- * @param {ShortNumberProps} param0 Props for the component
- * @returns {JSX.Element} Rendered number
- */
- function ShortNumber({ value, renderer, children }) {
- const shortNumber = toShortNumber(value);
- const [, division] = shortNumber;
- // eslint-disable-next-line eqeqeq
- if (children != null && renderer != null) {
- 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.');
- }
- // eslint-disable-next-line eqeqeq
- const customRenderer = children != null ? children : renderer;
- const displayNumber = <ShortNumberCounter value={shortNumber} />;
- // eslint-disable-next-line eqeqeq
- return customRenderer != null
- ? customRenderer(displayNumber, pluralReady(value, division))
- : displayNumber;
- }
- ShortNumber.propTypes = {
- value: PropTypes.number.isRequired,
- renderer: PropTypes.func,
- children: PropTypes.func,
- };
- /**
- * @typedef {object} ShortNumberCounterProps
- * @property {import('../utils/number').ShortNumber} value Short number
- */
- /**
- * Renders short number into corresponding localizable react fragment
- *
- * @param {ShortNumberCounterProps} param0 Props for the component
- * @returns {JSX.Element} FormattedMessage ready to be embedded in code
- */
- function ShortNumberCounter({ value }) {
- const [rawNumber, unit, maxFractionDigits = 0] = value;
- const count = (
- <FormattedNumber
- value={rawNumber}
- maximumFractionDigits={maxFractionDigits}
- />
- );
- let 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;
- }
- }
- ShortNumberCounter.propTypes = {
- value: PropTypes.arrayOf(PropTypes.number),
- };
- export default React.memo(ShortNumber);
|