{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "motion-cursor",
  "title": "Cursor",
  "description": "A custom cursor component with animated effects and interactions.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://ui.ndekocode.dev/r/theme.json",
    "https://ui.ndekocode.dev/r/use-prefers-reduced-motion.json",
    "https://ui.ndekocode.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "components/core/cursor.tsx",
      "content": "'use client';\nimport React, { useEffect, useState, useRef } from 'react';\nimport {\n  motion,\n  SpringOptions,\n  useMotionValue,\n  useSpring,\n  AnimatePresence,\n  Transition,\n  Variant,\n  MotionConfig,\n  MotionValue,\n} from 'motion/react';\nimport { cn } from '@/lib/utils';\nimport { usePrefersReducedMotion } from '@/registry/ndeko/hooks/use-prefers-reduced-motion';\n\nexport type CursorProps = {\n  children: React.ReactNode;\n  className?: string;\n  springConfig?: SpringOptions;\n  attachToParent?: boolean;\n  transition?: Transition;\n  variants?: {\n    initial: Variant;\n    animate: Variant;\n    exit: Variant;\n  };\n  onPositionChange?: (x: number, y: number) => void;\n};\n\nfunction ReducedMotionConfig({ children }: { children: React.ReactNode }) {\n  const prefersReducedMotion = usePrefersReducedMotion();\n  if (!prefersReducedMotion) {\n    return children;\n  }\n  return <MotionConfig reducedMotion='always'>{children}</MotionConfig>;\n}\n\nfunction followerOf(\n  prefersReducedMotion: boolean | null,\n  pointer: MotionValue<number>,\n  spring: MotionValue<number>\n) {\n  if (prefersReducedMotion) {\n    return pointer;\n  }\n  return spring;\n}\n\nexport function Cursor({\n  children,\n  className,\n  springConfig,\n  attachToParent,\n  variants,\n  transition,\n  onPositionChange,\n}: CursorProps) {\n  const cursorX = useMotionValue(0);\n  const cursorY = useMotionValue(0);\n  const cursorRef = useRef<HTMLDivElement>(null);\n  const [isVisible, setIsVisible] = useState(!attachToParent);\n  const prefersReducedMotion = usePrefersReducedMotion();\n\n  useEffect(() => {\n    if (typeof window !== 'undefined') {\n      cursorX.set(window.innerWidth / 2);\n      cursorY.set(window.innerHeight / 2);\n    }\n  }, [cursorX, cursorY]);\n\n  useEffect(() => {\n    if (!attachToParent) {\n      document.body.style.cursor = 'none';\n    } else {\n      document.body.style.cursor = 'auto';\n    }\n\n    const updatePosition = (e: MouseEvent) => {\n      cursorX.set(e.clientX);\n      cursorY.set(e.clientY);\n      onPositionChange?.(e.clientX, e.clientY);\n    };\n\n    document.addEventListener('mousemove', updatePosition);\n\n    return () => {\n      document.removeEventListener('mousemove', updatePosition);\n      if (!attachToParent) {\n        document.body.style.cursor = 'auto';\n      }\n    };\n  }, [cursorX, cursorY, onPositionChange, attachToParent]);\n\n  const cursorXSpring = useSpring(cursorX, springConfig || { duration: 0 });\n  const cursorYSpring = useSpring(cursorY, springConfig || { duration: 0 });\n  const followerX = followerOf(prefersReducedMotion, cursorX, cursorXSpring);\n  const followerY = followerOf(prefersReducedMotion, cursorY, cursorYSpring);\n\n  useEffect(() => {\n    const parent = cursorRef.current?.parentElement;\n    const shouldTrackParent = attachToParent && parent;\n    if (!shouldTrackParent) {\n      return;\n    }\n\n    const handleMouseEnter = () => {\n      parent.style.cursor = 'none';\n      setIsVisible(true);\n    };\n    const handleMouseLeave = () => {\n      parent.style.cursor = 'auto';\n      setIsVisible(false);\n    };\n\n    parent.addEventListener('mouseenter', handleMouseEnter);\n    parent.addEventListener('mouseleave', handleMouseLeave);\n\n    return () => {\n      parent.removeEventListener('mouseenter', handleMouseEnter);\n      parent.removeEventListener('mouseleave', handleMouseLeave);\n    };\n  }, [attachToParent]);\n\n  return (\n    <ReducedMotionConfig>\n      <motion.div\n        ref={cursorRef}\n        className={cn('pointer-events-none fixed top-0 left-0 z-50', className)}\n        style={{\n          x: followerX,\n          y: followerY,\n          translateX: '-50%',\n          translateY: '-50%',\n        }}\n      >\n        <AnimatePresence>\n          {isVisible && (\n            <motion.div\n              initial='initial'\n              animate='animate'\n              exit='exit'\n              variants={variants}\n              transition={transition}\n            >\n              {children}\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </motion.div>\n    </ReducedMotionConfig>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/core/cursor.tsx"
    }
  ],
  "categories": [
    "motion"
  ],
  "type": "registry:component"
}