fix(web): allow dragging connections between step nodes

Treat in-progress connections (no target yet) as valid so React Flow can complete handle-to-handle links, and enlarge step handles.

Co-authored-by: Nasyarobby Putra <nasyarobby@gmail.com>
This commit is contained in:
Cursor Agent
2026-08-22 06:10:26 +00:00
co-authored by nsrb
parent 527f9ac869
commit 1b08979699
3 changed files with 26 additions and 8 deletions
@@ -158,8 +158,10 @@ function GraphTabInner({
(conn) => { (conn) => {
if (disabled) return false; if (disabled) return false;
const from = parseGraphNodeId(conn.source); const from = parseGraphNodeId(conn.source);
if (from?.kind !== "step") return false;
if (!conn.target) return true;
const to = parseGraphNodeId(conn.target); const to = parseGraphNodeId(conn.target);
if (from?.kind !== "step" || to?.kind !== "step") return false; if (to?.kind !== "step") return false;
return canConnectSteps(doc, from.uiId, to.uiId); return canConnectSteps(doc, from.uiId, to.uiId);
}, },
[doc, disabled], [doc, disabled],
@@ -282,8 +284,8 @@ function GraphTabInner({
onEdgesDelete={onEdgesDelete} onEdgesDelete={onEdgesDelete}
nodesConnectable={!disabled} nodesConnectable={!disabled}
nodesDraggable={!disabled} nodesDraggable={!disabled}
elementsSelectable connectionRadius={40}
fitView defaultEdgeOptions={{ type: "smoothstep" }}
proOptions={{ hideAttribution: false }} proOptions={{ hideAttribution: false }}
> >
<Background /> <Background />
@@ -3,7 +3,7 @@ import { Handle, Position } from "@xyflow/react";
export function TriggerGraphNode({ data, selected }) { export function TriggerGraphNode({ data, selected }) {
return ( return (
<div <div
className={`min-w-44 max-w-56 rounded-box border bg-base-100 px-3 py-2 shadow-sm ${ className={`relative min-w-44 max-w-56 rounded-box border bg-base-100 px-3 py-2 shadow-sm ${
selected ? "border-primary ring-2 ring-primary/40" : "border-base-300" selected ? "border-primary ring-2 ring-primary/40" : "border-base-300"
}`} }`}
> >
@@ -12,7 +12,7 @@ export function TriggerGraphNode({ data, selected }) {
<p className="font-mono text-[11px] opacity-70 truncate" title={data.label}> <p className="font-mono text-[11px] opacity-70 truncate" title={data.label}>
{data.label} {data.label}
</p> </p>
<Handle type="source" position={Position.Right} isConnectable={false} /> <Handle type="source" position={Position.Right} isConnectable={false} className="!h-3 !w-3" />
</div> </div>
); );
} }
@@ -21,7 +21,7 @@ export function StepGraphNode({ data, selected }) {
const kindLabel = data.kind === "set" ? "set" : data.profile ? "profile" : "script"; const kindLabel = data.kind === "set" ? "set" : data.profile ? "profile" : "script";
return ( return (
<div <div
className={`min-w-48 max-w-60 rounded-box border bg-base-100 px-3 py-2 shadow-sm ${ className={`relative min-w-48 max-w-60 rounded-box border bg-base-100 px-3 py-2 shadow-sm ${
data.kind === "set" data.kind === "set"
? "border-secondary" ? "border-secondary"
: data.profile : data.profile
@@ -29,7 +29,13 @@ export function StepGraphNode({ data, selected }) {
: "border-primary" : "border-primary"
} ${selected ? "ring-2 ring-primary/40" : ""}`} } ${selected ? "ring-2 ring-primary/40" : ""}`}
> >
<Handle type="target" position={Position.Left} /> <Handle
type="target"
position={Position.Left}
id="in"
className="!h-3 !w-3 !bg-primary"
isConnectable
/>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<p className="text-[10px] uppercase tracking-wide opacity-60">{kindLabel}</p> <p className="text-[10px] uppercase tracking-wide opacity-60">{kindLabel}</p>
{data.stepId ? ( {data.stepId ? (
@@ -52,7 +58,13 @@ export function StepGraphNode({ data, selected }) {
{data.missingNeeds?.length ? ( {data.missingNeeds?.length ? (
<p className="text-error text-[11px] mt-0.5">Unknown needs: {data.missingNeeds.join(", ")}</p> <p className="text-error text-[11px] mt-0.5">Unknown needs: {data.missingNeeds.join(", ")}</p>
) : null} ) : null}
<Handle type="source" position={Position.Right} /> <Handle
type="source"
position={Position.Right}
id="out"
className="!h-3 !w-3 !bg-primary"
isConnectable
/>
</div> </div>
); );
} }
+4
View File
@@ -29,3 +29,7 @@ body,
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.workflow-graph .react-flow__handle {
opacity: 1;
}