{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "Carousel",
  "dependencies": [
    "cn",
    "embla-carousel-react",
    "lucide-react",
    "rescript-base-ui"
  ],
  "registryDependencies": [
    "@rescript-shadcn/Button",
    "@rescript-shadcn/Icons"
  ],
  "files": [
    {
      "path": "registry/base/ui/Carousel.res",
      "content": "@@jsxConfig({version: 4, mode: \"automatic\", module_: \"BaseUi.BaseUiJsxDOM\"})\n\n@@directive(\"'use client'\")\n\nopen BaseUi.Types\n\n@module(\"cn\")\nexternal cn: (string, option<string>) => string = \"cn\"\n\nmodule Api = {\n  type t\n  @send external scrollPrev: t => unit = \"scrollPrev\"\n  @send external scrollNext: t => unit = \"scrollNext\"\n  @send external canScrollPrev: t => bool = \"canScrollPrev\"\n  @send external canScrollNext: t => bool = \"canScrollNext\"\n  @send external scrollSnapList: t => array<float> = \"scrollSnapList\"\n  @send external selectedScrollSnap: t => int = \"selectedScrollSnap\"\n  @send external on: (t, string, t => unit) => unit = \"on\"\n  @send external off: (t, string, t => unit) => unit = \"off\"\n}\n\ntype carouselRef = ReactDOM.domRef\n\nmodule EmblaOptions = {\n  module AxisOptionType = {\n    @unboxed\n    type t =\n      | @as(\"x\") X\n      | @as(\"y\") Y\n  }\n  type t = {\n    active?: bool,\n    axis?: AxisOptionType.t,\n    container?: Dom.element,\n    slides?: array<Dom.element>,\n    containScroll?: string,\n    direction?: string,\n    slidesToScroll?: int,\n    align?: string,\n    dragFree?: bool,\n    dragThreshold?: float,\n    inViewThreshold?: float,\n    loop?: bool,\n    skipSnaps?: bool,\n    duration?: float,\n    startIndex?: int,\n    watchDrag?: bool,\n    watchResize?: bool,\n    watchSlides?: bool,\n    watchFocus?: bool,\n  }\n}\n\ntype emblaPlugin\n\n@module(\"embla-carousel-react\")\nexternal useEmblaCarousel: (\n  ~options: EmblaOptions.t=?,\n  ~plugins: array<emblaPlugin>=?,\n) => (carouselRef, option<Api.t>) = \"default\"\n\ntype carouselContext = {\n  carouselRef: carouselRef,\n  api: option<Api.t>,\n  opts: EmblaOptions.t,\n  orientation: DataOrientation.t,\n  scrollPrev: unit => unit,\n  scrollNext: unit => unit,\n  canScrollPrev: bool,\n  canScrollNext: bool,\n}\n\nlet context: React.Context.t<option<carouselContext>> = React.createContext(None)\n\n@throws(JsExn)\nlet useCarousel = () =>\n  switch React.useContext(context) {\n  | Some(context) => context\n  | None => JsError.throwWithMessage(\"useCarousel must be used within a <Carousel />\")\n  }\n\ntype props = {\n  ...BaseUi.Types.BaseDomWithoutOrientationProps.t,\n  ...BaseUi.Types.ExtraDomProps.t,\n  children?: React.element,\n  orientation?: DataOrientation.t,\n  opts?: EmblaOptions.t,\n  plugins?: array<emblaPlugin>,\n  setApi?: Api.t => unit,\n}\n\nlet toBaseUiProps: props => BaseUi.Types.DomProps.t = %raw(`({orientation, opts, plugins, setApi, ...props}) => props`)\n\n@react.componentWithProps(props)\nlet make = (props: props) => {\n  let orientation = props.orientation->Option.getOr(DataOrientation.Horizontal)\n  let opts = props.opts->Option.getOr({})\n  let plugins = props.plugins\n  let setApi = props.setApi\n  let (carouselRef, api) = useEmblaCarousel(\n    ~options={\n      ...opts,\n      axis: switch orientation {\n      | Horizontal => X\n      | Vertical | Responsive => Y\n      },\n    },\n    ~plugins?,\n  )\n  let (canScrollPrev, setCanScrollPrev) = React.useState(() => false)\n  let (canScrollNext, setCanScrollNext) = React.useState(() => false)\n  let onSelect = (api: Api.t) => {\n    setCanScrollPrev(_ => api->Api.canScrollPrev)\n    setCanScrollNext(_ => api->Api.canScrollNext)\n  }\n  let scrollPrev = () =>\n    switch api {\n    | Some(api) => api->Api.scrollPrev\n    | None => ()\n    }\n  let scrollNext = () =>\n    switch api {\n    | Some(api) => api->Api.scrollNext\n    | None => ()\n    }\n  React.useEffect(() => {\n    switch (api, setApi) {\n    | (Some(api), Some(setApi)) =>\n      setApi(api)\n      None\n    | _ => None\n    }\n  }, [api])\n  React.useEffect(() => {\n    switch (api, setApi) {\n    | (Some(api), Some(setApi)) =>\n      setApi(api)\n      None\n    | _ => None\n    }\n  }, [setApi])\n  React.useEffect(() => {\n    api->Option.map(api => {\n      onSelect(api)\n      api->Api.on(\"reInit\", onSelect)\n      api->Api.on(\"select\", onSelect)\n      () => api->Api.off(\"select\", onSelect)\n    })\n  }, [api])\n  let handleKeyDownCapture = React.useCallback(event => {\n    switch event->ReactEvent.Keyboard.key {\n    | \"ArrowLeft\" =>\n      event->ReactEvent.Keyboard.preventDefault\n      scrollPrev()\n    | \"ArrowRight\" =>\n      event->ReactEvent.Keyboard.preventDefault\n      scrollNext()\n    | _ => ()\n    }\n  }, [scrollPrev, scrollNext])\n  let providerValue = Some({\n    carouselRef,\n    api,\n    opts,\n    orientation,\n    scrollPrev,\n    scrollNext,\n    canScrollPrev,\n    canScrollNext,\n  })\n  module Provider = {\n    let make = React.Context.provider(context)\n  }\n  <Provider value={providerValue}>\n    <div\n      {...props->toBaseUiProps}\n      onKeyDownCapture={props.onKeyDownCapture->Option.getOr(handleKeyDownCapture)}\n      dataSlot={props.dataSlot->Option.getOr(\"carousel\")}\n      className={cn(\"relative\", props.className)}\n      role={props.role->Option.getOr(\"region\")}\n      ariaRoledescription={props.ariaRoledescription->Option.getOr(\"carousel\")}\n    />\n  </Provider>\n}\n\nmodule Content = {\n  @react.componentWithProps(BaseUi.Types.DomProps.t)\n  let make = (props: BaseUi.Types.DomProps.t) => {\n    let {carouselRef, orientation} = useCarousel()\n    <div dataSlot=\"carousel-content\" ref={carouselRef} className=\"overflow-hidden\">\n      <div\n        {...props}\n        className={cn(\n          `flex ${orientation == DataOrientation.Horizontal ? \"-ml-4\" : \"-mt-4 flex-col\"}`,\n          props.className,\n        )}\n      />\n    </div>\n  }\n}\n\nmodule Item = {\n  @react.componentWithProps(BaseUi.Types.DomProps.t)\n  let make = (props: BaseUi.Types.DomProps.t) => {\n    let {orientation} = useCarousel()\n    <div\n      {...props}\n      role={props.role->Option.getOr(\"group\")}\n      ariaRoledescription={props.ariaRoledescription->Option.getOr(\"slide\")}\n      dataSlot={props.dataSlot->Option.getOr(\"carousel-item\")}\n      className={cn(\n        `min-w-0 shrink-0 grow-0 basis-full ${orientation == DataOrientation.Horizontal\n            ? \"pl-4\"\n            : \"pt-4\"}`,\n        props.className,\n      )}\n    />\n  }\n}\n\nmodule Previous = {\n  @react.componentWithProps(Button.props)\n  let make = (props: Button.props) => {\n    let {orientation, scrollPrev, canScrollPrev} = useCarousel()\n    <Button\n      {...props}\n      className={cn(\n        `rounded-full absolute touch-manipulation ${orientation == DataOrientation.Horizontal\n            ? \"inset-y-0 -left-12 my-auto\"\n            : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\"}`,\n        props.className,\n      )}\n      variant={props.variant->Option.getOr(Outline)}\n      size={props.size->Option.getOr(IconSm)}\n      dataSlot={props.dataSlot->Option.getOr(\"carousel-previous\")}\n      disabled={props.disabled->Option.getOr(!canScrollPrev)}\n      onClick={props.onClick->Option.getOr(_ => scrollPrev())}\n    >\n      <Icons.ChevronLeft className=\"\" />\n      <span className=\"sr-only\"> {\"Previous slide\"->React.string} </span>\n    </Button>\n  }\n}\n\nmodule Next = {\n  @react.componentWithProps(Button.props)\n  let make = (props: Button.props) => {\n    let {orientation, scrollNext, canScrollNext} = useCarousel()\n    <Button\n      {...props}\n      className={cn(\n        `rounded-full absolute touch-manipulation ${orientation == DataOrientation.Horizontal\n            ? \"inset-y-0 -right-12 my-auto\"\n            : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\"}`,\n        props.className,\n      )}\n      variant={props.variant->Option.getOr(Outline)}\n      size={props.size->Option.getOr(IconSm)}\n      dataSlot={props.dataSlot->Option.getOr(\"carousel-next\")}\n      disabled={props.disabled->Option.getOr(!canScrollNext)}\n      onClick={props.onClick->Option.getOr(_ => scrollNext())}\n    >\n      <Icons.ChevronRight className=\"\" />\n      <span className=\"sr-only\"> {\"Next slide\"->React.string} </span>\n    </Button>\n  }\n}\n",
      "type": "registry:file",
      "target": "@ui/Carousel.res"
    }
  ],
  "type": "registry:ui"
}