feat(svelte): add useHandleConnections, useNodesData and useUpdateNodeData
This commit is contained in:
@@ -171,7 +171,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
lib,
|
||||
});
|
||||
|
||||
if (isValid) {
|
||||
if (isValid && connection) {
|
||||
onConnectExtended(connection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { Connection, HandleType } from '@xyflow/system';
|
||||
import { Connection, HandleType, areConnectionMapsEqual, handleConnectionChange } from '@xyflow/system';
|
||||
|
||||
import { useStore } from './useStore';
|
||||
import { useNodeId } from '../contexts/NodeIdContext';
|
||||
@@ -52,55 +52,3 @@ export function useHandleConnections({
|
||||
|
||||
return useMemo(() => Array.from(connections?.values() ?? []), [connections]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function areConnectionMapsEqual(a?: Map<string, Connection>, b?: Map<string, Connection>) {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!a || !b || a.size !== b.size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!a.size && !b.size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const key of a.keys()) {
|
||||
if (!b.has(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* We call the callback for all connections in a that are not in b
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
function handleConnectionChange(
|
||||
a: Map<string, Connection>,
|
||||
b: Map<string, Connection>,
|
||||
cb?: (diff: Connection[]) => void
|
||||
) {
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diff: Connection[] = [];
|
||||
|
||||
a.forEach((connection, key) => {
|
||||
if (!b?.has(key)) {
|
||||
diff.push(connection);
|
||||
}
|
||||
});
|
||||
|
||||
if (diff.length) {
|
||||
cb(diff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,14 @@ import { useCallback } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { useStore } from '../hooks/useStore';
|
||||
import type { Node } from '../types';
|
||||
|
||||
export function useNodesData<NodeData = unknown>(nodeId: string): NodeData | null;
|
||||
export function useNodesData<NodeData = unknown>(nodeIds: string[]): NodeData[];
|
||||
export function useNodesData<NodeType extends Node = Node>(nodeId: string): NodeType['data'] | null;
|
||||
export function useNodesData<NodeType extends Node = Node>(nodeIds: string[]): NodeType['data'][];
|
||||
export function useNodesData<NodeType extends Node = Node>(
|
||||
nodeIds: string[],
|
||||
guard: (node: Node) => node is NodeType
|
||||
): NodeType['data'][];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function useNodesData(nodeIds: any): any {
|
||||
const nodesData = useStore(
|
||||
@@ -14,15 +19,17 @@ export function useNodesData(nodeIds: any): any {
|
||||
return s.nodeLookup.get(nodeIds)?.data || null;
|
||||
}
|
||||
|
||||
return nodeIds.reduce((res, id) => {
|
||||
const node = s.nodeLookup.get(id);
|
||||
const data = [];
|
||||
|
||||
if (node) {
|
||||
res.push(node.data);
|
||||
for (const nodeId of nodeIds) {
|
||||
const nodeData = s.nodeLookup.get(nodeId)?.data;
|
||||
|
||||
if (nodeData) {
|
||||
data.push(nodeData);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}, []);
|
||||
return data;
|
||||
},
|
||||
[nodeIds]
|
||||
),
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
panBy as panBySystem,
|
||||
Dimensions,
|
||||
updateNodeDimensions as updateNodeDimensionsSystem,
|
||||
updateConnectionLookup,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes';
|
||||
import { updateConnectionLookup, updateNodesAndEdgesSelections } from './utils';
|
||||
import { updateNodesAndEdgesSelections } from './utils';
|
||||
import getInitialState from './initialState';
|
||||
import type {
|
||||
ReactFlowState,
|
||||
|
||||
@@ -5,11 +5,10 @@ import {
|
||||
getNodesBounds,
|
||||
getViewportForBounds,
|
||||
Transform,
|
||||
Connection,
|
||||
updateConnectionLookup,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type { Edge, Node, ReactFlowStore } from '../types';
|
||||
import { updateConnectionLookup } from './utils';
|
||||
|
||||
const getInitialState = ({
|
||||
nodes = [],
|
||||
@@ -24,8 +23,8 @@ const getInitialState = ({
|
||||
height?: number;
|
||||
fitView?: boolean;
|
||||
} = {}): ReactFlowStore => {
|
||||
const nodeLookup = new Map<string, Node>();
|
||||
const connectionLookup = updateConnectionLookup(new Map<string, Map<string, Connection>>(), edges);
|
||||
const nodeLookup = new Map();
|
||||
const connectionLookup = updateConnectionLookup(new Map(), edges);
|
||||
const nextNodes = updateNodes(nodes, nodeLookup, { nodeOrigin: [0, 0], elevateNodesOnSelect: false });
|
||||
|
||||
let transform: Transform = [0, 0, 1];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { StoreApi } from 'zustand';
|
||||
import type { Edge, EdgeSelectionChange, Node, NodeSelectionChange, ReactFlowState } from '../types';
|
||||
import { Connection } from '@xyflow/system';
|
||||
|
||||
export function handleControlledSelectionChange<NodeOrEdge extends Node | Edge>(
|
||||
changes: NodeSelectionChange[] | EdgeSelectionChange[],
|
||||
@@ -43,23 +42,3 @@ export function updateNodesAndEdgesSelections({ changedNodes, changedEdges, get,
|
||||
onEdgesChange?.(changedEdges);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateConnectionLookup(lookup: Map<string, Map<string, Connection>>, edges: Edge[]) {
|
||||
lookup.clear();
|
||||
|
||||
edges.forEach(({ source, target, sourceHandle = null, targetHandle = null }) => {
|
||||
if (source && target) {
|
||||
const sourceKey = `${source}-source-${sourceHandle}`;
|
||||
const targetKey = `${target}-target-${targetHandle}`;
|
||||
|
||||
const prevSource = lookup.get(sourceKey) || new Map();
|
||||
const prevTarget = lookup.get(targetKey) || new Map();
|
||||
const connection = { source, target, sourceHandle, targetHandle };
|
||||
|
||||
lookup.set(sourceKey, prevSource.set(`${target}-${targetHandle}`, connection));
|
||||
lookup.set(targetKey, prevTarget.set(`${source}-${sourceHandle}`, connection));
|
||||
}
|
||||
});
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user