admin08077/Githubgemini
0
1{"version":3,"file":"AiImageGenerator-DdG4FXBe.js","sources":["../../components/features/AiImageGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef } from 'react';\nimport { generateImage, generateImageFromImageAndText } from '../../services/aiService.ts';\nimport { fileToBase64, blobToDataURL } from '../../services/fileUtils.ts';\nimport { ImageGeneratorIcon, SparklesIcon, ArrowDownTrayIcon, XMarkIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\n\nconst surprisePrompts = [\n 'A majestic lion wearing a crown, painted in the style of Van Gogh.',\n 'A futuristic cityscape on another planet with two moons in the sky.',\n 'A cozy, magical library inside a giant tree.',\n 'A surreal image of a ship sailing on a sea of clouds.',\n 'An astronaut riding a space-themed bicycle on the moon.',\n];\n\ninterface UploadedImage {\n base64: string;\n dataUrl: string;\n mimeType: string;\n}\n\nexport const AiImageGenerator: React.FC = () => {\n const [prompt, setPrompt] = useState<string>('A photorealistic image of a futuristic city at sunset, with flying cars.');\n const [uploadedImage, setUploadedImage] = useState<UploadedImage | null>(null);\n const [generatedImageUrl, setGeneratedImageUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleGenerate = useCallback(async () => {\n if (!prompt.trim()) {\n setError('Please enter a prompt to generate an image.');\n return;\n }\n setIsLoading(true);\n setError('');\n setGeneratedImageUrl(null);\n try {\n let resultUrl: string;\n if (uploadedImage) {\n resultUrl = await generateImageFromImageAndText(prompt, uploadedImage.base64, uploadedImage.mimeType);\n } else {\n resultUrl = await generateImage(prompt);\n }\n setGeneratedImageUrl(resultUrl);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate image: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [prompt, uploadedImage]);\n\n const handleSurpriseMe = () => {\n const randomPrompt = surprisePrompts[Math.floor(Math.random() * surprisePrompts.length)];\n setPrompt(randomPrompt);\n };\n\n const processImageBlob = async (blob: Blob) => {\n try {\n const [dataUrl, base64] = await Promise.all([\n blobToDataURL(blob),\n fileToBase64(blob as File)\n ]);\n setUploadedImage({ dataUrl, base64, mimeType: blob.type });\n } catch (e) {\n setError('Could not process the image.');\n }\n };\n\n const handlePaste = useCallback(async (event: React.ClipboardEvent) => {\n const items = event.clipboardData.items;\n for (const item of items) {\n if (item.type.indexOf('image') !== -1) {\n const blob = item.getAsFile();\n if (blob) {\n await processImageBlob(blob);\n return;\n }\n }\n }\n }, []);\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n if (file) {\n await processImageBlob(file);\n }\n };\n \n const handleDownload = () => {\n if (!generatedImageUrl) return;\n const link = document.createElement('a');\n link.href = generatedImageUrl;\n link.download = `${prompt.slice(0, 30).replace(/\\s/g, '_')}.png`;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\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\">\n <ImageGeneratorIcon />\n <span className=\"ml-3\">AI Image Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Generate images from text, or provide an image for inspiration.</p>\n </header>\n \n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 min-h-0\">\n {/* Left Column: Inputs */}\n <div className=\"flex flex-col gap-4\">\n <div>\n <label htmlFor=\"prompt-input\" className=\"text-sm font-medium text-text-secondary\">Your Prompt</label>\n <textarea\n id=\"prompt-input\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder=\"e.g., A cute cat wearing a wizard hat\"\n className=\"w-full p-3 mt-1 rounded-md bg-surface border border-border focus:ring-2 focus:ring-primary focus:outline-none resize-y\"\n rows={3}\n />\n </div>\n \n <div className=\"flex flex-col flex-grow min-h-[200px]\">\n <label className=\"text-sm font-medium text-text-secondary mb-1\">Inspiration Image (Optional)</label>\n <div onPaste={handlePaste} className=\"relative flex-grow flex flex-col items-center justify-center bg-surface p-4 rounded-lg border-2 border-dashed border-border focus:outline-none focus:border-primary\" tabIndex={0}>\n {uploadedImage ? (\n <>\n <img src={uploadedImage.dataUrl} alt=\"Uploaded content\" className=\"max-w-full max-h-full object-contain rounded-md shadow-lg\" />\n <button onClick={() => setUploadedImage(null)} className=\"absolute top-2 right-2 p-1 bg-black/30 text-white rounded-full hover:bg-black/50\"><XMarkIcon /></button>\n </>\n ) : (\n <div className=\"text-center text-text-secondary\">\n <h2 className=\"text-lg font-bold text-text-primary\">Paste an image here</h2>\n <p className=\"text-sm\">(Cmd/Ctrl + V)</p>\n <p className=\"text-xs my-1\">or</p>\n <button onClick={() => fileInputRef.current?.click()} className=\"text-sm font-semibold text-primary hover:underline\">Upload File</button>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} accept=\"image/*\" className=\"hidden\"/>\n </div>\n )}\n </div>\n </div>\n \n <div className=\"flex gap-2\">\n <button\n onClick={handleGenerate}\n disabled={isLoading}\n className=\"btn-primary w-full flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? <LoadingSpinner /> : 'Generate Image'}\n </button>\n <button\n onClick={handleSurpriseMe}\n disabled={isLoading}\n className=\"px-4 py-3 bg-surface border border-border rounded-md hover:bg-gray-100 transition-colors\"\n title=\"Surprise Me!\"\n >\n <SparklesIcon />\n </button>\n </div>\n </div>\n\n {/* Right Column: Output */}\n <div className=\"flex flex-col h-full\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Generated Image</label>\n <div className=\"flex-grow flex items-center justify-center bg-background border-2 border-dashed border-border rounded-lg p-4 relative overflow-auto\">\n {isLoading && <LoadingSpinner />}\n {error && <p className=\"text-red-500 text-center\">{error}</p>}\n {generatedImageUrl && !isLoading && (\n <>\n <img src={generatedImageUrl} alt={prompt || \"Generated by AI\"} className=\"max-w-full max-h-full object-contain rounded-md shadow-lg\" />\n <button \n onClick={handleDownload}\n className=\"absolute top-4 right-4 p-2 bg-black/30 text-white rounded-full hover:bg-black/50 backdrop-blur-sm\"\n title=\"Download Image\"\n >\n <ArrowDownTrayIcon />\n </button>\n </>\n )}\n {!isLoading && !generatedImageUrl && !error && (\n <div className=\"text-center text-text-secondary\">\n <p>Your generated image will appear here.</p>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["surprisePrompts","AiImageGenerator","prompt","setPrompt","useState","uploadedImage","setUploadedImage","generatedImageUrl","setGeneratedImageUrl","isLoading","setIsLoading","error","setError","fileInputRef","useRef","handleGenerate","useCallback","resultUrl","generateImageFromImageAndText","generateImage","err","errorMessage","handleSurpriseMe","randomPrompt","processImageBlob","blob","dataUrl","base64","blobToDataURL","fileToBase64","handlePaste","event","items","item","handleFileChange","file","handleDownload","link","jsxs","jsx","ImageGeneratorIcon","e","Fragment","XMarkIcon","LoadingSpinner","SparklesIcon","ArrowDownTrayIcon"],"mappings":"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"}