From 6fd9d19797ca72997d0c0afdbb71418e2238c825 Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 5 Oct 2023 13:28:04 +0200 Subject: [PATCH] feat(react, svelte) added getIncomers & getOutgoers to use...Flow() --- packages/react/src/hooks/useReactFlow.ts | 36 +++++++++++++++++-- packages/react/src/types/instance.ts | 2 ++ .../svelte/src/lib/hooks/useSvelteFlow.ts | 24 +++++++++++++ packages/system/src/utils/graph.ts | 8 ++--- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts index cec31cc8..8e94954a 100644 --- a/packages/react/src/hooks/useReactFlow.ts +++ b/packages/react/src/hooks/useReactFlow.ts @@ -1,5 +1,13 @@ import { useCallback, useMemo } from 'react'; -import { getElementsToRemove, getOverlappingArea, isRectObject, nodeToRect, type Rect } from '@xyflow/system'; +import { + getElementsToRemove, + getIncomersBase, + getOutgoersBase, + getOverlappingArea, + isRectObject, + nodeToRect, + type Rect, +} from '@xyflow/system'; import useViewportHelper from './useViewportHelper'; import { useStoreApi } from '../hooks/useStore'; @@ -224,7 +232,7 @@ export default function useReactFlow(): ReactFlo ); const getConnectedEdges = useCallback((node) => { - const edges = store.getState().edges; + const { edges } = store.getState(); const nodeIds = new Set(); if (typeof node === 'string') { @@ -238,6 +246,26 @@ export default function useReactFlow(): ReactFlo return edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target)); }, []); + const getIncomers = useCallback((node) => { + const { nodes, edges } = store.getState(); + + if (typeof node === 'string') { + return getIncomersBase({ id: node }, nodes, edges); + } + + return getIncomersBase(node, nodes, edges); + }, []); + + const getOutgoers = useCallback((node) => { + const { nodes, edges } = store.getState(); + + if (typeof node == 'string') { + return getOutgoersBase({ id: node }, nodes, edges); + } + + return getOutgoersBase(node, nodes, edges); + }, []); + return useMemo(() => { return { ...viewportHelper, @@ -254,6 +282,8 @@ export default function useReactFlow(): ReactFlo getIntersectingNodes, isNodeIntersecting, getConnectedEdges, + getIncomers, + getOutgoers, }; }, [ viewportHelper, @@ -270,5 +300,7 @@ export default function useReactFlow(): ReactFlo getIntersectingNodes, isNodeIntersecting, getConnectedEdges, + getIncomers, + getOutgoers, ]); } diff --git a/packages/react/src/types/instance.ts b/packages/react/src/types/instance.ts index 0bc61617..694329fb 100644 --- a/packages/react/src/types/instance.ts +++ b/packages/react/src/types/instance.ts @@ -40,6 +40,8 @@ export namespace Instance { partially?: boolean ) => boolean; export type getConnectedEdges = (id: string | (Partial & { id: Node['id'] })[]) => Edge[]; + export type getIncomers = (node: string | (Partial & { id: Node['id'] })) => Node[]; + export type getOutgoers = (node: string | (Partial & { id: Node['id'] })) => Node[]; } export type ReactFlowInstance = { diff --git a/packages/svelte/src/lib/hooks/useSvelteFlow.ts b/packages/svelte/src/lib/hooks/useSvelteFlow.ts index 191b2ea0..c3b6caec 100644 --- a/packages/svelte/src/lib/hooks/useSvelteFlow.ts +++ b/packages/svelte/src/lib/hooks/useSvelteFlow.ts @@ -1,5 +1,7 @@ import { get, type Writable } from 'svelte/store'; import { + getIncomersBase, + getOutgoersBase, pointToRendererPoint, type Project, type SetCenterOptions, @@ -27,6 +29,8 @@ export function useSvelteFlow(): { nodes: SvelteFlowStore['nodes']; edges: SvelteFlowStore['edges']; getConnectedEdges: (id: string | (Partial & { id: Node['id'] })[]) => Edge[]; + getIncomers: (node: string | (Partial & { id: Node['id'] })) => Node[]; + getOutgoers: (node: string | (Partial & { id: Node['id'] })) => Node[]; } { const { zoomIn, @@ -101,6 +105,26 @@ export function useSvelteFlow(): { return _edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target)); }, + getIncomers: (node) => { + const _edges = get(edges); + const _nodes = get(nodes); + + if (typeof node === 'string') { + return getIncomersBase({ id: node }, _nodes, _edges); + } + + return getIncomersBase(node, _nodes, _edges); + }, + getOutgoers: (node) => { + const _edges = get(edges); + const _nodes = get(nodes); + + if (typeof node == 'string') { + return getOutgoersBase({ id: node }, _nodes, _edges); + } + + return getOutgoersBase(node, _nodes, _edges); + }, viewport: viewport }; } diff --git a/packages/system/src/utils/graph.ts b/packages/system/src/utils/graph.ts index e72642be..17467503 100644 --- a/packages/system/src/utils/graph.ts +++ b/packages/system/src/utils/graph.ts @@ -35,11 +35,11 @@ export const isNodeBase = 'id' in element && !('source' in element) && !('target' in element); export const getOutgoersBase = ( - node: NodeType, + node: Partial & { id: string }, nodes: NodeType[], edges: EdgeType[] ): NodeType[] => { - if (!isNodeBase(node)) { + if (!node.id) { return []; } @@ -54,11 +54,11 @@ export const getOutgoersBase = ( - node: NodeType, + node: Partial & { id: string }, nodes: NodeType[], edges: EdgeType[] ): NodeType[] => { - if (!isNodeBase(node)) { + if (!node.id) { return []; } const incomersIds = new Set();