import { CSSProperties } from 'react'; import theme, { Theme } from '../theme'; import { SxKeys, SxObject, SxValues, SystemProperties, ThemeScales, COLORS_MAP, FONT_WEIGHTS_MAP, } from '../components/common'; const aliases: Partial> = { bgColor: 'backgroundColor', m: 'margin', mt: 'marginTop', mr: 'marginRight', mb: 'marginBottom', ml: 'marginLeft', p: 'padding', pt: 'paddingTop', pr: 'paddingRight', pb: 'paddingBottom', pl: 'paddingLeft', }; const scaleNames: Partial> = { backgroundColor: 'colors', borderColor: 'colors', borderRadius: 'radii', borderStyle: 'borderStyles', borderWidth: 'borderWidths', color: 'colors', fontSize: 'fontSizes', fontWeight: 'fontWeights', lineHeight: 'lineHeights', margin: 'space', marginBottom: 'space', marginLeft: 'space', marginRight: 'space', marginTop: 'space', padding: 'space', paddingBottom: 'space', paddingLeft: 'space', paddingRight: 'space', paddingTop: 'space', }; // this is needed since border styles scale does not exist in theme const borderStylesScale = { dotted: 'dotted', dashed: 'dashed', solid: 'solid', }; type AvailableThemeScales = Omit; type Scale = Theme[keyof AvailableThemeScales] | typeof borderStylesScale; function getCamelValue( value: SxValues | undefined, scaleName: keyof ThemeScales ) { switch (scaleName) { case 'colors': return COLORS_MAP[value as keyof typeof COLORS_MAP] ?? value; case 'fontWeights': return FONT_WEIGHTS_MAP[value as keyof typeof FONT_WEIGHTS_MAP] ?? value; default: return value; } } function getCssValue( camelValue: SxValues | undefined, scale: Scale, scaleName: keyof ThemeScales ) { if (camelValue === undefined || !(camelValue in scale)) return camelValue; switch (scaleName) { case 'borderWidths': case 'fontSizes': case 'lineHeights': case 'radii': case 'space': return `${scale[camelValue as keyof Scale]}px`; default: return scale[camelValue as keyof Scale]; } } export default function css(sx: SxObject): CSSProperties { const styleObject: CSSProperties = {}; Object.entries(sx).forEach(([prop, value]) => { const cssProp = aliases[prop as keyof SystemProperties] ?? prop; const scaleName = scaleNames[cssProp as keyof CSSProperties]; if (scaleName === undefined) { styleObject[cssProp as keyof CSSProperties] = value as never; return; } const scale: Scale = scaleName === 'borderStyles' ? borderStylesScale : theme[scaleName]; const camelValue = getCamelValue(value, scaleName); const cssValue = getCssValue(camelValue, scale, scaleName); styleObject[cssProp as keyof CSSProperties] = cssValue as never; }); return styleObject; }