{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "plan-group",
  "type": "registry:ui",
  "title": "Plan Group",
  "description": "A container for displaying multiple pricing plans with a monthly/yearly toggle.",
  "files": [
    {
      "path": "src/registry/ui/plan-group.tsx",
      "content": "\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { PlanCardPrice } from \"./plan-card\";\n\nconst planGroupVariants = cva(\"w-full\", {\n  variants: {\n    layout: {\n      horizontal: \"grid gap-6\",\n      vertical: \"flex flex-col gap-6\",\n    },\n    columns: {\n      2: \"md:grid-cols-2\",\n      3: \"lg:grid-cols-3\",\n      4: \"lg:grid-cols-2 xl:grid-cols-4\",\n    },\n  },\n  defaultVariants: {\n    layout: \"horizontal\",\n    columns: 2,\n  },\n});\n\ntype BillingPeriod = \"month\" | \"year\";\n\ninterface PlanGroupContextValue {\n  period: BillingPeriod;\n  setPeriod: (period: BillingPeriod) => void;\n}\n\nconst PlanGroupContext = React.createContext<PlanGroupContextValue | null>(\n  null,\n);\n\nfunction usePlanGroup() {\n  const context = React.useContext(PlanGroupContext);\n  if (!context) {\n    throw new Error(\"usePlanGroup must be used within a PlanGroup\");\n  }\n  return context;\n}\n\ninterface PlanGroupProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof planGroupVariants> {\n  defaultPeriod?: BillingPeriod;\n  onPeriodChange?: (period: BillingPeriod) => void;\n}\n\nconst PlanGroup = React.forwardRef<HTMLDivElement, PlanGroupProps>(\n  (\n    {\n      className,\n      layout,\n      columns,\n      defaultPeriod = \"month\",\n      onPeriodChange,\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    const [period, setPeriodState] =\n      React.useState<BillingPeriod>(defaultPeriod);\n\n    const setPeriod = React.useCallback(\n      (newPeriod: BillingPeriod) => {\n        setPeriodState(newPeriod);\n        onPeriodChange?.(newPeriod);\n      },\n      [onPeriodChange],\n    );\n\n    return (\n      <PlanGroupContext.Provider value={{ period, setPeriod }}>\n        <div ref={ref} className={cn(\"space-y-8\", className)} {...props}>\n          {children}\n        </div>\n      </PlanGroupContext.Provider>\n    );\n  },\n);\nPlanGroup.displayName = \"PlanGroup\";\n\nconst PlanGroupHeader = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn(\"flex flex-col items-center gap-4 text-center\", className)}\n    {...props}\n  />\n));\nPlanGroupHeader.displayName = \"PlanGroupHeader\";\n\nconst PlanGroupTitle = React.forwardRef<\n  HTMLHeadingElement,\n  React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n  <h2\n    ref={ref}\n    className={cn(\"text-3xl font-bold tracking-tight\", className)}\n    {...props}\n  />\n));\nPlanGroupTitle.displayName = \"PlanGroupTitle\";\n\nconst PlanGroupDescription = React.forwardRef<\n  HTMLSpanElement,\n  React.HTMLAttributes<HTMLSpanElement>\n>(({ className, ...props }, ref) => (\n  <span\n    ref={ref}\n    className={cn(\"block text-muted-foreground max-w-2xl\", className)}\n    {...props}\n  />\n));\nPlanGroupDescription.displayName = \"PlanGroupDescription\";\n\ninterface PlanGroupToggleProps extends React.HTMLAttributes<HTMLDivElement> {\n  monthLabel?: string;\n  yearLabel?: string;\n  yearDiscount?: string;\n}\n\nconst PlanGroupToggle = React.forwardRef<HTMLDivElement, PlanGroupToggleProps>(\n  (\n    {\n      className,\n      monthLabel = \"Monthly\",\n      yearLabel = \"Yearly\",\n      yearDiscount,\n      ...props\n    },\n    ref,\n  ) => {\n    const { period, setPeriod } = usePlanGroup();\n\n    return (\n      <div\n        ref={ref}\n        className={cn(\n          \"inline-flex items-center gap-2 rounded-full border bg-muted p-1\",\n          className,\n        )}\n        {...props}\n      >\n        <button\n          type=\"button\"\n          onClick={() => setPeriod(\"month\")}\n          className={cn(\n            \"rounded-full px-4 py-2 text-sm font-medium transition-all\",\n            period === \"month\"\n              ? \"bg-background text-foreground shadow-sm\"\n              : \"text-muted-foreground hover:text-foreground\",\n          )}\n        >\n          {monthLabel}\n        </button>\n        <button\n          type=\"button\"\n          onClick={() => setPeriod(\"year\")}\n          className={cn(\n            \"inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all\",\n            period === \"year\"\n              ? \"bg-background text-foreground shadow-sm\"\n              : \"text-muted-foreground hover:text-foreground\",\n          )}\n        >\n          {yearLabel}\n          {yearDiscount && (\n            <span className=\"rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary\">\n              {yearDiscount}\n            </span>\n          )}\n        </button>\n      </div>\n    );\n  },\n);\nPlanGroupToggle.displayName = \"PlanGroupToggle\";\n\ninterface PlanGroupContentProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof planGroupVariants> {}\n\nconst PlanGroupContent = React.forwardRef<\n  HTMLDivElement,\n  PlanGroupContentProps\n>(({ className, layout, columns, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn(\n      planGroupVariants({ layout, columns }),\n      \"items-stretch\",\n      className,\n    )}\n    {...props}\n  />\n));\nPlanGroupContent.displayName = \"PlanGroupContent\";\n\ninterface PlanPriceProps\n  extends Omit<\n    React.ComponentPropsWithoutRef<typeof PlanCardPrice>,\n    \"amount\" | \"originalAmount\" | \"period\"\n  > {\n  monthlyAmount: number;\n  yearlyAmount: number;\n  originalMonthlyAmount?: number;\n  originalYearlyAmount?: number;\n}\n\nconst PlanPrice = React.forwardRef<HTMLDivElement, PlanPriceProps>(\n  (\n    {\n      monthlyAmount,\n      yearlyAmount,\n      originalMonthlyAmount,\n      originalYearlyAmount,\n      ...props\n    },\n    ref,\n  ) => {\n    const { period } = usePlanGroup();\n\n    const amount = period === \"month\" ? monthlyAmount : yearlyAmount;\n    const originalAmount =\n      period === \"month\" ? originalMonthlyAmount : originalYearlyAmount;\n\n    return (\n      <PlanCardPrice\n        ref={ref}\n        amount={amount}\n        originalAmount={originalAmount}\n        period={period}\n        {...props}\n      />\n    );\n  },\n);\nPlanPrice.displayName = \"PlanPrice\";\n\nexport {\n  PlanGroup,\n  PlanGroupHeader,\n  PlanGroupTitle,\n  PlanGroupDescription,\n  PlanGroupToggle,\n  PlanGroupContent,\n  PlanPrice,\n  usePlanGroup,\n  planGroupVariants,\n};\n\nexport type {\n  PlanGroupProps,\n  PlanGroupToggleProps,\n  PlanGroupContentProps,\n  PlanPriceProps,\n  BillingPeriod,\n};\n",
      "type": "registry:ui",
      "target": "components/ui/plan-group.tsx"
    },
    {
      "path": "src/registry/lib/utils.ts",
      "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n",
      "type": "registry:lib",
      "target": "lib/utils.ts"
    },
    {
      "path": "src/registry/ui/plan-card.tsx",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport { Check, X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nconst planCardVariants = cva(\n  \"relative rounded-2xl border bg-card text-card-foreground transition-all duration-200\",\n  {\n    variants: {\n      variant: {\n        default: \"border-border\",\n        highlighted:\n          \"border-primary shadow-lg shadow-primary/10 ring-1 ring-primary\",\n        compact: \"border-border p-4\",\n      },\n      size: {\n        default: \"p-6\",\n        lg: \"p-8\",\n      },\n      layout: {\n        vertical: \"flex flex-col min-w-[280px]\",\n        horizontal: \"flex flex-row items-center gap-6 w-full\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n      layout: \"vertical\",\n    },\n  },\n);\n\ninterface PlanCardProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof planCardVariants> {}\n\nconst PlanCard = React.forwardRef<HTMLDivElement, PlanCardProps>(\n  ({ className, variant, size, layout, ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(planCardVariants({ variant, size, layout, className }))}\n      {...props}\n    />\n  ),\n);\nPlanCard.displayName = \"PlanCard\";\n\nconst PlanCardHeader = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div ref={ref} className={cn(\"flex flex-col gap-2\", className)} {...props} />\n));\nPlanCardHeader.displayName = \"PlanCardHeader\";\n\ninterface PlanCardBadgeProps\n  extends React.ComponentPropsWithoutRef<typeof Badge> {}\n\nconst PlanCardBadge = React.forwardRef<HTMLDivElement, PlanCardBadgeProps>(\n  ({ className, ...props }, ref) => (\n    <Badge ref={ref} className={cn(\"w-fit\", className)} {...props} />\n  ),\n);\nPlanCardBadge.displayName = \"PlanCardBadge\";\n\nconst PlanCardTitle = React.forwardRef<\n  HTMLHeadingElement,\n  React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n  <h3\n    ref={ref}\n    className={cn(\"text-2xl font-bold tracking-tight\", className)}\n    {...props}\n  />\n));\nPlanCardTitle.displayName = \"PlanCardTitle\";\n\nconst PlanCardDescription = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n  <p\n    ref={ref}\n    className={cn(\"text-sm text-muted-foreground\", className)}\n    {...props}\n  />\n));\nPlanCardDescription.displayName = \"PlanCardDescription\";\n\ninterface PlanCardPriceProps extends React.HTMLAttributes<HTMLDivElement> {\n  amount: number;\n  currency?: string;\n  period?: \"month\" | \"year\" | \"once\";\n  originalAmount?: number;\n}\n\nconst PlanCardPrice = React.forwardRef<HTMLDivElement, PlanCardPriceProps>(\n  (\n    {\n      className,\n      amount,\n      currency = \"$\",\n      period = \"month\",\n      originalAmount,\n      ...props\n    },\n    ref,\n  ) => {\n    const periodLabel = {\n      month: \"/mo\",\n      year: \"/yr\",\n      once: \"\",\n    };\n\n    return (\n      <div\n        ref={ref}\n        className={cn(\"my-6 flex items-baseline gap-1\", className)}\n        {...props}\n      >\n        {originalAmount && (\n          <span className=\"text-lg text-muted-foreground line-through\">\n            {currency}\n            {originalAmount}\n          </span>\n        )}\n        <span className=\"text-4xl font-bold tracking-tight\">\n          {currency}\n          {amount}\n        </span>\n        {period !== \"once\" && (\n          <span className=\"text-muted-foreground\">{periodLabel[period]}</span>\n        )}\n      </div>\n    );\n  },\n);\nPlanCardPrice.displayName = \"PlanCardPrice\";\n\nconst PlanCardFeatures = React.forwardRef<\n  HTMLUListElement,\n  React.HTMLAttributes<HTMLUListElement>\n>(({ className, ...props }, ref) => (\n  <ul\n    ref={ref}\n    className={cn(\"flex flex-col gap-3 text-sm\", className)}\n    {...props}\n  />\n));\nPlanCardFeatures.displayName = \"PlanCardFeatures\";\n\ninterface PlanCardFeatureProps extends React.HTMLAttributes<HTMLLIElement> {\n  included?: boolean;\n}\n\nconst PlanCardFeature = React.forwardRef<HTMLLIElement, PlanCardFeatureProps>(\n  ({ className, included = true, children, ...props }, ref) => (\n    <li\n      ref={ref}\n      className={cn(\n        \"flex items-center gap-3\",\n        !included && \"text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    >\n      {included ? (\n        <Check className=\"h-4 w-4 shrink-0 text-primary\" />\n      ) : (\n        <X className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n      )}\n      <span>{children}</span>\n    </li>\n  ),\n);\nPlanCardFeature.displayName = \"PlanCardFeature\";\n\ninterface PlanCardActionProps\n  extends React.ComponentPropsWithoutRef<typeof Button> {}\n\nconst PlanCardAction = React.forwardRef<HTMLButtonElement, PlanCardActionProps>(\n  ({ className, ...props }, ref) => (\n    <Button ref={ref} className={cn(\"mt-6 w-full\", className)} {...props} />\n  ),\n);\nPlanCardAction.displayName = \"PlanCardAction\";\n\nexport {\n  PlanCard,\n  PlanCardHeader,\n  PlanCardBadge,\n  PlanCardTitle,\n  PlanCardDescription,\n  PlanCardPrice,\n  PlanCardFeatures,\n  PlanCardFeature,\n  PlanCardAction,\n  planCardVariants,\n};\n\nexport type {\n  PlanCardProps,\n  PlanCardBadgeProps,\n  PlanCardPriceProps,\n  PlanCardFeatureProps,\n  PlanCardActionProps,\n};\n",
      "type": "registry:ui",
      "target": "components/ui/plan-card.tsx"
    }
  ],
  "dependencies": [
    "class-variance-authority",
    "clsx",
    "tailwind-merge",
    "lucide-react"
  ],
  "registryDependencies": [
    "badge",
    "button"
  ]
}