import type React from 'react'
/**
* Visual layout for a `LinkAttachment.*` card.
*
* - `featured` — full card with a 180px hero thumbnail above the body.
* The default; matches the hero-image "LinkApps" frames in Figma
* (Spotify with cover art, TikTok with a frame, etc.).
* - `classic` — compact card without a hero thumbnail. Title /
* description / URL / CTA only. Used for Link App embeds that don't
* carry artwork (and for plain link previews without OG imagery).
*
* For document / image / video / audio chat attachments, reach for
* `MessageAttachment.{Image,Video,Audio,Pdf,File}` instead — those
* render as bubbles with built-in viewers and download support and
* carry a `text` slot for accompanying captions.
*/
export type LinkAttachmentLayout = 'featured' | 'classic'
/**
* Render state of a link card. Mirrors Stream's `LinkPreviewStatus` 1:1
* (`LOADING` -> `'loading'`, `LOADED` -> `'ready'`, `FAILED` -> `'failed'`)
* so a composer can forward its preview state without inventing a parallel
* vocabulary.
*/
export type LinkAttachmentStatus = 'loading' | 'ready' | 'failed'
/**
* Shared props for the three `LinkAttachment.*` variants (Composer, Sent,
* Received). Maps to the "Attachments" + "LinkApps" sections of the messaging
* design system in Figma — a 290px-wide, 250px-tall card whose hero thumbnail
* absorbs whatever height the chin doesn't use, a title (optionally prefixed
* with a brand badge for Link Apps), a description, and either a URL footer
* or a CTA button.
*/
export interface LinkAttachmentBaseProps {
title?: string
/** Placeholder shown in the title slot before one is configured (dark variants only). */
placeholderTitle?: string
/** Secondary description rendered below the title. */
description?: string
/**
* Max lines the description renders before truncating with an ellipsis.
* Defaults to `1` (single-line truncate — the link-preview default). Set
* higher for cards whose body is prose (e.g. official messages) so it wraps
* across multiple lines like the mobile card.
*/
descriptionLines?: number
/**
* Optional URL displayed at the bottom of the card (e.g. `tr.ee/briemix`).
* Ignored when `cta` is provided. Also used as the navigation target for
* the Received card when no `cta` is set.
*/
url?: string
/** MIME type of the hero thumbnail — drives the type icon for empty states. */
mimeType?: string
/** Hero thumbnail shown above the title block; fills the card above the chin. */
thumbnailUrl?: string
/**
* Source URL for playable media in the hero region. When provided
* alongside a video / audio `mimeType`, the hero renders an inline
* native player (used by media-rich link previews that embed a
* preview clip). For chat document / file attachments, reach for
* `MessageAttachment.{Pdf,File}` instead.
*/
sourceUrl?: string
/**
* Visual layout — `'featured'` keeps the 180px hero thumbnail above the
* body, `'classic'` drops the hero entirely for a compact text-only
* card. Defaults to `'featured'`.
*/
layout?: LinkAttachmentLayout
/**
* Optional 16x16 brand badge rendered before the title (used by Link Apps:
* Spotify, TikTok, FAQ, Form, etc.). Consumers render whatever they want
* — typically a colored 4px-rounded square containing a glyph or ``.
*/
appIcon?: React.ReactNode
/**
* Optional call-to-action rendered below the description. When set,
* replaces the URL footer (e.g. FAQ "View FAQs", Form "Complete form").
*/
cta?: LinkAttachmentCta
/**
* Dominant colour extracted from `thumbnailUrl`, as a hex string
* (`#RRGGBB` or `#RGB`). Paints the card and — when the card is the last
* bubble in a same-author run — its tail. Its hue is kept while the lightness
* is swapped to a fixed per-side stop (`oklch(from …)` in `styles.css`); the
* stops clear WCAG AA at every hue by construction, so callers never pass a
* text colour.
*
* Only painted while the hero image it was extracted from is actually on
* screen. Omitted, unparseable, `layout: 'classic'`, no `thumbnailUrl`,
* `status` other than `'ready'`, a playable-audio `mimeType` + `sourceUrl`
* (whose hero is the native player rather than an image), or a hero that fails
* to load => the card keeps the plain bubble fill. Browsers without
* relative-colour-syntax support also keep that fill (progressive enhancement).
*/
accentColor?: string
/**
* Render state. `'loading'` shows a neutral pulsing hero plus two skeleton
* text bars and ignores `accentColor` (there is no image yet). `'failed'`
* renders the fallback chin with whatever text is available. Defaults to
* `'ready'`.
*
* `'loading'` outranks the hero shape that `mimeType` + `sourceUrl` would
* otherwise select: a card mid-scrape does not yet know what the asset is, so
* it renders the skeleton rather than a live `