{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "carousel", "type": "registry:ui", "dependencies": [ "lucide-react", "embla-carousel-react" ], "files": [ { "path": "components/ui/carousel.tsx", "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport useEmblaCarousel, {\r\n type UseEmblaCarouselType,\r\n} from \"embla-carousel-react\"\r\nimport { ArrowLeft, ArrowRight } from \"lucide-react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\nimport { Button } from \"@/components/ui/button\"\r\n\r\ntype CarouselApi = UseEmblaCarouselType[1]\r\ntype UseCarouselParameters = Parameters\r\ntype CarouselOptions = UseCarouselParameters[0]\r\ntype CarouselPlugin = UseCarouselParameters[1]\r\n\r\ntype CarouselProps = {\r\n opts?: CarouselOptions\r\n plugins?: CarouselPlugin\r\n orientation?: \"horizontal\" | \"vertical\"\r\n setApi?: (api: CarouselApi) => void\r\n}\r\n\r\ntype CarouselContextProps = {\r\n carouselRef: ReturnType[0]\r\n api: ReturnType[1]\r\n scrollPrev: () => void\r\n scrollNext: () => void\r\n canScrollPrev: boolean\r\n canScrollNext: boolean\r\n} & CarouselProps\r\n\r\nconst CarouselContext = React.createContext(null)\r\n\r\nfunction useCarousel() {\r\n const context = React.useContext(CarouselContext)\r\n\r\n if (!context) {\r\n throw new Error(\"useCarousel must be used within a \")\r\n }\r\n\r\n return context\r\n}\r\n\r\nfunction Carousel({\r\n orientation = \"horizontal\",\r\n opts,\r\n setApi,\r\n plugins,\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\"> & CarouselProps) {\r\n const [carouselRef, api] = useEmblaCarousel(\r\n {\r\n ...opts,\r\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\r\n },\r\n plugins\r\n )\r\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\r\n const [canScrollNext, setCanScrollNext] = React.useState(false)\r\n\r\n const onSelect = React.useCallback((api: CarouselApi) => {\r\n if (!api) return\r\n setCanScrollPrev(api.canScrollPrev())\r\n setCanScrollNext(api.canScrollNext())\r\n }, [])\r\n\r\n const scrollPrev = React.useCallback(() => {\r\n api?.scrollPrev()\r\n }, [api])\r\n\r\n const scrollNext = React.useCallback(() => {\r\n api?.scrollNext()\r\n }, [api])\r\n\r\n const handleKeyDown = React.useCallback(\r\n (event: React.KeyboardEvent) => {\r\n if (event.key === \"ArrowLeft\") {\r\n event.preventDefault()\r\n scrollPrev()\r\n } else if (event.key === \"ArrowRight\") {\r\n event.preventDefault()\r\n scrollNext()\r\n }\r\n },\r\n [scrollPrev, scrollNext]\r\n )\r\n\r\n React.useEffect(() => {\r\n if (!api || !setApi) return\r\n setApi(api)\r\n }, [api, setApi])\r\n\r\n React.useEffect(() => {\r\n if (!api) return\r\n onSelect(api)\r\n api.on(\"reInit\", onSelect)\r\n api.on(\"select\", onSelect)\r\n\r\n return () => {\r\n api?.off(\"select\", onSelect)\r\n }\r\n }, [api, onSelect])\r\n\r\n return (\r\n \r\n \r\n {children}\r\n \r\n \r\n )\r\n}\r\n\r\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { carouselRef, orientation } = useCarousel()\r\n\r\n return (\r\n \r\n \r\n \r\n )\r\n}\r\n\r\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\r\n const { orientation } = useCarousel()\r\n\r\n return (\r\n \r\n )\r\n}\r\n\r\nfunction CarouselPrevious({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon\",\r\n ...props\r\n}: React.ComponentProps) {\r\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\r\n\r\n return (\r\n \r\n \r\n Previous slide\r\n \r\n )\r\n}\r\n\r\nfunction CarouselNext({\r\n className,\r\n variant = \"outline\",\r\n size = \"icon\",\r\n ...props\r\n}: React.ComponentProps) {\r\n const { orientation, scrollNext, canScrollNext } = useCarousel()\r\n\r\n return (\r\n \r\n \r\n Next slide\r\n \r\n )\r\n}\r\n\r\nexport {\r\n type CarouselApi,\r\n Carousel,\r\n CarouselContent,\r\n CarouselItem,\r\n CarouselPrevious,\r\n CarouselNext,\r\n}\r\n", "type": "registry:ui", "target": "components/ui/carousel.tsx" } ] }