/** * Live application instances the frames of one editor share to produce * screen previews. * * A frame that has no frozen snapshot yet has to run the real application once. * Doing that per frame means one boot per screen, which is what made opening a * catalog feel like waiting for a build. A screen whose state is declared does * not need its own boot: the instance is already running, so the state is * switched and the next snapshot is taken from the same document. * * A lease is exclusive. Snapshot production reads the document while it freezes, * so two frames must never drive one instance at the same time. * * Every editor runtime owns one pool, `runtime.schedulers.livePreviews`, so two * editors on one page never queue behind each other's screens. React * components reach it through `useEditorRuntime()`; other code takes it as a * parameter. */ export interface LivePreviewInstanceOptions { /** Creates the offscreen frame. Injected so the pool can be tested without a browser. */ createIframe?: () => HTMLIFrameElement; /** Where offscreen instances live. Defaults to the document body. */ resolveContainer?: () => HTMLElement | null; /** Upper bound on booted instances. Groups beyond it fall back to their own frame. */ maximumInstances?: number; } export interface LivePreviewLease { iframe: HTMLIFrameElement; /** False on the boot that created the instance, true when an existing one was reused. */ reused: boolean; release(): void; } export declare const LIVE_PREVIEW_INSTANCE_LIMIT = 4; /** * Names the group of screens that one running instance can serve. * * Screens agree on a group only when the application would boot identically: * same origin, same route, same pre-mount environment, same viewport. Anything * else is a different application state before the first render, and switching * state cannot reach it. */ export declare function livePreviewInstanceKey(input: { origin: string; route: string; environment?: Record | null; width: number; height: number; }): string; /** * Reports whether a screen may be previewed on a shared running instance. * * Three things disqualify a screen. It has no declared group, so the host never * promised the declaration is the whole state. It replays interactions, and only * the screen knows how to undo what a click opened. Or it is the frame the * designer is looking at, which is shown rather than only read, and imports its * layers from the running document. */ export declare function canShareLivePreviewInstance(page: { session?: string; route?: string | null; interactions?: readonly unknown[]; layersImported?: boolean; }, options?: { detailActive?: boolean; }): boolean; export declare function createLivePreviewInstances(options?: LivePreviewInstanceOptions): { lease: (input: { key: string; url: string; width: number; height: number; }) => Promise; /** * Boots an instance for a group without keeping the lease. * * Warming pays the boot before any screen asks for it, so the first real * lease of the group reuses a running document instead of waiting on a * load. A warmed instance is an ordinary pool member afterwards: leases, * discards, and failure handling treat it exactly like one that a frame * booted itself. * * Returns true only when this call booted a new instance. Warming is * best-effort and never throws — a failed boot is discarded through the * lease path and reported as false. */ warm(input: { key: string; url: string; width: number; height: number; }): Promise; /** Drops an instance whose document can no longer be trusted. */ discard(key: string): void; size(): number; /** * Releases every instance: the offscreen frames are removed and waiting * leases are resumed. The pool stays usable — the next lease boots fresh — * which is what a change of origin or revision needs, since every booted * document would otherwise keep showing old code. */ dispose(): void; }; export type LivePreviewInstances = ReturnType;