chore(system): add polyfill for Promise.withResolvers #5210

This commit is contained in:
moklick
2025-04-14 10:19:30 +02:00
parent f4528f5b00
commit 5412f71ae5
6 changed files with 32 additions and 8 deletions

View File

@@ -8,6 +8,7 @@ import {
isRectObject,
NodeRemoveChange,
nodeToRect,
withResolvers,
type Rect,
} from '@xyflow/system';
@@ -280,7 +281,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
fitView: async (options: FitViewOptions<NodeType> | 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<boolean>();
const fitViewResolver = store.getState().fitViewResolver ?? withResolvers<boolean>();
// We schedule a fitView by setting fitViewQueued and triggering a setNodes
store.setState({ fitViewQueued: true, fitViewOptions: options, fitViewResolver });

View File

@@ -1,5 +1,6 @@
import {
ConnectionMode,
withResolvers,
type ConnectionState,
type CoordinateExtent,
type InternalNodeUpdate,
@@ -121,7 +122,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
fitViewQueued: boolean;
fitViewOptions: FitViewOptions | undefined;
fitViewResolver: PromiseWithResolvers<boolean> | null;
fitViewResolver: ReturnType<typeof withResolvers<boolean>> | null;
onNodesDelete?: OnNodesDelete<NodeType>;
onEdgesDelete?: OnEdgesDelete<EdgeType>;

View File

@@ -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<boolean>();
const fitViewResolver = get(store.fitViewResolver) ?? withResolvers<boolean>();
// We schedule a fitView by setting fitViewQueued and triggering a setNodes
store.fitViewQueued.set(true);

View File

@@ -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<boolean>(false);
const fitViewOptions = writable<FitViewOptions | undefined>(undefined);
const fitViewResolver = writable<PromiseWithResolvers<boolean> | null>(null);
const fitViewResolver = writable<ReturnType<typeof withResolvers<boolean>> | null>(null);
const panZoom = writable<PanZoomInstance | null>(null);
const widthStore = writable<number>(500);
const heightStore = writable<number>(500);

View File

@@ -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<boolean>,
fitViewOptions: Writable<FitViewOptions | undefined>,
fitViewResolver: Writable<PromiseWithResolvers<boolean> | null>,
fitViewResolver: Writable<ReturnType<typeof withResolvers<boolean>> | null>,
panZoom: Writable<PanZoomInstance | null>,
width: Writable<number>,
height: Writable<number>,

View File

@@ -399,3 +399,22 @@ export function areSetsEqual(a: Set<string>, b: Set<string>) {
return true;
}
/**
* Polyfill for Promise.withResolvers until we can use it in all browsers
* @internal
*/
export function withResolvers<T>(): {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: unknown) => void;
} {
let resolve!: (value: T | PromiseLike<T>) => void;
let reject!: (reason?: unknown) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}