import { SOCIAL_MEDIA_PRESETS } from "@stirling-image/shared"; import { Download, Link, Unlink } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { ProgressCard } from "@/components/common/progress-card"; import { useToolProcessor } from "@/hooks/use-tool-processor"; import { useFileStore } from "@/stores/file-store"; type ResizeTab = "presets" | "custom" | "scale"; type FitMode = "cover" | "contain" | "fill"; const FIT_LABELS: Record = { cover: "Crop to fit", contain: "Fit inside", fill: "Stretch", }; // Group presets by platform const platforms = [...new Set(SOCIAL_MEDIA_PRESETS.map((p) => p.platform))]; export interface ResizeControlsProps { onChange?: (settings: Record) => void; } export function ResizeControls({ onChange }: ResizeControlsProps) { const [tab, setTab] = useState("custom"); const [selectedPreset, setSelectedPreset] = useState(null); const [width, setWidth] = useState(""); const [height, setHeight] = useState(""); const [percentage, setPercentage] = useState("50"); const [fit, setFit] = useState("cover"); const [lockAspect, setLockAspect] = useState(true); const [withoutEnlargement, setWithoutEnlargement] = useState(false); const onChangeRef = useRef(onChange); useEffect(() => { onChangeRef.current = onChange; }); useEffect(() => { const settings: Record = {}; if (tab === "scale") { settings.percentage = Number(percentage); } else { if (width) settings.width = Number(width); if (height) settings.height = Number(height); settings.fit = tab === "presets" ? "cover" : fit; settings.withoutEnlargement = withoutEnlargement; } onChangeRef.current?.(settings); }, [tab, width, height, percentage, fit, withoutEnlargement]); const handlePreset = (preset: (typeof SOCIAL_MEDIA_PRESETS)[number]) => { const key = `${preset.platform}-${preset.name}`; if (selectedPreset === key) { setSelectedPreset(null); setWidth(""); setHeight(""); } else { setSelectedPreset(key); setWidth(String(preset.width)); setHeight(String(preset.height)); } }; const tabClass = (t: ResizeTab) => `flex-1 text-xs py-1.5 rounded ${tab === t ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`; return (
{/* Tab selector */}
{/* Presets tab */} {tab === "presets" && (
{platforms.map((platform) => (

{platform}

{SOCIAL_MEDIA_PRESETS.filter((p) => p.platform === platform).map((preset) => { const key = `${preset.platform}-${preset.name}`; const isSelected = selectedPreset === key; return ( ); })}
))} {/* Don't enlarge */}
)} {/* Custom Size tab */} {tab === "custom" && (
setWidth(e.target.value)} placeholder="Auto" className="w-full mt-0.5 px-2 py-1.5 rounded border border-border bg-background text-sm text-foreground" />
setHeight(e.target.value)} placeholder="Auto" className="w-full mt-0.5 px-2 py-1.5 rounded border border-border bg-background text-sm text-foreground" />
{/* Fit mode */}

Fit Mode

{(Object.keys(FIT_LABELS) as FitMode[]).map((f) => ( ))}
{/* Don't enlarge */}
)} {/* Scale tab */} {tab === "scale" && (
setPercentage(e.target.value)} min={1} className="w-full mt-0.5 px-2 py-1.5 rounded border border-border bg-background text-sm text-foreground" />
{[25, 50, 75].map((pct) => ( ))}
)}
); } export function ResizeSettings() { const { files } = useFileStore(); const { processFiles, processAllFiles, processing, error, downloadUrl, progress } = useToolProcessor("resize"); const [settings, setSettings] = useState>({}); const handleProcess = () => { if (files.length > 1) { processAllFiles(files, settings); } else { processFiles(files, settings); } }; const hasFile = files.length > 0; const tab = settings.percentage !== undefined ? "scale" : "other"; const canProcess = hasFile && !processing && (tab === "scale" ? Number(settings.percentage) > 0 : Boolean(settings.width) || Boolean(settings.height)); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (canProcess) handleProcess(); }; return (
{/* Error */} {error &&

{error}

} {/* Process button */} {processing ? ( ) : ( )} {/* Download */} {downloadUrl && ( Download )} ); }