{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pricing-table-five",
  "title": "Pricing Table Five",
  "description": "A modern pricing table component with contact us plan",
  "dependencies": ["lucide-react", "class-variance-authority", "motion"],
  "registryDependencies": [
    "button",
    "card",
    "badge",
    "radio-group",
    "label",
    "utils"
  ],
  "files": [
    {
      "path": "src/registry/billingsdk/pricing-table-five.tsx",
      "content": "\"use client\";\n\nimport { useState, useId } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Label } from \"@/components/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/components/ui/radio-group\";\nimport { Check, Phone } from \"lucide-react\";\nimport { type Plan } from \"@/lib/billingsdk-config\";\nimport { cn } from \"@/lib/utils\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { AnimatePresence, motion } from \"motion/react\";\n\nconst sectionVariants = cva(\"py-32 relative overflow-hidden\", {\n  variants: {\n    size: {\n      small: \"py-12\",\n      medium: \"py-20\",\n      large: \"py-32\",\n    },\n    theme: {\n      minimal: \"bg-background\",\n      classic: \"bg-gradient-to-b from-background to-muted/20\",\n    },\n  },\n  defaultVariants: {\n    size: \"medium\",\n    theme: \"minimal\",\n  },\n});\n\nconst titleVariants = cva(\"font-bold mb-4 text-foreground\", {\n  variants: {\n    size: {\n      small: \"text-3xl lg:text-4xl\",\n      medium: \"text-4xl lg:text-5xl\",\n      large: \"text-4xl lg:text-6xl\",\n    },\n    theme: {\n      minimal: \"\",\n      classic:\n        \"bg-gradient-to-r from-foreground to-muted-foreground bg-clip-text text-transparent\",\n    },\n  },\n  defaultVariants: {\n    size: \"medium\",\n    theme: \"minimal\",\n  },\n});\n\nconst descriptionVariants = cva(\n  \"text-muted-foreground max-w-3xl mx-auto mb-8\",\n  {\n    variants: {\n      size: {\n        small: \"text-base lg:text-lg\",\n        medium: \"text-lg lg:text-xl\",\n        large: \"lg:text-xl\",\n      },\n    },\n    defaultVariants: {\n      size: \"medium\",\n    },\n  },\n);\n\nconst toggleVariants = cva(\n  \"flex h-11 w-fit shrink-0 items-center rounded-md p-1 text-lg\",\n  {\n    variants: {\n      theme: {\n        minimal: \"bg-muted\",\n        classic:\n          \"bg-muted/50 backdrop-blur-sm border border-border/50 shadow-lg\",\n      },\n    },\n    defaultVariants: {\n      theme: \"minimal\",\n    },\n  },\n);\n\nconst planCardVariants = cva(\n  \"relative border transition-all duration-300 rounded-lg\",\n  {\n    variants: {\n      size: {\n        small: \"p-4\",\n        medium: \"p-5\",\n        large: \"p-6\",\n      },\n      theme: {\n        minimal: \"bg-card border-border hover:bg-muted/30 shadow-sm\",\n        classic:\n          \"bg-card border-border/50 hover:shadow-xl hover:border-border backdrop-blur-sm shadow-md\",\n      },\n      highlight: {\n        true: \"\",\n        false: \"\",\n      },\n    },\n    compoundVariants: [\n      {\n        theme: \"classic\",\n        highlight: true,\n        className:\n          \"ring-1 ring-primary/20 border-primary/30 bg-gradient-to-b from-primary/5 to-card shadow-lg\",\n      },\n      {\n        theme: \"minimal\",\n        highlight: true,\n        className: \"bg-muted/50 border-primary/20 shadow-md\",\n      },\n    ],\n    defaultVariants: {\n      size: \"large\",\n      theme: \"minimal\",\n      highlight: false,\n    },\n  },\n);\n\nconst contactCardVariants = cva(\n  \"border transition-all duration-300 h-full rounded-lg\",\n  {\n    variants: {\n      size: {\n        small: \"p-6\",\n        medium: \"p-7\",\n        large: \"p-8\",\n      },\n      theme: {\n        minimal: \"bg-muted/50 border-border hover:bg-muted/70 shadow-sm\",\n        classic:\n          \"bg-card border-border/50 hover:shadow-xl hover:border-primary/20 backdrop-blur-sm shadow-md\",\n      },\n    },\n    defaultVariants: {\n      size: \"large\",\n      theme: \"minimal\",\n    },\n  },\n);\n\nconst priceTextVariants = cva(\"font-bold\", {\n  variants: {\n    size: {\n      small: \"text-3xl\",\n      medium: \"text-4xl\",\n      large: \"text-4xl\",\n    },\n    theme: {\n      minimal: \"text-foreground\",\n      classic:\n        \"font-extrabold bg-gradient-to-r from-foreground to-muted-foreground bg-clip-text text-transparent\",\n    },\n  },\n  defaultVariants: {\n    size: \"large\",\n    theme: \"minimal\",\n  },\n});\n\nconst featureIconVariants = cva(\"flex-none\", {\n  variants: {\n    size: {\n      small: \"w-3 h-3\",\n      medium: \"w-4 h-4\",\n      large: \"w-4 h-4\",\n    },\n    theme: {\n      minimal: \"text-primary\",\n      classic: \"text-emerald-500\",\n    },\n  },\n  defaultVariants: {\n    size: \"large\",\n    theme: \"minimal\",\n  },\n});\n\nexport interface PricingTableFiveProps extends VariantProps<\n  typeof sectionVariants\n> {\n  plans: Plan[];\n  title?: string;\n  description?: string;\n  onPlanSelect?: (planId: string) => void;\n  className?: string;\n}\n\nexport function PricingTableFive({\n  plans,\n  title = \"Pricing Plans\",\n  description = \"Choose the plan that's right for you\",\n  onPlanSelect,\n  className,\n  size = \"medium\",\n  theme = \"minimal\",\n}: PricingTableFiveProps) {\n  const [isAnnually, setIsAnnually] = useState(false);\n  const uniqueId = useId();\n\n  function calculateDiscount(\n    monthlyPrice: string,\n    yearlyPrice: string,\n  ): number {\n    const monthly = parseFloat(monthlyPrice);\n    const yearly = parseFloat(yearlyPrice);\n\n    if (\n      monthlyPrice.toLowerCase() === \"custom\" ||\n      yearlyPrice.toLowerCase() === \"custom\" ||\n      isNaN(monthly) ||\n      isNaN(yearly) ||\n      monthly === 0\n    ) {\n      return 0;\n    }\n\n    const discount = ((monthly * 12 - yearly) / (monthly * 12)) * 100;\n    return Math.round(discount);\n  }\n\n  const yearlyPriceDiscount = plans.length\n    ? Math.max(\n        ...plans.map((plan) =>\n          calculateDiscount(plan.monthlyPrice, plan.yearlyPrice),\n        ),\n      )\n    : 0;\n\n  const regularPlans = plans.slice(0, -1);\n  const contactUsPlan = plans[plans.length - 1];\n\n  return (\n    <section className={cn(sectionVariants({ size, theme }), className)}>\n      {/* Classic theme background elements */}\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-96 w-96 -translate-x-1/2 -translate-y-1/2 rounded-full blur-3xl\" />\n          <div className=\"bg-secondary/5 absolute top-1/4 right-1/4 h-64 w-64 rounded-full blur-2xl\" />\n        </>\n      )}\n\n      <div className=\"relative container mx-auto max-w-7xl\">\n        {/* Header */}\n        <div className=\"mb-12 pb-1 text-center\">\n          <h2 className={cn(titleVariants({ size, theme }), \"leading-[1.12]\")}>\n            {title}\n          </h2>\n          <p className={cn(descriptionVariants({ size }))}>{description}</p>\n\n          {/* Billing Toggle */}\n          <div\n            className={cn(\n              \"mx-auto mt-8 flex justify-center\",\n              toggleVariants({ theme }),\n            )}\n          >\n            <RadioGroup\n              defaultValue=\"monthly\"\n              className=\"h-full grid-cols-2\"\n              onValueChange={(value) => {\n                setIsAnnually(value === \"annually\");\n              }}\n            >\n              <div className='has-[button[data-state=\"checked\"]]:bg-background h-full rounded-md transition-all'>\n                <RadioGroupItem\n                  value=\"monthly\"\n                  id={`${uniqueId}-monthly`}\n                  className=\"peer sr-only\"\n                />\n                <Label\n                  htmlFor={`${uniqueId}-monthly`}\n                  className=\"text-muted-foreground peer-data-[state=checked]:text-primary hover:text-foreground flex h-full cursor-pointer items-center justify-center px-2 font-semibold transition-all md:px-7\"\n                >\n                  Monthly\n                </Label>\n              </div>\n              <div className='has-[button[data-state=\"checked\"]]:bg-background h-full rounded-md transition-all'>\n                <RadioGroupItem\n                  value=\"annually\"\n                  id={`${uniqueId}-annually`}\n                  className=\"peer sr-only\"\n                />\n                <Label\n                  htmlFor={`${uniqueId}-annually`}\n                  className=\"text-muted-foreground peer-data-[state=checked]:text-primary hover:text-foreground flex h-full cursor-pointer items-center justify-center gap-1 px-2 font-semibold transition-all md:px-7\"\n                >\n                  Annually\n                  {yearlyPriceDiscount > 0 && (\n                    <span className=\"bg-primary/10 text-primary border-primary/20 ml-1 rounded border px-2 py-0.5 text-xs font-medium\">\n                      Save {yearlyPriceDiscount}%\n                    </span>\n                  )}\n                </Label>\n              </div>\n            </RadioGroup>\n          </div>\n        </div>\n\n        {/* Plans Layout */}\n        <div className=\"flex flex-col gap-6 lg:flex-row\">\n          {/* Regular Plans */}\n          <div className=\"flex flex-col gap-4 lg:w-2/3\">\n            {regularPlans.map((plan, index) => (\n              <motion.div\n                key={plan.id}\n                initial={{ opacity: 0, y: 20 }}\n                animate={{ opacity: 1, y: 0 }}\n                transition={{ duration: 0.4, delay: index * 0.1 }}\n              >\n                <Card\n                  className={cn(\n                    planCardVariants({\n                      size,\n                      theme,\n                      highlight: plan.highlight,\n                    }),\n                  )}\n                >\n                  {plan.badge && (\n                    <Badge\n                      className={cn(\n                        \"absolute -top-3 left-1/2 z-10 -translate-x-1/2 transform\",\n                        theme === \"classic\"\n                          ? \"from-primary to-primary/80 text-primary-foreground border-primary/20 bg-gradient-to-r shadow-lg\"\n                          : \"bg-primary text-primary-foreground\",\n                      )}\n                    >\n                      {plan.badge}\n                    </Badge>\n                  )}\n\n                  {theme === \"classic\" && plan.highlight && (\n                    <div className=\"via-primary absolute -top-px left-1/2 h-px w-32 -translate-x-1/2 bg-gradient-to-r from-transparent to-transparent\" />\n                  )}\n\n                  <CardContent className=\"flex flex-col gap-6 p-0 md:flex-row md:items-center md:justify-between\">\n                    {/* Plan Info and Price */}\n                    <div className=\"flex min-w-[200px] flex-col gap-3\">\n                      <Badge\n                        variant=\"outline\"\n                        className=\"w-fit text-xs font-medium uppercase\"\n                      >\n                        {plan.title}\n                      </Badge>\n\n                      <AnimatePresence mode=\"wait\">\n                        <motion.div\n                          key={isAnnually ? \"year\" : \"month\"}\n                          initial={{ opacity: 0, y: 10 }}\n                          animate={{ opacity: 1, y: 0 }}\n                          exit={{ opacity: 0, y: -10 }}\n                          transition={{ duration: 0.2 }}\n                          className=\"flex items-baseline gap-1\"\n                        >\n                          <span\n                            className={cn(priceTextVariants({ size, theme }))}\n                          >\n                            {parseFloat(\n                              isAnnually ? plan.yearlyPrice : plan.monthlyPrice,\n                            ) >= 0 && <>{plan.currency}</>}\n                            {isAnnually ? plan.yearlyPrice : plan.monthlyPrice}\n                          </span>\n                          <span className=\"text-muted-foreground text-sm\">\n                            /{isAnnually ? \"year\" : \"month\"}\n                          </span>\n                        </motion.div>\n                      </AnimatePresence>\n\n                      <Button\n                        onClick={() => onPlanSelect?.(plan.id)}\n                        className={cn(\n                          \"w-full md:w-auto\",\n                          plan.highlight &&\n                            theme === \"minimal\" &&\n                            \"hover:bg-primary/90 group bg-primary text-primary-foreground ring-primary before:from-primary-foreground/20 after:from-primary-foreground/10 relative isolate inline-flex h-9 items-center justify-center overflow-hidden rounded-md px-6 py-2 text-left text-sm font-medium shadow ring-1 before:pointer-events-none before:absolute before:inset-0 before:-z-10 before:rounded-md before:bg-gradient-to-b before:opacity-80 before:transition-opacity before:duration-300 before:ease-[cubic-bezier(0.4,0.36,0,1)] after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:rounded-md after:bg-gradient-to-b after:to-transparent after:mix-blend-overlay hover:cursor-pointer\",\n                        )}\n                        variant={plan.highlight ? \"default\" : \"secondary\"}\n                      >\n                        {plan.buttonText}\n                      </Button>\n                    </div>\n\n                    {/* Features */}\n                    <div className=\"grid flex-1 gap-3 md:grid-cols-2\">\n                      {plan.features.map((feature, featureIndex) => (\n                        <motion.div\n                          key={featureIndex}\n                          className=\"flex items-start gap-2\"\n                          initial={{ opacity: 0, x: -10 }}\n                          animate={{ opacity: 1, x: 0 }}\n                          transition={{\n                            duration: 0.3,\n                            delay: featureIndex * 0.05,\n                          }}\n                        >\n                          <Check\n                            className={cn(\n                              featureIconVariants({ size, theme }),\n                              \"mt-0.5\",\n                            )}\n                          />\n                          <span\n                            className={cn(\n                              \"text-sm\",\n                              theme === \"classic\"\n                                ? \"text-foreground/90\"\n                                : \"text-muted-foreground\",\n                            )}\n                          >\n                            {feature.name}\n                          </span>\n                        </motion.div>\n                      ))}\n                    </div>\n                  </CardContent>\n                </Card>\n              </motion.div>\n            ))}\n          </div>\n\n          {/* Contact Card */}\n          <motion.div\n            className=\"lg:w-1/3\"\n            initial={{ opacity: 0, y: 20 }}\n            animate={{ opacity: 1, y: 0 }}\n            transition={{ duration: 0.4, delay: regularPlans.length * 0.1 }}\n          >\n            <Card\n              className={cn(contactCardVariants({ size, theme }), \"rounded-lg\")}\n            >\n              <CardContent className=\"flex flex-col items-center space-y-6 p-0 text-center\">\n                <div className=\"bg-primary/10 flex h-16 w-16 items-center justify-center rounded-full\">\n                  <Phone className=\"text-primary h-8 w-8\" />\n                </div>\n\n                <div>\n                  <h3\n                    className={cn(\n                      \"mb-2 text-2xl font-bold\",\n                      theme === \"classic\" &&\n                        \"from-foreground to-muted-foreground bg-gradient-to-r bg-clip-text text-transparent\",\n                    )}\n                  >\n                    {contactUsPlan.title}\n                  </h3>\n                  <p className=\"text-muted-foreground text-sm leading-relaxed\">\n                    {contactUsPlan.description}\n                  </p>\n                </div>\n\n                <Button\n                  onClick={() => onPlanSelect?.(contactUsPlan.id)}\n                  variant=\"outline\"\n                  className=\"hover:bg-primary w-full transition-colors\"\n                >\n                  {contactUsPlan.buttonText}\n                </Button>\n\n                <p className=\"text-muted-foreground text-xs\">\n                  Custom pricing and solutions available\n                </p>\n              </CardContent>\n            </Card>\n          </motion.div>\n        </div>\n      </div>\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/billingsdk/pricing-table-five.tsx"
    },
    {
      "path": "src/registry/billingsdk/demo/pricing-table-five-demo.tsx",
      "content": "\"use client\";\n\nimport { PricingTableFive } from \"@/components/billingsdk/pricing-table-five\";\nimport { plans } from \"@/lib/billingsdk-config\";\n\nexport function PricingTableFiveDemo() {\n  return (\n    <PricingTableFive\n      plans={plans}\n      theme=\"classic\"\n      onPlanSelect={(planId: string) => console.log(\"Selected plan:\", planId)}\n      title=\"Budget-friendly pricing alternatives\"\n      description=\"Get started free or upgrade to share your impact for all completed tasks with multiple people\"\n    />\n  );\n}\n",
      "type": "registry:component",
      "target": "components/pricing-table-five-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"
}
