{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "direction-reveal",
  "title": "Direction Reveal",
  "description": "A reveal overlay that enters and exits from the pointer direction.",
  "registryDependencies": [
    "@rivelle/utils"
  ],
  "files": [
    {
      "path": "registry/nova/effects/direction-reveal.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype Direction = \"top\" | \"right\" | \"bottom\" | \"left\";\n\ntype DirectionRevealProps = React.ComponentProps<\"div\"> & {\n  reveal: React.ReactNode;\n  revealClassName?: string;\n};\n\nconst transforms: Record<Direction, string> = {\n  top: \"translate3d(0,-101%,0)\",\n  right: \"translate3d(101%,0,0)\",\n  bottom: \"translate3d(0,101%,0)\",\n  left: \"translate3d(-101%,0,0)\",\n};\n\nfunction getDirection(event: React.MouseEvent<HTMLDivElement>): Direction {\n  const bounds = event.currentTarget.getBoundingClientRect();\n  const x = event.clientX - bounds.left - bounds.width / 2;\n  const y = event.clientY - bounds.top - bounds.height / 2;\n  const angle = Math.atan2(y, x) * (180 / Math.PI);\n  if (angle >= -45 && angle < 45) return \"right\";\n  if (angle >= 45 && angle < 135) return \"bottom\";\n  if (angle >= -135 && angle < -45) return \"top\";\n  return \"left\";\n}\n\nfunction DirectionReveal({\n  children,\n  className,\n  onMouseEnter,\n  onMouseLeave,\n  onPointerMove,\n  reveal,\n  revealClassName,\n  ...props\n}: DirectionRevealProps) {\n  const [direction, setDirection] = React.useState<Direction>(\"bottom\");\n  const [visible, setVisible] = React.useState(false);\n\n  return (\n    <div\n      className={cn(\n        \"group relative isolate overflow-hidden rounded-[2rem] border border-foreground/10 bg-card [contain:paint]\",\n        className,\n      )}\n      data-direction={direction}\n      data-slot=\"direction-reveal\"\n      onMouseEnter={(event) => {\n        setDirection(getDirection(event));\n        setVisible(true);\n        onMouseEnter?.(event);\n      }}\n      onMouseLeave={(event) => {\n        setDirection(getDirection(event));\n        setVisible(false);\n        onMouseLeave?.(event);\n      }}\n      onPointerMove={(event) => {\n        if (!visible) {\n          setDirection(getDirection(event));\n          setVisible(true);\n        }\n        onPointerMove?.(event);\n      }}\n      {...props}\n    >\n      <div className=\"h-full transition-transform duration-500 ease-[cubic-bezier(.22,1,.36,1)] group-hover:scale-[1.025]\">\n        {children}\n      </div>\n      <div\n        aria-hidden={!visible}\n        className={cn(\n          \"absolute inset-0 z-10 transition-transform duration-500 ease-[cubic-bezier(.22,1,.36,1)] will-change-transform [backface-visibility:hidden] motion-reduce:transition-none\",\n          revealClassName,\n        )}\n        style={{\n          transform: visible ? \"translate3d(0,0,0)\" : transforms[direction],\n        }}\n      >\n        {reveal}\n      </div>\n    </div>\n  );\n}\n\nexport { DirectionReveal };\nexport type { DirectionRevealProps };\n",
      "type": "registry:ui",
      "target": "@effects/direction-reveal.tsx"
    }
  ],
  "type": "registry:ui"
}