{
  "name": "billing-plan-selector",
  "title": "BillingPlanSelector",
  "description": "Subscription / billing-plan picker — surfaces eligible plans with pricing and trial periods.",
  "type": "component",
  "registryDependencies": [
    "price",
    "cn"
  ],
  "files": [
    {
      "path": "billing-plan-selector.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport type { ProductBillingPlan, BillingFrequency } from \"@cimplify/sdk\";\nimport type { CurrencyCode } from \"@cimplify/sdk\";\nimport { useBillingPlans } from \"./hooks/use-billing-plans\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface BillingPlanSelectorClassNames {\n  root?: string;\n  plan?: string;\n  activePlan?: string;\n  frequency?: string;\n  price?: string;\n  setupFee?: string;\n  trialBadge?: string;\n  empty?: string;\n  loading?: string;\n}\n\nexport interface BillingPlanSelectorProps {\n  /** Product ID to fetch billing plans for. */\n  productId: string;\n  /** Override plans (skips fetch). For SSR, pass pre-fetched plans. */\n  plans?: ProductBillingPlan[];\n  /** Called when a plan is selected. */\n  onPlanSelect?: (plan: ProductBillingPlan | null) => void;\n  /** Currently selected plan ID. */\n  selectedPlanId?: string | null;\n  /** Currency the plan amounts are denominated in. */\n  currency?: CurrencyCode;\n  /** Show a \"One-time purchase\" option at the top. */\n  showOneTimePurchase?: boolean;\n  /** Label for the one-time purchase option. Default: \"One-time purchase\". */\n  oneTimePurchaseLabel?: string;\n  /** Custom plan card renderer. */\n  renderPlan?: (plan: ProductBillingPlan, isActive: boolean) => React.ReactNode;\n  className?: string;\n  classNames?: BillingPlanSelectorClassNames;\n}\n\nconst FREQUENCY_LABELS: Record<BillingFrequency, string> = {\n  weekly: \"Weekly\",\n  biweekly: \"Biweekly\",\n  monthly: \"Monthly\",\n  quarterly: \"Quarterly\",\n  annually: \"Annually\",\n};\n\nfunction formatMarkup(plan: ProductBillingPlan): string | null {\n  if (!plan.markup_type || plan.markup_amount == null) return null;\n  if (plan.markup_type === \"percentage\") return `+${plan.markup_amount}%`;\n  return null;\n}\n\n/**\n * BillingPlanSelector — subscription/installment plan comparison and selection.\n *\n * Renders plan cards with frequency, markup, trial, and setup fee details.\n * Returns `null` when no plans are available (and one-time purchase is hidden).\n */\nexport function BillingPlanSelector({\n  productId,\n  plans: plansProp,\n  currency,\n  onPlanSelect,\n  selectedPlanId,\n  showOneTimePurchase = false,\n  oneTimePurchaseLabel = \"One-time purchase\",\n  renderPlan,\n  className,\n  classNames,\n}: BillingPlanSelectorProps): React.ReactElement | null {\n  const { plans: fetched, isLoading } = useBillingPlans(productId, {\n    enabled: plansProp === undefined,\n  });\n\n  const plans = plansProp ?? fetched;\n\n  if (isLoading && plans.length === 0) {\n    return (\n      <div\n        data-cimplify-billing-plan-selector\n        aria-busy=\"true\"\n        className={cn(className, classNames?.root, classNames?.loading)}\n      />\n    );\n  }\n\n  if (plans.length === 0 && !showOneTimePurchase) {\n    return null;\n  }\n\n  const isOneTimePurchaseSelected = selectedPlanId === null;\n\n  return (\n    <div data-cimplify-billing-plan-selector className={cn(className, classNames?.root)}>\n      {showOneTimePurchase && (\n        <button\n          type=\"button\"\n          onClick={() => onPlanSelect?.(null)}\n          data-cimplify-billing-plan\n          data-plan-type=\"one-time\"\n          data-active={isOneTimePurchaseSelected || undefined}\n          aria-pressed={isOneTimePurchaseSelected}\n          className={cn(\n            classNames?.plan,\n            isOneTimePurchaseSelected && classNames?.activePlan,\n          )}\n        >\n          <span data-cimplify-billing-frequency className={classNames?.frequency}>\n            {oneTimePurchaseLabel}\n          </span>\n        </button>\n      )}\n\n      {plans.map((plan) => {\n        const isActive = selectedPlanId === plan.id;\n        const markup = formatMarkup(plan);\n\n        return (\n          <button\n            key={plan.id}\n            type=\"button\"\n            onClick={() => onPlanSelect?.(plan)}\n            data-cimplify-billing-plan\n            data-plan-type={plan.plan_type}\n            data-active={isActive || undefined}\n            aria-pressed={isActive}\n            className={cn(classNames?.plan, isActive && classNames?.activePlan)}\n          >\n            {renderPlan ? (\n              renderPlan(plan, isActive)\n            ) : (\n              <>\n                <span data-cimplify-billing-frequency className={classNames?.frequency}>\n                  {FREQUENCY_LABELS[plan.frequency]}\n                </span>\n\n                {markup && (\n                  <span data-cimplify-billing-markup className={classNames?.price}>\n                    {markup}\n                  </span>\n                )}\n\n                {plan.markup_type === \"fixed\" && plan.markup_amount != null && (\n                  <span data-cimplify-billing-markup className={classNames?.price}>\n                    +<Price amount={plan.markup_amount} currency={currency} />\n                  </span>\n                )}\n\n                {plan.trial_days > 0 && (\n                  <span data-cimplify-billing-trial className={classNames?.trialBadge}>\n                    {plan.trial_days}-day trial\n                  </span>\n                )}\n\n                {plan.setup_fee > 0 && (\n                  <span data-cimplify-billing-setup-fee className={classNames?.setupFee}>\n                    Setup fee: <Price amount={plan.setup_fee} currency={currency} />\n                  </span>\n                )}\n\n                {plan.plan_type === \"installment\" && plan.installment_periods != null && (\n                  <span data-cimplify-billing-periods>\n                    {plan.installment_periods} payments\n                  </span>\n                )}\n              </>\n            )}\n          </button>\n        );\n      })}\n    </div>\n  );\n}\n"
    }
  ]
}
