{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "limited-offer-dialog",
  "title": "Limited Offer Dialog",
  "description": "A dialog component for displaying limited-time offers with customizable content and actions",
  "dependencies": ["lucide-react"],
  "registryDependencies": [
    "dialog",
    "button",
    "badge",
    "button",
    "card",
    "utils"
  ],
  "files": [
    {
      "path": "src/registry/billingsdk/limited-offer-dialog.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogTrigger,\n  DialogTitle,\n} from \"@/components/ui/dialog\";\nimport { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Circle } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { useTheme } from \"@/contexts/theme-context\";\nimport { getThemeStyles } from \"@/lib/themes\";\n\n// Plan interface for type safety\nexport interface Offer {\n  id: string;\n  title: string;\n  description: string;\n  discount: string;\n  features: Array<{ name: string; icon?: string; iconColor?: string }>;\n}\n\n// Component props interface\nexport interface LimitedOfferDialogProps {\n  title?: string;\n  description?: string;\n  offer?: Offer;\n  triggerButtonText?: string;\n  warningTitle?: string;\n  warningText?: string;\n  claimButtonText?: string;\n  declineButtonText?: string;\n  onClaimOffer?: (offerId: string) => Promise<void> | void;\n  onDeclineOffer?: (offerId: string) => Promise<void> | void;\n  onDialogClose?: () => void;\n  className?: string;\n}\n\n// Default offer object\nconst defaultOffer: Offer = {\n  id: \"limited-offer-dialog\",\n  title: \"Special Offer\",\n  description: \"Limited time deal\",\n  discount: \"50% OFF\",\n  features: [\n    { name: \"50% off your first month\" },\n    { name: \"Valid until December 31, 2024\" },\n    { name: \"First 100 users only\" },\n  ],\n};\n\nexport function LimitedOfferDialog({\n  title = \"🔥 Limited Time Offer!\",\n  description = \"Grab this deal before it's gone\",\n  offer = defaultOffer,\n  triggerButtonText = \"Open Offer Dialog\",\n  warningTitle = \"Don't miss out!\",\n  warningText = \"This exclusive offer won't last long. Claim it now before it's gone forever.\",\n  claimButtonText = \"👉 Claim Offer Now\",\n  declineButtonText = \"No thanks, I'll pay full price\",\n  onClaimOffer,\n  onDeclineOffer,\n  onDialogClose,\n  className,\n}: LimitedOfferDialogProps) {\n  // State management\n  const [isOpen, setIsOpen] = React.useState(false);\n  const [isLoading, setIsLoading] = React.useState(false);\n  const [error, setError] = React.useState<string | null>(null);\n\n  // Theme integration\n  const { currentTheme, previewDarkMode } = useTheme();\n  const themeStyles = getThemeStyles(currentTheme, previewDarkMode);\n\n  // Event handlers\n  const handleClaimOffer = async () => {\n    if (!onClaimOffer) {\n      console.log(\"Claim offer clicked\");\n      return;\n    }\n\n    setIsLoading(true);\n    setError(null);\n\n    try {\n      await onClaimOffer(offer.id);\n      setIsOpen(false);\n      onDialogClose?.();\n    } catch (err) {\n      setError(err instanceof Error ? err.message : \"Failed to claim offer\");\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const handleDeclineOffer = async () => {\n    if (!onDeclineOffer) {\n      console.log(\"Decline offer clicked\");\n      setIsOpen(false);\n      onDialogClose?.();\n      return;\n    }\n\n    setIsLoading(true);\n    setError(null);\n\n    try {\n      await onDeclineOffer(offer.id);\n      setIsOpen(false);\n      onDialogClose?.();\n    } catch (err) {\n      setError(err instanceof Error ? err.message : \"Operation failed\");\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const handleDialogClose = () => {\n    setIsOpen(false);\n    setError(null);\n    onDialogClose?.();\n  };\n\n  // Keyboard navigation (ESC key)\n  React.useEffect(() => {\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === \"Escape\" && isOpen) {\n        handleDialogClose();\n      }\n    };\n\n    document.addEventListener(\"keydown\", handleKeyDown);\n    return () => document.removeEventListener(\"keydown\", handleKeyDown);\n  }, [isOpen]);\n\n  return (\n    <Dialog\n      open={isOpen}\n      onOpenChange={(open) => {\n        if (open) {\n          setIsOpen(true);\n        } else {\n          handleDialogClose();\n        }\n      }}\n    >\n      <DialogTrigger asChild>\n        <Button variant=\"outline\" className={className}>\n          {triggerButtonText}\n        </Button>\n      </DialogTrigger>\n      <DialogContent\n        className={cn(\n          \"max-w-[calc(100vw-2rem)] gap-0 p-0 sm:max-w-lg\",\n          className,\n        )}\n        style={themeStyles}\n      >\n        <div className=\"space-y-6 p-6\">\n          {/* Dialog Title for accessibility */}\n          <DialogTitle className=\"sr-only\">\n            {title} - {description}\n          </DialogTitle>\n\n          {/* Header */}\n          <div className=\"space-y-2 text-center\">\n            <h2 className=\"text-foreground text-xl font-semibold\">{title}</h2>\n            <p className=\"text-muted-foreground text-sm\">{description}</p>\n          </div>\n\n          {/* Offer Card */}\n          <div className=\"bg-muted space-y-4 rounded-lg p-4\">\n            <div className=\"flex items-start justify-between\">\n              <div className=\"space-y-1\">\n                <h3 className=\"text-foreground font-semibold\">{offer.title}</h3>\n                <p className=\"text-muted-foreground text-xs\">\n                  {offer.description}\n                </p>\n              </div>\n              <Badge\n                variant=\"secondary\"\n                className=\"text-foreground font-semibold\"\n              >\n                {offer.discount}\n              </Badge>\n            </div>\n\n            <div className=\"space-y-3\">\n              {offer.features.map((feature, index) => (\n                <div key={index} className=\"flex items-center gap-3\">\n                  <Circle className=\"text-foreground h-2 w-2 fill-current\" />\n                  <span className=\"text-foreground text-sm\">\n                    {feature.name}\n                  </span>\n                </div>\n              ))}\n            </div>\n          </div>\n\n          {/* Warning Section */}\n          <div className=\"bg-destructive/10 border-destructive/20 space-y-2 rounded-lg border p-4\">\n            <h4 className=\"text-destructive font-medium\">{warningTitle}</h4>\n            <p className=\"text-destructive/80 text-sm\">{warningText}</p>\n          </div>\n\n          {/* Error Display */}\n          {error && (\n            <div className=\"bg-destructive/10 border-destructive/20 rounded-lg border p-3\">\n              <p className=\"text-destructive text-sm\">{error}</p>\n            </div>\n          )}\n\n          {/* Action Buttons */}\n          <div className=\"flex flex-col gap-3 pt-2 sm:flex-row\">\n            <Button\n              onClick={handleClaimOffer}\n              disabled={isLoading}\n              className=\"bg-foreground hover:bg-foreground/90 text-background flex-1\"\n            >\n              {isLoading ? \"Processing...\" : claimButtonText}\n            </Button>\n            <Button\n              onClick={handleDeclineOffer}\n              disabled={isLoading}\n              variant=\"outline\"\n              className=\"border-border text-foreground hover:bg-muted flex-1\"\n            >\n              {declineButtonText}\n            </Button>\n          </div>\n        </div>\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/billingsdk/limited-offer-dialog.tsx"
    },
    {
      "path": "src/registry/billingsdk/demo/limited-offer-dialog-demo.tsx",
      "content": "\"use client\";\n\nimport { LimitedOfferDialog } from \"@/components/billingsdk/limited-offer-dialog\";\n\n// Sample offer data\nconst sampleOffer = {\n  id: \"limited-offer-dialog\",\n  title: \"Special Offer\",\n  description: \"Limited time deal\",\n  discount: \"50% OFF\",\n  features: [\n    { name: \"50% off your first month\" },\n    { name: \"Valid until December 31, 2024\" },\n    { name: \"First 100 users only\" },\n  ],\n};\n\nexport function LimitedOfferDialogDemo() {\n  const handleClaimOffer = async (offerId: string) => {\n    console.log(\"Claiming offer:\", offerId);\n    // Simulate API call\n    await new Promise((resolve) => setTimeout(resolve, 1000));\n    alert(\"Offer claimed successfully!\");\n  };\n\n  const handleDeclineOffer = async (offerId: string) => {\n    console.log(\"Declining offer:\", offerId);\n    // Simulate API call\n    await new Promise((resolve) => setTimeout(resolve, 500));\n    alert(\"Offer declined. You can always come back later!\");\n  };\n\n  const handleDialogClose = () => {\n    console.log(\"Dialog closed\");\n  };\n\n  return (\n    <div className=\"mx-auto flex min-h-[300px] flex-1 flex-col justify-center p-4 text-center\">\n      <LimitedOfferDialog\n        title=\"🔥 Limited Time Offer!\"\n        description=\"Grab this deal before it's gone\"\n        offer={sampleOffer}\n        triggerButtonText=\"Open Offer Dialog\"\n        warningTitle=\"Don't miss out!\"\n        warningText=\"This exclusive offer won't last long. Claim it now before it's gone forever.\"\n        claimButtonText=\"👉 Claim Offer Now\"\n        declineButtonText=\"No thanks, I'll pay full price\"\n        onClaimOffer={handleClaimOffer}\n        onDeclineOffer={handleDeclineOffer}\n        onDialogClose={handleDialogClose}\n        className=\"w-auto\"\n      />\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/limited-offer-dialog-demo.tsx"
    }
  ],
  "type": "registry:block"
}
