{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "Toast",
  "dependencies": [
    "@base-ui/react",
    "cn",
    "lucide-react",
    "rescript-base-ui"
  ],
  "registryDependencies": [
    "@rescript-shadcn/Button",
    "@rescript-shadcn/Icons"
  ],
  "files": [
    {
      "path": "registry/base/ui/Toast.res",
      "content": "@@jsxConfig({version: 4, mode: \"automatic\", module_: \"BaseUi.BaseUiJsxDOM\"})\n\n@@directive(\"'use client'\")\n\n@module(\"cn\")\nexternal cn: (string, option<string>) => string = \"cn\"\n\nlet createToastManager = BaseUi.Toast.createToastManager\nlet useToastManager = BaseUi.Toast.useToastManager\nlet toast = createToastManager()\n\nmodule Provider = {\n  let make = BaseUi.Toast.Provider.make\n}\n\nmodule Portal = {\n  @react.componentWithProps(BaseUi.Types.BaseUIComponentProps.t)\n  let make = (props: BaseUi.Types.BaseUIComponentProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-portal\")\n    <BaseUi.Toast.Portal {...props} dataSlot />\n  }\n}\n\nmodule Viewport = {\n  @react.componentWithProps(BaseUi.Types.BaseUIComponentProps.t)\n  let make = (props: BaseUi.Types.BaseUIComponentProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-viewport\")\n    <BaseUi.Toast.Viewport\n      {...props}\n      dataSlot\n      className={cn(\n        \"pointer-events-none fixed inset-x-4 bottom-4 z-50 mx-auto w-auto max-w-sm outline-none sm:right-4 sm:left-auto sm:mx-0 sm:w-full\",\n        props.className,\n      )}\n    />\n  }\n}\n\nmodule Root = {\n  type props = BaseUi.Toast.Root.props\n\n  @react.componentWithProps(props)\n  let make = (props: props) => {\n    let children = props.children\n    <BaseUi.Toast.Root\n      {...props}\n      dataSlot={props.dataSlot->Option.getOr(\"toast\")}\n      className={cn(\n        \"rounded-2xl group/toast pointer-events-auto absolute right-0 bottom-0 z-[calc(1000-var(--toast-index))] w-full origin-bottom border bg-popover text-popover-foreground shadow-lg will-change-transform outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))] h-(--height) [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] [transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms] after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-[''] data-expanded:h-(--toast-height) data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))] data-limited:opacity-0 data-starting-style:[transform:translateY(150%)] [&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)] data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))] data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))] data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))] data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))] data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))] data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]\",\n        props.className,\n      )}\n    >\n      {children->Option.getOr(React.null)}\n    </BaseUi.Toast.Root>\n  }\n}\n\nmodule Content = {\n  @react.componentWithProps(BaseUi.Types.BaseUIComponentProps.t)\n  let make = (props: BaseUi.Types.BaseUIComponentProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-content\")\n    <BaseUi.Toast.Content\n      {...props}\n      dataSlot\n      className={cn(\n        \"flex h-full items-center gap-3 overflow-hidden p-4 transition-opacity duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] data-behind:opacity-0 data-expanded:opacity-100\",\n        props.className,\n      )}\n    />\n  }\n}\n\nmodule Title = {\n  @react.componentWithProps(BaseUi.Types.BaseUIComponentProps.t)\n  let make = (props: BaseUi.Types.BaseUIComponentProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-title\")\n    <BaseUi.Toast.Title\n      {...props} dataSlot className={cn(\"text-sm font-medium\", props.className)}\n    />\n  }\n}\n\nmodule Description = {\n  @react.componentWithProps(BaseUi.Types.BaseUIComponentProps.t)\n  let make = (props: BaseUi.Types.BaseUIComponentProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-description\")\n    <BaseUi.Toast.Description\n      {...props} dataSlot className={cn(\"text-muted-foreground text-sm\", props.className)}\n    />\n  }\n}\n\nmodule Action = {\n  @react.componentWithProps(BaseUi.Toast.Action.props)\n  let make = (props: BaseUi.Toast.Action.props) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-action\")\n    <BaseUi.Toast.Action\n      {...props}\n      render={props.render->Option.getOr(<Button variant=Outline size=Sm />)}\n      dataSlot\n      className={cn(\"shrink-0\", props.className)}\n    />\n  }\n}\n\nmodule Close = {\n  @react.componentWithProps(BaseUi.Toast.Close.props)\n  let make = (props: BaseUi.Toast.Close.props) => {\n    let ariaLabel = props.ariaLabel->Option.getOr(\"Close toast\")\n    let dataSlot = props.dataSlot->Option.getOr(\"toast-close\")\n    <BaseUi.Toast.Close\n      {...props}\n      render={props.render->Option.getOr(<Button variant=Ghost size=IconSm />)}\n      dataSlot\n      ariaLabel\n      className={cn(\n        \"text-muted-foreground hover:text-foreground relative shrink-0 after:absolute after:-inset-2 after:content-['']\",\n        props.className,\n      )}\n    >\n      {props.children->Option.getOr(<Icons.X ariaHidden=true />)}\n    </BaseUi.Toast.Close>\n  }\n}\n\nmodule Icon = {\n  @react.component\n  let make = (~type_: option<string>=?) => {\n    let icon = switch type_ {\n    | Some(\"success\") => <Icons.CircleCheck ariaHidden=true />\n    | Some(\"info\") => <Icons.Info ariaHidden=true />\n    | Some(\"warning\") => <Icons.TriangleAlert ariaHidden=true />\n    | Some(\"error\") => <Icons.OctagonX className=\"text-destructive\" ariaHidden=true />\n    | Some(\"loading\") => <Icons.Loader2 className=\"animate-spin\" ariaHidden=true />\n    | _ => React.null\n    }\n    if icon == React.null {\n      React.null\n    } else {\n      <span\n        dataSlot=\"toast-icon\"\n        className=\"shrink-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\"\n      >\n        {icon}\n      </span>\n    }\n  }\n}\n\nmodule List = {\n  @react.component\n  let make = () => {\n    let {toasts} = useToastManager()\n    toasts\n    ->Array.map(item =>\n      <Root key=item.id toast=item>\n        <Content>\n          <Icon type_=?item.type_ />\n          <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n            <Title />\n            <Description />\n          </div>\n          <Action />\n          <Close />\n        </Content>\n      </Root>\n    )\n    ->React.array\n  }\n}\n\nmodule Toaster = {\n  @react.componentWithProps(BaseUi.Toast.Provider.props)\n  let make = (props: BaseUi.Toast.Provider.props) => {\n    let children = props.children\n    let toastManager = props.toastManager->Option.getOr(toast)\n    <Provider {...props} toastManager>\n      {children->Option.getOr(React.null)}\n      <Portal>\n        <Viewport>\n          <List />\n        </Viewport>\n      </Portal>\n    </Provider>\n  }\n}\n\nlet make = Root.make\n",
      "type": "registry:file",
      "target": "@ui/Toast.res"
    }
  ],
  "type": "registry:ui"
}