{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"lazy-image","type":"registry:component","description":"Lazy image component.","files":[{"path":"registry/components/lazy-image.tsx","type":"registry:component","content":"\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { useInView } from \"motion/react\";\nimport React from \"react\";\nimport { AspectRatio } from \"@/components/ui/aspect-ratio\";\n\ntype LazyImageProps = {\n\talt: string;\n\tsrc: string;\n\tclassName?: string;\n\tcontainerClassName?: string;\n\t/** URL of the fallback image. default: undefined */\n\tfallback?: string;\n\t/** The ratio of the image. */\n\tratio: number;\n\t/** Whether the image should only load when it is in view. default: false */\n\tinView?: boolean;\n};\n\nexport function LazyImage({\n\talt,\n\tsrc,\n\tratio,\n\tfallback,\n\tinView = false,\n\tclassName,\n\tcontainerClassName,\n}: LazyImageProps) {\n\tconst ref = React.useRef<HTMLDivElement | null>(null);\n\tconst imgRef = React.useRef<HTMLImageElement | null>(null);\n\tconst isInView = useInView(ref, { once: true });\n\n\tconst [imgSrc, setImgSrc] = React.useState<string | undefined>(\n\t\tinView ? undefined : src\n\t);\n\tconst [isLoading, setIsLoading] = React.useState(true);\n\n\tconst handleError = () => {\n\t\tif (fallback) {\n\t\t\tsetImgSrc(fallback);\n\t\t}\n\t\tsetIsLoading(false);\n\t};\n\n\tconst handleLoad = React.useCallback(() => {\n\t\tsetIsLoading(false);\n\t}, []);\n\n\t// Load image only when inView\n\tReact.useEffect(() => {\n\t\tif (inView && isInView && !imgSrc) {\n\t\t\tsetImgSrc(src);\n\t\t}\n\t}, [inView, isInView, src, imgSrc]);\n\n\t// Handle cached images instantly\n\tReact.useEffect(() => {\n\t\tif (imgRef.current?.complete) {\n\t\t\thandleLoad();\n\t\t}\n\t}, [handleLoad]);\n\n\treturn (\n\t\t<AspectRatio\n\t\t\tclassName={cn(\n\t\t\t\t\"relative size-full overflow-hidden border bg-accent/30\",\n\t\t\t\tcontainerClassName\n\t\t\t)}\n\t\t\tratio={ratio}\n\t\t\tref={ref}\n\t\t>\n\t\t\t{imgSrc && (\n\t\t\t\t// biome-ignore lint/correctness/useImageSize: dynamic image size\n\t\t\t\t<img\n\t\t\t\t\talt={alt}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"size-full object-cover transition-opacity duration-500\",\n\t\t\t\t\t\tisLoading ? \"opacity-0\" : \"opacity-100\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\tfetchPriority={inView ? \"high\" : \"low\"}\n\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\tonError={handleError}\n\t\t\t\t\tonLoad={handleLoad}\n\t\t\t\t\tref={imgRef}\n\t\t\t\t\trole=\"presentation\" // Changed from \"img\" to \"presentation\" since it's decorative\n\t\t\t\t\tsrc={imgSrc}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</AspectRatio>\n\t);\n}\n"}],"registryDependencies":["aspect-ratio"]}