{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "dependencies": [
    "embla-carousel-react",
    "lucide-react"
  ],
  "files": [
    {
      "content": "export * from \"./carousel\";\nexport * as Carousel from \"./namespace\";\n",
      "path": "src/registry/ui/carousel/index.ts",
      "type": "registry:ui"
    },
    {
      "content": "\"use client\";\n\nimport useEmblaCarousel, {\n  type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { ArrowLeftIcon, ArrowRightIcon } from \"lucide-react\";\n\nimport { createContext, use, useCallback, useEffect, useState } from \"react\";\nimport { cn } from \"~/registry/lib/cva\";\nimport { Button, type ButtonProps } from \"~/registry/ui/button/button\";\n\nexport type CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\nexport interface CarouselProps extends React.ComponentProps<\"div\"> {\n  opts?: CarouselOptions;\n  orientation?: \"horizontal\" | \"vertical\";\n  plugins?: CarouselPlugin;\n  setApi?: (api: CarouselApi) => void;\n}\n\ninterface CarouselContextProps extends CarouselProps {\n  api: ReturnType<typeof useEmblaCarousel>[1];\n  canScrollNext: boolean;\n  canScrollPrev: boolean;\n  carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n  scrollNext: () => void;\n  scrollPrev: () => void;\n}\n\nconst CarouselContext = createContext<CarouselContextProps | null>(null);\n\nfunction 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 function CarouselRoot({\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    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    setApi(api);\n  }, [api, setApi]);\n\n  useEffect(() => {\n    if (!api) {\n      return;\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        api,\n        canScrollNext,\n        canScrollPrev,\n        carouselRef,\n        opts,\n        orientation:\n          orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n        scrollNext,\n        scrollPrev,\n      }}\n    >\n      {/** biome-ignore lint/a11y/useAriaPropsSupportedByRole: The role is correct. */}\n      <section\n        aria-roledescription=\"carousel\"\n        className={cn(\"relative\", className)}\n        data-slot=\"carousel\"\n        onKeyDownCapture={handleKeyDown}\n        {...props}\n      >\n        {children}\n      </section>\n    </CarouselContext.Provider>\n  );\n}\n\nexport interface CarouselContentProps extends React.ComponentProps<\"div\"> {}\n\nexport function CarouselContent({ className, ...props }: CarouselContentProps) {\n  const { carouselRef, orientation } = useCarousel();\n\n  return (\n    <div\n      className=\"overflow-hidden\"\n      data-slot=\"carousel-content\"\n      ref={carouselRef}\n    >\n      <div\n        className={cn(\n          \"flex\",\n          orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n          className\n        )}\n        {...props}\n      />\n    </div>\n  );\n}\n\nexport interface CarouselItemProps extends React.ComponentProps<\"div\"> {}\n\nexport function CarouselItem({ className, ...props }: CarouselItemProps) {\n  const { orientation } = useCarousel();\n\n  return (\n    <div\n      aria-roledescription=\"slide\"\n      className={cn(\n        \"min-w-0 shrink-0 grow-0 basis-full\",\n        orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n        className\n      )}\n      data-slot=\"carousel-item\"\n      role=\"group\"\n      {...props}\n    />\n  );\n}\n\nexport interface CarouselPreviousProps extends ButtonProps {}\n\nexport function CarouselPrevious({\n  className,\n  variant = \"outline\",\n  size = \"icon\",\n  ...props\n}: CarouselPreviousProps) {\n  const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n  return (\n    <Button\n      className={cn(\n        \"absolute size-8 rounded-full\",\n        orientation === \"horizontal\"\n          ? \"top-1/2 -left-12 -translate-y-1/2\"\n          : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n        className\n      )}\n      data-slot=\"carousel-previous\"\n      isDisabled={!canScrollPrev}\n      onPress={scrollPrev}\n      size={size}\n      variant={variant}\n      {...props}\n    >\n      <ArrowLeftIcon />\n      <span className=\"sr-only\">Previous slide</span>\n    </Button>\n  );\n}\n\nexport interface CarouselNextProps extends ButtonProps {}\n\nexport function CarouselNext({\n  className,\n  variant = \"outline\",\n  size = \"icon\",\n  ...props\n}: CarouselNextProps) {\n  const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n  return (\n    <Button\n      className={cn(\n        \"absolute size-8 rounded-full\",\n        orientation === \"horizontal\"\n          ? \"top-1/2 -right-12 -translate-y-1/2\"\n          : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n        className\n      )}\n      data-slot=\"carousel-next\"\n      isDisabled={!canScrollNext}\n      onPress={scrollNext}\n      size={size}\n      variant={variant}\n      {...props}\n    >\n      <ArrowRightIcon />\n      <span className=\"sr-only\">Next slide</span>\n    </Button>\n  );\n}\n",
      "path": "src/registry/ui/carousel/carousel.tsx",
      "type": "registry:ui"
    },
    {
      "content": "export {\n  CarouselContent as Content,\n  CarouselItem as Item,\n  CarouselNext as Next,\n  CarouselPrevious as Previous,\n  CarouselRoot as Root,\n} from \"./carousel\";\n",
      "path": "src/registry/ui/carousel/namespace.ts",
      "type": "registry:ui"
    }
  ],
  "name": "carousel",
  "registryDependencies": [
    "@kanpeki/cva",
    "@kanpeki/custom-plugin",
    "@kanpeki/button"
  ],
  "type": "registry:ui"
}