UNPKG

@activecollab/components

Version:

ActiveCollab Components

89 lines 3.72 kB
/** * 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