11import { css } from '@emotion/react'
22import styled from '@emotion/styled'
33import React , { ElementType } from 'react'
4- import { SolvedTheme } from '../styles'
4+ import { SolvedTheme , solvedThemes } from '../styles'
55import { PC , PP , PR } from '../types/PolymorphicElementProps'
66
77const variants = ( theme : SolvedTheme ) =>
@@ -85,10 +85,10 @@ const variants = (theme: SolvedTheme) =>
8585 margin-inline-end : 0px ;
8686 ` ,
8787 small : css `
88- font-size : small ;
88+ font-size : 75 % ;
8989 ` ,
9090 smaller : css `
91- font-size : smaller ;
91+ font-size : 65 % ;
9292 ` ,
9393 tabular : css `
9494 font-feature-settings : 'tnum' ;
@@ -104,7 +104,13 @@ const variants = (theme: SolvedTheme) =>
104104 ` ,
105105 } as const )
106106
107- export type TypoVariant = keyof ReturnType < typeof variants >
107+ const variantKeys = Object . keys ( variants ( solvedThemes . light ) )
108+
109+ type VariantsObject = ReturnType < typeof variants >
110+ type OptionalVariables = {
111+ [ key in keyof VariantsObject ] : boolean
112+ }
113+ export type TypoVariant = keyof VariantsObject
108114
109115const asMap = {
110116 h1 : 'h1' ,
@@ -118,23 +124,18 @@ const asMap = {
118124} as const
119125
120126interface TypoContainerProps {
121- variant : TypoVariant | TypoVariant [ ]
127+ variant : TypoVariant [ ]
122128}
123129
124130const TypoContainer = styled . span < TypoContainerProps > `
125- ${ ( { theme, variant } ) =>
126- typeof variant === 'string'
127- ? variants ( theme ) [ variant ]
128- : variant . map ( ( v ) => variants ( theme ) [ v ] ) }
131+ ${ ( { theme, variant } ) => variant . map ( ( v ) => variants ( theme ) [ v ] ) }
129132`
130133
131- export interface TypoProps {
134+ export type TypoProps = {
132135 variant ?: TypoVariant | TypoVariant [ ]
133- }
136+ } & OptionalVariables
134137
135- const firstVariant = (
136- variant ?: TypoVariant | TypoVariant [ ]
137- ) : TypoVariant | undefined => {
138+ const firstVariant = ( variant ?: TypoVariant [ ] ) : TypoVariant | undefined => {
138139 if ( typeof variant === 'string' ) return variant
139140 if ( Array . isArray ( variant ) && variant . length > 0 ) return variant [ 0 ]
140141 return undefined
@@ -144,12 +145,30 @@ export const Typo: PC<'span', TypoProps> = React.forwardRef(
144145 < T extends ElementType > ( props : PP < T , TypoProps > , ref ?: PR < T > ) => {
145146 const { variant = [ ] , as, ...rest } = props
146147
148+ const calculatedVariants = [
149+ ...( typeof variant === 'string' ? [ variant ] : variant ) ,
150+ ...Object . entries ( rest )
151+ . filter (
152+ ( [ k , v ] ) => variantKeys . includes ( k ) && typeof v === 'boolean' && v
153+ )
154+ . map ( ( [ k ] ) => k ) ,
155+ ] as TypoVariant [ ]
156+
147157 // TODO types are wrong when `as` is inferred by variant
148158 const calculatedAs =
149- as || asMap [ firstVariant ( variant ) ?? 'default' ] || 'span'
159+ as || asMap [ firstVariant ( calculatedVariants ) ?? 'default' ] || 'span'
160+
161+ const filteredRest = Object . fromEntries (
162+ Object . entries ( rest ) . filter ( ( [ k ] ) => ! variantKeys . includes ( k ) )
163+ )
150164
151165 return (
152- < TypoContainer ref = { ref } as = { calculatedAs } variant = { variant } { ...rest } />
166+ < TypoContainer
167+ ref = { ref }
168+ as = { calculatedAs }
169+ variant = { calculatedVariants }
170+ { ...filteredRest }
171+ />
153172 )
154173 }
155174)
0 commit comments