{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "carousel",
  "title": "carousel",
  "description": "carousel",
  "dependencies": [
    "@heroicons/react",
    "embla-carousel-react",
    "cn"
  ],
  "registryDependencies": [
    "https://intentui.com/r/primitive",
    "https://intentui.com/r/button"
  ],
  "files": [
    {
      "path": "src/components/ui/carousel.tsx",
      "content": "\"use client\"\n\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@heroicons/react/20/solid\"\nimport useEmblaCarousel, { type UseEmblaCarouselType } from \"embla-carousel-react\"\nimport { createContext, use, useCallback, useEffect, useState } from \"react\"\nimport { cn } from \"cn\"\nimport { cx } from \"@/lib/primitive\"\nimport { Button, type ButtonProps } from \"./button\"\n\nexport type CarouselApi = UseEmblaCarouselType[1]\nexport type UseCarouselParameters = Parameters<typeof useEmblaCarousel>\nexport type CarouselOptions = UseCarouselParameters[0]\nexport type CarouselPlugin = UseCarouselParameters[1]\n\nexport type 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 = createContext<CarouselContextProps | null>(null)\n\nconst useCarousel = () => {\n  const context = use(CarouselContext)\n\n  if (!context) {\n    throw new Error(\"useCarousel must be used within a <Carousel />\")\n  }\n\n  return context\n}\n\nexport interface CarouselRootProps {\n  CarouselContent?: typeof CarouselContent\n  CarouselHandler?: typeof CarouselHandler\n  CarouselItem?: typeof CarouselItem\n  CarouselButton?: typeof CarouselButton\n}\n\nexport interface CarouselProps extends React.HTMLAttributes<HTMLDivElement>, CarouselRootProps {\n  opts?: CarouselOptions\n  plugins?: CarouselPlugin\n  orientation?: \"horizontal\" | \"vertical\"\n  setApi?: (api: CarouselApi) => void\n}\n\nexport function Carousel({\n  orientation = \"horizontal\",\n  opts,\n  setApi,\n  plugins,\n  className,\n  children,\n  ...props\n}: CarouselProps) {\n  const [carouselRef, api] = useEmblaCarousel(\n    {\n      ...opts,\n      axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n    },\n    plugins\n  )\n  const [canScrollPrev, setCanScrollPrev] = useState(false)\n  const [canScrollNext, setCanScrollNext] = useState(false)\n\n  const onSelect = useCallback((api: CarouselApi) => {\n    if (!api) {\n      return\n    }\n\n    setCanScrollPrev(api.canScrollPrev())\n    setCanScrollNext(api.canScrollNext())\n  }, [])\n\n  const scrollPrev = useCallback(() => {\n    api?.scrollPrev()\n  }, [api])\n\n  const scrollNext = useCallback(() => {\n    api?.scrollNext()\n  }, [api])\n\n  const handleKeyDown = 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  useEffect(() => {\n    if (!api || !setApi) {\n      return\n    }\n\n    setApi(api)\n  }, [api, setApi])\n\n  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(\"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    >\n      <div\n        onKeyDownCapture={handleKeyDown}\n        className={cn(\"relative\", className)}\n        role=\"region\"\n        aria-roledescription=\"carousel\"\n        {...props}\n      >\n        {children}\n      </div>\n    </CarouselContext.Provider>\n  )\n}\n\nexport function CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n  const { carouselRef, orientation } = useCarousel()\n\n  return (\n    <div ref={carouselRef} className=\"overflow-hidden\">\n      <div\n        className={cn(\"flex\", orientation === \"horizontal\" ? \"-ms-4\" : \"-mt-4 flex-col\", className)}\n        {...props}\n      />\n    </div>\n  )\n}\n\nexport function CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n  const { orientation } = useCarousel()\n\n  return (\n    <div\n      className={cn(\n        \"group/carousel-item relative min-w-0 shrink-0 grow-0 basis-full focus:outline-hidden focus-visible:outline-hidden\",\n        orientation === \"horizontal\" ? \"ps-4\" : \"pt-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport function CarouselHandler({ ref, className, ...props }: React.ComponentProps<\"div\">) {\n  const { orientation } = useCarousel()\n  return (\n    <div\n      data-slot=\"carousel-handler\"\n      ref={ref}\n      className={cn(\n        \"relative z-10 mt-6 flex items-center gap-x-2\",\n        orientation === \"horizontal\" ? \"justify-end\" : \"justify-center\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport function CarouselButton({\n  segment,\n  className,\n  intent = \"outline\",\n  isCircle = true,\n  size = \"sq-sm\",\n  ref,\n  ...props\n}: ButtonProps & { segment: \"previous\" | \"next\" }) {\n  const { orientation, scrollPrev, canScrollPrev, scrollNext, canScrollNext } = useCarousel()\n  const isNext = segment === \"next\"\n  const canScroll = isNext ? canScrollNext : canScrollPrev\n  const scroll = isNext ? scrollNext : scrollPrev\n  const Icon = isNext ? ChevronRightIcon : ChevronLeftIcon\n\n  return (\n    <Button\n      aria-label={isNext ? \"Next slide\" : \"Previous slide\"}\n      data-handler={segment}\n      intent={intent}\n      ref={ref}\n      size={size}\n      isCircle={isCircle}\n      className={cx([orientation === \"vertical\" ? \"rotate-90\" : \"\", \"shrink-0\"], className)}\n      isDisabled={!canScroll}\n      onPress={scroll}\n      {...props}\n    >\n      <Icon className=\"size-4\" />\n    </Button>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}