{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar-rac",
  "title": "Calendar (React Aria)",
  "description": "Accessible calendar and range calendar on React Aria.",
  "dependencies": [
    "react-aria-components",
    "@internationalized/date"
  ],
  "registryDependencies": [
    "https://ui.ndekocode.dev/r/theme.json",
    "https://ui.ndekocode.dev/r/utils.json",
    "https://ui.ndekocode.dev/r/icons.json"
  ],
  "files": [
    {
      "path": "registry/ndeko/ui/calendar-rac.tsx",
      "content": "'use client';\n\nimport { getLocalTimeZone, today } from '@internationalized/date';\nimport {\n  Button as ButtonRac,\n  CalendarCell as CalendarCellRac,\n  CalendarGridBody as CalendarGridBodyRac,\n  CalendarGridHeader as CalendarGridHeaderRac,\n  CalendarGrid as CalendarGridRac,\n  CalendarHeaderCell as CalendarHeaderCellRac,\n  Calendar as CalendarRac,\n  composeRenderProps,\n  Heading as HeadingRac,\n  RangeCalendar as RangeCalendarRac,\n  type CalendarProps as CalendarRacProps,\n  type DateValue,\n  type RangeCalendarProps as RangeCalendarRacProps,\n} from 'react-aria-components';\n\nimport { ChevronLeftIcon, ChevronRightIcon } from '@/registry/ndeko/lib/icons';\nimport { cn } from '@/registry/ndeko/lib/utils';\n\nconst NAV_BUTTON =\n  'flex size-8 items-center justify-center rounded-full text-muted-foreground outline-none transition-[color,background-color,box-shadow,scale] duration-150 ease-(--ease-out-strong) data-hovered:bg-foreground/5 data-hovered:text-foreground data-pressed:scale-[0.97] data-focus-visible:ring-[3px] data-focus-visible:ring-ring/25';\n\nfunction CalendarHeader() {\n  return (\n    <header className='flex w-full items-center gap-1 pb-1'>\n      <ButtonRac slot='previous' className={NAV_BUTTON}>\n        <ChevronLeftIcon className='size-4' />\n      </ButtonRac>\n      <HeadingRac className='grow text-center text-[13px] font-medium' />\n      <ButtonRac slot='next' className={NAV_BUTTON}>\n        <ChevronRightIcon className='size-4' />\n      </ButtonRac>\n    </header>\n  );\n}\n\nconst CELL = [\n  'relative flex size-9 items-center justify-center whitespace-nowrap rounded-md p-0 text-[13px] font-normal tabular-nums text-foreground outline-none',\n  'transition-[color,background-color,border-radius,box-shadow,scale] duration-150 ease-(--ease-out-strong) data-pressed:scale-90',\n  'data-hovered:bg-foreground/5 data-selected:bg-primary data-selected:text-primary-foreground',\n  'data-focus-visible:z-10 data-focus-visible:ring-[3px] data-focus-visible:ring-ring/25',\n  'data-disabled:pointer-events-none data-disabled:opacity-30',\n  'data-unavailable:pointer-events-none data-unavailable:line-through data-unavailable:opacity-30',\n].join(' ');\n\nconst RANGE_CELL = [\n  'data-selected:rounded-none data-selected:bg-primary/[0.08] data-selected:text-foreground',\n  'data-selection-start:rounded-s-md data-selection-start:bg-primary data-selection-start:text-primary-foreground',\n  'data-selection-end:rounded-e-md data-selection-end:bg-primary data-selection-end:text-primary-foreground',\n  'data-invalid:bg-destructive/10 data-invalid:data-selection-start:bg-destructive data-invalid:data-selection-end:bg-destructive',\n].join(' ');\n\nconst TODAY_DOT =\n  'after:pointer-events-none after:absolute after:start-1/2 after:bottom-1 after:z-10 after:size-[3px] after:-translate-x-1/2 after:rounded-full after:bg-primary';\n\nconst TODAY_DOT_ON_SELECTION = 'data-selected:after:bg-primary-foreground';\n\nconst TODAY_DOT_ON_RANGE_EDGE =\n  'data-selection-end:after:bg-primary-foreground data-selection-start:after:bg-primary-foreground';\n\nfunction todayDotOf(isRange: boolean) {\n  if (isRange) {\n    return cn(TODAY_DOT, TODAY_DOT_ON_RANGE_EDGE);\n  }\n  return cn(TODAY_DOT, TODAY_DOT_ON_SELECTION);\n}\n\nfunction CalendarGrid({ isRange = false }: { isRange?: boolean }) {\n  const now = today(getLocalTimeZone());\n\n  return (\n    <CalendarGridRac>\n      <CalendarGridHeaderRac>\n        {(day) => (\n          <CalendarHeaderCellRac className='text-muted-foreground size-9 rounded-md p-0 text-xs font-medium'>\n            {day}\n          </CalendarHeaderCellRac>\n        )}\n      </CalendarGridHeaderRac>\n      <CalendarGridBodyRac className='[&_td]:px-0 [&_td]:py-px'>\n        {(date) => {\n          const isToday = date.compare(now) === 0;\n          return (\n            <CalendarCellRac\n              date={date}\n              className={cn(\n                CELL,\n                isRange && RANGE_CELL,\n                isToday && todayDotOf(isRange)\n              )}\n            />\n          );\n        }}\n      </CalendarGridBodyRac>\n    </CalendarGridRac>\n  );\n}\n\ntype CalendarProps<T extends DateValue> = Omit<\n  CalendarRacProps<T>,\n  'className'\n> & {\n  className?: string;\n};\n\ntype RangeCalendarProps<T extends DateValue> = Omit<\n  RangeCalendarRacProps<T>,\n  'className'\n> & {\n  className?: string;\n};\n\nfunction Calendar<T extends DateValue>({\n  className,\n  ...props\n}: CalendarProps<T>) {\n  return (\n    <CalendarRac\n      {...props}\n      className={composeRenderProps(className, (value) => cn('w-fit', value))}\n    >\n      <CalendarHeader />\n      <CalendarGrid />\n    </CalendarRac>\n  );\n}\n\nfunction RangeCalendar<T extends DateValue>({\n  className,\n  ...props\n}: RangeCalendarProps<T>) {\n  return (\n    <RangeCalendarRac\n      {...props}\n      className={composeRenderProps(className, (value) => cn('w-fit', value))}\n    >\n      <CalendarHeader />\n      <CalendarGrid isRange />\n    </RangeCalendarRac>\n  );\n}\n\nexport { Calendar, RangeCalendar };\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "primitives"
  ],
  "type": "registry:ui"
}