From 66caa4c8caf7119623b13cf1d0ae17ca0ef08d86 Mon Sep 17 00:00:00 2001
From: Peter
Date: Wed, 27 Sep 2023 13:40:03 +0200
Subject: [PATCH] chore(svelte) refactored connectionPath & connection
---
.../ConnectionLine.svelte | 8 +--
.../ConnectionLine/ConnectionLine.svelte | 8 +--
...on-path.ts => derived-connection-props.ts} | 49 +++++++++++++++++--
packages/svelte/src/lib/store/index.ts | 42 +++++++---------
.../svelte/src/lib/store/initial-store.ts | 13 ++---
packages/system/src/types/general.ts | 8 +--
packages/system/src/xyhandle/XYHandle.ts | 17 +++++--
7 files changed, 88 insertions(+), 57 deletions(-)
rename packages/svelte/src/lib/store/{connection-path.ts => derived-connection-props.ts} (68%)
diff --git a/examples/svelte/src/routes/custom-connection-line/ConnectionLine.svelte b/examples/svelte/src/routes/custom-connection-line/ConnectionLine.svelte
index a3676bb0..20ac6192 100644
--- a/examples/svelte/src/routes/custom-connection-line/ConnectionLine.svelte
+++ b/examples/svelte/src/routes/custom-connection-line/ConnectionLine.svelte
@@ -1,11 +1,11 @@
-{#if $connectionPath}
-
-
+{#if $connection.path}
+
+
{/if}
diff --git a/packages/svelte/src/lib/components/ConnectionLine/ConnectionLine.svelte b/packages/svelte/src/lib/components/ConnectionLine/ConnectionLine.svelte
index 9f53f486..d88cb728 100644
--- a/packages/svelte/src/lib/components/ConnectionLine/ConnectionLine.svelte
+++ b/packages/svelte/src/lib/components/ConnectionLine/ConnectionLine.svelte
@@ -6,14 +6,14 @@
export let containerStyle: string = '';
export let style: string = '';
- const { connectionPath, width, height, connection } = useStore();
+ const { width, height, connection } = useStore();
-{#if $connectionPath}
+{#if $connection.path}
diff --git a/packages/svelte/src/lib/store/connection-path.ts b/packages/svelte/src/lib/store/derived-connection-props.ts
similarity index 68%
rename from packages/svelte/src/lib/store/connection-path.ts
rename to packages/svelte/src/lib/store/derived-connection-props.ts
index aea51c3f..f9586885 100644
--- a/packages/svelte/src/lib/store/connection-path.ts
+++ b/packages/svelte/src/lib/store/derived-connection-props.ts
@@ -1,4 +1,4 @@
-import { derived } from 'svelte/store';
+import { derived, type Writable } from 'svelte/store';
import {
getBezierPath,
getSmoothStepPath,
@@ -10,6 +10,35 @@ import {
} from '@xyflow/system';
import type { SvelteFlowStoreState } from './types';
+import type { ConnectionData } from '$lib/types';
+
+export type ConnectionProps = {
+ path: string | null;
+ sourceX: number | null;
+ sourceY: number | null;
+ sourcePosition: Position | undefined | null;
+ targetX: number | null;
+ targetY: number | null;
+ targetPosition: Position | undefined | null;
+ pointerPosition: ConnectionData['connectionPosition'] | null;
+ startHandle: ConnectionData['connectionStartHandle'] | null;
+ endHandle: ConnectionData['connectionEndHandle'] | null;
+ status: ConnectionData['connectionStatus'] | null;
+};
+
+export const initConnectionProps = {
+ path: null,
+ sourceX: null,
+ sourceY: null,
+ sourcePosition: null,
+ targetX: null,
+ targetY: null,
+ targetPosition: null,
+ pointerPosition: null,
+ startHandle: null,
+ endHandle: null,
+ status: null
+};
const oppositePosition = {
[Position.Left]: Position.Right,
@@ -18,10 +47,13 @@ const oppositePosition = {
[Position.Bottom]: Position.Top
};
-export function getConnectionPath(store: SvelteFlowStoreState) {
+export function getDerivedConnectionProps(
+ store: SvelteFlowStoreState,
+ currentConnection: Writable
+) {
return derived(
[
- store.connection,
+ currentConnection,
store.connectionLineType,
store.connectionMode,
store.nodes,
@@ -29,7 +61,7 @@ export function getConnectionPath(store: SvelteFlowStoreState) {
],
([connection, connectionLineType, connectionMode, nodes, transform]) => {
if (!connection.connectionStartHandle?.nodeId) {
- return null;
+ return initConnectionProps;
}
const fromNode = nodes.find((n) => n.id === connection.connectionStartHandle?.nodeId);
@@ -80,7 +112,14 @@ export function getConnectionPath(store: SvelteFlowStoreState) {
[path] = getStraightPath(pathParams);
}
- return path;
+ return {
+ path,
+ ...pathParams,
+ pointerPosition: connection.connectionPosition,
+ startHandle: connection.connectionStartHandle,
+ endHandle: connection.connectionEndHandle,
+ status: connection.connectionStatus
+ };
}
);
}
diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts
index 08fc8b90..18896dae 100644
--- a/packages/svelte/src/lib/store/index.ts
+++ b/packages/svelte/src/lib/store/index.ts
@@ -1,5 +1,5 @@
import { getContext, setContext } from 'svelte';
-import { derived, get } from 'svelte/store';
+import { derived, get, writable } from 'svelte/store';
import {
internalsSymbol,
createMarkerIds,
@@ -19,18 +19,13 @@ import {
} from '@xyflow/system';
import { addEdge as addEdgeUtil } from '$lib/utils';
-import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types';
-import { getConnectionPath } from './connection-path';
-import {
- initConnectionData,
- initialEdgeTypes,
- initialNodeTypes,
- getInitialStore
-} from './initial-store';
+import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions, ConnectionData } from '$lib/types';
+import { initialEdgeTypes, initialNodeTypes, getInitialStore } from './initial-store';
import type { SvelteFlowStore } from './types';
import { syncNodeStores, syncEdgeStores } from './utils';
import { getEdgeTree } from './edge-tree';
import { getVisibleNodes } from './visible-nodes';
+import { getDerivedConnectionProps } from './derived-connection-props';
export const key = Symbol();
@@ -252,25 +247,22 @@ export function createStore(): SvelteFlowStore {
});
}
- const updateConnection: UpdateConnection = (update) => {
- const currentConnectionData = get(store.connection);
+ const initConnectionUpdateData = {
+ connectionStartHandle: null,
+ connectionEndHandle: null,
+ connectionPosition: null,
+ connectionStatus: null
+ };
- const nextConnectionData = currentConnectionData
- ? {
- ...initConnectionData,
- ...currentConnectionData,
- ...update
- }
- : {
- ...initConnectionData,
- ...update
- };
-
- store.connection.set(nextConnectionData);
+ // by creating an internal, unexposed store and using a derived store
+ // we prevent using slow get() calls
+ const currentConnection = writable(initConnectionUpdateData);
+ const updateConnection: UpdateConnection = (newConnection: ConnectionData) => {
+ currentConnection.set(newConnection);
};
function cancelConnection() {
- updateConnection(initConnectionData);
+ updateConnection(initConnectionUpdateData);
}
function reset() {
@@ -292,7 +284,7 @@ export function createStore(): SvelteFlowStore {
// derived state
edgeTree: getEdgeTree(store),
- connectionPath: getConnectionPath(store),
+ connection: getDerivedConnectionProps(store, currentConnection),
visibleNodes: getVisibleNodes(store),
markers: derived(
[store.edges, store.defaultMarkerColor, store.flowId],
diff --git a/packages/svelte/src/lib/store/initial-store.ts b/packages/svelte/src/lib/store/initial-store.ts
index f3e69b9e..2740be0a 100644
--- a/packages/svelte/src/lib/store/initial-store.ts
+++ b/packages/svelte/src/lib/store/initial-store.ts
@@ -24,15 +24,9 @@ import BezierEdge from '$lib/components/edges/BezierEdge.svelte';
import StraightEdge from '$lib/components/edges/StraightEdge.svelte';
import SmoothStepEdge from '$lib/components/edges/SmoothStepEdge.svelte';
import StepEdge from '$lib/components/edges/StepEdge.svelte';
-import type { ConnectionData, NodeTypes, EdgeTypes, EdgeLayouted, Node } from '$lib/types';
+import type { NodeTypes, EdgeTypes, EdgeLayouted, Node } from '$lib/types';
import { createNodesStore, createEdgesStore } from './utils';
-
-export const initConnectionData = {
- connectionStartHandle: null,
- connectionEndHandle: null,
- connectionPosition: null,
- connectionStatus: null
-};
+import { initConnectionProps, type ConnectionProps } from './derived-connection-props';
export const initialNodeTypes = {
input: InputNode,
@@ -79,8 +73,7 @@ export const getInitialStore = () => ({
transform: writable([0, 0, 1]),
connectionMode: writable(ConnectionMode.Strict),
domNode: writable(null),
- connectionPath: readable(null),
- connection: writable(initConnectionData),
+ connection: readable(initConnectionProps),
connectionLineType: writable(ConnectionLineType.Bezier),
connectionRadius: writable(20),
isValidConnection: writable(() => true),
diff --git a/packages/system/src/types/general.ts b/packages/system/src/types/general.ts
index ba1c6e3c..d23dee9b 100644
--- a/packages/system/src/types/general.ts
+++ b/packages/system/src/types/general.ts
@@ -131,8 +131,8 @@ export type UpdateNodePositions = (
export type PanBy = (delta: XYPosition) => boolean;
export type UpdateConnection = (params: {
- connectionPosition?: XYPosition | null;
- connectionStatus?: ConnectionStatus | null;
- connectionStartHandle?: ConnectingHandle | null;
- connectionEndHandle?: ConnectingHandle | null;
+ connectionPosition: XYPosition | null;
+ connectionStatus: ConnectionStatus | null;
+ connectionStartHandle: ConnectingHandle | null;
+ connectionEndHandle: ConnectingHandle | null;
}) => void;
diff --git a/packages/system/src/xyhandle/XYHandle.ts b/packages/system/src/xyhandle/XYHandle.ts
index 732b3e60..6ec86528 100644
--- a/packages/system/src/xyhandle/XYHandle.ts
+++ b/packages/system/src/xyhandle/XYHandle.ts
@@ -66,6 +66,8 @@ const nullConnection: Connection = { source: null, target: null, sourceHandle: n
const alwaysValid = () => true;
+let connectionStartHandle: ConnectingHandle | null = null;
+
function onPointerDown(
event: MouseEvent | TouchEvent,
{
@@ -129,15 +131,18 @@ function onPointerDown(
autoPanId = requestAnimationFrame(autoPan);
}
+ // Stays the same for all consecutive pointermove events
+ connectionStartHandle = {
+ nodeId,
+ handleId,
+ type: handleType,
+ };
+
updateConnection({
connectionPosition,
connectionStatus: null,
// connectionNodeId etc will be removed in the next major in favor of connectionStartHandle
- connectionStartHandle: {
- nodeId,
- handleId,
- type: handleType,
- },
+ connectionStartHandle,
connectionEndHandle: null,
});
@@ -173,6 +178,7 @@ function onPointerDown(
isValid = result.isValid;
updateConnection({
+ connectionStartHandle,
connectionPosition:
closestHandle && isValid
? rendererPointToPoint(
@@ -220,6 +226,7 @@ function onPointerDown(
isValid = false;
connection = null;
handleDomNode = null;
+ connectionStartHandle = null;
doc.removeEventListener('mousemove', onPointerMove as EventListener);
doc.removeEventListener('mouseup', onPointerUp as EventListener);