{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel",
  "title": "Carousel",
  "description": "Swipeable carousel with previous/next controls, built on Embla.",
  "dependencies": [
    "embla-carousel-react@^8.6.0",
    "lucide-react@^1.48.0"
  ],
  "registryDependencies": [
    "https://rdf.dev.360online.com/r/button.json"
  ],
  "files": [
    {
      "path": "registry/rapid/ui/carousel/carousel.tsx",
      "content": "'use client'\n\nimport useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'\nimport { ChevronLeftIcon, ChevronRightIcon } 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<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\ntype CarouselProps = {\n\topts?: CarouselOptions\n\tplugins?: CarouselPlugin\n\torientation?: 'horizontal' | 'vertical'\n\tsetApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n\tcarouselRef: ReturnType<typeof useEmblaCarousel>[0]\n\tapi: ReturnType<typeof useEmblaCarousel>[1]\n\tscrollPrev: () => void\n\tscrollNext: () => void\n\tcanScrollPrev: boolean\n\tcanScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n\tconst context = React.useContext(CarouselContext)\n\n\tif (!context) {\n\t\tthrow new Error('useCarousel must be used within a <Carousel />')\n\t}\n\n\treturn context\n}\n\nfunction Carousel({\n\torientation = 'horizontal',\n\topts,\n\tsetApi,\n\tplugins,\n\tclassName,\n\tchildren,\n\t...props\n}: React.ComponentProps<'div'> & CarouselProps) {\n\tconst [carouselRef, api] = useEmblaCarousel(\n\t\t{\n\t\t\t...opts,\n\t\t\taxis: orientation === 'horizontal' ? 'x' : 'y',\n\t\t},\n\t\tplugins,\n\t)\n\tconst [canScrollPrev, setCanScrollPrev] = React.useState(false)\n\tconst [canScrollNext, setCanScrollNext] = React.useState(false)\n\n\tconst onSelect = React.useCallback((api: CarouselApi) => {\n\t\tif (!api) return\n\t\tsetCanScrollPrev(api.canScrollPrev())\n\t\tsetCanScrollNext(api.canScrollNext())\n\t}, [])\n\n\tconst scrollPrev = React.useCallback(() => {\n\t\tapi?.scrollPrev()\n\t}, [api])\n\n\tconst scrollNext = React.useCallback(() => {\n\t\tapi?.scrollNext()\n\t}, [api])\n\n\tconst handleKeyDown = React.useCallback(\n\t\t(event: React.KeyboardEvent<HTMLDivElement>) => {\n\t\t\tif (event.key === 'ArrowLeft') {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tscrollPrev()\n\t\t\t} else if (event.key === 'ArrowRight') {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tscrollNext()\n\t\t\t}\n\t\t},\n\t\t[scrollPrev, scrollNext],\n\t)\n\n\tReact.useEffect(() => {\n\t\tif (!api || !setApi) return\n\t\tsetApi(api)\n\t}, [api, setApi])\n\n\tReact.useEffect(() => {\n\t\tif (!api) return\n\t\tonSelect(api)\n\t\tapi.on('reInit', onSelect)\n\t\tapi.on('select', onSelect)\n\n\t\treturn () => {\n\t\t\tapi?.off('select', onSelect)\n\t\t}\n\t}, [api, onSelect])\n\n\tconst contextValue = React.useMemo<CarouselContextProps>(\n\t\t() => ({\n\t\t\tcarouselRef,\n\t\t\tapi,\n\t\t\topts,\n\t\t\torientation: orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),\n\t\t\tscrollPrev,\n\t\t\tscrollNext,\n\t\t\tcanScrollPrev,\n\t\t\tcanScrollNext,\n\t\t}),\n\t\t[carouselRef, api, opts, orientation, scrollPrev, scrollNext, canScrollPrev, canScrollNext],\n\t)\n\n\treturn (\n\t\t<CarouselContext.Provider value={contextValue}>\n\t\t\t<div\n\t\t\t\tonKeyDownCapture={handleKeyDown}\n\t\t\t\tclassName={cn('relative', className)}\n\t\t\t\trole=\"region\"\n\t\t\t\taria-roledescription=\"carousel\"\n\t\t\t\tdata-slot=\"carousel\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</CarouselContext.Provider>\n\t)\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<'div'>) {\n\tconst { carouselRef, orientation } = useCarousel()\n\n\treturn (\n\t\t<div ref={carouselRef} className=\"overflow-hidden\" data-slot=\"carousel-content\">\n\t\t\t<div className={cn('flex', orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col', className)} {...props} />\n\t\t</div>\n\t)\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<'div'>) {\n\tconst { orientation } = useCarousel()\n\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-roledescription=\"slide\"\n\t\t\tdata-slot=\"carousel-item\"\n\t\t\tclassName={cn('min-w-0 shrink-0 grow-0 basis-full', orientation === 'horizontal' ? 'pl-4' : 'pt-4', className)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction CarouselPrevious({\n\tclassName,\n\tvariant = 'outline',\n\tsize = 'icon-sm',\n\t...props\n}: React.ComponentProps<typeof Button>) {\n\tconst { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n\treturn (\n\t\t<Button\n\t\t\tdata-slot=\"carousel-previous\"\n\t\t\tvariant={variant}\n\t\t\tsize={size}\n\t\t\tclassName={cn(\n\t\t\t\t'absolute touch-manipulation rounded-full',\n\t\t\t\torientation === 'horizontal' ? 'inset-y-0 -left-12 my-auto' : '-top-12 left-1/2 -translate-x-1/2 rotate-90',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tdisabled={!canScrollPrev}\n\t\t\tonClick={scrollPrev}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronLeftIcon />\n\t\t\t<span className=\"sr-only\">Previous slide</span>\n\t\t</Button>\n\t)\n}\n\nfunction CarouselNext({\n\tclassName,\n\tvariant = 'outline',\n\tsize = 'icon-sm',\n\t...props\n}: React.ComponentProps<typeof Button>) {\n\tconst { orientation, scrollNext, canScrollNext } = useCarousel()\n\n\treturn (\n\t\t<Button\n\t\t\tdata-slot=\"carousel-next\"\n\t\t\tvariant={variant}\n\t\t\tsize={size}\n\t\t\tclassName={cn(\n\t\t\t\t'absolute touch-manipulation rounded-full',\n\t\t\t\torientation === 'horizontal' ? 'inset-y-0 -right-12 my-auto' : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tdisabled={!canScrollNext}\n\t\t\tonClick={scrollNext}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronRightIcon />\n\t\t\t<span className=\"sr-only\">Next slide</span>\n\t\t</Button>\n\t)\n}\n\nexport { type CarouselApi, Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, useCarousel }\n",
      "type": "registry:ui",
      "target": "components/ui/carousel.tsx"
    }
  ],
  "meta": {
    "new": true
  },
  "type": "registry:ui"
}