{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "logos-carousel",
  "title": "Logos Carousel",
  "description": "Animated carousel component that cycles through sets of logos with staggered animations.",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/spell-ui/logos-carousel.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface LogosCarouselProps {\n  children: React.ReactNode;\n  stagger?: number;\n  count?: number;\n  className?: string;\n  duration?: number;\n  interval?: number;\n  initialDelay?: number;\n}\n\nexport function LogosCarousel({\n  children,\n  stagger = 0.14,\n  count,\n  className,\n  duration = 600,\n  interval = 2500,\n  initialDelay = 500,\n}: LogosCarouselProps) {\n  const [index, setIndex] = React.useState(0);\n  const [animate, setAnimate] = React.useState(false);\n  const [nextIndex, setNextIndex] = React.useState(1);\n\n  const childrenArray = React.Children.toArray(children);\n  const logosPerGroup = count || childrenArray.length;\n  const groups: React.ReactNode[][] = [];\n\n  for (let i = 0; i < childrenArray.length; i += logosPerGroup) {\n    groups.push(childrenArray.slice(i, i + logosPerGroup));\n  }\n\n  const groupsLength = groups.length;\n\n  React.useEffect(() => {\n    const id = setTimeout(() => {\n      setAnimate(true);\n    }, initialDelay);\n\n    return () => {\n      clearTimeout(id);\n    };\n  }, [initialDelay]);\n\n  React.useEffect(() => {\n    if (!animate || groupsLength === 0) {\n      return;\n    }\n\n    function loop() {\n      setIndex((prevIndex) => {\n        const newIndex = (prevIndex + 1) % groupsLength;\n        setNextIndex((newIndex + 1) % groupsLength);\n        return newIndex;\n      });\n    }\n\n    const intervalId = setInterval(loop, interval);\n\n    return () => {\n      clearInterval(intervalId);\n    };\n  }, [animate, interval, groupsLength]);\n\n  if (groupsLength === 0) {\n    return null;\n  }\n\n  return (\n    <>\n      <style jsx>{`\n        @keyframes logos-enter {\n          0% {\n            transform: translateY(40px);\n            filter: blur(4px);\n            opacity: 0;\n          }\n          100% {\n            transform: translateY(0);\n            filter: blur(0px);\n            opacity: 1;\n          }\n        }\n\n        @keyframes logos-exit {\n          0% {\n            transform: translateY(0);\n            filter: blur(0px);\n            opacity: 1;\n          }\n          100% {\n            transform: translateY(-40px);\n            filter: blur(4px);\n            opacity: 0;\n          }\n        }\n      `}</style>\n      <div\n        className=\"max-w-[720px] grid place-items-center w-full\"\n      >\n        {groups.map((group, groupIndex) => {\n          const isCurrent = groupIndex === index;\n          const isNext = groupIndex === nextIndex && animate;\n          const isVisible = isCurrent || isNext;\n\n          return (\n            <div\n              key={groupIndex}\n              className={cn(\n                \"flex w-full justify-center gap-10\",\n                className\n              )}\n              style={{ \n                gridArea: \"1 / 1\", \n                pointerEvents: isVisible ? \"auto\" : \"none\",\n              }}\n            >\n              {group.map((logo, logoIndex) => {\n                return (\n                  <Logo\n                    key={logoIndex}\n                    state={isCurrent ? \"exit\" : \"enter\"}\n                    animate={animate && isVisible}\n                    index={logoIndex}\n                    stagger={stagger}\n                    duration={duration}\n                  >\n                    {logo}\n                  </Logo>\n                );\n              })}\n            </div>\n          );\n        })}\n      </div>\n    </>\n  );\n}\n\ninterface LogoProps {\n  children: React.ReactNode;\n  animate?: boolean;\n  index: number;\n  state?: \"enter\" | \"exit\";\n  stagger?: number;\n  duration?: number;\n}\n\nfunction Logo({\n  children,\n  animate,\n  index,\n  state = \"enter\",\n  stagger = 0.14,\n  duration = 500,\n}: LogoProps) {\n  const delay = index * stagger;\n  const durationMs = duration;\n\n  const animationStyles: React.CSSProperties = {\n    animationDelay: `${delay}s`,\n    animationDuration: `${durationMs}ms`,\n    animationFillMode: \"both\",\n  };\n\n  if (!animate) {\n    if (state === \"enter\") {\n      return (\n        <div\n          className=\"opacity-0\"\n          style={animationStyles}\n        >\n          {children}\n        </div>\n      );\n    }\n    return (\n      <div\n        className=\"opacity-100\"\n        style={animationStyles}\n      >\n        {children}\n      </div>\n    );\n  }\n\n  const animationName = state === \"enter\" ? \"logos-enter\" : \"logos-exit\";\n\n  return (\n    <div\n      style={{\n        ...animationStyles,\n        animationName,\n        animationTimingFunction: \"ease\",\n      }}\n    >\n      {children}\n    </div>\n  );\n}\n\nexport default LogosCarousel;\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}