/** * Copy slots: what each island's slots are, how long their copy may be, and * when visible copy is allowed to change. * * Two rules live here because the browser and the server must apply them * identically: * * - The fallback sets the size. Each field's fallback defines its slot, so * its length is sent with every request as that field's length budget * (`len.=`), and the server writes copy to fit. The * server read and the browser's stream compute the budget with the same * function, so they ask for, and cache, the same copy. * - Visible copy changes only on a visitor's action. A change to what an * island would show (a context or campaign change) replaces visible text * only when the visitor caused it: the interaction handler calls * `markVisitorChange()` before it updates state. Any other change waits * until the slot is off screen or the next page view. */ import type { CopyField } from "./state.js"; /** The copy fields each island has. */ export declare const ISLAND_COPY_FIELDS: Readonly>; /** Prefix of the length-budget query parameters: `len.headline=42`. */ export declare const LENGTH_PARAM_PREFIX = "len."; /** * The length of copy as a length budget counts it: Unicode code points, so * an emoji or an accented letter written as one character counts as one. */ export declare function copyLength(text: string): number; /** * The length budget per field: the length of each field's fallback, for the * fields named in `fields` whose fallback is not empty. A field without a * fallback has no slot and no budget. */ export declare function lengthBudgets(fallback: Partial> | null | undefined, fields: readonly CopyField[]): Partial>; /** Add `len.` parameters for `budgets`, in field order. */ export declare function setLengthParams(params: URLSearchParams, budgets: Partial> | null | undefined): void; /** * How long a `markVisitorChange()` call stays valid for the change it * announces: the state update it precedes renders well inside this. */ export declare const VISITOR_CHANGE_WINDOW_MS = 1000; /** * Announce that the visitor caused the next change to what islands and * fragments show — call it in the interaction handler (a click, a submit, a * choice) before the state update that changes their campaign, context or * declaration: * * ```tsx * onClick={() => { * markVisitorChange(); * setAudience("teams"); * }} * ``` * * Visible copy then changes once, with one cross-fade. Without it, a change * keeps the visible copy until the slot is off screen or the next page view. */ export declare function markVisitorChange(): void; /** Internal: the current visitor-change generation, to remember as seen. */ export declare function visitorChangeGeneration(): number; /** * Internal: has the visitor announced a change since generation `seen`, recently * enough that the change being rendered now is the one they caused? */ export declare function isVisitorChange(seen: number): boolean; //# sourceMappingURL=slots.d.ts.map