{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel",
  "type": "registry:ui",
  "title": "Carousel",
  "dependencies": [
    "embla-carousel-react"
  ],
  "registryDependencies": [
    "https://neobrutalism.dev/r/nbutton.json"
  ],
  "files": [
    {
      "path": "src/components/ui/carousel.tsx",
      "content": "\"use client\"\r\n\r\nimport useEmblaCarousel, {\r\n  type UseEmblaCarouselType,\r\n} from \"embla-carousel-react\"\r\nimport { ArrowLeft, ArrowRight } from \"lucide-react\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { Button } from \"@/components/ui/button\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\ntype CarouselApi = UseEmblaCarouselType[1]\r\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\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<typeof useEmblaCarousel>[0]\r\n  api: ReturnType<typeof useEmblaCarousel>[1]\r\n  scrollPrev: () => void\r\n  scrollNext: () => void\r\n  canScrollPrev: boolean\r\n  canScrollNext: boolean\r\n  plugins?: CarouselPlugin\r\n} & CarouselProps\r\n\r\nconst CarouselContext = React.createContext<CarouselContextProps | null>(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 <Carousel />\")\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) {\r\n      return\r\n    }\r\n\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<HTMLDivElement>) => {\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) {\r\n      return\r\n    }\r\n\r\n    setApi(api)\r\n  }, [api, setApi])\r\n\r\n  React.useEffect(() => {\r\n    if (!api) {\r\n      return\r\n    }\r\n\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    <CarouselContext.Provider\r\n      value={{\r\n        carouselRef,\r\n        api: api,\r\n        opts,\r\n        orientation:\r\n          orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\r\n        scrollPrev,\r\n        scrollNext,\r\n        canScrollPrev,\r\n        canScrollNext,\r\n      }}\r\n    >\r\n      <div\r\n        onKeyDownCapture={handleKeyDown}\r\n        className={cn(\"relative\", className)}\r\n        role=\"region\"\r\n        aria-roledescription=\"carousel\"\r\n        data-slot=\"carousel\"\r\n        {...props}\r\n      >\r\n        {children}\r\n      </div>\r\n    </CarouselContext.Provider>\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    <div\r\n      ref={carouselRef}\r\n      className=\"overflow-hidden\"\r\n      data-slot=\"carousel-content\"\r\n    >\r\n      <div\r\n        className={cn(\r\n          \"flex\",\r\n          orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\r\n          className,\r\n        )}\r\n        {...props}\r\n      />\r\n    </div>\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    <div\r\n      data-slot=\"carousel-item\"\r\n      role=\"group\"\r\n      aria-roledescription=\"slide\"\r\n      className={cn(\r\n        \"min-w-0 shrink-0 grow-0 basis-full\",\r\n        orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  )\r\n}\r\n\r\nfunction CarouselPrevious({\r\n  className,\r\n  variant = \"noShadow\",\r\n  size = \"icon\",\r\n  ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n  const { orientation, scrollPrev, canScrollPrev } = useCarousel()\r\n\r\n  return (\r\n    <Button\r\n      data-slot=\"carousel-previous\"\r\n      variant={variant}\r\n      size={size}\r\n      className={cn(\r\n        \"absolute size-8 rounded-base\",\r\n        orientation === \"horizontal\"\r\n          ? \"top-1/2 -left-12 -translate-y-1/2\"\r\n          : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n        className,\r\n      )}\r\n      disabled={!canScrollPrev}\r\n      onClick={scrollPrev}\r\n      {...props}\r\n    >\r\n      <ArrowLeft />\r\n      <span className=\"sr-only\">Previous slide</span>\r\n    </Button>\r\n  )\r\n}\r\n\r\nfunction CarouselNext({\r\n  className,\r\n  variant = \"noShadow\",\r\n  size = \"icon\",\r\n  ...props\r\n}: React.ComponentProps<typeof Button>) {\r\n  const { orientation, scrollNext, canScrollNext } = useCarousel()\r\n\r\n  return (\r\n    <Button\r\n      data-slot=\"carousel-next\"\r\n      variant={variant}\r\n      size={size}\r\n      className={cn(\r\n        \"absolute h-8 w-8 rounded-base\",\r\n        orientation === \"horizontal\"\r\n          ? \"-right-12 top-1/2 -translate-y-1/2\"\r\n          : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\r\n        className,\r\n      )}\r\n      disabled={!canScrollNext}\r\n      onClick={scrollNext}\r\n      {...props}\r\n    >\r\n      <ArrowRight />\r\n      <span className=\"sr-only\">Next slide</span>\r\n    </Button>\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"
    }
  ]
}