/** * 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, BackgroundAction, BACKGROUND_ACTIONS } from '../enhance/backgroundApi' export interface BackgroundToolsProps { /** Backend URL (e.g., http://localhost:8000) */ backendUrl: string /** Optional API key for authentication */ apiKey?: string /** Current image URL to process */ imageUrl: string | null /** Callback when operation completes with new image URL */ onResult: (resultUrl: string, action: BackgroundAction, hasAlpha: boolean) => void /** Callback for errors */ onError: (error: string) => void /** Optional: Disable all buttons */ disabled?: boolean /** Optional: Compact mode for smaller spaces */ compact?: boolean } /** * 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, }: BackgroundToolsProps) { 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: BackgroundAction, prompt?: string) => { 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: BackgroundAction) => { 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