# DatePicker

日期选择器，支持单日期、月份、季度、日期范围及多选日期模式。

## 适用场景

- 需要用户选择单一日期、月份或季度
- 需要选择起止日期范围（RangePicker）
- 需要一次性选择多个离散日期（MultiDatePicker）
- 表单中的日期字段录入，搭配 `<Field>` 使用

## Props

### DatePicker Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `-` | 否 | 自定义 class |
| value | `Date \| DayJS \| null` | `-` | 否 | 选中的日期值（控制属性） |
| defaultValue | `Date \| DayJS \| null` | `-` | 否 | 选中的日期值（非控制属性） |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| size | `TypePickerSize` | `-` | 否 | 整体大小：xs, sm, md, lg, xl，影响输入框和面板尺寸 |
| status | `TypePickerStatus` | `-` | 否 | 是否处于出错状态 |
| mode | `TypeDatePickerMode` | `-` | 否 | 选择器取值类型（date / month / quarter） |
| itemFormat | `string` | `-` | 否 | 格式化 value 给 input 框。默认：date 为 `YYYY-MM-DD`，month 为 `YYYY-MM`，quarter 为 `YYYY-\QQ` |
| renderItem | `(currentDate: Dayjs, today: Dayjs) => string \| number \| Element` | `-` | 否 | 自定义日期格子内容 |
| getDisabledItem | `(currentDate: Dayjs, today: Dayjs) => boolean` | `-` | 否 | 控制哪些日期不可选 |
| getDefaultDisplayDate | `(today: Dayjs) => Dayjs` | `-` | 否 | 面板打开时的默认显示位置 |
| showTime | `boolean` | `false` | 否 | 仅 date 模式有效，是否允许选择时间 |
| hideNow | `boolean` | `false` | 否 | 是否隐藏「此刻」按钮 |
| showSecond | `boolean` | `false` | 否 | 是否显示秒选择 |
| getDisabledTime | `(currentDate: Dayjs) => { start: number; end: number; }` | `-` | 否 | 某天中可选时间范围（start/end 为 0~86400 秒） |
| open | `boolean` | `-` | 否 | 面板显隐（控制属性） |
| onOpenChange | `(openStatus: boolean, value: Dayjs) => void` | `-` | 否 | 面板显隐变化时的回调。接管 open 时必须实现此回调 |
| placeholder | `string` | `-` | 否 | 输入框的 placeholder |
| popupClassName | `string` | `-` | 否 | 面板的附加 className |
| onChange | `(selected: Dayjs) => void` | `-` | 否 | 选中日期时的回调 |
| renderFooter | `() => Element \| TypeActionLink[]` | `-` | 否 | 自定义面板底部区域 |
| yearStart | `number` | `-` | 否 | 年份快速切换的起始年份（默认：当前年往前 12 年） |
| yearEnd | `number` | `-` | 否 | 年份快速切换的结束年份（默认：当前年往后 12 年） |
| clearable | `boolean` | `-` | 否 | 是否支持清除已选值 |
| onFocus | `(e: FocusEvent) => void` | `-` | 否 | focus 事件回调 |
| onBlur | `(e: FocusEvent) => void` | `-` | 否 | blur 事件回调 |
| autoFocus | `boolean` | `-` | 否 | 自动聚焦 |
| iconSvg | `FC<{}>` | `-` | 否 | 自定义日历图标 SVG 组件 |
| iconNode | `ReactNode` | `-` | 否 | 自定义日历图标节点 |

### RangePicker Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `-` | 否 | 自定义 class |
| startValue | `TypeDateValue` | `-` | 否 | 开始日期（控制属性） |
| endValue | `TypeDateValue` | `-` | 否 | 结束日期（控制属性） |
| defaultStartValue | `TypeDateValue` | `-` | 否 | 开始日期默认值 |
| defaultEndValue | `TypeDateValue` | `-` | 否 | 结束日期默认值 |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| size | `TypePickerSize` | `-` | 否 | 整体大小控制 |
| status | `TypePickerStatus` | `-` | 否 | 是否处于出错状态 |
| mode | `TypeDatePickerMode` | `-` | 否 | 选择器取值类型 |
| itemFormat | `string` | `-` | 否 | 格式化模板 |
| showTime | `boolean` | `-` | 否 | 仅 `mode='date'` 有效；使用单个带时间 DatePicker 面板，先确认开始日期时间，再确认结束日期时间 |
| hideNow | `boolean` | `false` | 否 | 带时间模式下是否隐藏「此刻」按钮 |
| showSecond | `boolean` | `false` | 否 | 带时间模式下是否显示秒选择 |
| getDisabledTime | `(currentDate: Dayjs) => { start: number; end: number; }` | `-` | 否 | 当前编辑日期的可选时间范围（start/end 为 0~86400 秒） |
| open | `boolean` | `-` | 否 | 面板显隐（控制属性） |
| clearable | `boolean` | `-` | 否 | 是否支持清除已选值 |
| startPlaceholder | `string` | `-` | 否 | 开始日期输入框 placeholder |
| endPlaceholder | `string` | `-` | 否 | 结束日期输入框 placeholder |
| popupClassName | `string` | `-` | 否 | 面板的附加 className |
| onChange | `(start: Dayjs, end: Dayjs) => void` | `-` | 否 | 日期范围变化回调 |
| yearStart | `number` | `-` | 否 | 年份范围起始 |
| yearEnd | `number` | `-` | 否 | 年份范围结束 |

### MultiDatePicker Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `-` | 否 | 自定义 class |
| value | `string[]` | `-` | 否 | 选中的日期值列表（控制属性），如 `['2023-01-01']` |
| defaultValue | `string[]` | `-` | 否 | 选中的日期值默认列表 |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| size | `TypePickerSize` | `-` | 否 | 整体大小控制 |
| status | `TypePickerStatus` | `-` | 否 | 是否处于出错状态 |
| mode | `TypeDatePickerMode` | `date` | 否 | 选择器取值类型 |
| formatItem | `(dateText: string) => string` | `-` | 否 | 选中值在输入框中的展示格式 |
| getDisabledItem | `(date: Dayjs, firstDayOfCurrentUnit: Dayjs) => boolean` | `-` | 否 | 控制哪些日期不可选 |
| getDefaultDisplayDate | `(today: Dayjs) => Dayjs` | `-` | 否 | 面板打开时的默认显示位置 |
| hideNow | `boolean` | `false` | 否 | 是否隐藏「今日」按钮（月份/季度模式下无效） |
| popupClassName | `string` | `-` | 否 | 面板的附加 className |
| onChange | `(selectedList: string[]) => void` | `-` | 否 | 选中日期变化时的回调 |
| placeholder | `string` | `-` | 否 | 输入框的 placeholder |

## 典型用法

### 基础单日期选择

```tsx
import { DatePicker } from '@befe/brick-comp-date-picker'
import { useState } from 'react'
import dayjs from 'dayjs'

function Demo() {
    const [date, setDate] = useState(dayjs(new Date(2024, 0, 1)))

    return (
        <DatePicker
            value={date}
            onChange={setDate}
        />
    )
}
```

### 月份 / 季度选择

```tsx
import { DatePicker } from '@befe/brick-comp-date-picker'

// 月份选择
<DatePicker mode={'month'} defaultValue={new Date(2024, 0)} />

// 季度选择
<DatePicker mode={'quarter'} />
```

### 日期范围选择

```tsx
import { RangePicker } from '@befe/brick-comp-date-picker'
import { useState } from 'react'
import { Dayjs } from 'dayjs'

function Demo() {
    const [start, setStart] = useState<Dayjs | null>(null)
    const [end, setEnd] = useState<Dayjs | null>(null)

    return (
        <RangePicker
            startValue={start}
            endValue={end}
            onChange={(s, e) => {
                setStart(s)
                setEnd(e)
            }}
        />
    )
}
```

### 日期时间范围选择

```tsx
<RangePicker
    showTime
    showSecond
    startValue={start}
    endValue={end}
    onChange={(nextStart, nextEnd) => {
        setStart(nextStart)
        setEnd(nextEnd)
    }}
/>
```

`showTime` 的 RangePicker 使用单个带时间面板串行完成选择：先确认开始日期时间，再确认结束日期时间。该能力仅适用于 `mode='date'`，月份范围仍使用原有双面板交互。

### 禁用特定日期

```tsx
<DatePicker
    getDisabledItem={(date, today) =>
        date.isBefore(today.subtract(4, 'day'))
    }
/>
```

### 多选日期

```tsx
import { MultiDatePicker } from '@befe/brick-comp-date-picker'
import { useState } from 'react'

function Demo() {
    const [dates, setDates] = useState<string[]>([])
    return <MultiDatePicker value={dates} onChange={setDates} />
}
```

## 注意事项

- `DatePicker` 的 `value` 类型为 `Date | DayJS | null`，而 `MultiDatePicker` 的 `value` 是 `string[]`，两者格式不同，不可混用
- `RangePicker` 的 `onChange` 回调签名为 `(start, end)` 两个参数，在 Form 的 `Field` 中使用时需自行适配，不能直接展开 `{...control}`
- `showTime` 仅在 `mode='date'` 时有效
- 接管 `open` 属性时，必须同步实现 `onOpenChange` 回调，否则面板无法正常关闭
- `getDisabledItem` 在 month/quarter 模式下，`date` 参数代表该月/季度的第一天
