import React from 'react'; import { useMobile } from '@/hooks/use-mobile'; import { Sheet, SheetContent } from '@/components/ui/sheet'; import { Button } from '@/components/ui/button'; import { ChevronUp, Image as ImageIcon, Clipboard } from 'lucide-react'; import { useMockupStore } from '@/contexts/MockupContext'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { toast } from 'sonner'; import { DialogDescription } from '@radix-ui/react-dialog'; interface CustomBackground { name: string; image: string; // Base64 string } export const Backgrounds: React.FC = () => { const { backgroundImage, setBackgroundType, setGradientColors, setGradientDirection, setBackgroundImage, customBackgrounds, addCustomBackground, } = useMockupStore(); const isMobile = useMobile(); const [isOpen, setIsOpen] = React.useState(false); const [isDialogOpen, setIsDialogOpen] = React.useState(false); const [isDragOver, setIsDragOver] = React.useState(false); const fileInputRef = React.useRef(null); const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB const gradientPresets = [ { name: 'Deep Horizon', colors: ['#141e30', '#243b55'], direction: 'to-tl', image: '/assets/deep_horizon.webp' }, { name: 'Ocean Glow', colors: ['#56ccf2', '#2f80ed'], direction: 'to-r', image: '/assets/ocean_glow.webp' }, { name: 'Ocean Breeze', colors: ['#ff9a9e', '#fecfef'], direction: 'to-r', image: '/assets/ocean_breeze.png' }, { name: 'Purple Haze', colors: ['#c471ed', '#f64f59'], direction: 'to-r', image: '/assets/purple_haze.png' }, { name: 'Summer Vibes', colors: ['#56ab2f', '#a8e6cf'], direction: 'to-tr', image: '/assets/summer_vibes.png' }, { name: 'Rainbow Dreams', colors: ['#ff6b6b', '#4ecdc4'], direction: 'to-br', image: '/assets/rainbow_dreams.png' }, { name: 'Neon Heat', colors: ['#ff0844', '#ffb199'], direction: 'to-br', image: '/assets/neon_heat.webp' }, { name: 'Purple Magic', colors: ['#667eea', '#764ba2'], direction: 'to-br', image: '/assets/purple_magic.png' }, { name: 'Sunset Glow', colors: ['#ff9a56', '#ff6b9d'], direction: 'to-r', image: '/assets/sunset_glow.png' }, { name: 'Warm Embrace', colors: ['#ff9472', '#f2d388'], direction: 'to-tr', image: '/assets/warm_embrace.png' }, { name: 'Cosmic Night', colors: ['#667eea', '#764ba2'], direction: 'to-br', image: '/assets/cosmic_night.webp' }, { name: 'Mint Breeze', colors: ['#a8edea', '#fed6e3'], direction: 'to-tr', image: '/assets/mint_breeze.webp' }, { name: 'Neon Midnight', colors: ['#c471ed', '#f64f59'], direction: 'to-r', image: '/assets/neon_midnight.webp' }, { name: 'Monochrome', colors: ['#2c3e50', '#34495e'], direction: 'to-br', image: '/assets/monochrome.png' }, { name: 'Arctic Pulse', colors: ['#cce3df', '#3a6c7a', '#0e1a1f'], direction: 'to-r', image: '/assets/arctic_pulse.webp' }, { name: 'Molten Dusk', colors: ['#f0e7da', '#f857a6', '#2c2c2c'], direction: 'to-l', image: '/assets/molten_dusk.webp' }, { name: 'Twilight Ember', colors: ['#ffb88c', '#ea5753', '#111d2f'], direction: 'to-br', image: '/assets/twilight_ember.webp' } ]; const handleGradientSelect = (gradient: typeof gradientPresets[0] | CustomBackground) => { setBackgroundType('pattern'); if ('colors' in gradient && 'direction' in gradient) { setGradientColors(gradient.colors); setGradientDirection(gradient.direction); } else { setGradientColors(['#ffffff', '#ffffff']); setGradientDirection('to-r'); } setBackgroundImage(gradient.image); if (isMobile) setIsOpen(false); }; const handleImageUpload = (file: File) => { if (!['image/jpeg', 'image/png'].includes(file.type)) { toast.error('Invalid file format! Please use JPG, PNG.'); setIsDragOver(false); setIsDialogOpen(false); return; } if (file.size > MAX_FILE_SIZE) { toast.error('File too large! Maximum size is 10MB.'); setIsDragOver(false); setIsDialogOpen(false); return; } const reader = new FileReader(); reader.onload = (e) => { const base64Image = e.target?.result as string; if (base64Image) { const newBackground: CustomBackground = { name: `Custom ${customBackgrounds.length + 1}`, image: base64Image }; addCustomBackground(newBackground); handleGradientSelect(newBackground); toast('Background added successfully!'); setTimeout(() => setIsDialogOpen(false), 300); // Delay for toast visibility setIsDragOver(false); } }; reader.onerror = () => { toast.error('Failed to read the file. Please try again.'); setIsDragOver(false); setIsDialogOpen(false); }; reader.readAsDataURL(file); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDragOver(false); const file = e.dataTransfer.files[0]; if (file) { handleImageUpload(file); } else { toast.error('No valid file dropped.'); setIsDialogOpen(false); } }; const handleFileInput = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { handleImageUpload(file); } else { toast.error('No file selected.'); setIsDialogOpen(false); } }; const handlePaste = (e: React.ClipboardEvent) => { const file = e.clipboardData.files[0]; if (file) { handleImageUpload(file); } else { toast.error('No valid image pasted.'); setIsDialogOpen(false); } }; const getDropZoneClasses = () => { const baseClasses = "relative transition-all duration-300 cursor-pointer border-2 border-dashed rounded-xl bg-primary/20"; const hoverClasses = "hover:bg-primary/10"; const dragOverClasses = isDragOver ? "scale-105 border-primary" : "border-gray-400"; return `${baseClasses} ${hoverClasses} ${dragOverClasses}`; }; const GradientGrid = () => (

Background Gradients

Upload Custom Background custom background to personalise your creation.
{ e.preventDefault(); setIsDragOver(true); }} onDragLeave={() => setIsDragOver(false)} onClick={() => fileInputRef.current?.click()} >

Drop image here or click to upload

Supports JPG, PNG

{isDragOver && (
Drop image here
)}
{[...customBackgrounds, ...gradientPresets].map((gradient, index) => ( ))}
); if (isMobile) { return ( <>
); } return (
); };