make viewport bindable

This commit is contained in:
peterkogo
2024-12-18 12:14:32 +01:00
parent 08b5f81cf5
commit 801300e895
5 changed files with 33 additions and 16 deletions
@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store';
import { import {
SvelteFlow, SvelteFlow,
Controls, Controls,
@@ -12,7 +11,7 @@
import '@xyflow/svelte/dist/style.css'; import '@xyflow/svelte/dist/style.css';
const nodes = writable([ let nodes = $state.raw([
{ {
id: 'A', id: 'A',
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
@@ -20,22 +19,20 @@
}, },
{ id: 'B', position: { x: 0, y: 100 }, data: { label: 'B' } } { id: 'B', position: { x: 0, y: 100 }, data: { label: 'B' } }
]); ]);
const edges = writable([{ id: 'ab', source: 'A', target: 'B' }]);
const viewport = writable<Viewport>({ x: 100, y: 100, zoom: 1.25 });
const { fitView } = useSvelteFlow(); let edges = $state.raw([{ id: 'ab', source: 'A', target: 'B' }]);
let viewport = $state<Viewport>({ x: 100, y: 100, zoom: 1.25 });
const { fitView } = $derived(useSvelteFlow());
const updateViewport = () => { const updateViewport = () => {
$viewport.x += 10; viewport.x += 10;
$viewport = $viewport;
}; };
viewport.subscribe((vp) => { $inspect(viewport);
console.log('viewport update', vp);
});
</script> </script>
<SvelteFlow {nodes} {edges} {viewport}> <SvelteFlow bind:nodes bind:edges bind:viewport>
<Controls /> <Controls />
<Background variant={BackgroundVariant.Dots} /> <Background variant={BackgroundVariant.Dots} />
@@ -64,6 +64,7 @@
children, children,
nodes = $bindable([]), nodes = $bindable([]),
edges = $bindable([]), edges = $bindable([]),
viewport = $bindable(undefined),
...props ...props
}: SvelteFlowProps = $props(); }: SvelteFlowProps = $props();
@@ -93,6 +94,12 @@
}, },
set edges(newEdges) { set edges(newEdges) {
edges = newEdges; edges = newEdges;
},
get viewport() {
return viewport;
},
set viewport(newViewport) {
viewport = newViewport;
} }
}); });
@@ -35,7 +35,7 @@ import type {
IsValidConnection, IsValidConnection,
DefaultNodeOptions DefaultNodeOptions
} from '$lib/types'; } from '$lib/types';
import type { Writable } from 'svelte/store';
import type { Snippet } from 'svelte'; import type { Snippet } from 'svelte';
import type { EdgeEvents, NodeEvents, NodeSelectionEvents, PaneEvents } from '$lib/types/events'; import type { EdgeEvents, NodeEvents, NodeSelectionEvents, PaneEvents } from '$lib/types/events';
@@ -168,8 +168,8 @@ export type SvelteFlowProps = NodeEvents &
* }; * };
*/ */
initialViewport?: Viewport; initialViewport?: Viewport;
/** Custom viewport writable to be used instead of internal one */ /** Custom viewport to be used instead of internal one */
viewport?: Writable<Viewport>; viewport?: Viewport;
/** The radius around a handle where you drop a connection line to create a new edge. /** The radius around a handle where you drop a connection line to create a new edge.
* @default 20 * @default 20
*/ */
@@ -102,6 +102,7 @@ export const getInitialStore = (signals: StoreSignals) => {
set edges(edges) { set edges(edges) {
signals.edges = edges; signals.edges = edges;
} }
nodeLookup: NodeLookup = new Map(); nodeLookup: NodeLookup = new Map();
parentLookup: ParentLookup = new Map(); parentLookup: ParentLookup = new Map();
connectionLookup: ConnectionLookup = new Map(); connectionLookup: ConnectionLookup = new Map();
@@ -147,7 +148,17 @@ export const getInitialStore = (signals: StoreSignals) => {
nodeTypes: NodeTypes = $derived({ ...initialNodeTypes, ...signals.props.nodeTypes }); nodeTypes: NodeTypes = $derived({ ...initialNodeTypes, ...signals.props.nodeTypes });
edgeTypes: EdgeTypes = $derived({ ...initialEdgeTypes, ...signals.props.edgeTypes }); edgeTypes: EdgeTypes = $derived({ ...initialEdgeTypes, ...signals.props.edgeTypes });
viewport: Viewport = $state(signals.props.initialViewport ?? { x: 0, y: 0, zoom: 1 }); // _viewport is the internal viewport. We either return signals.viewport or _viewport
_viewport: Viewport = $state(signals.props.initialViewport ?? { x: 0, y: 0, zoom: 1 });
get viewport() {
return signals.viewport ?? this._viewport;
}
set viewport(viewport: Viewport) {
if (signals.viewport) {
signals.viewport = viewport;
}
this._viewport = viewport;
}
connectionMode: ConnectionMode = $derived( connectionMode: ConnectionMode = $derived(
signals.props.connectionMode ?? ConnectionMode.Strict signals.props.connectionMode ?? ConnectionMode.Strict
+3 -1
View File
@@ -5,7 +5,8 @@ import type {
Connection, Connection,
UpdateNodePositions, UpdateNodePositions,
CoordinateExtent, CoordinateExtent,
UpdateConnection UpdateConnection,
Viewport
} from '@xyflow/system'; } from '@xyflow/system';
import type { getInitialStore } from './initial-store.svelte'; import type { getInitialStore } from './initial-store.svelte';
@@ -42,6 +43,7 @@ export type StoreSignals = {
height?: number; height?: number;
nodes: Node[]; nodes: Node[];
edges: Edge[]; edges: Edge[];
viewport?: Viewport;
}; };
export type SvelteFlowStoreState = ReturnType<typeof getInitialStore>; export type SvelteFlowStoreState = ReturnType<typeof getInitialStore>;