{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar",
  "type": "registry:ui",
  "title": "Calendar",
  "description": "Calendar component for Tile UI.",
  "devDependencies": [
    "sass"
  ],
  "registryDependencies": [
    "@tile-ui/core",
    "@tile-ui/styles"
  ],
  "files": [
    {
      "path": "packages/react/src/components/calendar/calendar.tsx",
      "type": "registry:ui",
      "target": "components/ui/calendar/calendar.tsx",
      "content": "import React, { useState } from 'react';\nimport {\n\taddMonths,\n\tcalendarStyleKeys,\n\tgetCalendarDayModifiers,\n\tgetCalendarFirstSelectedDate,\n\tgetMonthCaption,\n\tgetMonthGrid,\n\tgetWeekdayLabels,\n\tselectCalendarDay,\n\tstartOfMonth,\n} from '../lib/core';\nimport type { CalendarBaseProps, CalendarDayModifiers, CalendarSelection } from '../lib/core';\nimport styles from './calendar.module.scss';\n\nexport interface CalendarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'>, CalendarBaseProps {}\n\nexport interface CalendarDayButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\t/** 日期 */\n\tdate: Date;\n\t/** 修饰状态 */\n\tmodifiers: CalendarDayModifiers;\n}\n\n/**\n * 单个日期按钮（独立导出，供自定义网格使用）\n */\nconst CalendarDayButton = React.forwardRef<HTMLButtonElement, CalendarDayButtonProps>(({ date, modifiers, className = '', children, ...props }, ref) => {\n\tconst classes = [styles[calendarStyleKeys.dayButton], className].filter(Boolean).join(' ');\n\n\treturn (\n\t\t<button\n\t\t\tref={ref}\n\t\t\ttype=\"button\"\n\t\t\tdata-day={date.toLocaleDateString()}\n\t\t\tdata-selected={modifiers.selected}\n\t\t\tdata-selected-single={modifiers.selected && !modifiers.rangeStart && !modifiers.rangeEnd && !modifiers.rangeMiddle}\n\t\t\tdata-range-start={modifiers.rangeStart}\n\t\t\tdata-range-end={modifiers.rangeEnd}\n\t\t\tdata-range-middle={modifiers.rangeMiddle}\n\t\t\tdata-outside={modifiers.outside}\n\t\t\tdata-disabled={modifiers.disabled}\n\t\t\tdata-today={modifiers.today}\n\t\t\tdisabled={modifiers.disabled}\n\t\t\taria-disabled={modifiers.disabled}\n\t\t\tclassName={classes}\n\t\t\t{...props}>\n\t\t\t{children ?? date.getDate()}\n\t\t</button>\n\t);\n});\nCalendarDayButton.displayName = 'CalendarDayButton';\n\n/**\n * Calendar 日历组件（单选 / 多选 / 范围选择）\n */\nconst Calendar = React.forwardRef<HTMLDivElement, CalendarProps>(\n\t({ className = '', mode = 'single', selected, defaultSelected, defaultMonth, showOutsideDays = true, disabled, onSelect, ...props }, ref) => {\n\t\tconst [internalSelected, setInternalSelected] = useState<CalendarSelection>(defaultSelected);\n\t\tconst currentSelected = selected !== undefined ? selected : internalSelected;\n\n\t\tconst [month, setMonth] = useState<Date>(() => {\n\t\t\tif (defaultMonth) {\n\t\t\t\treturn startOfMonth(defaultMonth);\n\t\t\t}\n\t\t\tconst firstSelected = getCalendarFirstSelectedDate(defaultSelected);\n\t\t\tif (firstSelected) {\n\t\t\t\treturn startOfMonth(firstSelected);\n\t\t\t}\n\t\t\treturn startOfMonth(new Date());\n\t\t});\n\n\t\tfunction handleSelect(day: Date) {\n\t\t\tif (disabled?.(day)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst next = selectCalendarDay(mode, currentSelected, day);\n\t\t\tif (selected === undefined) {\n\t\t\t\tsetInternalSelected(next);\n\t\t\t}\n\t\t\tonSelect?.(next);\n\t\t}\n\n\t\tconst grid = getMonthGrid(month, showOutsideDays);\n\t\tconst weekdays = getWeekdayLabels();\n\n\t\treturn (\n\t\t\t<div ref={ref} data-slot=\"calendar\" data-mode={mode} className={`${styles[calendarStyleKeys.root]} ${className}`} {...props}>\n\t\t\t\t<div className={styles[calendarStyleKeys.header]}>\n\t\t\t\t\t<nav className={styles[calendarStyleKeys.nav]}>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label=\"上个月\"\n\t\t\t\t\t\t\tclassName={`${styles[calendarStyleKeys.navButton]} ${styles[calendarStyleKeys.navPrev]}`}\n\t\t\t\t\t\t\tonClick={() => setMonth((prev) => addMonths(prev, -1))}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tclassName={styles[calendarStyleKeys.icon]}\n\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\twidth=\"24\"\n\t\t\t\t\t\t\t\theight=\"24\"\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<path d=\"m15 18-6-6 6-6\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label=\"下个月\"\n\t\t\t\t\t\t\tclassName={`${styles[calendarStyleKeys.navButton]} ${styles[calendarStyleKeys.navNext]}`}\n\t\t\t\t\t\t\tonClick={() => setMonth((prev) => addMonths(prev, 1))}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\tclassName={styles[calendarStyleKeys.icon]}\n\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\twidth=\"24\"\n\t\t\t\t\t\t\t\theight=\"24\"\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<path d=\"m9 18 6-6-6-6\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</nav>\n\t\t\t\t\t<div className={styles[calendarStyleKeys.monthCaption]}>{getMonthCaption(month)}</div>\n\t\t\t\t</div>\n\t\t\t\t<div className={styles[calendarStyleKeys.weekdays]}>\n\t\t\t\t\t{weekdays.map((label) => (\n\t\t\t\t\t\t<div key={label} className={styles[calendarStyleKeys.weekday]}>\n\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t<div className={styles[calendarStyleKeys.weeks]} role=\"grid\">\n\t\t\t\t\t{grid.map((week, weekIndex) => (\n\t\t\t\t\t\t<div key={weekIndex} role=\"row\" className={styles[calendarStyleKeys.week]}>\n\t\t\t\t\t\t\t{week.map((day, dayIndex) => {\n\t\t\t\t\t\t\t\tif (!day) {\n\t\t\t\t\t\t\t\t\treturn <div key={dayIndex} className={styles[calendarStyleKeys.day]} />;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst modifiers = getCalendarDayModifiers(day, month, currentSelected, showOutsideDays, disabled);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div key={dayIndex} role=\"gridcell\" aria-selected={modifiers.selected} className={styles[calendarStyleKeys.day]}>\n\t\t\t\t\t\t\t\t\t\t<CalendarDayButton date={day} modifiers={modifiers} onClick={() => handleSelect(day)} />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t},\n);\nCalendar.displayName = 'Calendar';\n\nexport { Calendar, CalendarDayButton };\nexport default Calendar;\n"
    },
    {
      "path": "packages/styles/scss/components/calendar.module.scss",
      "type": "registry:file",
      "target": "components/ui/calendar/calendar.module.scss",
      "content": "@use '../../../styles/variables/colors' as *;\n\n// 日历根容器\n.root {\n\twidth: fit-content;\n\tpadding: var(--tile-calendar-padding, $spacing-3);\n\tbackground-color: var(--tile-calendar-background, $background);\n\tborder-radius: var(--tile-calendar-radius, $radius-md);\n\tborder: var(--tile-calendar-border, 1px solid $border);\n\tfont-variant-numeric: var(--tile-calendar-numerals, inherit);\n}\n\n// 头部（导航 + 月份标题）\n.header {\n\tposition: relative;\n\theight: var(--tile-calendar-header-height, auto);\n\tdisplay: flex;\n\talign-items: center;\n}\n\n// 上 / 下月导航\n.nav {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\twidth: 100%;\n\tgap: $spacing-1;\n}\n\n.navButton {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: var(--tile-calendar-nav-size, 2rem);\n\theight: var(--tile-calendar-nav-size, 2rem);\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: var(--tile-calendar-day-radius, $radius);\n\tbox-shadow: var(--tile-calendar-nav-shadow, none);\n\tbackground-color: transparent;\n\tcolor: $foreground;\n\tcursor: pointer;\n\toutline: none;\n\ttransition: background-color $transition-fast;\n\n\t&:hover:not(:disabled) {\n\t\tbackground-color: var(--tile-calendar-hover-background, $accent);\n\t\tcolor: $accent-foreground;\n\t}\n\n\t&:focus-visible {\n\t\tbox-shadow: var(--tile-calendar-focus-shadow, 0 0 0 2px $background, 0 0 0 4px $ring);\n\t}\n\n\t&:disabled {\n\t\topacity: 0.5;\n\t\tpointer-events: none;\n\t}\n\n\t.icon {\n\t\twidth: 1rem;\n\t\theight: 1rem;\n\t\tpointer-events: none;\n\t}\n}\n\n// 月份标题\n.monthCaption {\n\tposition: absolute;\n\tinset-inline: 2rem;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tfont-size: $text-sm;\n\tfont-weight: var(--tile-calendar-caption-weight, $font-medium);\n\tuser-select: none;\n\tpointer-events: none;\n}\n\n// 星期表头\n.weekdays {\n\tdisplay: flex;\n\twidth: 100%;\n\tmargin-top: var(--tile-calendar-weekdays-margin, $spacing-2);\n}\n\n.weekday {\n\tflex: 1;\n\tborder-radius: $radius;\n\tfont-size: var(--tile-calendar-weekday-size, 0.8rem);\n\tfont-weight: var(--tile-calendar-weekday-weight, $font-normal);\n\tcolor: $muted-foreground;\n\ttext-align: center;\n\tpadding-block: var(--tile-calendar-weekday-padding, $spacing-1);\n\tuser-select: none;\n}\n\n// 日期网格\n.weeks {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: var(--tile-calendar-weeks-gap, $spacing-1);\n\tmargin-top: var(--tile-calendar-weeks-margin, $spacing-1);\n}\n\n.week {\n\tdisplay: flex;\n\twidth: 100%;\n}\n\n// 日期单元格\n.day {\n\tflex: 1;\n\tpadding: var(--tile-calendar-cell-padding, 0);\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.dayButton {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 2rem;\n\theight: 2rem;\n\tmin-width: 2rem;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: var(--tile-calendar-day-radius, $radius);\n\tbackground-color: transparent;\n\tcolor: $foreground;\n\tfont-size: var(--tile-calendar-day-size, $text-sm);\n\tfont-weight: $font-normal;\n\tline-height: 1;\n\ttext-align: center;\n\tcursor: pointer;\n\toutline: none;\n\ttransition:\n\t\tbackground-color $transition-fast,\n\t\tcolor $transition-fast;\n\tuser-select: none;\n\n\t&:hover:not(:disabled):not([data-selected='true']) {\n\t\tbackground-color: var(--tile-calendar-hover-background, $accent);\n\t\tcolor: $accent-foreground;\n\t}\n\n\t&:focus-visible {\n\t\tbox-shadow: var(--tile-calendar-focus-shadow, 0 0 0 2px $background, 0 0 0 4px $ring);\n\t}\n\n\t// 今天\n\t&[data-today='true'] {\n\t\tbackground-color: var(--tile-calendar-today-background, $accent);\n\t\tcolor: var(--tile-calendar-today-color, $accent-foreground);\n\t\tfont-weight: var(--tile-calendar-today-weight, $font-normal);\n\n\t\t&[data-selected='true'] {\n\t\t\tbackground-color: var(--tile-calendar-selected-background, $primary);\n\t\t\tcolor: var(--tile-calendar-selected-color, $primary-foreground);\n\t\t}\n\t}\n\n\t// 相邻月份的天\n\t&[data-outside='true'] {\n\t\tcolor: $muted-foreground;\n\t\topacity: var(--tile-calendar-outside-opacity, 1);\n\t}\n\n\t// 禁用\n\t&[data-disabled='true'] {\n\t\tcolor: $muted-foreground;\n\t\topacity: var(--tile-calendar-disabled-opacity, 0.5);\n\t\tcursor: not-allowed;\n\t\tpointer-events: none;\n\t}\n\n\t// 单选选中态\n\t&[data-selected-single='true'] {\n\t\tbackground-color: var(--tile-calendar-selected-background, $primary);\n\t\tcolor: var(--tile-calendar-selected-color, $primary-foreground);\n\t}\n\n\t// 范围起点\n\t&[data-range-start='true'] {\n\t\tbackground-color: var(--tile-calendar-selected-background, $primary);\n\t\tcolor: var(--tile-calendar-selected-color, $primary-foreground);\n\t\tborder-radius: var(--tile-calendar-day-radius, $radius);\n\t\tborder-end-end-radius: 0;\n\t\tborder-start-end-radius: 0;\n\t}\n\n\t// 范围终点\n\t&[data-range-end='true'] {\n\t\tbackground-color: var(--tile-calendar-selected-background, $primary);\n\t\tcolor: var(--tile-calendar-selected-color, $primary-foreground);\n\t\tborder-radius: var(--tile-calendar-day-radius, $radius);\n\t\tborder-start-start-radius: 0;\n\t\tborder-end-start-radius: 0;\n\t}\n\n\t// 范围中间\n\t&[data-range-middle='true'] {\n\t\tbackground-color: var(--tile-calendar-range-background, $accent);\n\t\tcolor: var(--tile-calendar-range-color, $accent-foreground);\n\t\tborder-radius: 0;\n\t}\n}\n"
    },
    {
      "path": "packages/react/src/components/calendar/index.ts",
      "type": "registry:ui",
      "target": "components/ui/calendar/index.ts",
      "content": "export { Calendar, CalendarDayButton, type CalendarProps, type CalendarDayButtonProps } from './calendar';\n"
    }
  ]
}
