{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"infinite-slider","type":"registry:component","description":"Infinite slider component.","files":[{"path":"components/ui/infinite-slider.tsx","type":"registry:component","content":"\"use client\";\nimport { cn } from \"@/lib/utils\";\nimport { animate, motion, useMotionValue } from \"motion/react\";\nimport { useEffect, useState } from \"react\";\nimport useMeasure from \"react-use-measure\";\n\nexport type InfiniteSliderProps = {\n\tchildren: React.ReactNode;\n\tgap?: number;\n\tspeed?: number;\n\tspeedOnHover?: number;\n\tdirection?: \"horizontal\" | \"vertical\";\n\treverse?: boolean;\n\tclassName?: string;\n};\n\nexport function InfiniteSlider({\n\tchildren,\n\tgap = 16,\n\tspeed = 100,\n\tspeedOnHover,\n\tdirection = \"horizontal\",\n\treverse = false,\n\tclassName,\n}: InfiniteSliderProps) {\n\tconst [currentSpeed, setCurrentSpeed] = useState(speed);\n\tconst [ref, { width, height }] = useMeasure();\n\tconst translation = useMotionValue(0);\n\tconst [isTransitioning, setIsTransitioning] = useState(false);\n\n\tuseEffect(() => {\n\t\tlet controls: ReturnType<typeof animate> | undefined;\n\t\tconst size = direction === \"horizontal\" ? width : height;\n\t\tconst contentSize = size + gap;\n\t\tconst from = reverse ? -contentSize / 2 : 0;\n\t\tconst to = reverse ? 0 : -contentSize / 2;\n\n\t\tconst distanceToTravel = Math.abs(to - from);\n\t\tconst duration = distanceToTravel / currentSpeed;\n\n\t\tif (isTransitioning) {\n\t\t\tconst remainingDistance = Math.abs(translation.get() - to);\n\t\t\tconst transitionDuration = remainingDistance / currentSpeed;\n\n\t\t\tcontrols = animate(translation, [translation.get(), to], {\n\t\t\t\tease: \"linear\",\n\t\t\t\tduration: transitionDuration,\n\t\t\t\tonComplete: () => {\n\t\t\t\t\tsetIsTransitioning(false);\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tcontrols = animate(translation, [from, to], {\n\t\t\t\tease: \"linear\",\n\t\t\t\tduration,\n\t\t\t\trepeat: Number.POSITIVE_INFINITY,\n\t\t\t\trepeatType: \"loop\",\n\t\t\t\trepeatDelay: 0,\n\t\t\t\tonRepeat: () => {\n\t\t\t\t\ttranslation.set(from);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\treturn controls?.stop;\n\t}, [\n\t\ttranslation,\n\t\tcurrentSpeed,\n\t\twidth,\n\t\theight,\n\t\tgap,\n\t\tisTransitioning,\n\t\tdirection,\n\t\treverse,\n\t]);\n\n\tconst hoverProps = speedOnHover\n\t\t? {\n\t\t\t\tonHoverStart: () => {\n\t\t\t\t\tsetIsTransitioning(true);\n\t\t\t\t\tsetCurrentSpeed(speedOnHover);\n\t\t\t\t},\n\t\t\t\tonHoverEnd: () => {\n\t\t\t\t\tsetIsTransitioning(true);\n\t\t\t\t\tsetCurrentSpeed(speed);\n\t\t\t\t},\n\t\t\t}\n\t\t: {};\n\n\treturn (\n\t\t<div className={cn(\"overflow-hidden\", className)}>\n\t\t\t<motion.div\n\t\t\t\tclassName=\"flex w-max\"\n\t\t\t\tref={ref}\n\t\t\t\tstyle={{\n\t\t\t\t\t...(direction === \"horizontal\"\n\t\t\t\t\t\t? { x: translation }\n\t\t\t\t\t\t: { y: translation }),\n\t\t\t\t\tgap: `${gap}px`,\n\t\t\t\t\tflexDirection: direction === \"horizontal\" ? \"row\" : \"column\",\n\t\t\t\t}}\n\t\t\t\t{...hoverProps}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t{children}\n\t\t\t</motion.div>\n\t\t</div>\n\t);\n}\n"}],"dependencies":["motion","react-use-measure"]}