UNPKG

create-rn-starter-kit

Version:

Interactive CLI for creating modular React Native apps with Expo

291 lines (279 loc) 8.18 kB
// template/src/theme/tokenProcessor.ts // Import all brand tokens statically import lloydsTokens from './brands/lloyds.json'; import brandATokens from './brands/brandA.json'; import brandBTokens from './brands/brandB.json'; // Type definitions for token structure interface TokenValue { value: string; type: string; } interface BrandTokens { global: { colors: { primary: { [key: string]: TokenValue }; neutral: { [key: string]: TokenValue }; accent: { [key: string]: TokenValue }; semantic: { error: TokenValue; success: TokenValue; warning: TokenValue; }; }; spacing: { [key: string]: TokenValue }; borderRadius: { [key: string]: TokenValue }; fontSize: { [key: string]: TokenValue }; fontFamily: { [key: string]: TokenValue }; }; light: { colors: { [key: string]: TokenValue }; }; dark: { colors: { [key: string]: TokenValue }; }; } // Type for the processed theme export interface ProcessedTheme { colors: { primary: { 50: string; 100: string; 500: string; 600: string; 900: string; }; neutral: { 50: string; 100: string; 200: string; 500: string; 900: string; }; semantic: { error: string; success: string; warning: string; }; background: string; surface: string; text: string; textSecondary: string; border: string; accent: string; }; spacing: { xs: number; sm: number; md: number; lg: number; xl: number; }; borderRadius: { sm: number; md: number; lg: number; }; fontSize: { sm: number; base: number; lg: number; xl: number; }; fontFamily: { primary: string; primaryBold: string; primarySemiBold: string; secondary: string; }; textStyles: { // Headings heading: { fontSize: number; fontFamily: string; }; subheading: { fontSize: number; fontFamily: string; }; // Body text body: { fontSize: number; fontFamily: string; }; bodyLarge: { fontSize: number; fontFamily: string; }; bodySmall: { fontSize: number; fontFamily: string; }; // Labels and captions caption: { fontSize: number; fontFamily: string; }; label: { fontSize: number; fontFamily: string; }; labelSmall: { fontSize: number; fontFamily: string; }; // Financial/numbers amount: { fontSize: number; fontFamily: string; }; amountLarge: { fontSize: number; fontFamily: string; }; // Account numbers and codes accountNumber: { fontSize: number; fontFamily: string; }; } } // Available brands export type BrandName = 'lloyds' | 'brandA' | 'brandB'; // Function to get brand tokens synchronously function getBrandTokens(brandName: BrandName): BrandTokens { switch (brandName) { case 'brandA': return brandATokens as BrandTokens; case 'brandB': return brandBTokens as BrandTokens; case 'lloyds': default: return lloydsTokens as BrandTokens; } } // Function to resolve token references like {global.colors.neutral.50} function resolveTokenReference(value: string, tokenData: BrandTokens): string { if (!value.startsWith('{') || !value.endsWith('}')) { return value; } const path = value.slice(1, -1).split('.'); let current: any = tokenData; for (const key of path) { current = current?.[key]; if (!current) { console.warn(`Token reference not found: ${value}`); return value; } } return current.value || current; } // Process tokens for a specific brand and theme (light/dark) - now using JSON files export function processTokens(brandName: BrandName, themeName: 'light' | 'dark'): ProcessedTheme { const tokens = getBrandTokens(brandName); const globalTokens = tokens.global; const themeTokens = tokens[themeName]; return { colors: { primary: { 50: globalTokens.colors.primary['50'].value, 100: globalTokens.colors.primary['100'].value, 500: globalTokens.colors.primary['500'].value, 600: globalTokens.colors.primary['600'].value, 900: globalTokens.colors.primary['900'].value, }, neutral: { 50: globalTokens.colors.neutral['50'].value, 100: globalTokens.colors.neutral['100'].value, 200: globalTokens.colors.neutral['200'].value, 500: globalTokens.colors.neutral['500'].value, 900: globalTokens.colors.neutral['900'].value, }, semantic: { error: globalTokens.colors.semantic.error.value, success: globalTokens.colors.semantic.success.value, warning: globalTokens.colors.semantic.warning.value, }, background: resolveTokenReference(themeTokens.colors.background.value, tokens), surface: resolveTokenReference(themeTokens.colors.surface.value, tokens), text: resolveTokenReference(themeTokens.colors.text.value, tokens), textSecondary: resolveTokenReference(themeTokens.colors.textSecondary.value, tokens), border: resolveTokenReference(themeTokens.colors.border.value, tokens), accent: resolveTokenReference(themeTokens.colors.accent.value, tokens), }, spacing: { xs: parseInt(globalTokens.spacing.xs.value), sm: parseInt(globalTokens.spacing.sm.value), md: parseInt(globalTokens.spacing.md.value), lg: parseInt(globalTokens.spacing.lg.value), xl: parseInt(globalTokens.spacing.xl.value), }, borderRadius: { sm: parseInt(globalTokens.borderRadius.sm.value), md: parseInt(globalTokens.borderRadius.md.value), lg: parseInt(globalTokens.borderRadius.lg.value), }, fontSize: { sm: parseInt(globalTokens.fontSize.sm.value), base: parseInt(globalTokens.fontSize.base.value), lg: parseInt(globalTokens.fontSize.lg.value), xl: parseInt(globalTokens.fontSize.xl.value), }, fontFamily: { primary: globalTokens.fontFamily.primary.value, primaryBold: globalTokens.fontFamily.primaryBold.value, primarySemiBold: globalTokens.fontFamily.primarySemiBold.value, secondary: globalTokens.fontFamily.secondary.value, }, textStyles: { // Headings heading: { fontSize: parseInt(globalTokens.fontSize.xl.value), // ~20px fontFamily: globalTokens.fontFamily.primaryBold.value, }, subheading: { fontSize: parseInt(globalTokens.fontSize.lg.value), // ~18px fontFamily: globalTokens.fontFamily.primarySemiBold.value, }, // Body text variations body: { fontSize: parseInt(globalTokens.fontSize.base.value), // ~16px fontFamily: globalTokens.fontFamily.secondary.value, }, bodyLarge: { fontSize: parseInt(globalTokens.fontSize.lg.value), // ~18px fontFamily: globalTokens.fontFamily.secondary.value, }, bodySmall: { fontSize: 14, // Between sm and base fontFamily: globalTokens.fontFamily.secondary.value, }, // Labels and captions caption: { fontSize: parseInt(globalTokens.fontSize.sm.value), // ~12px fontFamily: globalTokens.fontFamily.secondary.value, }, label: { fontSize: parseInt(globalTokens.fontSize.base.value), // ~16px fontFamily: globalTokens.fontFamily.primarySemiBold.value, }, labelSmall: { fontSize: 14, // ~14px fontFamily: globalTokens.fontFamily.primarySemiBold.value, }, // Financial amounts amount: { fontSize: parseInt(globalTokens.fontSize.lg.value), // ~18px fontFamily: globalTokens.fontFamily.primaryBold.value, }, amountLarge: { fontSize: 28, // Large amounts like £935.68 fontFamily: globalTokens.fontFamily.primaryBold.value, }, // Account numbers accountNumber: { fontSize: parseInt(globalTokens.fontSize.sm.value), // ~12px fontFamily: globalTokens.fontFamily.secondary.value, }, } }; }