diff --git a/web/app/dashboard/ai-workflows/_components/workflow-editor.tsx b/web/app/dashboard/ai-workflows/_components/workflow-editor.tsx index 9ce9237..a0eea23 100644 --- a/web/app/dashboard/ai-workflows/_components/workflow-editor.tsx +++ b/web/app/dashboard/ai-workflows/_components/workflow-editor.tsx @@ -36,11 +36,7 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover" -import { - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, -} from "@/components/ui/resizable" +import { cn } from "@/lib/utils" import type { AIWorkflowDefinition, AIWorkflowNodeSpec } from "@/lib/api/admin" import { applyAutoInputMappings, @@ -167,9 +163,12 @@ export function WorkflowEditor({ const [nodeLibraryCollapsed, setNodeLibraryCollapsed] = useState(false) const [nodeLibraryRendered, setNodeLibraryRendered] = useState(true) const [nodeLibraryVisible, setNodeLibraryVisible] = useState(true) + const [nodeLibraryWidth, setNodeLibraryWidth] = useState(260) + const [nodeLibraryResizing, setNodeLibraryResizing] = useState(false) const [pendingNodeDrag, setPendingNodeDrag] = useState(null) const [propertyPanelNode, setPropertyPanelNode] = useState(null) const [propertyPanelVisible, setPropertyPanelVisible] = useState(false) + const editorRef = useRef(null) const canvasRef = useRef(null) const pendingNodeDragRef = useRef(null) const suppressNextClickRef = useRef(false) @@ -206,13 +205,15 @@ export function WorkflowEditor({ useEffect(() => { if (!nodeLibraryCollapsed) { setNodeLibraryRendered(true) - window.setTimeout(() => setNodeLibraryVisible(true), 0) - return + const timer = window.setTimeout(() => { + setNodeLibraryVisible(true) + }, 0) + return () => window.clearTimeout(timer) } setNodeLibraryVisible(false) - const timer = window.setTimeout(() => setNodeLibraryRendered(false), 220) - return () => window.clearTimeout(timer) + const unmountTimer = window.setTimeout(() => setNodeLibraryRendered(false), 220) + return () => window.clearTimeout(unmountTimer) }, [nodeLibraryCollapsed]) useEffect(() => { @@ -364,11 +365,49 @@ export function WorkflowEditor({ ) } + const clampNodeLibraryWidth = useCallback((width: number) => { + const containerWidth = editorRef.current?.getBoundingClientRect().width ?? 0 + const maxWidth = containerWidth > 0 ? containerWidth * 0.34 : 520 + return Math.min(maxWidth, Math.max(192, width)) + }, []) + + const onNodeLibraryResizePointerDown = (event: React.PointerEvent) => { + if (event.button !== 0) { + return + } + event.preventDefault() + const startX = event.clientX + const startWidth = nodeLibraryWidth + setNodeLibraryResizing(true) + + const handlePointerMove = (event: PointerEvent) => { + setNodeLibraryWidth(clampNodeLibraryWidth(startWidth + event.clientX - startX)) + } + + const handlePointerUp = () => { + window.removeEventListener("pointermove", handlePointerMove) + window.removeEventListener("pointerup", handlePointerUp) + setNodeLibraryResizing(false) + } + + window.addEventListener("pointermove", handlePointerMove) + window.addEventListener("pointerup", handlePointerUp) + } + return ( - +
{nodeLibraryRendered ? ( <> - +
- - +
+
+
+
) : null} - +
) : null}
- - +
+
) }