admin08077/Githubgemini
0
1{"version":3,"file":"ThemeDesigner-DPl6yDXo.js","sources":["../../components/features/ThemeDesigner.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport { SparklesIcon, ArrowDownTrayIcon, PhotoIcon } from '../icons.tsx';\nimport { generateSemanticTheme } from '../../services/index.ts';\nimport { fileToBase64 } from '../../services/fileUtils.ts';\nimport type { SemanticColorTheme, ColorTheme } from '../../types.ts';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { useTheme } from '../../hooks/useTheme.ts';\n\nconst ColorDisplay: React.FC<{ name: string; color: { name: string; value: string; } }> = ({ name, color }) => (\n <div className=\"flex items-center justify-between p-2 bg-background rounded-md border border-border\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-6 h-6 rounded-full border border-border\" style={{ backgroundColor: color.value }} />\n <div>\n <p className=\"text-sm font-semibold text-text-primary capitalize\">{name}</p>\n <p className=\"text-xs text-text-secondary\">{color.name}</p>\n </div>\n </div>\n <span className=\"font-mono text-sm text-text-secondary\">{color.value}</span>\n </div>\n);\n\nconst AccessibilityCheck: React.FC<{ name: string, check: { ratio: number; score: string; } }> = ({ name, check }) => {\n const scoreColor = check.score === 'AAA' ? 'text-green-600' : check.score === 'AA' ? 'text-emerald-600' : 'text-red-600';\n return (\n <div className=\"flex items-center justify-between p-2 bg-background rounded-md border border-border text-sm\">\n <p className=\"text-text-secondary\">{name}</p>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-mono\">{check.ratio.toFixed(2)}</span>\n <span className={`font-bold px-2 py-0.5 rounded-full text-xs ${scoreColor} ${scoreColor.replace('text-', 'bg-')}/10`}>{check.score}</span>\n </div>\n </div>\n );\n}\n\nexport const ThemeDesigner: React.FC = () => {\n const [theme, setTheme] = useState<SemanticColorTheme | null>(null);\n const [prompt, setPrompt] = useState('A calming, minimalist theme for a blog');\n const [image, setImage] = useState<{ base64: string, name: string } | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n const [, , applyCustomTheme] = useTheme();\n\n const handleGenerate = useCallback(async () => {\n const textPart = { text: `Generate a theme based on this description: \"${prompt}\"` };\n const imagePart = image ? { inlineData: { mimeType: 'image/png', data: image.base64 } } : null;\n const parts = imagePart ? [textPart, imagePart] : [textPart];\n\n setIsLoading(true); setError('');\n try {\n const newTheme = await generateSemanticTheme({ parts });\n setTheme(newTheme);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"An unknown error occurred.\");\n } finally {\n setIsLoading(false);\n }\n }, [prompt, image]);\n \n const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n const base64 = await fileToBase64(file);\n setImage({ base64, name: file.name });\n setPrompt(`A theme based on the uploaded image: ${file.name}`);\n }\n };\n \n useEffect(() => { handleGenerate(); }, []);\n\n const handleApplyTheme = () => {\n if (!theme) return;\n const colorsToApply: ColorTheme = {\n primary: theme.palette.primary.value,\n background: theme.theme.background.value,\n surface: theme.theme.surface.value,\n textPrimary: theme.theme.textPrimary.value,\n textSecondary: theme.theme.textSecondary.value,\n textOnPrimary: theme.theme.textOnPrimary.value,\n border: theme.theme.border.value,\n };\n applyCustomTheme(colorsToApply, theme.mode);\n };\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\"><SparklesIcon /><span className=\"ml-3\">AI Theme Designer</span></h1>\n <p className=\"text-text-secondary mt-1\">Generate a full design system from a description or image.</p>\n </header>\n <div className=\"flex-grow grid grid-cols-1 md:grid-cols-2 gap-6 min-h-0\">\n <div className=\"md:col-span-1 flex flex-col gap-4 bg-surface border border-border p-6 rounded-lg overflow-y-auto\">\n <h3 className=\"text-xl font-bold\">Describe or Upload</h3>\n <textarea value={prompt} onChange={e => setPrompt(e.target.value)} className=\"p-2 bg-background border border-border rounded-md resize-none text-sm h-24\" placeholder=\"e.g., A light, airy theme for a blog\" />\n <div className=\"relative border border-dashed border-border rounded-lg p-4 text-center\">\n <input type=\"file\" onChange={handleFileChange} className=\"absolute inset-0 w-full h-full opacity-0 cursor-pointer\" />\n <PhotoIcon/>\n <p className=\"text-sm mt-1\">{image ? `Image: ${image.name}` : 'Upload an image (optional)'}</p>\n </div>\n <div className=\"flex gap-2\">\n <button onClick={handleGenerate} disabled={isLoading} className=\"btn-primary flex-grow flex items-center justify-center gap-2 px-4 py-2\">\n {isLoading ? <LoadingSpinner /> : 'Generate New Theme'}\n </button>\n <button onClick={handleApplyTheme} disabled={isLoading || !theme} className=\"px-4 py-2 bg-emerald-600 text-white font-bold rounded-md hover:opacity-90 transition-all disabled:opacity-50 shadow-md\">\n Apply to App\n </button>\n </div>\n {error && <p className=\"text-red-500 text-xs text-center\">{error}</p>}\n\n {theme && !isLoading && (\n <div className=\"mt-4 border-t border-border pt-4 space-y-4\">\n <div><h3 className=\"text-lg font-bold mb-2\">Palette</h3><div className=\"space-y-2\"><ColorDisplay name=\"Primary\" color={theme.palette.primary}/><ColorDisplay name=\"Secondary\" color={theme.palette.secondary}/><ColorDisplay name=\"Accent\" color={theme.palette.accent}/><ColorDisplay name=\"Neutral\" color={theme.palette.neutral}/></div></div>\n <div><h3 className=\"text-lg font-bold mb-2\">Theme Roles</h3><div className=\"space-y-2\"><ColorDisplay name=\"Background\" color={theme.theme.background}/><ColorDisplay name=\"Surface\" color={theme.theme.surface}/><ColorDisplay name=\"Text Primary\" color={theme.theme.textPrimary}/><ColorDisplay name=\"Text Secondary\" color={theme.theme.textSecondary}/><ColorDisplay name=\"Text on Primary\" color={theme.theme.textOnPrimary}/><ColorDisplay name=\"Border\" color={theme.theme.border}/></div></div>\n <div><h3 className=\"text-lg font-bold mb-2\">Accessibility (WCAG 2.1)</h3><div className=\"space-y-2\"><AccessibilityCheck name=\"Primary on Surface\" check={theme.accessibility.primaryOnSurface}/><AccessibilityCheck name=\"Text on Surface\" check={theme.accessibility.textPrimaryOnSurface}/><AccessibilityCheck name=\"Subtle Text on Surface\" check={theme.accessibility.textSecondaryOnSurface}/><AccessibilityCheck name=\"Text on Primary\" check={theme.accessibility.textOnPrimaryOnPrimary}/></div></div>\n </div>\n )}\n </div>\n <div className=\"md:col-span-1 rounded-lg p-8 overflow-y-auto border border-border\" style={{ backgroundColor: theme?.theme.background.value, color: theme?.theme.textPrimary.value }}>\n <h3 className=\"text-2xl font-bold mb-6\">Live Preview</h3>\n {theme ? (\n <div className=\"p-6 rounded-lg grid grid-cols-1 md:grid-cols-2 gap-6\" style={{ backgroundColor: theme.theme.surface.value }}>\n <div className=\"space-y-4\">\n <h4 className=\"text-lg font-bold\">Sample Card</h4>\n <p className=\"text-sm\" style={{color: theme.theme.textSecondary.value}}>This is a sample card to demonstrate the theme colors. It contains a primary button and some secondary text.</p>\n <button className=\"px-4 py-2 rounded-md font-bold transition-colors\" style={{ backgroundColor: theme.palette.primary.value, color: theme.theme.textOnPrimary.value }}>Primary Button</button>\n </div>\n <div className=\"space-y-4\">\n <input type=\"text\" placeholder=\"Text input\" className=\"w-full px-3 py-2 rounded-md border\" style={{backgroundColor: theme.theme.background.value, borderColor: theme.theme.border.value, color: theme.theme.textPrimary.value}} />\n <div className=\"p-3 border rounded\" style={{borderColor: theme.theme.border.value, color: theme.theme.textSecondary.value}}>\n <p>A bordered container.</p>\n </div>\n </div>\n </div>\n ) : <div className=\"flex items-center justify-center h-full text-text-secondary\">Theme preview will appear here.</div>}\n </div>\n </div>\n </div>\n );\n};"],"names":["ColorDisplay","name","color","jsxs","jsx","AccessibilityCheck","check","scoreColor","ThemeDesigner","theme","setTheme","useState","prompt","setPrompt","image","setImage","isLoading","setIsLoading","error","setError","applyCustomTheme","useTheme","handleGenerate","useCallback","textPart","imagePart","parts","newTheme","generateSemanticTheme","err","handleFileChange","e","file","base64","fileToBase64","useEffect","handleApplyTheme","colorsToApply","SparklesIcon","PhotoIcon","LoadingSpinner"],"mappings":"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"}