{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "marquee",
  "title": "Marquee",
  "description": "Seamless infinite scrolling loop that eases to a stop on hover.",
  "dependencies": [],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json",
    "https://ui.cuelark.com/r/motion.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/marquee.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { gsap, motionScale, useGSAP } from \"@/lib/motion\";\nimport { cn } from \"@/lib/utils\";\n\ntype MarqueeProps = React.ComponentProps<\"div\"> & {\n  /** Pixels per second. */\n  speed?: number;\n  reverse?: boolean;\n  /** On hover the loop eases to a stop (instead of freezing) and eases back up on leave. */\n  pauseOnHover?: boolean;\n  /** Fades both edges. */\n  fade?: boolean;\n  /** Gap between items, any CSS length. */\n  gap?: string;\n};\n\n/**\n * A seamless infinite loop (logos, testimonials, tickers). GSAP drives one track holding two copies;\n * hover decelerates it smoothly. With motion off it becomes a normal horizontally scrollable row.\n */\nfunction Marquee({ className, speed = 40, reverse = false, pauseOnHover = true, fade = true, gap = \"2.5rem\", children, ...props }: MarqueeProps) {\n  const ref = React.useRef<HTMLDivElement>(null);\n  const tween = React.useRef<gsap.core.Tween | null>(null);\n  const [still, setStill] = React.useState(false);\n\n  useGSAP(\n    () => {\n      const root = ref.current;\n      const track = root?.querySelector<HTMLElement>('[data-slot=\"marquee-track\"]');\n      if (!root || !track) return;\n      if (!motionScale(root)) return setStill(true);\n      const distance = track.scrollWidth / 2;\n      tween.current = gsap.fromTo(track, { x: reverse ? -distance : 0 }, { x: reverse ? 0 : -distance, duration: distance / speed, ease: \"none\", repeat: -1 });\n    },\n    { scope: ref, dependencies: [speed, reverse] },\n  );\n\n  const ease = (to: number) => tween.current && gsap.to(tween.current, { timeScale: to, duration: 0.6, ease: \"cue\" });\n\n  return (\n    <div\n      ref={ref}\n      data-slot=\"marquee\"\n      className={cn(\n        \"relative flex w-full\",\n        still ? \"overflow-x-auto\" : \"overflow-hidden\",\n        fade && \"[mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]\",\n        className,\n      )}\n      onPointerEnter={() => pauseOnHover && ease(0)}\n      onPointerLeave={() => pauseOnHover && ease(1)}\n      {...props}\n    >\n      <div data-slot=\"marquee-track\" className=\"flex w-max shrink-0\" style={{ gap }}>\n        <div className=\"flex shrink-0 items-center\" style={{ gap }}>\n          {children}\n        </div>\n        {!still && (\n          <div aria-hidden=\"true\" className=\"flex shrink-0 items-center\" style={{ gap }}>\n            {children}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\nexport { Marquee };\nexport type { MarqueeProps };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/marquee",
  "categories": [
    "motion"
  ],
  "type": "registry:ui"
}