diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts index 2cfc3430..84b1cb77 100644 --- a/packages/react/src/hooks/useReactFlow.ts +++ b/packages/react/src/hooks/useReactFlow.ts @@ -8,6 +8,7 @@ import { isRectObject, NodeRemoveChange, nodeToRect, + withResolvers, type Rect, } from '@xyflow/system'; @@ -280,7 +281,7 @@ export function useReactFlow | undefined) => { // We either create a new Promise or reuse the existing one // Even if fitView is called multiple times in a row, we only end up with a single Promise - const fitViewResolver = store.getState().fitViewResolver ?? Promise.withResolvers(); + const fitViewResolver = store.getState().fitViewResolver ?? withResolvers(); // We schedule a fitView by setting fitViewQueued and triggering a setNodes store.setState({ fitViewQueued: true, fitViewOptions: options, fitViewResolver }); diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index efd9d957..aef78aaa 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -1,5 +1,6 @@ import { ConnectionMode, + withResolvers, type ConnectionState, type CoordinateExtent, type InternalNodeUpdate, @@ -121,7 +122,7 @@ export type ReactFlowStore | null; + fitViewResolver: ReturnType> | null; onNodesDelete?: OnNodesDelete; onEdgesDelete?: OnEdgesDelete; diff --git a/packages/svelte/src/lib/store/index.ts b/packages/svelte/src/lib/store/index.ts index 83c6c623..8f07f105 100644 --- a/packages/svelte/src/lib/store/index.ts +++ b/packages/svelte/src/lib/store/index.ts @@ -18,7 +18,8 @@ import { type UpdateConnection, type ConnectionState, type NodeOrigin, - updateAbsolutePositions + updateAbsolutePositions, + withResolvers } from '@xyflow/system'; import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types'; @@ -146,7 +147,7 @@ export function createStore({ function fitView(options?: FitViewOptions) { // We either create a new Promise or reuse the existing one // Even if fitView is called multiple times in a row, we only end up with a single Promise - const fitViewResolver = get(store.fitViewResolver) ?? Promise.withResolvers(); + const fitViewResolver = get(store.fitViewResolver) ?? withResolvers(); // We schedule a fitView by setting fitViewQueued and triggering a setNodes store.fitViewQueued.set(true); diff --git a/packages/svelte/src/lib/store/initial-store.ts b/packages/svelte/src/lib/store/initial-store.ts index 3b0064a8..3a88696d 100644 --- a/packages/svelte/src/lib/store/initial-store.ts +++ b/packages/svelte/src/lib/store/initial-store.ts @@ -25,7 +25,8 @@ import { type EdgeLookup, type ConnectionState, type ParentLookup, - getInternalNodesBounds + getInternalNodesBounds, + withResolvers } from '@xyflow/system'; import DefaultNode from '$lib/components/nodes/DefaultNode.svelte'; @@ -114,7 +115,7 @@ export const getInitialStore = ({ const fitViewQueued = writable(false); const fitViewOptions = writable(undefined); - const fitViewResolver = writable | null>(null); + const fitViewResolver = writable> | null>(null); const panZoom = writable(null); const widthStore = writable(500); const heightStore = writable(500); diff --git a/packages/svelte/src/lib/store/utils.ts b/packages/svelte/src/lib/store/utils.ts index e924d832..0fa76828 100644 --- a/packages/svelte/src/lib/store/utils.ts +++ b/packages/svelte/src/lib/store/utils.ts @@ -18,7 +18,8 @@ import { type NodeOrigin, infiniteExtent, type CoordinateExtent, - fitViewport + fitViewport, + withResolvers } from '@xyflow/system'; import type { @@ -145,7 +146,7 @@ export const createNodesStore = ( nodeExtent: CoordinateExtent = infiniteExtent, fitViewQueued: Writable, fitViewOptions: Writable, - fitViewResolver: Writable | null>, + fitViewResolver: Writable> | null>, panZoom: Writable, width: Writable, height: Writable, diff --git a/packages/system/src/utils/general.ts b/packages/system/src/utils/general.ts index 67743b5d..0e9b8d85 100644 --- a/packages/system/src/utils/general.ts +++ b/packages/system/src/utils/general.ts @@ -399,3 +399,22 @@ export function areSetsEqual(a: Set, b: Set) { return true; } + +/** + * Polyfill for Promise.withResolvers until we can use it in all browsers + * @internal + */ +export function withResolvers(): { + promise: Promise; + resolve: (value: T | PromiseLike) => void; + reject: (reason?: unknown) => void; +} { + let resolve!: (value: T | PromiseLike) => void; + let reject!: (reason?: unknown) => void; + + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +}