/** * 连线的受控样式与曲线工具栏。接收当前data及回调,编辑外观、动画、传播开关和曲线点,不直接持有文档状态。 */ "use client"; import { EdgeToolbar } from "@xyflow/react"; import { Plus, Trash2 } from "lucide-react"; import type { EdgeData, EdgeMarker, MarkerShape } from "@/lib/canvas-v2"; import styles from "./canvas.module.css"; /** x/y是工具栏锚点;count与knotMode来自外层曲线编辑器。add/remove/changeKnotMode委托外层选择具体曲线点。 * EdgeToolbar只负责屏幕定位,外层仅在选中连线时挂载本组件。 */ export function EdgeToolbarControls({ id, x, y, data, change, add, remove, count, knotMode, changeKnotMode }: { id: string; x: number; y: number; data: EdgeData; change: (data: EdgeData) => void; add: () => void; remove: () => void; count: number; knotMode?: string; changeKnotMode: (mode: "corner" | "smooth" | "symmetric") => void }) { const a = data.appearance || {}, animation = data.animation || {}; /** 合并appearance子对象并保留其它连线数据;箭头/箭尾各自更新时仍需在事件内保留其嵌套字段。 */ const appearance = (patch: NonNullable) => change({ ...data, appearance: { ...a, ...patch } }); /** 动画属性单独合并,调整一个设置不覆盖已有方向、效果等其它字段。 */ const animate = (patch: NonNullable) => change({ ...data, animation: { ...animation, ...patch } }); /** 箭头与箭尾共用的六种形状;实际SVG绘制由CanvasEdge中的Marker实现。 */ const markers: [MarkerShape, string][] = [["none", "无"], ["open-arrow", "开放箭头"], ["triangle", "三角箭头"], ["circle", "圆形"], ["diamond", "菱形"], ["square", "方形"]]; // 宽度校验0.5—20,端部尺寸4—32,动画时长250—30000ms;透明度范围由range控件给出。 // head/tail分别合并type/size/filled;传播开关将execution替换为当前enabled对象。 // 无曲线点时禁用模式和删除,达到64点时禁用添加;外层仍负责相应操作的实际合法性。 // 所有指针/键盘冒泡止于工具栏,避免颜色或输入操作同时触发画布编辑。 return
event.stopPropagation()} onClick={(event) => event.stopPropagation()} onDoubleClick={(event) => event.stopPropagation()} onKeyDown={(event) => event.stopPropagation()}> {(["head", "tail"] as const).map((end) => )} 拖动锚点或控制柄 · 双击添加 · Shift 镜像控制柄
; }