added useNodeConnections
This commit is contained in:
69
packages/react/src/hooks/useNodeConnections.ts
Normal file
69
packages/react/src/hooks/useNodeConnections.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import {
|
||||
Connection,
|
||||
HandleConnection,
|
||||
HandleType,
|
||||
areConnectionMapsEqual,
|
||||
handleConnectionChange,
|
||||
errorMessages,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore } from './useStore';
|
||||
import { useNodeId } from '../contexts/NodeIdContext';
|
||||
|
||||
const error014 = errorMessages['error014']();
|
||||
|
||||
type UseNodeConnectionsParams = {
|
||||
type?: HandleType;
|
||||
handleId?: string;
|
||||
nodeId?: string;
|
||||
onConnect?: (connections: Connection[]) => void;
|
||||
onDisconnect?: (connections: Connection[]) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
|
||||
*
|
||||
* @public
|
||||
* @param param.nodeId - node id - optional if called inside a custom node
|
||||
* @param param.type - filter by handle type 'source' or 'target'
|
||||
* @param param.handleId - filter by handle id (this is only needed if the node has multiple handles of the same type)
|
||||
* @param param.onConnect - gets called when a connection is established
|
||||
* @param param.onDisconnect - gets called when a connection is removed
|
||||
* @returns an array with connections
|
||||
*/
|
||||
export function useHandleConnections({
|
||||
type,
|
||||
handleId,
|
||||
nodeId,
|
||||
onConnect,
|
||||
onDisconnect,
|
||||
}: UseNodeConnectionsParams): HandleConnection[] {
|
||||
const _nodeId = useNodeId();
|
||||
const currentNodeId = nodeId ?? _nodeId;
|
||||
|
||||
if (!currentNodeId) {
|
||||
throw new Error(error014);
|
||||
}
|
||||
|
||||
const prevConnections = useRef<Map<string, HandleConnection> | null>(null);
|
||||
|
||||
const connections = useStore(
|
||||
(state) =>
|
||||
state.connectionLookup.get(`${currentNodeId}${type ? (handleId ? `-${type}-${handleId}` : `-${type}`) : ''}`),
|
||||
areConnectionMapsEqual
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// @todo dicuss if onConnect/onDisconnect should be called when the component mounts/unmounts
|
||||
if (prevConnections.current && prevConnections.current !== connections) {
|
||||
const _connections = connections ?? new Map();
|
||||
handleConnectionChange(prevConnections.current, _connections, onDisconnect);
|
||||
handleConnectionChange(_connections, prevConnections.current, onConnect);
|
||||
}
|
||||
|
||||
prevConnections.current = connections ?? new Map();
|
||||
}, [connections, onConnect, onDisconnect]);
|
||||
|
||||
return useMemo(() => Array.from(connections?.values() ?? []), [connections]);
|
||||
}
|
||||
62
packages/svelte/src/lib/hooks/useNodeConnections.ts
Normal file
62
packages/svelte/src/lib/hooks/useNodeConnections.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { derived } from 'svelte/store';
|
||||
import {
|
||||
areConnectionMapsEqual,
|
||||
errorMessages,
|
||||
type HandleConnection,
|
||||
type HandleType
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
const error014 = errorMessages['error014']();
|
||||
|
||||
type UseNodeConnectionsParams = {
|
||||
type?: HandleType;
|
||||
handleId?: string;
|
||||
nodeId?: string;
|
||||
// TODO: Svelte 5
|
||||
// onConnect?: (connections: Connection[]) => void;
|
||||
// onDisconnect?: (connections: Connection[]) => void;
|
||||
};
|
||||
|
||||
const initialConnections: HandleConnection[] = [];
|
||||
|
||||
/**
|
||||
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
|
||||
*
|
||||
* @public
|
||||
* @param param.nodeId - node id - optional if called inside a custom node
|
||||
* @param param.type - filter by handle type 'source' or 'target'
|
||||
* @param param.handleId - filter by handle id (this is only needed if the node has multiple handles of the same type)
|
||||
* @todo @param param.onConnect - gets called when a connection is established
|
||||
* @todo @param param.onDisconnect - gets called when a connection is removed
|
||||
* @returns an array with connections
|
||||
*/
|
||||
export function useHandleConnections({ type, nodeId, handleId }: UseNodeConnectionsParams) {
|
||||
const { edges, connectionLookup } = useStore();
|
||||
|
||||
const _nodeId = getContext<string>('svelteflow__node_id');
|
||||
const currentNodeId = nodeId ?? _nodeId;
|
||||
|
||||
if (!currentNodeId) {
|
||||
throw new Error(error014);
|
||||
}
|
||||
|
||||
let prevConnections: Map<string, HandleConnection> | undefined = undefined;
|
||||
|
||||
return derived(
|
||||
[edges, connectionLookup],
|
||||
([, connectionLookup], set) => {
|
||||
const nextConnections = connectionLookup.get(
|
||||
`${currentNodeId}${type ? (handleId ? `-${type}-${handleId}` : `-${type}`) : ''}`
|
||||
);
|
||||
|
||||
if (!areConnectionMapsEqual(nextConnections, prevConnections)) {
|
||||
prevConnections = nextConnections;
|
||||
set(Array.from(prevConnections?.values() || []));
|
||||
}
|
||||
},
|
||||
initialConnections
|
||||
);
|
||||
}
|
||||
@@ -24,6 +24,8 @@ export const errorMessages = {
|
||||
`Node with id "${id}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,
|
||||
error013: (lib: string = 'react') =>
|
||||
`It seems that you haven't loaded the styles. Please import '@xyflow/${lib}/dist/style.css' or base.css to make sure everything is working properly.`,
|
||||
error014: () =>
|
||||
'useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.',
|
||||
};
|
||||
|
||||
export const infiniteExtent: CoordinateExtent = [
|
||||
|
||||
Reference in New Issue
Block a user