{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "offers-list",
  "title": "Offers List",
  "description": "Compares merchant offers for a product, cheapest first, with affiliate-tracked buy links.",
  "dependencies": [
    "@channel3/sdk",
    "lucide-react"
  ],
  "registryDependencies": [
    "badge",
    "button",
    "empty",
    "https://ui.trychannel3.com/r/format.json"
  ],
  "files": [
    {
      "path": "registry/default/components/offers-list.tsx",
      "content": "import * as React from \"react\";\nimport { ExternalLink } from \"lucide-react\";\nimport type { ProductOffer } from \"@channel3/sdk/resources\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { buttonVariants } from \"@/components/ui/button\";\nimport { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from \"@/components/ui/empty\";\nimport { formatCurrency, formatDomain, formatPrice, isInStock, isOnSale } from \"@/registry/default/lib/format\";\n\nexport interface OffersListProps extends React.ComponentProps<\"div\"> {\n  offers: ReadonlyArray<ProductOffer>;\n  onOfferClick?: (offer: ProductOffer) => void;\n  actionLabel?: string;\n  locale?: string;\n  /** `rel` for each buy link. Use `\"sponsored noopener noreferrer\"` for affiliate links. */\n  buyLinkRel?: string;\n}\n\nconst byPrice = (a: ProductOffer, b: ProductOffer) => a.price.price - b.price.price;\n\nexport function OffersList({\n  offers,\n  onOfferClick,\n  actionLabel = \"View\",\n  locale,\n  buyLinkRel = \"noopener noreferrer\",\n  className,\n  ...props\n}: OffersListProps) {\n  const { inStock, outOfStock, lead } = React.useMemo(() => {\n    const sorted = [...offers].sort(byPrice);\n    const purchasable = sorted.filter((offer) => isInStock(offer.availability));\n    const unavailable = sorted.filter((offer) => !isInStock(offer.availability));\n    return { inStock: purchasable, outOfStock: unavailable, lead: purchasable[0] ?? sorted[0] };\n  }, [offers]);\n\n  if (offers.length === 0) {\n    return (\n      <Empty className={className} {...props}>\n        <EmptyHeader>\n          <EmptyTitle>No offers</EmptyTitle>\n          <EmptyDescription>No merchants are currently listing this product.</EmptyDescription>\n        </EmptyHeader>\n      </Empty>\n    );\n  }\n\n  const renderRow = (offer: ProductOffer, index: number, dimmed: boolean) => (\n    <OfferRow\n      key={`${offer.domain}-${index}`}\n      offer={offer}\n      isLead={offer === lead}\n      dimmed={dimmed}\n      actionLabel={actionLabel}\n      locale={locale}\n      buyLinkRel={buyLinkRel}\n      onOfferClick={onOfferClick}\n    />\n  );\n\n  return (\n    <div data-slot=\"offers-list\" className={cn(\"flex flex-col gap-2\", className)} {...props}>\n      {inStock.map((offer, index) => renderRow(offer, index, false))}\n      {outOfStock.length > 0 ? (\n        <>\n          <span className=\"pt-2 text-xs font-medium text-muted-foreground\">Out of stock</span>\n          {outOfStock.map((offer, index) => renderRow(offer, index, true))}\n        </>\n      ) : null}\n    </div>\n  );\n}\n\nfunction OfferRow({\n  offer,\n  isLead,\n  dimmed,\n  actionLabel,\n  locale,\n  buyLinkRel,\n  onOfferClick,\n}: {\n  offer: ProductOffer;\n  isLead: boolean;\n  dimmed: boolean;\n  actionLabel: string;\n  locale: string | undefined;\n  buyLinkRel: string;\n  onOfferClick: ((offer: ProductOffer) => void) | undefined;\n}) {\n  return (\n    <div\n      className={cn(\n        \"flex items-center justify-between gap-3 rounded-lg border p-3\",\n        dimmed && \"opacity-60\",\n      )}\n    >\n      <div className=\"flex min-w-0 items-center gap-2\">\n        <span className=\"truncate text-sm font-medium\">{formatDomain(offer.domain)}</span>\n        {isLead ? <Badge variant=\"secondary\">Best Price</Badge> : null}\n      </div>\n\n      <div className=\"flex items-center gap-3\">\n        <div className=\"flex items-baseline gap-2\">\n          {isOnSale(offer.price) && offer.price.compare_at_price ? (\n            <span className=\"text-xs text-muted-foreground line-through\">\n              {formatCurrency(offer.price.compare_at_price, offer.price.currency, locale)}\n            </span>\n          ) : null}\n          <span className=\"text-sm font-semibold\">{formatPrice(offer.price, locale)}</span>\n        </div>\n        <a\n          href={offer.url}\n          target=\"_blank\"\n          rel={buyLinkRel}\n          onClick={() => onOfferClick?.(offer)}\n          className={cn(buttonVariants({ variant: \"outline\", size: \"sm\" }))}\n        >\n          {actionLabel}\n          <ExternalLink className=\"size-3.5\" aria-hidden />\n        </a>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}
