import type { FontFaceDescriptor, FontFaceLoadResult, FontFaceRequest, FontLoadResult, FontLoadStatus, RegisteredFace, RequiredFace } from './types.js';
/**
 * Default per-font budget the gate waits before treating a face as `timed_out`
 * and proceeding with a fallback. Generous enough for a cold cache on a slow
 * connection, short enough that a missing font never blocks first paint forever.
 */
export declare const DEFAULT_FONT_LOAD_TIMEOUT_MS = 3000;
/**
 * Structural slice of the CSS Font Loading API (`FontFaceSet`) the registry
 * depends on. Declared as an interface (not the DOM type) so the registry is
 * unit-testable with a fake and degrades cleanly where there is no DOM.
 */
export interface FontSetLike {
    add(face: FontFaceLike): void;
    load(font: string, text?: string): Promise<FontFaceLike[]>;
    check(font: string, text?: string): boolean;
}
/** Structural slice of a `FontFace`. */
export interface FontFaceLike {
    readonly family: string;
    load(): Promise<FontFaceLike>;
    readonly status?: string;
}
/** Structural slice of the global `FontFace` constructor. */
export type FontFaceCtor = new (family: string, source: string | ArrayBuffer | ArrayBufferView, descriptors?: FontFaceDescriptors) => FontFaceLike;
export interface FontRegistryOptions {
    /** The font set to drive. Defaults to the ambient `document.fonts`. */
    fontSet?: FontSetLike | null;
    /** Constructor for new managed faces. Defaults to the global `FontFace`. */
    FontFaceCtor?: FontFaceCtor | null;
    /** Font size used in probe strings. Only affects the `font` shorthand syntax. */
    probeSize?: string;
    /** Timer hooks, injectable for deterministic tests. Default to the globals. */
    scheduleTimeout?: (cb: () => void, ms: number) => unknown;
    cancelTimeout?: (handle: unknown) => void;
}
/**
 * Runtime registry of font faces and their load state.
 *
 * Two jobs:
 *  1. **Register** managed faces (bundled substitutes, customer BYO fonts) so the
 *     browser knows how to load them. Registration is lazy - it adds the face to
 *     the set but does not download until something awaits it.
 *  2. **Await** the specific faces a layout pass needs, with a per-font timeout,
 *     reporting `loaded | failed | timed_out | fallback_used`. This is the
 *     contract the load-before-measure gate consumes; it works for *any* family
 *     in the set, whether the registry created the face (managed) or it was
 *     injected elsewhere (embedded `@font-face`, a system font).
 *
 * The registry intentionally does not subscribe to font-loading events or touch
 * measurement caches - those belong to the gate, which owns the editor lifecycle.
 */
export declare class FontRegistry {
    #private;
    constructor(options?: FontRegistryOptions);
    /**
     * Register a managed face. Adds it to the font set so the browser can load it
     * on demand, but does not download yet. Safe to call where there is no DOM /
     * constructor: the family is recorded as `unloaded` and will resolve to
     * `fallback_used` when awaited.
     */
    register(descriptor: FontFaceDescriptor): RegisteredFace;
    /** True if this registry created a managed face for the family. */
    isManaged(family: string): boolean;
    /**
     * Last known status for a family, rolled up from its faces (and any legacy family-path
     * load). Used by declared-font diagnostics (`buildFontReport`).
     *
     * A FAILED/TIMED_OUT/FALLBACK_USED face surfaces OVER a loaded sibling: if a document
     * uses Arial regular (Liberation Sans loads) and Arial bold (its face 404s), the family
     * reports the failure (`missing: true`), not a misleadingly-clean `loaded`. This is sound
     * because the gate only awaits USED faces - an unused face stays `unloaded` (lowest
     * priority), so a declared-but-unused family stays `unloaded` (not settled => not missing)
     * and a used-but-failed face is never masked. Per-face detail is in `getFaceStatus` and
     * the load summary's per-face counts.
     */
    getStatus(family: string): FontLoadStatus;
    /**
     * Synchronous availability check: is a real face for this family loaded and
     * usable in the set *right now*? Used by the gate's late-load handler to detect
     * a face that finished after the first measure. Returns false where there is no
     * font set.
     */
    isAvailable(family: string): boolean;
    /**
     * Await one family with a per-font timeout. Concurrent calls for the same
     * family share the in-flight probe. A family already known to be `loaded`
     * resolves immediately.
     */
    awaitFace(family: string, timeoutMs?: number): Promise<FontLoadResult>;
    /**
     * Await many families. The result preserves input order after de-duplication.
     * This is the gate's primary entry point before a measurement pass.
     */
    awaitFaces(families: Iterable<string>, options?: {
        timeoutMs?: number;
    }): Promise<FontLoadResult[]>;
    /**
     * Required families as `{ family, status, ready }` handles. Reading `status` is
     * synchronous; `ready` settles when the load resolves. Calling this starts the
     * loads (idempotently).
     */
    getRequiredFaces(families: Iterable<string>, timeoutMs?: number): RequiredFace[];
    /** Snapshot of every family the registry has seen and its status (diagnostics). */
    getStates(): RegisteredFace[];
    /** Last known status for a specific face (`unloaded` if never seen). */
    getFaceStatus(request: FontFaceRequest): FontLoadStatus;
    /**
     * Await one specific face (family + weight + style) with a per-font timeout. Uses a
     * weight/style-specific probe (`italic 700 16px "Carlito"`), so unlike {@link awaitFace}
     * it loads the EXACT face the run needs, not just the regular one. Concurrent awaits of
     * the same face share one probe; an already-`loaded` face resolves immediately.
     */
    awaitFaceRequest(request: FontFaceRequest, timeoutMs?: number): Promise<FontFaceLoadResult>;
    /** Await many faces; result preserves input order after de-duplication by face key. */
    awaitFaceRequests(requests: Iterable<FontFaceRequest>, options?: {
        timeoutMs?: number;
    }): Promise<FontFaceLoadResult[]>;
}
/**
 * The single registry bound to a given font set. There is exactly one registry
 * per `FontFaceSet`, so a document's load gate, its bundled faces, and the public
 * `superdoc.fonts.*` surface all share load state.
 *
 * Callers MUST pass the same font set they watch for load events. A consumer that
 * awaits one set but listens to another would never observe its fonts arriving -
 * the exact failure mode for an editor inside an iframe whose `document.fonts`
 * differs from the top window's. Pass `null` (no DOM) to get a shared DOM-less
 * registry whose every await resolves to `fallback_used`.
 */
export declare function getFontRegistryFor(fontSet: FontSetLike | null, FontFaceCtor: FontFaceCtor | null): FontRegistry;
/**
 * The registry for the ambient `document.fonts`. Convenience for the common
 * single-document case; iframe/embedded callers should use {@link getFontRegistryFor}
 * with their own document's font set so the registry and the watched set match.
 */
export declare function getDefaultFontRegistry(): FontRegistry;
/** Reset the cached DOM-less registry. Test-only; not part of the public surface. */
export declare function __resetDefaultFontRegistry(): void;
