Files
zui/frontend/src/lib/graph/state.ts
2026-03-12 17:40:05 +01:00

88 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Central state contracts for the graph: in-memory graph, connection path (edge visuals),
* and node display status. Use these types to keep state flow predictable and readable.
*
* ## State flow (high level)
*
* 1. **Graph state** (nodes, edges) Owned by useGraphStateWithHistory, persisted by useCanvasGraph.
* Updates via setNodes/setEdges (with undo) or setNodesSilent/setEdgesSilent (no history).
*
* 2. **Connection path state** Owned by useCanvasConnectionPath, provided via FlowContext.
* Nodes report lifecycle (updating / error / paused) via useSyncConnectionStatus; the hook
* updates context sets. Edges read those sets and getConnectionStatus() to decide color (default / updating / paused / error).
*
* 3. **Node display state** Each node type derives its own UI state (e.g. loading, success, error, initial).
* Rendering node uses displayStatus from useRenderingNodeState; other nodes can use getNodeDisplayStatus().
*/
import type { AppNode, AppEdge } from './nodeTypes'
// ---------------------------------------------------------------------------
// Graph state (in-memory)
// ---------------------------------------------------------------------------
/** In-memory graph: nodes and edges. Updated via setNodes/setEdges; history in useGraphStateWithHistory. */
export type GraphState = {
nodes: AppNode[]
edges: AppEdge[]
}
// ---------------------------------------------------------------------------
// Connection path state (edge visuals and path animation)
// ---------------------------------------------------------------------------
/**
* Slice of FlowContext that drives edge status and path animation.
* Nodes report updating/error/paused via useSyncConnectionStatus; this state is derived from those reports.
* Edges use pathNodeIds, pausedSegmentNodeIds, activeSegmentNodeIds, errorTargetNodeIds in getConnectionStatus().
*/
export type ConnectionPathState = {
/** Node ids currently doing async work (e.g. render loading). Path edges show "updating" (blue). */
connectionPathUpdatingNodeIds: string[]
/** Node ids that triggered the update (e.g. config changed). Path = downstream(trigger) ∩ upstream(updating). */
connectionPathTriggerNodeIds: string[]
/** All node ids on the path. Edges with both endpoints here animate. */
connectionPathNodeIds: Set<string>
/** Path nodes in the paused segment (yellow edges). */
connectionPathPausedSegmentNodeIds: Set<string>
/** Path nodes in the active segment (blue edges). */
connectionPathActiveSegmentNodeIds: Set<string>
/** Node ids on hold (e.g. render in manual mode). */
connectionPathPausedNodeIds: string[]
/** Node ids with error (incoming edges show red). */
connectionPathErrorNodeIds: string[]
}
// ---------------------------------------------------------------------------
// Node display status (for UI: status indicator, empty state)
// ---------------------------------------------------------------------------
/** Status for node UI: what to show in NodeStatusIndicator and empty/error states. */
export type NodeDisplayStatus = 'initial' | 'loading' | 'success' | 'error'
/**
* Derive display status from node state. Use in nodes to drive NodeStatusIndicator and empty/error UI.
* Priority: loading > error > hasContent (success) > initial.
*/
export function getNodeDisplayStatus(state: {
loading: boolean
error: unknown
hasContent: boolean
}): NodeDisplayStatus {
if (state.loading) return 'loading'
if (state.error != null) return 'error'
if (state.hasContent) return 'success'
return 'initial'
}
// ---------------------------------------------------------------------------
// Stored graph state (persistence)
// ---------------------------------------------------------------------------
/** Shape of graph state when saved/loaded (e.g. localStorage). version for future migrations. */
export type StoredGraphState = {
version: number
nodes: unknown[]
edges: unknown[]
}