diff --git a/examples/svelte/package.json b/examples/svelte/package.json index 365fbbc5..0cdc4813 100644 --- a/examples/svelte/package.json +++ b/examples/svelte/package.json @@ -21,7 +21,7 @@ "eslint-plugin-svelte": "^2.46.0", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.8", - "svelte": "^5.1.15", + "svelte": "^5.1.16", "svelte-check": "^4.0.7", "tslib": "^2.8.1", "typescript": "^5.6.3", diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 89ccce66..913259ea 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -50,7 +50,7 @@ "access": "public" }, "dependencies": { - "@svelte-put/shortcut": "^3.1.0", + "@svelte-put/shortcut": "^4.0.0", "@xyflow/system": "workspace:*", "classcat": "^5.0.5" }, @@ -74,7 +74,7 @@ "postcss-rename": "^0.6.1", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.8", - "svelte": "^5.1.15", + "svelte": "^5.1.16", "svelte-check": "^4.0.7", "svelte-eslint-parser": "^0.43.0", "svelte-preprocess": "^6.0.3", diff --git a/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte b/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte index fd4090fb..acaf86c6 100644 --- a/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte +++ b/packages/svelte/src/lib/components/EdgeWrapper/EdgeWrapper.svelte @@ -1,90 +1,86 @@ - - - - + + {#if !hidden} { - onMouseEvent(e, 'edgecontextmenu'); - }} - on:mouseenter={(e) => { - onMouseEvent(e, 'edgemouseenter'); - }} - on:mouseleave={(e) => { - onMouseEvent(e, 'edgemouseleave'); - }} + {onclick} + oncontextmenu={onedgecontextmenu + ? (e) => { + onMouseEvent(e, onedgecontextmenu); + } + : undefined} + onmouseenter={onedgemouseenter + ? (e) => { + onMouseEvent(e, onedgemouseenter); + } + : undefined} + onmouseleave={onedgemouseleave + ? (e) => { + onMouseEvent(e, onedgemouseleave); + } + : undefined} aria-label={ariaLabel === null ? undefined : ariaLabel @@ -110,8 +112,7 @@ : `Edge from ${source} to ${target}`} role="img" > - - //TODO SVELTE5 import { getContext } from 'svelte'; - import type { Writable } from 'svelte/store'; import cc from 'classcat'; import { Position, @@ -15,34 +13,32 @@ import { useStore } from '$lib/store'; import type { HandleProps } from '$lib/types'; + import type { ConnectableContext } from '../NodeWrapper/types'; - type $$Props = HandleProps; - - export let id: $$Props['id'] = undefined; - export let type: $$Props['type'] = 'source'; - export let position: $$Props['position'] = Position.Top; - export let style: $$Props['style'] = undefined; - export let isValidConnection: $$Props['isValidConnection'] = undefined; - export let onconnect: $$Props['onconnect'] = undefined; - export let ondisconnect: $$Props['ondisconnect'] = undefined; + let { + id: handleId = null, + type = 'source', + position = Position.Top, + style, + class: className, + isConnectable: isConnectableProp, + isValidConnection: isValidConnectionProp, + onconnect, + ondisconnect, + children + }: HandleProps = $props(); // @todo implement connectablestart, connectableend // export let isConnectableStart: $$Props['isConnectableStart'] = undefined; // export let isConnectableEnd: $$Props['isConnectableEnd'] = undefined; - let isConnectableProp: $$Props['isConnectable'] = undefined; - export { isConnectableProp as isConnectable }; - - let className: $$Props['class'] = undefined; - export { className as class }; - - $: isTarget = type === 'target'; const nodeId = getContext('svelteflow__node_id'); - const connectable = getContext>('svelteflow__node_connectable'); - $: isConnectable = isConnectableProp !== undefined ? isConnectableProp : $connectable; + const isConnectableContext = getContext('svelteflow__node_connectable'); - $: handleId = id || null; + let isTarget = $derived(type === 'target'); + let isConnectable = $derived( + isConnectableProp !== undefined ? isConnectableProp : isConnectableContext.value + ); - const store = useStore(); const { connectionMode, domNode, @@ -64,7 +60,7 @@ onconnectend: onConnectEndAction, flowId, connection - } = store; + } = useStore(); function onPointerDown(event: MouseEvent | TouchEvent) { const isMouseTriggered = isMouseEvent(event); @@ -81,7 +77,7 @@ lib: $lib, autoPanOnConnect: $autoPanOnConnect, flowId: $flowId, - isValidConnection: isValidConnection ?? $isValidConnectionStore, + isValidConnection: isValidConnectionProp ?? $isValidConnectionStore, updateConnection, cancelConnection, panBy, @@ -112,39 +108,45 @@ } let prevConnections: Map | null = null; - let connections: Map | undefined; - - $: if (onconnect || ondisconnect) { + $effect.pre(() => { // connectionLookup is not reactive, so we use edges to get notified about updates $edges; - connections = $connectionLookup.get(`${nodeId}-${type}-${id || null}`); - } + if (onconnect || ondisconnect) { + let connections = $connectionLookup.get(`${nodeId}-${type}-${handleId}`); - $: { - if (prevConnections && !areConnectionMapsEqual(connections, prevConnections)) { - const _connections = connections ?? new Map(); + if (prevConnections && !areConnectionMapsEqual(connections, prevConnections)) { + const _connections = connections ?? new Map(); - handleConnectionChange(prevConnections, _connections, ondisconnect); - handleConnectionChange(_connections, prevConnections, onconnect); + handleConnectionChange(prevConnections, _connections, ondisconnect); + handleConnectionChange(_connections, prevConnections, onconnect); + } + + prevConnections = new Map(connections); } + }); - prevConnections = connections ?? new Map(); - } + let [connectionInProcess, connectingFrom, connectingTo, isPossibleEndHandle, valid] = $derived.by( + () => { + const { fromHandle, toHandle, isValid } = $connection; - $: connectionInProcess = !!$connection.fromHandle; - $: connectingFrom = - $connection.fromHandle?.nodeId === nodeId && - $connection.fromHandle?.type === type && - $connection.fromHandle?.id === handleId; - $: connectingTo = - $connection.toHandle?.nodeId === nodeId && - $connection.toHandle?.type === type && - $connection.toHandle?.id === handleId; - $: isPossibleEndHandle = - $connectionMode === ConnectionMode.Strict - ? $connection.fromHandle?.type !== type - : nodeId !== $connection.fromHandle?.nodeId || handleId !== $connection.fromHandle?.id; - $: valid = connectingTo && $connection.isValid; + const connectionInProcess = !!fromHandle; + + const connectingFrom = + fromHandle?.nodeId === nodeId && fromHandle?.type === type && fromHandle?.id === handleId; + + const connectingTo = + toHandle?.nodeId === nodeId && toHandle?.type === type && toHandle?.id === handleId; + + const isPossibleEndHandle = + $connectionMode === ConnectionMode.Strict + ? fromHandle?.type !== type + : nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.id; + + const valid = connectingTo && isValid; + + return [connectionInProcess, connectingFrom, connectingTo, isPossibleEndHandle, valid]; + } + );