{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "carousel",
  "title": "carousel",
  "description": "carousel",
  "dependencies": [
    "@heroicons/react",
    "embla-carousel-react",
    "tailwind-merge"
  ],
  "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 { twMerge } from 'tailwind-merge'\nimport { cx } from '@/lib/primitive'\nimport { Button, type ButtonProps } from './button'\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\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 = 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\ninterface CarouselRootProps {\n  CarouselContent?: typeof CarouselContent\n  CarouselHandler?: typeof CarouselHandler\n  CarouselItem?: typeof CarouselItem\n  CarouselButton?: typeof CarouselButton\n}\n\ninterface CarouselProps extends React.HTMLAttributes<HTMLDivElement>, CarouselRootProps {\n  opts?: CarouselOptions\n  plugins?: CarouselPlugin\n  orientation?: 'horizontal' | 'vertical'\n  setApi?: (api: CarouselApi) => void\n}\n\nconst 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={twMerge('relative', className)}\n        role=\"region\"\n        aria-roledescription=\"carousel\"\n        {...props}\n      >\n        {children}\n      </div>\n    </CarouselContext.Provider>\n  )\n}\n\nconst 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={twMerge(\n          'flex',\n          orientation === 'horizontal' ? '-ms-4' : '-mt-4 flex-col',\n          className\n        )}\n        {...props}\n      />\n    </div>\n  )\n}\n\nconst CarouselItem = ({ className, ...props }: React.ComponentProps<'div'>) => {\n  const { orientation } = useCarousel()\n\n  return (\n    <div\n      className={twMerge(\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\nconst 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={twMerge(\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\nconst 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\nexport type { CarouselApi }\nexport { Carousel, CarouselButton, CarouselContent, CarouselHandler, CarouselItem }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}