{
  "name": "pricing-table",
  "type": "registry:component",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/saaskit/pricing-table.tsx",
      "content": "\"use client\";\n\nimport type * as React from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { Check, Minus, Zap } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\nfunction useSaaskitFont() {\n  useEffect(() => {\n    const id = \"__saaskit_font\";\n    if (typeof document === \"undefined\" || document.getElementById(id)) return;\n    const link = Object.assign(document.createElement(\"link\"), {\n      id,\n      rel: \"stylesheet\",\n      href: \"https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,100..900&display=swap\",\n    });\n    document.head.appendChild(link);\n  }, []);\n}\n\ntype Lang = \"en\" | \"fr\";\n\ninterface PricingFeature {\n  name: string;\n  free: boolean | string;\n  pro: boolean | string;\n  enterprise: boolean | string;\n}\n\ninterface PricingTableLabels {\n  monthly?: string;\n  annual?: string;\n  recommended?: string;\n  free?: string;\n  pro?: string;\n  enterprise?: string;\n  perMonth?: string;\n  startFree?: string;\n  upgradePro?: string;\n  contactSales?: string;\n  feature?: string;\n  billedAnnual?: (amount: string) => string;\n  descriptions?: { free?: string; pro?: string; enterprise?: string };\n}\n\nconst T: Record<Lang, Required<Omit<PricingTableLabels, \"descriptions\">> & { descriptions: Required<NonNullable<PricingTableLabels[\"descriptions\"]>> }> = {\n  en: {\n    monthly: \"Monthly\",\n    annual: \"Annual\",\n    recommended: \"Recommended\",\n    free: \"FREE\",\n    pro: \"PRO\",\n    enterprise: \"ENTERPRISE\",\n    perMonth: \"/month\",\n    startFree: \"Get started free\",\n    upgradePro: \"Upgrade to Pro\",\n    contactSales: \"Contact sales\",\n    feature: \"Feature\",\n    billedAnnual: (amount) => `Billed ${amount}/year`,\n    descriptions: {\n      free: \"For getting started.\",\n      pro: \"For growing teams.\",\n      enterprise: \"For large organizations.\",\n    },\n  },\n  fr: {\n    monthly: \"Mensuel\",\n    annual: \"Annuel\",\n    recommended: \"Recommandé\",\n    free: \"GRATUIT\",\n    pro: \"PRO\",\n    enterprise: \"ENTERPRISE\",\n    perMonth: \"/mois\",\n    startFree: \"Commencer gratuitement\",\n    upgradePro: \"Passer au Pro\",\n    contactSales: \"Contacter les ventes\",\n    feature: \"Fonctionnalité\",\n    billedAnnual: (amount) => `Facturé ${amount}/an`,\n    descriptions: {\n      free: \"Pour démarrer et tester.\",\n      pro: \"Pour les équipes en croissance.\",\n      enterprise: \"Pour les grandes organisations.\",\n    },\n  },\n};\n\ninterface PricingTableProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n  features?: PricingFeature[];\n  onSelectPlan?: (plan: \"free\" | \"pro\" | \"enterprise\", billing: \"monthly\" | \"annual\") => void;\n  lang?: Lang;\n  labels?: PricingTableLabels;\n}\n\nexport function PricingTable({ features, onSelectPlan, lang = \"en\", labels, className, ...rest }: PricingTableProps) {\n  useSaaskitFont();\n  const [billing, setBilling] = useState<\"monthly\" | \"annual\">(\"monthly\");\n\n  const base = T[lang];\n  const L = {\n    monthly: labels?.monthly ?? base.monthly,\n    annual: labels?.annual ?? base.annual,\n    recommended: labels?.recommended ?? base.recommended,\n    free: labels?.free ?? base.free,\n    pro: labels?.pro ?? base.pro,\n    enterprise: labels?.enterprise ?? base.enterprise,\n    perMonth: labels?.perMonth ?? base.perMonth,\n    startFree: labels?.startFree ?? base.startFree,\n    upgradePro: labels?.upgradePro ?? base.upgradePro,\n    contactSales: labels?.contactSales ?? base.contactSales,\n    feature: labels?.feature ?? base.feature,\n    billedAnnual: labels?.billedAnnual ?? base.billedAnnual,\n    descriptions: {\n      free: labels?.descriptions?.free ?? base.descriptions.free,\n      pro: labels?.descriptions?.pro ?? base.descriptions.pro,\n      enterprise: labels?.descriptions?.enterprise ?? base.descriptions.enterprise,\n    },\n  };\n\n  const unlimited = lang === \"fr\" ? \"Illimité\" : \"Unlimited\";\n  const defaultFeatures: PricingFeature[] = [\n    { name: lang === \"fr\" ? \"Projets actifs\" : \"Active projects\", free: \"3\", pro: unlimited, enterprise: unlimited },\n    { name: lang === \"fr\" ? \"Membres d'équipe\" : \"Team members\", free: \"1\", pro: \"10\", enterprise: unlimited },\n    { name: lang === \"fr\" ? \"Appels API / mois\" : \"API calls / month\", free: \"10,000\", pro: \"500,000\", enterprise: unlimited },\n    { name: lang === \"fr\" ? \"Stockage\" : \"Storage\", free: \"1 GB\", pro: \"50 GB\", enterprise: \"500 GB\" },\n    { name: lang === \"fr\" ? \"Support prioritaire\" : \"Priority support\", free: false, pro: true, enterprise: true },\n    { name: \"SSO / SAML\", free: false, pro: false, enterprise: true },\n    { name: lang === \"fr\" ? \"Audit logs\" : \"Audit logs\", free: false, pro: true, enterprise: true },\n    { name: lang === \"fr\" ? \"SLA garanti\" : \"Guaranteed SLA\", free: false, pro: false, enterprise: true },\n  ];\n\n  const displayFeatures = features ?? defaultFeatures;\n\n  const prices = {\n    free: { monthly: 0, annual: 0 },\n    pro: { monthly: 29, annual: 23 },\n    enterprise: { monthly: 99, annual: 79 },\n  };\n\n  return (\n    <div className={cn(\"w-full\", className)} {...rest}>\n      {/* Billing toggle */}\n      <div className=\"flex items-center justify-center gap-3 mb-8\">\n        <button\n          onClick={() => setBilling(\"monthly\")}\n          className={cn(\n            \"text-sm font-medium transition-colors\",\n            billing === \"monthly\" ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n          )}\n        >\n          {L.monthly}\n        </button>\n        <button\n          onClick={() => setBilling(billing === \"monthly\" ? \"annual\" : \"monthly\")}\n          className={cn(\n            \"relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n            billing === \"annual\" ? \"bg-primary\" : \"bg-muted\"\n          )}\n          role=\"switch\"\n          aria-checked={billing === \"annual\"}\n        >\n          <span\n            className={cn(\n              \"inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform\",\n              billing === \"annual\" ? \"translate-x-6\" : \"translate-x-1\"\n            )}\n          />\n        </button>\n        <button\n          onClick={() => setBilling(\"annual\")}\n          className={cn(\n            \"text-sm font-medium transition-colors flex items-center gap-1.5\",\n            billing === \"annual\" ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n          )}\n        >\n          {L.annual}\n          <span className=\"text-xs font-semibold px-1.5 py-0.5 rounded bg-primary/15 text-primary border border-primary/30\">\n            −20%\n          </span>\n        </button>\n      </div>\n\n      {/* Plans grid */}\n      <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-8\">\n        {/* Free */}\n        <div className=\"rounded-lg border border-border bg-card p-6 flex flex-col\">\n          <div className=\"mb-4\">\n            <span className=\"bg-muted text-muted-foreground border border-border text-xs font-semibold px-2 py-0.5 rounded-full\">\n              {L.free}\n            </span>\n          </div>\n          <div className=\"mb-1\">\n            <span className=\"text-3xl font-bold text-foreground font-[family-name:var(--saaskit-font-display,Fraunces)]\">$0</span>\n            <span className=\"text-muted-foreground text-sm ml-1\">{L.perMonth}</span>\n          </div>\n          <p className=\"text-sm text-muted-foreground mb-6\">{L.descriptions.free}</p>\n          <button\n            onClick={() => onSelectPlan?.(\"free\", billing)}\n            className=\"w-full py-2 px-4 rounded-md border border-border text-sm font-medium text-foreground hover:bg-secondary transition-colors mt-auto\"\n          >\n            {L.startFree}\n          </button>\n        </div>\n\n        {/* Pro — highlighted */}\n        <div className=\"rounded-lg border border-primary/50 bg-card p-6 flex flex-col relative ring-1 ring-primary/20 shadow-lg shadow-primary/10\">\n          <div className=\"absolute -top-3 left-1/2 -translate-x-1/2\">\n            <span className=\"flex items-center gap-1 text-xs font-semibold px-3 py-1 rounded-full bg-primary text-primary-foreground shadow-sm\">\n              <Zap className=\"h-3 w-3\" />\n              {L.recommended}\n            </span>\n          </div>\n          <div className=\"mb-4\">\n            <span className=\"bg-primary/15 text-primary border border-primary/30 text-xs font-semibold px-2 py-0.5 rounded-full\">\n              {L.pro}\n            </span>\n          </div>\n          <div className=\"mb-1\">\n            <span className=\"text-3xl font-bold text-foreground font-[family-name:var(--saaskit-font-display,Fraunces)]\">\n              ${prices.pro[billing]}\n            </span>\n            <span className=\"text-muted-foreground text-sm ml-1\">{L.perMonth}</span>\n          </div>\n          {billing === \"annual\" && (\n            <p className=\"text-xs text-primary mb-1\">{L.billedAnnual(`$${prices.pro.annual * 12}`)}</p>\n          )}\n          <p className=\"text-sm text-muted-foreground mb-6\">{L.descriptions.pro}</p>\n          <button\n            onClick={() => onSelectPlan?.(\"pro\", billing)}\n            className=\"w-full py-2 px-4 rounded-md bg-primary text-primary-foreground text-sm font-medium hover:opacity-90 transition-opacity mt-auto\"\n          >\n            {L.upgradePro}\n          </button>\n        </div>\n\n        {/* Enterprise */}\n        <div className=\"rounded-lg border border-border bg-card p-6 flex flex-col\">\n          <div className=\"mb-4\">\n            <span className=\"bg-[oklch(0.75_0.15_80/15%)] text-[oklch(0.80_0.15_80)] border border-[oklch(0.75_0.15_80/30%)] text-xs font-semibold px-2 py-0.5 rounded-full\">\n              {L.enterprise}\n            </span>\n          </div>\n          <div className=\"mb-1\">\n            <span className=\"text-3xl font-bold text-foreground font-[family-name:var(--saaskit-font-display,Fraunces)]\">\n              ${prices.enterprise[billing]}\n            </span>\n            <span className=\"text-muted-foreground text-sm ml-1\">{L.perMonth}</span>\n          </div>\n          {billing === \"annual\" && (\n            <p className=\"text-xs text-yellow-400/80 mb-1\">{L.billedAnnual(`$${prices.enterprise.annual * 12}`)}</p>\n          )}\n          <p className=\"text-sm text-muted-foreground mb-6\">{L.descriptions.enterprise}</p>\n          <button\n            onClick={() => onSelectPlan?.(\"enterprise\", billing)}\n            className=\"w-full py-2 px-4 rounded-md border border-border text-sm font-medium text-foreground hover:bg-secondary transition-colors mt-auto\"\n          >\n            {L.contactSales}\n          </button>\n        </div>\n      </div>\n\n      {/* Feature comparison table */}\n      <div className=\"rounded-lg border border-border overflow-hidden\">\n        <table className=\"w-full text-sm\">\n          <thead>\n            <tr className=\"border-b border-border bg-muted/30\">\n              <th className=\"text-left px-4 py-3 text-muted-foreground font-medium\">{L.feature}</th>\n              <th className=\"text-center px-4 py-3 text-muted-foreground font-medium\">{L.free}</th>\n              <th className=\"text-center px-4 py-3 text-primary font-semibold\">{L.pro}</th>\n              <th className=\"text-center px-4 py-3 text-muted-foreground font-medium\">{L.enterprise}</th>\n            </tr>\n          </thead>\n          <tbody>\n            {displayFeatures.map((feature, i) => (\n              <tr\n                key={feature.name}\n                className={cn(\n                  \"border-b border-border last:border-0\",\n                  i % 2 === 0 ? \"bg-transparent\" : \"bg-muted/10\"\n                )}\n              >\n                <td className=\"px-4 py-3 text-foreground\">{feature.name}</td>\n                <td className=\"px-4 py-3 text-center\"><FeatureValue value={feature.free} /></td>\n                <td className=\"px-4 py-3 text-center\"><FeatureValue value={feature.pro} /></td>\n                <td className=\"px-4 py-3 text-center\"><FeatureValue value={feature.enterprise} /></td>\n              </tr>\n            ))}\n          </tbody>\n        </table>\n      </div>\n    </div>\n  );\n}\n\nfunction FeatureValue({ value }: { value: boolean | string }) {\n  if (value === false) return <Minus className=\"h-4 w-4 text-muted-foreground mx-auto\" />;\n  if (value === true) return <Check className=\"h-4 w-4 text-emerald-400 mx-auto\" />;\n  return <span className=\"text-sm text-foreground\">{value}</span>;\n}\n",
      "type": "registry:component",
      "target": "components/saaskit/pricing-table.tsx"
    }
  ],
  "title": "PricingTable",
  "description": "Plans, toggle mensuel/annuel, highlight plan recommandé",
  "categories": [
    "monetisation",
    "saas"
  ]
}