/** One offer; `code` adds a copy button. */ export interface Offer { /** Stable React key; `bestOfferId` is matched against it. */ id: string; /** Bold headline; also names the best offer in the collapsed summary. */ title: string; /** Muted description under the title; a single offer's summary reads `title · detail`. */ detail: string; /** Coupon code shown as a chip with a copy button; omit for offers that need no code. */ code?: string; } /** Every string the list renders; override all of them for another language. */ export interface OffersListLabels { /** Collapsed summary, given the offer count and the best offer's title. */ summary: (count: number, best: string) => string; /** Collapsed summary used when the best offer has an empty title. */ summaryCount: (count: number) => string; /** Copy button text before a copy. */ copy: string; /** Copy button text for about 1.6 s after a copy. */ copied: string; /** Accessible name of a copy button, given the code. */ copyCode: (code: string) => string; /** Screen-reader announcement after a copy, given the code. */ copiedMessage: (code: string) => string; } /** One collapsed row ("Offers (3) · Best: ...") that opens into the full list with copy-code buttons; renders nothing for no offers. */ export interface OffersListProps { /** Offers to list; nothing renders when empty. */ offers: Offer[]; /** Offer named in the collapsed summary; defaults to the first. */ bestOfferId?: string; /** Controlled open state; pair with `onOpenChange`. */ isOpen?: boolean; /** Initial open state when uncontrolled; collapsed by default. */ defaultOpen?: boolean; /** Fires with the next open state on every toggle, controlled or not. */ onOpenChange?: (open: boolean) => void; /** Fires after a code is copied, with the offer. */ onCopy?: (offer: Offer) => void; /** Partial overrides of the default English strings. */ labels?: Partial; /** Test id on the outer container. */ "data-testid"?: string; }