{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "polar-revenue-card",
  "title": "Polar Revenue Card",
  "description": "MRR/ARR metric card with trend sparkline and percentage change indicator.",
  "dependencies": [
    "@polar-sh/sdk"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/blocks/polar/polar-revenue-card/components/elements/polar-revenue-card.tsx",
      "content": "\"use client\";\n\nimport { useMemo } from \"react\";\n\nfunction cn(...classes: (string | boolean | undefined)[]) {\n  return classes.filter(Boolean).join(\" \");\n}\n\nexport interface PolarRevenueCardProps {\n  title?: string;\n  value: number;\n  previousValue?: number;\n  currency?: string;\n  interval?: \"mrr\" | \"arr\" | \"total\";\n  trend?: number[];\n  showChange?: boolean;\n  size?: \"sm\" | \"md\" | \"lg\";\n  className?: string;\n}\n\nfunction TrendingUpIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      className={className}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"16\"\n      height=\"16\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n    >\n      <polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\" />\n      <polyline points=\"16 7 22 7 22 13\" />\n    </svg>\n  );\n}\n\nfunction TrendingDownIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      className={className}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"16\"\n      height=\"16\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n    >\n      <polyline points=\"22 17 13.5 8.5 8.5 13.5 2 7\" />\n      <polyline points=\"16 17 22 17 22 11\" />\n    </svg>\n  );\n}\n\nfunction Sparkline({ data, className }: { data: number[]; className?: string }) {\n  if (!data || data.length < 2) return null;\n\n  const min = Math.min(...data);\n  const max = Math.max(...data);\n  const range = max - min || 1;\n\n  const height = 32;\n  const width = 80;\n  const padding = 2;\n\n  const points = data.map((value, index) => {\n    const x = padding + (index / (data.length - 1)) * (width - padding * 2);\n    const y = height - padding - ((value - min) / range) * (height - padding * 2);\n    return `${x},${y}`;\n  });\n\n  const isPositive = data[data.length - 1] >= data[0];\n\n  return (\n    <svg\n      className={className}\n      viewBox={`0 0 ${width} ${height}`}\n      fill=\"none\"\n      preserveAspectRatio=\"none\"\n    >\n      <polyline\n        points={points.join(\" \")}\n        fill=\"none\"\n        stroke={isPositive ? \"#22c55e\" : \"#ef4444\"}\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </svg>\n  );\n}\n\nconst SIZE_CLASSES = {\n  sm: {\n    container: \"p-3\",\n    title: \"text-xs\",\n    value: \"text-xl\",\n    change: \"text-xs\",\n    sparkline: \"h-6 w-16\",\n  },\n  md: {\n    container: \"p-4\",\n    title: \"text-sm\",\n    value: \"text-2xl\",\n    change: \"text-sm\",\n    sparkline: \"h-8 w-20\",\n  },\n  lg: {\n    container: \"p-5\",\n    title: \"text-base\",\n    value: \"text-3xl\",\n    change: \"text-base\",\n    sparkline: \"h-10 w-24\",\n  },\n};\n\nconst INTERVAL_LABELS = {\n  mrr: \"MRR\",\n  arr: \"ARR\",\n  total: \"Total Revenue\",\n};\n\nexport function PolarRevenueCard({\n  title,\n  value,\n  previousValue,\n  currency = \"$\",\n  interval = \"mrr\",\n  trend,\n  showChange = true,\n  size = \"md\",\n  className,\n}: PolarRevenueCardProps) {\n  const sizes = SIZE_CLASSES[size];\n\n  const formatValue = (val: number) => {\n    if (val >= 1000000) {\n      return `${currency}${(val / 1000000).toFixed(1)}M`;\n    }\n    if (val >= 1000) {\n      return `${currency}${(val / 1000).toFixed(1)}K`;\n    }\n    return `${currency}${val.toLocaleString()}`;\n  };\n\n  const changePercent = useMemo(() => {\n    if (!previousValue || previousValue === 0) return null;\n    return ((value - previousValue) / previousValue) * 100;\n  }, [value, previousValue]);\n\n  const isPositive = changePercent !== null && changePercent >= 0;\n\n  return (\n    <div\n      data-slot=\"polar-revenue-card\"\n      className={cn(\n        \"rounded-xl border border-border bg-card\",\n        sizes.container,\n        className\n      )}\n    >\n      <div className=\"flex items-start justify-between\">\n        <div data-slot=\"content\" className=\"flex-1\">\n          <p\n            data-slot=\"title\"\n            className={cn(\"font-medium text-muted-foreground\", sizes.title)}\n          >\n            {title || INTERVAL_LABELS[interval]}\n          </p>\n          <p\n            data-slot=\"value\"\n            className={cn(\"font-bold text-foreground mt-1\", sizes.value)}\n          >\n            {formatValue(value)}\n          </p>\n          {showChange && changePercent !== null && (\n            <div\n              data-slot=\"change\"\n              className={cn(\n                \"flex items-center gap-1 mt-1\",\n                sizes.change,\n                isPositive ? \"text-green-600 dark:text-green-400\" : \"text-red-600 dark:text-red-400\"\n              )}\n            >\n              {isPositive ? (\n                <TrendingUpIcon className=\"h-3.5 w-3.5\" />\n              ) : (\n                <TrendingDownIcon className=\"h-3.5 w-3.5\" />\n              )}\n              <span>\n                {isPositive ? \"+\" : \"\"}\n                {changePercent.toFixed(1)}%\n              </span>\n              <span className=\"text-muted-foreground\">vs last period</span>\n            </div>\n          )}\n        </div>\n        {trend && trend.length > 1 && (\n          <div data-slot=\"sparkline\" className={sizes.sparkline}>\n            <Sparkline data={trend} className=\"h-full w-full\" />\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "docs": "Display revenue metrics with SVG sparkline trends. Shows MRR, ARR, or custom metrics with automatic value formatting.",
  "categories": [
    "polar"
  ],
  "type": "registry:block"
}