fix: wire libtv connection controls
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-18 17:46:48 +08:00
parent 3d091a665b
commit 5ba8900438

View File

@ -1195,6 +1195,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
const node = createWorkflowNode(workflow, 440 + index * 24, 350 + index * 18);
addNodes([node], []);
setActivePanel(null);
setConnectionMenu(null);
toast.success("已添加工作流");
},
[addNodes]
@ -1742,7 +1743,15 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
routerBack={() => router.push("/")}
/>
<LeftToolbar activePanel={activePanel} onOpen={(panel) => setActivePanel((current) => current === panel ? null : panel)} />
<LeftToolbar
activePanel={activePanel}
onOpen={(panel) => {
setCanvasCommand(null);
setNodeContextMenu(null);
setConnectionMenu(null);
setActivePanel((current) => current === panel ? null : panel);
}}
/>
<ZoomDock
compact={false}
@ -3396,6 +3405,62 @@ function CanvasCommandPalette({
);
}
function ConnectionAddMenu({
node,
onClose,
onCreate,
state,
}: {
node: CloneNode;
onClose: () => void;
onCreate: (kind: Exclude<AddModuleKind, "audio">) => void;
state: NonNullable<ConnectionMenuState>;
}) {
const title = state.side === "target" ? "添加上下文" : "引用该节点生成";
return (
<div
className="fixed z-[91] flex w-[240px] flex-col gap-2 rounded-[16px] border border-white/10 bg-[#202020]/96 p-2 text-white shadow-[0_28px_80px_rgba(0,0,0,0.56)] backdrop-blur-[32px]"
data-canvas-overlay="true"
onPointerDown={(event) => event.stopPropagation()}
style={{
left:
state.side === "target"
? `max(12px, min(${state.screenX - 252}px, calc(100vw - 252px)))`
: `min(${state.screenX + 12}px, calc(100vw - 252px))`,
top: `min(${state.screenY - 120}px, calc(100vh - 330px))`,
}}
>
<div className="flex items-start justify-between gap-2 px-2 py-1">
<div className="min-w-0">
<h4 className="text-[14px] font-medium leading-5 text-white/60">{title}</h4>
<div className="mt-1 truncate text-[11px] text-white/34">{node.title}</div>
</div>
<button className="flex h-7 w-7 shrink-0 items-center justify-center rounded-[8px] text-white/42 hover:bg-white/8 hover:text-white" onClick={onClose} type="button">
<X className="h-4 w-4" />
</button>
</div>
{CONNECTION_ADD_MODULES.map((item) => {
const Icon = item.icon;
return (
<button
className="group flex h-[52px] w-full cursor-pointer items-center gap-2 rounded-[12px] px-2 py-2 text-left text-white/82 transition-colors duration-200 hover:bg-white/8"
key={item.kind}
onClick={() => onCreate(item.kind)}
type="button"
>
<span className="flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-[8px] bg-white/8 text-white/82">
<Icon className="h-5 w-5" />
</span>
<span className="text-[14px] font-medium leading-5">{item.label}</span>
</button>
);
})}
</div>
);
}
function NodeContextMenu({
node,
onClose,
@ -3725,12 +3790,14 @@ function CanvasNodeShell({
children,
node,
onContextMenu,
onOpenConnectionMenu,
onPointerDown,
selected,
}: {
children: ReactNode;
node: CloneNode;
onContextMenu: (event: ReactMouseEvent<HTMLDivElement>) => void;
onOpenConnectionMenu: (event: ReactMouseEvent<HTMLButtonElement>, side: ConnectionSide) => void;
onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;
selected: boolean;
}) {
@ -3750,17 +3817,45 @@ function CanvasNodeShell({
>
{targetModuleKind ? (
<>
<span className="absolute left-[-13px] top-1/2 z-10 mt-[14px] flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full border border-white/18 bg-[#242424] text-[20px] leading-none text-white/50">
<button
className="absolute left-[-13px] top-1/2 z-10 mt-[14px] flex h-6 w-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full border border-white/18 bg-[#242424] text-[20px] leading-none text-white/50 hover:border-white/34 hover:text-white/82"
onClick={(event) => onOpenConnectionMenu(event, "target")}
onPointerDown={(event) => event.stopPropagation()}
title="添加上下文"
type="button"
>
+
</span>
<span className="absolute right-[-13px] top-1/2 z-10 mt-[14px] flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full border border-white/18 bg-[#242424] text-[20px] leading-none text-white/50">
</button>
<button
className="absolute right-[-13px] top-1/2 z-10 mt-[14px] flex h-6 w-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full border border-white/18 bg-[#242424] text-[20px] leading-none text-white/50 hover:border-white/34 hover:text-white/82"
onClick={(event) => onOpenConnectionMenu(event, "source")}
onPointerDown={(event) => event.stopPropagation()}
title="引用该节点生成"
type="button"
>
+
</span>
</button>
</>
) : (
<>
<span className="absolute left-[-10px] top-1/2 z-10 h-5 w-5 -translate-y-1/2 rounded-full border border-white/30 bg-white" />
<span className="absolute right-[-10px] top-1/2 z-10 h-5 w-5 -translate-y-1/2 rounded-full border border-white/30 bg-white" />
<button
className="absolute left-[-10px] top-1/2 z-10 h-5 w-5 -translate-y-1/2 cursor-pointer rounded-full border border-white/30 bg-white text-[16px] leading-[16px] text-black/45 hover:text-black"
onClick={(event) => onOpenConnectionMenu(event, "target")}
onPointerDown={(event) => event.stopPropagation()}
title="添加上下文"
type="button"
>
+
</button>
<button
className="absolute right-[-10px] top-1/2 z-10 h-5 w-5 -translate-y-1/2 cursor-pointer rounded-full border border-white/30 bg-white text-[16px] leading-[16px] text-black/45 hover:text-black"
onClick={(event) => onOpenConnectionMenu(event, "source")}
onPointerDown={(event) => event.stopPropagation()}
title="引用该节点生成"
type="button"
>
+
</button>
</>
)}
{children}