{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "PixelTransition-TS-TW",
	"title": "PixelTransition",
	"description": "Pixel dissolve transition for content reveal on hover.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "PixelTransition/PixelTransition.tsx",
			"content": "import React, { useRef, useEffect, useState, type CSSProperties } from 'react';\nimport { gsap } from 'gsap';\n\ninterface PixelTransitionProps {\n  firstContent: React.ReactNode | string;\n  secondContent: React.ReactNode | string;\n  gridSize?: number;\n  pixelColor?: string;\n  animationStepDuration?: number;\n  once?: boolean;\n  className?: string;\n  style?: CSSProperties;\n  aspectRatio?: string;\n}\n\nconst PixelTransition: React.FC<PixelTransitionProps> = ({\n  firstContent,\n  secondContent,\n  gridSize = 7,\n  pixelColor = 'currentColor',\n  animationStepDuration = 0.3,\n  once = false,\n  aspectRatio = '100%',\n  className = '',\n  style = {}\n}) => {\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const pixelGridRef = useRef<HTMLDivElement | null>(null);\n  const activeRef = useRef<HTMLDivElement | null>(null);\n  const delayedCallRef = useRef<gsap.core.Tween | null>(null);\n\n  const [isActive, setIsActive] = useState<boolean>(false);\n\n  const isTouchDevice =\n    'ontouchstart' in window || navigator.maxTouchPoints > 0 || window.matchMedia('(pointer: coarse)').matches;\n\n  useEffect(() => {\n    const pixelGridEl = pixelGridRef.current;\n    if (!pixelGridEl) return;\n\n    pixelGridEl.innerHTML = '';\n\n    for (let row = 0; row < gridSize; row++) {\n      for (let col = 0; col < gridSize; col++) {\n        const pixel = document.createElement('div');\n        pixel.classList.add('pixelated-image-card__pixel');\n        pixel.classList.add('absolute', 'hidden');\n        pixel.style.backgroundColor = pixelColor;\n\n        const size = 100 / gridSize;\n        pixel.style.width = `${size}%`;\n        pixel.style.height = `${size}%`;\n        pixel.style.left = `${col * size}%`;\n        pixel.style.top = `${row * size}%`;\n\n        pixelGridEl.appendChild(pixel);\n      }\n    }\n  }, [gridSize, pixelColor]);\n\n  const animatePixels = (activate: boolean): void => {\n    setIsActive(activate);\n\n    const pixelGridEl = pixelGridRef.current;\n    const activeEl = activeRef.current;\n    if (!pixelGridEl || !activeEl) return;\n\n    const pixels = pixelGridEl.querySelectorAll<HTMLDivElement>('.pixelated-image-card__pixel');\n    if (!pixels.length) return;\n\n    gsap.killTweensOf(pixels);\n    if (delayedCallRef.current) {\n      delayedCallRef.current.kill();\n    }\n\n    gsap.set(pixels, { display: 'none' });\n\n    const totalPixels = pixels.length;\n    const staggerDuration = animationStepDuration / totalPixels;\n\n    gsap.to(pixels, {\n      display: 'block',\n      duration: 0,\n      stagger: {\n        each: staggerDuration,\n        from: 'random'\n      }\n    });\n\n    delayedCallRef.current = gsap.delayedCall(animationStepDuration, () => {\n      activeEl.style.display = activate ? 'block' : 'none';\n      activeEl.style.pointerEvents = activate ? 'none' : '';\n    });\n\n    gsap.to(pixels, {\n      display: 'none',\n      duration: 0,\n      delay: animationStepDuration,\n      stagger: {\n        each: staggerDuration,\n        from: 'random'\n      }\n    });\n  };\n\n  const handleEnter = (): void => {\n    if (!isActive) animatePixels(true);\n  };\n  const handleLeave = (): void => {\n    if (isActive && !once) animatePixels(false);\n  };\n  const handleClick = (): void => {\n    if (!isActive) animatePixels(true);\n    else if (isActive && !once) animatePixels(false);\n  };\n  return (\n    <div\n      ref={containerRef}\n      className={`\n        ${className}\n        bg-[#222]\n        text-white\n        rounded-[15px]\n        border-2\n        border-white\n        w-[300px]\n        max-w-full\n        relative\n        overflow-hidden\n      `}\n      style={style}\n      onMouseEnter={!isTouchDevice ? handleEnter : undefined}\n      onMouseLeave={!isTouchDevice ? handleLeave : undefined}\n      onClick={isTouchDevice ? handleClick : undefined}\n      onFocus={!isTouchDevice ? handleEnter : undefined}\n      onBlur={!isTouchDevice ? handleLeave : undefined}\n      tabIndex={0}\n    >\n      <div style={{ paddingTop: aspectRatio }} />\n\n      <div className=\"absolute inset-0 w-full h-full\" aria-hidden={isActive}>\n        {firstContent}\n      </div>\n\n      <div\n        ref={activeRef}\n        className=\"absolute inset-0 w-full h-full z-[2]\"\n        style={{ display: 'none' }}\n        aria-hidden={!isActive}\n      >\n        {secondContent}\n      </div>\n\n      <div ref={pixelGridRef} className=\"absolute inset-0 w-full h-full pointer-events-none z-[3]\" />\n    </div>\n  );\n};\n\nexport default PixelTransition;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"gsap@^3.13.0"
	]
}