import { useStore } from '@nanostores/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { $edgePendingUpdate, $pendingConnection, $templates } from 'features/nodes/store/nodesSlice'; import { selectNodesSlice } from 'features/nodes/store/selectors'; import { makeConnectionErrorSelector } from 'features/nodes/store/util/makeConnectionErrorSelector'; import { useMemo } from 'react'; type UseConnectionStateProps = { nodeId: string; fieldName: string; kind: 'inputs' | 'outputs'; }; export const useConnectionState = ({ nodeId, fieldName, kind }: UseConnectionStateProps) => { const pendingConnection = useStore($pendingConnection); const templates = useStore($templates); const edgePendingUpdate = useStore($edgePendingUpdate); const selectIsConnected = useMemo( () => createSelector(selectNodesSlice, (nodes) => Boolean( nodes.edges.filter((edge) => { return ( (kind === 'inputs' ? edge.target : edge.source) === nodeId && (kind === 'inputs' ? edge.targetHandle : edge.sourceHandle) === fieldName ); }).length ) ), [fieldName, kind, nodeId] ); const selectValidationResult = useMemo( () => makeConnectionErrorSelector(templates, nodeId, fieldName, kind === 'inputs' ? 'target' : 'source'), [templates, nodeId, fieldName, kind] ); const isConnected = useAppSelector(selectIsConnected); const isConnectionInProgress = useMemo(() => Boolean(pendingConnection), [pendingConnection]); const isConnectionStartField = useMemo(() => { if (!pendingConnection) { return false; } return ( pendingConnection.nodeId === nodeId && pendingConnection.handleId === fieldName && pendingConnection.fieldTemplate.fieldKind === { inputs: 'input', outputs: 'output' }[kind] ); }, [fieldName, kind, nodeId, pendingConnection]); const validationResult = useAppSelector((s) => selectValidationResult(s, pendingConnection, edgePendingUpdate)); const shouldDim = useMemo( () => Boolean(isConnectionInProgress && !validationResult.isValid && !isConnectionStartField), [validationResult, isConnectionInProgress, isConnectionStartField] ); return { isConnected, isConnectionInProgress, isConnectionStartField, validationResult, shouldDim, }; };