{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel",
  "title": "Carousel",
  "description": "Embla-powered horizontal slider with prev/next controls.",
  "dependencies": ["embla-carousel-react", "lucide-react"],
  "registryDependencies": ["@glasswave/button"],
  "files": [
    {
      "path": "registry/glasswave/ui/carousel.tsx",
      "content": "\"use client\";\n\nimport useEmblaCarousel, {\n  type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { ArrowLeft, ArrowRight } from \"lucide-react\";\nimport {\n  createContext,\n  forwardRef,\n  useCallback,\n  useContext,\n  useEffect,\n  useState,\n} from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nexport type CarouselApi = UseEmblaCarouselType[1];\ntype CarouselOptions = NonNullable<Parameters<typeof useEmblaCarousel>[0]>;\ntype CarouselPlugins = NonNullable<Parameters<typeof useEmblaCarousel>[1]>;\n\ntype CarouselContextValue = {\n  carouselRef: UseEmblaCarouselType[0];\n  api: CarouselApi;\n  scrollPrev: () => void;\n  scrollNext: () => void;\n  canScrollPrev: boolean;\n  canScrollNext: boolean;\n};\n\nconst CarouselCtx = createContext<CarouselContextValue | null>(null);\n\nexport function useCarousel() {\n  const ctx = useContext(CarouselCtx);\n  if (!ctx) {\n    throw new Error(\"useCarousel must be used within <Carousel>\");\n  }\n  return ctx;\n}\n\nexport function Carousel({\n  orientation = \"horizontal\",\n  opts,\n  setApi,\n  plugins,\n  className,\n  children,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement> & {\n  opts?: CarouselOptions;\n  plugins?: CarouselPlugins;\n  orientation?: \"horizontal\" | \"vertical\";\n  setApi?: (api: CarouselApi) => void;\n}) {\n  const [carouselRef, api] = useEmblaCarousel(\n    { ...opts, axis: orientation === \"horizontal\" ? \"x\" : \"y\" },\n    plugins,\n  );\n  const [canScrollPrev, setCanScrollPrev] = useState(false);\n  const [canScrollNext, setCanScrollNext] = useState(false);\n\n  const onSelect = useCallback((emblaApi: CarouselApi) => {\n    if (!emblaApi) return;\n    setCanScrollPrev(emblaApi.canScrollPrev());\n    setCanScrollNext(emblaApi.canScrollNext());\n  }, []);\n\n  useEffect(() => {\n    if (!api) return;\n    setApi?.(api);\n    onSelect(api);\n    api.on(\"reInit\", onSelect);\n    api.on(\"select\", onSelect);\n    return () => {\n      api.off(\"select\", onSelect);\n    };\n  }, [api, onSelect, setApi]);\n\n  const scrollPrev = useCallback(() => api?.scrollPrev(), [api]);\n  const scrollNext = useCallback(() => api?.scrollNext(), [api]);\n\n  return (\n    <CarouselCtx.Provider\n      value={{\n        carouselRef,\n        api,\n        scrollPrev,\n        scrollNext,\n        canScrollPrev,\n        canScrollNext,\n      }}\n    >\n      <div\n        className={cn(\"relative\", className)}\n        role=\"region\"\n        aria-roledescription=\"carousel\"\n        {...props}\n      >\n        {children}\n      </div>\n    </CarouselCtx.Provider>\n  );\n}\n\nexport const CarouselContent = forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n  const { carouselRef } = useCarousel();\n  return (\n    <div\n      ref={carouselRef}\n      className=\"overflow-hidden rounded-[32px] border border-black/[0.08] dark:border-white/[0.15]\"\n    >\n      <div ref={ref} className={cn(\"flex\", className)} {...props} />\n    </div>\n  );\n});\nCarouselContent.displayName = \"CarouselContent\";\n\nexport const CarouselItem = forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    role=\"group\"\n    aria-roledescription=\"slide\"\n    className={cn(\n      \"min-w-0 shrink-0 grow-0 basis-full px-2 py-1 md:px-4\",\n      className,\n    )}\n    {...props}\n  />\n));\nCarouselItem.displayName = \"CarouselItem\";\n\nexport const CarouselPrevious = forwardRef<\n  HTMLButtonElement,\n  React.ComponentProps<\"button\">\n>(({ className, ...props }, ref) => {\n  const { scrollPrev, canScrollPrev } = useCarousel();\n  return (\n    <button\n      ref={ref}\n      type=\"button\"\n      disabled={!canScrollPrev}\n      className={cn(\n        buttonVariants({ variant: \"glass\", size: \"icon\" }),\n        \"absolute left-2 top-1/2 z-10 -translate-y-1/2\",\n        className,\n      )}\n      onClick={scrollPrev}\n      {...props}\n    >\n      <ArrowLeft className=\"size-4\" />\n      <span className=\"sr-only\">Previous slide</span>\n    </button>\n  );\n});\nCarouselPrevious.displayName = \"CarouselPrevious\";\n\nexport const CarouselNext = forwardRef<\n  HTMLButtonElement,\n  React.ComponentProps<\"button\">\n>(({ className, ...props }, ref) => {\n  const { scrollNext, canScrollNext } = useCarousel();\n  return (\n    <button\n      ref={ref}\n      type=\"button\"\n      disabled={!canScrollNext}\n      className={cn(\n        buttonVariants({ variant: \"glass\", size: \"icon\" }),\n        \"absolute right-2 top-1/2 z-10 -translate-y-1/2\",\n        className,\n      )}\n      onClick={scrollNext}\n      {...props}\n    >\n      <ArrowRight className=\"size-4\" />\n      <span className=\"sr-only\">Next slide</span>\n    </button>\n  );\n});\nCarouselNext.displayName = \"CarouselNext\";\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
