DateRangePicker
date-range-picker用双月日历选出起止日期,带快捷区间
用法
基础用法
点击触发器弹出双月日历,依次选起止两端确定区间。
<DateRangePicker defaultValue={["2026-06-08", "2026-06-20"]} />受控
对外受控值为 [start, end](ISO YYYY-MM-DD),清空回传 null。
const [range, setRange] = useState<DateRangeValue | null>(["2026-06-08", "2026-06-20"]);
<DateRangePicker value={range} onValueChange={setRange} />无快捷预设
presets={false} 隐藏左侧「今天 / 最近 7 天…」预设栏。
<DateRangePicker defaultValue={["2026-06-03", "2026-06-09"]} presets={false} />限定范围 + 禁用周末
minDate / maxDate 框定可选区间,disabledDate 进一步禁选某些天。
<DateRangePicker
defaultValue={["2026-06-10", "2026-06-12"]}
minDate="2026-06-01"
maxDate="2026-06-30"
disabledDate={(iso) => {
const day = new Date(iso + "T00:00:00").getDay();
return day === 0 || day === 6;
}}
/>月份区间 / 年份区间
picker 决定粒度,与 DatePicker 的同名 prop 同义(对标 el-date-picker 的 monthrange)。值形状随之变成 ["YYYY-MM"] / ["YYYY"],预设也换成该粒度的常用档;两端仍由组件自己夹,选不出「起点晚于终点」。
<DateRangePicker picker="month" defaultValue={["2026-03", "2026-06"]} />
<DateRangePicker picker="year" defaultValue={["2024", "2026"]} />月份区间的上界
maxDate 恒按 ISO 日期说话。月粒度下判的是「整月都超界才禁」,所以写今天即可得到「当月可选、未来月灰掉」——运营点右面板拿到明年某月那个坑就是这么堵的。
<DateRangePicker picker="month" maxDate="2026-08-14" defaultValue={["2026-05", "2026-08"]} />尺寸
size 与 Input / Select 共用同一套刻度(sm 32px / md 40px / lg 48px),同一行表单里高度天然对齐。面板里日期格的几何不随之变化。
<DateRangePicker size="sm" defaultValue={["2026-06-08", "2026-06-20"]} />
<DateRangePicker size="md" defaultValue={["2026-06-08", "2026-06-20"]} />
<DateRangePicker size="lg" defaultValue={["2026-06-08", "2026-06-20"]} />禁用
整体置灰,触发器不可打开。
<DateRangePicker defaultValue={["2026-06-01", "2026-06-15"]} disabled />何时用
选一段区间(起止两端)时用,自带双面板并排 + 快捷预设。picker 决定粒度:日(默认)/ 月 / 年,分别对应 el-date-picker 的 daterange / monthrange / yearrange。选单个日期用 DatePicker;连时间一起选用 DateTimePicker;月历常驻铺开用 Calendar。全库日期族都是零依赖自研,值一律是定宽字符串。
导入
import { DateRangePicker } from "@hulianui/ui"Props
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| value | [string, string] | null | - | 受控值 [start, end],形状随 picker(YYYY-MM-DD / YYYY-MM / YYYY);null = 已清空;传入即受控 |
| defaultValue | [string, string] | null | - | 非受控初始值 |
| picker | "date" | "month" | "year" | "date" | 选择粒度,与 DatePicker 的同名 prop 同义。面板形态随之变化:两个月历 / 两个年份页(各 12 个月)/ 两个 12 年段 |
| size | "sm" | "md" | "lg" | "md" | 触发器尺寸档,刻度与 Input 一致(32 / 40 / 48px);面板里日期格的几何不随之变化 |
| minDate | string | - | 最早可选日,恒为 ISO `YYYY-MM-DD`,不随 `picker` 变;月/年粒度下按「整段都超界才禁」判定 |
| maxDate | string | - | 最晚可选日,口径同 minDate |
| disabledDate | (isoDate: string) => boolean | - | 自定义禁用,入参恒为 ISO YYYY-MM-DD;月/年粒度下只按该段首日问一次 |
| presets | boolean | DateRangePreset[] | true | 快捷预设:true/省略 = 该粒度的默认档(日:今天/最近 7 天/最近 30 天/本月;月:本月/最近 3 个月/最近 6 个月/今年;年:今年/最近 3 年/最近 5 年);数组 = 自定义;false = 隐藏 |
| placeholder | [string, string] | 随 picker | 占位文案 [开始, 结束],默认「开始日期 / 开始月份 / 开始年份」 |
| displayFormat | string | 随 picker | 展示格式(dayjs format),默认 YYYY-MM-DD / YYYY-MM / YYYY;对外受控值的形状不受它影响 |
| disabled | boolean | false | 禁用 |
| readOnly | boolean | false | 只读:可打开查看,无端点选择/无预设/无清除 |
| className | string | - | 容器类名 |
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onValueChange | (range: [string, string] | null) => void | 区间变化(含清空 → null) |
DateRangePreset:{ label: string; getValue: () => [string, string] },点击时调用、可基于"今天"动态计算。
禁忌 / 坑
- 受控/非受控二选一:给
value走受控须配onValueChange;只想要初值用defaultValue,别同时给。 - 对外受控值恒为定宽字符串数组(不是 Date),形状由
picker决定:YYYY-MM-DD/YYYY-MM/YYYY。displayFormat只改触发器上的展示,回传值不变。 - `minDate` / `maxDate` / `disabledDate` 恒按 ISO 日期说话,不随
picker变。月/年粒度下的判定是「整段都超界才禁」:maxDate="2026-06-15"时2026-06仍可选,2026-07才灰掉。想连当月一起禁就把maxDate写到上一段的末尾(2026-05-31)。 - 月/年粒度下
disabledDate每段只被问一次,入参是该段首日(2026-09-01代表整个 9 月)。别在里面写按「日」判断的逻辑(如禁周末),那在这两档没有意义。 - 年份页是 12 年整段(不是十年段),因为两页并排时十年段的首尾补位年会让同一个年份在左右两页各出现一次。
disabledDate入参是 ISO 字符串,自己拼new Date(iso + "T00:00:00")算 getDay 时注意时区,别直接new Date(iso)(会按 UTC 解析偏一天)。- 触发器是
role="combobox"的按钮:未在 Props 里列出的原生属性(aria-*/data-*/id/title/onBlur…)落到它身上,不是外层容器 —— 读屏念的、能聚焦的都是它(#293)。 - 放进 Field 时,
label的htmlFor、aria-describedby、invalid与disabled会自动串到触发器上;<Field required>注入的aria-required同理。0.54.0 之前这条链是断的(label 指向一个不存在的 id,读屏念不出字段名),升级后无需改调用代码。 - 测试里按角色取触发器要用
getByRole("combobox"),不再是"button"。
相关
Calendar · DatePicker · DateTimePicker · TimeField · Button · ShimmerButton
Playground
<DateRangePicker
value={range}
onValueChange={setRange}
/>