LFM2-WebGPU / src /components /ToolItem.tsx
mlabonne's picture
Add demo source code (#1)
68185ce verified
import Editor from "@monaco-editor/react";
import { ChevronUp, ChevronDown, Trash2, Power } from "lucide-react";
import { useMemo } from "react";
import { extractFunctionAndRenderer, generateSchemaFromCode } from "../utils";
export interface Tool {
id: number;
name: string;
code: string;
enabled: boolean;
isCollapsed?: boolean;
renderer?: string;
}
interface ToolItemProps {
tool: Tool;
onToggleEnabled: () => void;
onToggleCollapsed: () => void;
onExpand: () => void;
onDelete: () => void;
onCodeChange: (newCode: string) => void;
}
const ToolItem: React.FC<ToolItemProps> = ({
tool,
onToggleEnabled,
onToggleCollapsed,
onDelete,
onCodeChange,
}) => {
const { functionCode } = extractFunctionAndRenderer(tool.code);
const schema = useMemo(
() => generateSchemaFromCode(functionCode),
[functionCode],
);
return (
<div
className={`bg-gray-700 rounded-lg p-4 transition-all ${!tool.enabled ? "opacity-50 grayscale" : ""}`}
>
<div
className="flex justify-between items-center cursor-pointer"
onClick={onToggleCollapsed}
>
<div>
<h3 className="text-lg font-bold text-teal-300 font-mono">
{schema.name}
</h3>
<div className="text-xs text-gray-300 mt-1">{schema.description}</div>
</div>
<div className="flex items-center space-x-3">
<button
onClick={(e) => {
e.stopPropagation();
onToggleEnabled();
}}
className={`p-1 rounded-full ${tool.enabled ? "text-green-400 hover:bg-green-900" : "text-red-400 hover:bg-red-900"}`}
>
<Power size={18} />
</button>
<button
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="p-2 text-gray-400 hover:text-red-500 hover:bg-gray-600 rounded-lg"
>
<Trash2 size={18} />
</button>
<button
onClick={(e) => {
e.stopPropagation();
onToggleCollapsed();
}}
className="p-2 text-gray-400 hover:text-white"
>
{tool.isCollapsed ? (
<ChevronDown size={20} />
) : (
<ChevronUp size={20} />
)}
</button>
</div>
</div>
{!tool.isCollapsed && (
<div className="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="md:col-span-2">
<label className="text-sm font-bold text-gray-400">
Implementation & Renderer
</label>
<div
className="mt-1 rounded-md overflow-visible border border-gray-600"
style={{ overflow: "visible" }}
>
<Editor
height="300px"
language="javascript"
theme="vs-dark"
value={tool.code}
onChange={(value) => onCodeChange(value || "")}
options={{
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 10 },
fontSize: 14,
lineDecorationsWidth: 0,
lineNumbersMinChars: 3,
scrollBeyondLastLine: false,
}}
/>
</div>
</div>
<div className="flex flex-col">
<label className="text-sm font-bold text-gray-400">
Generated Schema
</label>
<div className="mt-1 rounded-md flex-grow overflow-visible border border-gray-600">
<Editor
height="300px"
language="json"
theme="vs-dark"
value={JSON.stringify(schema, null, 2)}
options={{
readOnly: true,
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 10 },
lineNumbers: "off",
glyphMargin: false,
folding: false,
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
scrollBeyondLastLine: false,
fontSize: 12,
}}
/>
</div>
</div>
</div>
)}
</div>
);
};
export default ToolItem;