{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "horizontal-progressive-carousel",
  "dependencies": [
    "motion"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/ui/progressive-carousel.tsx",
      "content": "import { cn } from '@/lib/utils';\nimport { AnimatePresence, motion } from 'motion/react';\nimport React, {\n  createContext,\n  type FC,\n  type ReactNode,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n} from 'react';\n\n// Define the type for the context value\ninterface ProgressSliderContextType {\n  active: string;\n  progress: number;\n  handleButtonClick: (value: string) => void;\n  vertical: boolean;\n}\n\n// Define the type for the component props\ninterface ProgressSliderProps {\n  children: ReactNode;\n  duration?: number;\n  fastDuration?: number;\n  vertical?: boolean;\n  activeSlider: string;\n  className?: string;\n}\n\ninterface SliderContentProps {\n  children: ReactNode;\n  className?: string;\n}\n\ninterface SliderWrapperProps {\n  children: ReactNode;\n  value: string;\n  className?: string;\n}\n\ninterface ProgressBarProps {\n  children: ReactNode;\n  className?: string;\n}\n\ninterface SliderBtnProps {\n  children: ReactNode;\n  value: string;\n  className?: string;\n  progressBarClass?: string;\n}\n\n// Create the context with an undefined initial value\nconst ProgressSliderContext = createContext<ProgressSliderContextType | undefined>(undefined);\n\nexport const useProgressSliderContext = (): ProgressSliderContextType => {\n  const context = useContext(ProgressSliderContext);\n  if (!context) {\n    throw new Error('useProgressSliderContext must be used within a ProgressSlider');\n  }\n  return context;\n};\n\nexport const ProgressSlider: FC<ProgressSliderProps> = ({\n  children,\n  duration = 5000,\n  fastDuration = 400,\n  vertical = false,\n  activeSlider,\n  className,\n}) => {\n  const [active, setActive] = useState<string>(activeSlider);\n  const [progress, setProgress] = useState<number>(0);\n  const [isFastForward, setIsFastForward] = useState<boolean>(false);\n  const frame = useRef<number>(0);\n  const firstFrameTime = useRef<number>(performance.now());\n  const targetValue = useRef<string | null>(null);\n  const [sliderValues, setSliderValues] = useState<string[]>([]);\n\n  useEffect(() => {\n    const getChildren = React.Children.toArray(children).find(\n      (child) => (child as React.ReactElement<any>).type === SliderContent\n    ) as React.ReactElement<any> | undefined;\n\n    if (getChildren) {\n      const values = React.Children.toArray(getChildren.props.children).map(\n        (child) => (child as React.ReactElement<any>).props.value as string\n      );\n      setSliderValues(values);\n    }\n  }, [children]);\n\n  useEffect(() => {\n    if (sliderValues.length > 0) {\n      firstFrameTime.current = performance.now();\n      frame.current = requestAnimationFrame(animate);\n    }\n    return () => {\n      cancelAnimationFrame(frame.current);\n    };\n  }, [sliderValues, active, isFastForward]);\n\n  const animate = (now: number) => {\n    const currentDuration = isFastForward ? fastDuration : duration;\n    const elapsedTime = now - firstFrameTime.current;\n    const timeFraction = elapsedTime / currentDuration;\n\n    if (timeFraction <= 1) {\n      setProgress(isFastForward ? progress + (100 - progress) * timeFraction : timeFraction * 100);\n      frame.current = requestAnimationFrame(animate);\n    } else {\n      if (isFastForward) {\n        setIsFastForward(false);\n        if (targetValue.current !== null) {\n          setActive(targetValue.current);\n          targetValue.current = null;\n        }\n      } else {\n        // Move to the next slide\n        const currentIndex = sliderValues.indexOf(active);\n        const nextIndex = (currentIndex + 1) % sliderValues.length;\n        setActive(sliderValues[nextIndex]);\n      }\n      setProgress(0);\n      firstFrameTime.current = performance.now();\n    }\n  };\n\n  const handleButtonClick = (value: string) => {\n    if (value !== active) {\n      const elapsedTime = performance.now() - firstFrameTime.current;\n      const currentProgress = (elapsedTime / duration) * 100;\n      setProgress(currentProgress);\n      targetValue.current = value;\n      setIsFastForward(true);\n      firstFrameTime.current = performance.now();\n    }\n  };\n\n  return (\n    <ProgressSliderContext.Provider value={{ active, progress, handleButtonClick, vertical }}>\n      <div className={cn('relative', className)}>{children}</div>\n    </ProgressSliderContext.Provider>\n  );\n};\n\nexport const SliderContent: FC<SliderContentProps> = ({ children, className }) => {\n  return <div className={cn('', className)}>{children}</div>;\n};\n\nexport const SliderWrapper: FC<SliderWrapperProps> = ({ children, value, className }) => {\n  const { active } = useProgressSliderContext();\n\n  return (\n    <AnimatePresence mode='popLayout'>\n      {active === value && (\n        <motion.div\n          key={value}\n          initial={{ opacity: 0 }}\n          animate={{ opacity: 1 }}\n          exit={{ opacity: 0 }}\n          className={cn('', className)}\n        >\n          {children}\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n};\n\nexport const SliderBtnGroup: FC<ProgressBarProps> = ({ children, className }) => {\n  return <div className={cn('', className)}>{children}</div>;\n};\n\nexport const SliderBtn: FC<SliderBtnProps> = ({ children, value, className, progressBarClass }) => {\n  const { active, progress, handleButtonClick, vertical } = useProgressSliderContext();\n\n  return (\n    <button\n      className={cn(`relative ${active === value ? 'opacity-100' : 'opacity-50'}`, className)}\n      onClick={() => handleButtonClick(value)}\n    >\n      {children}\n      <div\n        className='absolute inset-0 overflow-hidden -z-10 max-h-full max-w-full '\n        role='progressbar'\n        aria-valuenow={active === value ? progress : 0}\n      >\n        <span\n          className={cn('absolute left-0 ', progressBarClass)}\n          style={{\n            [vertical ? 'height' : 'width']: active === value ? `${progress}%` : '0%',\n          }}\n        />\n      </div>\n    </button>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "./registry/components/carousel/horizontal-progressive.tsx",
      "content": "'use client';\nimport {\n  ProgressSlider,\n  SliderBtn,\n  SliderBtnGroup,\n  SliderContent,\n  SliderWrapper,\n} from '@/components/ui/progressive-carousel';\nimport Image from 'next/image';\n\nconst items = [\n  {\n    img: 'https://images.unsplash.com/photo-1548192746-dd526f154ed9?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n    title: 'Autumn',\n    desc: 'A picturesque path winding through a dense forest adorned with vibrant autumn foliage.',\n    sliderName: 'autumn',\n  },\n  {\n    img: 'https://images.unsplash.com/photo-1709949908058-a08659bfa922?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n    title: 'Bridge',\n    desc: 'A breathtaking view of a city illuminated by countless lights, showcasing the vibrant and bustling nightlife.',\n    sliderName: 'bridge',\n  },\n  {\n    img: 'https://images.unsplash.com/photo-1518972734183-c5b490a7c637?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n    title: 'Mountains View',\n    desc: 'A serene lake reflecting the surrounding mountains and trees, creating a mirror-like surface.',\n    sliderName: 'mountains',\n  },\n  {\n    img: 'https://images.unsplash.com/photo-1768300835487-f4711bf749de?q=80&w=1171&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n    title: 'Foggy',\n    sliderName: 'foggy',\n    desc: 'A stunning foggy view over the foresh, with the sun casting a golden glow across the forest',\n  },\n];\nexport default function HorizontalProgressive() {\n  return (\n    <>\n      <ProgressSlider vertical={false} activeSlider='bridge'>\n        <SliderContent>\n          {items.map((item, index) => (\n            <SliderWrapper key={item.sliderName} value={item?.sliderName}>\n              <Image\n                className='rounded-xl 2xl:h-[500px] xl:h-[400px] h-[350px] w-full object-cover'\n                src={item.img}\n                width={1900}\n                height={1080}\n                alt={item.desc}\n              />\n            </SliderWrapper>\n          ))}\n        </SliderContent>\n\n        <SliderBtnGroup className='absolute bottom-0 h-fit cursor-pointer dark:text-white text-black dark:bg-black/40 bg-white/40  backdrop-blur-md overflow-hidden grid grid-cols-2 md:grid-cols-4  rounded-md'>\n          {items.map((item, index) => (\n            <SliderBtn\n              key={item.sliderName}\n              value={item?.sliderName}\n              className='text-left  p-3 border-r'\n              progressBarClass='dark:bg-black bg-white h-full'\n            >\n              <h2 className='relative px-4 rounded-full w-fit dark:bg-white dark:text-black text-white bg-neutral-900 mb-2'>\n                {item.title}\n              </h2>\n              <p className='text-sm font-medium  line-clamp-2'>{item.desc}</p>\n            </SliderBtn>\n          ))}\n        </SliderBtnGroup>\n      </ProgressSlider>\n    </>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}