feat(workflow): edit edges on click
This commit is contained in:
@@ -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
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
title="删除连线"
|
||||||
title="编辑条件"
|
aria-label="删除连线"
|
||||||
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"
|
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={() => actions.edit(id)}
|
onClick={(event) => {
|
||||||
>
|
event.stopPropagation();
|
||||||
<Pencil size={12} />
|
actions.remove(id);
|
||||||
</button>
|
}}
|
||||||
)}
|
>
|
||||||
{expanded && (
|
<Trash2 size={12} />
|
||||||
<button
|
</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-destructive"
|
|
||||||
onClick={() => actions.remove(id)}
|
|
||||||
>
|
|
||||||
<Trash2 size={12} />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</EdgeLabelRenderer>
|
</EdgeLabelRenderer>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user