refactor: switch all node types to left/right handles for L-to-R layout
- Updated handle positions: - Target: Position.Left (incoming edges from left) - Source: Position.Right (outgoing edges to right) - Updated MiniMap nodeColor to color-code all 9 node types - Maintains consistency across narrative, primitive, and control nodes
This commit is contained in:
parent
4a573f7cfc
commit
cfba38ca24
10 changed files with 42 additions and 25 deletions
|
|
@ -8,7 +8,7 @@ export function BooleanNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-emerald-950/80 border border-emerald-500/50 rounded-lg shadow-md min-w-28">
|
||||
<Handle type="target" position={Position.Top} className="!bg-emerald-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-emerald-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-emerald-500/30">
|
||||
<CheckCircleIcon className="size-4 text-emerald-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-emerald-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function BooleanNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-emerald-300/80 line-clamp-2">
|
||||
{d.description || "Boolean flag"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-emerald-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-emerald-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ export function ChoiceNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-amber-950/80 border border-amber-500/50 rounded-lg shadow-md min-w-56">
|
||||
<Handle type="target" position={Position.Top} className="!bg-amber-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-amber-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-amber-500/30">
|
||||
<WaypointsIcon className="size-4 text-amber-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-amber-200 flex-1 truncate">
|
||||
{d.question || "Untitled Choice"}
|
||||
</span>
|
||||
<PencilIcon className="size-3 text-amber-500/40 shrink-0" />
|
||||
<PencilIcon className="size-3 text-amber-500/60 shrink-0" />
|
||||
</div>
|
||||
<div className="px-3 py-2 space-y-1">
|
||||
{options.length === 0 ? (
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function DateNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-cyan-950/80 border border-cyan-500/50 rounded-lg shadow-md min-w-32">
|
||||
<Handle type="target" position={Position.Top} className="!bg-cyan-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-cyan-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-cyan-500/30">
|
||||
<CalendarIcon className="size-4 text-cyan-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-cyan-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function DateNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-cyan-300/80 line-clamp-2">
|
||||
{d.description || "Date value"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-cyan-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-cyan-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function NarrativeBeatNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-blue-950/80 border border-blue-500/50 rounded-lg shadow-md min-w-56">
|
||||
<Handle type="target" position={Position.Top} className="!bg-blue-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-blue-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-blue-500/30">
|
||||
<BookOpenTextIcon className="size-4 text-blue-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-blue-200 flex-1 truncate">
|
||||
|
|
@ -19,7 +19,7 @@ export function NarrativeBeatNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-blue-300/80 line-clamp-3">
|
||||
{d.text || "No description."}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-blue-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-blue-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,13 +267,30 @@ export function NarrativeFlowEditor() {
|
|||
<MiniMap
|
||||
className="!border-zinc-700"
|
||||
style={{ background: "#18181b" }}
|
||||
nodeColor={(n) =>
|
||||
n.type === "choice"
|
||||
? "#d97706"
|
||||
: n.type === "outcome"
|
||||
? "#10b981"
|
||||
: "#3b82f6"
|
||||
}
|
||||
nodeColor={(n) => {
|
||||
switch (n.type) {
|
||||
case "choice":
|
||||
return "#d97706"; // amber
|
||||
case "outcome":
|
||||
return "#10b981"; // emerald
|
||||
case "narrativeBeat":
|
||||
return "#3b82f6"; // blue
|
||||
case "wait":
|
||||
return "#facc15"; // yellow
|
||||
case "number":
|
||||
return "#a855f7"; // purple
|
||||
case "string":
|
||||
return "#14b8a6"; // teal
|
||||
case "random":
|
||||
return "#ec4899"; // pink
|
||||
case "boolean":
|
||||
return "#34d399"; // light green
|
||||
case "date":
|
||||
return "#06b6d4"; // cyan
|
||||
default:
|
||||
return "#6366f1"; // indigo
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ReactFlow>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function NumberNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-purple-950/80 border border-purple-500/50 rounded-lg shadow-md min-w-32">
|
||||
<Handle type="target" position={Position.Top} className="!bg-purple-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-purple-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-purple-500/30">
|
||||
<HashIcon className="size-4 text-purple-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-purple-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function NumberNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-purple-300/80 line-clamp-2">
|
||||
{d.description || "Numeric value"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-purple-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-purple-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ export function OutcomeNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-emerald-950/80 border border-emerald-500/50 rounded-lg shadow-md min-w-56">
|
||||
<Handle type="target" position={Position.Top} className="!bg-emerald-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-emerald-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-emerald-500/30">
|
||||
<FlagIcon className="size-4 text-emerald-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-emerald-200 flex-1 truncate">
|
||||
{d.title || "Untitled Outcome"}
|
||||
</span>
|
||||
<PencilIcon className="size-3 text-emerald-500/40 shrink-0" />
|
||||
<PencilIcon className="size-3 text-emerald-500/60 shrink-0" />
|
||||
</div>
|
||||
<div className="px-3 py-2 border-b border-emerald-500/20 text-xs text-emerald-300/80 line-clamp-2">
|
||||
{d.text || "No description."}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function RandomNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-pink-950/80 border border-pink-500/50 rounded-lg shadow-md min-w-32">
|
||||
<Handle type="target" position={Position.Top} className="!bg-pink-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-pink-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-pink-500/30">
|
||||
<ShuffleIcon className="size-4 text-pink-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-pink-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function RandomNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-pink-300/80 line-clamp-2">
|
||||
{d.description || "Random number generator"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-pink-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-pink-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function StringNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-teal-950/80 border border-teal-500/50 rounded-lg shadow-md min-w-32">
|
||||
<Handle type="target" position={Position.Top} className="!bg-teal-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-teal-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-teal-500/30">
|
||||
<TypeIcon className="size-4 text-teal-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-teal-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function StringNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-teal-300/80 line-clamp-2">
|
||||
{d.description || "String value"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-teal-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-teal-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function WaitNode({ data }: NodeProps) {
|
|||
|
||||
return (
|
||||
<div className="bg-yellow-950/80 border border-yellow-500/50 rounded-lg shadow-md min-w-48">
|
||||
<Handle type="target" position={Position.Top} className="!bg-yellow-400" />
|
||||
<Handle type="target" position={Position.Left} className="!bg-yellow-400" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-yellow-500/30">
|
||||
<TimerIcon className="size-4 text-yellow-400 shrink-0" />
|
||||
<span className="text-sm font-medium text-yellow-200 flex-1 truncate">
|
||||
|
|
@ -18,7 +18,7 @@ export function WaitNode({ data }: NodeProps) {
|
|||
<div className="px-3 py-2 text-xs text-yellow-300/80 line-clamp-2">
|
||||
{d.input !== undefined ? `Input: ${String(d.input).substring(0, 50)}${String(d.input).length > 50 ? "..." : ""}` : "No input"}
|
||||
</div>
|
||||
<Handle type="source" position={Position.Bottom} className="!bg-yellow-400" />
|
||||
<Handle type="source" position={Position.Right} className="!bg-yellow-400" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue