{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "watchlist",
  "title": "Watchlist",
  "description": "Tracked-symbol list with price, change, and advancing/declining summary.",
  "dependencies": [
    "@vllnt/ui@^0.3.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/watchlist/watchlist.tsx",
      "content": "import * as React from \"react\";\n\nimport { ArrowDownRight, ArrowUpRight, Star } from \"lucide-react\";\n\nimport { formatChange } from \"@vllnt/ui\";\nimport type { HeadingTag } from \"@vllnt/ui\";\nimport { cn } from \"@vllnt/ui\";\n\nexport type WatchlistItem = {\n  change: number;\n  name?: string;\n  price: number | string;\n  starred?: boolean;\n  symbol: string;\n  volume?: string;\n};\n\nexport type WatchlistProps = {\n  /** Heading tag for the title. Defaults to `h2`. */\n  as?: HeadingTag;\n  eyebrow?: string;\n  items: WatchlistItem[];\n  title?: string;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nfunction formatPrice(price: number | string): string {\n  return typeof price === \"number\"\n    ? price.toLocaleString(undefined, {\n        maximumFractionDigits: 2,\n        minimumFractionDigits: 2,\n      })\n    : price;\n}\n\nfunction WatchlistRow({ item }: { item: WatchlistItem }): React.JSX.Element {\n  const isPositive = item.change >= 0;\n  const TrendIcon = isPositive ? ArrowUpRight : ArrowDownRight;\n\n  return (\n    <li className=\"grid grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-3 rounded-xl px-3 py-2.5 transition-colors hover:bg-muted/40\">\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          \"flex size-7 items-center justify-center rounded-full border\",\n          item.starred\n            ? \"border-amber-400/40 bg-amber-400/10 text-amber-500\"\n            : \"border-border bg-background text-muted-foreground\",\n        )}\n      >\n        <Star\n          className={cn(\"size-3.5\", item.starred && \"fill-current\")}\n          strokeWidth={1.75}\n        />\n      </span>\n      <div className=\"min-w-0\">\n        <p className=\"truncate text-sm font-semibold text-foreground\">\n          {item.symbol}\n        </p>\n        {item.name ? (\n          <p className=\"truncate text-xs text-muted-foreground\">{item.name}</p>\n        ) : null}\n      </div>\n      <div className=\"text-right\">\n        <p className=\"text-sm font-semibold tabular-nums text-foreground\">\n          {formatPrice(item.price)}\n        </p>\n        {item.volume ? (\n          <p className=\"text-[11px] text-muted-foreground tabular-nums\">\n            {item.volume}\n          </p>\n        ) : null}\n      </div>\n      <span\n        className={cn(\n          \"inline-flex items-center gap-1 rounded-full border px-2 py-1 text-xs font-medium tabular-nums\",\n          isPositive\n            ? \"border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400\"\n            : \"border-rose-500/30 bg-rose-500/10 text-rose-600 dark:text-rose-400\",\n        )}\n      >\n        <TrendIcon className=\"size-3\" />\n        {formatChange(item.change)}\n      </span>\n    </li>\n  );\n}\n\nexport const Watchlist = ({\n  as: Heading = \"h2\",\n  className,\n  eyebrow = \"Tracked symbols\",\n  items,\n  ref: reference,\n  title = \"Watchlist\",\n  ...props\n}: WatchlistProps & { ref?: React.Ref<HTMLDivElement> }) => {\n  if (items.length === 0) {\n    return null;\n  }\n\n  const advancing = items.filter((item) => item.change >= 0).length;\n  const declining = items.length - advancing;\n\n  return (\n    <section\n      aria-label={title}\n      className={cn(\n        \"rounded-2xl border border-border bg-card/80 p-4 shadow-sm\",\n        className,\n      )}\n      ref={reference}\n      {...props}\n    >\n      <header className=\"mb-3 flex flex-wrap items-start justify-between gap-3\">\n        <div>\n          <p className=\"text-xs font-medium uppercase tracking-[0.28em] text-muted-foreground\">\n            {eyebrow}\n          </p>\n          <Heading className=\"text-lg font-semibold text-foreground\">\n            {title}\n          </Heading>\n        </div>\n        <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n          <span className=\"inline-flex items-center gap-1 rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2 py-1 text-emerald-600 dark:text-emerald-400\">\n            <ArrowUpRight className=\"size-3\" />\n            {advancing} up\n          </span>\n          <span className=\"inline-flex items-center gap-1 rounded-full border border-rose-500/30 bg-rose-500/10 px-2 py-1 text-rose-600 dark:text-rose-400\">\n            <ArrowDownRight className=\"size-3\" />\n            {declining} down\n          </span>\n        </div>\n      </header>\n      <ul className=\"divide-y divide-border/60\">\n        {items.map((item) => (\n          <WatchlistRow item={item} key={item.symbol} />\n        ))}\n      </ul>\n    </section>\n  );\n};\n\nWatchlist.displayName = \"Watchlist\";\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.3.0",
  "stability": "stable"
}
