{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"credit-card","type":"registry:ui","title":"credit-card","description":"Credit card components for displaying and validating credit card information.","author":"Hayden Bleasel <hello@haydenbleasel.com>","dependencies":["react-svg-credit-card-payment-icons"],"devDependencies":[],"registryDependencies":[],"files":[{"type":"registry:ui","path":"index.tsx","content":"\"use client\";\n\nimport {\n  type ComponentProps,\n  createContext,\n  type HTMLAttributes,\n  type ReactNode,\n  useContext,\n  useEffect,\n  useState,\n} from \"react\";\nimport { PaymentIcon } from \"react-svg-credit-card-payment-icons\";\nimport { cn } from \"@/lib/utils\";\n\nconst useSupportsHover = () => {\n  const [supportsHover, setSupportsHover] = useState(false);\n\n  useEffect(() => {\n    const mql = window.matchMedia(\"(hover: hover)\");\n    const handler = (e: MediaQueryListEvent) => setSupportsHover(e.matches);\n\n    setSupportsHover(mql.matches);\n    mql.addEventListener(\"change\", handler);\n\n    return () => mql.removeEventListener(\"change\", handler);\n  }, []);\n\n  return supportsHover;\n};\n\nexport type CreditCardProps = HTMLAttributes<HTMLDivElement>;\n\nexport const CreditCard = ({ className, ...props }: CreditCardProps) => (\n  <div\n    className={cn(\n      \"group/kibo-credit-card perspective-distant aspect-[8560/5398] w-full max-w-96 text-white\",\n      \"@container\",\n      className\n    )}\n    {...props}\n  />\n);\n\nconst CreditCardFlipContext = createContext(false);\n\nexport type CreditCardFlipperProps = HTMLAttributes<HTMLDivElement>;\n\nexport const CreditCardFlipper = ({\n  className,\n  children,\n  ...props\n}: CreditCardFlipperProps & { children?: ReactNode }) => {\n  const supportsHover = useSupportsHover();\n  const [isFlipped, setIsFlipped] = useState(false);\n\n  const handleClick = () => {\n    if (!supportsHover) {\n      setIsFlipped((prev) => !prev);\n    }\n  };\n\n  return (\n    <CreditCardFlipContext.Provider value={true}>\n      {/* biome-ignore lint/nursery/noStaticElementInteractions: tap to flip for touch devices */}\n      <div\n        aria-label=\"Flip credit card\"\n        className={cn(\n          \"h-full w-full\",\n          \"@xs:rounded-2xl rounded-lg\",\n          \"transform-3d transition duration-700 ease-in-out\",\n          supportsHover &&\n            \"group-hover/kibo-credit-card:-rotate-y-180 group-hover/kibo-credit-card:shadow-lg\",\n          !supportsHover && isFlipped && \"-rotate-y-180 shadow-lg\",\n          className\n        )}\n        onClick={handleClick}\n        {...props}\n      >\n        {children}\n      </div>\n    </CreditCardFlipContext.Provider>\n  );\n};\n\nexport type CreditCardNameProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const CreditCardName = ({\n  className,\n  style,\n  ...props\n}: CreditCardNameProps) => (\n  <p\n    className={cn(\"font-semibold uppercase\", className)}\n    style={{\n      lineHeight: \"100%\",\n      ...style,\n    }}\n    {...props}\n  />\n);\n\nexport type CreditCardChipProps = HTMLAttributes<SVGSVGElement>;\n\nexport const CreditCardChip = ({\n  className,\n  children,\n  ...props\n}: CreditCardChipProps) =>\n  children ? (\n    <div\n      className={cn(\n        \"-translate-y-1/2 absolute top-1/2 left-0 w-1/6 shrink-0 rounded-[18%]\",\n        className\n      )}\n    >\n      {children}\n    </div>\n  ) : (\n    <svg\n      className={cn(\n        \"-translate-y-1/2 absolute top-1/2 left-0 w-1/6 shrink-0 rounded-[18%]\",\n        className\n      )}\n      enableBackground=\"new 0 0 110 92\"\n      viewBox=\"0 0 110 92\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <title>Chip</title>\n      <path\n        d=\"M1 13A12 12 0 0 1 13 1h84a12 12 0 0 1 12 12v66a12 12 0 0 1-12 12H13A12 12 0 0 1 1 79V13Z\"\n        fill=\"url(#kibo-credit-card-chip-gradient)\"\n      />\n      <path\n        d=\"M108 71.5H83.65L70.53 60.87A21.41 21.41 0 0 1 56 67.47V90h41a11 11 0 0 0 11-11v-7.5ZM76.48 47a21.38 21.38 0 0 1-4.63 12.36l12.5 10.14H108V47H76.48ZM2 69.5h24.14l12.02-10.12A21.38 21.38 0 0 1 33.52 47H2v22.5Zm53-43c-5.85 0-11.1 2.57-14.68 6.66A19.4 19.4 0 0 0 35.5 46a19.4 19.4 0 0 0 4.82 12.84A19.43 19.43 0 0 0 55 65.5c5.85 0 11.1-2.57 14.68-6.66A19.4 19.4 0 0 0 74.5 46a19.4 19.4 0 0 0-4.82-12.84A19.43 19.43 0 0 0 55 26.5Zm16.85 6.14A21.38 21.38 0 0 1 76.48 45H108V22.5H84.35l-12.5 10.14ZM2 45h31.52a21.38 21.38 0 0 1 4.64-12.38L26.14 22.5H2V45Zm0 34a11 11 0 0 0 11 11h41V67.47a21.41 21.41 0 0 1-14.52-6.59L27.14 71.26l-.27.24H2V79Zm106-66A11 11 0 0 0 97 2H56v22.52c5.7.27 10.83 2.74 14.53 6.61L83.65 20.5H108V13ZM2 20.5h24.87l.27.24 12.34 10.38A21.41 21.41 0 0 1 54 24.52V2H13A11 11 0 0 0 2 13v7.5ZM110 79a13 13 0 0 1-13 13H13A13 13 0 0 1 0 79V13A13 13 0 0 1 13 0h84a13 13 0 0 1 13 13v66Z\"\n        fill=\"#000\"\n      />\n      <defs>\n        <linearGradient\n          gradientUnits=\"userSpaceOnUse\"\n          id=\"kibo-credit-card-chip-gradient\"\n          x1=\"1\"\n          x2=\"112.7\"\n          y1=\"46\"\n          y2=\"78.12\"\n        >\n          <stop stopColor=\"#EDE5A6\" />\n          <stop offset=\"1\" stopColor=\"#CFA255\" />\n        </linearGradient>\n      </defs>\n    </svg>\n  );\n\nexport type CreditCardLogoProps = HTMLAttributes<HTMLDivElement>;\n\nexport const CreditCardLogo = ({\n  className,\n  ...props\n}: CreditCardLogoProps) => (\n  <div\n    className={cn(\"absolute top-0 right-0 size-1/6\", className)}\n    {...props}\n  />\n);\n\nexport type CreditCardFrontProps = HTMLAttributes<HTMLDivElement> & {\n  safeArea?: number;\n};\n\nexport const CreditCardFront = ({\n  className,\n  safeArea = 20,\n  children,\n  ...props\n}: CreditCardFrontProps) => (\n  <div\n    className={cn(\n      \"backface-hidden absolute inset-0 flex overflow-hidden bg-foreground/90\",\n      \"@xs:rounded-2xl rounded-lg\",\n      className\n    )}\n    {...props}\n  >\n    <div\n      className=\"relative flex-1\"\n      style={{\n        margin: `${safeArea}px`,\n      }}\n    >\n      {children}\n    </div>\n  </div>\n);\n\nexport type CreditCardServiceProviderProps = ComponentProps<typeof PaymentIcon>;\n\nexport const CreditCardServiceProvider = ({\n  className,\n  children,\n  type = \"Visa\",\n  ...props\n}: CreditCardServiceProviderProps) => {\n  if (children) {\n    return (\n      <div\n        className={cn(\n          \"absolute right-0 bottom-0\",\n          \"max-h-1/3 max-w-1/3\",\n          className\n        )}\n      >\n        {children}\n      </div>\n    );\n  }\n\n  return (\n    <PaymentIcon\n      className={cn(\n        \"absolute right-0 bottom-0\",\n        \"max-h-1/3 max-w-1/3\",\n        className\n      )}\n      type={type}\n      {...props}\n    />\n  );\n};\n\nexport type CreditCardMagStripeProps = HTMLAttributes<HTMLDivElement>;\n\nexport type CreditCardBackContextValue = {\n  safeArea: number;\n};\n\nconst CreditCardBackContext = createContext<CreditCardBackContextValue>({\n  safeArea: 20,\n});\n\nexport type CreditCardBackProps = HTMLAttributes<HTMLDivElement> & {\n  safeArea?: number;\n};\n\nexport const CreditCardBack = ({\n  safeArea = 16,\n  children,\n  className,\n  ...props\n}: CreditCardBackProps) => {\n  const isInsideFlipper = useContext(CreditCardFlipContext);\n\n  return (\n    <CreditCardBackContext.Provider value={{ safeArea }}>\n      <div\n        className={cn(\n          \"backface-hidden absolute inset-0 flex overflow-hidden bg-foreground/90\",\n          \"@xs:rounded-2xl rounded-lg\",\n          isInsideFlipper && \"rotate-y-180\",\n          className\n        )}\n        {...props}\n      >\n        <div\n          className=\"relative flex-1\"\n          style={{\n            margin: `${safeArea}px`,\n          }}\n        >\n          {children}\n        </div>\n      </div>\n    </CreditCardBackContext.Provider>\n  );\n};\n\nexport const CreditCardMagStripe = ({\n  className,\n  ...props\n}: CreditCardMagStripeProps) => {\n  const context = useContext(CreditCardBackContext);\n\n  return (\n    <div\n      className={cn(\n        \"-translate-x-1/2 absolute top-[3%] left-1/2 h-1/4 bg-gray-900\",\n        className\n      )}\n      style={{\n        width: `calc(100% + 2 * ${context.safeArea}px)`,\n      }}\n      {...props}\n    />\n  );\n};\n\nexport type CreditCardNumberProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const CreditCardNumber = ({\n  className,\n  children,\n  style,\n  ...props\n}: CreditCardNumberProps) => (\n  <p\n    className={cn(\"font-mono\", \"@xs:text-2xl\", className)}\n    style={{\n      lineHeight: \"100%\",\n      ...style,\n    }}\n    {...props}\n  >\n    {children}\n  </p>\n);\n\nexport type CreditCardExpiryProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const CreditCardExpiry = ({\n  className,\n  style,\n  ...props\n}: CreditCardExpiryProps) => (\n  <p\n    className={cn(\"font-mono\", className)}\n    style={{\n      lineHeight: \"100%\",\n      ...style,\n    }}\n    {...props}\n  />\n);\n\nexport type CreditCardCvvProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const CreditCardCvv = ({\n  className,\n  style,\n  ...props\n}: CreditCardCvvProps) => (\n  <p\n    className={cn(\"font-mono\", className)}\n    style={{\n      lineHeight: \"100%\",\n      ...style,\n    }}\n    {...props}\n  />\n);\n","target":"components/kibo-ui/credit-card/index.tsx"}],"css":{}}