create-rn-starter-kit
Version:
Interactive CLI for creating modular React Native apps with Expo
171 lines (160 loc) • 4.79 kB
text/typescript
// Import all brand tokens statically
import defaultTokens from './brands/default.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 };
semantic: {
error: TokenValue;
success: TokenValue;
warning: TokenValue;
};
};
spacing: { [key: string]: TokenValue };
borderRadius: { [key: string]: TokenValue };
fontSize: { [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;
};
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;
};
}
// Available brands
export type BrandName = 'default' | '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 'default':
default:
return defaultTokens 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),
},
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),
},
};
}