UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 17.1 kB
{"version":3,"file":"theme.cjs","sources":["../../../src/config/theme.ts"],"sourcesContent":["/**\n * @frank-auth/react - Theme Configuration\n *\n * Advanced theme management system with support for light/dark modes,\n * custom color palettes, and HeroUI integration.\n */\n\nimport {type BrandingConfig, type Theme, type ThemeMode, ThemeUtils,} from './types';\n\nimport {DEFAULT_COLOR_PALETTE, DEFAULT_THEME_CONFIG,} from './defaults';\nimport {generateColorPalette} from '../utils';\nimport type {ThemeColors} from '../types';\n\n// ============================================================================\n// Theme Utilities\n// ============================================================================\n\n/**\n * Creates a dark theme variant from a light theme\n */\nexport function createDarkTheme(lightTheme: Theme): Theme {\n const darkColors: ThemeColors = {\n ...lightTheme.colors,\n // Invert background colors\n background: '#0f172a',\n foreground: '#f8fafc',\n card: '#1e293b',\n cardForeground: '#f8fafc',\n popover: '#1e293b',\n popoverForeground: '#f8fafc',\n muted: '#334155',\n mutedForeground: '#94a3b8',\n accent: '#334155',\n accentForeground: '#f8fafc',\n border: '#334155',\n input: '#334155',\n ring: lightTheme.palette.primary.DEFAULT,\n };\n\n return {\n ...lightTheme,\n mode: 'dark',\n colors: darkColors,\n palette: {\n ...lightTheme.palette,\n\n // Adjust primary colors for dark mode\n primary: {\n ...lightTheme.palette.primary,\n DEFAULT: lightTheme.colors.primary[400],\n foreground: '#000000',\n },\n\n // Adjust secondary colors for dark mode\n secondary: {\n ...lightTheme.palette.secondary,\n DEFAULT: lightTheme.colors.secondary[400],\n foreground: '#000000',\n },\n }\n };\n}\n\n// ============================================================================\n// Predefined Themes\n// ============================================================================\n\n/**\n * Blue theme (default)\n */\nexport const BLUE_THEME: Theme = {\n ...DEFAULT_THEME_CONFIG,\n colors: {\n ...DEFAULT_THEME_CONFIG.colors,\n primary: generateColorPalette('#3b82f6'),\n },\n palette: {\n ...DEFAULT_COLOR_PALETTE,\n primary: generateColorPalette('#3b82f6'),\n },\n};\n\n/**\n * Purple theme\n */\nexport const PURPLE_THEME: Theme = {\n ...DEFAULT_THEME_CONFIG,\n colors: {\n ...DEFAULT_THEME_CONFIG.colors,\n primary: generateColorPalette('#8b5cf6'),\n secondary: generateColorPalette('#6366f1'),\n },\n palette: {\n ...DEFAULT_COLOR_PALETTE,\n primary: generateColorPalette('#8b5cf6'),\n secondary: generateColorPalette('#6366f1'),\n },\n};\n\n/**\n * Green theme\n */\nexport const GREEN_THEME: Theme = {\n ...DEFAULT_THEME_CONFIG,\n colors: {\n ...DEFAULT_THEME_CONFIG.colors,\n primary: generateColorPalette('#10b981'),\n secondary: generateColorPalette('#059669'),\n },\n palette: {\n ...DEFAULT_COLOR_PALETTE,\n primary: generateColorPalette('#10b981'),\n secondary: generateColorPalette('#059669'),\n },\n};\n\n/**\n * Orange theme\n */\nexport const ORANGE_THEME: Theme = {\n ...DEFAULT_THEME_CONFIG,\n colors: {\n ...DEFAULT_THEME_CONFIG.colors,\n primary: generateColorPalette('#f97316').DEFAULT,\n secondary: generateColorPalette('#ea580c').DEFAULT,\n },\n palette: {\n ...DEFAULT_COLOR_PALETTE,\n primary: generateColorPalette('#f97316'),\n secondary: generateColorPalette('#ea580c'),\n },\n};\n\n/**\n * Pink theme\n */\nexport const PINK_THEME: Theme = {\n ...DEFAULT_THEME_CONFIG,\n colors: {\n ...DEFAULT_THEME_CONFIG.colors,\n primary: generateColorPalette('#ec4899').DEFAULT,\n secondary: generateColorPalette('#db2777').DEFAULT,\n },\n palette: {\n ...DEFAULT_COLOR_PALETTE,\n primary: generateColorPalette('#ec4899'),\n secondary: generateColorPalette('#db2777'),\n },\n};\n\n/**\n * Available theme presets\n */\nexport const THEME_PRESETS = {\n blue: BLUE_THEME,\n purple: PURPLE_THEME,\n green: GREEN_THEME,\n orange: ORANGE_THEME,\n pink: PINK_THEME,\n} as const;\n\nexport type ThemePreset = keyof typeof THEME_PRESETS;\n\n// ============================================================================\n// Theme Manager Class\n// ============================================================================\n\nexport class ThemeManager {\n private currentTheme: Theme;\n private systemPreference: ThemeMode;\n private listeners: Set<(theme: Theme) => void> = new Set();\n\n constructor(initialTheme?: Partial<Theme>) {\n this.currentTheme = this.mergeTheme(DEFAULT_THEME_CONFIG, initialTheme);\n this.systemPreference = this.detectSystemPreference();\n\n // Listen for system theme changes\n if (typeof window !== 'undefined') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n mediaQuery.addEventListener('change', () => {\n this.systemPreference = this.detectSystemPreference();\n this.updateTheme();\n });\n }\n }\n\n /**\n * Get current theme\n */\n getTheme(): Theme {\n return { ...this.currentTheme };\n }\n\n /**\n * Set theme configuration\n */\n setTheme(theme: Partial<Theme>): void {\n this.currentTheme = this.mergeTheme(this.currentTheme, theme);\n this.updateTheme();\n }\n\n /**\n * Apply a theme preset\n */\n applyPreset(preset: ThemePreset): void {\n this.currentTheme = { ...THEME_PRESETS[preset] };\n this.updateTheme();\n }\n\n /**\n * Set theme mode\n */\n setMode(mode: ThemeMode): void {\n this.currentTheme.mode = mode;\n this.updateTheme();\n }\n\n /**\n * Get effective theme mode (resolves 'system' to 'light' or 'dark')\n */\n getEffectiveMode(): 'light' | 'dark' {\n if (this.currentTheme.mode === 'system') {\n return this.systemPreference === 'dark' ? 'dark' : 'light';\n }\n return this.currentTheme.mode === 'dark' ? 'dark' : 'light';\n }\n\n /**\n * Apply branding colors to theme\n */\n applyBranding(branding: BrandingConfig): void {\n if (branding.colors?.primary) {\n this.currentTheme.palette.primary = generateColorPalette(branding.colors.primary);\n }\n\n if (branding.colors?.secondary) {\n this.currentTheme.palette.secondary = generateColorPalette(branding.colors.secondary);\n }\n\n if (branding.fonts?.primary) {\n this.currentTheme.typography.fontFamily.sans = [\n branding.fonts.primary,\n ...this.currentTheme.typography.fontFamily.sans,\n ];\n }\n\n this.updateTheme();\n }\n\n /**\n * Generate CSS variables for the current theme\n */\n generateCSSVariables(): Record<string, string> {\n const theme = this.getResolvedTheme();\n return ThemeUtils.generateCSSVariables(theme);\n }\n\n /**\n * Apply theme to DOM\n */\n applyToDOM(): void {\n if (typeof document === 'undefined') return;\n\n const variables = this.generateCSSVariables();\n const root = document.documentElement;\n\n // Apply CSS variables\n Object.entries(variables).forEach(([property, value]) => {\n root.style.setProperty(property, value);\n });\n\n // Apply theme class\n const effectiveMode = this.getEffectiveMode();\n root.classList.remove('light', 'dark');\n root.classList.add(effectiveMode);\n }\n\n /**\n * Subscribe to theme changes\n */\n subscribe(callback: (theme: Theme) => void): () => void {\n this.listeners.add(callback);\n return () => {\n this.listeners.delete(callback);\n };\n }\n\n // Private methods\n\n private detectSystemPreference(): ThemeMode {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n\n private mergeTheme(base: Theme, override?: Partial<Theme>): Theme {\n if (!override) return { ...base };\n\n return {\n ...base,\n ...override,\n colors: { ...base.colors, ...override.colors },\n typography: {\n ...base.typography,\n ...override.typography,\n fontFamily: { ...base.typography.fontFamily, ...override.typography?.fontFamily },\n fontSize: { ...base.typography.fontSize, ...override.typography?.fontSize },\n fontWeight: { ...base.typography.fontWeight, ...override.typography?.fontWeight },\n },\n spacing: { ...base.spacing, ...override.spacing },\n borderRadius: { ...base.borderRadius, ...override.borderRadius },\n shadows: { ...base.shadows, ...override.shadows },\n animations: {\n ...base.animations,\n ...override.animations,\n duration: { ...base.animations.duration, ...override.animations?.duration },\n timingFunction: { ...base.animations.timingFunction, ...override.animations?.timingFunction },\n keyframes: { ...base.animations.keyframes, ...override.animations?.keyframes },\n },\n };\n }\n\n private getResolvedTheme(): Theme {\n const effectiveMode = this.getEffectiveMode();\n\n if (effectiveMode === 'dark' && this.currentTheme.mode !== 'dark') {\n return createDarkTheme(this.currentTheme);\n }\n\n return this.currentTheme;\n }\n\n private updateTheme(): void {\n this.applyToDOM();\n this.listeners.forEach(callback => callback(this.currentTheme));\n }\n}\n\n// ============================================================================\n// Theme Hooks and Utilities\n// ============================================================================\n\n/**\n * Create a theme manager instance\n */\nexport function createThemeManager(initialTheme?: Partial<Theme>): ThemeManager {\n return new ThemeManager(initialTheme);\n}\n\n/**\n * Get theme CSS for server-side rendering\n */\nexport function getThemeCSS(theme: Theme): string {\n const manager = new ThemeManager(theme);\n const variables = manager.generateCSSVariables();\n\n return `:root {\n ${Object.entries(variables)\n .map(([property, value]) => `${property}: ${value};`)\n .join('\\n ')}\n }`;\n}\n\n/**\n * Validate theme configuration\n */\nexport function validateTheme(theme: Partial<Theme>): boolean {\n try {\n // Basic validation - ensure required color properties exist\n if (theme.colors) {\n const requiredColors = ['primary', 'secondary', 'background', 'foreground'];\n for (const color of requiredColors) {\n if (!(color in theme.colors)) {\n return false;\n }\n }\n }\n\n // Validate typography if provided\n if (theme.typography) {\n if (theme.typography.fontFamily && !Array.isArray(theme.typography.fontFamily.sans)) {\n return false;\n }\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Export theme utilities\n// ============================================================================\n\nexport {\n DEFAULT_THEME_CONFIG,\n};"],"names":["createDarkTheme","lightTheme","darkColors","BLUE_THEME","DEFAULT_THEME_CONFIG","generateColorPalette","DEFAULT_COLOR_PALETTE","PURPLE_THEME","GREEN_THEME","ORANGE_THEME","PINK_THEME","THEME_PRESETS","ThemeManager","initialTheme","__publicField","theme","preset","mode","branding","ThemeUtils","variables","root","property","value","effectiveMode","callback","base","override","createThemeManager","getThemeCSS","validateTheme","requiredColors","color"],"mappings":"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"}