diff --git a/packages/svelte/src/lib/actions/drag/index.ts b/packages/svelte/src/lib/actions/drag/index.ts index 1405ccd9..f5649a29 100644 --- a/packages/svelte/src/lib/actions/drag/index.ts +++ b/packages/svelte/src/lib/actions/drag/index.ts @@ -34,7 +34,7 @@ export default function drag(domNode: Element, params: UseDragParams) { nodeExtent: get(store.nodeExtent), snapGrid: snapGrid ? snapGrid : [0, 0], snapToGrid: !!snapGrid, - nodeOrigin: [0, 0], + nodeOrigin: get(store.nodeOrigin), multiSelectionActive: get(store.multiselectionKeyPressed), domNode: get(store.domNode), transform: [vp.x, vp.y, vp.zoom], diff --git a/packages/svelte/src/lib/components/SvelteFlowProvider/SvelteFlowProvider.svelte b/packages/svelte/src/lib/components/SvelteFlowProvider/SvelteFlowProvider.svelte index b943ab0a..053373c0 100644 --- a/packages/svelte/src/lib/components/SvelteFlowProvider/SvelteFlowProvider.svelte +++ b/packages/svelte/src/lib/components/SvelteFlowProvider/SvelteFlowProvider.svelte @@ -11,12 +11,14 @@ export let initialWidth: $$Props['initialWidth'] = undefined; export let initialHeight: $$Props['initialHeight'] = undefined; export let fitView: $$Props['fitView'] = undefined; + export let nodeOrigin: $$Props['nodeOrigin'] = undefined; const store = createStore({ nodes: initialNodes, edges: initialEdges, width: initialWidth, height: initialHeight, + nodeOrigin, fitView }); diff --git a/packages/svelte/src/lib/components/SvelteFlowProvider/types.ts b/packages/svelte/src/lib/components/SvelteFlowProvider/types.ts index 769588b2..39fa5350 100644 --- a/packages/svelte/src/lib/components/SvelteFlowProvider/types.ts +++ b/packages/svelte/src/lib/components/SvelteFlowProvider/types.ts @@ -1,4 +1,5 @@ import type { Edge, Node } from '$lib/types'; +import type { NodeOrigin } from '@xyflow/system'; export type SvelteFlowProviderProps = { initialNodes?: Node[]; @@ -6,4 +7,5 @@ export type SvelteFlowProviderProps = { initialWidth?: number; initialHeight?: number; fitView?: boolean; + nodeOrigin?: NodeOrigin; }; diff --git a/packages/svelte/src/lib/container/SvelteFlow/SvelteFlow.svelte b/packages/svelte/src/lib/container/SvelteFlow/SvelteFlow.svelte index dea8549f..74709680 100644 --- a/packages/svelte/src/lib/container/SvelteFlow/SvelteFlow.svelte +++ b/packages/svelte/src/lib/container/SvelteFlow/SvelteFlow.svelte @@ -78,6 +78,7 @@ export let onconnectend: $$Props['onconnectend'] = undefined; export let onbeforedelete: $$Props['onbeforedelete'] = undefined; export let oninit: $$Props['oninit'] = undefined; + export let nodeOrigin: $$Props['nodeOrigin'] = undefined; export let defaultMarkerColor = '#b1b1b7'; @@ -93,7 +94,14 @@ const store = hasContext(key) ? useStore() - : createStoreContext({ nodes: get(nodes), edges: get(edges), width, height, fitView }); + : createStoreContext({ + nodes: get(nodes), + edges: get(edges), + width, + height, + fitView, + nodeOrigin + }); onMount(() => { store.width.set(clientWidth); @@ -168,7 +176,8 @@ onconnect, onconnectstart, onconnectend, - onbeforedelete + onbeforedelete, + nodeOrigin }; updateStoreByKeys(store, updatableProps); diff --git a/packages/svelte/src/lib/container/SvelteFlow/utils.ts b/packages/svelte/src/lib/container/SvelteFlow/utils.ts index 29e65db4..c7166b0c 100644 --- a/packages/svelte/src/lib/container/SvelteFlow/utils.ts +++ b/packages/svelte/src/lib/container/SvelteFlow/utils.ts @@ -70,6 +70,7 @@ export type UpdatableStoreProps = { onconnectstart?: UnwrapWritable; onconnectend?: UnwrapWritable; onbeforedelete?: UnwrapWritable; + nodeOrigin?: UnwrapWritable; }; export function updateStoreByKeys(store: SvelteFlowStore, keys: UpdatableStoreProps) { diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index fc8ba6b2..606475dc 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -14,7 +14,8 @@ import { type XYPosition, type CoordinateExtent, type UpdateConnection, - errorMessages + errorMessages, + type NodeOrigin } from '@xyflow/system'; import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions, ConnectionData } from '$lib/types'; @@ -32,15 +33,24 @@ export function createStore({ edges, width, height, - fitView: fitViewOnCreate + fitView: fitViewOnCreate, + nodeOrigin }: { nodes?: Node[]; edges?: Edge[]; width?: number; height?: number; fitView?: boolean; + nodeOrigin?: NodeOrigin; }): SvelteFlowStore { - const store = getInitialStore({ nodes, edges, width, height, fitView: fitViewOnCreate }); + const store = getInitialStore({ + nodes, + edges, + width, + height, + fitView: fitViewOnCreate, + nodeOrigin + }); function setNodeTypes(nodeTypes: NodeTypes) { store.nodeTypes.set({ @@ -438,15 +448,17 @@ export function createStoreContext({ edges, width, height, - fitView + fitView, + nodeOrigin }: { nodes?: Node[]; edges?: Edge[]; width?: number; height?: number; fitView?: boolean; + nodeOrigin?: NodeOrigin; }) { - const store = createStore({ nodes, edges, width, height, fitView }); + const store = createStore({ nodes, edges, width, height, fitView, nodeOrigin }); setContext(key, { getStore: () => store diff --git a/packages/svelte/src/lib/store/initial-store.ts b/packages/svelte/src/lib/store/initial-store.ts index 34d3635b..0c6435c3 100644 --- a/packages/svelte/src/lib/store/initial-store.ts +++ b/packages/svelte/src/lib/store/initial-store.ts @@ -6,7 +6,6 @@ import { ConnectionLineType, devWarn, adoptUserNodes, - getNodesBounds, getViewportForBounds, updateConnectionLookup, type SelectionRect, @@ -22,7 +21,9 @@ import { type OnConnectStart, type OnConnectEnd, type NodeLookup, - type EdgeLookup + type EdgeLookup, + type ParentLookup, + getInternalNodesBounds } from '@xyflow/system'; import DefaultNode from '$lib/components/nodes/DefaultNode.svelte'; @@ -72,18 +73,21 @@ export const getInitialStore = ({ edges = [], width, height, - fitView + fitView, + nodeOrigin }: { nodes?: Node[]; edges?: Edge[]; width?: number; height?: number; fitView?: boolean; + nodeOrigin?: NodeOrigin; }) => { const nodeLookup: NodeLookup = new Map(); const parentLookup = new Map(); + const storeNodeOrigin = nodeOrigin ?? [0, 0]; adoptUserNodes(nodes, nodeLookup, parentLookup, { - nodeOrigin: [0, 0], + nodeOrigin: storeNodeOrigin, elevateNodesOnSelect: false, checkEquality: false }); @@ -94,20 +98,17 @@ export const getInitialStore = ({ let viewport: Viewport = { x: 0, y: 0, zoom: 1 }; if (fitView && width && height) { - const nodesWithDimensions = nodes.filter( - (node) => (node.width && node.height) || (node.initialWidth && node.initialHeight) - ); - - // @todo users nodeOrigin should be used here - const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] }); + const bounds = getInternalNodesBounds(nodeLookup, { + filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)) + }); viewport = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1); } return { flowId: writable(null), - nodes: createNodesStore(nodes, nodeLookup, parentLookup), + nodes: createNodesStore(nodes, nodeLookup, parentLookup, storeNodeOrigin), nodeLookup: readable>(nodeLookup), - parentLookup: readable>>(parentLookup), + parentLookup: readable>(parentLookup), edgeLookup: readable>(edgeLookup), visibleNodes: readable([]), edges: createEdgesStore(edges, connectionLookup, edgeLookup), @@ -117,7 +118,7 @@ export const getInitialStore = ({ width: writable(500), minZoom: writable(0.5), maxZoom: writable(2), - nodeOrigin: writable([0, 0]), + nodeOrigin: writable(storeNodeOrigin), nodeDragThreshold: writable(1), nodeExtent: writable(infiniteExtent), translateExtent: writable(infiniteExtent), diff --git a/packages/svelte/src/lib/store/utils.ts b/packages/svelte/src/lib/store/utils.ts index 4eb402dc..e0b53c46 100644 --- a/packages/svelte/src/lib/store/utils.ts +++ b/packages/svelte/src/lib/store/utils.ts @@ -14,7 +14,8 @@ import { type ConnectionLookup, type EdgeLookup, type NodeLookup, - type ParentLookup + type ParentLookup, + type NodeOrigin } from '@xyflow/system'; import type { DefaultEdgeOptions, DefaultNodeOptions, Edge, InternalNode, Node } from '$lib/types'; @@ -129,7 +130,8 @@ export type NodeStoreOptions = { export const createNodesStore = ( nodes: Node[], nodeLookup: NodeLookup, - parentLookup: ParentLookup + parentLookup: ParentLookup, + nodeOrigin: NodeOrigin = [0, 0] ): { subscribe: (this: void, run: Subscriber) => Unsubscriber; update: (this: void, updater: Updater) => void; @@ -145,6 +147,7 @@ export const createNodesStore = ( const _set = (nds: Node[]): Node[] => { adoptUserNodes(nds, nodeLookup, parentLookup, { elevateNodesOnSelect, + nodeOrigin, defaults, checkEquality: false });