import { FC } from 'react'; import { RendererBgColor } from '../components/TokenRenderers/RendererBgColor'; import { RendererBorderColor } from '../components/TokenRenderers/RendererBorderColor'; import { RendererBorderImage } from '../components/TokenRenderers/RendererBorderImage'; import { RendererBorderRadius } from '../components/TokenRenderers/RendererBorderRadius'; import { RendererBorderWidth } from '../components/TokenRenderers/RendererBorderWidth'; import { RendererBoxShadow } from '../components/TokenRenderers/RendererBoxShadow'; import { RendererBrightness } from '../components/TokenRenderers/RendererBrightness'; import { RendererFgColor } from '../components/TokenRenderers/RendererFgColor'; import { RendererFontFamily } from '../components/TokenRenderers/RendererFontFamily'; import { RendererFontSize } from '../components/TokenRenderers/RendererFontSize'; import { RendererFontStyle } from '../components/TokenRenderers/RendererFontStyle'; import { RendererFontWeight } from '../components/TokenRenderers/RendererFontWeight'; import { RendererHeight } from '../components/TokenRenderers/RendererHeight'; import { RendererLetterSpacing } from '../components/TokenRenderers/RendererLetterSpacing'; import { RendererLineHeightPixels } from '../components/TokenRenderers/RendererLineHeightPixels'; import { RendererLineHeightRatio } from '../components/TokenRenderers/RendererLineHeightRatio'; import { RendererOutlineColor } from '../components/TokenRenderers/RendererOutlineColor'; import { RendererOutlineOffset } from '../components/TokenRenderers/RendererOutlineOffset'; import { RendererOutlineWidth } from '../components/TokenRenderers/RendererOutlineWidth'; import { RendererPaletteItem } from '../components/TokenRenderers/RendererPaletteItem'; import { RendererProps } from '../components/TokenRenderers/RendererProps'; import { RendererSize } from '../components/TokenRenderers/RendererSize'; import { RendererSpace } from '../components/TokenRenderers/RendererSpace'; import { RendererTextDecoration } from '../components/TokenRenderers/RendererTextDecoration'; import { RendererDuration } from '../components/TokenRenderers/RenderDuration'; import { RendererEasing } from '../components/TokenRenderers/RenderEasing'; import { ExtendedToken } from '../types'; import { RendererTransition } from '../components/TokenRenderers/RenderTransition'; import { RendererEasingCoordinate } from '../components/TokenRenderers/RendererEasingCoordinate'; import { RendererBackground } from '../components/TokenRenderers/RendererBackground'; type TokenRenderer = { renderer: FC; }; /** * pick a type for root tokens */ const typeFromPrefix: Record = { 'icon.size': 'size', spacing: 'space', sizing: 'space', radius: 'borderRadius', 'dsInternalPrimitive.button.borderWeight': 'borderWidth', 'icon.fieldLayout.width': 'horizontalPadding', 'icon.fieldLayout.height': 'horizontalPadding', background: 'color', 'color.border.ai.button.borderImage': 'borderImage', 'color.border.ai.surface.borderImage': 'borderImage', 'color.background.ai.surface.linearGradient': 'background', color: 'color', 'spinner.icon.color': 'color', 'dsInternalPrimitive.color': 'color', 'exp.color': 'color', 'badge.base.color': 'color', 'badge.accent': 'color', content: 'color', elevation: 'boxShadow', // TODO: create a rendered similar to https://ethercreative.github.io/react-native-shadow-generator/ dropShadow: 'boxShadow', 'motion.components.interaction': 'transition', 'calloutBanner.background': 'background', 'alertBanner.background': 'background', }; const suffixMap: Record = { color: 'fgColor', lineHeight: 'lineHeightPixels', shadow: 'boxShadow', borderImage: 'borderImage', offset: 'size', x1: 'easingCoordinate', y1: 'easingCoordinate', x2: 'easingCoordinate', y2: 'easingCoordinate', short: 'duration', function: 'easing', functionName: 'easing', }; const renderers: Record = { background: { renderer: RendererBackground, }, bgColor: { renderer: RendererBgColor, }, borderColor: { renderer: RendererBorderColor, }, borderImage: { renderer: RendererBorderImage, }, borderRadius: { renderer: RendererBorderRadius, }, brightness: { renderer: RendererBrightness, }, color: { renderer: RendererPaletteItem, }, fgColor: { renderer: RendererFgColor, }, fontFamily: { renderer: RendererFontFamily, }, fontSize: { renderer: RendererFontSize, }, fontWeight: { renderer: RendererFontWeight, }, fontStyle: { renderer: RendererFontStyle, }, letterSpacing: { renderer: RendererLetterSpacing, }, gap: { renderer: RendererSpace, }, height: { renderer: RendererHeight, }, horizontalPadding: { renderer: RendererSize, }, lineHeightRatio: { renderer: RendererLineHeightRatio, }, lineHeightPixels: { renderer: RendererLineHeightPixels, }, outlineColor: { renderer: RendererOutlineColor, }, outlineOffset: { renderer: RendererOutlineOffset, }, outlineWidth: { renderer: RendererOutlineWidth, }, borderWidth: { renderer: RendererBorderWidth, }, padding: { renderer: RendererSize, }, size: { renderer: RendererSize, }, space: { renderer: RendererSpace, }, boxShadow: { renderer: RendererBoxShadow, }, typeface: { renderer: RendererFontFamily, }, verticalPadding: { renderer: RendererSize, }, textDecoration: { renderer: RendererTextDecoration, }, duration: { renderer: RendererDuration, }, easing: { renderer: RendererEasing, }, transition: { renderer: RendererTransition, }, easingCoordinate: { renderer: RendererEasingCoordinate, }, }; function getTypeFromPrefix(name: string): string | undefined { const match = Object.entries(typeFromPrefix).find(([prefix]) => name.startsWith(prefix)); return match && match[1]; } function getTypeFromSufix(name: string): string | undefined { const sufix = name.split('.').pop() || ''; return sufix in suffixMap ? suffixMap[sufix] : sufix; } function getRenderer(token: ExtendedToken): TokenRenderer | undefined { const type = getTypeFromPrefix(token.name) || getTypeFromSufix(token.name) || ''; return renderers[type]; } export const tokenRenderer = (token: ExtendedToken): TokenRenderer => { const renderer = getRenderer(token); if (!renderer) { throw new Error(`No renderer for token "${token.name}".`); } return renderer; };