import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import upiQR from "/assets/upiQR.png"; import { Download, ChevronDown, Coffee, ExternalLink, Loader2, Heart, X, CheckCircle, } from "lucide-react"; import { Github } from "@/components/icons/Github"; import { Bluesky } from "@/components/icons/Bluesky"; import { X as XIcon } from "@/components/icons/X"; import { toast } from "sonner"; import { useMockupStore } from "@/contexts/MockupContext"; import html2canvas from "html2canvas"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; export function Navbar() { const [showExportOptions, setShowExportOptions] = useState(false); const [exportFormat, setExportFormat] = useState("PNG"); const [quality, setQuality] = useState([2]); const [isExporting, setIsExporting] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false); const { uploadedImage, imageBorder, fixedMargin, margin } = useMockupStore(); const isMobile = typeof window !== "undefined" ? window.innerWidth < 768 : false; const getQualityLabel = (value) => { switch (value) { case 1: return "Standard (1x)"; case 2: return "High (2x)"; case 3: return "Ultra (3x)"; default: return `${value}x`; } }; const exportImage = async (format: string, qualityMultiplier: number) => { if (!uploadedImage) return; try { const mockupElement = document.querySelector("[data-mockup-canvas]") as HTMLDivElement; if (!mockupElement) throw new Error("Mockup canvas not found"); const imgElement = mockupElement.querySelector("img") as HTMLImageElement; if (!imgElement) throw new Error("Image element not found"); // For fixed margin mode: capture the entire canvas (image + background margins) const canvas = await html2canvas(mockupElement, { scale: qualityMultiplier * 2, useCORS: true, allowTaint: true, backgroundColor: null, // Capture the entire mockup element without any cropping }); const mimeType = `image/${format.toLowerCase()}`; const imageQuality = format === "JPEG" ? 1 : undefined; canvas.toBlob( (blob) => { if (blob) { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `mockup-${Date.now()}.${format.toLowerCase()}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } else { throw new Error("Failed to create blob"); } }, mimeType, imageQuality, ); } catch (error) { console.error("Export error:", error); throw error; } }; const handleSingleExport = async () => { if (!uploadedImage) { toast.error("Please upload an image first"); return; } setIsExporting(true); try { await exportImage(exportFormat, quality[0]); toast.success(`Successfully exported as ${exportFormat}!`, { icon: , }); } catch (error) { toast.error("Failed to export image. Please try again."); } finally { setIsExporting(false); } }; const handleAllFormatsExport = async () => { if (!uploadedImage) { toast.error("Please upload an image first"); return; } setIsExporting(true); const formats = ["PNG", "JPEG", "WebP"]; const qualityMultiplier = quality[0]; try { await Promise.all(formats.map((format) => exportImage(format, qualityMultiplier))); toast.success(`Successfully exported all formats (${formats.join(", ")})!`, { icon: , }); } catch (error) { console.error("Export all formats error:", error); toast.error("Failed to export some formats. Please try again."); } finally { setIsExporting(false); } }; const ExportOptionsContent = () => (

Export Settings

value && setExportFormat(value)} className="flex gap-1 bg-sidebar/80 rounded-full ring-2 ring-secondary p-1" > {["PNG", "JPEG", "WebP"].map((format) => ( {format} ))}
value && setQuality([parseInt(value)])} className="flex gap-1 bg-sidebar/80 rounded-full ring-2 ring-secondary p-1" > Standard High Ultra

Hi, I'm Jaydip

moocup is a simple offline tool.

focus on your craft, we'll take care of rest.

you can show your support by sponsoring my work!

Thanks for contribution!
QR code for making payment in Indian Rupees

Scan with any UPI app

Say Hi! I'm always up for quick chat :)

); return (

Moo

{!isMobile && (
crafted by
)}
{isMobile ? (
Export & Support
) : ( )}
); }