{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "image-gallery-1",
  "description": "Masonry-style responsive gallery using random images with dynamic aspect ratios.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "aspect-ratio"
  ],
  "files": [
    {
      "path": "registry/blocks/image-gallery/1/image-gallery.tsx",
      "content": "import { LazyImage } from \"./lazy-image\";\n\nexport function ImageGallery() {\n  return (\n    <div className=\"relative flex min-h-screen w-full flex-col items-center justify-center px-4 py-10\">\n      <div className=\"mx-auto grid w-full max-w-5xl grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4 md:gap-6\">\n        {Array.from({ length: 4 }).map((_, col) => (\n          // biome-ignore lint/suspicious/noArrayIndexKey: fixed gallery layout\n          <div className=\"grid gap-4\" key={`col-${col}`}>\n            {/* biome-ignore lint/nursery/noShadow: false positive */}\n            {Array.from({ length: 8 }).map((_, index) => {\n              const isPortrait = Math.random() > 0.5;\n              const width = isPortrait ? 1080 : 1920;\n              const height = isPortrait ? 1920 : 1080;\n              const ratio = isPortrait ? 9 / 16 : 16 / 9;\n\n              return (\n                <LazyImage\n                  alt={`Image ${col}-${index}`}\n                  fallback={`https://placehold.co/${width}x${height}/`}\n                  inView={true}\n                  // biome-ignore lint/suspicious/noArrayIndexKey: fixed gallery image seed\n                  key={`img-${col}-${index}`}\n                  ratio={ratio}\n                  src={`https://picsum.photos/seed/${col}-${index}/${width}/${height}`}\n                />\n              );\n            })}\n          </div>\n        ))}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/image-gallery/1/lazy-image.tsx",
      "content": "\"use client\";\n\nimport { useInView } from \"motion/react\";\nimport React from \"react\";\nimport { AspectRatio } from \"@/components/ui/aspect-ratio\";\nimport { cn } from \"@/lib/utils\";\n\ntype LazyImageProps = {\n  alt: string;\n  src: string;\n  className?: string;\n  AspectRatioClassName?: string;\n  /** URL of the fallback image. default: undefined */\n  fallback?: string;\n  /** The ratio of the image. */\n  ratio: number;\n  /** Whether the image should only load when it is in view. default: false */\n  inView?: boolean;\n};\n\nexport function LazyImage({\n  alt,\n  src,\n  ratio,\n  fallback,\n  inView = false,\n  className,\n  AspectRatioClassName,\n}: LazyImageProps) {\n  const ref = React.useRef<HTMLDivElement | null>(null);\n  const imgRef = React.useRef<HTMLImageElement | null>(null);\n  const isInView = useInView(ref, { once: true });\n\n  const [imgSrc, setImgSrc] = React.useState<string | undefined>(\n    inView ? undefined : src\n  );\n  const [isLoading, setIsLoading] = React.useState(true);\n\n  const handleError = () => {\n    if (fallback) {\n      setImgSrc(fallback);\n    }\n    setIsLoading(false);\n  };\n\n  const handleLoad = React.useCallback(() => {\n    setIsLoading(false);\n  }, []);\n\n  // Load image only when inView\n  React.useEffect(() => {\n    if (inView && isInView && !imgSrc) {\n      setImgSrc(src);\n    }\n  }, [inView, isInView, src, imgSrc]);\n\n  // Handle cached images instantly\n  React.useEffect(() => {\n    if (imgRef.current?.complete) {\n      handleLoad();\n    }\n  }, [handleLoad]);\n\n  return (\n    <AspectRatio\n      className={cn(\n        \"relative size-full overflow-hidden rounded-lg border bg-accent/30\",\n        AspectRatioClassName\n      )}\n      ratio={ratio}\n      ref={ref}\n    >\n      {imgSrc && (\n        // biome-ignore lint/correctness/useImageSize: dynamic image size\n        <img\n          alt={alt}\n          className={cn(\n            \"size-full rounded-md object-cover transition-opacity duration-500\",\n            isLoading ? \"opacity-0\" : \"opacity-100\",\n            className\n          )}\n          decoding=\"async\"\n          fetchPriority={inView ? \"high\" : \"low\"}\n          loading=\"lazy\"\n          onError={handleError}\n          onLoad={handleLoad}\n          ref={imgRef}\n          role=\"presentation\" // Changed from \"img\" to \"presentation\" since it's decorative\n          src={imgSrc}\n        />\n      )}\n    </AspectRatio>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "image-gallery"
  ],
  "type": "registry:block"
}