From 9105d22c46881ec75b841e2925c0326ce14939c0 Mon Sep 17 00:00:00 2001 From: peterkogo Date: Thu, 12 Dec 2024 12:11:07 +0100 Subject: [PATCH] Fixed rerendering of edges & simplified rerendering of nodes --- .../components/NodeWrapper/NodeWrapper.svelte | 19 +++++-------------- .../src/lib/components/NodeWrapper/types.ts | 4 ++-- .../EdgeRenderer/EdgeRenderer.svelte | 16 ++++++++++++---- .../NodeRenderer/NodeRenderer.svelte | 10 ++++++++-- .../src/lib/store/initial-store.svelte.ts | 5 +++-- packages/svelte/src/lib/types/edges.ts | 1 + 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte index 96885848..00d830ee 100644 --- a/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte +++ b/packages/svelte/src/lib/components/NodeWrapper/NodeWrapper.svelte @@ -45,7 +45,11 @@ initialHeight, width, height, - dragHandle + dragHandle, + internals: { + z: zIndex = 0, + positionAbsolute: { x: positionX, y: positionY } + } } = $derived(node); let { id } = node; @@ -55,19 +59,6 @@ let connectable = $derived(_connectable ?? store.nodesConnectable); let initialized = $derived(nodeHasDimensions(node)); - // we also pass store.nodes to this function to rerender when a node changes - // eslint-disable-next-line @typescript-eslint/no-unused-vars - function getInternalNode(node: Node, nodes: Node[]) { - return { ...store.nodeLookup.get(node.id)! }; - } - - let { - internals: { - z: zIndex = 0, - positionAbsolute: { x: positionX, y: positionY } - } - } = $derived(getInternalNode(node, store.nodes)); - function isInParentLookup(id: string) { return store.parentLookup.has(id); } diff --git a/packages/svelte/src/lib/components/NodeWrapper/types.ts b/packages/svelte/src/lib/components/NodeWrapper/types.ts index 2e06e63f..d0633c7d 100644 --- a/packages/svelte/src/lib/components/NodeWrapper/types.ts +++ b/packages/svelte/src/lib/components/NodeWrapper/types.ts @@ -1,12 +1,12 @@ import type { SvelteFlowStore } from '$lib/store/types'; -import type { Node } from '$lib/types'; +import type { InternalNode } from '$lib/types'; export type ConnectableContext = { value: boolean; }; export type NodeWrapperProps = { - node: Node; + node: InternalNode; store: SvelteFlowStore; nodeClickDistance?: number; resizeObserver?: ResizeObserver | null; diff --git a/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte b/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte index 70ca8370..0be591e6 100644 --- a/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte +++ b/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte @@ -28,10 +28,17 @@ continue; } - // we reuse the previous edge object if the source and target node are the same as before - // references to internalNodes that haven't changed stay the same + // we reuse the previous edge object if + // the current and previous edge are the same + // and the source and target node are the same + // and references to internalNodes are the same const previous = previousLayoutedEdges.get(edge.id); - if (previous && sourceNode == previous.sourceNode && targetNode == previous.targetNode) { + if ( + previous && + edge == previous.edge && + sourceNode == previous.sourceNode && + targetNode == previous.targetNode + ) { layoutedEdges.set(edge.id, previous); continue; } @@ -58,7 +65,8 @@ }), ...edgePosition, sourceNode, - targetNode + targetNode, + edge }); } } diff --git a/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte b/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte index a86f64c4..50d63c3c 100644 --- a/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte +++ b/packages/svelte/src/lib/container/NodeRenderer/NodeRenderer.svelte @@ -3,8 +3,9 @@ import { NodeWrapper } from '$lib/components/NodeWrapper'; - import type { NodeEvents } from '$lib/types'; + import type { Node, NodeEvents } from '$lib/types'; import type { SvelteFlowStore } from '$lib/store/types'; + import type { NodeLookup } from '@xyflow/system'; let { store, @@ -41,10 +42,15 @@ onDestroy(() => { resizeObserver?.disconnect(); }); + + // We pass an unused reference to nodes to trigger a re-render + function getNodes(nodeLookup: NodeLookup, nodes: Node[]) { + return nodeLookup.values(); + }
- {#each store.nodes as node (node.id)} + {#each getNodes(store.nodeLookup, store.nodes) as node (node.id)} { connectionLookup: ConnectionLookup = new Map(); edgeLookup: EdgeLookup = new Map(); - adoptNodes: Set = $derived.by(() => { - return adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, { + adoptNodes: true = $derived.by(() => { + adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, { nodeExtent: this.nodeExtent, nodeOrigin: this.nodeOrigin, elevateNodesOnSelect: false, checkEquality: true }); + return true; }); adoptEdges: true = $derived.by(() => { updateConnectionLookup(this.connectionLookup, this.edgeLookup, signals.edges); diff --git a/packages/svelte/src/lib/types/edges.ts b/packages/svelte/src/lib/types/edges.ts index 3901be4c..decabe5e 100644 --- a/packages/svelte/src/lib/types/edges.ts +++ b/packages/svelte/src/lib/types/edges.ts @@ -176,4 +176,5 @@ export type EdgeLayouted = Pick< targetNode?: Node; sourceHandleId?: string | null; targetHandleId?: string | null; + edge: Edge; };