import React, { ReactNode } from "react"; import { ColorVariantType } from "../../types/colors"; /** * Defines the props of the component. * @params id - Id to identify uniquely the component * @params children - Content of the component. * @params align - Text-align on the component. * @params color - Color of the component. It supports those theme colors that make sense for this component. * @params variant - Component used for the root node. Either a string to use a HTML element or a component. * @params whitespace - White space to apply to the component. * @params className - Override or extend the styles applied to the component. */ export type TypographySizeType = "xs" | "sm" | "md" | "lg" | "xl" | "2xl"; export type TypographyWeightType = "normal" | "medium" | "semibold" | "bold"; export type TypographyTextType = "display" | "text"; const typographySizes = ["xs", "sm", "md", "lg", "xl", "2xl"]; const typographyWeights = [ "thin", "extralight", "light", "normal", "medium", "semibold", "bold", "extrabold", "black", ]; const compare = (array: string[], a: string, b: string) => { const aIndex = array.findIndex(v => v === a); const bIndex = array.findIndex(v => v === b); return aIndex === bIndex ? 0 : aIndex < bIndex ? -1 : 1; }; const isGreaterSizeThan = (a: TypographySizeType, b: TypographySizeType) => compare(typographySizes, a, b) === 1; const isGreaterWeightThan = ( a: TypographyWeightType, b: TypographyWeightType ) => compare(typographyWeights, a, b) === 1; export interface TypographyProps { children: ReactNode; className?: string; color?: ColorVariantType; variant?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span"; size?: TypographySizeType; weight?: TypographyWeightType; type?: TypographyTextType; } /** * @param {TypographyProps} props * @returns Typography component * @description This component is used to render text * @example Heading 1 */ export function Typography({ children, color = "gray-900", variant = "h1", size = "md", weight = "normal", type = "text", className = "", ...restProps }: TypographyProps) { const isMediumOrAboveDisplay = type === "display" && isGreaterSizeThan(size, "sm"); const fontFamily = isMediumOrAboveDisplay ? "font-eudoxus-sans" : "font-inter"; const weightIndex = typographyWeights.findIndex(w => w === weight); const fontWeight = isMediumOrAboveDisplay && isGreaterWeightThan(weight, "medium") && weightIndex !== typographyWeights.length - 1 ? typographyWeights[weightIndex + 1] : weight; const classes = `text-${color} text-${ type === "display" ? "d" : "t" }-${size} font-${fontWeight} ${fontFamily} ${className}`; return React.createElement( variant, { ...restProps, className: classes, }, children ); } export default Typography;