import React, { HTMLAttributes } from 'react';
import styled, { css } from 'styled-components';
import classnames from 'classnames';
import Text from '../../atoms/Text/Text';
import Heading from '../../atoms/Heading/Heading';
import { typography } from '../../../constants';
interface StyleProps {
/**
* font size styling for title
* @default `body`
*/
labelFontSize?: keyof typeof typography.sizes.text;
/**
* font size styling for number
* @default `main`
*/
numberFontSize?: 'main' | 'large' | 'lead' | 'small';
/**
* Position for the numerical value
* @default `top`
*/
numberPosition?: 'top' | 'bottom' | 'right' | 'left';
/**
* Override font weight for number and set to semi bold
*/
semiBold?: boolean;
/**
* Where the rendered text should be aligned to.
* @default 'center'
*/
align?: 'left' | 'right' | 'center';
}
type ContainerProps = Pick;
type TitleProps = Pick;
type NumberProps = Pick;
const numberFontStyles = {
main: 'h1',
large: 'h2',
lead: 'h4',
small: 'h5',
};
export interface NumberTextProps extends HTMLAttributes, StyleProps {
title?: string;
value?: number;
fallback?: string;
formatterOptions?: Intl.NumberFormatOptions;
titleClassName?: string;
}
const Container = styled.div>`
display: flex;
align-items: ${({ align }) => {
switch (align) {
case 'left':
return 'flex-start';
case 'right':
return 'flex-end';
default:
return align;
}
}};
${({ numberPosition }) => {
if (numberPosition === 'left' || numberPosition === 'right') {
return css`
flex-direction: row;
justify-content: space-between;
align-items: center;
`;
} else {
return css`
flex-direction: column;
justify-content: center;
`;
}
}}
`;
const Title = styled(Text)>`
order: ${({ numberPosition }) => (numberPosition === 'top' || numberPosition === 'left' ? 2 : 1)};
`;
const Value = styled(Heading).attrs(({ numberFontSize = 'main' }: NumberProps) => ({
size: numberFontStyles[numberFontSize],
}))>`
order: ${({ numberPosition }) => (numberPosition === 'top' || numberPosition === 'left' ? 1 : 2)};
${({ semiBold }) => (semiBold ? 'font-weight: 600' : null)}
`;
const NumberText = ({
title,
value,
fallback,
numberPosition = 'top',
labelFontSize = 'body',
numberFontSize = 'main',
formatterOptions = {},
align = 'center',
semiBold = false,
titleClassName,
...rest
}: NumberTextProps) => {
const numberFormatter = (value: number) => new Intl.NumberFormat('en-GB', formatterOptions).format(value);
const valueClassNames = classnames({
'mt-2': numberPosition === 'bottom' && numberFontSize === 'main',
'mt-1': numberPosition === 'bottom' && numberFontSize === 'small',
'mb-2': numberPosition === 'top' && numberFontSize === 'main',
'mb-1': numberPosition === 'top' && numberFontSize === 'small',
'pr-2': numberPosition === 'left' && numberFontSize === 'main',
'pr-1': numberPosition === 'left' && numberFontSize === 'small',
'pl-2': numberPosition === 'right' && numberFontSize === 'main',
'pl-1': numberPosition === 'right' && numberFontSize === 'small',
});
return (
{title ? (
{title}
) : null}
{value !== undefined ? numberFormatter(value) : fallback}
);
};
export default NumberText;