{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "blur-fade",
  "title": "Blur Fade",
  "description": "The workhorse entrance — blur, fade and drift into view.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/blur-fade.tsx",
      "content": "\"use client\";\n\nimport { motion, useReducedMotion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface BlurFadeProps {\n  children: React.ReactNode;\n  className?: string;\n  /** Seconds before the animation starts */\n  delay?: number;\n  duration?: number;\n  /** Direction the element enters from */\n  direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"none\";\n  /** Distance travelled in px */\n  offset?: number;\n  /** Animate only the first time it enters the viewport */\n  once?: boolean;\n  /** Start animating immediately instead of waiting to scroll into view */\n  inView?: boolean;\n}\n\nconst axis = { up: \"y\", down: \"y\", left: \"x\", right: \"x\" } as const;\nconst sign = { up: 1, down: -1, left: 1, right: -1 } as const;\n\n/**\n * Fades and un-blurs its children in as they scroll into view.\n *\n * Content starts invisible until JavaScript runs, so don't wrap your page's\n * largest above-the-fold element (usually the hero headline or intro): it\n * delays Largest Contentful Paint. Fade the badges, buttons and visuals\n * around it instead.\n */\nexport function BlurFade({\n  children,\n  className,\n  delay = 0,\n  duration = 0.5,\n  direction = \"up\",\n  offset = 16,\n  once = true,\n}: BlurFadeProps) {\n  const reducedMotion = useReducedMotion();\n\n  const hidden =\n    direction === \"none\"\n      ? { opacity: 0, filter: \"blur(6px)\" }\n      : {\n          opacity: 0,\n          filter: \"blur(6px)\",\n          [axis[direction]]: sign[direction] * offset,\n        };\n\n  // Keep `initial` identical on server and client (the server can't know the\n  // motion preference — branching it mismatches on hydration). Under reduced\n  // motion the reveal still happens, just instantly.\n  return (\n    <motion.div\n      data-slot=\"blur-fade\"\n      className={cn(className)}\n      initial={hidden}\n      whileInView={{ opacity: 1, filter: \"blur(0px)\", x: 0, y: 0 }}\n      viewport={{ once, margin: \"0px 0px -10% 0px\" }}\n      transition={\n        reducedMotion\n          ? { duration: 0 }\n          : { delay, duration, ease: [0.21, 0.47, 0.32, 0.98] }\n      }\n    >\n      {children}\n    </motion.div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/blur-fade.tsx"
    }
  ],
  "type": "registry:ui"
}