@asafarim/react-themes
Version:
A comprehensive theme management system for React applications with automatic dark/light mode detection, custom theme creation, and smooth transitions.
1 lines • 35 kB
Source Map (JSON)
{"version":3,"sources":["../src/themes.ts","../src/components/ThemeProvider.tsx","../src/utils/applyTheme.ts","../src/hooks/useTheme.ts","../src/hooks/useThemeToggle.ts","../src/components/ThemeToggle.tsx","../src/components/ThemeSelector.tsx","../src/utils/createTheme.ts","../src/utils/mergeThemes.ts"],"sourcesContent":["import type { Theme, ThemeColors } from './types';\r\n\r\n// Light theme colors\r\nconst lightColors: ThemeColors = {\r\n // Background colors\r\n background: '#ffffff',\r\n backgroundSecondary: '#f8fafc',\r\n backgroundTertiary: '#f1f5f9',\r\n \r\n // Text colors\r\n text: '#0f172a',\r\n textSecondary: '#475569',\r\n textMuted: '#64748b',\r\n \r\n // Border colors\r\n border: '#e2e8f0',\r\n borderLight: '#f1f5f9',\r\n borderHover: '#cbd5e1',\r\n \r\n // Accent colors\r\n primary: '#3b82f6',\r\n primaryHover: '#2563eb',\r\n primaryActive: '#1d4ed8',\r\n \r\n // Status colors\r\n success: '#10b981',\r\n warning: '#f59e0b',\r\n error: '#ef4444',\r\n info: '#06b6d4',\r\n \r\n // Interactive states\r\n hover: '#f8fafc',\r\n active: '#f1f5f9',\r\n focus: 'rgba(59, 130, 246, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\r\n};\r\n\r\n// Dark theme colors\r\nconst darkColors: ThemeColors = {\r\n // Background colors\r\n background: '#0f172a',\r\n backgroundSecondary: '#1e293b',\r\n backgroundTertiary: '#334155',\r\n \r\n // Text colors\r\n text: '#f8fafc',\r\n textSecondary: '#cbd5e1',\r\n textMuted: '#94a3b8',\r\n \r\n // Border colors\r\n border: '#334155',\r\n borderLight: '#475569',\r\n borderHover: '#64748b',\r\n \r\n // Accent colors\r\n primary: '#60a5fa',\r\n primaryHover: '#3b82f6',\r\n primaryActive: '#2563eb',\r\n \r\n // Status colors\r\n success: '#34d399',\r\n warning: '#fbbf24',\r\n error: '#f87171',\r\n info: '#22d3ee',\r\n \r\n // Interactive states\r\n hover: '#1e293b',\r\n active: '#334155',\r\n focus: 'rgba(96, 165, 250, 0.1)',\r\n \r\n // Shadows\r\n shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',\r\n shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',\r\n shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)',\r\n};\r\n\r\n// Base theme structure\r\nconst baseTheme = {\r\n spacing: {\r\n xs: '0.25rem',\r\n sm: '0.5rem',\r\n md: '0.75rem',\r\n lg: '1rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '2rem',\r\n '4xl': '3rem',\r\n },\r\n radius: {\r\n none: '0',\r\n sm: '0.25rem',\r\n md: '0.375rem',\r\n lg: '0.5rem',\r\n xl: '0.75rem',\r\n '2xl': '1rem',\r\n full: '9999px',\r\n },\r\n typography: {\r\n fontFamily: {\r\n sans: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif',\r\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\r\n mono: 'ui-monospace, SFMono-Regular, \"SF Mono\", Consolas, \"Liberation Mono\", Menlo, monospace',\r\n },\r\n fontSize: {\r\n xs: '0.75rem',\r\n sm: '0.875rem',\r\n base: '1rem',\r\n lg: '1.125rem',\r\n xl: '1.25rem',\r\n '2xl': '1.5rem',\r\n '3xl': '1.875rem',\r\n '4xl': '2.25rem',\r\n '5xl': '3rem',\r\n },\r\n fontWeight: {\r\n light: '300',\r\n normal: '400',\r\n medium: '500',\r\n semibold: '600',\r\n bold: '700',\r\n },\r\n lineHeight: {\r\n tight: '1.25',\r\n normal: '1.5',\r\n relaxed: '1.75',\r\n },\r\n },\r\n transitions: {\r\n fast: 'all 0.1s ease',\r\n normal: 'all 0.2s ease',\r\n slow: 'all 0.3s ease',\r\n bounce: 'all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)',\r\n },\r\n zIndex: {\r\n dropdown: 1000,\r\n modal: 1050,\r\n tooltip: 1100,\r\n overlay: 1200,\r\n },\r\n};\r\n\r\n// Light theme\r\nexport const lightTheme: Theme = {\r\n name: 'light',\r\n mode: 'light',\r\n colors: lightColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Dark theme\r\nexport const darkTheme: Theme = {\r\n name: 'dark',\r\n mode: 'dark',\r\n colors: darkColors,\r\n ...baseTheme,\r\n};\r\n\r\n// Default theme (light)\r\nexport const defaultTheme = lightTheme;\r\n\r\n// Theme presets\r\nexport const themes = {\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Default themes for the provider\r\nexport const defaultThemes = {\r\n default: lightTheme,\r\n light: lightTheme,\r\n dark: darkTheme,\r\n};\r\n\r\n// Helper function to merge themes\r\nexport function mergeTheme(baseTheme: Theme, customTheme: Partial<Theme>): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { createContext, useContext, useEffect, useState, ReactNode } from 'react';\r\nimport { Theme, ThemeConfig, ThemeMode } from '../types';\r\nimport { defaultThemes } from '../themes';\r\nimport { applyTheme } from '../utils/applyTheme';\r\n\r\nexport interface ThemeContextType {\r\n currentTheme: Theme;\r\n mode: ThemeMode;\r\n setMode: (mode: ThemeMode) => void;\r\n setTheme: (theme: Theme) => void;\r\n themes: Record<string, Theme>;\r\n toggleMode: () => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\r\n\r\nexport interface ThemeProviderProps {\r\n children: ReactNode;\r\n config?: ThemeConfig;\r\n defaultMode?: ThemeMode;\r\n defaultTheme?: string;\r\n persistMode?: boolean;\r\n storageKey?: string;\r\n customThemes?: Record<string, Theme>;\r\n}\r\n\r\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\r\n children,\r\n defaultMode = 'auto',\r\n defaultTheme = 'default',\r\n persistMode = true,\r\n storageKey = 'asafarim-theme-mode',\r\n customThemes = {},\r\n}) => {\r\n const allThemes = { ...defaultThemes, ...customThemes };\r\n \r\n // Get initial mode from localStorage or use default\r\n const getInitialMode = (): ThemeMode => {\r\n if (!persistMode || typeof window === 'undefined') return defaultMode;\r\n \r\n try {\r\n const stored = localStorage.getItem(storageKey);\r\n if (stored && ['light', 'dark', 'auto'].includes(stored)) {\r\n return stored as ThemeMode;\r\n }\r\n } catch (error) {\r\n console.warn('Failed to read theme mode from localStorage:', error);\r\n }\r\n \r\n return defaultMode;\r\n };\r\n const [mode, setModeState] = useState<ThemeMode>(getInitialMode);\r\n const [currentThemeName, setCurrentThemeName] = useState<string>(defaultTheme);\r\n\r\n // Get the effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n // Get the current theme based on mode and theme name\r\n const getCurrentTheme = (): Theme => {\r\n const effectiveMode = getEffectiveMode();\r\n \r\n // If user selected a specific theme, use it\r\n if (currentThemeName !== 'default' && currentThemeName in allThemes) {\r\n return allThemes[currentThemeName as keyof typeof allThemes];\r\n }\r\n \r\n // Otherwise use the theme that matches the effective mode\r\n return effectiveMode === 'dark' ? allThemes.dark : allThemes.light;\r\n };\r\n\r\n const currentTheme = getCurrentTheme();\r\n\r\n // Update mode and persist if enabled\r\n const setMode = (newMode: ThemeMode) => {\r\n setModeState(newMode);\r\n \r\n if (persistMode && typeof window !== 'undefined') {\r\n try {\r\n localStorage.setItem(storageKey, newMode);\r\n } catch (error) {\r\n console.warn('Failed to save theme mode to localStorage:', error);\r\n }\r\n }\r\n };\r\n\r\n // Toggle between light and dark modes\r\n const toggleMode = () => {\r\n if (mode === 'auto') {\r\n // If auto, switch to opposite of system preference\r\n const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n setMode(systemDark ? 'light' : 'dark');\r\n } else {\r\n setMode(mode === 'light' ? 'dark' : 'light');\r\n }\r\n };\r\n // Set theme by name\r\n const setTheme = (theme: Theme) => {\r\n setCurrentThemeName(theme.name);\r\n };\r\n // Apply theme to document\r\n useEffect(() => {\r\n applyTheme(currentTheme, mode);\r\n }, [currentTheme, mode, currentThemeName]); // Add currentThemeName as dependency\r\n\r\n // Listen for system theme changes when in auto mode\r\n useEffect(() => {\r\n if (mode !== 'auto') return;\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleChange = () => {\r\n // Force re-render when system preference changes\r\n applyTheme(getCurrentTheme(), mode);\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, [mode]);\r\n\r\n const contextValue: ThemeContextType = {\r\n currentTheme,\r\n mode,\r\n setMode,\r\n setTheme,\r\n themes: allThemes,\r\n toggleMode,\r\n };\r\n\r\n return (\r\n <ThemeContext.Provider value={contextValue}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport const useThemeContext = () => {\r\n const context = useContext(ThemeContext);\r\n if (context === undefined) {\r\n throw new Error('useThemeContext must be used within a ThemeProvider');\r\n }\r\n return context;\r\n};\r\n","import { Theme, ThemeMode } from '../types';\r\n\r\n/**\r\n * Applies theme CSS variables to the document root\r\n */\r\nexport function applyTheme(theme: Theme, mode: ThemeMode): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Determine the effective mode\r\n let effectiveMode = mode;\r\n if (mode === 'auto') {\r\n effectiveMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n\r\n // Set data attributes for CSS targeting\r\n root.setAttribute('data-theme', theme.name);\r\n root.setAttribute('data-theme-mode', effectiveMode);\r\n\r\n // Apply color variables\r\n Object.entries(theme.colors).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-color-${kebabCase(key)}`, value);\r\n });\r\n\r\n // Apply spacing variables\r\n Object.entries(theme.spacing).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-spacing-${key}`, value);\r\n });\r\n\r\n // Apply radius variables\r\n Object.entries(theme.radius).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-radius-${key}`, value);\r\n });\r\n\r\n // Apply typography variables\r\n Object.entries(theme.typography.fontFamily).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-family-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontSize).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-size-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.fontWeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-font-weight-${key}`, value);\r\n });\r\n\r\n Object.entries(theme.typography.lineHeight).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-line-height-${key}`, value);\r\n });\r\n\r\n // Apply transition variables\r\n Object.entries(theme.transitions).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-transition-${key}`, value);\r\n });\r\n\r\n // Apply z-index variables\r\n Object.entries(theme.zIndex).forEach(([key, value]) => {\r\n root.style.setProperty(`--theme-z-index-${kebabCase(key)}`, value.toString());\r\n });\r\n\r\n // Add theme class to body for additional styling\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n document.body.classList.add(`theme-${theme.name}`, `theme-${effectiveMode}`);\r\n}\r\n\r\n/**\r\n * Removes all theme-related CSS variables and classes\r\n */\r\nexport function removeTheme(): void {\r\n if (typeof document === 'undefined') return;\r\n\r\n const root = document.documentElement;\r\n \r\n // Remove data attributes\r\n root.removeAttribute('data-theme');\r\n root.removeAttribute('data-theme-mode');\r\n\r\n // Remove CSS variables (this is a simplified approach - in production you might want to track which variables were set)\r\n const styles = root.style;\r\n for (let i = styles.length - 1; i >= 0; i--) {\r\n const property = styles[i];\r\n if (property.startsWith('--theme-')) {\r\n root.style.removeProperty(property);\r\n }\r\n }\r\n\r\n // Remove theme classes from body\r\n document.body.className = document.body.className.replace(/theme-\\w+/g, '');\r\n}\r\n\r\n/**\r\n * Converts camelCase to kebab-case\r\n */\r\nfunction kebabCase(str: string): string {\r\n return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n}\r\n","import { useThemeContext, ThemeContextType } from '../components/ThemeProvider';\r\n\r\n/**\r\n * Hook to access theme context\r\n */\r\nexport function useTheme(): ThemeContextType {\r\n return useThemeContext();\r\n}\r\n","import { useTheme } from './useTheme';\r\n\r\n/**\r\n * Hook that provides theme toggle functionality\r\n */\r\nexport function useThemeToggle() {\r\n const { mode, setMode, toggleMode } = useTheme();\r\n \r\n // Get effective mode (resolving 'auto' to actual light/dark)\r\n const getEffectiveMode = (): 'light' | 'dark' => {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined') {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return 'light'; // fallback for SSR\r\n }\r\n return mode;\r\n };\r\n\r\n const effectiveMode = getEffectiveMode();\r\n \r\n return {\r\n mode,\r\n setMode,\r\n toggleMode,\r\n isDark: effectiveMode === 'dark',\r\n isLight: effectiveMode === 'light',\r\n isAuto: mode === 'auto',\r\n effectiveMode, // Expose the resolved mode\r\n };\r\n}\r\n","import * as React from 'react';\r\nimport { useTheme } from '../hooks/useTheme';\r\n\r\nexport interface ThemeToggleProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n size?: 'sm' | 'md' | 'lg';\r\n}\r\n\r\nexport const ThemeToggle: React.FC<ThemeToggleProps> = ({\r\n className = '',\r\n style = {},\r\n showLabels = false,\r\n size = 'md',\r\n}) => {\r\n const { mode, toggleMode } = useTheme();\r\n\r\n const sizeClasses = {\r\n sm: 'w-8 h-8 text-sm',\r\n md: 'w-10 h-10 text-base',\r\n lg: 'w-12 h-12 text-lg',\r\n };\r\n\r\n const buttonClass = `\r\n ${sizeClasses[size]}\r\n inline-flex items-center justify-center\r\n rounded-md border border-gray-300\r\n bg-white hover:bg-gray-50\r\n dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n const getIcon = () => {\r\n switch (mode) {\r\n case 'light':\r\n return '☀️';\r\n case 'dark':\r\n return '🌙';\r\n case 'auto':\r\n default:\r\n return '🌓';\r\n }\r\n };\r\n\r\n const getLabel = () => {\r\n switch (mode) {\r\n case 'light':\r\n return 'Light';\r\n case 'dark':\r\n return 'Dark';\r\n case 'auto':\r\n default:\r\n return 'Auto';\r\n }\r\n };\r\n\r\n return (\r\n <button\r\n onClick={toggleMode}\r\n className={buttonClass}\r\n style={style}\r\n title={`Current theme: ${getLabel()}. Click to toggle.`}\r\n aria-label={`Switch theme. Current: ${getLabel()}`}\r\n >\r\n <span role=\"img\" aria-hidden=\"true\">\r\n {getIcon()}\r\n </span>\r\n {showLabels && (\r\n <span className=\"ml-2 text-sm font-medium\">\r\n {getLabel()}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n};\r\n","import * as React from \"react\";\r\nimport { useTheme } from \"../hooks/useTheme\";\r\nimport { ThemeMode } from \"../types\";\r\n\r\nexport interface ThemeSelectorProps {\r\n className?: string;\r\n style?: React.CSSProperties;\r\n showLabels?: boolean;\r\n options?: Array<{\r\n mode: ThemeMode;\r\n label: string;\r\n icon?: string;\r\n }>;\r\n}\r\n\r\nexport const ThemeSelector: React.FC<ThemeSelectorProps> = ({\r\n className = \"\",\r\n style = {},\r\n showLabels = true,\r\n options = [\r\n { mode: \"light\", label: \"Light\", icon: \"☀️\" },\r\n { mode: \"dark\", label: \"Dark\", icon: \"🌙\" },\r\n { mode: \"auto\", label: \"Auto\", icon: \"🌓\" },\r\n ],\r\n}) => {\r\n const { mode, setMode } = useTheme();\r\n\r\n const selectClass = `\r\n px-3 py-2 border border-gray-300 rounded-md\r\n bg-white dark:bg-gray-800 dark:border-gray-600\r\n text-gray-900 dark:text-gray-100\r\n focus:outline-none focus:ring-2 focus:ring-blue-500\r\n transition-all duration-200\r\n ${className}\r\n `.trim();\r\n\r\n return (\r\n <select\r\n value={mode}\r\n onChange={(e) => setMode(e.target.value as ThemeMode)}\r\n className={selectClass}\r\n style={style}\r\n aria-label=\"Select theme mode\"\r\n >\r\n {options.map((option) => (\r\n <option key={option.mode} value={option.mode}>\r\n {showLabels\r\n ? `${option.icon ? option.icon + \" \" : \"\"}${option.label}`\r\n : option.icon || option.label}\r\n </option>\r\n ))}\r\n </select>\r\n );\r\n};\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Creates a new theme by merging a base theme with custom properties\r\n */\r\nexport function createTheme(\r\n baseTheme: Theme,\r\n customTheme: Partial<Theme>\r\n): Theme {\r\n return {\r\n ...baseTheme,\r\n ...customTheme,\r\n name: customTheme.name || `${baseTheme.name}-custom`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customTheme.colors,\r\n },\r\n spacing: {\r\n ...baseTheme.spacing,\r\n ...customTheme.spacing,\r\n },\r\n radius: {\r\n ...baseTheme.radius,\r\n ...customTheme.radius,\r\n },\r\n typography: {\r\n ...baseTheme.typography,\r\n ...customTheme.typography,\r\n fontFamily: {\r\n ...baseTheme.typography.fontFamily,\r\n ...customTheme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...baseTheme.typography.fontSize,\r\n ...customTheme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...baseTheme.typography.fontWeight,\r\n ...customTheme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...baseTheme.typography.lineHeight,\r\n ...customTheme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...baseTheme.transitions,\r\n ...customTheme.transitions,\r\n },\r\n zIndex: {\r\n ...baseTheme.zIndex,\r\n ...customTheme.zIndex,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Creates a theme variant with modified colors\r\n */\r\nexport function createThemeVariant(\r\n baseTheme: Theme,\r\n colorOverrides: Partial<Theme['colors']>,\r\n name?: string\r\n): Theme {\r\n return createTheme(baseTheme, {\r\n name: name || `${baseTheme.name}-variant`,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...colorOverrides,\r\n },\r\n });\r\n}\r\n","import { Theme } from '../types';\r\n\r\n/**\r\n * Merges multiple themes into a single theme\r\n * Later themes in the array take precedence over earlier ones\r\n */\r\nexport function mergeThemes(...themes: Array<Theme | Partial<Theme>>): Theme {\r\n if (themes.length === 0) {\r\n throw new Error('At least one theme must be provided to mergeThemes');\r\n }\r\n\r\n const [baseTheme, ...additionalThemes] = themes;\r\n \r\n if (!isFullTheme(baseTheme)) {\r\n throw new Error('First theme must be a complete theme object');\r\n }\r\n return additionalThemes.reduce((merged: Theme, theme): Theme => {\r\n return {\r\n ...merged,\r\n ...theme,\r\n name: theme.name || merged.name,\r\n mode: theme.mode || merged.mode,\r\n colors: {\r\n ...merged.colors,\r\n ...theme.colors,\r\n },\r\n spacing: {\r\n ...merged.spacing,\r\n ...theme.spacing,\r\n },\r\n radius: {\r\n ...merged.radius,\r\n ...theme.radius,\r\n },\r\n typography: {\r\n ...merged.typography,\r\n ...theme.typography,\r\n fontFamily: {\r\n ...merged.typography.fontFamily,\r\n ...theme.typography?.fontFamily,\r\n },\r\n fontSize: {\r\n ...merged.typography.fontSize,\r\n ...theme.typography?.fontSize,\r\n },\r\n fontWeight: {\r\n ...merged.typography.fontWeight,\r\n ...theme.typography?.fontWeight,\r\n },\r\n lineHeight: {\r\n ...merged.typography.lineHeight,\r\n ...theme.typography?.lineHeight,\r\n },\r\n },\r\n transitions: {\r\n ...merged.transitions,\r\n ...theme.transitions,\r\n },\r\n zIndex: {\r\n ...merged.zIndex,\r\n ...theme.zIndex,\r\n },\r\n };\r\n }, baseTheme);\r\n}\r\n\r\n/**\r\n * Type guard to check if an object is a complete theme\r\n */\r\nfunction isFullTheme(theme: Theme | Partial<Theme>): theme is Theme {\r\n return !!(\r\n theme &&\r\n typeof theme === 'object' &&\r\n 'name' in theme &&\r\n 'mode' in theme &&\r\n 'colors' in theme &&\r\n 'spacing' in theme &&\r\n 'radius' in theme &&\r\n 'typography' in theme &&\r\n 'transitions' in theme &&\r\n 'zIndex' in theme\r\n );\r\n}\r\n\r\n/**\r\n * Merges theme colors only\r\n */\r\nexport function mergeThemeColors(\r\n baseColors: Theme['colors'],\r\n ...colorSets: Array<Partial<Theme['colors']>>\r\n): Theme['colors'] {\r\n return colorSets.reduce((merged: Theme['colors'], colors): Theme['colors'] => ({\r\n ...merged,\r\n ...colors,\r\n }), baseColors);\r\n}\r\n\r\n/**\r\n * Deep merge utility for complex theme objects\r\n */\r\nexport function deepMergeThemes(target: Theme, ...sources: Array<Partial<Theme>>): Theme {\r\n return sources.reduce((merged: Theme, source): Theme => {\r\n const result = { ...merged };\r\n \r\n for (const key in source) {\r\n const sourceValue = source[key as keyof Theme];\r\n const targetValue = merged[key as keyof Theme];\r\n \r\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object') {\r\n result[key as keyof Theme] = {\r\n ...targetValue,\r\n ...sourceValue,\r\n } as any;\r\n } else if (sourceValue !== undefined) {\r\n result[key as keyof Theme] = sourceValue as any;\r\n }\r\n }\r\n \r\n return result;\r\n }, target);\r\n}\r\n"],"mappings":"AAGA,IAAMA,EAA2B,CAE/B,WAAY,UACZ,oBAAqB,UACrB,mBAAoB,UAGpB,KAAM,UACN,cAAe,UACf,UAAW,UAGX,OAAQ,UACR,YAAa,UACb,YAAa,UAGb,QAAS,UACT,aAAc,UACd,cAAe,UAGf,QAAS,UACT,QAAS,UACT,MAAO,UACP,KAAM,UAGN,MAAO,UACP,OAAQ,UACR,MAAO,0BAGP,OAAQ,kCACR,SAAU,wEACV,SAAU,yEACZ,EAGMC,EAA0B,CAE9B,WAAY,UACZ,oBAAqB,UACrB,mBAAoB,UAGpB,KAAM,UACN,cAAe,UACf,UAAW,UAGX,OAAQ,UACR,YAAa,UACb,YAAa,UAGb,QAAS,UACT,aAAc,UACd,cAAe,UAGf,QAAS,UACT,QAAS,UACT,MAAO,UACP,KAAM,UAGN,MAAO,UACP,OAAQ,UACR,MAAO,0BAGP,OAAQ,iCACR,SAAU,uEACV,SAAU,wEACZ,EAGMC,EAAY,CAChB,QAAS,CACP,GAAI,UACJ,GAAI,SACJ,GAAI,UACJ,GAAI,OACJ,GAAI,UACJ,MAAO,SACP,MAAO,OACP,MAAO,MACT,EACA,OAAQ,CACN,KAAM,IACN,GAAI,UACJ,GAAI,WACJ,GAAI,SACJ,GAAI,UACJ,MAAO,OACP,KAAM,QACR,EACA,WAAY,CACV,WAAY,CACV,KAAM,oIACN,MAAO,8DACP,KAAM,wFACR,EACA,SAAU,CACR,GAAI,UACJ,GAAI,WACJ,KAAM,OACN,GAAI,WACJ,GAAI,UACJ,MAAO,SACP,MAAO,WACP,MAAO,UACP,MAAO,MACT,EACA,WAAY,CACV,MAAO,MACP,OAAQ,MACR,OAAQ,MACR,SAAU,MACV,KAAM,KACR,EACA,WAAY,CACV,MAAO,OACP,OAAQ,MACR,QAAS,MACX,CACF,EACA,YAAa,CACX,KAAM,gBACN,OAAQ,gBACR,KAAM,gBACN,OAAQ,iDACV,EACA,OAAQ,CACN,SAAU,IACV,MAAO,KACP,QAAS,KACT,QAAS,IACX,CACF,EAGaC,EAAoB,CAC/B,KAAM,QACN,KAAM,QACN,OAAQH,EACR,GAAGE,CACL,EAGaE,EAAmB,CAC9B,KAAM,OACN,KAAM,OACN,OAAQH,EACR,GAAGC,CACL,EAGaG,EAAeF,EAGfG,EAAS,CACpB,MAAOH,EACP,KAAMC,CACR,EAGaG,EAAgB,CAC3B,QAASJ,EACT,MAAOA,EACP,KAAMC,CACR,EAGO,SAASI,EAAWN,EAAkBO,EAAoC,CAC/E,MAAO,CACL,GAAGP,EACH,GAAGO,EACH,OAAQ,CACN,GAAGP,EAAU,OACb,GAAGO,EAAY,MACjB,EACA,QAAS,CACP,GAAGP,EAAU,QACb,GAAGO,EAAY,OACjB,EACA,OAAQ,CACN,GAAGP,EAAU,OACb,GAAGO,EAAY,MACjB,EACA,WAAY,CACV,GAAGP,EAAU,WACb,GAAGO,EAAY,WACf,WAAY,CACV,GAAGP,EAAU,WAAW,WACxB,GAAGO,EAAY,YAAY,UAC7B,EACA,SAAU,CACR,GAAGP,EAAU,WAAW,SACxB,GAAGO,EAAY,YAAY,QAC7B,EACA,WAAY,CACV,GAAGP,EAAU,WAAW,WACxB,GAAGO,EAAY,YAAY,UAC7B,EACA,WAAY,CACV,GAAGP,EAAU,WAAW,WACxB,GAAGO,EAAY,YAAY,UAC7B,CACF,EACA,YAAa,CACX,GAAGP,EAAU,YACb,GAAGO,EAAY,WACjB,EACA,OAAQ,CACN,GAAGP,EAAU,OACb,GAAGO,EAAY,MACjB,CACF,CACF,CC9NA,OAAS,iBAAAC,EAAe,cAAAC,EAAY,aAAAC,EAAW,YAAAC,MAA2B,QCInE,SAASC,EAAWC,EAAcC,EAAuB,CAC9D,GAAI,OAAO,SAAa,IAAa,OAErC,IAAMC,EAAO,SAAS,gBAGlBC,EAAgBF,EAChBA,IAAS,SACXE,EAAgB,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAAS,SAIvFD,EAAK,aAAa,aAAcF,EAAM,IAAI,EAC1CE,EAAK,aAAa,kBAAmBC,CAAa,EAGlD,OAAO,QAAQH,EAAM,MAAM,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACrDH,EAAK,MAAM,YAAY,iBAAiBI,EAAUF,CAAG,CAAC,GAAIC,CAAK,CACjE,CAAC,EAGD,OAAO,QAAQL,EAAM,OAAO,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACtDH,EAAK,MAAM,YAAY,mBAAmBE,CAAG,GAAIC,CAAK,CACxD,CAAC,EAGD,OAAO,QAAQL,EAAM,MAAM,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACrDH,EAAK,MAAM,YAAY,kBAAkBE,CAAG,GAAIC,CAAK,CACvD,CAAC,EAGD,OAAO,QAAQL,EAAM,WAAW,UAAU,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACpEH,EAAK,MAAM,YAAY,uBAAuBE,CAAG,GAAIC,CAAK,CAC5D,CAAC,EAED,OAAO,QAAQL,EAAM,WAAW,QAAQ,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CAClEH,EAAK,MAAM,YAAY,qBAAqBE,CAAG,GAAIC,CAAK,CAC1D,CAAC,EAED,OAAO,QAAQL,EAAM,WAAW,UAAU,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACpEH,EAAK,MAAM,YAAY,uBAAuBE,CAAG,GAAIC,CAAK,CAC5D,CAAC,EAED,OAAO,QAAQL,EAAM,WAAW,UAAU,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACpEH,EAAK,MAAM,YAAY,uBAAuBE,CAAG,GAAIC,CAAK,CAC5D,CAAC,EAGD,OAAO,QAAQL,EAAM,WAAW,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CAC1DH,EAAK,MAAM,YAAY,sBAAsBE,CAAG,GAAIC,CAAK,CAC3D,CAAC,EAGD,OAAO,QAAQL,EAAM,MAAM,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACrDH,EAAK,MAAM,YAAY,mBAAmBI,EAAUF,CAAG,CAAC,GAAIC,EAAM,SAAS,CAAC,CAC9E,CAAC,EAGD,SAAS,KAAK,UAAY,SAAS,KAAK,UAAU,QAAQ,aAAc,EAAE,EAC1E,SAAS,KAAK,UAAU,IAAI,SAASL,EAAM,IAAI,GAAI,SAASG,CAAa,EAAE,CAC7E,CA8BA,SAASI,EAAUC,EAAqB,CACtC,OAAOA,EAAI,QAAQ,SAAWC,GAAU,IAAIA,EAAM,YAAY,CAAC,EAAE,CACnE,CDuCI,cAAAC,MAAA,oBAzHJ,IAAMC,EAAeC,EAA4C,MAAS,EAY7DC,EAA8C,CAAC,CAC1D,SAAAC,EACA,YAAAC,EAAc,OACd,aAAAC,EAAe,UACf,YAAAC,EAAc,GACd,WAAAC,EAAa,sBACb,aAAAC,EAAe,CAAC,CAClB,IAAM,CACJ,IAAMC,EAAY,CAAE,GAAGC,EAAe,GAAGF,CAAa,EAGhDG,EAAiB,IAAiB,CACtC,GAAI,CAACL,GAAe,OAAO,OAAW,IAAa,OAAOF,EAE1D,GAAI,CACF,IAAMQ,EAAS,aAAa,QAAQL,CAAU,EAC9C,GAAIK,GAAU,CAAC,QAAS,OAAQ,MAAM,EAAE,SAASA,CAAM,EACrD,OAAOA,CAEX,OAASC,EAAO,CACd,QAAQ,KAAK,+CAAgDA,CAAK,CACpE,CAEA,OAAOT,CACT,EACM,CAACU,EAAMC,CAAY,EAAIC,EAAoBL,CAAc,EACzD,CAACM,EAAkBC,CAAmB,EAAIF,EAAiBX,CAAY,EAGvEc,EAAmB,IACnBL,IAAS,OACP,OAAO,OAAW,KACb,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAE9D,QAEFA,EAGHM,EAAkB,IAAa,CACnC,IAAMC,EAAgBF,EAAiB,EAGvC,OAAIF,IAAqB,WAAaA,KAAoBR,EACjDA,EAAUQ,CAA0C,EAItDI,IAAkB,OAASZ,EAAU,KAAOA,EAAU,KAC/D,EAEMa,EAAeF,EAAgB,EAG/BG,EAAWC,GAAuB,CAGtC,GAFAT,EAAaS,CAAO,EAEhBlB,GAAe,OAAO,OAAW,IACnC,GAAI,CACF,aAAa,QAAQC,EAAYiB,CAAO,CAC1C,OAASX,EAAO,CACd,QAAQ,KAAK,6CAA8CA,CAAK,CAClE,CAEJ,EAGMY,EAAa,IAAM,CACvB,GAAIX,IAAS,OAAQ,CAEnB,IAAMY,EAAa,OAAO,WAAW,8BAA8B,EAAE,QACrEH,EAAQG,EAAa,QAAU,MAAM,CACvC,MACEH,EAAQT,IAAS,QAAU,OAAS,OAAO,CAE/C,EAEMa,EAAYC,GAAiB,CACjCV,EAAoBU,EAAM,IAAI,CAChC,EAEAC,EAAU,IAAM,CACdC,EAAWR,EAAcR,CAAI,CAC/B,EAAG,CAACQ,EAAcR,EAAMG,CAAgB,CAAC,EAGzCY,EAAU,IAAM,CACd,GAAIf,IAAS,OAAQ,OAErB,IAAMiB,EAAa,OAAO,WAAW,8BAA8B,EAC7DC,EAAe,IAAM,CAEzBF,EAAWV,EAAgB,EAAGN,CAAI,CACpC,EAEA,OAAAiB,EAAW,iBAAiB,SAAUC,CAAY,EAC3C,IAAMD,EAAW,oBAAoB,SAAUC,CAAY,CACpE,EAAG,CAAClB,CAAI,CAAC,EAET,IAAMmB,EAAiC,CACrC,aAAAX,EACA,KAAAR,EACA,QAAAS,EACA,SAAAI,EACA,OAAQlB,EACR,WAAAgB,CACF,EAEA,OACE1B,EAACC,EAAa,SAAb,CAAsB,MAAOiC,EAC3B,SAAA9B,EACH,CAEJ,EAEa+B,EAAkB,IAAM,CACnC,IAAMC,EAAUC,EAAWpC,CAAY,EACvC,GAAImC,IAAY,OACd,MAAM,IAAI,MAAM,qDAAqD,EAEvE,OAAOA,CACT,EE/IO,SAASE,GAA6B,CAC3C,OAAOC,EAAgB,CACzB,CCFO,SAASC,GAAiB,CAC/B,GAAM,CAAE,KAAAC,EAAM,QAAAC,EAAS,WAAAC,CAAW,EAAIC,EAAS,EAazCC,EATAJ,IAAS,OACP,OAAO,OAAW,KACb,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAE9D,QAEFA,EAKT,MAAO,CACL,KAAAA,EACA,QAAAC,EACA,WAAAC,EACA,OAAQE,IAAkB,OAC1B,QAASA,IAAkB,QAC3B,OAAQJ,IAAS,OACjB,cAAAI,CACF,CACF,CC8BI,OAOE,OAAAC,EAPF,QAAAC,MAAA,oBAlDG,IAAMC,EAA0C,CAAC,CACtD,UAAAC,EAAY,GACZ,MAAAC,EAAQ,CAAC,EACT,WAAAC,EAAa,GACb,KAAAC,EAAO,IACT,IAAM,CACJ,GAAM,CAAE,KAAAC,EAAM,WAAAC,CAAW,EAAIC,EAAS,EAQhCC,EAAc;AAAA,MANA,CAClB,GAAI,kBACJ,GAAI,sBACJ,GAAI,mBACN,EAGgBJ,CAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOjBH,CAAS;AAAA,IACX,KAAK,EAEDQ,EAAU,IAAM,CACpB,OAAQJ,EAAM,CACZ,IAAK,QACH,MAAO,eACT,IAAK,OACH,MAAO,YACT,IAAK,OACL,QACE,MAAO,WACX,CACF,EAEMK,EAAW,IAAM,CACrB,OAAQL,EAAM,CACZ,IAAK,QACH,MAAO,QACT,IAAK,OACH,MAAO,OACT,IAAK,OACL,QACE,MAAO,MACX,CACF,EAEA,OACEN,EAAC,UACC,QAASO,EACT,UAAWE,EACX,MAAON,EACP,MAAO,kBAAkBQ,EAAS,CAAC,qBACnC,aAAY,0BAA0BA,EAAS,CAAC,GAEhD,UAAAZ,EAAC,QAAK,KAAK,MAAM,cAAY,OAC1B,SAAAW,EAAQ,EACX,EACCN,GACCL,EAAC,QAAK,UAAU,2BACb,SAAAY,EAAS,EACZ,GAEJ,CAEJ,EChCQ,cAAAC,MAAA,oBA9BD,IAAMC,EAA8C,CAAC,CAC1D,UAAAC,EAAY,GACZ,MAAAC,EAAQ,CAAC,EACT,WAAAC,EAAa,GACb,QAAAC,EAAU,CACR,CAAE,KAAM,QAAS,MAAO,QAAS,KAAM,cAAK,EAC5C,CAAE,KAAM,OAAQ,MAAO,OAAQ,KAAM,WAAK,EAC1C,CAAE,KAAM,OAAQ,MAAO,OAAQ,KAAM,WAAK,CAC5C,CACF,IAAM,CACJ,GAAM,CAAE,KAAAC,EAAM,QAAAC,CAAQ,EAAIC,EAAS,EAE7BC,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMhBP,CAAS;AAAA,IACX,KAAK,EAEP,OACEF,EAAC,UACC,MAAOM,EACP,SAAWI,GAAMH,EAAQG,EAAE,OAAO,KAAkB,EACpD,UAAWD,EACX,MAAON,EACP,aAAW,oBAEV,SAAAE,EAAQ,IAAKM,GACZX,EAAC,UAAyB,MAAOW,EAAO,KACrC,SAAAP,EACG,GAAGO,EAAO,KAAOA,EAAO,KAAO,IAAM,EAAE,GAAGA,EAAO,KAAK,GACtDA,EAAO,MAAQA,EAAO,OAHfA,EAAO,IAIpB,CACD,EACH,CAEJ,EChDO,SAASC,EACdC,EACAC,EACO,CACP,MAAO,CACL,GAAGD,EACH,GAAGC,EACH,KAAMA,EAAY,MAAQ,GAAGD,EAAU,IAAI,UAC3C,OAAQ,CACN,GAAGA,EAAU,OACb,GAAGC,EAAY,MACjB,EACA,QAAS,CACP,GAAGD,EAAU,QACb,GAAGC,EAAY,OACjB,EACA,OAAQ,CACN,GAAGD,EAAU,OACb,GAAGC,EAAY,MACjB,EACA,WAAY,CACV,GAAGD,EAAU,WACb,GAAGC,EAAY,WACf,WAAY,CACV,GAAGD,EAAU,WAAW,WACxB,GAAGC,EAAY,YAAY,UAC7B,EACA,SAAU,CACR,GAAGD,EAAU,WAAW,SACxB,GAAGC,EAAY,YAAY,QAC7B,EACA,WAAY,CACV,GAAGD,EAAU,WAAW,WACxB,GAAGC,EAAY,YAAY,UAC7B,EACA,WAAY,CACV,GAAGD,EAAU,WAAW,WACxB,GAAGC,EAAY,YAAY,UAC7B,CACF,EACA,YAAa,CACX,GAAGD,EAAU,YACb,GAAGC,EAAY,WACjB,EACA,OAAQ,CACN,GAAGD,EAAU,OACb,GAAGC,EAAY,MACjB,CACF,CACF,CChDO,SAASC,KAAeC,EAA8C,CAC3E,GAAIA,EAAO,SAAW,EACpB,MAAM,IAAI,MAAM,oDAAoD,EAGtE,GAAM,CAACC,EAAW,GAAGC,CAAgB,EAAIF,EAEzC,GAAI,CAACG,EAAYF,CAAS,EACxB,MAAM,IAAI,MAAM,6CAA6C,EAE/D,OAAOC,EAAiB,OAAO,CAACE,EAAeC,KACtC,CACL,GAAGD,EACH,GAAGC,EACH,KAAMA,EAAM,MAAQD,EAAO,KAC3B,KAAMC,EAAM,MAAQD,EAAO,KAC3B,OAAQ,CACN,GAAGA,EAAO,OACV,GAAGC,EAAM,MACX,EACA,QAAS,CACP,GAAGD,EAAO,QACV,GAAGC,EAAM,OACX,EACA,OAAQ,CACN,GAAGD,EAAO,OACV,GAAGC,EAAM,MACX,EACA,WAAY,CACV,GAAGD,EAAO,WACV,GAAGC,EAAM,WACT,WAAY,CACV,GAAGD,EAAO,WAAW,WACrB,GAAGC,EAAM,YAAY,UACvB,EACA,SAAU,CACR,GAAGD,EAAO,WAAW,SACrB,GAAGC,EAAM,YAAY,QACvB,EACA,WAAY,CACV,GAAGD,EAAO,WAAW,WACrB,GAAGC,EAAM,YAAY,UACvB,EACA,WAAY,CACV,GAAGD,EAAO,WAAW,WACrB,GAAGC,EAAM,YAAY,UACvB,CACF,EACA,YAAa,CACX,GAAGD,EAAO,YACV,GAAGC,EAAM,WACX,EACA,OAAQ,CACN,GAAGD,EAAO,OACV,GAAGC,EAAM,MACX,CACF,GACCJ,CAAS,CACd,CAKA,SAASE,EAAYE,EAA+C,CAClE,MAAO,CAAC,EACNA,GACA,OAAOA,GAAU,UACjB,SAAUA,GACV,SAAUA,GACV,WAAYA,GACZ,YAAaA,GACb,WAAYA,GACZ,eAAgBA,GAChB,gBAAiBA,GACjB,WAAYA,EAEhB,CAKO,SAASC,EACdC,KACGC,EACc,CACjB,OAAOA,EAAU,OAAO,CAACJ,EAAyBK,KAA6B,CAC7E,GAAGL,EACH,GAAGK,CACL,GAAIF,CAAU,CAChB,CAKO,SAASG,EAAgBC,KAAkBC,EAAuC,CACvF,OAAOA,EAAQ,OAAO,CAACR,EAAeS,IAAkB,CACtD,IAAMC,EAAS,CAAE,GAAGV,CAAO,EAE3B,QAAWW,KAAOF,EAAQ,CACxB,IAAMG,EAAcH,EAAOE,CAAkB,EACvCE,EAAcb,EAAOW,CAAkB,EAEzCC,GAAe,OAAOA,GAAgB,UAAY,CAAC,MAAM,QAAQA,CAAW,GAAKC,GAAe,OAAOA,GAAgB,SACzHH,EAAOC,CAAkB,EAAI,CAC3B,GAAGE,EACH,GAAGD,CACL,EACSA,IAAgB,SACzBF,EAAOC,CAAkB,EAAIC,EAEjC,CAEA,OAAOF,CACT,EAAGH,CAAM,CACX","names":["lightColors","darkColors","baseTheme","lightTheme","darkTheme","defaultTheme","themes","defaultThemes","mergeTheme","customTheme","createContext","useContext","useEffect","useState","applyTheme","theme","mode","root","effectiveMode","key","value","kebabCase","kebabCase","str","match","jsx","ThemeContext","createContext","ThemeProvider","children","defaultMode","defaultTheme","persistMode","storageKey","customThemes","allThemes","defaultThemes","getInitialMode","stored","error","mode","setModeState","useState","currentThemeName","setCurrentThemeName","getEffectiveMode","getCurrentTheme","effectiveMode","currentTheme","setMode","newMode","toggleMode","systemDark","setTheme","theme","useEffect","applyTheme","mediaQuery","handleChange","contextValue","useThemeContext","context","useContext","useTheme","useThemeContext","useThemeToggle","mode","setMode","toggleMode","useTheme","effectiveMode","jsx","jsxs","ThemeToggle","className","style","showLabels","size","mode","toggleMode","useTheme","buttonClass","getIcon","getLabel","jsx","ThemeSelector","className","style","showLabels","options","mode","setMode","useTheme","selectClass","e","option","createTheme","baseTheme","customTheme","mergeThemes","themes","baseTheme","additionalThemes","isFullTheme","merged","theme","mergeThemeColors","baseColors","colorSets","colors","deepMergeThemes","target","sources","source","result","key","sourceValue","targetValue"]}