{activeRegion ? (
<>
/
>
) : null}
{activeView ? (
<>
/
{activeView.name}
{dirty ? " *" : ""}
>
) : null}
{selectedNodes.length > 0 || selectedEdgeId ? (
{selectedNodes.length > 0
? t("topology.selectedCount").replace("{{count}}", String(selectedNodes.length))
: t("topology.selectedEdge")}
) : null}
{(
[
["select", t("topology.toolSelect"), "V"],
["pan", t("topology.toolPan"), "H"],
["connect", t("topology.toolConnect"), "C"],
] as const
).map(([mode, label, key]) => (
))}
{t("topology.display")}
{t("topology.edgeDefaults")}
{(
[
["manual", t("topology.edgeManual")],
["discovered", t("topology.edgeDiscovered")],
["stale", t("topology.edgeStale")],
] as const
).map(([kind, label]) => {
const d = edgeDefaults[kind];
return (
{label}
updateEdgeDefault(kind, { stroke_color: e.target.value })}
/>
);
})}
setCanvasQuery(e.target.value)}
onFocus={() => {
if (canvasQuery.trim()) setFindOpen(true);
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault();
if (!canvasHits.length) return;
setFindOpen(true);
setFindActiveIdx((i) => (i + 1) % canvasHits.length);
return;
}
if (e.key === "ArrowUp") {
e.preventDefault();
if (!canvasHits.length) return;
setFindOpen(true);
setFindActiveIdx((i) => (i - 1 + canvasHits.length) % canvasHits.length);
return;
}
if (e.key === "Escape") {
setFindOpen(false);
return;
}
if (e.key === "Enter") {
e.preventDefault();
findOnCanvas();
}
}}
placeholder={t("topology.findNodePh")}
disabled={!mapId || nodes.length === 0}
aria-label={t("topology.findNode")}
aria-autocomplete="list"
aria-expanded={findOpen}
/>
{findOpen && canvasQuery.trim() ? (
{canvasHits.length === 0 ? (
{t("topology.findNoMatch")}
) : (
canvasHits.slice(0, 12).map((n, idx) => (
))
)}
{canvasHits.length > 12 ? (
{t("topology.findMore").replace("{{count}}", String(canvasHits.length - 12))}
) : null}
) : null}
) : null}
{discoverOpen ? (
{t("topology.discoverReport")}
{discovering && discoverProgress.total > 0 ? (
{t("topology.discoverProgressLive")
.replace("{{index}}", String(discoverProgress.index))
.replace("{{total}}", String(discoverProgress.total))
.replace(
"{{name}}",
discoverProgress.neName || discoverProgress.neIp || "?",
)}
{discoverPct}%
) : null}
{discovering && discoverProgress.total <= 0 ? (
{t("topology.discoverNoTargets")}
) : null}
{!discovering && discoverReport && discoverReport.scanned === 0 ? (
{t("topology.discoverNoTargets")}
) : null}
{discoverError ?
{discoverError}
: null}
{discoverResults.length > 0 || discoverReport ? (
<>
{t("topology.discoverSummary")
.replace("{{scanned}}", String(discoverSummary.scanned))
.replace("{{added}}", String(discoverSummary.added))
.replace("{{updated}}", String(discoverSummary.updated))
.replace("{{stale}}", String(discoverSummary.missing))
.replace("{{failed}}", String(discoverSummary.failed))}
>
) : null}
) : null}
{!canvasMode ? (
{activeRegion ? (
/
{regionDisplayName(activeRegion)}
) : (
{titleText}
)}
{activeRegion
? t("topology.browserRegionSub").replace(
"{{count}}",
String(browseEntries.length),
)
: t("topology.browserRegionsSub").replace(
"{{count}}",
String(regions.length),
)}
{!activeRegion ? (
regions.length === 0 ? (
{t("topology.emptyMaps")}
) : (
{regions.map((region, idx) => (
))}
)
) : browseEntries.length === 0 ? (
) : (
{browseEntries.map((v, idx) => {
const isPhysical = String(v.kind) === "physical";
const tone = isPhysical ? "physical" : String((idx + 1) % 5);
return (
);
})}
)}
) : (
{fullscreen ? (
{(
[
["select", t("topology.toolSelect"), "V"],
["pan", t("topology.toolPan"), "H"],
["connect", t("topology.toolConnect"), "C"],
] as const
).map(([mode, label, key]) => (
))}
) : null}
{treeRoot ? (
searchHitIds.includes(n.id)
? { ...n, className: "is-search-hit" }
: { ...n, className: undefined },
)}
edges={displayEdges}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
onlyRenderVisibleElements
connectionMode={ConnectionMode.Loose}
defaultEdgeOptions={{ type: "straight", labelShowBg: false }}
proOptions={{ hideAttribution: true }}
minZoom={0.05}
maxZoom={4}
nodesDraggable={toolBehavior.nodesDraggable}
nodesConnectable={toolBehavior.nodesConnectable}
elementsSelectable={toolBehavior.elementsSelectable}
panOnDrag={toolBehavior.panOnDrag}
selectionOnDrag={toolBehavior.selectionOnDrag}
panOnScroll={toolBehavior.panOnScroll}
selectionMode={SelectionMode.Partial}
multiSelectionKeyCode="Shift"
snapToGrid={snapToGrid}
snapGrid={SNAP_GRID}
onNodeDragStart={() => {
pushHistory();
}}
onNodesChange={(changes) => {
if (
changes.some(
(c) => c.type === "position" || c.type === "remove" || c.type === "add",
)
) {
markDirty();
}
onNodesChange(changes);
}}
onEdgesChange={(changes) => {
const physical = changes.filter((c) => {
if (c.type === "select") return false;
if ("id" in c && isAggregateEdgeId(String(c.id))) return false;
return true;
});
if (physical.some((c) => c.type !== "select")) {
markDirty();
}
if (physical.length) onEdgesChange(physical);
}}
onConnect={onConnect}
isValidConnection={isValidConnection}
onNodeClick={onNodeClick}
onEdgeClick={(_e, edge) => {
setCtxMenu(null);
focusEdge(edge.id);
}}
onPaneClick={() => {
setCtxMenu(null);
clearSelection();
}}
onNodeContextMenu={(e, node) => {
e.preventDefault();
const multi = selectedNodeIds.length > 1 && selectedNodeIds.includes(node.id);
if (!multi) focusNode(node.id, false);
const pos = placeCtxMenu(e.clientX, e.clientY);
setCtxMenu(
multi ? { kind: "selection", ...pos } : { kind: "node", id: node.id, ...pos },
);
}}
onEdgeContextMenu={(e, edge) => {
e.preventDefault();
focusEdge(edge.id);
const pos = placeCtxMenu(e.clientX, e.clientY, { w: 260, h: 280 });
setCtxMenu({ kind: "edge", id: edge.id, ...pos });
}}
onSelectionContextMenu={(e) => {
e.preventDefault();
const pos = placeCtxMenu(e.clientX, e.clientY);
setCtxMenu({ kind: "selection", ...pos });
}}
onMoveStart={closeCtxMenu}
onInit={(inst) => {
rfRef.current = inst as ReactFlowInstance, Edge>;
if (nodesRef.current.length > 0) {
window.setTimeout(() => inst.fitView({ ...FIT_VIEW_OPTS }), 0);
}
}}
fitView
fitViewOptions={{ ...FIT_VIEW_OPTS }}
deleteKeyCode={null}
edgesFocusable
>
{toolMode === "connect" ? (
{t("topology.connectHint")}
) : null}
void toggleFullscreen()}
title={fullscreen ? t("topology.exitFullscreen") : t("topology.fullscreen")}
aria-label={fullscreen ? t("topology.exitFullscreen") : t("topology.fullscreen")}
>
) : (
{t("topology.treeLoading")}
)}
)}