Calendar
calendar日历面板 · 自研零依赖(日/月/年三层下钻·常驻不带浮层) + min-max/disabledDate/今天快捷 · 定宽字符串受控
用法
基础用法
常驻月历面板,不带触发器也不带浮层 —— 要「输入框 + 弹层」用 DatePicker,它内部就是这个面板。对外值是 ISO 日期串 YYYY-MM-DD。
<Calendar defaultValue="2026-06-08" />选月份 / 选年份
picker 决定粒度与值形状:month → YYYY-MM,year → YYYY。面板标题可点,逐层上卷到月/年视图。
<Calendar picker="month" defaultValue="2026-06" />
<Calendar picker="year" defaultValue="2026" />限定范围 + 禁用周末
minDate / maxDate 框定可选区间,disabledDate 进一步逐日禁选。
<Calendar
defaultValue="2026-06-10"
minDate="2026-06-01"
maxDate="2026-06-30"
disabledDate={(iso) => {
const day = new Date(iso + "T00:00:00").getDay();
return day === 0 || day === 6;
}}
/>指定初始月份
defaultMonth 只决定面板停在哪一屏,与选中值无关 —— 适合「没有值但想从某个月开始看」。
<Calendar defaultMonth="2026-09-01" />禁用 / 只读
disabled 连翻页都停掉;readOnly 可以翻页浏览但选不动。
<Calendar defaultValue="2026-06-08" disabled />
<Calendar defaultValue="2026-06-08" readOnly />何时用
需要一块常驻铺开的月历时用:仪表盘侧栏的日期导航、预约页的选日区、任何「面板本身就是界面一部分」
的场景。它不带触发器也不带浮层。
要「输入框 + 点开才出日历」用 DatePicker —— 它的弹层里就是本组件,
两者共用同一套下钻与禁用逻辑,行为完全一致。选一段区间用
DateRangePicker;连时间一起选用
DateTimePicker。
本组件在 0.15.0 之前是 MUI XDateCalendar的桥接件,要装四个 optional peer 并挂MuiBridgeProvider。现在是零依赖自研,装库即用。
导入
import { Calendar } from "@hulianui/ui"Props
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| value | string | null | — | 受控值。形状随 picker:"YYYY-MM-DD" / "YYYY-MM" / "YYYY" |
| defaultValue | string | null | — | 非受控初始值,形状同上 |
| picker | "date" | "month" | "year" | "date" | 选择粒度,同时决定值形状与面板起始层 |
| defaultMonth | string | 随 value | 面板初始停留的月份(任意可解析日期串),与选中值无关。之后由内部导航接管 |
| minDate | string | — | 最早可选日期(任意可解析日期串,内部规范化) |
| maxDate | string | — | 最晚可选日期 |
| disabledDate | (isoDate: string) => boolean | — | 逐日禁用判定,入参恒为 "YYYY-MM-DD"(月/年粒度传该月/该年首日) |
| showToday | boolean | true | 底部跟随 locale 的「今天 / 本月 / 今年」快捷 |
| disabled | boolean | false | 整块置灰,连翻页都停掉 |
| readOnly | boolean | false | 可翻页浏览,但选不动 |
| aria-label | string | 来自 ConfigProvider | 面板无障碍名;显式值优先 |
| className | string | — | 落在面板外层容器 |
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onValueChange | (value: string) => void | 选中回调。面板内的下钻不会触发,只有真正选到 picker 那一层才回调;面板没有清空入口,所以不回传 null |
禁忌 / 坑
- 月份标题、星期与月份名称、翻页标签和快捷文案跟随最近的
ConfigProviderlocale;未提供 Provider 时默认中文。ISO 值与选择规则不受 locale 影响。 - 值是定宽文本,不是 `Date`:
"YYYY-MM-DD"定宽 → 字典序即时间序,区间比较可以直接比字符串,
也避开了 new Date("2026-06-08").toISOString() 在东八区少算 8 小时那类日界坑。要 Date 对象请自己转。
onValueChange的参数类型是string而非string | null:面板没有清空入口。
需要「可清空」用 DatePicker,它的触发器上带清除按钮。
- 下钻不回调:
picker="date"时点标题上卷到月视图、再点某个月,只是把光标挪过去,不算选中,
只有点到日格才提交。写测试时别把「点了 9 月」当成一次选值。
disabledDate在date粒度下逐日调用(一屏 42 次),请保持它是纯计算 —— 别在里面发请求或建对象。
月/年粒度下只对该月/该年首日调一次,判据也随之变粗:想精确到天就别用粗粒度 picker。
disabled与readOnly不是一回事:readOnly还能翻页浏览,disabled连翻页按钮都禁掉。- 面板宽度固定
15.75rem(7 列 × 2.25rem),不做响应式收窄 —— 日历一挤压就点不准。
要塞进更窄的容器请自行缩放。
相关
DatePicker · DateRangePicker · DateTimePicker · TimePicker · TimeField · Scheduler
Playground
<Calendar
value={date}
onValueChange={setDate}
/>