Files
xyflow/packages/svelte/src/lib/container/EdgeRenderer/EdgeRenderer.svelte
T

106 lines
2.7 KiB
Svelte

<script lang="ts">
import { EdgeWrapper } from '$lib/components/EdgeWrapper';
import { CallOnMount } from '$lib/components/CallOnMount';
import { MarkerDefinition } from '$lib/container/EdgeRenderer/MarkerDefinition';
import type { EdgeEvents, EdgeLayouted } from '$lib/types';
import { getEdgePosition, getElevatedEdgeZIndex } from '@xyflow/system';
import type { SvelteFlowStore } from '$lib/store/types';
let {
store,
onedgeclick,
onedgecontextmenu,
onedgemouseenter,
onedgemouseleave
}: { store: SvelteFlowStore } & EdgeEvents = $props();
let previousLayoutedEdges = new Map<string, EdgeLayouted>();
let layoutedEdges = $derived.by(() => {
store.nodes;
const layoutedEdges = new Map<string, EdgeLayouted>();
for (let edge of store.edges) {
const sourceNode = store.nodeLookup.get(edge.source);
const targetNode = store.nodeLookup.get(edge.target);
if (!sourceNode || !targetNode) {
continue;
}
// 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 &&
edge == previous.edge &&
sourceNode == previous.sourceNode &&
targetNode == previous.targetNode
) {
layoutedEdges.set(edge.id, previous);
continue;
}
const edgePosition = getEdgePosition({
id: edge.id,
sourceNode,
targetNode,
sourceHandle: edge.sourceHandle || null,
targetHandle: edge.targetHandle || null,
connectionMode: store.connectionMode,
onError: store.onerror
});
if (edgePosition) {
layoutedEdges.set(edge.id, {
...edge,
zIndex: getElevatedEdgeZIndex({
selected: edge.selected,
zIndex: edge.zIndex,
sourceNode,
targetNode,
elevateOnSelect: false
}),
...edgePosition,
sourceNode,
targetNode,
edge
});
}
}
previousLayoutedEdges = layoutedEdges;
return layoutedEdges;
});
</script>
<div class="svelte-flow__edges">
<svg class="svelte-flow__marker">
<MarkerDefinition />
</svg>
{#each layoutedEdges.values() as edge (edge.id)}
<EdgeWrapper
{store}
{edge}
{onedgeclick}
{onedgecontextmenu}
{onedgemouseenter}
{onedgemouseleave}
/>
{/each}
{#if layoutedEdges.size > 0}
<CallOnMount
onMount={() => {
store.edgesInitialized = true;
}}
onDestroy={() => {
store.edgesInitialized = false;
}}
/>
{/if}
</div>