{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "carousel", "title": "Carousel", "description": "A carousel for cycling through content.", "dependencies": [ "embla-carousel-react", "lucide-react" ], "files": [ { "path": "registry/default/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 '@/registry/default/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 TCarouselProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: 'horizontal' | 'vertical';\n};\n\ntype TCarouselContextProps = {\n carouselRef: ReturnType[0];\n api: ReturnType[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & TCarouselProps;\n\nconst CarouselContext = React.createContext(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\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 plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<'div'> & TCarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n { ...opts, axis: orientation === 'horizontal' ? 'x' : 'y' },\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 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) return;\n onSelect(api);\n api.on('reInit', onSelect);\n api.on('select', onSelect);\n\n return () => {\n api.off('reInit', onSelect);\n api.off('select', onSelect);\n };\n }, [api, onSelect]);\n\n const context = React.useMemo(\n () => ({\n carouselRef,\n api,\n opts,\n orientation:\n orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }),\n [\n carouselRef,\n api,\n opts,\n orientation,\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n ]\n );\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-md',\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-md',\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 Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n type CarouselApi,\n};\n", "type": "registry:ui" } ], "type": "registry:ui" }