{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "stats-band-sparklines",
  "title": "Stats — Band with Sparklines",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/stats-band-sparklines/stats-band-sparklines.component.ts",
      "content": "// Metric band pairing each headline figure with an inline sparkline and its period,\n// so a number arrives with the shape of the trend behind it.\n// Port of the Vue/React block 1:1 — inline SVG, no chart dependency.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\n\ninterface SparklineMetric {\n  value: string\n  unit: string\n  label: string\n  period: string\n  series: number[]\n}\n\nconst metrics: SparklineMetric[] = [\n  {\n    value: '4.2',\n    unit: 'days',\n    label: 'Median time to close',\n    period: 'last 12 months',\n    series: [9.4, 9.1, 8.7, 8.2, 7.4, 6.8, 6.1, 5.6, 5.1, 4.8, 4.4, 4.2],\n  },\n  {\n    value: '61',\n    unit: '/mo',\n    label: 'Ad-hoc data requests',\n    period: 'last 12 months',\n    series: [212, 198, 184, 160, 141, 122, 108, 96, 84, 74, 66, 61],\n  },\n  {\n    value: '340',\n    unit: '',\n    label: 'Certified metrics live',\n    period: 'since launch',\n    series: [0, 12, 38, 74, 112, 148, 181, 214, 248, 281, 312, 340],\n  },\n  {\n    value: '99.98',\n    unit: '%',\n    label: 'Query availability',\n    period: 'rolling 90 days',\n    series: [99.9, 99.95, 99.92, 99.97, 99.99, 99.96, 99.98, 99.99, 99.97, 99.98, 99.99, 99.98],\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-stats-band-sparklines, [ui-stats-band-sparklines]',\n  standalone: true,\n  // Vue renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [UiBadgeComponent, UiSeparatorComponent],\n  template: `\n    <section data-slot=\"stats-band-sparklines\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-12\">\n        <span ui-badge variant=\"secondary\">Measured</span>\n\n        <dl class=\"mt-6 grid gap-8 sm:grid-cols-2 lg:grid-cols-4 lg:gap-0\">\n          @for (metric of allMetrics; track metric.label; let idx = $index) {\n            <div class=\"relative lg:px-6 lg:first:pl-0\">\n              <dd class=\"font-display text-3xl font-bold tracking-tight\">\n                {{ metric.value }}<span class=\"text-muted-foreground text-lg font-semibold\">{{ metric.unit }}</span>\n              </dd>\n              <dt class=\"mt-1 text-sm font-medium\">{{ metric.label }}</dt>\n\n              <svg\n                class=\"text-primary/70 mt-3 h-7 w-full\"\n                viewBox=\"0 0 100 28\"\n                preserveAspectRatio=\"none\"\n                aria-hidden=\"true\"\n              >\n                <polyline [attr.points]=\"points(metric.series)\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n              </svg>\n\n              <p class=\"text-muted-foreground mt-1 font-mono text-xs\">{{ metric.period }}</p>\n\n              @if (idx < allMetrics.length - 1) {\n                <div ui-separator orientation=\"vertical\" class=\"absolute top-0 right-0 hidden h-full lg:block\"></div>\n              }\n            </div>\n          }\n        </dl>\n      </div>\n    </section>\n  `,\n})\nexport class UiStatsBandSparklinesComponent {\n  protected readonly allMetrics = metrics\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('border-border bg-card border-y', this.className)\n  }\n\n  /** Normalise a series into a 100x28 viewBox so every sparkline shares a baseline. */\n  points(series: number[]): string {\n    const min = Math.min(...series)\n    const max = Math.max(...series)\n    const span = max - min || 1\n    return series\n      .map((value, index) => {\n        const x = (index / (series.length - 1)) * 100\n        const y = 26 - ((value - min) / span) * 24\n        return `${x.toFixed(1)},${y.toFixed(1)}`\n      })\n      .join(' ')\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/stats-band-sparklines/stats-band-sparklines.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/stats-band-sparklines/index.ts",
      "content": "export { UiStatsBandSparklinesComponent } from './stats-band-sparklines.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/stats-band-sparklines/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/separator.json"
  ],
  "description": "Metric band pairing each headline figure with an inline sparkline and its period, so a number arrives with the shape of the trend behind it.",
  "categories": [
    "marketing"
  ]
}