{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "payment-details",
  "title": "Payment Details",
  "description": "A comprehensive payment details form component with card details, billing information, and country selection",
  "dependencies": ["lucide-react"],
  "registryDependencies": ["button", "card", "input", "label", "utils"],
  "files": [
    {
      "path": "src/registry/billingsdk/payment-details.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Calendar, Shield, Check, CreditCard } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { useTheme } from \"@/contexts/theme-context\";\nimport { getThemeStyles } from \"@/lib/themes\";\nimport { Country, State, City, IState, ICity } from \"country-state-city\";\n/**\n * Detects the card type based on the card number\n * @param cardNumber - The card number to analyze\n * @returns The detected card type (visa, mastercard, amex, rupay, diners, or unknown)\n * @note This is a best-effort detection based on known BIN ranges\n */\nconst detectCardType = (\n  cardNumber: string,\n):\n  | \"visa\"\n  | \"mastercard\"\n  | \"amex\"\n  | \"rupay\"\n  | \"diners\"\n  | \"discover\"\n  | \"unknown\" => {\n  const number = cardNumber.replace(/\\s/g, \"\");\n\n  // Order matters: check more specific patterns first\n  if (/^4/.test(number)) return \"visa\";\n  if (/^3[47]/.test(number)) return \"amex\";\n  // Diners Club with expanded prefixes\n  if (/^3(?:0[0-5]|09|095|6|8)/.test(number)) return \"diners\";\n  // Mastercard with expanded range (51-55 and 2221-2720)\n  if (\n    /^5[1-5]/.test(number) ||\n    /^222[1-9]/.test(number) ||\n    /^22[3-9]\\d/.test(number) ||\n    /^2[3-6]\\d{2}/.test(number) ||\n    /^27[0-1]\\d/.test(number) ||\n    /^2720/.test(number)\n  )\n    return \"mastercard\";\n  // Discover with expanded prefixes\n  if (\n    /^6011/.test(number) ||\n    /^65/.test(number) ||\n    /^64[4-9]/.test(number) ||\n    /^622(?:12[6-9]|1[3-9]\\d|[2-8]\\d{2}|9[0-1]\\d|92[0-5])/.test(number)\n  )\n    return \"discover\";\n  // More specific RuPay BIN ranges (best effort)\n  if (\n    /^60/.test(number) ||\n    /^81/.test(number) ||\n    /^82/.test(number) ||\n    /^508/.test(number)\n  )\n    return \"rupay\";\n\n  return \"unknown\";\n};\n\n/**\n * Formats a card number by adding spaces every 4 digits\n * @param value - The raw card number input\n * @returns The formatted card number with spaces\n */\nconst formatCardNumber = (value: string): string => {\n  const number = value.replace(/\\s/g, \"\").replace(/[^0-9]/gi, \"\");\n  const matches = number.match(/\\d{4,16}/g);\n  const match = (matches && matches[0]) || \"\";\n  const parts = [];\n\n  for (let i = 0, len = match.length; i < len; i += 4) {\n    parts.push(match.substring(i, i + 4));\n  }\n\n  if (parts.length) {\n    return parts.join(\" \");\n  } else {\n    return number;\n  }\n};\n\n/**\n * Formats an expiry date in MM/YY format\n * @param value - The raw expiry date input\n * @returns The formatted expiry date (MM/YY)\n */\nconst formatExpiryDate = (value: string): string => {\n  const number = value.replace(/\\D/g, \"\");\n  if (number.length >= 2) {\n    return number.substring(0, 2) + \"/\" + number.substring(2, 4);\n  }\n  return number;\n};\n\n/**\n * Validates a card number using the Luhn algorithm\n * @param cardNumber - The card number to validate\n * @returns Boolean indicating if the card number is valid\n */\nconst validateLuhn = (cardNumber: string): boolean => {\n  const number = cardNumber.replace(/\\s/g, \"\");\n  if (!number || !/^\\d+$/.test(number)) return false;\n\n  let sum = 0;\n  let shouldDouble = false;\n\n  // Loop through values starting from the rightmost digit\n  for (let i = number.length - 1; i >= 0; i--) {\n    let digit = parseInt(number.charAt(i));\n\n    if (shouldDouble) {\n      digit *= 2;\n      if (digit > 9) digit -= 9;\n    }\n\n    sum += digit;\n    shouldDouble = !shouldDouble;\n  }\n\n  return sum % 10 === 0;\n};\n\n/**\n * Validates the payment form data\n * @param data - The form data to validate\n * @param validators - Optional validation configuration\n * @returns Object containing validation errors\n */\nconst validateForm = (\n  data: PaymentFormData,\n  validators?: ValidationConfig,\n): Partial<PaymentFormData> => {\n  const errors: Partial<PaymentFormData> = {};\n  const cardType = detectCardType(data.cardNumber || \"\");\n\n  if (!data.nameOnCard?.trim()) errors.nameOnCard = \"Name is required\";\n\n  // Card number validation with Luhn algorithm\n  const strippedCardNumber = data.cardNumber?.replace(/\\s/g, \"\") || \"\";\n  if (\n    !strippedCardNumber ||\n    strippedCardNumber.length < 13 ||\n    !validateLuhn(strippedCardNumber)\n  ) {\n    errors.cardNumber = \"Valid card number is required\";\n  }\n\n  // Expiry date validation\n  if (!data.validTill || !/^\\d{2}\\/\\d{2}$/.test(data.validTill)) {\n    errors.validTill = \"Valid expiry date is required (MM/YY)\";\n  } else {\n    const [month, year] = data.validTill.split(\"/\");\n    const expiryMonth = parseInt(month);\n    const expiryYear = 2000 + parseInt(year);\n\n    const currentDate = new Date();\n\n    if (expiryMonth < 1 || expiryMonth > 12) {\n      errors.validTill = \"Invalid expiry month\";\n    } else {\n      // Create date for last day of expiry month\n      const expiryDate = new Date(expiryYear, expiryMonth, 0); // Day 0 gives last day of previous month\n      expiryDate.setHours(23, 59, 59, 999); // Set to last moment of the day\n\n      if (expiryDate < currentDate) {\n        errors.validTill = \"Card has expired\";\n      }\n    }\n  }\n\n  // CVV validation based on card type\n  const requiredCvvLength = cardType === \"amex\" ? 4 : 3;\n  if (!data.cvv || data.cvv.length !== requiredCvvLength) {\n    errors.cvv = `Valid ${requiredCvvLength}-digit CVV is required`;\n  }\n\n  if (!data.firstName?.trim()) errors.firstName = \"First name is required\";\n  if (!data.middleLastName?.trim())\n    errors.middleLastName = \"Last name is required\";\n  if (!data.billingAddress?.trim())\n    errors.billingAddress = \"Billing address is required\";\n  // PIN code validation - configurable based on country\n  const pinCodePattern = validators?.pinCode || /^\\d{6}$/;\n  if (!data.pinCode || !pinCodePattern.test(data.pinCode)) {\n    errors.pinCode = validators?.pinCodeErrorMessage || \"Invalid postal code\";\n  }\n\n  // Contact number validation - configurable based on country\n  const contactNumberPattern = validators?.contactNumber || /^\\d{10}$/;\n  if (!data.contactNumber || !contactNumberPattern.test(data.contactNumber)) {\n    errors.contactNumber =\n      validators?.contactNumberErrorMessage || \"Invalid phone number\";\n  }\n\n  return errors;\n};\n\nconst CardLogo = ({ type }: { type: string }) => {\n  switch (type) {\n    case \"visa\":\n      return (\n        <div className=\"flex h-6 w-10 items-center justify-center rounded bg-blue-600 text-xs font-bold text-white\">\n          VISA\n        </div>\n      );\n    case \"mastercard\":\n      return (\n        <div className=\"flex items-center\">\n          <div className=\"h-5 w-5 rounded-full bg-red-500\"></div>\n          <div className=\"-ml-2 h-5 w-5 rounded-full bg-orange-400\"></div>\n        </div>\n      );\n    case \"amex\":\n      return (\n        <div className=\"flex h-6 w-10 items-center justify-center rounded bg-blue-500 text-xs font-bold text-white\">\n          AMEX\n        </div>\n      );\n    case \"rupay\":\n      return (\n        <div className=\"flex h-6 w-10 items-center justify-center rounded bg-green-600 text-xs font-bold text-white\">\n          RuPay\n        </div>\n      );\n    case \"discover\":\n      return (\n        <div className=\"flex h-6 w-10 items-center justify-center rounded bg-orange-600 text-xs font-bold text-white\">\n          DISC\n        </div>\n      );\n    default:\n      return <CreditCard className=\"text-muted-foreground h-5 w-5\" />;\n  }\n};\n\n/**\n * Payment form data interface\n */\nexport interface PaymentFormData {\n  /** Name as it appears on the card */\n  nameOnCard?: string;\n  /** Card number (will be formatted automatically) */\n  cardNumber?: string;\n  /** Expiry date in MM/YY format */\n  validTill?: string;\n  /** Card verification value (CVV) */\n  cvv?: string;\n  /** Customer's first name */\n  firstName?: string;\n  /** Customer's middle and last name */\n  middleLastName?: string;\n  /** Customer's country */\n  country?: string;\n  /** Customer's state */\n  state?: string;\n  /** Customer's city */\n  city?: string;\n  /** Customer's billing address */\n  billingAddress?: string;\n  /** Customer's PIN code */\n  pinCode?: string;\n  /** Customer's phone number */\n  contactNumber?: string;\n  /** General form error message */\n  general?: string;\n}\n\n/**\n * Validation configuration interface\n */\nexport interface ValidationConfig {\n  /** Custom PIN code validation regex */\n  pinCode?: RegExp;\n  /** Custom PIN code error message */\n  pinCodeErrorMessage?: string;\n  /** Custom contact number validation regex */\n  contactNumber?: RegExp;\n  /** Custom contact number error message */\n  contactNumberErrorMessage?: string;\n  /** Country code for phone validation */\n  countryCode?: string;\n}\n\n/**\n * Payment form component props\n */\nexport interface PaymentFormProps {\n  /** Additional CSS classes for styling */\n  className?: string;\n  /** Main title for the payment form */\n  title?: string;\n  /** Description text below the title */\n  description?: string;\n  /** Initial form data */\n  initialData?: Partial<PaymentFormData>;\n  /** Validation configuration */\n  validators?: ValidationConfig;\n  /** Callback when form is submitted */\n  onSubmit?: (data: PaymentFormData) => void | Promise<void>;\n  /** Callback when discard button is clicked */\n  onDiscard?: () => void;\n  /** Text for submit button */\n  submitButtonText?: string;\n  /** Text for discard button */\n  discardButtonText?: string;\n  /** External loading state */\n  isLoading?: boolean;\n  /** Show success confirmation modal */\n  showConfirmation?: boolean;\n  /** Title for confirmation modal */\n  confirmationTitle?: string;\n  /** Message for confirmation modal */\n  confirmationMessage?: string;\n  /** Callback when confirmation is closed */\n  onConfirmationClose?: () => void;\n}\n\n/**\n * PaymentDetails component - A comprehensive payment form with card details and billing information\n *\n * Features:\n * - Card type detection (Visa, Mastercard, Amex, RuPay, Diners)\n * - Real-time input formatting and validation\n * - Responsive design with mobile support\n * - Accessibility features (ARIA labels, keyboard navigation)\n * - Customizable confirmation modal\n * - Support for multiple themes\n * - Country, state, and city selection\n *\n * @param props - PaymentFormProps object\n * @returns JSX element containing the payment details form\n */\nexport function PaymentDetails({\n  className,\n  title = \"Payment Details\",\n  description = \"Enter your payment information to complete the transaction.\",\n  initialData = {},\n  validators,\n  onSubmit,\n  onDiscard,\n  submitButtonText = \"Save Changes\",\n  discardButtonText = \"Discard\",\n  isLoading = false,\n  showConfirmation = false,\n  confirmationTitle = \"Payment Details Saved!\",\n  confirmationMessage = \"Your payment information has been securely saved and updated.\",\n  onConfirmationClose,\n}: PaymentFormProps) {\n  const { currentTheme, previewDarkMode } = useTheme();\n  const themeStyles = getThemeStyles(currentTheme, previewDarkMode);\n  const [selectedCountryCode, setSelectedCountryCode] = useState(\"\");\n  const [selectedStateCode, setSelectedStateCode] = useState(\"\");\n  const [availableStates, setAvailableStates] = useState<IState[]>([]);\n  const [availableCities, setAvailableCities] = useState<ICity[]>([]);\n\n  const allCountries = Country.getAllCountries();\n\n  // Initialize with empty strings, allowing initialData to override if provided\n  const [formData, setFormData] = useState<PaymentFormData>({\n    nameOnCard: \"\",\n    cardNumber: \"\",\n    validTill: \"\",\n    cvv: \"\",\n    firstName: \"\",\n    middleLastName: \"\",\n    country: \"\",\n    state: \"\",\n    city: \"\",\n    billingAddress: \"\",\n    pinCode: \"\",\n    contactNumber: \"\",\n    ...initialData,\n  });\n\n  const [errors, setErrors] = useState<Partial<PaymentFormData>>({});\n  const [isSubmitting, setIsSubmitting] = useState(false);\n  const [cardType, setCardType] = useState(\n    detectCardType(formData.cardNumber || \"\"),\n  );\n\n  const handleInputChange = (field: keyof PaymentFormData, value: string) => {\n    let formattedValue = value;\n\n    const isField = <K extends keyof PaymentFormData>(\n      f: keyof PaymentFormData,\n      k: K,\n    ): f is K => f === k;\n\n    if (isField(field, \"cardNumber\")) {\n      formattedValue = formatCardNumber(value);\n      setCardType(detectCardType(formattedValue));\n    } else if (isField(field, \"cvv\")) {\n      const maxLength = cardType === \"amex\" ? 4 : 3;\n      formattedValue = value.slice(0, maxLength);\n    } else if (isField(field, \"validTill\")) {\n      formattedValue = formatExpiryDate(value);\n    } else if (isField(field, \"pinCode\")) {\n      formattedValue = value.replace(/\\D/g, \"\").substring(0, 6);\n    } else if (isField(field, \"contactNumber\")) {\n      formattedValue = value.replace(/\\D/g, \"\").substring(0, 10);\n    }\n\n    // Handle country change - load states and reset state/city\n    if (isField(field, \"country\")) {\n      const selectedCountry = allCountries.find((c) => c.name === value);\n      if (selectedCountry) {\n        setSelectedCountryCode(selectedCountry.isoCode);\n        const states = State.getStatesOfCountry(selectedCountry.isoCode);\n        setAvailableStates(states);\n        setAvailableCities([]);\n        setFormData((prev) => ({\n          ...prev,\n          country: value,\n          state: \"\",\n          city: \"\",\n        }));\n        setSelectedStateCode(\"\");\n      }\n      return;\n    }\n\n    // Handle state change - load cities and reset city\n    if (isField(field, \"state\")) {\n      const selectedState = availableStates.find((s) => s.name === value);\n      if (selectedState) {\n        setSelectedStateCode(selectedState.isoCode);\n        const cities = City.getCitiesOfState(\n          selectedCountryCode,\n          selectedState.isoCode,\n        );\n        setAvailableCities(cities);\n        setFormData((prev) => ({ ...prev, state: value, city: \"\" }));\n      }\n      return;\n    }\n\n    setFormData((prev) => ({ ...prev, [field]: formattedValue }));\n\n    if (errors[field]) {\n      setErrors((prev) => ({ ...prev, [field]: \"\" }));\n    }\n  };\n\n  const handleSubmit = async () => {\n    const formErrors = validateForm(formData, validators);\n\n    if (Object.keys(formErrors).length > 0) {\n      setErrors(formErrors);\n      return;\n    }\n\n    setIsSubmitting(true);\n\n    try {\n      await onSubmit?.(formData);\n    } catch (error) {\n      console.error(\"Error submitting form:\", error);\n      // Set user-facing error message\n      setErrors((prev) => ({\n        ...prev,\n        general: \"Payment submission failed. Please try again.\",\n      }));\n      // Could also send to monitoring service if integrated\n      // monitoringService.captureException(error)\n    } finally {\n      setIsSubmitting(false);\n    }\n  };\n\n  return (\n    <>\n      <div\n        className={cn(\n          \"relative w-full max-w-xl rounded-3xl p-6 shadow-sm\",\n          className,\n        )}\n        style={themeStyles}\n      >\n        <div className=\"mb-6\">\n          <h1 className=\"text-foreground mb-2 font-sans text-3xl font-bold\">\n            {title}\n          </h1>\n          <p className=\"text-muted-foreground font-sans\">{description}</p>\n        </div>\n        {/* Card Details Section */}\n        <div className=\"border-border bg-card/50 mb-6 rounded-2xl border p-6\">\n          <h2 className=\"text-foreground mb-5 font-sans text-2xl font-semibold\">\n            Card Details\n          </h2>\n\n          <div className=\"space-y-4\">\n            {/* Name on Card and Valid Till */}\n            <div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n              <div className=\"md:col-span-2\">\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Name On Card <span className=\"text-destructive\">*</span>\n                </label>\n                <input\n                  type=\"text\"\n                  value={formData.nameOnCard || \"\"}\n                  onChange={(e) =>\n                    handleInputChange(\"nameOnCard\", e.target.value)\n                  }\n                  className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                    errors.nameOnCard\n                      ? \"border-destructive focus:ring-destructive/20\"\n                      : \"border-border\"\n                  }`}\n                />\n                {errors.nameOnCard && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.nameOnCard}\n                  </p>\n                )}\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Valid Till <span className=\"text-destructive\">*</span>\n                </label>\n                <div className=\"relative\">\n                  <Calendar className=\"text-muted-foreground absolute top-1/2 left-4 h-5 w-5 -translate-y-1/2 transform\" />\n                  <input\n                    type=\"text\"\n                    placeholder=\"MM/YY\"\n                    value={formData.validTill || \"\"}\n                    onChange={(e) =>\n                      handleInputChange(\"validTill\", e.target.value)\n                    }\n                    className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border py-3 pr-4 pl-12 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                      errors.validTill\n                        ? \"border-destructive focus:ring-destructive/20\"\n                        : \"border-border\"\n                    }`}\n                  />\n                </div>\n                {errors.validTill && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.validTill}\n                  </p>\n                )}\n              </div>\n            </div>\n\n            {/* Card Number and CVV */}\n            <div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n              <div className=\"md:col-span-2\">\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Card Number <span className=\"text-destructive\">*</span>\n                </label>\n                <div className=\"relative\">\n                  <div className=\"absolute top-1/2 left-4 flex -translate-y-1/2 transform items-center\">\n                    <CardLogo type={cardType} />\n                  </div>\n                  <input\n                    type=\"text\"\n                    placeholder=\"1234 5678 9012 3456\"\n                    value={formData.cardNumber || \"\"}\n                    onChange={(e) =>\n                      handleInputChange(\"cardNumber\", e.target.value)\n                    }\n                    className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border py-3 pr-4 pl-20 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                      errors.cardNumber\n                        ? \"border-destructive focus:ring-destructive/20\"\n                        : \"border-border\"\n                    }`}\n                  />\n                </div>\n                {errors.cardNumber && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.cardNumber}\n                  </p>\n                )}\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  CVV <span className=\"text-destructive\">*</span>\n                </label>\n                <div className=\"relative\">\n                  <Shield className=\"text-muted-foreground absolute top-1/2 left-4 h-5 w-5 -translate-y-1/2 transform\" />\n                  <input\n                    type=\"password\"\n                    placeholder=\"123\"\n                    value={formData.cvv || \"\"}\n                    onChange={(e) => handleInputChange(\"cvv\", e.target.value)}\n                    className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border py-3 pr-4 pl-12 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                      errors.cvv\n                        ? \"border-destructive focus:ring-destructive/20\"\n                        : \"border-border\"\n                    }`}\n                  />\n                </div>\n                {errors.cvv && (\n                  <p className=\"text-destructive mt-1 text-sm\">{errors.cvv}</p>\n                )}\n              </div>\n            </div>\n          </div>\n        </div>\n\n        {/* Divider between sections */}\n        <div className=\"border-border my-6 border-t\"></div>\n\n        {/* Billing Details Section */}\n        <div className=\"border-border bg-card/50 mb-6 rounded-2xl border p-6\">\n          <h2 className=\"text-foreground mb-5 font-sans text-2xl font-semibold\">\n            Billing Details\n          </h2>\n\n          <div className=\"space-y-4\">\n            {/* First Name and Middle & Last Name */}\n            <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  First Name <span className=\"text-destructive\">*</span>\n                </label>\n                <input\n                  type=\"text\"\n                  value={formData.firstName || \"\"}\n                  onChange={(e) =>\n                    handleInputChange(\"firstName\", e.target.value)\n                  }\n                  className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                    errors.firstName\n                      ? \"border-destructive focus:ring-destructive/20\"\n                      : \"border-border\"\n                  }`}\n                />\n                {errors.firstName && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.firstName}\n                  </p>\n                )}\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Middle & Last Name <span className=\"text-destructive\">*</span>\n                </label>\n                <input\n                  type=\"text\"\n                  value={formData.middleLastName || \"\"}\n                  onChange={(e) =>\n                    handleInputChange(\"middleLastName\", e.target.value)\n                  }\n                  className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                    errors.middleLastName\n                      ? \"border-destructive focus:ring-destructive/20\"\n                      : \"border-border\"\n                  }`}\n                />\n                {errors.middleLastName && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.middleLastName}\n                  </p>\n                )}\n              </div>\n            </div>\n\n            {/* Country, State and City */}\n            <div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Country\n                </label>\n                <select\n                  value={formData.country || \"\"}\n                  onChange={(e) => handleInputChange(\"country\", e.target.value)}\n                  className=\"border-border bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border custom-select w-full appearance-none rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2\"\n                >\n                  <option value=\"\">Country</option>\n                  {allCountries.map((country) => (\n                    <option key={country.isoCode} value={country.name}>\n                      {country.name}\n                    </option>\n                  ))}\n                </select>\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  State\n                </label>\n                <select\n                  value={formData.state || \"\"}\n                  onChange={(e) => handleInputChange(\"state\", e.target.value)}\n                  disabled={\n                    !selectedCountryCode || availableStates.length === 0\n                  }\n                  className=\"border-border bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border custom-select w-full appearance-none rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 disabled:cursor-not-allowed disabled:opacity-50\"\n                >\n                  <option value=\"\">State</option>\n                  {availableStates.map((state) => (\n                    <option key={state.isoCode} value={state.name}>\n                      {state.name}\n                    </option>\n                  ))}\n                </select>\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  City\n                </label>\n                <select\n                  value={formData.city || \"\"}\n                  onChange={(e) => handleInputChange(\"city\", e.target.value)}\n                  disabled={!selectedStateCode || availableCities.length === 0}\n                  className=\"border-border bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border custom-select w-full appearance-none rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 disabled:cursor-not-allowed disabled:opacity-50\"\n                >\n                  <option value=\"\">City</option>\n                  {availableCities.map((city) => (\n                    <option key={city.name} value={city.name}>\n                      {city.name}\n                    </option>\n                  ))}\n                </select>\n              </div>\n            </div>\n\n            {/* Billing Address */}\n            <div>\n              <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                Billing Address <span className=\"text-destructive\">*</span>\n              </label>\n              <textarea\n                value={formData.billingAddress || \"\"}\n                onChange={(e) =>\n                  handleInputChange(\"billingAddress\", e.target.value)\n                }\n                rows={3}\n                className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full resize-none rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                  errors.billingAddress\n                    ? \"border-destructive focus:ring-destructive/20\"\n                    : \"border-border\"\n                }`}\n              />\n              {errors.billingAddress && (\n                <p className=\"text-destructive mt-1 text-sm\">\n                  {errors.billingAddress}\n                </p>\n              )}\n            </div>\n\n            {/* Pin Code and Contact Number */}\n            <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Pin Code <span className=\"text-destructive\">*</span>\n                </label>\n                <input\n                  type=\"text\"\n                  placeholder=\"123456\"\n                  value={formData.pinCode || \"\"}\n                  onChange={(e) => handleInputChange(\"pinCode\", e.target.value)}\n                  className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                    errors.pinCode\n                      ? \"border-destructive focus:ring-destructive/20\"\n                      : \"border-border\"\n                  }`}\n                />\n                {errors.pinCode && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.pinCode}\n                  </p>\n                )}\n              </div>\n              <div>\n                <label className=\"text-muted-foreground mb-2 block text-sm font-medium\">\n                  Phone Number <span className=\"text-destructive\">*</span>\n                </label>\n                <input\n                  type=\"text\"\n                  placeholder=\"9876543210\"\n                  value={formData.contactNumber || \"\"}\n                  onChange={(e) =>\n                    handleInputChange(\"contactNumber\", e.target.value)\n                  }\n                  className={`bg-background text-foreground focus:ring-ring focus:border-ring hover:border-border w-full rounded-xl border px-4 py-3 font-sans font-medium transition-all duration-200 focus:ring-2 ${\n                    errors.contactNumber\n                      ? \"border-destructive focus:ring-destructive/20\"\n                      : \"border-border\"\n                  }`}\n                />\n                {errors.contactNumber && (\n                  <p className=\"text-destructive mt-1 text-sm\">\n                    {errors.contactNumber}\n                  </p>\n                )}\n              </div>\n            </div>\n          </div>\n        </div>\n\n        {/* Display general error message */}\n        {errors.general && (\n          <div className=\"bg-destructive/10 border-destructive text-destructive mb-6 rounded-xl border p-4\">\n            {errors.general}\n          </div>\n        )}\n\n        {/* Action Buttons */}\n        <div className=\"flex justify-end gap-4\">\n          <button\n            className=\"text-muted-foreground border-border bg-background hover:bg-muted hover:border-border/80 rounded-xl border px-6 py-3 font-sans font-medium transition-all duration-200\"\n            onClick={onDiscard}\n            disabled={isSubmitting || isLoading}\n          >\n            {discardButtonText}\n          </button>\n          <button\n            onClick={handleSubmit}\n            disabled={isSubmitting || isLoading}\n            className={`flex transform items-center gap-2 rounded-xl px-6 py-3 font-sans font-medium shadow-sm transition-all duration-300 hover:scale-105 hover:shadow-lg active:scale-95 ${\n              isSubmitting || isLoading\n                ? \"bg-primary text-primary-foreground cursor-not-allowed opacity-70\"\n                : \"bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-primary/25\"\n            }`}\n          >\n            {isSubmitting || isLoading ? (\n              <>\n                <div className=\"border-primary-foreground h-4 w-4 animate-spin rounded-full border-2 border-t-transparent\"></div>\n                Saving...\n              </>\n            ) : (\n              submitButtonText\n            )}\n          </button>\n        </div>\n      </div>\n\n      {showConfirmation && (\n        <div className=\"animate-in fade-in fixed inset-0 z-50 flex items-center justify-center bg-black/50 duration-300\">\n          <div className=\"bg-background border-border animate-in zoom-in-95 mx-4 max-w-md rounded-2xl border p-8 shadow-lg duration-300\">\n            <div className=\"text-center\">\n              <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/20\">\n                <Check className=\"h-8 w-8 text-green-600 dark:text-green-400\" />\n              </div>\n              <h3 className=\"text-foreground mb-2 font-sans text-xl font-semibold\">\n                {confirmationTitle}\n              </h3>\n              <p className=\"text-muted-foreground font-sans\">\n                {confirmationMessage}\n              </p>\n              <button\n                onClick={onConfirmationClose}\n                className=\"bg-primary text-primary-foreground hover:bg-primary/90 mt-4 transform rounded-xl px-6 py-2 font-medium transition-all duration-200 hover:scale-105 active:scale-95\"\n              >\n                Close\n              </button>\n            </div>\n          </div>\n        </div>\n      )}\n    </>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/billingsdk/payment-details.tsx"
    },
    {
      "path": "src/registry/billingsdk/demo/payment-details-demo.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport {\n  PaymentDetails,\n  type PaymentFormData,\n} from \"@/components/billingsdk/payment-details\";\n\nexport function PaymentDetailsDemo() {\n  const [showConfirmation, setShowConfirmation] = useState(false);\n\n  const handleSubmit = async (_data: PaymentFormData) => {\n    // Simulate API call\n    await new Promise((resolve) => setTimeout(resolve, 1500));\n    setShowConfirmation(true);\n\n    // Auto-hide confirmation after 3 seconds\n    setTimeout(() => {\n      setShowConfirmation(false);\n    }, 3000);\n  };\n\n  const handleDiscard = () => {\n    console.log(\"Form discarded\");\n  };\n\n  return (\n    <div className=\"flex w-full justify-center\">\n      <PaymentDetails\n        title=\"Payment Details\"\n        description=\"Enter your payment information to complete the transaction.\"\n        onSubmit={handleSubmit}\n        onDiscard={handleDiscard}\n        showConfirmation={showConfirmation}\n        onConfirmationClose={() => setShowConfirmation(false)}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/payment-details-demo.tsx"
    }
  ],
  "type": "registry:block"
}
