import { memo } from "react";
import { Handle, Position, type NodeProps } from "reactflow";
import type { RFData } from "../layout";
// One pipeline stage on the map. Color encodes live state; a badge shows the
// live task count; gated (P3/inert) nodes render dimmed with a tag. ARIA role +
// label keep the map reachable for screen readers / keyboard users.
function MapNodeImpl({ data }: NodeProps<RFData>) {
const { meta, state, count, dimmed, onPath, loopBackTo } = data;
const cls = [
"node",
`state-${state}`,
meta.gated ? "gated" : "",
dimmed ? "dimmed" : "",
onPath ? "on-path" : "",
]
.filter(Boolean)
.join(" ");
const canLoop = loopBackTo.length > 0;
return (
<div
className={cls}
role="group"
aria-label={`${meta.label} stage, ${state}, ${count} task${count === 1 ? "" : "s"}`}
tabIndex={0}
>
<Handle type="target" position={Position.Left} />
<div className="node-label">
{meta.label}
{meta.kind === "gate" && (
<span className="gate-pip" title="human gate" aria-hidden>
⛋
</span>
)}
{canLoop && (
<span
className="loop-chip"
title={`can send work back to ${loopBackTo.join(", ")}`}
aria-label={`can send work back to ${loopBackTo.join(", ")}`}
↺
</div>
<div className="node-agent">{meta.agent}</div>
{count > 0 && (
<span className="node-count" aria-hidden>
{count}
{meta.gated && <span className="node-gated-tag">inert</span>}
<Handle type="source" position={Position.Right} />
);
}
export const MapNode = memo(MapNodeImpl);