{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "clipped-circle",
  "title": "Clipped Circle",
  "description": "A cursor-following spotlight effect that reveals a soft glowing circle wherever the user moves their mouse inside the container.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/components/unlumen/clipped-circle/index.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { motion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface ClippedCircleProps {\n  className?: string;\n  circleClassName?: string;\n  circleSize?: number;\n}\n\nfunction ClippedCircle({\n  className,\n  circleClassName = \"bg-white/20\",\n  circleSize = 400,\n}: ClippedCircleProps) {\n  const containerRef = React.useRef<HTMLDivElement>(null);\n  const [isHovered, setIsHovered] = React.useState(false);\n  const [position, setPosition] = React.useState({ x: \"50%\", y: \"50%\" });\n\n  React.useEffect(() => {\n    const container = containerRef.current;\n    if (!container || !container.parentElement) return;\n\n    const parent = container.parentElement;\n\n    const handleMouseEnter = (e: MouseEvent) => {\n      const rect = parent.getBoundingClientRect();\n      const x = ((e.clientX - rect.left) / rect.width) * 100;\n      const y = ((e.clientY - rect.top) / rect.height) * 100;\n      setPosition({ x: `${x}%`, y: `${y}%` });\n      setIsHovered(true);\n    };\n\n    const handleMouseMove = (e: MouseEvent) => {\n      const rect = parent.getBoundingClientRect();\n      const x = ((e.clientX - rect.left) / rect.width) * 100;\n      const y = ((e.clientY - rect.top) / rect.height) * 100;\n      setPosition({ x: `${x}%`, y: `${y}%` });\n    };\n\n    const handleMouseLeave = () => {\n      setIsHovered(false);\n    };\n\n    parent.addEventListener(\"mouseenter\", handleMouseEnter);\n    parent.addEventListener(\"mousemove\", handleMouseMove);\n    parent.addEventListener(\"mouseleave\", handleMouseLeave);\n\n    return () => {\n      parent.removeEventListener(\"mouseenter\", handleMouseEnter);\n      parent.removeEventListener(\"mousemove\", handleMouseMove);\n      parent.removeEventListener(\"mouseleave\", handleMouseLeave);\n    };\n  }, []);\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        \"absolute inset-0 overflow-hidden pointer-events-none\",\n        className,\n      )}\n    >\n      <motion.div\n        className={cn(\n          \"pointer-events-none absolute rounded-full\",\n          circleClassName,\n        )}\n        style={{\n          left: position.x,\n          top: position.y,\n          width: circleSize,\n          height: circleSize,\n          mixBlendMode: \"difference\",\n        }}\n        initial={{ scale: 0, x: \"-50%\", y: \"-50%\" }}\n        animate={{\n          scale: isHovered ? 1 : 0,\n          x: \"-50%\",\n          y: \"-50%\",\n        }}\n        transition={{\n          duration: 0.5,\n          ease: [0.19, 1, 0.22, 1],\n        }}\n      />\n    </div>\n  );\n}\n\nexport { ClippedCircle, type ClippedCircleProps };\n",
      "type": "registry:ui",
      "target": "components/unlumen-ui/clipped-circle.tsx"
    }
  ],
  "type": "registry:ui"
}