{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "Calendar",
  "dependencies": [
    "cn",
    "lucide-react",
    "react-day-picker",
    "rescript-base-ui"
  ],
  "registryDependencies": [
    "@rescript-shadcn/Button",
    "@rescript-shadcn/Icons"
  ],
  "files": [
    {
      "path": "registry/base/ui/Calendar.res",
      "content": "@@directive(\"'use client'\")\n\n@@jsxConfig({version: 4, mode: \"automatic\", module_: \"BaseUi.BaseUiJsxDOM\"})\n\n@send external focusElement: Dom.element => unit = \"focus\"\n\nmodule Locale = {\n  type t = private {\n    code: string,\n  }\n}\n\nmodule Day = {\n  type t = {date: Date.t}\n}\n\nmodule DayModifiers = {\n  type t = {\n    focused?: bool,\n    selected?: bool,\n    outside?: bool,\n    @as(\"range_start\") rangeStart?: bool,\n    @as(\"range_end\") rangeEnd?: bool,\n    @as(\"range_middle\") rangeMiddle?: bool,\n  }\n}\n\nmodule Orientation = {\n  type t =\n    | @as(\"left\") Left\n    | @as(\"right\") Right\n    | @as(\"up\") Up\n    | @as(\"down\") Down\n}\n\nmodule ChevronProps = {\n  type t = {\n    ...Icons.props,\n    orientation?: Orientation.t,\n  }\n}\n\nmodule RootProps = {\n  type t = {...BaseUi.Types.DomProps.t, rootRef?: JsxDOM.domRef}\n\n  let toDomProps: t => BaseUi.Types.DomProps.t = %raw(`({rootRef, ...props}) => ({...props, ref: rootRef})`)\n}\n\nmodule WeekNumberProps = {\n  type t = {\n    className?: string,\n    children?: React.element,\n    @as(\"aria-label\") ariaLabel?: string,\n    role?: string,\n    scope?: string,\n    week?: int,\n  }\n}\n\nmodule Modifiers = {\n  type t = {\n    selected?: bool,\n    disabled?: bool,\n    today?: bool,\n  }\n}\n\nmodule DayButtonProps = {\n  type t = {\n    @as(\"data-slot\") dataSlot?: string,\n    className?: string,\n    children: React.element,\n    day: Day.t,\n    modifiers: DayModifiers.t,\n    locale?: Locale.t,\n    id?: string,\n    style?: ReactDOM.Style.t,\n    disabled?: bool,\n    tabIndex?: int,\n    onClick?: JsxEvent.Mouse.t => unit,\n    onKeyDown?: JsxEvent.Keyboard.t => unit,\n    onBlur?: ReactEvent.Focus.t => unit,\n    onFocus?: ReactEvent.Focus.t => unit,\n    onMouseEnter?: ReactEvent.Mouse.t => unit,\n    onMouseLeave?: ReactEvent.Mouse.t => unit,\n    @as(\"aria-label\") ariaLabel?: string,\n  }\n}\n\nmodule DayPickerClassNames = {\n  type t = {\n    root?: string,\n    months?: string,\n    month?: string,\n    nav?: string,\n    @as(\"button_previous\") buttonPrevious?: string,\n    @as(\"button_next\") buttonNext?: string,\n    @as(\"month_caption\") monthCaption?: string,\n    dropdowns?: string,\n    @as(\"dropdown_root\") dropdownRoot?: string,\n    dropdown?: string,\n    @as(\"caption_label\") captionLabel?: string,\n    @as(\"month_grid\") monthGrid?: string,\n    weekdays?: string,\n    weekday?: string,\n    week?: string,\n    @as(\"week_number_header\") weekNumberHeader?: string,\n    @as(\"week_number\") weekNumber?: string,\n    day?: string,\n    @as(\"range_start\") rangeStart?: string,\n    @as(\"range_middle\") rangeMiddle?: string,\n    @as(\"range_end\") rangeEnd?: string,\n    today?: string,\n    outside?: string,\n    disabled?: string,\n    hidden?: string,\n  }\n}\n\n@module(\"react-day-picker\")\nexternal getDefaultClassNames: unit => DayPickerClassNames.t = \"getDefaultClassNames\"\n\n@module(\"cn\")\nexternal cn: (string, option<string>) => string = \"cn\"\n\n@module(\"cn\")\nexternal cn4: (\n  string,\n  string,\n  ~additional: option<string>=?,\n  ~additional2: option<string>=?,\n) => string = \"cn\"\n\nmodule DayButton = {\n  let toButtonProps: DayButtonProps.t => Button.props = %raw(`({day, modifiers, locale, ...rest}) => rest`)\n\n  @react.componentWithProps(DayButtonProps.t)\n  let make = (props: DayButtonProps.t) => {\n    let dataSlot = props.dataSlot->Option.getOr(\"button\")\n    let className = props.className\n    let day = props.day\n    let modifiers = props.modifiers\n    let locale = props.locale\n    let children = props.children\n    let props = props->toButtonProps\n\n    let defaultClassNames = getDefaultClassNames()\n\n    let buttonRef = React.useRef(null)\n    React.useEffect(() => {\n      if modifiers.focused->Option.getOr(false) {\n        buttonRef.current->Nullable.forEach(focusElement)\n      }\n      None\n    }, [modifiers.focused])\n\n    <Button\n      {...props}\n      variant=Ghost\n      size=Icon\n      ref={buttonRef->ReactDOM.Ref.domRef}\n      dataSlot\n      suppressHydrationWarning=true\n      dataDay={switch locale {\n      | Some({code}) => Date.toLocaleDateStringWithLocale(day.Day.date, code)\n      | None => Date.toLocaleDateString(day.Day.date)\n      }}\n      dataSelectedSingle={modifiers.selected->Option.getOr(false) &&\n      !(modifiers.rangeStart->Option.getOr(false)) &&\n      !(modifiers.rangeEnd->Option.getOr(false)) &&\n      !(modifiers.rangeMiddle->Option.getOr(false))}\n      dataRangeStart=?{modifiers.rangeStart}\n      dataRangeEnd=?{modifiers.rangeEnd}\n      dataRangeMiddle=?{modifiers.rangeMiddle}\n      className={cn4(\n        \" relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70\",\n        defaultClassNames.day->Option.getOr(\"\"),\n        ~additional=className,\n      )}\n    >\n      {children}\n    </Button>\n  }\n}\n\nmodule ComponentProps = {\n  type t = {\n    modifiers?: Modifiers.t,\n    ...JsxDOM.domProps,\n  }\n}\n\ntype componentRenderer = ComponentProps.t => React.element\n\nmodule DayPickerFormatters = {\n  module DateLibOptions = {\n    type t = {\n      locale?: Locale.t,\n      timeZone?: string,\n      numerals?: string,\n    }\n  }\n  type t = {\n    formatMonthDropdown?: Date.t => string,\n    formatCaption?: (Date.t, ~options: DateLibOptions.t=?) => string,\n    formatDay?: (Date.t, ~options: DateLibOptions.t) => string,\n    formatWeekdayName?: (Date.t, ~options: DateLibOptions.t=?) => string,\n    formatWeekNumber?: int => string,\n    formatYearDropdown?: int => string,\n    formatMonthCaption?: (Date.t, ~options: DateLibOptions.t=?) => string,\n  }\n}\n\nmodule DayPickerComponents = {\n  type t = {\n    @as(\"Root\") root?: RootProps.t => React.element,\n    @as(\"Chevron\") chevron?: ChevronProps.t => React.element,\n    @as(\"DayButton\") dayButton?: DayButtonProps.t => React.element,\n    @as(\"WeekNumber\") weekNumber?: WeekNumberProps.t => React.element,\n    @as(\"Months\") months?: componentRenderer,\n    @as(\"Month\") month?: componentRenderer,\n    @as(\"MonthCaption\") monthCaption?: componentRenderer,\n    @as(\"DropdownNav\") dropdownNav?: componentRenderer,\n    @as(\"Dropdown\") dropdown?: componentRenderer,\n    @as(\"CaptionLabel\") captionLabel?: componentRenderer,\n    @as(\"Nav\") nav?: componentRenderer,\n    @as(\"Weekdays\") weekdays?: componentRenderer,\n    @as(\"Weekday\") weekday?: componentRenderer,\n    @as(\"Week\") week?: componentRenderer,\n    @as(\"Day\") day?: componentRenderer,\n    @as(\"Footer\") footer?: componentRenderer,\n    @as(\"PreviousMonthButton\") previousMonthButton?: componentRenderer,\n    @as(\"NextMonthButton\") nextMonthButton?: componentRenderer,\n    @as(\"MonthGrid\") monthGrid?: componentRenderer,\n    @as(\"Select\") select?: componentRenderer,\n    @as(\"Option\") option?: componentRenderer,\n    @as(\"MonthsDropdown\") monthsDropdown?: componentRenderer,\n    @as(\"YearsDropdown\") yearsDropdown?: componentRenderer,\n    @as(\"Weeks\") weeks?: componentRenderer,\n    @as(\"WeekNumberHeader\") weekNumberHeader?: componentRenderer,\n    @as(\"Button\") button?: componentRenderer,\n  }\n}\n\nmodule CaptionLayout = {\n  type t =\n    | @as(\"label\") Label\n    | @as(\"dropdown\") Dropdown\n    | @as(\"dropdown-months\") DropdownMonths\n    | @as(\"dropdown-years\") DropdownYears\n}\n\nmodule Labels = {\n  type t = {\n    labelNav: unit => string,\n    labelGrid: Date.t => string,\n    labelGridcell: (Date.t, ~modifiers: Modifiers.t=?) => string,\n    labelMonthDropdown: unit => string,\n    labelYearDropdown: unit => string,\n    labelNext: (~nextMonth: Date.t=?) => string,\n    labelPrevious: (~previousMonth: Date.t=?) => string,\n    labelDayButton: (Date.t, ~modifiers: Modifiers.t=?) => string,\n    labelWeekday: Date.t => string,\n    labelWeekNumber: int => string,\n    labelWeekNumberHeader: unit => string,\n  }\n}\n\nmodule Direction = {\n  @unboxed\n  type t =\n    | @as(\"ltr\") Ltr\n    | @as(\"rtl\") Rtl\n}\n\nmodule DateRange = {\n  type t = {\n    from: Date.t,\n    to?: Date.t,\n  }\n}\n\nmodule DayPicker = {\n  module SelectionMode = {\n    type rec t<_> =\n      | @as(\"single\") Single: t<Date.t>\n      | @as(\"multiple\") Multiple: t<array<Date.t>>\n      | @as(\"range\") Range: t<DateRange.t>\n      | @as(\"none\") NoSelection: t<unit>\n  }\n\n  module Matcher = {\n    @unboxed\n    type t =\n      | Fn(Date.t => bool)\n      | Dates(array<Date.t>)\n  }\n\n  module Props = {\n    type t<'selected> = {\n      showOutsideDays?: bool,\n      className?: string,\n      captionLayout?: CaptionLayout.t,\n      dir?: Direction.t,\n      locale?: Locale.t,\n      formatters?: DayPickerFormatters.t,\n      classNames?: DayPickerClassNames.t,\n      required?: bool,\n      mode?: SelectionMode.t<'selected>,\n      selected?: 'selected,\n      onSelect?: option<'selected> => unit,\n      defaultMonth?: Date.t,\n      month?: Date.t,\n      onMonthChange?: Date.t => unit,\n      startMonth?: Date.t,\n      endMonth?: Date.t,\n      numberOfMonths?: int,\n      reverseMonths?: bool,\n      pagedNavigation?: bool,\n      navLayout?: string,\n      hideNavigation?: bool,\n      disableNavigation?: bool,\n      showWeekNumber?: bool,\n      fixedWeeks?: bool,\n      weekStartsOn?: int,\n      @as(\"ISOWeek\") isoWeek?: bool,\n      fromDate?: Date.t,\n      toDate?: Date.t,\n      fromMonth?: Date.t,\n      toMonth?: Date.t,\n      fromYear?: int,\n      toYear?: int,\n      broadcastCalendar?: bool,\n      timeZone?: string,\n      animate?: bool,\n      autoFocus?: bool,\n      onDayClick?: (Date.t, Modifiers.t, JsxEvent.Mouse.t) => unit,\n      onNextClick?: Date.t => unit,\n      onPrevClick?: Date.t => unit,\n      styles?: dict<ReactDOM.Style.t>,\n      labels?: Labels.t,\n      hidden?: Matcher.t,\n      footer?: React.element,\n      disabled?: Matcher.t,\n      modifiers?: dict<Matcher.t>,\n      modifiersClassNames?: dict<string>,\n      components?: DayPickerComponents.t,\n    }\n  }\n\n  @module(\"react-day-picker\")\n  external make: Props.t<'selected> => React.element = \"DayPicker\"\n}\n\nmodule Props = {\n  type t<'selected> = {\n    ...DayPicker.Props.t<'selected>,\n    buttonVariant?: Button.Variant.t,\n  }\n}\n\nlet toDayPickerProps: Props.t<'selected> => DayPicker.Props.t<\n  'selected,\n> = %raw(`function({buttonVariant, ...rest}){ return rest; }`)\n\n@scope(\"Object\") external merge: (~defaults: 'a, 'a) => 'a = \"assign\"\n\n@react.componentWithProps(Props.t)\nlet make = props => {\n  let showOutsideDays = props.Props.showOutsideDays->Option.getOr(true)\n  let captionLayout = props.captionLayout->Option.getOr(CaptionLayout.Label)\n  let buttonVariant = props.buttonVariant->Option.getOr(Button.Variant.Ghost)\n  let formatters = props.formatters->Option.getOr({})\n  let classNames = props.classNames->Option.getOr({})\n  let components = props.components->Option.getOr({})\n  let showWeekNumber = props.showWeekNumber->Option.getOr(false)\n  let defaultClassNames = getDefaultClassNames()\n  let props = props->toDayPickerProps\n\n  <DayPicker\n    {...props}\n    showOutsideDays\n    className={cn(\n      \"p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] bg-background group/calendar in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent rtl:**:[.rdp-button\\\\_next>svg]:rotate-180 rtl:**:[.rdp-button\\\\_previous>svg]:rotate-180\",\n      props.className,\n    )}\n    captionLayout\n    formatters={merge(\n      ~defaults={\n        DayPickerFormatters.formatMonthDropdown: date =>\n          date->Date.toLocaleDateStringWithLocaleAndOptions(\n            switch props.locale {\n            | Some({code}) => code\n            | None => \"default\"\n            },\n            {month: #short},\n          ),\n      },\n      formatters,\n    )}\n    classNames={merge(\n      ~defaults={\n        DayPickerClassNames.root: cn(\"w-fit\", defaultClassNames.root),\n        months: cn(\"flex gap-4 flex-col md:flex-row relative\", defaultClassNames.months),\n        month: cn(\"flex flex-col w-full gap-4\", defaultClassNames.month),\n        nav: cn(\n          \"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between\",\n          defaultClassNames.nav,\n        ),\n        buttonPrevious: cn4(\n          Button.buttonVariants(~variant=buttonVariant),\n          \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n          ~additional=defaultClassNames.buttonPrevious,\n        ),\n        buttonNext: cn4(\n          Button.buttonVariants(~variant=buttonVariant),\n          \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n          ~additional=defaultClassNames.buttonNext,\n        ),\n        monthCaption: cn(\n          \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n          defaultClassNames.monthCaption,\n        ),\n        dropdowns: cn(\n          \"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5\",\n          defaultClassNames.dropdowns,\n        ),\n        dropdownRoot: cn(\n          \"relative has-focus:border-ring border-input has-focus:ring-ring/50 border has-focus:ring-3 rounded-(--cell-radius)\",\n          defaultClassNames.dropdownRoot,\n        ),\n        dropdown: cn(\"absolute bg-popover inset-0 opacity-0\", defaultClassNames.dropdown),\n        captionLabel: cn4(\n          \"select-none font-medium\",\n          switch captionLayout {\n          | CaptionLayout.Label => \" text-sm\"\n          | Dropdown => \"h-6 pr-1 pl-1.5 rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5\"\n          | DropdownMonths => \"h-6 pr-1 pl-1.5 rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5\"\n          | DropdownYears => \"h-6 pr-1 pl-1.5 rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5\"\n          },\n          ~additional=defaultClassNames.captionLabel,\n        ),\n        monthGrid: cn(\"w-full border-collapse\", defaultClassNames.monthGrid),\n        weekdays: cn(\"flex\", defaultClassNames.weekdays),\n        weekday: cn(\n          \"text-muted-foreground rounded-(--cell-radius) flex-1 font-normal text-[0.8rem] select-none\",\n          defaultClassNames.weekday,\n        ),\n        week: cn(\"flex w-full mt-2\", defaultClassNames.week),\n        weekNumberHeader: cn(\"select-none w-(--cell-size)\", defaultClassNames.weekNumberHeader),\n        weekNumber: cn(\n          \"text-[0.8rem] select-none text-muted-foreground\",\n          defaultClassNames.weekNumber,\n        ),\n        day: cn4(\n          \"relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none\",\n          showWeekNumber\n            ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)\"\n            : \"[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)\",\n          ~additional=defaultClassNames.day,\n        ),\n        rangeStart: cn(\n          \"rounded-l-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:right-0 z-0 isolate\",\n          defaultClassNames.rangeStart,\n        ),\n        rangeMiddle: cn(\"rounded-none\", defaultClassNames.rangeMiddle),\n        rangeEnd: cn(\n          \"rounded-r-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:left-0 z-0 isolate\",\n          defaultClassNames.rangeEnd,\n        ),\n        today: cn(\n          \"bg-muted text-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none\",\n          defaultClassNames.today,\n        ),\n        outside: cn(\n          \"text-muted-foreground aria-selected:text-muted-foreground\",\n          defaultClassNames.outside,\n        ),\n        disabled: cn(\"text-muted-foreground opacity-50\", defaultClassNames.disabled),\n        hidden: cn(\"invisible\", defaultClassNames.hidden),\n      },\n      classNames,\n    )}\n    components={merge(\n      ~defaults={\n        DayPickerComponents.root: (props: RootProps.t) => {\n          let dataSlot = props.dataSlot->Option.getOr(\"calendar\")\n          <div {...RootProps.toDomProps(props)} dataSlot />\n        },\n        chevron: (props: ChevronProps.t) => {\n          let className = props.className\n          let orientation = props.orientation\n          let props = ({...props, orientation: ?None} :> Icons.props)\n          switch orientation {\n          | Some(Left) => <Icons.ChevronLeft {...props} className={cn(\" size-4\", className)} />\n          | Some(Right) => <Icons.ChevronRight {...props} className={cn(\" size-4\", className)} />\n          | Some(Up | Down) | None =>\n            <Icons.ChevronDown {...props} className={cn(\"size-4\", className)} />\n          }\n        },\n        dayButton: (props: DayButtonProps.t) => <DayButton {...props} locale=?{props.locale} />,\n        weekNumber: ({?children, ?className, ?ariaLabel, ?role, ?scope}) =>\n          <td ?className ?ariaLabel ?role ?scope>\n            <div\n              className=\"flex size-(--cell-size) items-center justify-center text-center\" ?children\n            />\n          </td>,\n        week: ({?children, ?className, ?role}) =>\n          <tr ?className ?role> {children->Option.getOr(React.null)} </tr>,\n      },\n      components,\n    )}\n  />\n}\n",
      "type": "registry:file",
      "target": "@ui/Calendar.res"
    }
  ],
  "type": "registry:ui"
}