{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "fade",
  "title": "Fade",
  "description": "One prop-driven fade — a refined opacity fade with an optional subtle directional drift (direction, default \"up\"), an optional blur focus-in (blur), and an inView/mount trigger. Covers above-the-fold fades and scroll reveals alike.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://motion.asmitsah.dev/r/provider.json"
  ],
  "files": [
    {
      "path": "components/motion/fade.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  type FadeDirection,\n  fadeVariants,\n  feel,\n  revealTransition,\n  viewportOnce,\n} from \"@/lib/motion\";\n\ntype FadeProps = {\n  children: ReactNode;\n  className?: string;\n  style?: CSSProperties;\n  delay?: number;\n  /** Subtle FIXED drift as it fades — default \"up\". \"none\" = pure opacity. Tunable travel is Slide's job. */\n  direction?: FadeDirection;\n  /** Layer a blur → sharp focus-in on top. `true` uses feel.fadeBlur (~8px); a number sets custom px. */\n  blur?: boolean | number;\n  /** Animate the first time it's in view (once) or immediately on mount. */\n  trigger?: \"inView\" | \"mount\";\n};\n\n/**\n * The one prop-driven fade — absorbs the old FadeIn / Reveal / BlurToFocus / BlurFadeRise.\n * A refined opacity fade plus an optional subtle directional drift and an optional blur settle.\n * Transforms are stripped for free by the provider's `reducedMotion=\"user\"`, but `filter` blur\n * is NOT — so on reduced motion we drop both blur AND drift and keep a plain opacity fade.\n */\nexport function Fade({\n  children,\n  className,\n  style,\n  delay = 0,\n  direction = \"up\",\n  blur = false,\n  trigger = \"inView\",\n}: FadeProps) {\n  const reduceMotion = useReducedMotion();\n  const blurPx = blur === true ? feel.fadeBlur : blur === false ? 0 : blur;\n\n  // Reduced motion → a plain opacity fade, no drift, no filter. Otherwise the full recipe.\n  const base: Variants = reduceMotion\n    ? { initial: { opacity: 0 }, animate: { opacity: 1 } }\n    : fadeVariants(direction, blurPx);\n\n  // fadeVariants bakes no transition, so fold `delay` into `animate` here — a variant's own\n  // transition overrides the component-level `transition` prop (the L004 idiom, as SlideIn does).\n  const variants: Variants = {\n    ...base,\n    animate: {\n      ...(base.animate as TargetAndTransition),\n      transition: { ...revealTransition, delay },\n    },\n  };\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/fade.tsx"
    }
  ],
  "type": "registry:component"
}