{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "reveal",
  "title": "Reveal",
  "description": "Moves its children in when they arrive on screen, and never decides whether they are there.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/default/reveal/reveal.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport type RevealDirection = \"up\" | \"down\" | \"left\" | \"right\" | \"none\"\n\nexport type RevealProps = React.HTMLAttributes<HTMLDivElement> & {\n  /** Which way the content travels in from. */\n  from?: RevealDirection\n  /** Pixels travelled. */\n  distance?: number\n  /** Milliseconds before it starts. Give a list an index times a step. */\n  delay?: number\n  duration?: number\n  /** How much has to be on screen before it starts, from nought to one. */\n  threshold?: number\n  /** Plays again whenever it comes back. Off by default. */\n  repeat?: boolean\n}\n\nconst OFFSET: Record<RevealDirection, string> = {\n  up: \"0, var(--reveal-distance)\",\n  down: \"0, calc(var(--reveal-distance) * -1)\",\n  left: \"var(--reveal-distance), 0\",\n  right: \"calc(var(--reveal-distance) * -1), 0\",\n  none: \"0, 0\",\n}\n\n/**\n * Moves its children in when they arrive on screen. The content is present and\n * readable from the first paint either way, so this changes how something\n * arrives and never whether it is there.\n */\nexport function Reveal({\n  from = \"up\",\n  distance = 16,\n  delay = 0,\n  duration = 600,\n  threshold = 0.15,\n  repeat = false,\n  className,\n  style,\n  children,\n  ...rootProps\n}: RevealProps) {\n  const ref = React.useRef<HTMLDivElement>(null)\n  const [shown, setShown] = React.useState(false)\n\n  React.useEffect(() => {\n    const element = ref.current\n    if (!element) return\n\n    const observer = new IntersectionObserver(\n      ([entry]) => {\n        if (entry?.isIntersecting) {\n          setShown(true)\n          if (!repeat) observer.disconnect()\n        } else if (repeat) {\n          setShown(false)\n        }\n      },\n      { threshold }\n    )\n\n    observer.observe(element)\n    return () => observer.disconnect()\n  }, [repeat, threshold])\n\n  return (\n    <div\n      ref={ref}\n      data-slot=\"reveal\"\n      data-shown={shown ? \"\" : undefined}\n      className={cn(\n        \"translate-(--reveal-offset) opacity-0 transition-[opacity,translate] ease-out\",\n        \"data-shown:translate-none data-shown:opacity-100\",\n        \"motion-reduce:translate-none motion-reduce:opacity-100 motion-reduce:transition-none\",\n        className\n      )}\n      style={\n        {\n          \"--reveal-distance\": `${distance}px`,\n          \"--reveal-offset\": OFFSET[from],\n          transitionDelay: `${delay}ms`,\n          transitionDuration: `${duration}ms`,\n          ...style,\n        } as React.CSSProperties\n      }\n      {...rootProps}\n    >\n      {children}\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "motion",
    "scroll",
    "entrance"
  ],
  "type": "registry:ui"
}