import React, { useState, useCallback } from ‘react’; import { generateImagesService } from ‘./services/geminiService’; import { STYLES, ASPECT_RATIOS } from ‘./constants’; import type { ImageStyle, AspectRatio, GenerationOptions, HistoryItem } from ‘./types’; import Loader from ‘./components/Loader’; import { OptionSelector } from ‘./components/OptionSelector’; const Header: React.FC = () => (

CyberCanvas

AI-Powered Image Synthesis Engine

); const ImageDisplay: React.FC<{ imageUrl: string | null; isLoading: boolean; error: string | null }> = ({ imageUrl, isLoading, error }) => (
{isLoading && } {error && !isLoading && (

Generation Failed

{error}

)} {!isLoading && !error && imageUrl && (
Generated art Download
)} {!isLoading && !error && !imageUrl && (

Your generated image will appear here.

Describe a vision, and let the AI paint it.

)}
); const HistoryPanel: React.FC<{ history: HistoryItem[], onSelect: (item: HistoryItem) => void }> = ({ history, onSelect }) => (

History

{history.length === 0 ? (

No generations yet.

) : (
{history.map(item => (
onSelect(item)} className=»group flex items-center gap-3 p-2 rounded-md bg-gray-700/50 hover:bg-cyan-900/50 cursor-pointer transition-colors duration-200″ > {item.prompt}

{item.prompt}

))}
)}
); function App() { const [prompt, setPrompt] = useState(«A futuristic cityscape at night, with flying cars and neon signs, in a synthwave style.»); const [options, setOptions] = useState({ style: ‘Cyberpunk’, aspectRatio: ’16:9′, }); const [generatedImageUrl, setGeneratedImageUrl] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [history, setHistory] = useState([]); const handleGenerate = useCallback(async () => { if (!prompt || isLoading) return; setIsLoading(true); setError(null); setGeneratedImageUrl(null); try { const images = await generateImagesService(prompt, options); if (images && images.length > 0) { const imageUrl = images[0]; setGeneratedImageUrl(imageUrl); const newHistoryItem: HistoryItem = { id: new Date().toISOString(), prompt, imageUrl, options, }; setHistory(prev => [newHistoryItem, …prev.slice(0, 19)]); // Keep history to 20 items } else { setError(«The model did not return an image. Try a different prompt.»); } } catch (e) { setError(e instanceof Error ? e.message : «An unknown error occurred.»); } finally { setIsLoading(false); } }, [prompt, options, isLoading]); const handleHistorySelect = (item: HistoryItem) => { setPrompt(item.prompt); setOptions(item.options); setGeneratedImageUrl(item.imageUrl); }; return (