import { CATEGORIES, TOOLS } from "@ashim/shared"; import { FileImage, Plus } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { SearchBar } from "@/components/common/search-bar"; import { apiGet } from "@/lib/api"; import { ICON_MAP } from "@/lib/icon-map"; import { cn } from "@/lib/utils"; const EXCLUDED_TOOLS = new Set(["pipeline", "compare", "find-duplicates", "collage", "compose"]); interface ToolPaletteProps { onAddStep: (toolId: string) => void; className?: string; } export function ToolPalette({ onAddStep, className }: ToolPaletteProps) { const [search, setSearch] = useState(""); const [disabledTools, setDisabledTools] = useState([]); const [experimentalEnabled, setExperimentalEnabled] = useState(false); const [pipelineToolIds, setPipelineToolIds] = useState(null); useEffect(() => { apiGet<{ settings: Record }>("/v1/settings") .then((data) => { setDisabledTools( data.settings.disabledTools ? JSON.parse(data.settings.disabledTools) : [], ); setExperimentalEnabled(data.settings.enableExperimentalTools === "true"); }) .catch(() => {}); apiGet<{ toolIds: string[] }>("/v1/pipeline/tools") .then((data) => setPipelineToolIds(data.toolIds)) .catch(() => {}); }, []); const availableTools = useMemo(() => { const q = search.toLowerCase(); return TOOLS.filter((t) => { if (EXCLUDED_TOOLS.has(t.id)) return false; if (disabledTools.includes(t.id)) return false; if (t.experimental && !experimentalEnabled) return false; if (pipelineToolIds && !pipelineToolIds.includes(t.id)) return false; if (q && !t.name.toLowerCase().includes(q) && !t.description.toLowerCase().includes(q)) { return false; } return true; }); }, [disabledTools, experimentalEnabled, pipelineToolIds, search]); const groupedTools = useMemo(() => { const groups: Record = {}; for (const tool of availableTools) { const cat = tool.category || "other"; if (!groups[cat]) groups[cat] = []; groups[cat].push(tool); } return groups; }, [availableTools]); const isSearching = search.length > 0; return (
{availableTools.length === 0 ? (

No tools found

) : isSearching ? (
{availableTools.map((tool) => ( ))}
) : (
{CATEGORIES.map((cat) => { const tools = groupedTools[cat.id]; if (!tools || tools.length === 0) return null; const CatIcon = (ICON_MAP[cat.icon] as React.ComponentType<{ className?: string }>) ?? FileImage; return (
{cat.name}
{tools.map((tool) => ( ))}
); })}
)}
); } interface ToolItemProps { tool: { id: string; name: string; description: string; icon: string }; onAdd: (toolId: string) => void; } function ToolItem({ tool, onAdd }: ToolItemProps) { const Icon = (ICON_MAP[tool.icon] as React.ComponentType<{ className?: string }>) ?? FileImage; return ( ); }