From 5a50aecd0bffebcd7c477d0122153dbf1e610f08 Mon Sep 17 00:00:00 2001 From: Siddharth Kumar Sah Date: Sat, 28 Mar 2026 15:40:38 +0800 Subject: [PATCH] refactor: extract RemoveBgControls for DRY reuse in pipeline steps Extract the settings controls (subject type, quality, background color) from RemoveBgSettings into a shared RemoveBgControls component that accepts settings + onChange props. Both the standalone tool page and the pipeline step configurator now render the same component, so the UI is identical and changes only need to be made in one place. --- .../tools/pipeline-step-settings.tsx | 29 +++-------- .../components/tools/remove-bg-settings.tsx | 50 ++++++++++++++----- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/apps/web/src/components/tools/pipeline-step-settings.tsx b/apps/web/src/components/tools/pipeline-step-settings.tsx index 60e20ccc..0940981d 100644 --- a/apps/web/src/components/tools/pipeline-step-settings.tsx +++ b/apps/web/src/components/tools/pipeline-step-settings.tsx @@ -1,3 +1,5 @@ +import { RemoveBgControls } from "./remove-bg-settings"; + type FieldType = "number" | "select" | "boolean" | "text" | "color"; interface FieldDef { @@ -479,27 +481,7 @@ const TOOL_FIELDS: Record = { { key: "background", label: "Background", type: "color", defaultValue: "#FFFFFF" }, ], - "remove-background": [ - { - key: "model", - label: "AI Model", - type: "select", - defaultValue: "birefnet-general-lite", - options: [ - { value: "u2net", label: "Fast (u2net)" }, - { value: "birefnet-general-lite", label: "Balanced (general)" }, - { value: "birefnet-general", label: "Best (general)" }, - { value: "birefnet-portrait", label: "Portrait / Passport" }, - { value: "bria-rmbg", label: "Products (bria)" }, - ], - }, - { - key: "backgroundColor", - label: "Background color", - type: "color", - defaultValue: "", - }, - ], + // remove-background uses its own shared controls component (DRY) favicon: [], "color-palette": [], "barcode-read": [], @@ -514,6 +496,11 @@ interface PipelineStepSettingsProps { } export function PipelineStepSettings({ toolId, settings, onChange }: PipelineStepSettingsProps) { + // Tools with their own shared controls component (DRY - same UI as standalone page) + if (toolId === "remove-background") { + return ; + } + const fields = TOOL_FIELDS[toolId]; if (!fields || fields.length === 0) { diff --git a/apps/web/src/components/tools/remove-bg-settings.tsx b/apps/web/src/components/tools/remove-bg-settings.tsx index 92647055..2a1b0bf3 100644 --- a/apps/web/src/components/tools/remove-bg-settings.tsx +++ b/apps/web/src/components/tools/remove-bg-settings.tsx @@ -1,5 +1,5 @@ import { Download, ImageIcon, Package, User } from "lucide-react"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { ProgressCard } from "@/components/common/progress-card"; import { useToolProcessor } from "@/hooks/use-tool-processor"; import { useFileStore } from "@/stores/file-store"; @@ -41,25 +41,27 @@ const BG_PRESETS = [ { color: "#0000FF", label: "Blue", preview: "#0000FF" }, ]; -export function RemoveBgSettings() { - const { files } = useFileStore(); - const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } = - useToolProcessor("remove-background"); +// ── Shared controls (used by both standalone page and pipeline steps) ── +export interface RemoveBgControlsProps { + settings: Record; + onChange: (settings: Record) => void; +} + +export function RemoveBgControls({ settings, onChange }: RemoveBgControlsProps) { const [subject, setSubject] = useState("people"); const [quality, setQuality] = useState("balanced"); const [isPassport, setIsPassport] = useState(false); - const [bgColor, setBgColor] = useState(""); + const [bgColor, setBgColor] = useState((settings.backgroundColor as string) || ""); const model = isPassport ? "birefnet-portrait" : MODEL_MAP[subject][quality]; - const handleProcess = () => { - const settings: Record = { model }; - if (bgColor) settings.backgroundColor = bgColor; - processFiles(files, settings); - }; - - const hasFile = files.length > 0; + // Sync settings on every control change + useEffect(() => { + const next: Record = { model }; + if (bgColor) next.backgroundColor = bgColor; + onChange(next); + }, [model, bgColor, onChange]); return (
@@ -175,6 +177,28 @@ export function RemoveBgSettings() { />
+ + ); +} + +// ── Standalone tool page wrapper ────────────────────────────────────── + +export function RemoveBgSettings() { + const { files } = useFileStore(); + const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } = + useToolProcessor("remove-background"); + + const [settings, setSettings] = useState>({}); + + const handleProcess = () => { + processFiles(files, settings); + }; + + const hasFile = files.length > 0; + + return ( +
+ {/* Error */} {error &&

{error}

}