{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar-reveal",
  "type": "registry:ui",
  "title": "Avatar Reveal",
  "description": "Three stacked avatars that scale and unblur in from the left on an elastic ease, then a caption slides in from the right.",
  "dependencies": [
    "gsap",
    "@gsap/react"
  ],
  "registryDependencies": [],
  "cssVars": {
    "theme": {}
  },
  "files": [
    {
      "path": "components/tweenui/avatar-reveal.tsx",
      "type": "registry:component",
      "target": "components/tweenui/avatar-reveal.tsx",
      "content": "'use client';\n\nimport { useRef, type ComponentPropsWithoutRef, type ReactNode } from 'react';\nimport { useGSAP } from '@gsap/react';\nimport gsap from 'gsap';\nimport { cn } from '@/lib/utils';\n\ngsap.registerPlugin(useGSAP);\n\nconst prefersReducedMotion = () =>\n  typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nexport interface AvatarRevealItem {\n  src: string;\n  alt: string;\n}\n\nconst DEFAULT_AVATARS: AvatarRevealItem[] = [\n  {\n    src: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=88&h=88&fit=crop&crop=faces',\n    alt: 'Team member 1',\n  },\n  {\n    src: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=88&h=88&fit=crop&crop=faces',\n    alt: 'Team member 2',\n  },\n  {\n    src: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=88&h=88&fit=crop&crop=faces',\n    alt: 'Team member 3',\n  },\n];\n\ninterface AvatarRevealProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n  avatars?: AvatarRevealItem[];\n  children?: ReactNode;\n}\n\nconst AvatarReveal = ({\n  avatars = DEFAULT_AVATARS,\n  children = '2,000+ teams shipping faster this week.',\n  className,\n  ...props\n}: AvatarRevealProps) => {\n  const rootRef = useRef<HTMLDivElement>(null);\n\n  useGSAP(\n    () => {\n      const root = rootRef.current;\n      if (!root) return;\n\n      const items = gsap.utils.toArray<HTMLElement>('[data-ns-avatar]', root);\n      const caption = root.querySelector<HTMLElement>('[data-ns-animate]');\n\n      if (prefersReducedMotion()) {\n        gsap.set([items, caption], { opacity: 1, x: 0, scale: 1, filter: 'none' });\n        return;\n      }\n\n      gsap.fromTo(\n        items,\n        { opacity: 0, scale: 0, x: -40, filter: 'blur(5px)' },\n        {\n          opacity: 1,\n          scale: 1,\n          x: 0,\n          filter: 'blur(0px)',\n          duration: 1.5,\n          stagger: 0.1,\n          delay: 0.1,\n          ease: 'elastic.out(1, 0.7)',\n        }\n      );\n\n      if (caption) {\n        gsap.fromTo(\n          caption,\n          { opacity: 0, x: 50 },\n          { opacity: 1, x: 0, duration: 0.8, delay: 0.2, ease: 'power2.out' }\n        );\n      }\n    },\n    { scope: rootRef }\n  );\n\n  return (\n    <div\n      {...props}\n      ref={rootRef}\n      data-avatar-reveal\n      className={cn('mx-auto flex max-w-[254px] items-center justify-center gap-x-3', className)}\n    >\n      <div className=\"flex items-center justify-center -space-x-3.5\">\n        {avatars.map((avatar) => (\n          <figure\n            key={avatar.src}\n            data-ns-avatar\n            className=\"size-11 overflow-hidden rounded-full opacity-0 outline outline-2 outline-white motion-reduce:opacity-100\"\n          >\n            <img\n              src={avatar.src}\n              alt={avatar.alt}\n              className=\"size-full rounded-full object-cover\"\n            />\n          </figure>\n        ))}\n      </div>\n      {children ? (\n        <p\n          data-ns-animate\n          className=\"mx-auto max-w-[142px] text-left text-sm text-[#045f64]/80 opacity-0 motion-reduce:opacity-100 dark:text-[#9fd4d6]/80\"\n        >\n          {children}\n        </p>\n      ) : null}\n    </div>\n  );\n};\n\nexport default AvatarReveal;\n"
    }
  ],
  "docs": "Docs, props and examples: https://tween-ui.vercel.app/component/avatar-reveal\nThe sample content loads images from images.unsplash.com. Replace them with your own before shipping."
}