{"$schema":"https://ui.shadcn.com/schema/registry-item.json","author":"Eduardo Calvo <educlopez93@gmail.com>","css":{},"dependencies":["motion"],"description":"A MaskRevealUp text animation component for SmoothUI.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport { motion, useInView, useReducedMotion } from \"motion/react\";\nimport { useRef } from \"react\";\n\nexport interface MaskRevealUpProps {\n  /** Text content. Use \"\\n\" to separate lines, or pass `lines` instead. */\n  children?: string;\n  className?: string;\n  /** Delay before the animation starts, in milliseconds. */\n  delay?: number;\n  /** Explicit line array. Takes precedence over children. */\n  lines?: string[];\n  /** Per-line stagger, in milliseconds. */\n  stagger?: number;\n  /** Animate only once the text scrolls into view. */\n  triggerOnView?: boolean;\n}\n\nconst DURATION_S = 0.76;\nconst MS = 1000;\nconst EASE = [0.22, 1, 0.36, 1] as const;\n\n/**\n * MaskRevealUp — per-line masked reveal with upward motion and soft blur,\n * inspired by Apple section transitions. Each line rises from beneath an\n * overflow-hidden mask. From the animate-text catalog (`mask-reveal-up`).\n * Best for two-line and three-line headings.\n */\nexport default function MaskRevealUp({\n  children,\n  lines: linesProp,\n  className = \"\",\n  delay = 0,\n  stagger = 90,\n  triggerOnView = false,\n}: MaskRevealUpProps) {\n  const ref = useRef<HTMLSpanElement>(null);\n  const inView = useInView(ref, { once: true });\n  const shouldReduceMotion = useReducedMotion();\n  const play = (!triggerOnView || inView) && !shouldReduceMotion;\n\n  const lines = linesProp ?? (children ? children.split(\"\\n\") : []);\n  const label = lines.join(\" \");\n\n  return (\n    <span\n      aria-label={label}\n      className={className}\n      ref={ref}\n      style={{ display: \"block\" }}\n    >\n      {lines.map((line, index) => (\n        // biome-ignore lint/suspicious/noArrayIndexKey: lines have no stable id\n        <span key={index} style={{ display: \"block\", overflow: \"hidden\" }}>\n          <motion.span\n            animate={\n              play ? { filter: \"blur(0px)\", opacity: 1, y: 0 } : undefined\n            }\n            aria-hidden=\"true\"\n            initial={\n              shouldReduceMotion\n                ? { opacity: 1 }\n                : { filter: \"blur(6px)\", opacity: 0, y: 30 }\n            }\n            style={{ display: \"block\" }}\n            transition={\n              shouldReduceMotion\n                ? { duration: 0 }\n                : {\n                    delay: delay / MS + (index * stagger) / MS,\n                    duration: DURATION_S,\n                    ease: EASE,\n                  }\n            }\n          >\n            {line}\n          </motion.span>\n        </span>\n      ))}\n    </span>\n  );\n}\n","path":"index.tsx","target":"components/smoothui/mask-reveal-up/index.tsx","type":"registry:ui"}],"name":"mask-reveal-up","registryDependencies":[],"title":"Mask Reveal Up","type":"registry:ui"}