{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "image-reveal2",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./registry/components/image-reveal/index.tsx",
      "content": "'use client';\n\nimport { useMediaQuery } from '@/hooks/use-media-query';\nimport { ArrowUpRight, MoveUpRight } from 'lucide-react';\nimport type React from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\ninterface ImageData {\n  id: number;\n  src: string;\n  alt: string;\n}\n\nconst images: ImageData[] = [\n  {\n    id: 1,\n    src: 'https://images.unsplash.com/photo-1682806816936-c3ac11f65112?q=80&w=1274&auto=format&fit=crop',\n    alt: 'Follow Your Path',\n  },\n  {\n    id: 2,\n    src: 'https://images.unsplash.com/photo-1681063762354-d542c03bbfc5?q=80&w=1274&auto=format&fit=crop',\n    alt: 'Shine Bright',\n  },\n  {\n    id: 3,\n    src: 'https://images.unsplash.com/photo-1679640034489-a6db1f096b70?q=80&w=1274&auto=format&fit=crop',\n    alt: 'Create Magic',\n  },\n  {\n    id: 4,\n    src: 'https://images.unsplash.com/photo-1679482451632-b2e126da7142?q=80&w=1274&auto=format&fit=crop',\n    alt: 'Keep Moving Forward',\n  },\n];\n\nconst ImageReveal2: React.FC = () => {\n  const isDesktop = useMediaQuery('(min-width: 768px)');\n  const [activeImage, setActiveImage] = useState<ImageData | null>(null);\n  const [cursorPosition, setCursorPosition] = useState({ x: 0, y: 0 });\n  const [opacity, setOpacity] = useState(0);\n  const [scale, setScale] = useState(0.5);\n  const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n  const requestRef = useRef<number | null>(null);\n  const prevCursorPosition = useRef({ x: 0, y: 0 });\n\n  const handleMouseMove = useCallback((e: MouseEvent) => {\n    const { clientX, clientY } = e;\n    const dx = clientX - prevCursorPosition.current.x;\n    const dy = clientY - prevCursorPosition.current.y;\n\n    // Apply easing to the cursor movement\n    const easeAmount = 0.2;\n    const newX = prevCursorPosition.current.x + dx * easeAmount;\n    const newY = prevCursorPosition.current.y + dy * easeAmount;\n\n    setCursorPosition({ x: newX, y: newY });\n    prevCursorPosition.current = { x: newX, y: newY };\n  }, []);\n\n  useEffect(() => {\n    const updateCursorPosition = (e: MouseEvent) => {\n      if (requestRef.current) return;\n      requestRef.current = requestAnimationFrame(() => {\n        handleMouseMove(e);\n        requestRef.current = null;\n      });\n    };\n\n    window.addEventListener('mousemove', updateCursorPosition);\n    return () => {\n      window.removeEventListener('mousemove', updateCursorPosition);\n      if (requestRef.current) cancelAnimationFrame(requestRef.current);\n    };\n  }, [handleMouseMove]);\n\n  const handleImageHover = useCallback(\n    (image: ImageData) => {\n      if (activeImage !== image) {\n        setActiveImage(image);\n        if (timeoutRef.current) clearTimeout(timeoutRef.current);\n        timeoutRef.current = setTimeout(() => {\n          setOpacity(1);\n          setScale(1);\n        }, 50);\n      } else {\n        setOpacity(1);\n        setScale(1);\n      }\n    },\n    [activeImage]\n  );\n\n  const handleMouseLeave = useCallback(() => {\n    setOpacity(0);\n    setScale(0.5);\n    if (timeoutRef.current) clearTimeout(timeoutRef.current);\n    timeoutRef.current = setTimeout(() => {\n      setActiveImage(null);\n    }, 300);\n  }, []);\n\n  return (\n    <div className='relative w-full' onMouseLeave={handleMouseLeave}>\n      {images.map((image) => (\n        <div\n          key={image.id}\n          className={`px-2 cursor-pointer relative sm:flex items-center border-b border-primary justify-between`}\n          onMouseEnter={() => handleImageHover(image)}\n        >\n          {!isDesktop && (\n            <img\n              src={image?.src}\n              className='sm:w-32 sm:h-20 w-full h-52 object-cover rounded-md'\n              alt='mobileImg'\n            />\n          )}\n          <h2\n            className={`newFont dark:text-neutral-300 uppercase md:text-5xl sm:text-2xl text-xl sm:py-6 py-2 leading-[100%] relative ${\n              activeImage?.id === image?.id\n                ? 'mix-blend-difference z-20 text-neutral-300'\n                : 'text-neutral-700'\n            }`}\n          >\n            {image.alt}\n          </h2>\n          <button\n            className={`sm:block hidden p-2 rounded-full transition-all duration-300 ease-out ${\n              activeImage?.id === image?.id ? 'mix-blend-difference z-20 bg-white text-black' : ''\n            }`}\n          >\n            <ArrowUpRight className='w-8 h-8' />\n          </button>\n          <div\n            className={`w-full dark:bg-white bg-black absolute bottom-0 left-0 transition-all duration-300 ease-linear ${\n              activeImage?.id === image?.id ? 'h-full' : 'h-0'\n            }`}\n          />\n        </div>\n      ))}\n      {isDesktop && activeImage && (\n        <img\n          src={activeImage.src}\n          alt={activeImage.alt}\n          className={`fixed dark:bg-neutral-950 rotate-12 bg-white object-cover pointer-events-none z-10 w-[300px] h-[400px] rounded-lg`}\n          style={{\n            left: `${cursorPosition.x}px`,\n            top: `${cursorPosition.y}px`,\n            transform: `translate(-50%, -50%) scale(${scale})`,\n            opacity: opacity,\n          }}\n        />\n      )}\n    </div>\n  );\n};\n\nexport default ImageReveal2;\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}