feat(svelte): add useHandleConnections, useNodesData and useUpdateNodeData
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { derived } from 'svelte/store';
|
||||
import { areConnectionMapsEqual, type Connection, type HandleType } from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
export type useHandleConnectionsParams = {
|
||||
nodeId: string;
|
||||
type: HandleType;
|
||||
id?: string | null;
|
||||
};
|
||||
|
||||
const initialConnections: Connection[] = [];
|
||||
|
||||
export function useHandleConnections({ nodeId, type, id = null }: useHandleConnectionsParams) {
|
||||
const { edges, connectionLookup } = useStore();
|
||||
let prevConnections: Map<string, Connection> | undefined = undefined;
|
||||
|
||||
return derived(
|
||||
[edges, connectionLookup],
|
||||
([, connectionLookup], set) => {
|
||||
const nextConnections = connectionLookup.get(`${nodeId}-${type}-${id || null}`);
|
||||
|
||||
if (!areConnectionMapsEqual(nextConnections, prevConnections)) {
|
||||
prevConnections = nextConnections;
|
||||
set(Array.from(prevConnections?.values() || []));
|
||||
}
|
||||
},
|
||||
initialConnections
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { derived, type Readable } from 'svelte/store';
|
||||
|
||||
import type { Node } from '$lib/types';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
function areNodesDataEqual(a: Node['data'][] | null, b: Node['data'][] | null) {
|
||||
if ((!a && !b) || (!a?.length && !b?.length)) {
|
||||
true;
|
||||
}
|
||||
|
||||
if (!a || !b || a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function useNodesData<NodeType extends Node = Node>(
|
||||
nodeId: string
|
||||
): Readable<NodeType['data'] | null>;
|
||||
export function useNodesData<NodeType extends Node = Node>(
|
||||
nodeIds: string[]
|
||||
): Readable<NodeType['data'][]>;
|
||||
export function useNodesData<NodeType extends Node = Node>(
|
||||
nodeIds: string[],
|
||||
guard: (node: Node) => node is NodeType
|
||||
): Readable<NodeType['data'][]>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function useNodesData(nodeIds: any): any {
|
||||
const { nodes, nodeLookup } = useStore();
|
||||
let prevNodesData: (Node['data'] | null)[] | null = null;
|
||||
|
||||
return derived([nodes, nodeLookup], ([, nodeLookup], set) => {
|
||||
let nextNodesData: (Node['data'] | null)[] | null = null;
|
||||
const nodeIdArray = Array.isArray(nodeIds);
|
||||
|
||||
if (!nodeIdArray) {
|
||||
nextNodesData = [nodeLookup.get(nodeIds)?.data || null];
|
||||
} else {
|
||||
const data = [];
|
||||
|
||||
for (const nodeId of nodeIds) {
|
||||
const nodeData = nodeLookup.get(nodeId)?.data;
|
||||
|
||||
if (nodeData) {
|
||||
data.push(nodeData);
|
||||
}
|
||||
}
|
||||
|
||||
nextNodesData = data;
|
||||
}
|
||||
|
||||
if (!areNodesDataEqual(nextNodesData, prevNodesData)) {
|
||||
prevNodesData = nextNodesData;
|
||||
set(nodeIdArray ? nextNodesData : nextNodesData[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
export function useUpdateNodeData(): (id: string, data: unknown) => void {
|
||||
const { nodes } = useStore();
|
||||
|
||||
const updateNodeData = (id: string, data: unknown) => {
|
||||
nodes.update((nds) =>
|
||||
nds.map((node) => {
|
||||
if (node.id === id) {
|
||||
return {
|
||||
...node,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
return node;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return updateNodeData;
|
||||
}
|
||||
Reference in New Issue
Block a user