{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "proration-preview",
  "title": "Proration Preview",
  "description": "Interactive component that shows billing adjustments when users change subscription plans, featuring cost breakdowns, credits, and prorated charges",
  "dependencies": ["lucide-react", "class-variance-authority", "motion"],
  "registryDependencies": [
    "button",
    "card",
    "badge",
    "separator",
    "tabs",
    "utils"
  ],
  "files": [
    {
      "path": "src/registry/billingsdk/proration-preview.tsx",
      "content": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Separator } from \"@/components/ui/separator\";\nimport {\n  ArrowRight,\n  Calendar,\n  CreditCard,\n  Calculator,\n  Clock,\n} from \"lucide-react\";\nimport { type Plan, type CurrentPlan } from \"@/lib/billingsdk-config\";\nimport { cn } from \"@/lib/utils\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nconst prorationPreviewVariants = cva(\"w-full max-w-3xl mx-auto\", {\n  variants: {\n    theme: {\n      minimal: \"\",\n      classic:\n        \"relative overflow-hidden rounded-xl border border-border/50 bg-gradient-to-br from-card/50 to-muted/30 backdrop-blur-sm\",\n    },\n    size: {\n      small: \"text-sm\",\n      medium: \"text-base\",\n      large: \"text-lg\",\n    },\n  },\n  defaultVariants: {\n    theme: \"minimal\",\n    size: \"medium\",\n  },\n});\n\nconst cardVariants = cva(\"transition-all duration-300\", {\n  variants: {\n    theme: {\n      minimal: \"border border-border bg-card\",\n      classic:\n        \"border border-border/30 bg-gradient-to-br from-card/80 to-muted/20 backdrop-blur-sm shadow-md\",\n    },\n  },\n  defaultVariants: {\n    theme: \"minimal\",\n  },\n});\n\n/**\n * Props for `ProrationPreview`.\n *\n * Combines visual variants from `prorationPreviewVariants` with\n * the billing context needed to compute proration math.\n *\n * - `currentPlan` and `newPlan` supply pricing and labels\n * - `billingCycle` controls the target cycle for the new plan\n * - `daysRemaining` and `effectiveDate` influence credit/charge math\n * - `onConfirm`/`onCancel` wire user actions\n */\nexport interface ProrationPreviewProps extends VariantProps<\n  typeof prorationPreviewVariants\n> {\n  className?: string;\n  currentPlan: CurrentPlan;\n  newPlan: Plan;\n  billingCycle: \"monthly\" | \"yearly\";\n  daysRemaining?: number;\n  effectiveDate?: string;\n  onConfirm?: () => void;\n  onCancel?: () => void;\n  confirmText?: string;\n  cancelText?: string;\n}\n\n/**\n * ProrationPreview\n *\n * Renders a detailed, accessible preview of billing changes when a user switches\n * subscription plans. It calculates and displays credits for unused time,\n * prorated charges for the new plan, and the resulting net amount, with clear\n * visual hierarchy and responsive styles.\n *\n * Key UI sections:\n * - From/To plan summary with upgrade/downgrade badges\n * - Billing breakdown (credit, prorated charge, net amount)\n * - Timeline note describing when changes take effect\n * - Primary/secondary actions to confirm or cancel\n *\n * Props accept both monthly and yearly cycles and support custom pricing\n * scenarios (e.g., enterprise). Visual appearance can be adjusted via\n * `theme` and `size` variants.\n *\n * @param props.className Optional container className override.\n * @param props.currentPlan Current subscription context including plan and cycle.\n * @param props.newPlan Target plan the user is moving to.\n * @param props.billingCycle Billing cycle for the new plan (monthly/yearly).\n * @param props.daysRemaining Remaining days in the current cycle (defaults to 15).\n * @param props.effectiveDate When the change takes effect (e.g., \"immediately\" or \"next billing cycle\").\n * @param props.onConfirm Callback invoked when user confirms the change.\n * @param props.onCancel Callback invoked when user cancels the change.\n * @param props.confirmText Custom label for the confirm action.\n * @param props.cancelText Custom label for the cancel action.\n * @param props.theme Visual theme variant (minimal | classic). Defaults to minimal.\n * @param props.size Component size (small | medium | large). Defaults to medium.\n */\nexport function ProrationPreview({\n  className,\n  currentPlan,\n  newPlan,\n  billingCycle,\n  daysRemaining = 15,\n  effectiveDate = \"immediately\",\n  onConfirm,\n  onCancel,\n  confirmText = \"Confirm Change\",\n  cancelText = \"Cancel\",\n  theme = \"minimal\",\n  size = \"medium\",\n}: ProrationPreviewProps) {\n  // Prices & proration (robust) - Fixed CodeRabbit issues\n  const currentCycleDays = currentPlan.type === \"yearly\" ? 365 : 30;\n  const newCycleDays = billingCycle === \"yearly\" ? 365 : 30;\n  const isNumericValue = (v?: string) => {\n    if (v == null) return false;\n    const s = String(v).replace(/[^\\d.\\-]/g, \"\");\n    const n = Number.parseFloat(s);\n    return Number.isFinite(n);\n  };\n  const toNumber = (v?: string) => {\n    if (v == null) return undefined;\n    const s = String(v).replace(/[^\\d.\\-]/g, \"\");\n    const n = Number.parseFloat(s);\n    return Number.isFinite(n) ? n : undefined;\n  };\n  const currentRaw =\n    currentPlan.type === \"monthly\"\n      ? currentPlan.plan.monthlyPrice\n      : currentPlan.type === \"yearly\"\n        ? currentPlan.plan.yearlyPrice\n        : currentPlan.price;\n  const newRaw =\n    billingCycle === \"monthly\" ? newPlan.monthlyPrice : newPlan.yearlyPrice;\n  const currentPrice = toNumber(currentRaw);\n  const newPrice = toNumber(newRaw);\n  const isCustomCurrent = !isNumericValue(currentRaw);\n  const isCustomNew = !isNumericValue(newRaw);\n  const chargeCurrency = newPlan.currency ?? currentPlan.plan.currency ?? \"$\";\n  const creditCurrency = currentPlan.plan.currency ?? newPlan.currency ?? \"$\";\n  const clampedUnusedDays = Math.max(\n    0,\n    Math.min(daysRemaining, currentCycleDays),\n  );\n  const isNextCycle =\n    typeof effectiveDate === \"string\" &&\n    effectiveDate.toLowerCase().includes(\"next\");\n\n  const prorationDays = isNextCycle ? 0 : clampedUnusedDays;\n  const canCompute =\n    !isNextCycle &&\n    !isCustomCurrent &&\n    !isCustomNew &&\n    currentPrice !== undefined &&\n    newPrice !== undefined;\n  const creditAmount = canCompute\n    ? (currentPrice! / currentCycleDays) * clampedUnusedDays\n    : 0;\n  const proratedCharge = canCompute\n    ? (newPrice! / newCycleDays) * prorationDays\n    : 0;\n  const netAmount = proratedCharge - creditAmount;\n\n  const normalizedCurrentMonthly =\n    currentPlan.type === \"yearly\" && currentPrice !== undefined\n      ? currentPrice / 12\n      : (currentPrice ?? 0);\n  const normalizedNewMonthly =\n    billingCycle === \"yearly\" && newPrice !== undefined\n      ? newPrice / 12\n      : (newPrice ?? 0);\n  const hasComparablePrices =\n    !isCustomCurrent &&\n    !isCustomNew &&\n    currentPrice !== undefined &&\n    newPrice !== undefined;\n  const isUpgrade =\n    hasComparablePrices && normalizedNewMonthly > normalizedCurrentMonthly;\n  const isDowngrade =\n    hasComparablePrices && normalizedNewMonthly < normalizedCurrentMonthly;\n\n  return (\n    <div className={cn(prorationPreviewVariants({ theme, size }), className)}>\n      {theme === \"classic\" && (\n        <>\n          <div className=\"bg-grid-pattern absolute inset-0 opacity-5\" />\n          <div className=\"bg-primary/5 absolute top-1/2 left-1/2 h-64 w-64 -translate-x-1/2 -translate-y-1/2 rounded-full blur-3xl\" />\n        </>\n      )}\n\n      <Card className={cn(cardVariants({ theme }))}>\n        <CardHeader className=\"px-4 pb-3 sm:px-6 sm:pb-4\">\n          <CardTitle className=\"flex items-center gap-2 text-base sm:text-lg\">\n            <div className=\"bg-primary/10 ring-primary/20 rounded-lg p-2 ring-1\">\n              <Calculator className=\"text-primary h-4 w-4 sm:h-5 sm:w-5\" />\n            </div>\n            Plan Change Preview\n          </CardTitle>\n          <p className=\"text-muted-foreground text-sm\">\n            Review the charges and credits for your plan change\n          </p>\n        </CardHeader>\n\n        <CardContent className=\"space-y-4 px-4 sm:space-y-6 sm:px-6\">\n          {/* From/To Plans */}\n          <div className=\"grid grid-cols-1 items-center gap-3 sm:gap-4 md:grid-cols-3\">\n            {/* Current Plan */}\n            <motion.div\n              initial={{ opacity: 0, x: -20 }}\n              animate={{ opacity: 1, x: 0 }}\n              transition={{ duration: 0.3 }}\n              className={cn(\n                \"rounded-lg border p-3 sm:p-4\",\n                theme === \"classic\"\n                  ? \"from-muted/50 to-background/50 border-border/50 bg-gradient-to-br\"\n                  : \"bg-muted/50 border-border\",\n              )}\n            >\n              <div className=\"mb-2 flex items-center gap-2\">\n                <Badge variant=\"outline\" className=\"text-[10px] sm:text-xs\">\n                  Current\n                </Badge>\n                {isDowngrade && (\n                  <Badge variant=\"secondary\" className=\"text-[10px] sm:text-xs\">\n                    Downgrading\n                  </Badge>\n                )}\n              </div>\n              <h3 className=\"text-base font-semibold sm:text-lg\">\n                {currentPlan.plan.title}\n              </h3>\n              <p className=\"text-muted-foreground mb-3 text-xs sm:text-sm\">\n                {isCustomCurrent\n                  ? \"Custom\"\n                  : `${creditCurrency}${currentPrice}/${currentPlan.type}`}\n              </p>\n              <div className=\"text-muted-foreground flex items-center gap-1 text-xs\">\n                <Clock className=\"h-3 w-3 sm:h-4 sm:w-4\" />\n                {daysRemaining} days remaining\n              </div>\n            </motion.div>\n\n            {/* Arrow */}\n            <div className=\"flex justify-center\">\n              <motion.div\n                initial={{ scale: 0 }}\n                animate={{ scale: 1 }}\n                transition={{ duration: 0.3, delay: 0.2 }}\n                className={cn(\n                  \"rounded-full p-2\",\n                  theme === \"classic\"\n                    ? \"from-primary to-primary/80 text-primary-foreground bg-gradient-to-r shadow-lg\"\n                    : \"bg-primary/10 text-primary\",\n                )}\n              >\n                <ArrowRight className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n              </motion.div>\n            </div>\n\n            {/* New Plan */}\n            <motion.div\n              initial={{ opacity: 0, x: 20 }}\n              animate={{ opacity: 1, x: 0 }}\n              transition={{ duration: 0.3, delay: 0.1 }}\n              className={cn(\n                \"rounded-lg border p-3 sm:p-4\",\n                theme === \"classic\"\n                  ? \"from-primary/5 to-primary/10 border-primary/30 bg-gradient-to-br\"\n                  : \"bg-primary/5 border-primary/30\",\n              )}\n            >\n              <div className=\"mb-2 flex items-center gap-2\">\n                <Badge variant=\"default\" className=\"text-[10px] sm:text-xs\">\n                  New Plan\n                </Badge>\n                {isUpgrade && (\n                  <Badge variant=\"secondary\" className=\"text-[10px] sm:text-xs\">\n                    Upgrading\n                  </Badge>\n                )}\n              </div>\n              <h3 className=\"text-base font-semibold sm:text-lg\">\n                {newPlan.title}\n              </h3>\n              <p className=\"text-muted-foreground mb-3 text-xs sm:text-sm\">\n                {isCustomNew\n                  ? \"Custom\"\n                  : `${chargeCurrency}${newPrice}/${billingCycle}`}\n              </p>\n              <div className=\"text-muted-foreground flex items-center gap-1 text-xs\">\n                <Calendar className=\"h-3 w-3 sm:h-4 sm:w-4\" />\n                Effective {effectiveDate}\n              </div>\n            </motion.div>\n          </div>\n\n          <Separator\n            className={cn(\n              theme === \"classic\" &&\n                \"via-border bg-gradient-to-r from-transparent to-transparent\",\n            )}\n          />\n\n          {/* Calculation Breakdown */}\n          <motion.div\n            initial={{ opacity: 0, y: 20 }}\n            animate={{ opacity: 1, y: 0 }}\n            transition={{ duration: 0.3, delay: 0.4 }}\n            className={cn(\n              \"rounded-lg border p-3 sm:p-4\",\n              theme === \"classic\"\n                ? \"from-muted/30 to-background/30 border-border/50 bg-gradient-to-br\"\n                : \"bg-muted/30 border-border\",\n            )}\n          >\n            <h4 className=\"mb-3 flex items-center gap-2 font-medium sm:mb-4\">\n              <CreditCard className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n              Billing Breakdown\n            </h4>\n\n            <div className=\"space-y-3\">\n              <div className=\"flex items-center justify-between text-xs sm:text-sm\">\n                <span className=\"text-muted-foreground\">\n                  Credit for unused time\n                </span>\n                <span className=\"font-medium text-green-600\">\n                  {canCompute\n                    ? `-${creditCurrency}${Math.abs(creditAmount).toFixed(2)}`\n                    : \"—\"}\n                </span>\n              </div>\n\n              <div className=\"flex items-center justify-between text-xs sm:text-sm\">\n                <span className=\"text-muted-foreground\">\n                  Prorated charge ({prorationDays} days)\n                </span>\n                <span className=\"font-medium\">\n                  {canCompute\n                    ? `+${chargeCurrency}${proratedCharge.toFixed(2)}`\n                    : \"—\"}\n                </span>\n              </div>\n\n              <Separator className=\"my-2\" />\n\n              <div className=\"flex items-center justify-between font-semibold\">\n                <span>\n                  {canCompute\n                    ? netAmount >= 0\n                      ? \"Amount to charge\"\n                      : \"Credit to account\"\n                    : \"Amount due will be calculated at checkout\"}\n                </span>\n                <span\n                  className={cn(\n                    \"text-base sm:text-lg\",\n                    canCompute\n                      ? netAmount >= 0\n                        ? \"text-foreground\"\n                        : \"text-green-600\"\n                      : \"text-muted-foreground\",\n                  )}\n                >\n                  {canCompute\n                    ? `${netAmount >= 0 ? \"+\" : \"\"}${chargeCurrency}${netAmount.toFixed(2)}`\n                    : \"—\"}\n                </span>\n              </div>\n            </div>\n          </motion.div>\n\n          {/* Timeline */}\n          <motion.div\n            initial={{ opacity: 0 }}\n            animate={{ opacity: 1 }}\n            transition={{ duration: 0.3, delay: 0.6 }}\n            className=\"bg-muted/20 border-border/50 rounded-lg border p-3 text-center sm:p-4\"\n          >\n            <p className=\"text-muted-foreground text-xs sm:text-sm\">\n              Your plan will change {effectiveDate}.\n              {isNextCycle\n                ? \" No immediate charge.\"\n                : hasComparablePrices\n                  ? netAmount >= 0\n                    ? ` You'll be charged ${chargeCurrency}${Math.abs(netAmount).toFixed(2)}.`\n                    : ` You'll receive a ${chargeCurrency}${Math.abs(netAmount).toFixed(2)} credit.`\n                  : \" Amount will be finalized at checkout.\"}\n            </p>\n          </motion.div>\n\n          {/* Action Buttons */}\n          <motion.div\n            initial={{ opacity: 0, y: 10 }}\n            animate={{ opacity: 1, y: 0 }}\n            transition={{ duration: 0.3, delay: 0.8 }}\n            className=\"flex flex-col gap-3 pt-3 sm:flex-row sm:pt-4\"\n          >\n            <Button\n              onClick={onConfirm}\n              className={cn(\n                \"flex-1\",\n                theme === \"classic\" &&\n                  \"from-primary to-primary/90 bg-gradient-to-r transition-all duration-200 hover:shadow-md active:scale-95\",\n              )}\n              size=\"lg\"\n            >\n              {confirmText}\n              <ArrowRight className=\"ml-2 h-4 w-4 sm:h-5 sm:w-5\" />\n            </Button>\n            <Button\n              variant=\"outline\"\n              onClick={onCancel}\n              className=\"flex-1\"\n              size=\"lg\"\n            >\n              {cancelText}\n            </Button>\n          </motion.div>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/billingsdk/proration-preview.tsx"
    },
    {
      "path": "src/registry/billingsdk/demo/proration-preview-demo.tsx",
      "content": "\"use client\";\n\nimport { ProrationPreview } from \"@/components/billingsdk/proration-preview\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\n\nconst currentPlan = {\n  plan: {\n    id: \"pro\",\n    title: \"Pro\",\n    description: \"Best for small teams\",\n    monthlyPrice: \"29.99\",\n    yearlyPrice: \"299.99\",\n    currency: \"$\",\n    buttonText: \"Current Plan\",\n    features: [\n      { name: \"Advanced features\", icon: \"check\" },\n      { name: \"Priority support\", icon: \"check\" },\n    ],\n  },\n  type: \"monthly\" as const,\n  price: \"29.99\",\n  nextBillingDate: \"2024-01-15\",\n  paymentMethod: \"•••• 4242\",\n  status: \"active\" as const,\n};\n\nconst yearlyCurrentPlan = {\n  plan: {\n    id: \"pro-yearly\",\n    title: \"Pro\",\n    description: \"Best for small teams\",\n    monthlyPrice: \"29.99\",\n    yearlyPrice: \"299.99\",\n    currency: \"$\",\n    buttonText: \"Current Plan\",\n    features: [\n      { name: \"Advanced features\", icon: \"check\" },\n      { name: \"Priority support\", icon: \"check\" },\n    ],\n  },\n  type: \"yearly\" as const,\n  price: \"299.99\",\n  nextBillingDate: \"2024-12-15\",\n  paymentMethod: \"•••• 4242\",\n  status: \"active\" as const,\n};\n\nconst basicPlan = {\n  id: \"basic\",\n  title: \"Basic\",\n  description: \"Perfect for getting started\",\n  monthlyPrice: \"9.99\",\n  yearlyPrice: \"99.99\",\n  currency: \"$\",\n  buttonText: \"Downgrade\",\n  features: [\n    { name: \"Basic features\", icon: \"check\" },\n    { name: \"Email support\", icon: \"check\" },\n  ],\n};\n\nconst enterprisePlan = {\n  id: \"enterprise\",\n  title: \"Enterprise\",\n  description: \"For large organizations\",\n  monthlyPrice: \"99.99\",\n  yearlyPrice: \"999.99\",\n  currency: \"$\",\n  buttonText: \"Upgrade\",\n  features: [\n    { name: \"All features\", icon: \"check\" },\n    { name: \"Priority support\", icon: \"check\" },\n    { name: \"Custom integrations\", icon: \"check\" },\n  ],\n};\n\nconst customPlan = {\n  id: \"custom\",\n  title: \"Custom\",\n  description: \"Tailored for your needs\",\n  monthlyPrice: \"Custom\",\n  yearlyPrice: \"Custom\",\n  currency: \"$\",\n  buttonText: \"Contact Sales\",\n  features: [\n    { name: \"Custom features\", icon: \"check\" },\n    { name: \"Dedicated support\", icon: \"check\" },\n  ],\n};\n\nexport function ProrationPreviewDemo() {\n  return (\n    <div className=\"space-y-8\">\n      <Tabs defaultValue=\"upgrade\" className=\"w-full\">\n        <TabsList className=\"grid w-full grid-cols-4\">\n          <TabsTrigger value=\"upgrade\">Upgrade</TabsTrigger>\n          <TabsTrigger value=\"downgrade\">Downgrade</TabsTrigger>\n          <TabsTrigger value=\"cycle-change\">Cycle Change</TabsTrigger>\n          <TabsTrigger value=\"next-cycle\">Next Cycle</TabsTrigger>\n        </TabsList>\n\n        <TabsContent value=\"upgrade\" className=\"space-y-6\">\n          <Card>\n            <CardHeader>\n              <CardTitle>Monthly to Enterprise Upgrade</CardTitle>\n              <CardDescription>\n                Upgrading from Pro monthly to Enterprise monthly with 15 days\n                remaining\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={currentPlan}\n                newPlan={enterprisePlan}\n                billingCycle=\"monthly\"\n                daysRemaining={15}\n                effectiveDate=\"immediately\"\n                theme=\"minimal\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n        </TabsContent>\n\n        <TabsContent value=\"downgrade\" className=\"space-y-6\">\n          <Card>\n            <CardHeader>\n              <CardTitle>Enterprise to Basic Downgrade</CardTitle>\n              <CardDescription>\n                Downgrading from Enterprise to Basic with account credit\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={{\n                  plan: enterprisePlan,\n                  type: \"monthly\",\n                  price: \"99.99\",\n                  nextBillingDate: \"2024-01-15\",\n                  paymentMethod: \"•••• 4242\",\n                  status: \"active\",\n                }}\n                newPlan={basicPlan}\n                billingCycle=\"monthly\"\n                daysRemaining={20}\n                effectiveDate=\"immediately\"\n                theme=\"minimal\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n        </TabsContent>\n\n        <TabsContent value=\"cycle-change\" className=\"space-y-6\">\n          <Card>\n            <CardHeader>\n              <CardTitle>Monthly to Yearly Switch</CardTitle>\n              <CardDescription>\n                Switching from monthly to yearly billing for the same plan\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={currentPlan}\n                newPlan={currentPlan.plan}\n                billingCycle=\"yearly\"\n                daysRemaining={10}\n                effectiveDate=\"immediately\"\n                theme=\"minimal\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n\n          <Card>\n            <CardHeader>\n              <CardTitle>Yearly to Monthly Switch</CardTitle>\n              <CardDescription>\n                Switching from yearly to monthly billing\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={yearlyCurrentPlan}\n                newPlan={yearlyCurrentPlan.plan}\n                billingCycle=\"monthly\"\n                daysRemaining={120}\n                effectiveDate=\"immediately\"\n                theme=\"classic\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n        </TabsContent>\n\n        <TabsContent value=\"next-cycle\" className=\"space-y-6\">\n          <Card>\n            <CardHeader>\n              <CardTitle>Next Cycle Change</CardTitle>\n              <CardDescription>\n                Plan change effective at the next billing cycle with no\n                immediate charge\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={currentPlan}\n                newPlan={enterprisePlan}\n                billingCycle=\"monthly\"\n                daysRemaining={25}\n                effectiveDate=\"next billing cycle\"\n                theme=\"minimal\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n\n          <Card>\n            <CardHeader>\n              <CardTitle>Custom Pricing Scenario</CardTitle>\n              <CardDescription>\n                Handling custom/enterprise pricing that doesn't follow standard\n                rates\n              </CardDescription>\n            </CardHeader>\n            <CardContent>\n              <ProrationPreview\n                currentPlan={currentPlan}\n                newPlan={customPlan}\n                billingCycle=\"monthly\"\n                daysRemaining={12}\n                effectiveDate=\"next billing cycle\"\n                theme=\"classic\"\n                onConfirm={() => {}}\n                onCancel={() => {}}\n              />\n            </CardContent>\n          </Card>\n        </TabsContent>\n      </Tabs>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/proration-preview-demo.tsx"
    },
    {
      "path": "src/registry/lib/billingsdk-config.ts",
      "content": "export interface Plan {\n  id: string;\n  title: string;\n  description: string;\n  highlight?: boolean;\n  type?: \"monthly\" | \"yearly\";\n  currency?: string;\n  monthlyPrice: string;\n  yearlyPrice: string;\n  buttonText: string;\n  badge?: string;\n  features: {\n    name: string;\n    icon: string;\n    iconColor?: string;\n  }[];\n}\n\nexport interface CurrentPlan {\n  plan: Plan;\n  type: \"monthly\" | \"yearly\" | \"custom\";\n  price?: string;\n  nextBillingDate: string;\n  paymentMethod: string;\n  status: \"active\" | \"inactive\" | \"past_due\" | \"cancelled\";\n}\n\nexport const plans: Plan[] = [\n  {\n    id: \"starter\",\n    title: \"Starter\",\n    description: \"For developers testing out Liveblocks locally.\",\n    currency: \"$\",\n    monthlyPrice: \"0\",\n    yearlyPrice: \"0\",\n    buttonText: \"Start today for free\",\n    features: [\n      {\n        name: \"Presence\",\n        icon: \"check\",\n        iconColor: \"text-green-500\",\n      },\n      {\n        name: \"Comments\",\n        icon: \"check\",\n        iconColor: \"text-orange-500\",\n      },\n      {\n        name: \"Notifications\",\n        icon: \"check\",\n        iconColor: \"text-teal-500\",\n      },\n      {\n        name: \"Text Editor\",\n        icon: \"check\",\n        iconColor: \"text-blue-500\",\n      },\n      {\n        name: \"Sync Datastore\",\n        icon: \"check\",\n        iconColor: \"text-zinc-500\",\n      },\n    ],\n  },\n  {\n    id: \"pro\",\n    title: \"Pro\",\n    description: \"For companies adding collaboration in production.\",\n    currency: \"$\",\n    monthlyPrice: \"20\",\n    yearlyPrice: \"199\",\n    buttonText: \"Sign up\",\n    badge: \"Most popular\",\n    highlight: true,\n    features: [\n      {\n        name: \"Presence\",\n        icon: \"check\",\n        iconColor: \"text-green-500\",\n      },\n      {\n        name: \"Comments\",\n        icon: \"check\",\n        iconColor: \"text-orange-500\",\n      },\n      {\n        name: \"Notifications\",\n        icon: \"check\",\n        iconColor: \"text-teal-500\",\n      },\n      {\n        name: \"Text Editor\",\n        icon: \"check\",\n        iconColor: \"text-blue-500\",\n      },\n      {\n        name: \"Sync Datastore\",\n        icon: \"check\",\n        iconColor: \"text-zinc-500\",\n      },\n    ],\n  },\n  {\n    id: \"enterprise\",\n    title: \"Enterprise\",\n    description:\n      \"For organizations that need more support and compliance features.\",\n    currency: \"$\",\n    monthlyPrice: \"Custom\",\n    yearlyPrice: \"Custom\",\n    buttonText: \"Contact sales\",\n    features: [\n      {\n        name: \"Presence\",\n        icon: \"check\",\n        iconColor: \"text-green-500\",\n      },\n      {\n        name: \"Comments\",\n        icon: \"check\",\n        iconColor: \"text-orange-500\",\n      },\n      {\n        name: \"Notifications\",\n        icon: \"check\",\n        iconColor: \"text-teal-500\",\n      },\n      {\n        name: \"Text Editor\",\n        icon: \"check\",\n        iconColor: \"text-blue-500\",\n      },\n      {\n        name: \"Sync Datastore\",\n        icon: \"check\",\n        iconColor: \"text-zinc-500\",\n      },\n    ],\n  },\n];\n",
      "type": "registry:lib",
      "target": "lib/billingsdk-config.ts"
    }
  ],
  "type": "registry:block"
}
