{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progress-carousel",
  "type": "registry:block",
  "title": "Progress carousel",
  "description": "Progress carousel",
  "files": [
    {
      "path": "components/usages/progresscarouselusage.tsx",
      "content": "\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport Image from \"next/image\";\r\n\r\nimport {\r\n\tProgressCarousel,\r\n\tSliderBtn,\r\n\tSliderBtnGroup,\r\n\tSliderContent,\r\n\tSliderWrapper,\r\n} from \"@/registry/open-source/progress-carousel\";\r\n\r\nexport default function Usage() {\r\n\tconst items = [\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Bridge\",\r\n\t\t\tdesc: \"A breathtaking view of a city illuminated by countless lights, showcasing the vibrant and bustling nightlife.\",\r\n\t\t\tsliderName: \"bridge\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Mountains View\",\r\n\t\t\tdesc: \"A serene lake reflecting the surrounding mountains and trees, creating a mirror-like surface.\",\r\n\t\t\tsliderName: \"mountains\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Autumn\",\r\n\t\t\tdesc: \"A picturesque path winding through a dense forest adorned with vibrant autumn foliage.\",\r\n\t\t\tsliderName: \"autumn\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Foggy\",\r\n\t\t\tsliderName: \"foggy\",\r\n\t\t\tdesc: \"A stunning foggy view over the foresh, with the sun casting a golden glow across the forest. \",\r\n\t\t},\r\n\t];\r\n\treturn (\r\n\t\t<div className=\"h-screen w-full flex items-center justify-center relative overflow-hidden bg-background\">\r\n\t\t\t<ProgressCarousel vertical={false} activeSlider=\"bridge\">\r\n\t\t\t\t<SliderContent>\r\n\t\t\t\t\t{items.map((item, index) => (\r\n\t\t\t\t\t\t<SliderWrapper value={item?.sliderName + \"wrapper\"}>\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tclassName=\"rounded-xl 2xl:h-[500px] h-[350px] object-cover\"\r\n\t\t\t\t\t\t\t\tsrc={item.img}\r\n\t\t\t\t\t\t\t\twidth={1900}\r\n\t\t\t\t\t\t\t\theight={1080}\r\n\t\t\t\t\t\t\t\talt={item.desc}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</SliderWrapper>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</SliderContent>\r\n\r\n\t\t\t\t<SliderBtnGroup className=\"absolute bottom-0 h-fit dark:text-secondary text-secondary dark:bg-background/40 bg-background/40  backdrop-blur-md overflow-hidden grid grid-cols-2 md:grid-cols-4  rounded-md\">\r\n\t\t\t\t\t{items.map((item, index) => (\r\n\t\t\t\t\t\t<SliderBtn\r\n\t\t\t\t\t\t\tvalue={item?.sliderName}\r\n\t\t\t\t\t\t\tclassName=\"text-left  p-3 border-r\"\r\n\t\t\t\t\t\t\tprogressBarClass=\"dark:bg-background bg-background h-full\"\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<span className=\"relative px-4 rounded-full w-fit dark:bg-background dark:text-secondary text-secondary bg-background mb-2\">\r\n\t\t\t\t\t\t\t\t{item.title}\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t\t<span className=\"text-sm font-medium  line-clamp-2\">\r\n\t\t\t\t\t\t\t\t{item.desc}\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t</SliderBtn>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</SliderBtnGroup>\r\n\t\t\t</ProgressCarousel>{\" \"}\r\n\t\t</div>\r\n\t);\r\n}\r\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/progresscarouselusage.tsx",
      "content": "\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport Image from \"next/image\";\r\n\r\nimport {\r\n\tProgressCarousel,\r\n\tSliderBtn,\r\n\tSliderBtnGroup,\r\n\tSliderContent,\r\n\tSliderWrapper,\r\n} from \"@/registry/open-source/progress-carousel\";\r\n\r\nexport default function Usage() {\r\n\tconst items = [\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Bridge\",\r\n\t\t\tdesc: \"A breathtaking view of a city illuminated by countless lights, showcasing the vibrant and bustling nightlife.\",\r\n\t\t\tsliderName: \"bridge\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Mountains View\",\r\n\t\t\tdesc: \"A serene lake reflecting the surrounding mountains and trees, creating a mirror-like surface.\",\r\n\t\t\tsliderName: \"mountains\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Autumn\",\r\n\t\t\tdesc: \"A picturesque path winding through a dense forest adorned with vibrant autumn foliage.\",\r\n\t\t\tsliderName: \"autumn\",\r\n\t\t},\r\n\t\t{\r\n\t\t\timg: \"/itjustworks.jpg\",\r\n\t\t\ttitle: \"Foggy\",\r\n\t\t\tsliderName: \"foggy\",\r\n\t\t\tdesc: \"A stunning foggy view over the foresh, with the sun casting a golden glow across the forest. \",\r\n\t\t},\r\n\t];\r\n\treturn (\r\n\t\t<div className=\"h-screen w-full flex items-center justify-center relative overflow-hidden bg-background\">\r\n\t\t\t<ProgressCarousel vertical={false} activeSlider=\"bridge\">\r\n\t\t\t\t<SliderContent>\r\n\t\t\t\t\t{items.map((item, index) => (\r\n\t\t\t\t\t\t<SliderWrapper value={item?.sliderName + \"wrapper\"}>\r\n\t\t\t\t\t\t\t<Image\r\n\t\t\t\t\t\t\t\tclassName=\"rounded-xl 2xl:h-[500px] h-[350px] object-cover\"\r\n\t\t\t\t\t\t\t\tsrc={item.img}\r\n\t\t\t\t\t\t\t\twidth={1900}\r\n\t\t\t\t\t\t\t\theight={1080}\r\n\t\t\t\t\t\t\t\talt={item.desc}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</SliderWrapper>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</SliderContent>\r\n\r\n\t\t\t\t<SliderBtnGroup className=\"absolute bottom-0 h-fit dark:text-secondary text-secondary dark:bg-background/40 bg-background/40  backdrop-blur-md overflow-hidden grid grid-cols-2 md:grid-cols-4  rounded-md\">\r\n\t\t\t\t\t{items.map((item, index) => (\r\n\t\t\t\t\t\t<SliderBtn\r\n\t\t\t\t\t\t\tvalue={item?.sliderName}\r\n\t\t\t\t\t\t\tclassName=\"text-left  p-3 border-r\"\r\n\t\t\t\t\t\t\tprogressBarClass=\"dark:bg-background bg-background h-full\"\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<span className=\"relative px-4 rounded-full w-fit dark:bg-background dark:text-secondary text-secondary bg-background mb-2\">\r\n\t\t\t\t\t\t\t\t{item.title}\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t\t<span className=\"text-sm font-medium  line-clamp-2\">\r\n\t\t\t\t\t\t\t\t{item.desc}\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t</SliderBtn>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</SliderBtnGroup>\r\n\t\t\t</ProgressCarousel>{\" \"}\r\n\t\t</div>\r\n\t);\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/progress-carousel.tsx",
      "content": "import React, {\n\tcreateContext,\n\tFC,\n\tReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nimport { cn } from \"@/registry/utilities/cn\";\nimport { AnimatePresence, motion } from \"motion/react\";\n\n// Credit:\n// https://www.ui-layouts.com/components/progressive-carousel\n\n// Define the type for the context value\ninterface ProgressCarouselContextType {\n\tactive: string;\n\tprogress: number;\n\thandleButtonClick: (value: string) => void;\n\tvertical: boolean;\n}\n\n// Define the type for the component props\ninterface ProgressCarouselProps {\n\tchildren: ReactNode;\n\tduration?: number;\n\tfastDuration?: number;\n\tvertical?: boolean;\n\tactiveSlider: string;\n\tclassName?: string;\n}\n\ninterface SliderContentProps {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\ninterface SliderWrapperProps {\n\tchildren: ReactNode;\n\tvalue: string;\n\tclassName?: string;\n}\n\ninterface ProgressBarProps {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\ninterface SliderBtnProps {\n\tchildren: ReactNode;\n\tvalue: string;\n\tclassName?: string;\n\tprogressBarClass?: string;\n}\n\n// Create the context with an undefined initial value\nconst ProgressCarouselContext = createContext<\n\tProgressCarouselContextType | undefined\n>(undefined);\n\nexport const useProgressCarouselContext = (): ProgressCarouselContextType => {\n\tconst context = useContext(ProgressCarouselContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useProgressCarouselContext must be used within a ProgressCarousel\"\n\t\t);\n\t}\n\treturn context;\n};\n\nexport const ProgressCarousel: FC<ProgressCarouselProps> = ({\n\tchildren,\n\tduration = 5000,\n\tfastDuration = 400,\n\tvertical = false,\n\tactiveSlider,\n\tclassName,\n}) => {\n\tconst [active, setActive] = useState<string>(activeSlider);\n\tconst [progress, setProgress] = useState<number>(0);\n\tconst [isFastForward, setIsFastForward] = useState<boolean>(false);\n\tconst frame = useRef<number>(0);\n\tconst firstFrameTime = useRef<number>(performance.now());\n\tconst targetValue = useRef<string | null>(null);\n\tconst [sliderValues, setSliderValues] = useState<string[]>([]);\n\n\tuseEffect(() => {\n\t\tconst getChildren = React.Children.toArray(children).find(\n\t\t\t(child) => (child as React.ReactElement).type === SliderContent\n\t\t) as React.ReactElement | undefined;\n\n\t\tif (getChildren) {\n\t\t\tconst values = React.Children.toArray(getChildren.props.children).map(\n\t\t\t\t(child) => (child as React.ReactElement).props.value as string\n\t\t\t);\n\t\t\tsetSliderValues(values);\n\t\t}\n\t}, [children]);\n\n\tuseEffect(() => {\n\t\tif (sliderValues.length > 0) {\n\t\t\tfirstFrameTime.current = performance.now();\n\t\t\tframe.current = requestAnimationFrame(animate);\n\t\t}\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(frame.current);\n\t\t};\n\t}, [sliderValues, active, isFastForward]);\n\n\tconst animate = (now: number) => {\n\t\tconst currentDuration = isFastForward ? fastDuration : duration;\n\t\tconst elapsedTime = now - firstFrameTime.current;\n\t\tconst timeFraction = elapsedTime / currentDuration;\n\n\t\tif (timeFraction <= 1) {\n\t\t\tsetProgress(\n\t\t\t\tisFastForward\n\t\t\t\t\t? progress + (100 - progress) * timeFraction\n\t\t\t\t\t: timeFraction * 100\n\t\t\t);\n\t\t\tframe.current = requestAnimationFrame(animate);\n\t\t} else {\n\t\t\tif (isFastForward) {\n\t\t\t\tsetIsFastForward(false);\n\t\t\t\tif (targetValue.current !== null) {\n\t\t\t\t\tsetActive(targetValue.current);\n\t\t\t\t\ttargetValue.current = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Move to the next slide\n\t\t\t\tconst currentIndex = sliderValues.indexOf(active);\n\t\t\t\tconst nextIndex = (currentIndex + 1) % sliderValues.length;\n\t\t\t\tsetActive(sliderValues[nextIndex]);\n\t\t\t}\n\t\t\tsetProgress(0);\n\t\t\tfirstFrameTime.current = performance.now();\n\t\t}\n\t};\n\n\tconst handleButtonClick = (value: string) => {\n\t\tif (value !== active) {\n\t\t\tconst elapsedTime = performance.now() - firstFrameTime.current;\n\t\t\tconst currentProgress = (elapsedTime / duration) * 100;\n\t\t\tsetProgress(currentProgress);\n\t\t\ttargetValue.current = value;\n\t\t\tsetIsFastForward(true);\n\t\t\tfirstFrameTime.current = performance.now();\n\t\t}\n\t};\n\n\treturn (\n\t\t<ProgressCarouselContext.Provider\n\t\t\tvalue={{ active, progress, handleButtonClick, vertical }}\n\t\t>\n\t\t\t<div className={cn(\"relative\", className)}>{children}</div>\n\t\t</ProgressCarouselContext.Provider>\n\t);\n};\n\nexport const SliderContent: FC<SliderContentProps> = ({\n\tchildren,\n\tclassName,\n}) => {\n\treturn <div className={cn(\"\", className)}>{children}</div>;\n};\n\nexport const SliderWrapper: FC<SliderWrapperProps> = ({\n\tchildren,\n\tvalue,\n\tclassName,\n}) => {\n\tconst { active } = useProgressCarouselContext();\n\n\treturn (\n\t\t<AnimatePresence mode=\"popLayout\">\n\t\t\t{active === value && (\n\t\t\t\t<motion.div\n\t\t\t\t\tkey={value}\n\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\tclassName={cn(\"\", className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</motion.div>\n\t\t\t)}\n\t\t</AnimatePresence>\n\t);\n};\n\nexport const SliderBtnGroup: FC<ProgressBarProps> = ({\n\tchildren,\n\tclassName,\n}) => {\n\treturn <div className={cn(\"\", className)}>{children}</div>;\n};\n\nexport const SliderBtn: FC<SliderBtnProps> = ({\n\tchildren,\n\tvalue,\n\tclassName,\n\tprogressBarClass,\n}) => {\n\tconst { active, progress, handleButtonClick, vertical } =\n\t\tuseProgressCarouselContext();\n\n\treturn (\n\t\t<button\n\t\t\tclassName={cn(\n\t\t\t\t`relative ${active === value ? \"opacity-100\" : \"opacity-50\"}`,\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tonClick={() => handleButtonClick(value)}\n\t\t\tkey={value}\n\t\t>\n\t\t\t{children}\n\t\t\t<div\n\t\t\t\tclassName=\"absolute inset-0 overflow-hidden -z-10 max-h-full max-w-full \"\n\t\t\t\trole=\"progressbar\"\n\t\t\t\taria-valuenow={active === value ? progress : 0}\n\t\t\t>\n\t\t\t\t<span\n\t\t\t\t\tclassName={cn(\"absolute left-0 \", progressBarClass)}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t[vertical ? \"height\" : \"width\"]:\n\t\t\t\t\t\t\tactive === value ? `${progress}%` : \"0%\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</button>\n\t);\n};\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}