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 • 10.8 kB
Source Map (JSON)
{"version":3,"file":"theme-Bz28eVNI.cjs","sources":["../../src/lib/utils/theme.ts"],"sourcesContent":["import { FileUploadConfig, FileUploadSize, FileUploadRadius, FileUploadTheme } from '../components/file-upload/file-upload.types'\r\n\r\n/**\r\n * Generates CSS class names based on component props and configuration\r\n */\r\nexport function generateThemeClasses(\r\n variant: string,\r\n size: FileUploadSize,\r\n radius: FileUploadRadius,\r\n config?: FileUploadConfig,\r\n additionalClasses?: string[]\r\n): string {\r\n const classes: string[] = ['file-upload']\r\n\r\n // Add variant class\r\n classes.push(`file-upload--${variant}`)\r\n\r\n // Add size class\r\n classes.push(`file-upload--${size}`)\r\n\r\n // Add radius class\r\n classes.push(`file-upload--radius-${radius}`)\r\n\r\n // Add responsive class by default\r\n classes.push('file-upload--responsive')\r\n\r\n // Add additional classes from config or props\r\n if (additionalClasses) {\r\n classes.push(...additionalClasses)\r\n }\r\n\r\n return classes.join(' ')\r\n}\r\n\r\n/**\r\n * Applies theme to document root\r\n */\r\nexport function applyTheme(theme: FileUploadTheme, config?: FileUploadConfig): void {\r\n const root = document.documentElement\r\n\r\n // Set theme attribute\r\n root.setAttribute('data-theme', theme)\r\n\r\n // Apply custom CSS variables if config is provided\r\n if (config?.styling) {\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 root.style.setProperty(`--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 root.style.setProperty(`--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 root.style.setProperty(`--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 root.style.setProperty(`--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 root.style.setProperty(`--file-upload-shadow-${key}`, value)\r\n })\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Gets the current system theme preference\r\n */\r\nexport function getSystemTheme(): 'light' | 'dark' {\r\n if (typeof window !== 'undefined' && window.matchMedia) {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\r\n }\r\n return 'light'\r\n}\r\n\r\n/**\r\n * Resolves the actual theme based on the theme setting\r\n */\r\nexport function resolveTheme(theme: FileUploadTheme): 'light' | 'dark' {\r\n if (theme === 'auto') {\r\n return getSystemTheme()\r\n }\r\n return theme\r\n}\r\n\r\n/**\r\n * Creates a theme watcher that responds to system theme changes\r\n */\r\nexport function createThemeWatcher(\r\n callback: (theme: 'light' | 'dark') => void\r\n): () => void {\r\n if (typeof window === 'undefined' || !window.matchMedia) {\r\n return () => { }\r\n }\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\r\n\r\n const handler = (e: MediaQueryListEvent) => {\r\n callback(e.matches ? 'dark' : 'light')\r\n }\r\n\r\n mediaQuery.addEventListener('change', handler)\r\n\r\n return () => {\r\n mediaQuery.removeEventListener('change', handler)\r\n }\r\n}\r\n\r\n/**\r\n * Generates CSS variables object for inline styles\r\n */\r\nexport function generateCSSVariables(config: FileUploadConfig): Record<string, string> {\r\n const variables: Record<string, string> = {}\r\n\r\n if (config.styling) {\r\n const { colors, spacing, typography, borders, shadows } = config.styling\r\n\r\n // Add 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 // Add 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 // Add 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 // Add 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 // Add 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\r\n return variables\r\n}\r\n\r\n/**\r\n * Utility to combine class names conditionally\r\n */\r\nexport function cn(...classes: (string | undefined | null | false)[]): string {\r\n return classes.filter(Boolean).join(' ')\r\n}\r\n\r\n/**\r\n * Gets responsive class names based on screen size\r\n */\r\nexport function getResponsiveClasses(\r\n size: FileUploadSize,\r\n variant: string\r\n): string[] {\r\n const classes: string[] = []\r\n\r\n // Add responsive classes based on variant\r\n switch (variant) {\r\n case 'dropzone':\r\n classes.push('file-upload--sm:responsive', 'file-upload--md:responsive')\r\n break\r\n case 'multi-file':\r\n classes.push('file-upload--sm:stack', 'file-upload--md:stack')\r\n break\r\n default:\r\n classes.push('file-upload--responsive')\r\n }\r\n\r\n return classes\r\n}\r\n\r\n/**\r\n * Validates theme configuration\r\n */\r\nexport function validateThemeConfig(config: Partial<FileUploadConfig>): {\r\n isValid: boolean\r\n errors: string[]\r\n} {\r\n const errors: string[] = []\r\n\r\n if (config.styling?.colors) {\r\n const hexPattern = /^#[0-9a-fA-F]{6}$/\r\n Object.entries(config.styling.colors).forEach(([key, value]) => {\r\n if (typeof value === 'string' && !hexPattern.test(value)) {\r\n errors.push(`Invalid color format for ${key}: ${value}. Expected hex format like #ffffff`)\r\n }\r\n })\r\n }\r\n\r\n if (config.styling?.spacing) {\r\n Object.entries(config.styling.spacing).forEach(([key, value]) => {\r\n if (typeof value === 'string' && !value.match(/^\\d+(\\.\\d+)?(px|rem|em|%)$/)) {\r\n errors.push(`Invalid spacing format for ${key}: ${value}. Expected CSS unit like 1rem, 16px, etc.`)\r\n }\r\n })\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n }\r\n}"],"names":[],"mappings":"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"}