/** * Composition anchors + a deterministic deck-level composition sequencer. * * An "anchor" is the spatial center of gravity of a slide — where the eye is * pulled. Layout variants each declare an anchor; the sequencer plans a * non-repeating, rhythmic anchor sequence for a whole deck so consecutive * slides never share the same spatial approach (the #1 cause of the "samey" * look). It also designates exactly one "loud" slide (full-bleed / high * intensity) so the deck has a single visual climax rather than a flat line. * * The sequencer is pure and deterministic: given a slide count, per-slide * content hints, and the active style, it returns an ordered plan the agent * follows slide-by-slide. Nothing here touches the store. */ /** Spatial center of gravity for a slide's composition. */ export type CompositionAnchor = 'centered' | 'leftHeavy' | 'rightHeavy' | 'edgeAligned' | 'split' | 'fullBleed'; /** Coarse content density, used to alternate busy and quiet slides. */ export type CompositionDensity = 'sparse' | 'balanced' | 'dense'; /** A per-slide composition assignment returned by the sequencer. */ export interface CompositionPlanEntry { /** * Slide number. The agentic API returns this 1-based (first slide = 1). * Internally the sequencer still stores 0-based positions and converts on the way out. */ index: number; /** The anchor to build this slide around. */ anchor: CompositionAnchor; /** Target density — keep dense slides apart. */ density: CompositionDensity; /** True for the single high-intensity "loud" slide of the deck. */ loud: boolean; /** One-line rationale the agent can read aloud / log. */ note: string; } /** Optional per-slide hint the caller can pass to bias the plan. */ export interface CompositionSlideHint { /** Suggested anchor (e.g. the caller knows this slide is a full-bleed hero). */ anchor?: CompositionAnchor; /** True to force this to be the loud slide. */ loud?: boolean; /** Hint at density so the sequencer can space out busy slides. */ density?: CompositionDensity; } /** The full composition plan for a deck. */ export interface CompositionPlan { /** Ordered per-slide assignments (length = slideCount). */ slides: CompositionPlanEntry[]; /** 1-based slide number of the loud slide when returned over the API, or -1 when none. */ loudIndex: number; /** The style id this plan was sequenced for (affects anchor preference). */ styleId: string; /** Human-readable rhythm summary (e.g. "centered → leftHeavy → split → …"). */ rhythm: string; } /** * Sequence a non-repeating composition plan for `slideCount` slides. * * Guarantees: * - No two consecutive slides share the same anchor. * - Dense slides are spaced out (never two dense anchors back to back). * - Exactly one loud slide (fullBleed) when the deck has ≥ 4 slides. * - Slide 0 is never loud; the final slide is quiet (centered/edgeAligned). * * Caller hints bias specific positions but never break the no-repeat rule — * a hinted anchor that would repeat its neighbour is nudged to the next * contrasting anchor in the style's bias order. Multiple `loud: true` hints * collapse to the first valid middle index. */ export declare function sequenceComposition(slideCount: number, styleId: string, hints?: CompositionSlideHint[]): CompositionPlan; /** List the anchors a layout family supports, used to match a plan to a variant. */ export declare function anchorsCompatible(preferred: CompositionAnchor, supported: CompositionAnchor[]): boolean; export interface NearestAnchorPick { anchor: CompositionAnchor; /** Exact match vs nearest-neighbor fallback. */ exact: boolean; } /** * Pick the best available anchor from `supported` for a planned `preferred`. * Returns null when the family cannot approximate at all (e.g. fullBleed-only * request on a family with no fullBleed). */ export declare function pickNearestAnchor(preferred: CompositionAnchor, supported: CompositionAnchor[]): NearestAnchorPick | null; /** Convert an internal 0-based plan to the 1-based numbers agents send and receive. */ export declare function toApiCompositionPlan(plan: CompositionPlan): CompositionPlan;