@moontra/moonui-cli
Version:
CLI tool for MoonUI component library
174 lines (149 loc) • 5.13 kB
text/typescript
import { themePresets } from '../theme-presets';
export interface ThemeConfig {
preset?: string;
custom?: {
colors: ThemeColors;
darkMode?: ThemeColors;
radius?: number;
};
}
export interface ThemeColors {
background: string;
foreground: string;
primary: string;
'primary-foreground': string;
secondary: string;
'secondary-foreground': string;
accent: string;
'accent-foreground': string;
destructive: string;
'destructive-foreground': string;
muted: string;
'muted-foreground': string;
border: string;
input: string;
ring: string;
card?: string;
'card-foreground'?: string;
popover?: string;
'popover-foreground'?: string;
success?: string;
'success-foreground'?: string;
warning?: string;
'warning-foreground'?: string;
error?: string;
'error-foreground'?: string;
}
/**
* Generate CSS variables from theme configuration
*/
export function generateThemeCSS(themeConfig: ThemeConfig): string {
let lightColors: ThemeColors;
let darkColors: ThemeColors | undefined;
let radius = 0.5;
// If using preset
if (themeConfig.preset && themePresets[themeConfig.preset]) {
const preset = themePresets[themeConfig.preset];
lightColors = preset.colors as unknown as ThemeColors;
darkColors = preset.dark as unknown as ThemeColors | undefined;
radius = preset.radius || 0.5;
}
// If using custom theme
else if (themeConfig.custom) {
lightColors = themeConfig.custom.colors;
darkColors = themeConfig.custom.darkMode;
radius = themeConfig.custom.radius || 0.5;
}
// Default to 'default' preset
else {
const defaultPreset = themePresets.default;
lightColors = defaultPreset.colors as unknown as ThemeColors;
darkColors = defaultPreset.dark as unknown as ThemeColors | undefined;
radius = defaultPreset.radius || 0.5;
}
// Generate CSS
let css = `/* MoonUI Theme - Generated automatically from moonui.config.js */\n`;
css += `/* This theme only affects MoonUI components with .moonui-theme class */\n\n`;
// Light mode variables - scoped to .moonui-theme
css += `.moonui-theme {\n`;
css += generateColorVariables(lightColors);
css += ` --radius: ${radius}rem;\n`;
css += `}\n\n`;
// Dark mode variables (if provided) - scoped to .moonui-theme.dark
if (darkColors) {
css += `.moonui-theme.dark,\n`;
css += `.dark .moonui-theme {\n`;
css += generateColorVariables(darkColors);
css += `}\n\n`;
}
// Add CSS for global usage (optional)
css += `/* To use theme globally, add .moonui-theme class to your root element */\n`;
css += `/* Example: <html class="moonui-theme"> or <body class="moonui-theme"> */\n\n`;
// Remove global Tailwind layer styles - these should be handled by the user
css += `/* MoonUI components automatically use these theme variables */\n`;
css += `/* No global styles are applied by default */\n`;
return css;
}
/**
* Generate color CSS variables from colors object
*/
function generateColorVariables(colors: ThemeColors): string {
let css = '';
Object.entries(colors).forEach(([key, value]) => {
css += ` --${key}: ${value};\n`;
});
return css;
}
/**
* Get theme colors from config
*/
export function getThemeColors(themeConfig: ThemeConfig): { light: ThemeColors; dark?: ThemeColors } {
let lightColors: ThemeColors;
let darkColors: ThemeColors | undefined;
if (themeConfig.preset && themePresets[themeConfig.preset]) {
const preset = themePresets[themeConfig.preset];
lightColors = preset.colors as unknown as ThemeColors;
darkColors = preset.dark as unknown as ThemeColors | undefined;
} else if (themeConfig.custom) {
lightColors = themeConfig.custom.colors;
darkColors = themeConfig.custom.darkMode;
} else {
const defaultPreset = themePresets.default;
lightColors = defaultPreset.colors as unknown as ThemeColors;
darkColors = defaultPreset.dark as unknown as ThemeColors | undefined;
}
return { light: lightColors, dark: darkColors };
}
/**
* Export theme configuration as JSON
*/
export function exportThemeAsJSON(themeConfig: ThemeConfig): string {
const colors = getThemeColors(themeConfig);
return JSON.stringify({
name: themeConfig.preset || 'custom',
colors: colors.light,
darkMode: colors.dark,
radius: themeConfig.custom?.radius || 0.5,
}, null, 2);
}
/**
* Export theme configuration for moonui.config.js
*/
export function exportThemeAsConfig(themeConfig: ThemeConfig): string {
const colors = getThemeColors(themeConfig);
let config = `// MoonUI Theme Configuration\n`;
config += `theme: {\n`;
if (themeConfig.preset) {
config += ` preset: '${themeConfig.preset}',\n`;
} else {
config += ` custom: {\n`;
config += ` colors: ${JSON.stringify(colors.light, null, 6).replace(/^/gm, ' ')},\n`;
if (colors.dark) {
config += ` darkMode: ${JSON.stringify(colors.dark, null, 6).replace(/^/gm, ' ')},\n`;
}
config += ` radius: ${themeConfig.custom?.radius || 0.5},\n`;
config += ` },\n`;
}
config += `}`;
return config;
}