import type { PPTChartElement, PPTImageElement, PPTMermaidElement, PPTShapeElement, PPTTableElement, PPTTextElement, Slide } from '../../types/slides'; import { type FikaStylePreset } from './styles'; import type { CompositionAnchor } from './composition'; /** * Un-normalized element inputs the builder emits. Typed as a discriminated * union of per-type partials so the engine's required fields are still checked, * while letting the bridge's `normalizeElement` fill ids/defaults on insert. */ export type FikaLayoutElementInput = (Partial & { type: 'text'; }) | (Partial & { type: 'shape'; }) | (Partial & { type: 'image'; }) | (Partial & { type: 'chart'; }) | (Partial & { type: 'table'; }) | (Partial & { type: 'mermaid'; }); export type FikaLayoutBackgroundMode = 'auto' | 'feature' | 'plain'; export interface FikaLayoutSlotDef { name: string; /** Coarse shape of the value the agent should pass for this slot. */ type: 'text' | 'bullets' | 'image' | 'chart' | 'stats' | 'rows' | 'cards' | 'steps' | 'diagram'; required: boolean; description: string; } /** * One visual variant of a layout family. Variants of the same family accept * the same slots but compose them differently (different anchor, background * treatment, and motif placement), so a deck built from one style still varies * slide-to-slide. `anchor` declares the variant's spatial center of gravity so * the composition sequencer can plan a non-repeating rhythm. */ export interface FikaLayoutVariant { id: string; label: string; /** Spatial center of gravity of this variant. */ anchor: CompositionAnchor; /** What it looks like / when to pick it over the family's other variants. */ summary: string; } export interface FikaLayout { id: string; label: string; /** One-line catalog description of the composition (what it looks like). */ summary: string; /** When to reach for it. */ bestFor: string; /** Whether it defaults to a feature (dark) background. */ feature: boolean; slots: FikaLayoutSlotDef[]; /** The visual variants this family can build. The first is the default. */ variants: FikaLayoutVariant[]; } /** Strip one or more leading bullet/number markers from a list item. */ export declare function stripLeadingListMarkers(raw: string): string; type Slots = Record; /** Natural (intrinsic) pixel size of a bitmap, when the host or the probe knows it. */ export interface ImageNaturalSize { width: number; height: number; } /** * Place a bitmap into a layout box WITHOUT distorting it. * * - `contain` (diagrams, screenshots): shrink the box to the image's aspect * and center it inside the original box. * - `cover` (photos): keep the box and center-crop the overflowing axis via * `clip.range` (percentages of the source image). * * When the natural size is unknown the box is used as-is; `fixedRatio` then * stays `false` because the box aspect is not the image's. */ export declare function imageElement(opts: { left: number; top: number; width: number; height: number; src: string; sourceUrl?: string; natural?: ImageNaturalSize; fit?: 'cover' | 'contain'; }): Partial & { type: 'image'; }; /** * Best-effort natural size of a bitmap. Browser only; resolves `undefined` * on error or after `timeoutMs` so a slow CDN never blocks slide creation. */ export declare function probeImageNaturalSize(src: string, timeoutMs?: number): Promise; export declare const PPTX_LAYOUTS: FikaLayout[]; export declare function listLayouts(): FikaLayout[]; /** * Whether a layout's job is to carry body content (bullets/columns/rows/cards/ * steps/stats/chart) beyond a title. Title/section/closing/quote/imageFull are * legitimately sparse; content layouts are not. Drives the QA `contentEmpty` * check that blocks a title-only slide (the "empty slide 3" bug). */ export declare function layoutExpectsBody(layoutId: string): boolean; /** Resolve a variant for a layout, warning (via return) on an unknown id. */ export declare function resolveLayoutVariant(layout: FikaLayout, variantId?: string): { variant: FikaLayoutVariant; unknownRequested: boolean; }; export interface FikaLayoutBuildResult { slide: Partial; warnings: string[]; /** The variant actually built (id + anchor), so the caller can record it. */ variantId: string; anchor: CompositionAnchor; } export interface SlotNormalization { slots: Slots; warnings: string[]; } /** * Validate + normalize the slots handed to a layout. Layers of defense against * the "silent content drop" bug class: * 1. ALIASES — map natural guessed names (leftColumn, columns, …) to canonical. * 2. COERCION — reshape near-miss values (rows from objects, bullets from array). * 3. IMAGE NEST — top-level sourceUrl/href next to an image slot becomes * `image: { src, sourceUrl }` (self-heal; soft advisory). * 4. VALIDATION — any key that still isn't a real slot becomes a loud warning * with a fuzzy "did you mean X?" suggestion instead of being ignored. * The slot definition list (`layout.slots`) is the single source of truth for * what a layout consumes. */ export declare function normalizeLayoutSlots(layout: FikaLayout, rawSlots: Slots): SlotNormalization; /** * Build a themed slide from a layout id + content slots. Pure and deterministic: * returns a `Partial` (background + un-normalized elements) plus any * non-fatal warnings (e.g. a missing optional image). Text is auto-fit to each * box via pretext, so content never overflows. Throws on missing required slots * or an unknown layout. * * `variantId` selects the visual variant (from the layout's `variants` in the * catalog); an unknown id falls back to the default variant with a warning. * * Async because slots may carry inline math; KaTeX is lazy-loaded up front (only * when math is present) so the otherwise-synchronous builders can render it. */ export declare function buildLayoutSlide(layoutId: string, slots: Slots, preset: FikaStylePreset, viewport: { width: number; height: number; }, backgroundMode?: FikaLayoutBackgroundMode, variantId?: string): Promise; export {};