{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "subscription-churn-analytics",
  "title": "Subscription Churn Analytics",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/subscription-churn-analytics/subscription-churn-analytics.component.ts",
      "content": "import { Component, Input, signal, ChangeDetectionStrategy } from '@angular/core'\nimport {\n  AlertCircle,\n  ArrowDownRight,\n  ArrowUpRight,\n  Calendar,\n  CheckCircle2,\n  DollarSign,\n  Download,\n  LucideAngularModule,\n  PhoneCall,\n  RefreshCw,\n  RotateCcw,\n  TrendingDown,\n  TrendingUp,\n  UserMinus,\n  UserPlus,\n  type LucideIconData,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent, type BadgeVariant } from '@/ui/badge/badge.component'\nimport { UiButtonComponent, type ButtonVariant } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiProgressComponent } from '@/ui/progress/progress.component'\nimport {\n  UiSelectComponent,\n  UiSelectContentComponent,\n  UiSelectItemComponent,\n  UiSelectTriggerComponent,\n  UiSelectValueComponent,\n} from '@/ui/select/select.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface ChurnPrimaryMetric {\n  id: string\n  label: string\n  value: string\n  unit: string\n  badge: string\n  badgeVariant: Extract<BadgeVariant, 'success' | 'outline' | 'secondary'>\n  badgeIcon: LucideIconData\n  description: string\n}\n\nexport interface MrrMovement {\n  id: string\n  label: string\n  amount: string\n  impact: 'positive' | 'warning' | 'negative' | 'info'\n  share: string\n  count: string\n  colorClass: string\n  badgeClass: string\n  barClass: string\n  icon: LucideIconData\n}\n\nexport interface ChurnReason {\n  id: string\n  reason: string\n  category: string\n  share: number\n  lostArr: string\n  accounts: number\n  trend: 'Increasing' | 'Decreasing'\n  trendDelta: string\n  trendVariant: Extract<BadgeVariant, 'destructive' | 'success' | 'warning'>\n}\n\nexport interface ChurnQuickAction {\n  id: string\n  title: string\n  description: string\n  impactBadge: string\n  buttonText: string\n  buttonVariant: Extract<ButtonVariant, 'default' | 'outline'>\n  icon: LucideIconData\n}\n\nconst primaryMetrics: ChurnPrimaryMetric[] = [\n  {\n    id: 'net-mrr',\n    label: 'Net MRR Growth',\n    value: '+$12,480',\n    unit: '/ mo',\n    badge: '+8.4%',\n    badgeVariant: 'success',\n    badgeIcon: TrendingUp,\n    description: 'Gross additions outpacing cancellations by 6.8x',\n  },\n  {\n    id: 'user-churn',\n    label: 'User Churn Rate',\n    value: '1.8%',\n    unit: '/ mo',\n    badge: 'Below 2% benchmark',\n    badgeVariant: 'success',\n    badgeIcon: CheckCircle2,\n    description: 'Logo churn down 0.4% from previous quarter',\n  },\n  {\n    id: 'revenue-churn',\n    label: 'Revenue Churn Rate',\n    value: '0.9%',\n    unit: '/ mo',\n    badge: 'Negative Net Churn',\n    badgeVariant: 'outline',\n    badgeIcon: TrendingDown,\n    description: 'Expansion ($6,450) exceeds total churn ($2,170)',\n  },\n  {\n    id: 'ltv',\n    label: 'Customer Lifetime Value',\n    value: '$4,850.00',\n    unit: '',\n    badge: 'CAC Payback 4.2 mo',\n    badgeVariant: 'secondary',\n    badgeIcon: DollarSign,\n    description: '3.4x LTV to CAC ratio across active cohort',\n  },\n]\n\nconst mrrWaterfall: MrrMovement[] = [\n  {\n    id: 'new',\n    label: 'New Subscriptions',\n    amount: '+$8,200.00',\n    impact: 'positive',\n    share: '52.9%',\n    count: '38 new accounts',\n    colorClass: 'text-success',\n    badgeClass: 'bg-success/10 text-success border-success/20',\n    barClass: 'bg-success',\n    icon: UserPlus,\n  },\n  {\n    id: 'expansion',\n    label: 'Expansion / Upgrades',\n    amount: '+$6,450.00',\n    impact: 'positive',\n    share: '41.6%',\n    count: '24 accounts expanded',\n    colorClass: 'text-success',\n    badgeClass: 'bg-success/10 text-success border-success/20',\n    barClass: 'bg-success/80',\n    icon: ArrowUpRight,\n  },\n  {\n    id: 'contraction',\n    label: 'Contraction / Downgrades',\n    amount: '-$1,120.00',\n    impact: 'warning',\n    share: '7.2%',\n    count: '9 tier downgrades',\n    colorClass: 'text-warning',\n    badgeClass: 'bg-warning/10 text-warning border-warning/20',\n    barClass: 'bg-warning',\n    icon: ArrowDownRight,\n  },\n  {\n    id: 'churn',\n    label: 'Churn / Cancellations',\n    amount: '-$1,050.00',\n    impact: 'negative',\n    share: '6.8%',\n    count: '7 accounts lost',\n    colorClass: 'text-destructive',\n    badgeClass: 'bg-destructive/10 text-destructive border-destructive/20',\n    barClass: 'bg-destructive',\n    icon: UserMinus,\n  },\n  {\n    id: 'reactivations',\n    label: 'Reactivations',\n    amount: '+$850.00',\n    impact: 'info',\n    share: '5.5%',\n    count: '4 win-back returns',\n    colorClass: 'text-info',\n    badgeClass: 'bg-info/10 text-info border-info/20',\n    barClass: 'bg-info bg-info',\n    icon: RefreshCw,\n  },\n]\n\nconst churnReasons: ChurnReason[] = [\n  {\n    id: 'competitor',\n    reason: 'Switched to competitor',\n    category: 'Product Fit / Competition',\n    share: 38,\n    lostArr: '-$24,800.00',\n    accounts: 19,\n    trend: 'Increasing',\n    trendDelta: '+12% QoQ',\n    trendVariant: 'destructive',\n  },\n  {\n    id: 'budget',\n    reason: 'Budget constraints',\n    category: 'Economic / Spend Freeze',\n    share: 28,\n    lostArr: '-$18,300.00',\n    accounts: 14,\n    trend: 'Decreasing',\n    trendDelta: '-8% QoQ',\n    trendVariant: 'success',\n  },\n  {\n    id: 'missing-sso',\n    reason: 'Missing feature: SAML SSO',\n    category: 'Security / Compliance',\n    share: 21,\n    lostArr: '-$13,750.00',\n    accounts: 8,\n    trend: 'Decreasing',\n    trendDelta: '-15% QoQ',\n    trendVariant: 'success',\n  },\n  {\n    id: 'project-ended',\n    reason: 'Project ended',\n    category: 'Seasonal / Lifecycle',\n    share: 13,\n    lostArr: '-$8,500.00',\n    accounts: 6,\n    trend: 'Increasing',\n    trendDelta: '+4% QoQ',\n    trendVariant: 'warning',\n  },\n]\n\nconst quickActions: ChurnQuickAction[] = [\n  {\n    id: 'winback',\n    title: 'Trigger Discount Win-Back Campaign',\n    description: 'Dispatch automated 20% annual renewal incentives to 25 accounts canceled within the last 45 days.',\n    impactBadge: 'Est. $4,800 MRR recovered',\n    buttonText: 'Trigger Win-Back',\n    buttonVariant: 'default',\n    icon: RotateCcw,\n  },\n  {\n    id: 'interviews',\n    title: 'Schedule Exit Discovery Interviews',\n    description:\n      'Book 15-minute product alignment calls with churned enterprise accounts ($10k+ ARR) for feature feedback.',\n    impactBadge: '3 enterprise accounts flagged',\n    buttonText: 'Schedule Interviews',\n    buttonVariant: 'outline',\n    icon: PhoneCall,\n  },\n  {\n    id: 'health-alerts',\n    title: 'Configure Churn Risk Telemetry Alerts',\n    description: 'Automate high-priority notifications when weekly active seat engagement drops below 40% threshold.',\n    impactBadge: '12 accounts in risk zone',\n    buttonText: 'Configure Triggers',\n    buttonVariant: 'outline',\n    icon: AlertCircle,\n  },\n]\n\n/**\n * ChartMogul / Baremetrics style SaaS subscription churn and MRR analytics dashboard: four\n * SaaS metric cards, the MRR movement waterfall bridge, the churn reason / lost ARR table and\n * the churn prevention playbooks. Angular port of the React `SubscriptionChurnAnalytics`\n * block (same markup, classes, copy and sample data).\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-subscription-churn-analytics, [ui-subscription-churn-analytics]',\n  standalone: true,\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiProgressComponent,\n    UiSelectComponent,\n    UiSelectContentComponent,\n    UiSelectItemComponent,\n    UiSelectTriggerComponent,\n    UiSelectValueComponent,\n    UiSeparatorComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  host: {\n    '[attr.data-uipkge]': '\"\"',\n    '[attr.data-slot]': '\"subscription-churn-analytics\"',\n    '[class]': 'hostClass',\n  },\n  template: `\n    <!-- Header Section -->\n    <div class=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n      <div class=\"space-y-1\">\n        <div class=\"flex items-center gap-2\">\n          <h2 class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">\n            Subscription Churn &amp; MRR Analytics\n          </h2>\n          <span\n            ui-badge\n            variant=\"outline\"\n            class=\"border-border text-muted-foreground hidden font-mono text-xs sm:inline-flex\"\n          >\n            SaaS Metrics\n          </span>\n        </div>\n        <p class=\"text-muted-foreground text-sm\">\n          Track recurring revenue dynamics, logo retention cohorts, and cancellation root causes.\n        </p>\n      </div>\n\n      <div class=\"flex flex-wrap items-center gap-3\">\n        <div class=\"w-44\">\n          <ui-select [value]=\"selectedRange()\" (valueChange)=\"selectedRange.set($event)\">\n            <button ui-select-trigger size=\"sm\" class=\"w-full\">\n              <!-- [class]: a static class on lucide-icon lands on the host and the svg, doubling mr-1. -->\n              <lucide-icon [img]=\"Calendar\" [class]=\"'text-muted-foreground mr-1 size-3.5'\" aria-hidden=\"true\" />\n              <ui-select-value placeholder=\"Select period\" />\n            </button>\n            <ui-select-content>\n              <ui-select-item value=\"30d\">Last 30 Days</ui-select-item>\n              <ui-select-item value=\"90d\">Last 90 Days</ui-select-item>\n              <ui-select-item value=\"12m\">Last 12 Months</ui-select-item>\n              <ui-select-item value=\"ytd\">Year to Date</ui-select-item>\n            </ui-select-content>\n          </ui-select>\n        </div>\n\n        <button ui-button aria-label=\"Download attachment\" size=\"sm\" variant=\"outline\" class=\"gap-2 shadow-xs\">\n          <lucide-icon [img]=\"Download\" class=\"text-muted-foreground size-4\" aria-hidden=\"true\" />\n          <span>Export Retention Report</span>\n        </button>\n      </div>\n    </div>\n\n    <!-- 4 Primary SaaS Metrics Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      @for (metric of primaryMetrics; track metric.id) {\n        <ui-card class=\"border-border bg-card hover:border-border/80 shadow-xs transition-colors\">\n          <ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <ui-card-title class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n                {{ metric.label }}\n              </ui-card-title>\n              <span ui-badge [variant]=\"metric.badgeVariant\" class=\"gap-1 font-medium tabular-nums\">\n                <lucide-icon [img]=\"metric.badgeIcon\" class=\"size-3\" aria-hidden=\"true\" />\n                <span>{{ metric.badge }}</span>\n              </span>\n            </div>\n          </ui-card-header>\n          <ui-card-content class=\"space-y-1 pb-4\">\n            <div class=\"flex items-baseline gap-1\">\n              <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums sm:text-3xl\">\n                {{ metric.value }}\n              </span>\n              @if (metric.unit) {\n                <span class=\"text-muted-foreground text-xs font-normal\">{{ metric.unit }}</span>\n              }\n            </div>\n            <p class=\"text-muted-foreground text-xs leading-relaxed\">{{ metric.description }}</p>\n          </ui-card-content>\n        </ui-card>\n      }\n    </div>\n\n    <!-- MRR Movement Waterfall Breakdown Card -->\n    <ui-card class=\"border-border bg-card shadow-xs\">\n      <ui-card-header class=\"pb-4\">\n        <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <div class=\"flex items-center gap-2\">\n              <ui-card-title class=\"text-foreground text-base font-semibold\"\n                >MRR Movement Waterfall Breakdown</ui-card-title\n              >\n              <span ui-badge variant=\"outline\" class=\"border-border bg-muted/30 text-xs font-medium\">\n                ChartMogul Bridge\n              </span>\n            </div>\n            <ui-card-description class=\"mt-1 text-xs\">\n              Decomposition of new customer revenue, expansion, contractions, logo churn, and reactivations.\n            </ui-card-description>\n          </div>\n          <div\n            class=\"border-border/80 bg-muted/20 flex items-center gap-2 self-start rounded-lg border px-3 py-1.5 sm:self-auto\"\n          >\n            <span class=\"text-muted-foreground text-xs font-medium\">Net MRR Change:</span>\n            <span class=\"text-success text-sm font-bold tabular-nums\">+$13,330.00</span>\n            <span ui-badge variant=\"success\" class=\"ml-1 text-xs\">+9.3%</span>\n          </div>\n        </div>\n      </ui-card-header>\n\n      <ui-card-content class=\"space-y-6\">\n        <!-- Visual Waterfall Proportional Bar -->\n        <div class=\"space-y-2\">\n          <div class=\"text-muted-foreground flex items-center justify-between text-xs\">\n            <span> Starting MRR: <strong class=\"text-foreground font-semibold tabular-nums\">$142,500.00</strong> </span>\n            <span> Ending MRR: <strong class=\"text-foreground font-semibold tabular-nums\">$155,830.00</strong> </span>\n          </div>\n          <div class=\"bg-muted/60 flex h-3 w-full overflow-hidden rounded-full p-0.5 shadow-inner\">\n            <div\n              class=\"bg-success h-full w-[48%] rounded-l-full transition-[width] duration-300\"\n              title=\"New Subscriptions (+$8,200.00)\"\n            ></div>\n            <div\n              class=\"bg-success/90 h-full w-[38%] transition-[width] duration-300\"\n              title=\"Expansion (+$6,450.00)\"\n            ></div>\n            <div class=\"bg-info h-full w-[5%] transition-[width] duration-300\" title=\"Reactivations (+$850.00)\"></div>\n            <div\n              class=\"bg-warning h-full w-[5%] transition-[width] duration-300\"\n              title=\"Contraction (-$1,120.00)\"\n            ></div>\n            <div\n              class=\"bg-destructive h-full w-[4%] rounded-r-full transition-[width] duration-300\"\n              title=\"Churn (-$1,050.00)\"\n            ></div>\n          </div>\n          <div class=\"text-muted-foreground flex flex-wrap items-center justify-between gap-2 pt-1 text-xs\">\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"bg-success inline-block size-2 rounded-full\"></span>\n              <span>New (+$8.2k)</span>\n            </div>\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"bg-success inline-block size-2 rounded-full\"></span>\n              <span>Expansion (+$6.45k)</span>\n            </div>\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"bg-info inline-block size-2 rounded-full\"></span>\n              <span>Reactivation (+$850)</span>\n            </div>\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"bg-warning inline-block size-2 rounded-full\"></span>\n              <span>Contraction (-$1.12k)</span>\n            </div>\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"bg-destructive inline-block size-2 rounded-full\"></span>\n              <span>Churn (-$1.05k)</span>\n            </div>\n          </div>\n        </div>\n\n        <ui-separator class=\"border-border\" />\n\n        <!-- Detailed Waterfall Grid -->\n        <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n          @for (item of mrrWaterfall; track item.id) {\n            <div\n              class=\"border-border bg-card/60 hover:bg-muted/20 flex items-start justify-between rounded-lg border p-3.5 shadow-xs transition-colors\"\n            >\n              <div class=\"flex items-start gap-3\">\n                <div\n                  [class]=\"\n                    cn(\n                      'border-border flex size-9 shrink-0 items-center justify-center rounded-md border shadow-xs',\n                      item.badgeClass\n                    )\n                  \"\n                >\n                  <lucide-icon [img]=\"item.icon\" class=\"size-4\" aria-hidden=\"true\" />\n                </div>\n                <div class=\"space-y-0.5\">\n                  <p class=\"text-foreground text-xs font-semibold\">{{ item.label }}</p>\n                  <p class=\"text-muted-foreground text-xs\">{{ item.count }}</p>\n                </div>\n              </div>\n              <div class=\"text-right\">\n                <p [class]=\"cn('text-sm font-bold tabular-nums', item.colorClass)\">{{ item.amount }}</p>\n                <span class=\"text-muted-foreground text-xs tabular-nums\">{{ item.share }} gross</span>\n              </div>\n            </div>\n          }\n\n          <!-- Net Summary Tile -->\n          <div\n            class=\"border-success/30 bg-success/5 flex items-start justify-between rounded-lg border p-3.5 shadow-xs\"\n          >\n            <div class=\"flex items-start gap-3\">\n              <div\n                class=\"border-success/30 bg-success/15 text-success flex size-9 shrink-0 items-center justify-center rounded-md border shadow-xs\"\n              >\n                <lucide-icon [img]=\"TrendingUp\" class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n              <div class=\"space-y-0.5\">\n                <p class=\"text-foreground text-xs font-semibold\">Net MRR Movement</p>\n                <p class=\"text-muted-foreground text-xs\">All streams combined</p>\n              </div>\n            </div>\n            <div class=\"text-right\">\n              <p class=\"text-success text-sm font-bold tabular-nums\">+$13,330.00</p>\n              <span ui-badge variant=\"success\" class=\"text-xs tabular-nums\">Net Positive</span>\n            </div>\n          </div>\n        </div>\n      </ui-card-content>\n    </ui-card>\n\n    <!-- Churn Reason Distribution Table -->\n    <ui-card class=\"border-border bg-card shadow-xs\">\n      <ui-card-header class=\"pb-3\">\n        <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <ui-card-title class=\"text-foreground text-base font-semibold\">\n              Churn Reason Distribution &amp; Lost ARR Attribution\n            </ui-card-title>\n            <ui-card-description class=\"mt-1 text-xs\">\n              Primary cancellation drivers captured via post-cancellation exit surveys and customer success logs.\n            </ui-card-description>\n          </div>\n          <div class=\"flex items-center gap-2\">\n            <span class=\"text-muted-foreground text-xs\">Total Lost ARR:</span>\n            <span class=\"text-destructive text-sm font-bold tabular-nums\">-$65,350.00</span>\n          </div>\n        </div>\n      </ui-card-header>\n      <ui-card-content class=\"p-0\">\n        <div class=\"overflow-x-auto\">\n          <div ui-table>\n            <thead ui-table-header class=\"bg-muted/40\">\n              <tr ui-table-row class=\"border-border hover:bg-transparent\">\n                <th ui-table-head class=\"text-foreground text-xs font-semibold\">Cancellation Reason</th>\n                <th ui-table-head class=\"text-foreground text-xs font-semibold\">Distribution Share</th>\n                <th ui-table-head class=\"text-foreground text-right text-xs font-semibold\">Lost ARR ($)</th>\n                <th ui-table-head class=\"text-foreground text-right text-xs font-semibold\">Impacted Accounts</th>\n                <th ui-table-head class=\"text-foreground text-right text-xs font-semibold\">Quarterly Trend</th>\n              </tr>\n            </thead>\n            <tbody ui-table-body>\n              @for (row of churnReasons; track row.id) {\n                <tr ui-table-row class=\"border-border hover:bg-muted/30 transition-colors\">\n                  <td ui-table-cell class=\"py-3.5\">\n                    <div class=\"text-foreground text-sm font-medium\">{{ row.reason }}</div>\n                    <div class=\"text-muted-foreground text-xs\">{{ row.category }}</div>\n                  </td>\n                  <td ui-table-cell class=\"min-w-[180px] py-3.5\">\n                    <div class=\"space-y-1.5\">\n                      <div class=\"flex items-center justify-between text-xs\">\n                        <span class=\"text-foreground font-medium tabular-nums\">{{ row.share }}%</span>\n                        <span class=\"text-muted-foreground text-xs\">of total churn</span>\n                      </div>\n                      <ui-progress [value]=\"row.share\" class=\"bg-muted h-1.5\" />\n                    </div>\n                  </td>\n                  <td ui-table-cell class=\"text-foreground py-3.5 text-right text-sm font-semibold tabular-nums\">\n                    {{ row.lostArr }}\n                  </td>\n                  <td ui-table-cell class=\"text-muted-foreground py-3.5 text-right text-xs tabular-nums\">\n                    <span class=\"text-foreground font-medium\">{{ row.accounts }}</span> accounts\n                  </td>\n                  <td ui-table-cell class=\"py-3.5 text-right\">\n                    <span ui-badge [variant]=\"row.trendVariant\" class=\"gap-1 text-xs font-medium tabular-nums\">\n                      <span>{{ row.trend === 'Increasing' ? '↑' : '↓' }}</span>\n                      <span>{{ row.trend }}</span>\n                      <span class=\"opacity-75\">({{ row.trendDelta }})</span>\n                    </span>\n                  </td>\n                </tr>\n              }\n            </tbody>\n          </div>\n        </div>\n      </ui-card-content>\n    </ui-card>\n\n    <!-- Churn Prevention Quick Actions -->\n    <ui-card class=\"border-border bg-card shadow-xs\">\n      <ui-card-header class=\"pb-3\">\n        <div class=\"flex items-center gap-2\">\n          <ui-card-title class=\"text-foreground text-base font-semibold\">\n            Churn Prevention &amp; Win-Back Quick Actions\n          </ui-card-title>\n          <span ui-badge variant=\"secondary\" class=\"text-xs\">Playbooks</span>\n        </div>\n        <ui-card-description class=\"text-xs\">\n          High-leverage intervention workflows to stem revenue loss and re-engage churned customer cohorts.\n        </ui-card-description>\n      </ui-card-header>\n      <ui-card-content>\n        <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n          @for (action of quickActions; track action.id) {\n            <div\n              class=\"border-border bg-card/60 hover:border-border/80 hover:bg-muted/10 flex flex-col justify-between rounded-lg border p-4 shadow-xs transition-colors\"\n            >\n              <div class=\"space-y-3\">\n                <div class=\"flex items-center justify-between\">\n                  <div\n                    class=\"border-border bg-muted/40 text-foreground flex size-9 items-center justify-center rounded-md border shadow-xs\"\n                  >\n                    <lucide-icon [img]=\"action.icon\" class=\"size-4\" aria-hidden=\"true\" />\n                  </div>\n                  <span ui-badge variant=\"outline\" class=\"border-border text-muted-foreground font-mono text-xs\">\n                    {{ action.impactBadge }}\n                  </span>\n                </div>\n                <div class=\"space-y-1\">\n                  <h4 class=\"text-foreground text-sm leading-snug font-semibold\">{{ action.title }}</h4>\n                  <p class=\"text-muted-foreground text-xs leading-relaxed\">{{ action.description }}</p>\n                </div>\n              </div>\n\n              <div class=\"mt-4 pt-2\">\n                <button ui-button [variant]=\"action.buttonVariant\" size=\"sm\" class=\"w-full gap-2 shadow-xs\">\n                  <lucide-icon [img]=\"action.icon\" class=\"size-3.5\" aria-hidden=\"true\" />\n                  <span>{{ action.buttonText }}</span>\n                </button>\n              </div>\n            </div>\n          }\n        </div>\n      </ui-card-content>\n    </ui-card>\n  `,\n})\nexport class UiSubscriptionChurnAnalyticsComponent {\n  @Input('class') className?: string\n\n  protected readonly cn = cn\n  protected readonly primaryMetrics = primaryMetrics\n  protected readonly mrrWaterfall = mrrWaterfall\n  protected readonly churnReasons = churnReasons\n  protected readonly quickActions = quickActions\n\n  protected readonly Calendar = Calendar\n  protected readonly Download = Download\n  protected readonly TrendingUp = TrendingUp\n\n  readonly selectedRange = signal('90d')\n\n  get hostClass(): string {\n    return cn('block w-full space-y-6', this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/subscription-churn-analytics/subscription-churn-analytics.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/subscription-churn-analytics/index.ts",
      "content": "export {\n  UiSubscriptionChurnAnalyticsComponent,\n  type ChurnPrimaryMetric,\n  type ChurnQuickAction,\n  type ChurnReason,\n  type MrrMovement,\n} from './subscription-churn-analytics.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/subscription-churn-analytics/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/progress.json",
    "https://uipkge.dev/r/angular/select.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "ChartMogul and Baremetrics style SaaS subscription churn and MRR analytics dashboard. Features 4 key SaaS metrics cards (Net MRR growth, logo churn rate, net revenue churn, and LTV/CAC), an MRR movement waterfall decomposition bridge, a churn reasons distribution table with lost ARR attribution and trend indicators, and automated churn prevention playbook quick actions.",
  "categories": [
    "analytics",
    "fintech",
    "dashboard"
  ]
}