feat: improve canvas connection interactions
This commit is contained in:
@@ -1,8 +1,24 @@
|
||||
import type { MouseEvent as ReactMouseEvent } from "react";
|
||||
|
||||
import { canvasThemes } from "@/lib/canvas-theme";
|
||||
import { useThemeStore } from "@/stores/use-theme-store";
|
||||
import type { CanvasConnection, CanvasNodeData, ConnectionHandle, Position } from "../types";
|
||||
|
||||
export function ConnectionPath({ connection, from, to, active, onSelect }: { connection: CanvasConnection; from: CanvasNodeData; to: CanvasNodeData; active: boolean; onSelect: () => void }) {
|
||||
export function ConnectionPath({
|
||||
connection,
|
||||
from,
|
||||
to,
|
||||
active,
|
||||
onSelect,
|
||||
onContextMenu,
|
||||
}: {
|
||||
connection: CanvasConnection;
|
||||
from: CanvasNodeData;
|
||||
to: CanvasNodeData;
|
||||
active: boolean;
|
||||
onSelect: () => void;
|
||||
onContextMenu?: (event: ReactMouseEvent<SVGPathElement>) => void;
|
||||
}) {
|
||||
const theme = canvasThemes[useThemeStore((state) => state.theme)];
|
||||
const startX = from.position.x + from.width;
|
||||
const startY = from.position.y + from.height / 2;
|
||||
@@ -25,6 +41,11 @@ export function ConnectionPath({ connection, from, to, active, onSelect }: { con
|
||||
event.stopPropagation();
|
||||
onSelect();
|
||||
}}
|
||||
onContextMenu={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onContextMenu?.(event);
|
||||
}}
|
||||
/>
|
||||
<path
|
||||
d={pathD}
|
||||
@@ -38,7 +59,7 @@ export function ConnectionPath({ connection, from, to, active, onSelect }: { con
|
||||
);
|
||||
}
|
||||
|
||||
export function ActiveConnectionPath({ node, handle, mouseWorld }: { node?: CanvasNodeData; handle: ConnectionHandle; mouseWorld: Position }) {
|
||||
export function ActiveConnectionPath({ node, handle, mouseWorld, target }: { node?: CanvasNodeData; handle: ConnectionHandle; mouseWorld: Position; target?: CanvasNodeData }) {
|
||||
const theme = canvasThemes[useThemeStore((state) => state.theme)];
|
||||
if (!node) return null;
|
||||
|
||||
@@ -46,8 +67,12 @@ export function ActiveConnectionPath({ node, handle, mouseWorld }: { node?: Canv
|
||||
const startY = handle.handleType === "source" ? node.position.y + node.height / 2 : mouseWorld.y;
|
||||
const endX = handle.handleType === "source" ? mouseWorld.x : node.position.x;
|
||||
const endY = handle.handleType === "source" ? mouseWorld.y : node.position.y + node.height / 2;
|
||||
const distance = Math.abs(endX - startX);
|
||||
const pathD = `M ${startX} ${startY} C ${startX + distance * 0.5} ${startY}, ${endX - distance * 0.5} ${endY}, ${endX} ${endY}`;
|
||||
const snappedStartX = handle.handleType === "target" && target ? target.position.x + target.width : startX;
|
||||
const snappedStartY = handle.handleType === "target" && target ? target.position.y + target.height / 2 : startY;
|
||||
const snappedEndX = handle.handleType === "source" && target ? target.position.x : endX;
|
||||
const snappedEndY = handle.handleType === "source" && target ? target.position.y + target.height / 2 : endY;
|
||||
const distance = Math.abs(snappedEndX - snappedStartX);
|
||||
const pathD = `M ${snappedStartX} ${snappedStartY} C ${snappedStartX + distance * 0.5} ${snappedStartY}, ${snappedEndX - distance * 0.5} ${snappedEndY}, ${snappedEndX} ${snappedEndY}`;
|
||||
|
||||
return <path d={pathD} stroke={theme.node.activeStroke} strokeWidth="2" fill="none" strokeDasharray="5,5" />;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export function CanvasNodeContextMenu({ menu, onClose, onDuplicate, onDelete }:
|
||||
style={{ left: menu.x, top: menu.y, background: theme.toolbar.panel, borderColor: theme.toolbar.border, color: theme.node.text }}
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
>
|
||||
<MenuButton icon={<Plus className="size-4" />} label="Duplicate" onClick={onDuplicate} />
|
||||
{menu.type === "node" ? <MenuButton icon={<Plus className="size-4" />} label="Duplicate" onClick={onDuplicate} /> : null}
|
||||
<MenuButton icon={<Trash2 className="size-4" />} label="Delete" onClick={onDelete} danger />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user