{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel",
  "type": "registry:ui",
  "dependencies": [
    "embla-carousel",
    "embla-carousel-solid",
    "lucide-solid"
  ],
  "registryDependencies": [
    "@gc-solid/button"
  ],
  "files": [
    {
      "path": "ui/carousel.tsx",
      "content": "import type { Accessor, ComponentProps, JSX, ValidComponent } from \"solid-js\"\nimport {\n  createContext,\n  createEffect,\n  createSignal,\n  mergeProps,\n  onCleanup,\n  splitProps,\n  useContext\n} from \"solid-js\"\n\nimport type { PolymorphicProps } from \"@kobalte/core/polymorphic\"\nimport type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from \"embla-carousel\"\nimport createEmblaCarousel from \"embla-carousel-solid\"\nimport { ChevronLeft, ChevronRight } from \"lucide-solid\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, type ButtonProps } from \"@/components/ui/button\"\n\ntype CarouselApi = EmblaCarouselType | undefined\ntype CarouselOptions = EmblaOptionsType\ntype CarouselPlugin = EmblaPluginType\n\ntype CarouselProps = {\n  opts?: CarouselOptions\n  plugins?: CarouselPlugin[]\n  orientation?: \"horizontal\" | \"vertical\"\n  setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n  carouselRef: ReturnType<typeof createEmblaCarousel>[0]\n  api: ReturnType<typeof createEmblaCarousel>[1]\n  scrollPrev: () => void\n  scrollNext: () => void\n  canScrollPrev: Accessor<boolean>\n  canScrollNext: Accessor<boolean>\n} & CarouselProps\n\nconst CarouselContext = createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n  const context = useContext(CarouselContext)\n\n  if (!context) {\n    throw new Error(\"useCarousel must be used within a <Carousel />\")\n  }\n\n  return context\n}\n\ntype CarouselRootProps<T extends ValidComponent = \"div\"> = ComponentProps<T> &\n  CarouselProps & {\n    class?: string | undefined\n    children?: JSX.Element\n  }\n\nconst Carousel = <T extends ValidComponent = \"div\">(\n  rawProps: PolymorphicProps<T, CarouselRootProps<T>>\n) => {\n  const props = mergeProps({ orientation: \"horizontal\" as const }, rawProps)\n  const [local, others] = splitProps(props as CarouselRootProps, [\n    \"class\",\n    \"children\",\n    \"opts\",\n    \"plugins\",\n    \"orientation\",\n    \"setApi\"\n  ])\n\n  const [carouselRef, api] = createEmblaCarousel(\n    () => ({\n      ...local.opts,\n      axis: local.orientation === \"horizontal\" ? \"x\" : \"y\"\n    }),\n    () => local.plugins ?? []\n  )\n\n  const [canScrollPrev, setCanScrollPrev] = createSignal(false)\n  const [canScrollNext, setCanScrollNext] = createSignal(false)\n\n  const onSelect = (emblaApi: EmblaCarouselType) => {\n    setCanScrollPrev(emblaApi.canScrollPrev())\n    setCanScrollNext(emblaApi.canScrollNext())\n  }\n\n  const scrollPrev = () => {\n    api()?.scrollPrev()\n  }\n\n  const scrollNext = () => {\n    api()?.scrollNext()\n  }\n\n  const handleKeyDown = (event: KeyboardEvent) => {\n    if (event.key === \"ArrowLeft\") {\n      event.preventDefault()\n      scrollPrev()\n    } else if (event.key === \"ArrowRight\") {\n      event.preventDefault()\n      scrollNext()\n    }\n  }\n\n  createEffect(() => {\n    const emblaApi = api()\n    if (!emblaApi || !local.setApi) return\n    local.setApi(emblaApi)\n  })\n\n  createEffect(() => {\n    const emblaApi = api()\n    if (!emblaApi) return\n\n    onSelect(emblaApi)\n    emblaApi.on(\"reInit\", onSelect)\n    emblaApi.on(\"select\", onSelect)\n\n    onCleanup(() => {\n      emblaApi.off(\"select\", onSelect)\n    })\n  })\n\n  return (\n    <CarouselContext.Provider\n      value={{\n        carouselRef,\n        api,\n        opts: local.opts,\n        orientation: local.orientation || (local.opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n        scrollPrev,\n        scrollNext,\n        canScrollPrev,\n        canScrollNext\n      }}\n    >\n      <div\n        aria-roledescription=\"carousel\"\n        class={cn(\"relative\", local.class)}\n        data-slot=\"carousel\"\n        onKeyDown={handleKeyDown}\n        role=\"region\"\n        {...others}\n      >\n        {local.children}\n      </div>\n    </CarouselContext.Provider>\n  )\n}\n\ntype CarouselContentProps<T extends ValidComponent = \"div\"> = ComponentProps<T> & {\n  class?: string | undefined\n}\n\nconst CarouselContent = <T extends ValidComponent = \"div\">(\n  props: PolymorphicProps<T, CarouselContentProps<T>>\n) => {\n  const [local, others] = splitProps(props as CarouselContentProps, [\"class\"])\n  const { carouselRef, orientation } = useCarousel()\n\n  return (\n    <div class=\"overflow-hidden\" data-slot=\"carousel-content\" ref={carouselRef}>\n      <div\n        class={cn(\"flex\", orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\", local.class)}\n        {...others}\n      />\n    </div>\n  )\n}\n\ntype CarouselItemProps<T extends ValidComponent = \"div\"> = ComponentProps<T> & {\n  class?: string | undefined\n}\n\nconst CarouselItem = <T extends ValidComponent = \"div\">(\n  props: PolymorphicProps<T, CarouselItemProps<T>>\n) => {\n  const [local, others] = splitProps(props as CarouselItemProps, [\"class\"])\n  const { orientation } = useCarousel()\n\n  return (\n    <div\n      aria-roledescription=\"slide\"\n      class={cn(\n        \"min-w-0 shrink-0 grow-0 basis-full\",\n        orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n        local.class\n      )}\n      data-slot=\"carousel-item\"\n      role=\"group\"\n      {...others}\n    />\n  )\n}\n\ntype CarouselPreviousProps<T extends ValidComponent = \"button\"> = ButtonProps<T> & {\n  class?: string | undefined\n}\n\nconst CarouselPrevious = <T extends ValidComponent = \"button\">(\n  rawProps: PolymorphicProps<T, CarouselPreviousProps<T>>\n) => {\n  const props = mergeProps({ variant: \"outline\" as const, size: \"icon-sm\" as const }, rawProps)\n  const [local, others] = splitProps(props as CarouselPreviousProps, [\"class\", \"variant\", \"size\"])\n  const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n  return (\n    <Button\n      class={cn(\n        \"cn-carousel-previous absolute touch-manipulation\",\n        orientation === \"horizontal\"\n          ? \"-left-12 -translate-y-1/2 top-1/2\"\n          : \"-top-12 -translate-x-1/2 left-1/2 rotate-90\",\n        local.class\n      )}\n      data-slot=\"carousel-previous\"\n      disabled={!canScrollPrev()}\n      onClick={scrollPrev}\n      size={local.size}\n      variant={local.variant}\n      {...others}\n    >\n      <ChevronLeft />\n      <span class=\"sr-only\">Previous slide</span>\n    </Button>\n  )\n}\n\ntype CarouselNextProps<T extends ValidComponent = \"button\"> = ButtonProps<T> & {\n  class?: string | undefined\n}\n\nconst CarouselNext = <T extends ValidComponent = \"button\">(\n  rawProps: PolymorphicProps<T, CarouselNextProps<T>>\n) => {\n  const props = mergeProps({ variant: \"outline\" as const, size: \"icon-sm\" as const }, rawProps)\n  const [local, others] = splitProps(props as CarouselNextProps, [\"class\", \"variant\", \"size\"])\n  const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n  return (\n    <Button\n      class={cn(\n        \"cn-carousel-next absolute touch-manipulation\",\n        orientation === \"horizontal\"\n          ? \"-right-12 -translate-y-1/2 top-1/2\"\n          : \"-bottom-12 -translate-x-1/2 left-1/2 rotate-90\",\n        local.class\n      )}\n      data-slot=\"carousel-next\"\n      disabled={!canScrollNext()}\n      onClick={scrollNext}\n      size={local.size}\n      variant={local.variant}\n      {...others}\n    >\n      <ChevronRight />\n      <span class=\"sr-only\">Next slide</span>\n    </Button>\n  )\n}\n\nexport {\n  type CarouselApi,\n  Carousel,\n  CarouselContent,\n  CarouselItem,\n  CarouselPrevious,\n  CarouselNext,\n  useCarousel\n}\n",
      "type": "registry:ui"
    }
  ]
}