66 lines
3.3 KiB
TypeScript
66 lines
3.3 KiB
TypeScript
import React, { useMemo } from 'react'
|
|
import type { Connection } from '@xyflow/react'
|
|
import type { AppNode, AppEdge } from '@/lib/nodeTypes'
|
|
|
|
export type ConnectionFrom = { nodeId: string; sourceHandle?: string } | null
|
|
|
|
/** Role of a node in the current connection path update: pushing data, receiving/loading, or just on path. */
|
|
export type ConnectionPathRole = 'trigger' | 'updating' | 'on-path'
|
|
|
|
export type FlowActions = {
|
|
pasteAtViewportCenter: () => void
|
|
fitView: () => void
|
|
}
|
|
|
|
export type FlowContextValue = {
|
|
nodes: AppNode[]
|
|
setNodes: (updater: AppNode[] | ((prev: AppNode[]) => AppNode[])) => void
|
|
edges: AppEdge[]
|
|
setEdges: (updater: AppEdge[] | ((prev: AppEdge[]) => AppEdge[])) => void
|
|
renamingNodeId: string | null
|
|
setRenamingNodeId: (id: string | null) => void
|
|
/** Set when user starts dragging from an output handle; cleared on connect end. Used to highlight valid targets. */
|
|
connectionFrom: ConnectionFrom
|
|
setConnectionFrom: (v: ConnectionFrom) => void
|
|
isValidConnection: (connection: Connection) => boolean
|
|
/** Set by FlowKeyboardShortcuts so Node menubar can trigger paste / fit view. */
|
|
flowActionsRef: React.MutableRefObject<FlowActions | null>
|
|
/** When set, graph centers on this node and a fullscreen dialog shows the node. Cleared on close. */
|
|
fullscreenNodeId: string | null
|
|
setFullscreenNodeId: (id: string | null) => void
|
|
/** Node ids currently updating (e.g. render loading, agent running). Only edges on those paths show the ant trail. */
|
|
connectionPathUpdatingNodeIds: string[]
|
|
/** Node ids that triggered the current update (e.g. variable/config that changed). Path is restricted to downstream(trigger) ∩ upstream(updating). */
|
|
connectionPathTriggerNodeIds: string[]
|
|
/** Call when this node's output changed and may trigger downstream updates (e.g. variable value, config content). */
|
|
addConnectionPathTrigger: (nodeId: string) => void
|
|
/** All node ids on the path of an update. Edges with both endpoints in this set animate. */
|
|
connectionPathNodeIds: Set<string>
|
|
/** Call when a path update starts for this node. Animation runs at least CONNECTION_PATH_UPDATE_MIN_MS. */
|
|
startConnectionPathUpdate: (nodeId: string) => void
|
|
/** Call when a path update ends for this node. If min duration not reached, animation continues until then. */
|
|
endConnectionPathUpdate: (nodeId: string) => void
|
|
}
|
|
|
|
const FlowContext = React.createContext<FlowContextValue | null>(null)
|
|
|
|
export default FlowContext
|
|
|
|
/**
|
|
* Returns this node's role in the current path update for styling (pushing vs receiving).
|
|
* Use with BaseNode's connectionPathRole prop or data-path-role for CSS.
|
|
*/
|
|
export function useConnectionPathRole(nodeId: string | undefined): ConnectionPathRole | null {
|
|
const ctx = React.useContext(FlowContext)
|
|
return useMemo(() => {
|
|
if (!nodeId) return null
|
|
const triggers = ctx?.connectionPathTriggerNodeIds
|
|
const updating = ctx?.connectionPathUpdatingNodeIds
|
|
const path = ctx?.connectionPathNodeIds
|
|
if (!path?.has(nodeId)) return null
|
|
if (triggers?.includes(nodeId)) return 'trigger'
|
|
if (updating?.includes(nodeId)) return 'updating'
|
|
return 'on-path'
|
|
}, [nodeId, ctx?.connectionPathTriggerNodeIds, ctx?.connectionPathUpdatingNodeIds, ctx?.connectionPathNodeIds])
|
|
}
|