/** Final backstop: a document that never settles is serialized best-effort. */ export declare const GEOMETRY_STABILITY_TIMEOUT_MS = 3000; /** * Secondary cap once perpetual motion is being ignored: when every rect that * still moves belongs to an ignored element but structural churn (element * count, sampled identity) keeps the strict check from passing, the document * will not settle by waiting longer. */ export declare const PERPETUAL_RESIDUE_TIMEOUT_MS = 1000; /** * An element that moved on every consecutive sample pair for this long is * treated as perpetually driven even when no animation claims it. One-shot * springs settle well inside this window, so they are never reclassified — * and a mover that pauses for even one pair either settles the wait outright * or is disqualified from reclassification for good. */ export declare const PERSISTENT_MOVER_MS = 1500; /** * Floor on observed pairs before the persistent-mover rule may fire, so a * slow sampling cadence cannot classify from a handful of observations. */ export declare const PERSISTENT_MOVER_MIN_PAIRS = 10; /** How many elements a geometry sample inspects, from the top of the body. */ export declare const GEOMETRY_SAMPLE_LIMIT = 160; /** One sampled element: an opaque identity plus its rounded geometry. */ export interface GeometryElementSample { /** Stable identity across samples — in the DOM, the element itself. */ key: unknown; /** Rounded rect signature, e.g. "12,40,300,24". */ rect: string; /** * True when an effectively-infinite animation drives this element or an * ancestor, so its movement must not block convergence. */ perpetual: boolean; } /** A point-in-time view of the document's geometry. */ export interface GeometrySample { /** Total rendered element count — a structure signal beyond the sampled window. */ elementCount: number; elements: readonly GeometryElementSample[]; /** Sample timestamp from the caller's clock, in milliseconds. */ at: number; } export type GeometrySettleReason = /** Everything held still for one full sample pair — the strict criterion. */ 'stable' /** Everything held still except elements owned by perpetual motion. */ | 'stable-ignoring-perpetual' /** Ignored motion plus structural churn: settled at the lower cap. */ | 'perpetual-residue' /** The final backstop: serialized best-effort. */ | 'timeout'; export interface GeometryVerdict { settled: boolean; reason?: GeometrySettleReason; } export interface GeometryStabilityJudgeOptions { timeoutMs?: number; perpetualResidueTimeoutMs?: number; persistentMoverMs?: number; persistentMoverMinPairs?: number; } export interface GeometryStabilityJudge { /** Consumes the next sample and reports whether the wait may end. */ next(sample: GeometrySample): GeometryVerdict; } /** * Creates the convergence policy for one stability wait. The strict * criterion is unchanged from the original hash comparison: one sample pair * with identical element count, identical sampled identities in order, and * identical rects. Movement owned by perpetual animations is exempt from * the rect comparison; structure changes never are (they fall through to * the residue cap or the timeout). */ export declare function createGeometryStabilityJudge(options?: GeometryStabilityJudgeOptions): GeometryStabilityJudge; export interface AnimationEffectLike { target?: unknown; getTiming?: () => { iterations?: number; }; getComputedTiming?: () => { endTime?: unknown; }; } export interface AnimationLike { effect?: AnimationEffectLike | null; } interface RectLike { left: number; top: number; width: number; height: number; } export interface GeometryElementLike { nodeType: number; getBoundingClientRect(): RectLike; contains?(other: GeometryElementLike): boolean; } export interface GeometryDocumentLike { body?: { querySelectorAll(selectors: string): ArrayLike; } | null; getAnimations?(options?: { subtree?: boolean; }): AnimationLike[]; } /** True for an animation that will never finish on its own. */ export declare function isEffectivelyPerpetualAnimation(animation: AnimationLike): boolean; /** * Elements owned by animations that will never finish on their own. CSS * animations with an infinite iteration count and Web Animations API loops * both surface here; one-shot animations never do. */ export declare function collectPerpetualMotionRoots(doc: GeometryDocumentLike): GeometryElementLike[]; /** * Reads one geometry sample from a document: rounded rects of the first * `limit` elements, each flagged when a perpetual animation drives it or an * ancestor (a transform loop on a container moves every descendant rect). */ export declare function sampleGeometry(doc: GeometryDocumentLike, at: number, limit?: number): GeometrySample; export {};