{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "clip-reveal",
  "title": "Clip Reveal",
  "description": "Directional clip/wipe reveal — content wipes open from a chosen edge.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://motion.asmitsah.dev/r/provider.json"
  ],
  "files": [
    {
      "path": "components/motion/clip-reveal.tsx",
      "content": "\"use client\";\n\nimport type { TargetAndTransition, Variants } from \"motion/react\";\nimport { useReducedMotion } from \"motion/react\";\nimport * as m from \"motion/react-m\";\nimport type { CSSProperties, ReactNode } from \"react\";\nimport {\n  fade,\n  revealTransition,\n  viewportOnce,\n  type WipeDirection,\n  wipeVariants,\n} from \"@/lib/motion\";\n\ntype ClipRevealProps = {\n  children: ReactNode;\n  className?: string;\n  style?: CSSProperties;\n  delay?: number;\n  trigger?: \"inView\" | \"mount\";\n  direction?: WipeDirection;\n};\n\n/** Hard clip-path inset() edge wipe — the box stays put while its content is\n *  unveiled from `direction`. clip-path survives reducedMotion=\"user\", so we\n *  guard it: on reduce, the element renders fully open with a plain fade. */\nexport function ClipReveal({\n  children,\n  className,\n  style,\n  delay = 0,\n  trigger = \"inView\",\n  direction = \"up\",\n}: ClipRevealProps) {\n  const reduced = useReducedMotion();\n\n  // Reduced motion: clip-path is NOT auto-stripped, so drop the wipe entirely\n  // and settle in with a plain opacity fade (the prop-object `fade` carries no\n  // transition of its own, so the component-level `delay` applies cleanly).\n  if (reduced) {\n    const play =\n      trigger === \"mount\"\n        ? ({ animate: fade.animate } as const)\n        : ({ whileInView: fade.animate, viewport: viewportOnce } as const);\n    return (\n      <m.div\n        className={className}\n        style={style}\n        initial={fade.initial}\n        {...play}\n        transition={{ ...revealTransition, delay }}\n      >\n        {children}\n      </m.div>\n    );\n  }\n\n  // A variant's own transition overrides the component `transition` prop, so\n  // fold `delay` into the variant rather than passing it alongside.\n  const base = wipeVariants(direction) as {\n    initial: TargetAndTransition;\n    animate: TargetAndTransition;\n  };\n  const variants: Variants = {\n    initial: base.initial,\n    animate: { ...base.animate, transition: { ...revealTransition, delay } },\n  };\n  const play =\n    trigger === \"mount\"\n      ? ({ animate: \"animate\" } as const)\n      : ({ whileInView: \"animate\", viewport: viewportOnce } as const);\n\n  return (\n    <m.div className={className} style={style} variants={variants} initial=\"initial\" {...play}>\n      {children}\n    </m.div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/motion/clip-reveal.tsx"
    }
  ],
  "type": "registry:component"
}