admin08077/Githubgemini
0
1{"version":3,"file":"ScreenshotToComponent-BVyEYXPa.js","sources":["../../components/features/ScreenshotToComponent.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef } from 'react';\nimport { generateComponentFromImageStream } from '../../services/geminiService.ts';\nimport { PhotoIcon, ArrowDownTrayIcon } from '../icons.tsx';\nimport { LoadingSpinner } from './shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\nimport { fileToBase64, blobToDataURL, downloadFile } from '../../services/fileUtils.ts';\n\nexport const ScreenshotToComponent: React.FC = () => {\n const [previewImage, setPreviewImage] = useState<string | null>(null);\n const [rawCode, setRawCode] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleGenerate = async (base64Image: string) => {\n setIsLoading(true);\n setError('');\n setRawCode('');\n try {\n const stream = generateComponentFromImageStream(base64Image);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setRawCode(fullResponse.replace(/^```(?:\\w+\\n)?/, '').replace(/```$/, ''));\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'An unknown error occurred.');\n } finally {\n setIsLoading(false);\n }\n };\n\n const processImageBlob = async (blob: Blob) => {\n try {\n const [dataUrl, base64Image] = await Promise.all([blobToDataURL(blob), fileToBase64(blob as File)]);\n setPreviewImage(dataUrl);\n handleGenerate(base64Image);\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) await processImageBlob(blob);\n return;\n }\n }\n }, []);\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n if (file) await processImageBlob(file);\n };\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8\">\n <header className=\"mb-6\"><h1 className=\"text-3xl font-bold text-slate-100 flex items-center\"><PhotoIcon /><span className=\"ml-3\">AI Screenshot-to-Component</span></h1><p className=\"text-slate-400 mt-1\">Paste or upload a screenshot of a UI element to generate React/Tailwind code.</p></header>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 min-h-0\">\n <div onPaste={handlePaste} className=\"flex flex-col items-center justify-center bg-slate-800/50 p-6 rounded-lg border-2 border-dashed border-slate-700 focus:outline-none focus:border-cyan-500 overflow-y-auto\" tabIndex={0}>\n {previewImage ? (<img src={previewImage} alt=\"Pasted content\" className=\"max-w-full max-h-full object-contain rounded-md shadow-lg\" />) : (<div className=\"text-center text-slate-400\">\n <h2 className=\"text-xl font-bold\">Paste an image here</h2>\n <p className=\"mb-2\">(Cmd/Ctrl + V)</p>\n <p className=\"text-sm\">or</p>\n <button onClick={() => fileInputRef.current?.click()} className=\"mt-2 btn-primary px-4 py-2 text-sm\">Upload File</button>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} accept=\"image/*\" className=\"hidden\"/>\n </div>)}\n </div>\n <div className=\"flex flex-col h-full\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"text-sm font-medium text-slate-400\">Generated Code</label>\n {rawCode && !isLoading && (\n <div className=\"flex items-center gap-2\">\n <button onClick={() => navigator.clipboard.writeText(rawCode)} className=\"px-3 py-1 bg-slate-700 text-xs rounded-md hover:bg-slate-600\">Copy Code</button>\n <button onClick={() => downloadFile(rawCode, 'Component.tsx', 'text/typescript')} className=\"flex items-center gap-1 px-3 py-1 bg-slate-700 text-xs rounded-md hover:bg-slate-600\">\n <ArrowDownTrayIcon className=\"w-4 h-4\" /> Download\n </button>\n </div>\n )}\n </div>\n <div className=\"flex-grow bg-slate-900 border border-slate-700 rounded-md overflow-y-auto\">\n {isLoading && (<div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>)}\n {error && <p className=\"p-4 text-red-400\">{error}</p>}\n {rawCode && !isLoading && <MarkdownRenderer content={`\\`\\`\\`tsx\\n${rawCode}\\n\\`\\`\\``} />}\n {!isLoading && !rawCode && !error && (<div className=\"text-slate-500 h-full flex items-center justify-center\">Generated component code will appear here.</div>)}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["ScreenshotToComponent","previewImage","setPreviewImage","useState","rawCode","setRawCode","isLoading","setIsLoading","error","setError","fileInputRef","useRef","handleGenerate","base64Image","stream","generateComponentFromImageStream","fullResponse","chunk","err","processImageBlob","blob","dataUrl","blobToDataURL","fileToBase64","handlePaste","useCallback","event","items","item","handleFileChange","file","_a","jsxs","jsx","PhotoIcon","downloadFile","ArrowDownTrayIcon","LoadingSpinner","MarkdownRenderer"],"mappings":"6cAOO,MAAMA,EAAkC,IAAM,CACjD,KAAM,CAACC,EAAcC,CAAe,EAAIC,EAAAA,SAAwB,IAAI,EAC9D,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAE,EACnC,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAS,EAAK,EAC1C,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAS,EAAE,EAC/BO,EAAeC,EAAAA,OAAyB,IAAI,EAE5CC,EAAiB,MAAOC,GAAwB,CAClDN,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAW,EAAE,EACb,GAAI,CACA,MAAMS,EAASC,EAAiCF,CAAW,EAC3D,IAAIG,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBZ,EAAWW,EAAa,QAAQ,iBAAkB,EAAE,EAAE,QAAQ,OAAQ,EAAE,CAAC,CAEjF,OAASE,EAAK,CACVT,EAASS,aAAe,MAAQA,EAAI,QAAU,4BAA4B,CAC9E,QAAA,CACIX,EAAa,EAAK,CACtB,CACJ,EAEMY,EAAmB,MAAOC,GAAe,CAC3C,GAAI,CACA,KAAM,CAACC,EAASR,CAAW,EAAI,MAAM,QAAQ,IAAI,CAACS,EAAcF,CAAI,EAAGG,EAAaH,CAAY,CAAC,CAAC,EAClGlB,EAAgBmB,CAAO,EACvBT,EAAeC,CAAW,CAC9B,MAAY,CACRJ,EAAS,8BAA8B,CAC3C,CACJ,EAEMe,EAAcC,cAAY,MAAOC,GAAgC,CACnE,MAAMC,EAAQD,EAAM,cAAc,MAClC,UAAWE,KAAQD,EACf,GAAIC,EAAK,KAAK,QAAQ,OAAO,IAAM,GAAI,CACnC,MAAMR,EAAOQ,EAAK,UAAA,EACdR,GAAM,MAAMD,EAAiBC,CAAI,EACrC,MACJ,CAER,EAAG,CAAA,CAAE,EAECS,EAAmB,MAAOH,GAA+C,OAC3E,MAAMI,GAAOC,EAAAL,EAAM,OAAO,QAAb,YAAAK,EAAqB,GAC9BD,GAAM,MAAMX,EAAiBW,CAAI,CACzC,EAEA,OACIE,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OAAO,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,sDAAsD,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAU,EAAED,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,4BAAA,CAA0B,CAAA,EAAO,EAAKA,EAAAA,IAAC,IAAA,CAAE,UAAU,sBAAsB,SAAA,+EAAA,CAA6E,CAAA,EAAI,EAC3RD,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACX,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,QAAST,EAAa,UAAU,4KAA4K,SAAU,EACtN,WAAgBS,EAAAA,IAAC,MAAA,CAAI,IAAKhC,EAAc,IAAI,iBAAiB,UAAU,2DAAA,CAA4D,EAAO+B,EAAAA,KAAC,MAAA,CAAI,UAAU,6BAClJ,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,oBAAoB,SAAA,sBAAmB,EACrDA,EAAAA,IAAC,IAAA,CAAE,UAAU,OAAO,SAAA,iBAAc,EAClCA,EAAAA,IAAC,IAAA,CAAE,UAAU,UAAU,SAAA,KAAE,EACzBA,EAAAA,IAAC,SAAA,CAAO,QAAS,IAAA,OAAM,OAAAF,EAAArB,EAAa,UAAb,YAAAqB,EAAsB,SAAS,UAAU,qCAAqC,SAAA,aAAA,CAAW,EAChHE,EAAAA,IAAC,QAAA,CAAM,KAAK,OAAO,IAAKvB,EAAc,SAAUmB,EAAkB,OAAO,UAAU,UAAU,QAAA,CAAQ,CAAA,CAAA,CACzG,CAAA,CACR,EACAG,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,qCAAqC,SAAA,iBAAc,EACnE7B,GAAW,CAACE,GACT0B,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACX,SAAA,CAAAC,EAAAA,IAAC,SAAA,CAAO,QAAS,IAAM,UAAU,UAAU,UAAU7B,CAAO,EAAG,UAAU,+DAA+D,SAAA,WAAA,CAAS,EACjJ4B,EAAAA,KAAC,SAAA,CAAO,QAAS,IAAMG,EAAa/B,EAAS,gBAAiB,iBAAiB,EAAG,UAAU,uFACxF,SAAA,CAAA6B,EAAAA,IAACG,EAAA,CAAkB,UAAU,SAAA,CAAU,EAAE,WAAA,CAAA,CAC7C,CAAA,CAAA,CACJ,CAAA,EAER,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,4EACV,SAAA,CAAA1B,SAAe,MAAA,CAAI,UAAU,0CAA0C,SAAA2B,MAACI,IAAe,EAAE,EACzF7B,GAASyB,EAAAA,IAAC,IAAA,CAAE,UAAU,mBAAoB,SAAAzB,EAAM,EAChDJ,GAAW,CAACE,GAAa2B,EAAAA,IAACK,GAAiB,QAAS;AAAA,EAAclC,CAAO;AAAA,QAAY,EACrF,CAACE,GAAa,CAACF,GAAW,CAACI,GAAUyB,EAAAA,IAAC,MAAA,CAAI,UAAU,yDAAyD,SAAA,4CAAA,CAA0C,CAAA,CAAA,CAC5J,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}