/** * BackgroundTools - Background manipulation buttons for the Edit page. * * Provides quick access to background operations: * - Remove BG: Make background transparent * - Change BG: Replace with AI-generated background * - Blur BG: Portrait mode / bokeh effect * * This component is additive and can be dropped into any page. */ import React, { useState } from 'react'; import { Loader2, Scissors, Palette, CircleDot, X } from 'lucide-react'; import { processBackground, BACKGROUND_ACTIONS } from '../enhance/backgroundApi'; /** * BackgroundTools component for background manipulation. * * @example * ```tsx * { * console.log(`Background ${action} completed: ${url}, hasAlpha: ${hasAlpha}`) * setCurrentImage(url) * }} * onError={(err) => setError(err)} * /> * ``` */ export function BackgroundTools({ backendUrl, apiKey, imageUrl, onResult, onError, disabled = false, compact = false, }) { const [loading, setLoading] = useState(null); const [showPromptInput, setShowPromptInput] = useState(false); const [bgPrompt, setBgPrompt] = useState(''); const [blurStrength, setBlurStrength] = useState(15); // Only show "Change BG" (replace) for now - remove and blur are disabled until fixed const ENABLED_ACTIONS = BACKGROUND_ACTIONS.filter(a => a.id === 'replace'); const handleAction = async (action, prompt) => { if (!imageUrl || loading || disabled) return; // For replace action, we need a prompt if (action === 'replace' && !prompt) { setShowPromptInput(true); return; } setLoading(action); setShowPromptInput(false); try { const result = await processBackground({ backendUrl, apiKey, imageUrl, action, prompt, blurStrength: action === 'blur' ? blurStrength : undefined, }); const resultUrl = result?.media?.images?.[0]; if (resultUrl) { onResult(resultUrl, action, result.has_alpha ?? false); } else { onError('Operation completed but no image was returned.'); } } catch (e) { onError(e instanceof Error ? e.message : 'Background operation failed'); } finally { setLoading(null); setBgPrompt(''); } }; const getIcon = (action) => { switch (action) { case 'remove': return ; case 'replace': return ; case 'blur': return ; } }; const isDisabled = !imageUrl || disabled; if (compact) { return (
{ENABLED_ACTIONS.map((actionInfo) => ())}
); } return (
Background
{ENABLED_ACTIONS.map((actionInfo) => ())}
{/* Prompt Input for Replace Action */} {showPromptInput && (
Describe new background
setBgPrompt(e.target.value)} placeholder="e.g., sunset beach, city skyline, forest..." className="w-full rounded-lg bg-black/40 border border-white/10 px-3 py-2 text-sm text-white placeholder:text-white/30 focus:border-blue-500/50 focus:outline-none" autoFocus onKeyDown={(e) => { if (e.key === 'Enter' && bgPrompt.trim()) { handleAction('replace', bgPrompt.trim()); } if (e.key === 'Escape') { setShowPromptInput(false); setBgPrompt(''); } }}/>
)}

Replace the background with AI-generated content. Results are added to your version history.

); } export default BackgroundTools;