'use client'; import * as React from 'react'; import { Download, Loader2, RefreshCw, Code2, Globe, Layout, Palette } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Progress } from '@/components/ui/progress'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { FaviconFileUpload } from './FaviconFileUpload'; import { CodeSnippet } from './CodeSnippet'; import { generateFaviconSet } from '@/lib/favicon/faviconService'; import { downloadBlobsAsZip } from '@/lib/media/utils/fileUtils'; import type { FaviconSet, FaviconOptions } from '@/types/favicon'; import { toast } from 'sonner'; export function FaviconGenerator() { const [sourceFile, setSourceFile] = React.useState(null); const [options, setOptions] = React.useState({ name: 'My Awesome App', shortName: 'App', backgroundColor: '#ffffff', themeColor: '#3b82f6', }); const [isGenerating, setIsGenerating] = React.useState(false); const [progress, setProgress] = React.useState(0); const [result, setResult] = React.useState(null); const handleGenerate = async () => { if (!sourceFile) { toast.error('Please upload a source image'); return; } setIsGenerating(true); setProgress(0); try { const resultSet = await generateFaviconSet(sourceFile, options, (p) => { setProgress(p); }); setResult(resultSet); toast.success('Favicon set generated successfully!'); } catch (error) { console.error(error); toast.error('Failed to generate favicons'); } finally { setIsGenerating(false); } }; const handleDownloadAll = async () => { if (!result) return; const files = result.icons.map((icon) => ({ blob: icon.blob!, filename: icon.name, })); // Add manifest to ZIP const manifestBlob = new Blob([result.manifest], { type: 'application/json' }); files.push({ blob: manifestBlob, filename: 'site.webmanifest', }); await downloadBlobsAsZip(files, 'favicons.zip'); toast.success('Downloading favicons ZIP...'); }; const handleReset = () => { setSourceFile(null); setResult(null); setProgress(0); }; return (
{/* Settings Column */}
App Details Configure how your app appears on devices
setOptions({ ...options, name: e.target.value })} placeholder="e.g. My Awesome Website" />
setOptions({ ...options, shortName: e.target.value })} placeholder="e.g. My App" />

Used for mobile home screen labels

Theme Colors
setOptions({ ...options, backgroundColor: e.target.value })} /> setOptions({ ...options, backgroundColor: e.target.value })} />
setOptions({ ...options, themeColor: e.target.value })} /> setOptions({ ...options, themeColor: e.target.value })} />
setSourceFile(null)} disabled={isGenerating} /> {result && ( )}
{/* Results Column */}
{!result && !isGenerating ? (

Ready to generate

Upload a square image (PNG or SVG recommended) and configure your app details to get started.

) : isGenerating ? (
Processing Icons {progress}%
) : (

Generated Assets

Icons HTML Code Manifest
{result?.icons.map((icon) => (
{icon.previewUrl && ( {icon.name} )}

{icon.name}

{icon.width}x{icon.height} • {(icon.size / 1024).toFixed(1)} KB

))}
{result && }

Note: Make sure to place the generated files in your website's root directory or update the href paths accordingly.

{result && }
)}
); }