Merge pull request #5335 from xyflow/fix/svelte-raw-store

Don't proxy objects in the store
This commit is contained in:
Moritz Klack
2025-06-16 14:29:22 +02:00
committed by GitHub
2 changed files with 31 additions and 26 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@xyflow/svelte': patch
---
Prevent proxying objects in the store
@@ -110,10 +110,10 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
// Inline classes have some performance implications but we just call it once (max twice). // Inline classes have some performance implications but we just call it once (max twice).
class SvelteFlowStore { class SvelteFlowStore {
flowId: string = $derived(signals.props.id ?? '1'); flowId: string = $derived(signals.props.id ?? '1');
domNode = $state<HTMLDivElement | null>(null); domNode = $state.raw<HTMLDivElement | null>(null);
panZoom: PanZoomInstance | null = $state(null); panZoom: PanZoomInstance | null = $state.raw(null);
width = $state<number>(signals.width ?? 0); width = $state.raw<number>(signals.width ?? 0);
height = $state<number>(signals.height ?? 0); height = $state.raw<number>(signals.height ?? 0);
nodesInitialized: boolean = $derived.by(() => { nodesInitialized: boolean = $derived.by(() => {
const nodesInitialized = adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, { const nodesInitialized = adoptUserNodes(signals.nodes, this.nodeLookup, this.parentLookup, {
@@ -293,16 +293,16 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
snapGrid: SnapGrid | null = $derived(signals.props.snapGrid ?? null); snapGrid: SnapGrid | null = $derived(signals.props.snapGrid ?? null);
dragging: boolean = $state(false); dragging: boolean = $state.raw(false);
selectionRect: SelectionRect | null = $state(null); selectionRect: SelectionRect | null = $state.raw(null);
selectionKeyPressed: boolean = $state(false); selectionKeyPressed: boolean = $state.raw(false);
multiselectionKeyPressed: boolean = $state(false); multiselectionKeyPressed: boolean = $state.raw(false);
deleteKeyPressed: boolean = $state(false); deleteKeyPressed: boolean = $state.raw(false);
panActivationKeyPressed: boolean = $state(false); panActivationKeyPressed: boolean = $state.raw(false);
zoomActivationKeyPressed: boolean = $state(false); zoomActivationKeyPressed: boolean = $state.raw(false);
selectionRectMode: string | null = $state(null); selectionRectMode: string | null = $state.raw(null);
ariaLiveMessage = $state<string>(''); ariaLiveMessage = $state.raw<string>('');
selectionMode: SelectionMode = $derived(signals.props.selectionMode ?? SelectionMode.Partial); selectionMode: SelectionMode = $derived(signals.props.selectionMode ?? SelectionMode.Partial);
nodeTypes: NodeTypes = $derived({ ...initialNodeTypes, ...signals.props.nodeTypes }); nodeTypes: NodeTypes = $derived({ ...initialNodeTypes, ...signals.props.nodeTypes });
@@ -317,7 +317,7 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
// _viewport is the internal viewport. // _viewport is the internal viewport.
// when binding to viewport, we operate on signals.viewport instead // when binding to viewport, we operate on signals.viewport instead
_viewport: Viewport = $state( _viewport: Viewport = $state.raw(
getInitialViewport( getInitialViewport(
this.nodesInitialized, this.nodesInitialized,
signals.props.fitView, signals.props.fitView,
@@ -338,21 +338,21 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
} }
// _connection is viewport independent and originating from XYHandle // _connection is viewport independent and originating from XYHandle
_connection: ConnectionState = $state(initialConnection); _connection: ConnectionState = $state.raw(initialConnection);
// We derive a viewport dependent connection here // We derive a viewport dependent connection here
connection: ConnectionState = $derived.by(() => { connection: ConnectionState = $derived.by(() => {
if (this._connection.inProgress) { if (!this._connection.inProgress) {
return {
...this._connection,
to: pointToRendererPoint(this._connection.to, [
this.viewport.x,
this.viewport.y,
this.viewport.zoom
])
};
} else {
return this._connection; return this._connection;
} }
return {
...this._connection,
to: pointToRendererPoint(this._connection.to, [
this.viewport.x,
this.viewport.y,
this.viewport.zoom
])
};
}); });
connectionMode: ConnectionMode = $derived( connectionMode: ConnectionMode = $derived(
signals.props.connectionMode ?? ConnectionMode.Strict signals.props.connectionMode ?? ConnectionMode.Strict
@@ -392,7 +392,7 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
clickConnect?: boolean = $derived(signals.props.clickConnect ?? true); clickConnect?: boolean = $derived(signals.props.clickConnect ?? true);
onclickconnectstart?: OnConnectStart = $derived(signals.props.onclickconnectstart); onclickconnectstart?: OnConnectStart = $derived(signals.props.onclickconnectstart);
onclickconnectend?: OnConnectEnd = $derived(signals.props.onclickconnectend); onclickconnectend?: OnConnectEnd = $derived(signals.props.onclickconnectend);
clickConnectStartHandle: Pick<Handle, 'id' | 'nodeId' | 'type'> | null = $state(null); clickConnectStartHandle: Pick<Handle, 'id' | 'nodeId' | 'type'> | null = $state.raw(null);
onselectiondrag?: OnSelectionDrag<NodeType> = $derived(signals.props.onselectiondrag); onselectiondrag?: OnSelectionDrag<NodeType> = $derived(signals.props.onselectiondrag);
onselectiondragstart?: OnSelectionDrag<NodeType> = $derived(signals.props.onselectiondragstart); onselectiondragstart?: OnSelectionDrag<NodeType> = $derived(signals.props.onselectiondragstart);