/** * Background capture sweep planning and driving. * * A cold canvas shows placeholders wherever no frozen snapshot exists yet, and * the editor only produces snapshots for frames the designer touches. The sweep * fills the rest while the editor is idle: it plans the missing screens once, * then produces them one at a time at a priority below all user work, joining * any production a user action already started for the same screen. * * The planner is pure so ordering is testable; the driver takes injected * dependencies so it can run in tests without a browser. */ export interface SweepFrameIdentity { id: string; fingerprint?: string; } export interface SweepCandidate { pageId: string; /** Persistent recipe cache key of the screen. */ key: string; /** * Producer dedup key shared with the frame's own producer, so a user opening * a screen mid-sweep joins the in-flight production instead of restarting it. */ runtimeKey: string; /** * Shared live instance group when the screen may run on the boot pool, * null when the screen needs its own throwaway frame. */ groupKey: string | null; /** Interaction screens are never booted by the sweep; they are delegated. */ hasInteractions: boolean; /** * Screen-space distance from the viewport center. The caller encodes * "active canvas first" by giving frames on other canvases an infinite * distance, so nearby visible work is always produced before offscreen work. */ distance: number; /** Exact-artifact identity used when the screen is delegated to capture. */ frame?: SweepFrameIdentity; } export interface SweepUnit { pageId: string; key: string; runtimeKey: string; groupKey: string | null; /** Planned position. The producer priority derives from it so earlier units run first. */ index: number; } export interface PreviewSweepPlan { units: SweepUnit[]; interactionFrames: SweepFrameIdentity[]; } export interface PlanPreviewSweepOptions { /** * Screens that already have a snapshot are not swept. A warm reopen finds * every key present after prehydration, so it plans zero units. */ hasSnapshot?: (key: string) => boolean; } /** Screen-space distance from the viewport center to a frame center. */ export declare function sweepViewportDistance(frame: { x: number; y: number; width: number; height: number; }, camera: { panX: number; panY: number; zoom: number; viewportWidth: number; viewportHeight: number; }): number; /** * Orders missing screens for background production. * * Distance ascending, with members of one instance group kept contiguous at * the position of their nearest member — the editor-side mirror of "one boot, * many screens": one lease serves the whole group by switching declared state * between serializations. Interaction screens are split out for delegation. */ export declare function planPreviewSweep(candidates: readonly SweepCandidate[], options?: PlanPreviewSweepOptions): PreviewSweepPlan; export type PreviewSweepPhase = 'idle' | 'running' | 'paused' | 'done' | 'cancelled'; export interface PreviewSweepStatus { phase: PreviewSweepPhase; total: number; completed: number; failed: number; } export interface PreviewSweepLease { /** True when the pool served an already booted instance. */ reused?: boolean; /** The live document a unit serializes from. */ iframe?: HTMLIFrameElement; release(): void; /** Drops the instance behind the lease when its document can no longer be trusted. */ discard(): void; } export interface PreviewSweeperDeps { /** * Provides the live document for one unit: a pooled lease for grouped * screens, an ephemeral offscreen frame otherwise. */ leaseInstance(unit: SweepUnit): Promise; /** Produces and stores the snapshot for one unit off the leased document. */ produce(unit: SweepUnit, lease: PreviewSweepLease | null, isCancelled: () => boolean): Promise; /** Delegates interaction screens to the exact capture pipeline, one call per chunk. */ requestArtifactFrames(frames: readonly SweepFrameIdentity[]): unknown; /** Checked before each unit; a paused sweep retries on a short backoff. */ shouldPause(): boolean; now?: () => number; log?: (message: string) => void; } export interface PreviewSweeperOptions { pauseBackoffMs?: number; interactionChunkSize?: number; interactionRequestCap?: number; } export interface PreviewSweeper { /** Runs one plan to completion. A later run or cancel abandons this one. */ run(plan: PreviewSweepPlan): Promise; /** Releases the held lease and invalidates in-flight unit completions. */ cancel(): void; } export declare const SWEEP_INTERACTION_CHUNK_SIZE = 8; export declare const SWEEP_INTERACTION_REQUEST_CAP = 32; /** One editor's sweep status channel and the sweeper factory that publishes into it. */ export declare function createPreviewSweepChannel(): { getPreviewSweepStatus: () => PreviewSweepStatus; subscribePreviewSweep: (listener: () => void) => () => void; createPreviewSweeper: (deps: PreviewSweeperDeps, options?: PreviewSweeperOptions) => PreviewSweeper; }; export type PreviewSweepChannel = ReturnType;