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:
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!