{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"carousel","type":"registry:ui","title":"Carousel","description":"Tailark Base UI Carousel component","dependencies":["embla-carousel-react"],"registryDependencies":["@tailark/core-utils","@tailark/button"],"files":[{"path":"ui/carousel.tsx","type":"registry:ui","target":"@ui/carousel.tsx","content":"'use client'\n\nimport * as React from 'react'\nimport useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'\nimport { ArrowLeft, ArrowRight } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\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<typeof useEmblaCarousel>[0]\n    api: ReturnType<typeof useEmblaCarousel>[1]\n    scrollPrev: () => void\n    scrollNext: () => void\n    canScrollPrev: boolean\n    canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n    const context = React.useContext(CarouselContext)\n\n    if (!context) {\n        throw new Error('useCarousel must be used within a <Carousel />')\n    }\n\n    return context\n}\n\nconst Carousel = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps>(({ orientation = 'horizontal', opts, setApi, plugins, className, children, ...props }, ref) => {\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) {\n            return\n        }\n\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<HTMLDivElement>) => {\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) {\n            return\n        }\n\n        setApi(api)\n    }, [api, setApi])\n\n    React.useEffect(() => {\n        if (!api) {\n            return\n        }\n\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    return (\n        <CarouselContext.Provider\n            value={{\n                carouselRef,\n                api: api,\n                opts,\n                orientation: orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),\n                scrollPrev,\n                scrollNext,\n                canScrollPrev,\n                canScrollNext,\n            }}>\n            <div\n                ref={ref}\n                onKeyDownCapture={handleKeyDown}\n                className={cn('relative', className)}\n                role=\"region\"\n                aria-roledescription=\"carousel\"\n                {...props}>\n                {children}\n            </div>\n        </CarouselContext.Provider>\n    )\n})\nCarousel.displayName = 'Carousel'\n\nconst CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => {\n    const { carouselRef, orientation } = useCarousel()\n\n    return (\n        <div\n            ref={carouselRef}\n            className=\"overflow-hidden px-4\">\n            <div\n                ref={ref}\n                className={cn('flex', orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col', className)}\n                {...props}\n            />\n        </div>\n    )\n})\nCarouselContent.displayName = 'CarouselContent'\n\nconst CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => {\n    const { orientation } = useCarousel()\n\n    return (\n        <div\n            ref={ref}\n            role=\"group\"\n            aria-roledescription=\"slide\"\n            className={cn('min-w-0 shrink-0 grow-0 basis-full', orientation === 'horizontal' ? 'pl-4' : 'pt-4', className)}\n            {...props}\n        />\n    )\n})\nCarouselItem.displayName = 'CarouselItem'\n\nconst CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {\n    const { scrollPrev, canScrollPrev } = useCarousel()\n\n    return (\n        <Button\n            ref={ref}\n            variant={variant}\n            size={size}\n            className={cn('size-8 rounded-full', className)}\n            disabled={!canScrollPrev}\n            onClick={scrollPrev}\n            {...props}>\n            <ArrowLeft className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Previous slide</span>\n        </Button>\n    )\n})\nCarouselPrevious.displayName = 'CarouselPrevious'\n\nconst CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(({ className, variant = 'outline', size = 'icon', ...props }, ref) => {\n    const { scrollNext, canScrollNext } = useCarousel()\n\n    return (\n        <Button\n            ref={ref}\n            variant={variant}\n            size={size}\n            className={cn('size-8 rounded-full', className)}\n            disabled={!canScrollNext}\n            onClick={scrollNext}\n            {...props}>\n            <ArrowRight className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Next slide</span>\n        </Button>\n    )\n})\nCarouselNext.displayName = 'CarouselNext'\n\nexport { type CarouselApi, Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }\n"}]}