Find a flow's declared inputs and outputs in the global search

/search lists each input and batch output under its qualified message,
and picking one opens the flow on the label's id, which the editor now
treats like a click on the label: it opens the flow's settings.
This commit is contained in:
2026-10-05 18:15:35 +02:00
parent 901e85f3fb
commit a677409079
9 changed files with 110 additions and 21 deletions
+17 -6
View File
@@ -240,7 +240,7 @@ function FlowEditorInner({
onReload,
}: {
flowName: string
/** A node to arrive on, from the address bar. */
/** A node or endpoint to arrive on, from the address bar. */
focus?: string
onReload: () => void
}) {
@@ -272,7 +272,10 @@ function FlowEditorInner({
const [canvasNodes, setCanvasNodes, onNodesChange] = useUnpositionedNodes(
detail.definition.nodes ?? [],
)
const [selectedId, setSelectedId] = useState<string | null>(focus ?? null)
// An endpoint is never selected; arriving on one opens it instead (below).
const [selectedId, setSelectedId] = useState<string | null>(
focus && !isEndpointNode({ id: focus }) ? focus : null,
)
const [paletteOpen, setPaletteOpen] = useState(false)
const [inspected, setInspected] = useState<InspectedEdge | null>(null)
// The edges are derived, so xyflow's own selection would be thrown away on
@@ -642,10 +645,18 @@ function FlowEditorInner({
// The canvas is not remounted per node — that would throw the session away
// on every click in the brain graph — so arriving at a flow already open
// only changes the address. Seeded above for the first arrival, set here for
// the ones after it.
// the ones after it. An endpoint — an input or output found by the search —
// does what clicking its label does, which also covers one the canvas does
// not draw because a dashboard already accounts for it.
useEffect(() => {
if (focus) setSelectedId(focus)
}, [focus])
if (!focus) return
if (isEndpointNode({ id: focus })) {
openEndpoint(focus)
} else {
setFlowPanelOpen(false)
setSelectedId(focus)
}
}, [focus, openEndpoint])
const selected = definitions.find((node) => node.id === selectedId) ?? null
// A panel is the view you are working in, so it takes the room — but never
@@ -1499,7 +1510,7 @@ export function FlowEditor({
focus,
}: {
flowName: string
/** A node to select on arrival — see `FlowEditorInner`. */
/** A node or endpoint to arrive on — see `FlowEditorInner`. */
focus?: string
}) {
const navigate = useNavigate()