{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "subscription-churn-analytics",
  "title": "Subscription Churn Analytics",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/subscription-churn-analytics/SubscriptionChurnAnalytics.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  AlertCircle,\n  ArrowDownRight,\n  ArrowUpRight,\n  Calendar,\n  CheckCircle2,\n  DollarSign,\n  Download,\n  PhoneCall,\n  RefreshCw,\n  RotateCcw,\n  TrendingDown,\n  TrendingUp,\n  UserMinus,\n  UserPlus,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport interface SubscriptionChurnAnalyticsProps {\n  className?: string\n}\n\nconst primaryMetrics = [\n  {\n    id: 'net-mrr',\n    label: 'Net MRR Growth',\n    value: '+$12,480',\n    unit: '/ mo',\n    badge: '+8.4%',\n    badgeVariant: 'success' as const,\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' as const,\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' as const,\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' as const,\n    badgeIcon: DollarSign,\n    description: '3.4x LTV to CAC ratio across active cohort',\n  },\n]\n\nconst mrrWaterfall = [\n  {\n    id: 'new',\n    label: 'New Subscriptions',\n    amount: '+$8,200.00',\n    impact: 'positive' as const,\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' as const,\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' as const,\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' as const,\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' as const,\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 = [\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' as const,\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' as const,\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' as const,\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' as const,\n  },\n]\n\nconst quickActions = [\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' as const,\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' as const,\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' as const,\n    icon: AlertCircle,\n  },\n]\n\nexport function SubscriptionChurnAnalytics({ className }: SubscriptionChurnAnalyticsProps) {\n  const [selectedRange, setSelectedRange] = React.useState('90d')\n\n  return (\n    <div data-uipkge=\"\" data-slot=\"subscription-churn-analytics\" className={cn('w-full space-y-6', className)}>\n      {/* Header Section */}\n      <div className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n        <div className=\"space-y-1\">\n          <div className=\"flex items-center gap-2\">\n            <h2 className=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">\n              Subscription Churn &amp; MRR Analytics\n            </h2>\n            <Badge\n              variant=\"outline\"\n              className=\"border-border text-muted-foreground hidden font-mono text-xs sm:inline-flex\"\n            >\n              SaaS Metrics\n            </Badge>\n          </div>\n          <p className=\"text-muted-foreground text-sm\">\n            Track recurring revenue dynamics, logo retention cohorts, and cancellation root causes.\n          </p>\n        </div>\n\n        <div className=\"flex flex-wrap items-center gap-3\">\n          <div className=\"w-44\">\n            <Select value={selectedRange} onValueChange={setSelectedRange}>\n              <SelectTrigger size=\"sm\" className=\"w-full\">\n                <Calendar className=\"text-muted-foreground mr-1 size-3.5\" aria-hidden=\"true\" />\n                <SelectValue placeholder=\"Select period\" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value=\"30d\">Last 30 Days</SelectItem>\n                <SelectItem value=\"90d\">Last 90 Days</SelectItem>\n                <SelectItem value=\"12m\">Last 12 Months</SelectItem>\n                <SelectItem value=\"ytd\">Year to Date</SelectItem>\n              </SelectContent>\n            </Select>\n          </div>\n\n          <Button aria-label=\"Download attachment\" size=\"sm\" variant=\"outline\" className=\"gap-2 shadow-xs\">\n            <Download className=\"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 className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        {primaryMetrics.map((metric) => {\n          const BadgeIcon = metric.badgeIcon\n          return (\n            <Card key={metric.id} className=\"border-border bg-card hover:border-border/80 shadow-xs transition-colors\">\n              <CardHeader className=\"pb-2\">\n                <div className=\"flex items-center justify-between gap-2\">\n                  <CardTitle className=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">\n                    {metric.label}\n                  </CardTitle>\n                  <Badge variant={metric.badgeVariant} className=\"gap-1 font-medium tabular-nums\">\n                    <BadgeIcon className=\"size-3\" aria-hidden=\"true\" />\n                    <span>{metric.badge}</span>\n                  </Badge>\n                </div>\n              </CardHeader>\n              <CardContent className=\"space-y-1 pb-4\">\n                <div className=\"flex items-baseline gap-1\">\n                  <span className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums sm:text-3xl\">\n                    {metric.value}\n                  </span>\n                  {metric.unit && <span className=\"text-muted-foreground text-xs font-normal\">{metric.unit}</span>}\n                </div>\n                <p className=\"text-muted-foreground text-xs leading-relaxed\">{metric.description}</p>\n              </CardContent>\n            </Card>\n          )\n        })}\n      </div>\n\n      {/* MRR Movement Waterfall Breakdown Card */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"pb-4\">\n          <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n            <div>\n              <div className=\"flex items-center gap-2\">\n                <CardTitle className=\"text-foreground text-base font-semibold\">\n                  MRR Movement Waterfall Breakdown\n                </CardTitle>\n                <Badge variant=\"outline\" className=\"border-border bg-muted/30 text-xs font-medium\">\n                  ChartMogul Bridge\n                </Badge>\n              </div>\n              <CardDescription className=\"mt-1 text-xs\">\n                Decomposition of new customer revenue, expansion, contractions, logo churn, and reactivations.\n              </CardDescription>\n            </div>\n            <div className=\"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              <span className=\"text-muted-foreground text-xs font-medium\">Net MRR Change:</span>\n              <span className=\"text-success text-sm font-bold tabular-nums\">+$13,330.00</span>\n              <Badge variant=\"success\" className=\"ml-1 text-xs\">\n                +9.3%\n              </Badge>\n            </div>\n          </div>\n        </CardHeader>\n\n        <CardContent className=\"space-y-6\">\n          {/* Visual Waterfall Proportional Bar */}\n          <div className=\"space-y-2\">\n            <div className=\"text-muted-foreground flex items-center justify-between text-xs\">\n              <span>\n                Starting MRR: <strong className=\"text-foreground font-semibold tabular-nums\">$142,500.00</strong>\n              </span>\n              <span>\n                Ending MRR: <strong className=\"text-foreground font-semibold tabular-nums\">$155,830.00</strong>\n              </span>\n            </div>\n            <div className=\"bg-muted/60 flex h-3 w-full overflow-hidden rounded-full p-0.5 shadow-inner\">\n              <div\n                className=\"bg-success h-full rounded-l-full transition-[width] duration-300\"\n                style={{ width: '48%' }}\n                title=\"New Subscriptions (+$8,200.00)\"\n              />\n              <div\n                className=\"bg-success/90 h-full transition-[width] duration-300\"\n                style={{ width: '38%' }}\n                title=\"Expansion (+$6,450.00)\"\n              />\n              <div\n                className=\"bg-info h-full transition-[width] duration-300\"\n                style={{ width: '5%' }}\n                title=\"Reactivations (+$850.00)\"\n              />\n              <div\n                className=\"bg-warning h-full transition-[width] duration-300\"\n                style={{ width: '5%' }}\n                title=\"Contraction (-$1,120.00)\"\n              />\n              <div\n                className=\"bg-destructive h-full rounded-r-full transition-[width] duration-300\"\n                style={{ width: '4%' }}\n                title=\"Churn (-$1,050.00)\"\n              />\n            </div>\n            <div className=\"text-muted-foreground flex flex-wrap items-center justify-between gap-2 pt-1 text-xs\">\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"bg-success inline-block size-2 rounded-full\" />\n                <span>New (+$8.2k)</span>\n              </div>\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"bg-success inline-block size-2 rounded-full\" />\n                <span>Expansion (+$6.45k)</span>\n              </div>\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"bg-info inline-block size-2 rounded-full\" />\n                <span>Reactivation (+$850)</span>\n              </div>\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"bg-warning inline-block size-2 rounded-full\" />\n                <span>Contraction (-$1.12k)</span>\n              </div>\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"bg-destructive inline-block size-2 rounded-full\" />\n                <span>Churn (-$1.05k)</span>\n              </div>\n            </div>\n          </div>\n\n          <Separator className=\"border-border\" />\n\n          {/* Detailed Waterfall Grid */}\n          <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n            {mrrWaterfall.map((item) => {\n              const ItemIcon = item.icon\n              return (\n                <div\n                  key={item.id}\n                  className=\"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 className=\"flex items-start gap-3\">\n                    <div\n                      className={cn(\n                        'border-border flex size-9 shrink-0 items-center justify-center rounded-md border shadow-xs',\n                        item.badgeClass,\n                      )}\n                    >\n                      <ItemIcon className=\"size-4\" aria-hidden=\"true\" />\n                    </div>\n                    <div className=\"space-y-0.5\">\n                      <p className=\"text-foreground text-xs font-semibold\">{item.label}</p>\n                      <p className=\"text-muted-foreground text-xs\">{item.count}</p>\n                    </div>\n                  </div>\n                  <div className=\"text-right\">\n                    <p className={cn('text-sm font-bold tabular-nums', item.colorClass)}>{item.amount}</p>\n                    <span className=\"text-muted-foreground text-xs tabular-nums\">{item.share} gross</span>\n                  </div>\n                </div>\n              )\n            })}\n\n            {/* Net Summary Tile */}\n            <div className=\"border-success/30 bg-success/5 flex items-start justify-between rounded-lg border p-3.5 shadow-xs\">\n              <div className=\"flex items-start gap-3\">\n                <div className=\"border-success/30 bg-success/15 text-success flex size-9 shrink-0 items-center justify-center rounded-md border shadow-xs\">\n                  <TrendingUp className=\"size-4\" aria-hidden=\"true\" />\n                </div>\n                <div className=\"space-y-0.5\">\n                  <p className=\"text-foreground text-xs font-semibold\">Net MRR Movement</p>\n                  <p className=\"text-muted-foreground text-xs\">All streams combined</p>\n                </div>\n              </div>\n              <div className=\"text-right\">\n                <p className=\"text-success text-sm font-bold tabular-nums\">+$13,330.00</p>\n                <Badge variant=\"success\" className=\"text-xs tabular-nums\">\n                  Net Positive\n                </Badge>\n              </div>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n\n      {/* Churn Reason Distribution Table */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"pb-3\">\n          <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n            <div>\n              <CardTitle className=\"text-foreground text-base font-semibold\">\n                Churn Reason Distribution &amp; Lost ARR Attribution\n              </CardTitle>\n              <CardDescription className=\"mt-1 text-xs\">\n                Primary cancellation drivers captured via post-cancellation exit surveys and customer success logs.\n              </CardDescription>\n            </div>\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-muted-foreground text-xs\">Total Lost ARR:</span>\n              <span className=\"text-destructive text-sm font-bold tabular-nums\">-$65,350.00</span>\n            </div>\n          </div>\n        </CardHeader>\n        <CardContent className=\"p-0\">\n          <div className=\"overflow-x-auto\">\n            <Table>\n              <TableHeader className=\"bg-muted/40\">\n                <TableRow className=\"border-border hover:bg-transparent\">\n                  <TableHead className=\"text-foreground text-xs font-semibold\">Cancellation Reason</TableHead>\n                  <TableHead className=\"text-foreground text-xs font-semibold\">Distribution Share</TableHead>\n                  <TableHead className=\"text-foreground text-right text-xs font-semibold\">Lost ARR ($)</TableHead>\n                  <TableHead className=\"text-foreground text-right text-xs font-semibold\">Impacted Accounts</TableHead>\n                  <TableHead className=\"text-foreground text-right text-xs font-semibold\">Quarterly Trend</TableHead>\n                </TableRow>\n              </TableHeader>\n              <TableBody>\n                {churnReasons.map((row) => (\n                  <TableRow key={row.id} className=\"border-border hover:bg-muted/30 transition-colors\">\n                    <TableCell className=\"py-3.5\">\n                      <div className=\"text-foreground text-sm font-medium\">{row.reason}</div>\n                      <div className=\"text-muted-foreground text-xs\">{row.category}</div>\n                    </TableCell>\n                    <TableCell className=\"min-w-[180px] py-3.5\">\n                      <div className=\"space-y-1.5\">\n                        <div className=\"flex items-center justify-between text-xs\">\n                          <span className=\"text-foreground font-medium tabular-nums\">{row.share}%</span>\n                          <span className=\"text-muted-foreground text-xs\">of total churn</span>\n                        </div>\n                        <Progress value={row.share} className=\"bg-muted h-1.5\" />\n                      </div>\n                    </TableCell>\n                    <TableCell className=\"text-foreground py-3.5 text-right text-sm font-semibold tabular-nums\">\n                      {row.lostArr}\n                    </TableCell>\n                    <TableCell className=\"text-muted-foreground py-3.5 text-right text-xs tabular-nums\">\n                      <span className=\"text-foreground font-medium\">{row.accounts}</span> accounts\n                    </TableCell>\n                    <TableCell className=\"py-3.5 text-right\">\n                      <Badge variant={row.trendVariant} className=\"gap-1 text-xs font-medium tabular-nums\">\n                        <span>{row.trend === 'Increasing' ? '↑' : '↓'}</span>\n                        <span>{row.trend}</span>\n                        <span className=\"opacity-75\">({row.trendDelta})</span>\n                      </Badge>\n                    </TableCell>\n                  </TableRow>\n                ))}\n              </TableBody>\n            </Table>\n          </div>\n        </CardContent>\n      </Card>\n\n      {/* Churn Prevention Quick Actions */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"pb-3\">\n          <div className=\"flex items-center gap-2\">\n            <CardTitle className=\"text-foreground text-base font-semibold\">\n              Churn Prevention &amp; Win-Back Quick Actions\n            </CardTitle>\n            <Badge variant=\"secondary\" className=\"text-xs\">\n              Playbooks\n            </Badge>\n          </div>\n          <CardDescription className=\"text-xs\">\n            High-leverage intervention workflows to stem revenue loss and re-engage churned customer cohorts.\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n            {quickActions.map((action) => {\n              const ActionIcon = action.icon\n              return (\n                <div\n                  key={action.id}\n                  className=\"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 className=\"space-y-3\">\n                    <div className=\"flex items-center justify-between\">\n                      <div className=\"border-border bg-muted/40 text-foreground flex size-9 items-center justify-center rounded-md border shadow-xs\">\n                        <ActionIcon className=\"size-4\" aria-hidden=\"true\" />\n                      </div>\n                      <Badge variant=\"outline\" className=\"border-border text-muted-foreground font-mono text-xs\">\n                        {action.impactBadge}\n                      </Badge>\n                    </div>\n                    <div className=\"space-y-1\">\n                      <h4 className=\"text-foreground text-sm leading-snug font-semibold\">{action.title}</h4>\n                      <p className=\"text-muted-foreground text-xs leading-relaxed\">{action.description}</p>\n                    </div>\n                  </div>\n\n                  <div className=\"mt-4 pt-2\">\n                    <Button variant={action.buttonVariant} size=\"sm\" className=\"w-full gap-2 shadow-xs\">\n                      <ActionIcon className=\"size-3.5\" aria-hidden=\"true\" />\n                      <span>{action.buttonText}</span>\n                    </Button>\n                  </div>\n                </div>\n              )\n            })}\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  )\n}\n\nexport default SubscriptionChurnAnalytics\n",
      "type": "registry:block",
      "target": "~/components/blocks/SubscriptionChurnAnalytics.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/progress.json",
    "https://uipkge.dev/r/react/select.json",
    "https://uipkge.dev/r/react/separator.json",
    "https://uipkge.dev/r/react/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"
  ]
}