feat(workflow): edit edges on click

This commit is contained in:
Xin Wang
2026-08-03 07:42:41 +08:00
parent c241e815cc
commit e3035abcc2
2 changed files with 19 additions and 34 deletions

View File

@@ -9,10 +9,9 @@ import {
EdgeLabelRenderer, EdgeLabelRenderer,
getBezierPath, getBezierPath,
type EdgeProps, type EdgeProps,
useReactFlow,
} from "@xyflow/react"; } from "@xyflow/react";
import { Pencil, Trash2 } from "lucide-react"; import { Trash2 } from "lucide-react";
import { useContext, useState } from "react"; import { useContext } from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { EdgeActionContext } from "./context"; import { EdgeActionContext } from "./context";
@@ -29,12 +28,7 @@ export function ConditionEdge({
selected, selected,
}: EdgeProps) { }: EdgeProps) {
const actions = useContext(EdgeActionContext); const actions = useContext(EdgeActionContext);
const { setEdges } = useReactFlow();
const [hovered, setHovered] = useState(false);
// 点击标签:只选中这条边(露出编辑/删除按钮),不直接进入编辑。
const selectThisEdge = () =>
setEdges((eds) => eds.map((e) => ({ ...e, selected: e.id === id })));
const [path, labelX, labelY] = getBezierPath({ const [path, labelX, labelY] = getBezierPath({
sourceX, sourceX,
sourceY, sourceY,
@@ -55,7 +49,6 @@ export function ConditionEdge({
? "表达式" ? "表达式"
: "默认路径") : "默认路径")
).toString().trim(); ).toString().trim();
const expanded = hovered || selected;
return ( return (
<> <>
@@ -70,16 +63,15 @@ export function ConditionEdge({
/> />
<EdgeLabelRenderer> <EdgeLabelRenderer>
<div <div
className="nodrag nopan pointer-events-auto absolute flex items-center gap-1" className="nodrag nopan group pointer-events-auto absolute after:absolute after:left-full after:top-0 after:h-full after:w-1 after:content-['']"
style={{ style={{
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`, transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
}} }}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
> >
<button <button
type="button" type="button"
title="条件" title="点击编辑条件"
aria-label="编辑连接条件"
className={cn( className={cn(
"max-w-[160px] truncate rounded-full border px-2.5 py-1 text-xs shadow-sm transition-colors", "max-w-[160px] truncate rounded-full border px-2.5 py-1 text-xs shadow-sm transition-colors",
label label
@@ -87,31 +79,23 @@ export function ConditionEdge({
: "border-dashed border-hairline-strong bg-card/80 text-muted-soft hover:text-foreground", : "border-dashed border-hairline-strong bg-card/80 text-muted-soft hover:text-foreground",
selected && "border-primary ring-2 ring-primary/30", selected && "border-primary ring-2 ring-primary/30",
)} )}
onClick={selectThisEdge} onClick={() => actions.edit(id)}
> >
{label || " 条件"} {label || " 条件"}
</button> </button>
{expanded && (
<button
type="button"
title="编辑条件"
className="flex h-6 w-6 items-center justify-center rounded-full border border-hairline bg-card text-muted-foreground shadow-sm transition-colors hover:text-foreground"
onClick={() => actions.edit(id)}
>
<Pencil size={12} />
</button>
)}
{expanded && (
<button <button
type="button" type="button"
title="删除连线" title="删除连线"
className="flex h-6 w-6 items-center justify-center rounded-full border border-hairline bg-card text-muted-foreground shadow-sm transition-colors hover:text-destructive" aria-label="删除连线"
onClick={() => actions.remove(id)} className="pointer-events-none absolute left-full top-1/2 ml-1 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded-full border border-hairline bg-card text-muted-foreground opacity-0 shadow-sm transition-[color,opacity] hover:text-destructive group-hover:pointer-events-auto group-hover:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100"
onClick={(event) => {
event.stopPropagation();
actions.remove(id);
}}
> >
<Trash2 size={12} /> <Trash2 size={12} />
</button> </button>
)}
</div> </div>
</EdgeLabelRenderer> </EdgeLabelRenderer>
</> </>

View File

@@ -552,6 +552,7 @@ export function WorkflowCanvas({
onEdgesChange={onEdgesChange} onEdgesChange={onEdgesChange}
onConnect={onConnect} onConnect={onConnect}
onConnectEnd={onConnectEnd} onConnectEnd={onConnectEnd}
onEdgeClick={(_, edge) => edgeActions.edit(edge.id)}
isValidConnection={isValidConnection} isValidConnection={isValidConnection}
onPaneClick={() => { onPaneClick={() => {
onEditingEdgeIdChange(null); onEditingEdgeIdChange(null);