{
  "name": "ui-components-bitcoinimage",
  "type": "registry:component",
  "dependencies": [
    "bitcoin-image"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/ui-components/BitcoinImage.tsx",
      "type": "registry:component",
      "content": "import { ImageProtocols } from \"bitcoin-image\";\nimport React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Initialize bitcoin-image protocols globally\nconst imageProtocols = new ImageProtocols();\n\nexport interface BitcoinImageProps {\n\t/**\n\t * Image source - can be blockchain URL (b://, ord://, etc.) or regular URL\n\t */\n\tsrc?: string;\n\t/**\n\t * Alt text for accessibility\n\t */\n\talt: string;\n\t/**\n\t * Additional styles to apply to the image\n\t */\n\tstyle?: React.CSSProperties;\n\t/**\n\t * Additional CSS classes to apply to the image\n\t */\n\tclassName?: string;\n\t/**\n\t * Fallback content when image fails to load\n\t */\n\tfallback?: React.ReactNode;\n\t/**\n\t * Show loading state\n\t */\n\tshowLoading?: boolean;\n\t/**\n\t * Timeout for image loading (ms)\n\t */\n\ttimeout?: number;\n}\n\n/**\n * BitcoinImage component that handles on-chain image resolution\n *\n * Automatically resolves blockchain image URLs (b://, ord://, etc.) to displayable URLs\n * using the bitcoin-image library. Falls back gracefully for invalid or missing images.\n */\nexport function BitcoinImage({\n\tsrc,\n\talt,\n\tstyle,\n\tclassName,\n\tfallback,\n\tshowLoading = true,\n\ttimeout = 5000,\n}: BitcoinImageProps) {\n\tconst [displayUrl, setDisplayUrl] = React.useState<string>(\"\");\n\tconst [isLoading, setIsLoading] = React.useState(true);\n\tconst [hasError, setHasError] = React.useState(false);\n\n\tReact.useEffect(() => {\n\t\tlet mounted = true;\n\n\t\tconst loadImage = async () => {\n\t\t\tif (!src) {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t\tsetHasError(true);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsetIsLoading(true);\n\t\t\t\tsetHasError(false);\n\n\t\t\t\tconst url = await imageProtocols.getDisplayUrl(src, {\n\t\t\t\t\tfallback: undefined, // Handle fallback in component\n\t\t\t\t\ttimeout,\n\t\t\t\t});\n\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetDisplayUrl(url);\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetDisplayUrl(\"\");\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t\tsetHasError(true);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tloadImage();\n\n\t\treturn () => {\n\t\t\tmounted = false;\n\t\t};\n\t}, [src, timeout]);\n\n\t// Show loading state\n\tif (isLoading && showLoading) {\n\t\treturn (\n\t\t\t<div className=\"flex items-center justify-center w-full h-full\">\n\t\t\t\t<span className=\"text-xs text-muted-foreground\">Loading...</span>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Show error or fallback\n\tif (hasError || !displayUrl) {\n\t\treturn fallback ? <>{fallback}</> : null;\n\t}\n\n\t// Show resolved image\n\treturn (\n\t\t<img\n\t\t\tsrc={displayUrl}\n\t\t\talt={alt}\n\t\t\tclassName={cn(\"w-full h-full object-cover\", className)}\n\t\t\tstyle={style}\n\t\t\tonError={() => setHasError(true)}\n\t\t/>\n\t);\n}\n",
      "target": "<%- config.aliases.components %>/bitcoinimage.tsx"
    }
  ]
}