@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
1 lines • 23.9 kB
Source Map (JSON)
{"version":3,"file":"theme-provider.cjs","sources":["../../../src/provider/theme-provider.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Theme Provider\n *\n * Theme provider that manages theme state, mode switching, organization branding,\n * and CSS variable generation for the authentication components.\n */\n\n'use client';\n\nimport type React from 'react';\nimport {createContext, useCallback, useContext, useEffect, useMemo, useReducer} from 'react';\n\nimport type {Organization} from '@frank-auth/client';\n\nimport type {Theme} from '../config';\nimport {createThemeManager, defaultTheme} from '../config';\n\nimport type {OrganizationBranding, ThemeContextValue, ThemeProviderProps, ThemeState,} from './types';\n\n// ============================================================================\n// Theme Context\n// ============================================================================\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\n// ============================================================================\n// Theme Reducer\n// ============================================================================\n\ntype ThemeAction =\n | { type: 'SET_THEME'; payload: Theme }\n | { type: 'SET_MODE'; payload: 'light' | 'dark' | 'system' }\n | { type: 'SET_EFFECTIVE_MODE'; payload: 'light' | 'dark' }\n | { type: 'SET_SYSTEM_MODE'; payload: boolean }\n | { type: 'SET_CSS_VARIABLES'; payload: Record<string, string> }\n | { type: 'SET_CUSTOMIZED'; payload: boolean }\n | { type: 'SET_ORGANIZATION_BRANDING'; payload: OrganizationBranding | undefined }\n | { type: 'RESET_THEME' };\n\nfunction themeReducer(state: ThemeState, action: ThemeAction): ThemeState {\n switch (action.type) {\n case 'SET_THEME':\n return {\n ...state,\n theme: action.payload,\n isCustomized: true,\n };\n\n case 'SET_MODE':\n return {\n ...state,\n mode: action.payload,\n isSystemMode: action.payload === 'system',\n };\n\n case 'SET_EFFECTIVE_MODE':\n return {\n ...state,\n effectiveMode: action.payload,\n };\n\n case 'SET_SYSTEM_MODE':\n return {\n ...state,\n isSystemMode: action.payload,\n };\n\n case 'SET_CSS_VARIABLES':\n return {\n ...state,\n cssVariables: action.payload,\n };\n\n case 'SET_CUSTOMIZED':\n return {\n ...state,\n isCustomized: action.payload,\n };\n\n case 'SET_ORGANIZATION_BRANDING':\n return {\n ...state,\n organizationBranding: action.payload,\n isCustomized: !!action.payload,\n };\n\n case 'RESET_THEME':\n return {\n ...initialThemeState,\n };\n\n default:\n return state;\n }\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialThemeState: ThemeState = {\n theme: defaultTheme,\n mode: 'system',\n effectiveMode: 'light',\n isSystemMode: true,\n cssVariables: {},\n isCustomized: false,\n};\n\n// ============================================================================\n// Theme Provider Component\n// ============================================================================\n\nexport function ThemeProvider({\n children,\n theme: initialTheme,\n mode: initialMode = 'system',\n organizationBranding,\n onThemeChange,\n }: ThemeProviderProps) {\n const [state, dispatch] = useReducer(themeReducer, {\n ...initialThemeState,\n theme: initialTheme ? { ...defaultTheme, ...initialTheme } : defaultTheme,\n mode: initialMode,\n isSystemMode: initialMode === 'system',\n });\n\n // Initialize theme manager\n const themeManager = useMemo(() => {\n return createThemeManager(state.theme);\n }, []);\n\n // Detect system preference\n const detectSystemPreference = useCallback((): 'light' | 'dark' => {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }, []);\n\n // Update effective mode based on current mode and system preference\n const updateEffectiveMode = useCallback(() => {\n let effectiveMode: 'light' | 'dark';\n\n if (state.mode === 'system') {\n effectiveMode = detectSystemPreference();\n } else {\n effectiveMode = state.mode;\n }\n\n if (effectiveMode !== state.effectiveMode) {\n dispatch({ type: 'SET_EFFECTIVE_MODE', payload: effectiveMode });\n }\n }, [state.mode, state.effectiveMode, detectSystemPreference]);\n\n // Listen for system theme changes\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n const handleChange = () => {\n if (state.mode === 'system') {\n updateEffectiveMode();\n }\n };\n\n mediaQuery.addEventListener('change', handleChange);\n\n // Initial check\n updateEffectiveMode();\n\n return () => {\n mediaQuery.removeEventListener('change', handleChange);\n };\n }, [state.mode, updateEffectiveMode]);\n\n // Update theme manager when theme changes\n useEffect(() => {\n themeManager.setTheme(state.theme);\n themeManager.setMode(state.effectiveMode);\n\n // Generate CSS variables\n const cssVariables = themeManager.generateCSSVariables();\n dispatch({ type: 'SET_CSS_VARIABLES', payload: cssVariables });\n\n // Notify parent component\n onThemeChange?.(state.theme);\n }, [themeManager, state.theme, state.effectiveMode, onThemeChange]);\n\n // Apply organization branding on initialization\n useEffect(() => {\n if (organizationBranding) {\n dispatch({ type: 'SET_ORGANIZATION_BRANDING', payload: organizationBranding });\n themeManager.applyBranding({\n logo: {\n url: organizationBranding.logo,\n alt: 'Organization Logo',\n },\n colors: {\n primary: organizationBranding.primaryColor || '#3b82f6',\n secondary: organizationBranding.secondaryColor || '#64748b',\n },\n fonts: {\n primary: organizationBranding.fonts?.primary || 'Inter, ui-sans-serif, system-ui, sans-serif',\n secondary: organizationBranding.fonts?.secondary,\n },\n customCSS: organizationBranding.customCSS,\n });\n }\n }, [organizationBranding, themeManager]);\n\n // Apply theme to DOM\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n // Apply CSS variables to root element\n const root = document.documentElement;\n Object.entries(state.cssVariables).forEach(([property, value]) => {\n root.style.setProperty(property, value);\n });\n\n // Apply theme mode class\n root.classList.remove('light', 'dark');\n root.classList.add(state.effectiveMode);\n\n // Apply data attributes for CSS selectors\n root.setAttribute('data-theme', state.effectiveMode);\n root.setAttribute('data-theme-mode', state.mode);\n root.setAttribute('data-theme-customized', state.isCustomized.toString());\n }, [state.cssVariables, state.effectiveMode, state.mode, state.isCustomized]);\n\n // Set theme method\n const setTheme = useCallback((theme: Partial<Theme>) => {\n const newTheme = { ...state.theme, ...theme };\n dispatch({ type: 'SET_THEME', payload: newTheme });\n }, [state.theme]);\n\n // Set mode method\n const setMode = useCallback((mode: 'light' | 'dark' | 'system') => {\n dispatch({ type: 'SET_MODE', payload: mode });\n\n // Immediately update effective mode if not system\n if (mode !== 'system') {\n dispatch({ type: 'SET_EFFECTIVE_MODE', payload: mode });\n } else {\n // Use current system preference\n const systemPreference = detectSystemPreference();\n dispatch({ type: 'SET_EFFECTIVE_MODE', payload: systemPreference });\n }\n }, [detectSystemPreference]);\n\n // Apply branding method\n const applyBranding = useCallback((branding: OrganizationBranding) => {\n dispatch({ type: 'SET_ORGANIZATION_BRANDING', payload: branding });\n\n // Apply branding to theme manager\n themeManager.applyBranding({\n logo: {\n url: branding.logo,\n alt: 'Organization Logo',\n },\n colors: {\n primary: branding.primaryColor || state.theme.colors.primary.DEFAULT,\n secondary: branding.secondaryColor || state.theme.colors.secondary.DEFAULT,\n },\n fonts: {\n primary: branding.fonts?.primary || state.theme.typography.fontFamily.sans[0],\n secondary: branding.fonts?.secondary,\n },\n customCSS: branding.customCSS,\n });\n }, [themeManager, state.theme]);\n\n // Reset theme method\n const resetTheme = useCallback(() => {\n themeManager.setTheme(defaultTheme);\n dispatch({ type: 'RESET_THEME' });\n }, [themeManager]);\n\n // Generate CSS method\n const generateCSS = useCallback((): string => {\n let css = ':root {\\n';\n\n // Add CSS variables\n Object.entries(state.cssVariables).forEach(([property, value]) => {\n css += ` ${property}: ${value};\\n`;\n });\n\n css += '}\\n\\n';\n\n // Add theme mode specific styles\n css += `[data-theme=\"light\"] {\\n`;\n css += ` color-scheme: light;\\n`;\n css += `}\\n\\n`;\n\n css += `[data-theme=\"dark\"] {\\n`;\n css += ` color-scheme: dark;\\n`;\n css += `}\\n\\n`;\n\n // Add organization branding styles if available\n if (state.organizationBranding?.customCSS) {\n css += `/* Organization Custom CSS */\\n`;\n css += state.organizationBranding.customCSS;\n css += '\\n\\n';\n }\n\n return css;\n }, [state.cssVariables, state.organizationBranding]);\n\n // Context value\n const contextValue: ThemeContextValue = {\n // State\n ...state,\n\n // Methods\n setTheme,\n setMode,\n applyBranding,\n resetTheme,\n generateCSS,\n };\n\n return (\n <ThemeContext.Provider value={contextValue}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook to use theme context\n// ============================================================================\n\nexport function useTheme() {\n const context = useContext(ThemeContext);\n\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n\n return context;\n}\n\n// ============================================================================\n// Hook for theme mode switching\n// ============================================================================\n\nexport function useThemeMode() {\n const { mode, effectiveMode, setMode, isSystemMode } = useTheme();\n\n return {\n mode,\n effectiveMode,\n isSystemMode,\n setMode,\n toggleMode: () => {\n if (mode === 'light') {\n setMode('dark');\n } else if (mode === 'dark') {\n setMode('light');\n } else {\n // If system mode, toggle to opposite of current effective mode\n setMode(effectiveMode === 'light' ? 'dark' : 'light');\n }\n },\n setLightMode: () => setMode('light'),\n setDarkMode: () => setMode('dark'),\n setSystemMode: () => setMode('system'),\n };\n}\n\n// ============================================================================\n// Hook for organization branding\n// ============================================================================\n\nexport function useOrganizationBranding() {\n const { organizationBranding, applyBranding, isCustomized } = useTheme();\n\n const applyOrganizationBranding = useCallback((organization: Organization) => {\n if (organization.settings?.branding) {\n const branding: OrganizationBranding = {\n primaryColor: organization.settings.branding.primaryColor,\n secondaryColor: organization.settings.branding.secondaryColor,\n logo: organization.logoUrl,\n favicon: organization.settings.branding.favicon,\n customCSS: organization.settings.branding.customCSS,\n };\n\n applyBranding(branding);\n }\n }, [applyBranding]);\n\n return {\n branding: organizationBranding,\n isCustomBranded: isCustomized,\n applyOrganizationBranding,\n applyBranding,\n hasLogo: !!organizationBranding?.logo,\n hasCustomCSS: !!organizationBranding?.customCSS,\n primaryColor: organizationBranding?.primaryColor,\n secondaryColor: organizationBranding?.secondaryColor,\n };\n}\n\n// ============================================================================\n// Hook for CSS variables\n// ============================================================================\n\nexport function useThemeVariables() {\n const { cssVariables, generateCSS } = useTheme();\n\n return {\n variables: cssVariables,\n getVariable: (name: string) => cssVariables[name],\n generateCSS,\n applyToElement: (element: HTMLElement) => {\n Object.entries(cssVariables).forEach(([property, value]) => {\n element.style.setProperty(property, value);\n });\n },\n };\n}\n\n// ============================================================================\n// Higher-order component for theme\n// ============================================================================\n\nexport function withTheme<T extends object>(Component: React.ComponentType<T>) {\n const WithThemeComponent = (props: T) => {\n const theme = useTheme();\n\n return <Component {...props} theme={theme} />;\n };\n\n WithThemeComponent.displayName = `withTheme(${Component.displayName || Component.name})`;\n\n return WithThemeComponent;\n}\n\n// ============================================================================\n// Theme switching button component\n// ============================================================================\n\nexport function ThemeSwitcher({\n className,\n iconClassName,\n showLabel = false,\n ...props\n }: {\n className?: string;\n iconClassName?: string;\n showLabel?: boolean;\n} & React.ButtonHTMLAttributes<HTMLButtonElement>) {\n const { mode, effectiveMode, toggleMode } = useThemeMode();\n\n const getIcon = () => {\n if (mode === 'system') {\n return effectiveMode === 'dark' ? '🌙' : '☀️';\n }\n return mode === 'dark' ? '🌙' : '☀️';\n };\n\n const getLabel = () => {\n if (mode === 'system') {\n return `System (${effectiveMode})`;\n }\n return mode === 'dark' ? 'Dark' : 'Light';\n };\n\n return (\n <button\n type=\"button\"\n onClick={toggleMode}\n className={className}\n title={`Switch to ${effectiveMode === 'dark' ? 'light' : 'dark'} mode`}\n {...props}\n >\n <span className={iconClassName}>\n {getIcon()}\n </span>\n {showLabel && <span>{getLabel()}</span>}\n </button>\n );\n}\n\n// ============================================================================\n// Export theme provider\n// ============================================================================\n\nexport { ThemeContext };\nexport type { ThemeContextValue };"],"names":["ThemeContext","createContext","themeReducer","state","action","initialThemeState","defaultTheme","ThemeProvider","children","initialTheme","initialMode","organizationBranding","onThemeChange","dispatch","useReducer","themeManager","useMemo","createThemeManager","detectSystemPreference","useCallback","updateEffectiveMode","effectiveMode","useEffect","mediaQuery","handleChange","cssVariables","root","property","value","setTheme","theme","newTheme","setMode","mode","systemPreference","applyBranding","branding","resetTheme","generateCSS","css","contextValue","useTheme","context","useContext","useThemeMode","isSystemMode","useOrganizationBranding","isCustomized","applyOrganizationBranding","organization","useThemeVariables","name","element","withTheme","Component","WithThemeComponent","props","jsx","ThemeSwitcher","className","iconClassName","showLabel","toggleMode","getIcon","getLabel","jsxs"],"mappings":"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"}