import { DocumentBackground, ResolvedPage } from '../../../contracts/src/index.js'; import { PageContentContext, PageDomState, PaintWorkSummary } from './page-content.js'; /** * One exact page band of the committed scaffold (numbers-only, * serializable). Structurally compatible with the host pipeline's * `PageScaffoldPage` so a host scaffold's `pages` array — including a lazy * incremental one — is passed through zero-copy. */ export type DomPainterPersistentScaffoldPage = { index: number; /** Prefix-sum offset of the page's top edge from the document top. */ topPx: number; heightPx: number; widthPx: number; /** * Physical page number for the shell's `data-page-number` stamp (page * numbering can restart per section, so it is data, never `index + 1`). * Optional: absent bands leave the stamp to content hydration — the * painter reports, it never invents. */ pageNumber?: number; }; /** * The immutable generation-scoped page scaffold. Reference identity IS the * commit identity: the host builds one scaffold object per committed layout * generation and passes the same object to every same-generation content * paint, so the painter's same-generation skip is O(1). */ export type DomPainterPersistentScaffold = { /** Layout generation that produced this scaffold (the torn-generation fence). */ generation: number; pageCount: number; /** * Uniform inter-page gap in px. The persistent surface owns the vertical * rhythm through the mount's flex `gap`, never through spacer nodes, so * `topPx` must equal the prefix sum of heights plus `gapPx` per boundary. */ gapPx: number; /** `last.topPx + last.heightPx`; `0` for an empty document. No trailing gap. */ totalHeightPx: number; /** Ascending by `index`; `index` must equal the array position. */ pages: readonly DomPainterPersistentScaffoldPage[]; }; /** * Read-only exact-packet lookup. A `ReadonlyMap` * satisfies it; so does a thin facade over a lazily-resolved page array — * the painter reads only the desired content pages, so untouched document * tails are never materialized by a paint. */ export interface DomPainterPersistentPacketSource { get(pageIndex: number): ResolvedPage | undefined; } /** * The one paginated reconcile input (plan §Target Architecture). Shells * always cover the whole scaffold; only the desired content set is bounded. */ export type DomPainterPersistentPageInput = { scaffold: DomPainterPersistentScaffold; /** Pages whose content must be hydrated (visible window + overscan). */ desiredContentPageIndices: readonly number[]; /** Interaction pins that must stay hydrated regardless of the window. */ pinnedContentPageIndices?: readonly number[]; /** * Exact resolved packets by page index, consumed only for desired content * pages. A packet stamped with a different layout epoch than * `scaffold.generation` is a torn generation and fails before DOM * mutation; so does packet page geometry that disagrees with the band. */ packetsByPageIndex: DomPainterPersistentPacketSource; sectionPageCounts?: Readonly>; documentBackground?: DocumentBackground | null; captureSnapshot?: boolean; }; /** Shell registry entry: the persistent page root and its geometry/style reuse key. */ export type PersistentShellEntry = { element: HTMLElement; shellKey: string; }; /** Bounded content state for one hydrated page. */ export type PersistentContentEntry = { state: PageDomState; versionKey: string | null; sdtLabels: ReadonlySet; }; type PersistentSurfaceIntegrity = { dirty: boolean; observer: MutationObserver | null; onInvalidated: () => void; }; /** The retained persistent-surface state the painter snapshots and restores. */ export type PersistentPageSurfaceState = { mount: HTMLElement; /** The committed scaffold; reference identity gates the O(1) skip. */ scaffold: DomPainterPersistentScaffold; shells: Map; content: Map; integrity: PersistentSurfaceIntegrity; }; /** * The narrow renderer capabilities this module consumes. The deep * fragment/decoration render call graph stays on the painter class and is * reached through the `PageContentContext` it builds. */ export interface PersistentSurfaceRenderContext { contentContext: PageContentContext; work: PaintWorkSummary; recordPageWork(kind: PersistentPageWorkKind, pageIndex: number): void; /** Read-and-consume the provider-change decorations-dirty flag. */ consumeDecorationsDirty(): boolean; /** * Signature of every non-geometry input to the shell's visual styles * (document background, page-style overrides). Folded into the shell reuse * key so a rare document-presentation change refreshes retained roots * while steady generations skip all shell attribute writes. */ shellStyleSignature: string; /** Wake the host's canonical planner when foreign DOM work corrupts page roots. */ onIntegrityInvalidated: () => void; } export type PersistentPageWorkKind = 'createdPersistentPageIndices' | 'removedPersistentPageIndices' | 'patchedContentPageIndices' | 'untouchedContentPageIndices' | 'decorationRefreshedContentPageIndices' | 'remappedContentPageIndices' | 'pmDemotedContentPageIndices' | 'hydratedContentPageIndices' | 'dehydratedContentPageIndices'; /** * Fail-closed scaffold validation: a scaffold is exact geometry or it is * nothing. The prefix-sum pin also proves the flex-gap layout reproduces the * scaffold offsets exactly, which is what lets the surface drop spacers. */ export declare function validatePersistentScaffold(scaffold: DomPainterPersistentScaffold): void; /** Resolve the validated, deduplicated, ascending desired content set. */ export declare function resolveDesiredContentPageIndices(input: DomPainterPersistentPageInput): number[]; /** * Read the live shell-plane integrity without mutating page content. The host * uses this before its zero-work skip so external child-list corruption can * never strand the camera over a missing page until some unrelated repaint. */ export declare function isPersistentPageSurfaceIntact(state: PersistentPageSurfaceState | null): boolean; export declare function disposePersistentPageSurfaceState(state: PersistentPageSurfaceState | null): void; /** * The one persistent paginated reconcile. Same-scaffold calls skip shell * work in O(1) (reference identity); scaffold identity changes rebuild the * shell registry by page index; the content window reconciles every call. */ export declare function reconcilePersistentPageSurface(ctx: PersistentSurfaceRenderContext, previous: PersistentPageSurfaceState | null, input: DomPainterPersistentPageInput, mount: HTMLElement): PersistentPageSurfaceState; /** Deep-clone the retained planes for the painter's rollback snapshot. */ export declare function clonePersistentPageSurfaceState(state: PersistentPageSurfaceState | null, clonePageState: (pageState: PageDomState) => PageDomState): PersistentPageSurfaceState | null; export {};