/**
 * Mock unfurl service for the LinkCard concept.
 *
 * A link preview is a LIFECYCLE, not two static layouts. The real service is
 * server-side (SSRF-guarded, oEmbed → OpenGraph → Twitter Cards → <title>,
 * cached ~24h with a stored `fetchedAt` and a manual re-unfurl affordance — see
 * note 52104 §B3). This is a promise-based fake with a configurable delay and a
 * failure toggle so the story can drive the whole lifecycle without a network.
 *
 * The data arrives on a PROGRESSIVE LADDER of three tiers, each carrying more
 * than the last:
 *   url    → just the raw URL (nothing fetched yet)
 *   basic  → favicon + title + domain
 *   full   → + description, hero image, media kind / duration
 * The card reserves the next tier's space at every tier, so climbing the ladder
 * never reflows the card.
 */
export type UnfurlTier = "url" | "basic" | "full";
export type UnfurlStatus = "resolving" | "resolved" | "stale" | "error";
/** The cumulative data shape. Fields fill in as the ladder climbs. */
export interface UnfurlData {
    /** Always present — the raw pasted URL. */
    url: string;
    /** Tier `basic` and up: a stand-in favicon colour. */
    faviconColor?: string;
    /** Tier `basic` and up: page title. */
    title?: string;
    /** Tier `basic` and up: the display domain. */
    domain?: string;
    /** Tier `full`: short description / summary. */
    description?: string;
    /** Tier `full`: hero image src (a real <img> in production). */
    heroSrc?: string;
    /** Tier `full`: hero fill colour, used when there is no hero image. */
    heroColor?: string;
    /** Tier `full`: media kind chip (Video, Article, …). */
    kind?: string;
    /** Tier `full`: duration chip for playable media. */
    duration?: string;
    /** Tier `full`: whether the media is playable (shows the cover play badge). */
    playable?: boolean;
}
/** A seed link — what the fake "server" would resolve the URL to at tier full. */
export interface MockLink {
    url: string;
    faviconColor: string;
    title: string;
    domain: string;
    description: string;
    heroColor: string;
    heroSrc?: string;
    kind: string;
    duration?: string;
    playable?: boolean;
}
export declare const MOCK_LINKS: Record<string, MockLink>;
export interface UnfurlConfig {
    /** Which seed link to resolve. */
    link: MockLink;
    /** Per-tier delay in ms (url→basic and basic→full each wait this long). */
    delayMs?: number;
    /** When true, the unfurl fails partway and lands in the error state. */
    shouldFail?: boolean;
}
export interface UnfurlController {
    status: UnfurlStatus;
    tier: UnfurlTier;
    data: UnfurlData;
    /** Epoch ms of the last successful resolve (drives the stale affordance). */
    fetchedAt: number | null;
    /** Start (or restart) the unfurl ladder from scratch. */
    start: () => void;
    /** Retry after an error — re-runs the simulation. */
    retry: () => void;
    /** Re-unfurl a resolved/stale card — re-runs the simulation. */
    reunfurl: () => void;
    /** Force the resolved card into the stale state (demo affordance). */
    markStale: () => void;
}
/**
 * Drives one link through the unfurl lifecycle. Climbs url → basic → full on a
 * timer, or lands in `error` if `shouldFail`. `retry` / `reunfurl` re-run it;
 * `markStale` moves a resolved card to the stale state so the re-unfurl
 * affordance can be shown.
 */
export declare const useUnfurl: ({ link, delayMs, shouldFail, }: UnfurlConfig) => UnfurlController;
/** Human-readable "fetched N ago" for the stale affordance. */
export declare const formatFetchedAt: (fetchedAt: number | null) => string;
//# sourceMappingURL=unfurl.d.ts.map