{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "qr-code-share-dialog",
  "type": "registry:component",
  "title": "QR Code Share Dialog",
  "description": "A share dialog with a QR code for a link, a copy button, a PNG download and the native share sheet.",
  "author": "bucharitesh <https://qrdx.dev>",
  "dependencies": ["qrdx", "lucide-react"],
  "registryDependencies": ["button", "dialog", "input"],
  "files": [
    {
      "path": "registry/qrdx/qr-code-share-dialog.tsx",
      "type": "registry:component",
      "content": "\"use client\";\n\nimport { Check, Copy, Download, Share2 } from \"lucide-react\";\nimport { downloadQRCode, getQRData, QRCode } from \"qrdx\";\nimport {\n  type ComponentProps,\n  type ReactNode,\n  useEffect,\n  useId,\n  useState,\n} from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\n\n/** qrdx style options: colors, gradients, patterns, logo, template. */\nexport type QrCodeStyle = Omit<ComponentProps<typeof QRCode>, \"value\" | \"size\">;\n\nexport interface QrCodeShareDialogProps\n  extends Omit<ComponentProps<typeof Dialog>, \"children\"> {\n  /** The link to share. It is encoded in the QR code. */\n  url: string;\n  /**\n   * Dialog title.\n   * @default \"Share link\"\n   */\n  title?: string;\n  /**\n   * Text under the title.\n   * @default \"Anyone with the link or the QR code can open it.\"\n   */\n  description?: ReactNode;\n  /** Custom trigger element. Defaults to a \"Share\" button. */\n  children?: ReactNode;\n  /**\n   * Width and height of the code in pixels.\n   * @default 200\n   */\n  size?: number;\n  /** qrdx style options for the code. */\n  qr?: QrCodeStyle;\n  /**\n   * File name for the PNG download, without extension.\n   * @default \"qr-code\"\n   */\n  filename?: string;\n}\n\nexport function QrCodeShareDialog({\n  url,\n  title = \"Share link\",\n  description = \"Anyone with the link or the QR code can open it.\",\n  children,\n  size = 200,\n  qr,\n  filename = \"qr-code\",\n  ...props\n}: QrCodeShareDialogProps) {\n  const inputId = useId();\n  const [copied, setCopied] = useState(false);\n  const [canShare, setCanShare] = useState(false);\n\n  useEffect(() => {\n    setCanShare(typeof navigator !== \"undefined\" && \"share\" in navigator);\n  }, []);\n\n  async function copyLink() {\n    await navigator.clipboard.writeText(url);\n    setCopied(true);\n    setTimeout(() => setCopied(false), 1500);\n  }\n\n  async function downloadPng() {\n    // getQRData lays a logo out for 1024px, the size of this file.\n    await downloadQRCode(getQRData({ margin: 2, ...qr, value: url }), {\n      format: \"png\",\n      size: { width: 1024, height: 1024 },\n      filename: `${filename}.png`,\n    });\n  }\n\n  async function share() {\n    try {\n      await navigator.share({ title, url });\n    } catch {\n      // Closing the share sheet rejects; nothing to do.\n    }\n  }\n\n  return (\n    <Dialog {...props}>\n      <DialogTrigger asChild>\n        {children ?? (\n          <Button variant=\"outline\">\n            <Share2 aria-hidden=\"true\" />\n            Share\n          </Button>\n        )}\n      </DialogTrigger>\n      <DialogContent className=\"sm:max-w-sm\">\n        <DialogHeader>\n          <DialogTitle>{title}</DialogTitle>\n          <DialogDescription>{description}</DialogDescription>\n        </DialogHeader>\n        <div className=\"flex justify-center\">\n          <div\n            aria-label={`QR code: ${url}`}\n            className=\"overflow-hidden rounded-[10px] border\"\n            role=\"img\"\n            style={{ width: size, height: size }}\n          >\n            <QRCode margin={2} {...qr} size={size} value={url} />\n          </div>\n        </div>\n        <div className=\"flex items-center gap-2\">\n          <label className=\"sr-only\" htmlFor={inputId}>\n            Link\n          </label>\n          <Input\n            className=\"font-mono text-xs\"\n            id={inputId}\n            onClick={(event) => event.currentTarget.select()}\n            readOnly\n            value={url}\n          />\n          <Button\n            aria-label={copied ? \"Link copied\" : \"Copy link\"}\n            onClick={copyLink}\n            size=\"icon\"\n            type=\"button\"\n            variant=\"outline\"\n          >\n            {copied ? (\n              <Check aria-hidden=\"true\" />\n            ) : (\n              <Copy aria-hidden=\"true\" />\n            )}\n          </Button>\n        </div>\n        <DialogFooter className=\"gap-2 sm:justify-center\">\n          <Button onClick={downloadPng} type=\"button\" variant=\"outline\">\n            <Download aria-hidden=\"true\" />\n            Download PNG\n          </Button>\n          {canShare ? (\n            <Button onClick={share} type=\"button\">\n              <Share2 aria-hidden=\"true\" />\n              Share…\n            </Button>\n          ) : null}\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
    }
  ],
  "docs": "Import it with `import { QrCodeShareDialog } from \"@/components/qr-code-share-dialog\"`. Props and examples: https://qrdx.dev/docs/components/qr-code-share-dialog",
  "categories": ["qr-code"]
}
