{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "interactive-team",
  "type": "registry:block",
  "title": "Interactive team",
  "description": "Interactive team",
  "files": [
    {
      "path": "components/usages/interactiveteamusage.tsx",
      "content": "import InteractiveTeam from \"@/registry/open-source/interactive-team\";\n\nconst teamMembers = [\n    {\n        name: \"John Doe\",\n        img: \"/itjustworks.jpg\",\n    },\n];\nexport default function InteractiveTeamUsage() {\n    return (\n        <div className=\"relative w-full flex items-center justify-center\">\n            <InteractiveTeam teamMembers={teamMembers} />\n        </div>\n    );\n}",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/interactiveteamusage.tsx",
      "content": "import InteractiveTeam from \"@/registry/open-source/interactive-team\";\n\nconst teamMembers = [\n    {\n        name: \"John Doe\",\n        img: \"/itjustworks.jpg\",\n    },\n];\nexport default function InteractiveTeamUsage() {\n    return (\n        <div className=\"relative w-full flex items-center justify-center\">\n            <InteractiveTeam teamMembers={teamMembers} />\n        </div>\n    );\n}",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/interactive-team.tsx",
      "content": "'use client'\n\n/**\n * @author: @codegrid\n * @description: Interactive Team with GSAP\n * @version: 1.0.0\n * @date: 2026-02-14\n * @license: MIT\n * @website: https://emerald-ui.com\n */\n\nimport { useRef } from 'react'\nimport { useGSAP } from '@gsap/react'\nimport gsap from 'gsap'\nimport { SplitText } from 'gsap/SplitText'\n\ngsap.registerPlugin(SplitText)\n\ninterface TeamMember {\n    name: string\n    img: string\n}\n\ninterface InteractiveTeamProps {\n    teamMembers: TeamMember[]\n    title?: string\n}\n\nexport default function InteractiveTeam({\n    teamMembers,\n    title = 'Dream Team',\n}: InteractiveTeamProps) {\n    const containerRef = useRef<HTMLElement>(null)\n    const profileImagesContainerRef = useRef<HTMLDivElement>(null)\n    const profileImagesRef = useRef<(HTMLDivElement | null)[]>([])\n    const nameElementsRef = useRef<(HTMLDivElement | null)[]>([])\n    const nameHeadingsRef = useRef<(HTMLHeadingElement | null)[]>([])\n\n    useGSAP(\n        () => {\n            const profileImagesContainer = profileImagesContainerRef.current\n            const profileImages = profileImagesRef.current\n            const nameElements = nameElementsRef.current\n            const nameHeadings = nameHeadingsRef.current.filter(\n                (el): el is HTMLHeadingElement => !!el\n            )\n\n            nameHeadings.forEach((heading) => {\n                const split = new SplitText(heading, { type: 'chars' })\n                if (split.chars) {\n                    split.chars.forEach((char) => {\n                        char.classList.add('letter', 'relative', 'translate-y-[0%]')\n                    })\n                }\n            })\n\n            if (nameElements[0]) {\n                const defaultLetters = nameElements[0].querySelectorAll('.letter')\n                gsap.set(defaultLetters, { y: '100%' })\n\n                if (window.innerWidth >= 900) {\n                    profileImages.forEach((img, index) => {\n                        if (!img) return\n\n                        const correspondingName = nameElements[index + 1]\n                        if (!correspondingName) return\n\n                        const letters = correspondingName.querySelectorAll('.letter')\n\n                        img.addEventListener('mouseenter', () => {\n                            gsap.to(img, {\n                                width: 140,\n                                height: 140,\n                                duration: 0.5,\n                                ease: 'power4.out',\n                            })\n\n                            gsap.to(letters, {\n                                y: '-100%',\n                                ease: 'power4.out',\n                                duration: 0.75,\n                                stagger: {\n                                    each: 0.025,\n                                    from: 'center',\n                                },\n                            })\n                        })\n\n                        img.addEventListener('mouseleave', () => {\n                            gsap.to(img, {\n                                width: 70,\n                                height: 70,\n                                duration: 0.5,\n                                ease: 'power4.out',\n                            })\n\n                            gsap.to(letters, {\n                                y: '0%',\n                                ease: 'power4.out',\n                                duration: 0.75,\n                                stagger: {\n                                    each: 0.025,\n                                    from: 'center',\n                                },\n                            })\n                        })\n                    })\n\n                    if (profileImagesContainer) {\n                        profileImagesContainer.addEventListener('mouseenter', () => {\n                            const defaultLetters =\n                                nameElements[0]?.querySelectorAll('.letter')\n                            if (defaultLetters) {\n                                gsap.to(defaultLetters, {\n                                    y: '0%',\n                                    ease: 'power4.out',\n                                    duration: 0.75,\n                                    stagger: {\n                                        each: 0.025,\n                                        from: 'center',\n                                    },\n                                })\n                            }\n                        })\n\n                        profileImagesContainer.addEventListener('mouseleave', () => {\n                            const defaultLetters =\n                                nameElements[0]?.querySelectorAll('.letter')\n                            if (defaultLetters) {\n                                gsap.to(defaultLetters, {\n                                    y: '100%',\n                                    ease: 'power4.out',\n                                    duration: 0.75,\n                                    stagger: {\n                                        each: 0.025,\n                                        from: 'center',\n                                    },\n                                })\n                            }\n                        })\n                    }\n                }\n            }\n\n            return () => {\n                if (window.innerWidth >= 900) {\n                    profileImages.forEach((img) => {\n                        if (!img) return\n\n                        img.removeEventListener('mouseenter', () => { })\n                        img.removeEventListener('mouseleave', () => { })\n                    })\n\n                    if (profileImagesContainer) {\n                        profileImagesContainer.removeEventListener('mouseenter', () => { })\n                        profileImagesContainer.removeEventListener('mouseleave', () => { })\n                    }\n                }\n            }\n        },\n        { scope: containerRef, dependencies: [teamMembers] }\n    )\n\n    return (\n        <section\n            className='relative z-10 flex h-svh w-full flex-col items-center justify-center gap-[2.5em] overflow-hidden bg-[#0f0f0f] px-4 text-[#e3e3db]'\n            ref={containerRef}\n        >\n            <div\n                className='profile-images flex w-full flex-wrap items-center justify-center'\n                ref={profileImagesContainerRef}\n            >\n                {teamMembers.map(({ img, name }, index) => (\n                    <div\n                        key={name}\n                        className='img relative size-18 cursor-pointer p-1.5 will-change-[width,height] max-xl:size-14'\n                        ref={(el) => {\n                            profileImagesRef.current[index] = el\n                        }}\n                    >\n                        <img\n                            src={img}\n                            className='h-full w-full rounded-lg bg-neutral-600 object-cover'\n                            alt={`Team member ${name}`}\n                        />\n                    </div>\n                ))}\n            </div>\n\n            <div className='profile-names clip-path-[polygon(0_0,100%_0,100%_100%,0_100%)] relative h-29 w-full overflow-hidden max-xl:h-22.5 max-lg:h-14.5'>\n                <div\n                    className='name default absolute w-full -translate-y-full text-center text-[6.5rem] leading-none font-black tracking-[-0.2rem] text-nowrap uppercase select-none max-xl:text-[5rem] max-lg:text-[3.2rem]'\n                    ref={(el) => {\n                        nameElementsRef.current[0] = el\n                    }}\n                >\n                    <h1\n                        ref={(el) => {\n                            nameHeadingsRef.current[0] = el\n                        }}\n                    >\n                        {title}\n                    </h1>\n                </div>\n                {teamMembers.map((person, index) => (\n                    <div\n                        key={person.name}\n                        className='name text-primary absolute w-full translate-y-full text-center text-[6.5rem] leading-none font-black tracking-[-0.2rem] text-nowrap uppercase select-none max-xl:text-[5rem] max-lg:text-[3.3rem]'\n                        ref={(el) => {\n                            nameElementsRef.current[index + 1] = el\n                        }}\n                    >\n                        <h1\n                            ref={(el) => {\n                                nameHeadingsRef.current[index + 1] = el\n                            }}\n                        >\n                            {person.name}\n                        </h1>\n                    </div>\n                ))}\n            </div>\n        </section>\n    )\n}",
      "type": "registry:ui"
    }
  ]
}