{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "fade-in",
  "title": "Fade In",
  "description": "Scroll-triggered fade with direction, distance, easing, scale and blur options.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://trytweenly.vercel.app/r/use-reduced-motion.json"
  ],
  "files": [
    {
      "path": "registry/new-york/fade-in/fade-in.tsx",
      "content": "\"use client\"\n\nimport { motion } from \"motion/react\"\nimport type { Transition } from \"motion/react\"\nimport { useReducedMotion } from \"@/registry/new-york/hooks/use-reduced-motion\"\n\nexport type FadeInDirection = \"up\" | \"down\" | \"left\" | \"right\" | \"none\"\nexport type FadeInEase = \"smooth\" | \"snappy\" | \"linear\" | \"spring\"\n\nexport interface FadeInProps {\n  children: React.ReactNode\n  /** Direction the element travels while appearing. Default: \"up\" */\n  direction?: FadeInDirection\n  /** Travel distance in px. Default: 24 */\n  distance?: number\n  /** Animation length in seconds (lower = faster). Default: 0.6 */\n  duration?: number\n  /** Delay before starting, in seconds. Default: 0 */\n  delay?: number\n  /** Easing preset. Default: \"smooth\" */\n  ease?: FadeInEase\n  /** Starting scale (1 = no scale). Default: 1 */\n  scale?: number\n  /** Starting blur in px (0 = no blur). Default: 0 */\n  blur?: number\n  /** Animate only the first time it enters view. Default: true */\n  once?: boolean\n  /** How much of the element must be visible, 0 to 1. Default: 0.2 */\n  amount?: number\n  className?: string\n}\n\nconst EASINGS: Record<\"smooth\" | \"snappy\" | \"linear\", [number, number, number, number]> = {\n  smooth: [0.16, 1, 0.3, 1],\n  snappy: [0.4, 0, 0.2, 1],\n  linear: [0, 0, 1, 1],\n}\n\nfunction getOffset(direction: FadeInDirection, distance: number) {\n  switch (direction) {\n    case \"up\":\n      return { x: 0, y: distance }\n    case \"down\":\n      return { x: 0, y: -distance }\n    case \"left\":\n      return { x: distance, y: 0 }\n    case \"right\":\n      return { x: -distance, y: 0 }\n    default:\n      return { x: 0, y: 0 }\n  }\n}\n\nexport function FadeIn({\n  children,\n  direction = \"up\",\n  distance = 24,\n  duration = 0.6,\n  delay = 0,\n  ease = \"smooth\",\n  scale = 1,\n  blur = 0,\n  once = true,\n  amount = 0.2,\n  className,\n}: FadeInProps) {\n  const reduced = useReducedMotion()\n\n  // Reduced motion: keep a short opacity fade, drop all movement.\n  const offset = reduced ? { x: 0, y: 0 } : getOffset(direction, distance)\n  const startScale = reduced ? 1 : scale\n  const startBlur = reduced ? 0 : blur\n\n  const hidden = {\n    opacity: 0,\n    x: offset.x,\n    y: offset.y,\n    scale: startScale,\n    ...(startBlur > 0 ? { filter: `blur(${startBlur}px)` } : {}),\n  }\n\n  const visible = {\n    opacity: 1,\n    x: 0,\n    y: 0,\n    scale: 1,\n    ...(startBlur > 0 ? { filter: \"blur(0px)\" } : {}),\n  }\n\n  let transition: Transition\n  if (reduced) {\n    transition = { duration: 0.2 }\n  } else if (ease === \"spring\") {\n    transition = { type: \"spring\", stiffness: 120, damping: 18, delay }\n  } else {\n    transition = { duration, delay, ease: EASINGS[ease] }\n  }\n\n  return (\n    <motion.div\n      className={className}\n      initial={hidden}\n      whileInView={visible}\n      viewport={{ once, amount }}\n      transition={transition}\n    >\n      {children}\n    </motion.div>\n  )\n}",
      "type": "registry:component"
    }
  ],
  "docs": "Docs, live playground and every prop: https://trytweenly.vercel.app/docs/components/fade-in",
  "type": "registry:component"
}