{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "blur-fade",
  "type": "registry:component",
  "title": "Blur fade",
  "description": "Reveals its children as they scroll into view, rising out of a soft blur and settling into focus on a spring.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/premium/blur-fade.tsx",
      "type": "registry:ui",
      "target": "components/ui/blur-fade.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\nimport { BellIcon, CircleCheckIcon, FileTextIcon, ReceiptIcon, ShieldCheckIcon, WalletIcon, type LucideIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Reveals its children as they scroll into view, rising out of a soft blur and settling into focus on a spring.\n * Wrap each item of a list and grow the `delay` to stagger them. Reduced\n * motion shows everything in place at once.\n */\ntype BlurFadeProps = {\n  children?: React.ReactNode\n  /** Seconds to wait before the reveal starts; grow it per item to stagger a list. */\n  delay?: number\n  /** Seconds the reveal takes. */\n  duration?: number\n  /** Which way the content travels as it settles. */\n  direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"none\"\n  /** Pixels of travel. */\n  offset?: number\n  /** Blur in pixels the content starts from. */\n  blur?: number\n  /** Reveal once, or again every time it enters the viewport. */\n  once?: boolean\n  /** How much of the element has to be visible before it reveals, 0 to 1. */\n  amount?: number\n  className?: string\n}\n\nconst FEATURES: { icon: LucideIcon; title: string; body: string }[] = [\n  { icon: ReceiptIcon, title: \"Invoices that close themselves\", body: \"Send once. Lumen chases, reconciles and marks it paid.\" },\n  { icon: WalletIcon, title: \"Live cash view\", body: \"Every account and currency, one number you can trust.\" },\n  { icon: FileTextIcon, title: \"Reports on a schedule\", body: \"Board packs on the first Monday, written for you.\" },\n  { icon: BellIcon, title: \"Reminders with manners\", body: \"Polite, timed and escalating. Customers pay 9 days sooner.\" },\n  { icon: CircleCheckIcon, title: \"Approvals anywhere\", body: \"Approve a bill from your phone in one tap.\" },\n  { icon: ShieldCheckIcon, title: \"A full audit trail\", body: \"Every change, who made it and why, kept forever.\" },\n]\n\nfunction BlurFade({ children, delay = 0, duration = 0.5, direction = \"up\", offset = 16, blur = 8, once = true, amount = 0.3, className }: BlurFadeProps) {\n  const reduce = useReducedMotion()\n  const from = {\n    opacity: 0,\n    filter: `blur(${blur}px)`,\n    x: direction === \"left\" ? offset : direction === \"right\" ? -offset : 0,\n    y: direction === \"up\" ? offset : direction === \"down\" ? -offset : 0,\n  }\n  const to = { opacity: 1, filter: \"blur(0px)\", x: 0, y: 0 }\n  // Position settles on the morph spring; opacity and blur are tweened so they never overshoot.\n  const transition = reduce\n    ? { duration: 0 }\n    : {\n        x: { type: \"spring\" as const, bounce: 0.16, duration: Math.max(0.1, duration * 1.4), delay },\n        y: { type: \"spring\" as const, bounce: 0.16, duration: Math.max(0.1, duration * 1.4), delay },\n        opacity: { duration, delay, ease: [0.2, 0, 0, 1] as [number, number, number, number] },\n        filter: { duration, delay, ease: [0.2, 0, 0, 1] as [number, number, number, number] },\n      }\n\n  if (children === undefined) {\n    return (\n      <div data-slot=\"blur-fade\" className={cn(\"mx-auto grid w-full max-w-4xl gap-3 sm:grid-cols-3\", className)}>\n        {FEATURES.map((f, i) => (\n          <BlurFade key={f.title} delay={delay + i * 0.08} duration={duration} direction={direction} offset={offset} blur={blur} once={once} amount={amount}>\n            <div className=\"h-full rounded-2xl border border-border bg-surface p-5 shadow-raised\">\n              <span className=\"grid size-9 place-items-center rounded-xl bg-accent-soft text-accent-fg\">\n                <f.icon className=\"size-[18px]\" strokeWidth={1.75} aria-hidden />\n              </span>\n              <p className=\"mt-4 text-[0.9375rem] font-medium tracking-[-0.01em] text-fg\">{f.title}</p>\n              <p className=\"mt-1 text-[0.8125rem] leading-[1.55] text-fg-muted\">{f.body}</p>\n            </div>\n          </BlurFade>\n        ))}\n      </div>\n    )\n  }\n\n  return (\n    <motion.div\n      data-slot=\"blur-fade\"\n      initial={reduce ? false : from}\n      whileInView={to}\n      viewport={{ once, amount }}\n      transition={transition}\n      className={className}\n    >\n      {children}\n    </motion.div>\n  )\n}\n\nexport { BlurFade }\nexport type { BlurFadeProps }\n"
    }
  ]
}
