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