zentrixui
Version:
ZentrixUI - A modern, highly customizable and accessible React file upload component library with multiple variants, JSON-based configuration, and excellent developer experience.
1 lines • 8.58 kB
Source Map (JSON)
{"version":3,"file":"theme.cjs","sources":["../src/lib/components/theme-provider.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'\r\nimport { FileUploadConfig, FileUploadTheme } from './file-upload/file-upload.types'\r\nimport { applyTheme, resolveTheme, createThemeWatcher, getSystemTheme } from '../utils/theme'\r\n\r\ninterface ThemeContextValue {\r\n theme: FileUploadTheme\r\n resolvedTheme: 'light' | 'dark'\r\n setTheme: (theme: FileUploadTheme) => void\r\n config?: FileUploadConfig\r\n setConfig: (config: FileUploadConfig) => void\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined)\r\n\r\ninterface ThemeProviderProps {\r\n children: ReactNode\r\n defaultTheme?: FileUploadTheme\r\n config?: FileUploadConfig\r\n storageKey?: string\r\n}\r\n\r\nexport function ThemeProvider({\r\n children,\r\n defaultTheme = 'auto',\r\n config,\r\n storageKey = 'file-upload-theme'\r\n}: ThemeProviderProps) {\r\n const [theme, setThemeState] = useState<FileUploadTheme>(defaultTheme)\r\n const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light')\r\n const [themeConfig, setThemeConfig] = useState<FileUploadConfig | undefined>(config)\r\n\r\n // Initialize theme from localStorage or default\r\n useEffect(() => {\r\n if (typeof window !== 'undefined') {\r\n const stored = localStorage.getItem(storageKey) as FileUploadTheme\r\n if (stored && ['light', 'dark', 'auto'].includes(stored)) {\r\n setThemeState(stored)\r\n }\r\n }\r\n }, [storageKey])\r\n\r\n // Update resolved theme when theme changes\r\n useEffect(() => {\r\n const resolved = resolveTheme(theme)\r\n setResolvedTheme(resolved)\r\n applyTheme(theme, themeConfig)\r\n }, [theme, themeConfig])\r\n\r\n // Watch for system theme changes when theme is 'auto'\r\n useEffect(() => {\r\n if (theme === 'auto') {\r\n const cleanup = createThemeWatcher((systemTheme) => {\r\n setResolvedTheme(systemTheme)\r\n applyTheme('auto', themeConfig)\r\n })\r\n return cleanup\r\n }\r\n }, [theme, themeConfig])\r\n\r\n const setTheme = (newTheme: FileUploadTheme) => {\r\n setThemeState(newTheme)\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem(storageKey, newTheme)\r\n }\r\n }\r\n\r\n const setConfig = (newConfig: FileUploadConfig) => {\r\n setThemeConfig(newConfig)\r\n }\r\n\r\n const value: ThemeContextValue = {\r\n theme,\r\n resolvedTheme,\r\n setTheme,\r\n config: themeConfig,\r\n setConfig\r\n }\r\n\r\n return (\r\n <ThemeContext.Provider value={value}>\r\n {children}\r\n </ThemeContext.Provider>\r\n )\r\n}\r\n\r\nexport function useTheme() {\r\n const context = useContext(ThemeContext)\r\n if (context === undefined) {\r\n throw new Error('useTheme must be used within a ThemeProvider')\r\n }\r\n return context\r\n}\r\n\r\n/**\r\n * Hook to get theme-aware CSS variables\r\n */\r\nexport function useThemeVariables() {\r\n const { config, resolvedTheme } = useTheme()\r\n\r\n return React.useMemo(() => {\r\n if (!config?.styling) return {}\r\n\r\n const variables: Record<string, string> = {}\r\n const { colors, spacing, typography, borders, shadows } = config.styling\r\n\r\n // Apply color variables\r\n if (colors) {\r\n Object.entries(colors).forEach(([key, value]) => {\r\n variables[`--file-upload-${key}`] = value\r\n })\r\n }\r\n\r\n // Apply spacing variables\r\n if (spacing) {\r\n Object.entries(spacing).forEach(([key, value]) => {\r\n variables[`--file-upload-spacing-${key}`] = value\r\n })\r\n }\r\n\r\n // Apply typography variables\r\n if (typography) {\r\n Object.entries(typography).forEach(([key, value]) => {\r\n variables[`--file-upload-${key}`] = value\r\n })\r\n }\r\n\r\n // Apply border variables\r\n if (borders) {\r\n Object.entries(borders).forEach(([key, value]) => {\r\n variables[`--file-upload-border-${key}`] = value\r\n })\r\n }\r\n\r\n // Apply shadow variables\r\n if (shadows) {\r\n Object.entries(shadows).forEach(([key, value]) => {\r\n variables[`--file-upload-shadow-${key}`] = value\r\n })\r\n }\r\n\r\n return variables\r\n }, [config, resolvedTheme])\r\n}\r\n\r\n/**\r\n * Component to toggle between themes\r\n */\r\ninterface ThemeToggleProps {\r\n className?: string\r\n children?: ReactNode\r\n}\r\n\r\nexport function ThemeToggle({ className, children }: ThemeToggleProps) {\r\n const { theme, setTheme } = useTheme()\r\n\r\n const toggleTheme = () => {\r\n const themes: FileUploadTheme[] = ['light', 'dark', 'auto']\r\n const currentIndex = themes.indexOf(theme)\r\n const nextIndex = (currentIndex + 1) % themes.length\r\n setTheme(themes[nextIndex])\r\n }\r\n\r\n return (\r\n <button\r\n onClick={toggleTheme}\r\n className={className}\r\n aria-label={`Switch to ${theme === 'light' ? 'dark' : theme === 'dark' ? 'auto' : 'light'} theme`}\r\n >\r\n {children || (\r\n <span>\r\n {theme === 'light' ? '🌙' : theme === 'dark' ? '🌓' : '☀️'}\r\n </span>\r\n )}\r\n </button>\r\n )\r\n}"],"names":["createContext","theme","useState","useEffect","resolveTheme","applyTheme","createThemeWatcher","jsx","useContext"],"mappings":"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"}