import { useEffect, useRef } from "react"; import { ImageIcon, List, Music2, Settings2, Video, X } from "lucide-react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; import { listNodeDefinitions, useNodeRegistryVersion } from "@/lib/canvas/node-registry"; import { CanvasNodeType, type ConnectionHandle, type Position } from "@/types/canvas"; export type PendingConnectionCreate = { connection: ConnectionHandle; position: Position; }; export function ConnectionCreateMenu({ pending, onCreate, onClose, }: { pending: PendingConnectionCreate; onCreate: (type: CanvasNodeType.Image | CanvasNodeType.Text | CanvasNodeType.Config | CanvasNodeType.Video | CanvasNodeType.Audio) => void; onClose: () => void; }) { const theme = canvasThemes[useThemeStore((state) => state.theme)]; return (
event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} >
引用该节点生成
} title="文本生成" description="脚本、广告词、品牌文案" onClick={() => onCreate(CanvasNodeType.Text)} /> } title="图片生成" onClick={() => onCreate(CanvasNodeType.Image)} /> } title="视频生成" onClick={() => onCreate(CanvasNodeType.Video)} /> } title="音频参考" onClick={() => onCreate(CanvasNodeType.Audio)} /> } title="配置节点" description="模型、尺寸、数量和输入顺序" onClick={() => onCreate(CanvasNodeType.Config)} />
); } export function ConnectionCreateOption({ theme, icon, title, description, onClick }: { theme: (typeof canvasThemes)[keyof typeof canvasThemes]; icon: React.ReactNode; title: string; description?: string; onClick?: () => void }) { return ( ); } export function NodeCreateMenu({ position, onCreate, onClose }: { position: Position; onCreate: (type: string) => void; onClose: () => void }) { const theme = canvasThemes[useThemeStore((state) => state.theme)]; useNodeRegistryVersion(); const menuRef = useRef(null); const definitions = listNodeDefinitions().filter((def) => def.showInCreateMenu !== false); // 点击菜单外的空白处自动关闭 useEffect(() => { const handlePointerDown = (event: PointerEvent) => { if (menuRef.current && !menuRef.current.contains(event.target as Node)) onClose(); }; document.addEventListener("pointerdown", handlePointerDown, true); return () => document.removeEventListener("pointerdown", handlePointerDown, true); }, [onClose]); return (
event.stopPropagation()} >
选择节点
{definitions.map((def) => ( onCreate(def.type)} /> ))}
); }