diff --git a/src/_common b/src/_common index addb5d0994..94e21e27e2 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit addb5d0994274db18d129c1809bd34eeeb789299 +Subproject commit 94e21e27e2aba45cc0da263d424537f453055180 diff --git a/src/date-picker/DatePicker.tsx b/src/date-picker/DatePicker.tsx index 6de9652de3..ebb51cde82 100644 --- a/src/date-picker/DatePicker.tsx +++ b/src/date-picker/DatePicker.tsx @@ -4,16 +4,17 @@ import dayjs from 'dayjs'; import isDate from 'lodash/isDate'; import useConfig from '../hooks/useConfig'; import { StyledProps } from '../common'; -import { TdDatePickerProps, PresetDate } from './type'; +import { TdDatePickerProps, PresetDate, DateMultipleValue, DateValue } from './type'; import SelectInput from '../select-input'; import SinglePanel from './panel/SinglePanel'; import useSingle from './hooks/useSingle'; import { parseToDayjs, getDefaultFormat, formatTime, formatDate } from '../_common/js/date-picker/format'; -import { subtractMonth, addMonth, extractTimeObj, covertToDate } from '../_common/js/date-picker/utils'; +import { subtractMonth, addMonth, extractTimeObj, covertToDate, isSame } from '../_common/js/date-picker/utils'; import { datePickerDefaultProps } from './defaultProps'; import useDefaultProps from '../hooks/useDefaultProps'; import useLatest from '../hooks/useLatest'; import useUpdateEffect from '../hooks/useUpdateEffect'; +import type { TagInputRemoveContext } from '../tag-input'; export interface DatePickerProps extends TdDatePickerProps, StyledProps {} @@ -35,6 +36,7 @@ const DatePicker = forwardRef((originalProps, r timePickerProps, presetsPlacement, needConfirm, + multiple, onPick, } = props; @@ -43,6 +45,7 @@ const DatePicker = forwardRef((originalProps, r popupVisible, inputProps, popupProps, + tagInputProps, value, year, month, @@ -63,7 +66,7 @@ const DatePicker = forwardRef((originalProps, r mode, format: props.format, valueType: props.valueType, - enableTimePicker, + enableTimePicker: multiple ? false : enableTimePicker, }); const onTriggerNeedConfirm = useLatest(() => { @@ -90,6 +93,7 @@ const DatePicker = forwardRef((originalProps, r }, [popupVisible]); useEffect(() => { + if (multiple) return; // 面板展开重置数据 // Date valueType、week mode 、quarter mode nad empty string don't need to be parsed const dateValue = @@ -100,8 +104,8 @@ const DatePicker = forwardRef((originalProps, r setInputValue(formatDate(dateValue, { format })); if (popupVisible) { - setYear(parseToDayjs(value, format).year()); - setMonth(parseToDayjs(value, format).month()); + setYear(parseToDayjs(value as DateValue, format).year()); + setMonth(parseToDayjs(value as DateValue, format).month()); setTime(formatTime(value, format, timeFormat, defaultTime)); } else { setIsHoverCell(false); @@ -111,12 +115,14 @@ const DatePicker = forwardRef((originalProps, r // 日期 hover function onCellMouseEnter(date: Date) { + if (multiple) return; setIsHoverCell(true); setInputValue(formatDate(date, { format })); } // 日期 leave function onCellMouseLeave() { + if (multiple) return; setIsHoverCell(false); setInputValue(formatDate(cacheValue, { format })); } @@ -133,6 +139,14 @@ const DatePicker = forwardRef((originalProps, r if (enableTimePicker) { setCacheValue(formatDate(date, { format })); } else { + if (multiple) { + const newDate = processDate(date); + onChange(newDate, { + dayjsValue: parseToDayjs(date, format), + trigger: 'pick', + }); + return; + } onChange(formatDate(date, { format, targetFormat: valueType }), { dayjsValue: parseToDayjs(date, format), trigger: 'pick', @@ -224,6 +238,38 @@ const DatePicker = forwardRef((originalProps, r // eslint-disable-next-line }, []); + function processDate(date: Date) { + const isSameDate = (value as DateMultipleValue).some((val) => isSame(dayjs(val).toDate(), date)); + let currentDate: DateMultipleValue; + + if (!isSameDate) { + currentDate = (value as DateMultipleValue).concat(formatDate(date, { format, targetFormat: valueType })); + } else { + currentDate = (value as DateMultipleValue).filter( + (val) => + formatDate(val, { format, targetFormat: valueType }) !== + formatDate(date, { format, targetFormat: valueType }), + ); + } + + return currentDate.sort((a, b) => dayjs(a).valueOf() - dayjs(b).valueOf()); + } + + const onTagRemoveClick = (ctx: TagInputRemoveContext) => { + const removeDate = dayjs(ctx.item).toDate(); + const newDate = processDate(removeDate); + onChange?.(newDate, { + dayjsValue: parseToDayjs(removeDate, format), + trigger: 'pick', + }); + }; + + const onTagClearClick = ({ e }) => { + e.stopPropagation(); + setPopupVisible(false); + onChange([], { dayjsValue: dayjs(), trigger: 'clear' }); + }; + const panelProps = { value: cacheValue, year, @@ -231,14 +277,15 @@ const DatePicker = forwardRef((originalProps, r mode, format, presets, - time, + time: multiple ? false : time, disableDate, firstDayOfWeek, timePickerProps, - enableTimePicker, + enableTimePicker: multiple ? false : enableTimePicker, presetsPlacement, popupVisible, needConfirm, + multiple, onCellClick, onCellMouseEnter, onCellMouseLeave, @@ -263,6 +310,12 @@ const DatePicker = forwardRef((originalProps, r inputProps={inputProps} popupVisible={popupVisible} panel={} + multiple={multiple} + tagInputProps={{ + onRemove: onTagRemoveClick, + ...tagInputProps, + }} + onClear={onTagClearClick} /> ); diff --git a/src/date-picker/DatePickerPanel.tsx b/src/date-picker/DatePickerPanel.tsx index d258ec8f93..1c60506d71 100644 --- a/src/date-picker/DatePickerPanel.tsx +++ b/src/date-picker/DatePickerPanel.tsx @@ -85,7 +85,7 @@ const DatePickerPanel = forwardRef((origin if (year !== nextYear) { props.onYearChange?.({ year: nextYear, - date: parseToDayjs(value, format).toDate(), + date: parseToDayjs(value as DateValue, format).toDate(), trigger: trigger === 'current' ? 'today' : (`year-${triggerMap[trigger]}` as DatePickerYearChangeTrigger), }); } @@ -93,7 +93,7 @@ const DatePickerPanel = forwardRef((origin if (month !== nextMonth) { props.onMonthChange?.({ month: nextMonth, - date: parseToDayjs(value, format).toDate(), + date: parseToDayjs(value as DateValue, format).toDate(), trigger: trigger === 'current' ? 'today' : (`month-${triggerMap[trigger]}` as DatePickerMonthChangeTrigger), }); } @@ -117,7 +117,7 @@ const DatePickerPanel = forwardRef((origin props.onTimeChange?.({ time: val, - date: parseToDayjs(value, format).toDate(), + date: parseToDayjs(value as DateValue, format).toDate(), trigger: 'time-hour', }); } @@ -129,7 +129,7 @@ const DatePickerPanel = forwardRef((origin trigger: 'confirm', }); - props.onConfirm?.({ date: dayjs(value).toDate(), e }); + props.onConfirm?.({ date: dayjs(value as DateValue).toDate(), e }); } // 预设 @@ -151,7 +151,7 @@ const DatePickerPanel = forwardRef((origin props.onYearChange?.({ year, - date: parseToDayjs(value, format).toDate(), + date: parseToDayjs(value as DateValue, format).toDate(), trigger: 'year-select', }); } @@ -161,7 +161,7 @@ const DatePickerPanel = forwardRef((origin props.onMonthChange?.({ month, - date: parseToDayjs(value, format).toDate(), + date: parseToDayjs(value as DateValue, format).toDate(), trigger: 'month-select', }); } diff --git a/src/date-picker/_example/date-time.tsx b/src/date-picker/_example/date-time.tsx index b43523a989..9f32b98226 100644 --- a/src/date-picker/_example/date-time.tsx +++ b/src/date-picker/_example/date-time.tsx @@ -6,7 +6,7 @@ export default function YearDatePicker() { const [value, setValue] = useState('2022-02-02 12:11:11'); const [value2, setValue2] = useState('2022-02-02 am 12:11:11'); - const handleChange: DatePickerProps['onChange'] = (value) => { + const handleChange: DatePickerProps['onChange'] = (value: DateValue) => { console.log(value); setValue(value); }; @@ -18,7 +18,7 @@ export default function YearDatePicker() { setValue2(v)} + onChange={(v: DateValue) => setValue2(v)} allowInput clearable format="YYYY-MM-DD a hh:mm:ss" diff --git a/src/date-picker/_example/multiple.tsx b/src/date-picker/_example/multiple.tsx new file mode 100644 index 0000000000..ad047fdd74 --- /dev/null +++ b/src/date-picker/_example/multiple.tsx @@ -0,0 +1,24 @@ +import React, { useState } from 'react'; +import { DatePicker } from 'tdesign-react'; +import type { DatePickerProps, DateMultipleValue } from 'tdesign-react'; + +export default function YearDatePicker() { + const [defaultValue, setDefaultValue] = useState(['2000-01-04', '2000-01-03', '2000-01-05']); + + const handleChange: DatePickerProps['onChange'] = (value: DateMultipleValue, context) => { + console.log('onChange:', value, context); + setDefaultValue(value); + }; + + return ( +
+ +
+ ); +} diff --git a/src/date-picker/base/Footer.tsx b/src/date-picker/base/Footer.tsx index 2f26b4350c..9f1cdeefd6 100644 --- a/src/date-picker/base/Footer.tsx +++ b/src/date-picker/base/Footer.tsx @@ -3,14 +3,14 @@ import classNames from 'classnames'; import { useLocaleReceiver } from '../../locale/LocalReceiver'; import Button from '../../button'; import useConfig from '../../hooks/useConfig'; -import { TdDatePickerProps, TdDateRangePickerProps, DateValue } from '../type'; +import { TdDatePickerProps, TdDateRangePickerProps, DateValue, DateMultipleValue } from '../type'; interface DatePickerFooterProps extends Pick { presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; onPresetClick?: Function; onConfirmClick?: Function; - selectedValue?: DateValue; + selectedValue?: DateValue | DateMultipleValue; } const DatePickerFooter = (props: DatePickerFooterProps) => { diff --git a/src/date-picker/date-picker.en-US.md b/src/date-picker/date-picker.en-US.md index c10e86f11e..bd5fc9ba01 100644 --- a/src/date-picker/date-picker.en-US.md +++ b/src/date-picker/date-picker.en-US.md @@ -13,25 +13,28 @@ borderless | Boolean | false | \- | N clearable | Boolean | false | \- | N defaultTime | String | '00:00:00' | Time selector default value | N disableDate | Object / Array / Function | - | Typescript:`DisableDate` `type DisableDate = Array \| DisableDateObj \| ((date: DateValue) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -disabled | Boolean | - | make DatePicker to be disabled | N +disabled | Boolean | undefined | make DatePicker to be disabled | N enableTimePicker | Boolean | false | \- | N firstDayOfWeek | Number | 7 | options: 1/2/3/4/5/6/7 | N format | String | 'YYYY-MM-DD' | \- | N inputProps | Object | - | Typescript:`InputProps`,[Input API Documents](./input?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N mode | String | date | options: year/quarter/month/week/date | N +multiple | Boolean | false | support multiple date,but not support being use together with range-picker、enableTimePicker and allowInput。Typescript:`boolean` | N needConfirm | Boolean | true | whether a confirmation button needs to be clicked to complete the action in the date-time picker scenario, default is true | N placeholder | String / Array | undefined | Typescript:`string` | N popupProps | Object | - | Typescript:`PopupProps`,[Popup API Documents](./popup?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N prefixIcon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N presets | Object | - | Typescript:`PresetDate` `interface PresetDate { [name: string]: DateValue \| (() => DateValue) }`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N presetsPlacement | String | bottom | options: left/top/right/bottom | N +selectInputProps | Object | - | Typescript:`SelectInputProps`,[SelectInput API Documents](./select-input?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N size | String | medium | options: small/medium/large。Typescript:`SizeEnum`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N status | String | default | options: default/success/warning/error | N suffixIcon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N timePickerProps | Object | - | Typescript:`TimePickerProps`,[TimePicker API Documents](./time-picker?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N tips | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N -value | String / Number / Date | '' | Typescript:`DateValue` `type DateValue = string \| number \| Date`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -defaultValue | String / Number / Date | '' | uncontrolled property。Typescript:`DateValue` `type DateValue = string \| number \| Date`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N +value | String / Number / Array / Date | '' | Typescript:`DateValue \| DateMultipleValue` ` type DateValue = string \| number \| Date ` ` type DateMultipleValue = Array `。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N +defaultValue | String / Number / Array / Date | '' | uncontrolled property。Typescript:`DateValue \| DateMultipleValue` ` type DateValue = string \| number \| Date ` ` type DateMultipleValue = Array `。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N +valueDisplay | TNode | - | `MouseEvent`。Typescript:`string \| TNode<{ value: DateValue; displayValue?: DateValue }>`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N valueType | String | - | Typescript:`DatePickerValueType` `type DatePickerValueType = 'time-stamp' \| 'Date' \| 'YYYY' \| 'YYYY-MM' \| 'YYYY-MM-DD' \| 'YYYY-MM-DD HH' \| 'YYYY-MM-DD HH:mm' \| 'YYYY-MM-DD HH:mm:ss' \| 'YYYY-MM-DD HH:mm:ss:SSS'` `type ValueTypeEnum = DatePickerValueType`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N onBlur | Function | | Typescript:`(context: { value: DateValue; e: FocusEvent }) => void`
| N onChange | Function | | Typescript:`(value: DateValue, context: { dayjsValue?: Dayjs, trigger?: DatePickerTriggerSource }) => void`
[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts)。
`import { Dayjs } from 'dayjs'`

`type DatePickerTriggerSource = 'confirm' \| 'pick' \| 'enter' \| 'preset' \| 'clear'`
| N @@ -49,15 +52,16 @@ className | String | - | className of component | N style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N allowInput | Boolean | false | \- | N borderless | Boolean | false | \- | N -cancelRangeSelectLimit | Boolean | false | The default date selection interaction is determined based on the order of dates clicked and will be restricted. For example, if a user first clicks on the start date input box and chooses a date, for instance, 2020-05-15, the interaction will automatically shift focus to the end date input box, waiting for the user to select the end time. At this point, the user can only select a date later than 2020-05-15 (previous dates will be grayed out and disabled, restricting the user's selection). When this value is set to `true`, this restriction is lifted. | N +cancelRangeSelectLimit | Boolean | false | The default date selection interaction is determined based on the order of dates clicked and will be restricted. For example, if a user first clicks on the start date input box and chooses a date, for instance, 2020-05-15, the interaction will automatically shift focus to the end date input box, waiting for the user to select the end time. At this point, the user can only select a date later than 2020-05-15 (previous dates will be grayed out and disabled, restricting the user's selection). When this value is set to `true`, this restriction is lifted | N clearable | Boolean | false | \- | N defaultTime | Array | ["00:00:00", "23:59:59"] | Time selector default value。Typescript:`string[]` | N disableDate | Object / Array / Function | - | Typescript:`DisableRangeDate` `type DisableRangeDate = Array \| DisableDateObj \| ((context: { date: DateRangeValue; partial: DateRangePickerPartial }) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }` `type DateRangePickerPartial = 'start' \| 'end'`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -disabled | Boolean | - | \- | N +disabled | Boolean | undefined | \- | N enableTimePicker | Boolean | false | \- | N firstDayOfWeek | Number | - | options: 1/2/3/4/5/6/7 | N format | String | - | \- | N mode | String | date | options: year/quarter/month/week/date | N +needConfirm | Boolean | true | whether a confirmation button needs to be clicked to complete the action in the date-time range picker scenario, default is true | N panelPreselection | Boolean | true | \- | N placeholder | String / Array | - | Typescript:`string \| Array` | N popupProps | Object | - | Typescript:`PopupProps`,[Popup API Documents](./popup?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N @@ -90,7 +94,7 @@ name | type | default | description | required className | String | - | className of component | N style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N defaultTime | String | '00:00:00' | Time selector default value | N -`Pick` | \- | - | extends `Pick` | N +`Pick` | \- | - | extends `Pick` | N onCellClick | Function | | Typescript:`(context: { date: Date, e: MouseEvent }) => void`
| N onChange | Function | | Typescript:`(value: DateValue, context: { dayjsValue?: Dayjs, e?: MouseEvent, trigger?: DatePickerTriggerSource }) => void`
| N onConfirm | Function | | Typescript:`(context: { date: Date, e: MouseEvent }) => void`
| N diff --git a/src/date-picker/date-picker.md b/src/date-picker/date-picker.md index 62a01b105b..c8b0cc00e4 100644 --- a/src/date-picker/date-picker.md +++ b/src/date-picker/date-picker.md @@ -13,25 +13,27 @@ borderless | Boolean | false | 无边框模式 | N clearable | Boolean | false | 是否显示清除按钮 | N defaultTime | String | '00:00:00' | 时间选择器默认值,当 value/defaultValue 未设置值时有效 | N disableDate | Object / Array / Function | - | 禁用日期,示例:['A', 'B'] 表示日期 A 和日期 B 会被禁用。`{ from: 'A', to: 'B' }` 表示在 A 到 B 之间的日期会被禁用。`{ before: 'A', after: 'B' }` 表示在 A 之前和在 B 之后的日期都会被禁用。其中 A = '2021-01-01',B = '2021-02-01'。值类型为 Function 则表示返回值为 true 的日期会被禁用。TS 类型:`DisableDate` `type DisableDate = Array \| DisableDateObj \| ((date: DateValue) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -disabled | Boolean | - | 是否禁用组件 | N +disabled | Boolean | undefined | 是否禁用组件 | N enableTimePicker | Boolean | false | 是否显示时间选择 | N firstDayOfWeek | Number | 7 | 第一天从星期几开始。可选项:1/2/3/4/5/6/7 | N format | String | 'YYYY-MM-DD' | 仅用于格式化日期显示的格式,不影响日期值。注意和 `valueType` 的区别,`valueType`会直接决定日期值 `value` 的格式。全局配置默认为:'YYYY-MM-DD',[详细文档](https://day.js.org/docs/en/display/format) | N inputProps | Object | - | 透传给输入框(Input)组件的参数。TS 类型:`InputProps`,[Input API Documents](./input?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N mode | String | date | 选择器模式。可选项:year/quarter/month/week/date | N +multiple | Boolean | false | 支持多选日期,但不支持在range-picker中,或与enableTimePicker、allowInput 一起使用。TS 类型:`boolean` | N needConfirm | Boolean | true | 决定在日期时间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为`true` | N placeholder | String / Array | undefined | 占位符。TS 类型:`string` | N popupProps | Object | - | 透传给 popup 组件的参数。TS 类型:`PopupProps`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N prefixIcon | TElement | - | 用于自定义组件前置图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N presets | Object | - | 预设快捷日期选择,示例:`{ '元旦': '2021-01-01', '昨天': dayjs().subtract(1, 'day').format('YYYY-MM-DD'), '特定日期': () => ['2021-02-01'] }`。TS 类型:`PresetDate` `interface PresetDate { [name: string]: DateValue \| (() => DateValue) }`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N presetsPlacement | String | bottom | 预设面板展示区域(包含确定按钮)。可选项:left/top/right/bottom | N +selectInputProps | Object | - | 透传 SelectInput 筛选器输入框组件的全部属性。TS 类型:`SelectInputProps`,[SelectInput API Documents](./select-input?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N size | String | medium | 输入框尺寸。可选项:small/medium/large。TS 类型:`SizeEnum`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N status | String | default | 输入框状态。可选项:default/success/warning/error | N suffixIcon | TElement | - | 用于自定义组件后置图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N timePickerProps | Object | - | 透传 TimePicker 组件属性。TS 类型:`TimePickerProps`,[TimePicker API Documents](./time-picker?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N tips | TNode | - | 输入框下方提示文本,会根据不同的 `status` 呈现不同的样式。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N -value | String / Number / Date | '' | 选中值。TS 类型:`DateValue` `type DateValue = string \| number \| Date`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -defaultValue | String / Number / Date | '' | 选中值。非受控属性。TS 类型:`DateValue` `type DateValue = string \| number \| Date`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N +value | String / Number / Array / Date | '' | 选中值。TS 类型:`DateValue \| DateMultipleValue` ` type DateValue = string \| number \| Date ` ` type DateMultipleValue = Array `。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N +defaultValue | String / Number / Array / Date | '' | 选中值。非受控属性。TS 类型:`DateValue \| DateMultipleValue` ` type DateValue = string \| number \| Date ` ` type DateMultipleValue = Array `。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N valueType | String | - | 用于格式化日期的值,仅支持部分格式,时间戳、日期等。⚠️ `YYYYMMDD` 这种格式不支持,请勿使用,如果希望支持可以给 `dayjs` 提个 PR。注意和 `format` 的区别,`format` 仅用于处理日期在页面中呈现的格式。`ValueTypeEnum` 即将废弃,请更为使用 `DatePickerValueType`。TS 类型:`DatePickerValueType` `type DatePickerValueType = 'time-stamp' \| 'Date' \| 'YYYY' \| 'YYYY-MM' \| 'YYYY-MM-DD' \| 'YYYY-MM-DD HH' \| 'YYYY-MM-DD HH:mm' \| 'YYYY-MM-DD HH:mm:ss' \| 'YYYY-MM-DD HH:mm:ss:SSS'` `type ValueTypeEnum = DatePickerValueType`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N onBlur | Function | | TS 类型:`(context: { value: DateValue; e: FocusEvent }) => void`
当输入框失去焦点时触发 | N onChange | Function | | TS 类型:`(value: DateValue, context: { dayjsValue?: Dayjs, trigger?: DatePickerTriggerSource }) => void`
选中值发生变化时触发。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts)。
`import { Dayjs } from 'dayjs'`

`type DatePickerTriggerSource = 'confirm' \| 'pick' \| 'enter' \| 'preset' \| 'clear'`
| N @@ -49,15 +51,16 @@ className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N allowInput | Boolean | false | 是否允许输入日期 | N borderless | Boolean | false | 无边框模式 | N -cancelRangeSelectLimit | Boolean | false | 默认的日期选择交互是根据点击前后日期的顺序来决定并且会加以限制。比如:用户先点击开始时间输入框,选择了一个日期例如2020-05-15,紧接着交互会自动将焦点跳到结束日期输入框,等待用户选择结束时间。此时用户只能选择大于2020-05-15的日期(之前的日期会被灰态禁止点击,限制用户的点击)。当该值传递`true`时,则取消该限制。 | N +cancelRangeSelectLimit | Boolean | false | 默认的日期选择交互是根据点击前后日期的顺序来决定并且会加以限制。比如:用户先点击开始时间输入框,选择了一个日期例如2020-05-15,紧接着交互会自动将焦点跳到结束日期输入框,等待用户选择结束时间。此时用户只能选择大于2020-05-15的日期(之前的日期会被灰态禁止点击,限制用户的点击)。当该值传递`true`时,则取消该限制 | N clearable | Boolean | false | 是否显示清除按钮 | N defaultTime | Array | ["00:00:00", "23:59:59"] | 时间选择器默认值,当 value/defaultValue 未设置值时有效。TS 类型:`string[]` | N disableDate | Object / Array / Function | - | 禁用日期,示例:['A', 'B'] 表示日期 A 和日期 B 会被禁用。{ from: 'A', to: 'B' } 表示在 A 到 B 之间的日期会被禁用。{ before: 'A', after: 'B' } 表示在 A 之前和在 B 之后的日期都会被禁用。其中 A = '2021-01-01',B = '2021-02-01'。值类型为 Function 则表示返回值为 true 的日期会被禁用。TS 类型:`DisableRangeDate` `type DisableRangeDate = Array \| DisableDateObj \| ((context: { date: DateRangeValue; partial: DateRangePickerPartial }) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }` `type DateRangePickerPartial = 'start' \| 'end'`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N -disabled | Boolean | - | 是否禁用组件 | N +disabled | Boolean | undefined | 是否禁用组件 | N enableTimePicker | Boolean | false | 是否显示时间选择 | N firstDayOfWeek | Number | - | 第一天从星期几开始。可选项:1/2/3/4/5/6/7 | N format | String | - | 用于格式化日期,[详细文档](https://day.js.org/docs/en/display/format) | N mode | String | date | 选择器模式。可选项:year/quarter/month/week/date | N +needConfirm | Boolean | true | 决定在日期时间区间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为 `true` | N panelPreselection | Boolean | true | 在开始日期选中之前,面板是否显示预选状态,即是否高亮预选日期 | N placeholder | String / Array | - | 占位符,值为数组表示可分别为开始日期和结束日期设置占位符。TS 类型:`string \| Array` | N popupProps | Object | - | 透传给 popup 组件的参数。TS 类型:`PopupProps`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N @@ -90,7 +93,7 @@ onPresetClick | Function | | TS 类型:`(context: { preset: PresetDate, e: Mo className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N defaultTime | String | '00:00:00' | 时间选择器默认值,当 value/defaultValue 未设置值时有效 | N -`Pick` | \- | - | 继承 `Pick` 中的全部属性 | N +`Pick` | \- | - | 继承 `Pick` 中的全部属性 | N onCellClick | Function | | TS 类型:`(context: { date: Date, e: MouseEvent }) => void`
点击日期单元格时触发 | N onChange | Function | | TS 类型:`(value: DateValue, context: { dayjsValue?: Dayjs, e?: MouseEvent, trigger?: DatePickerTriggerSource }) => void`
选中值发生变化时触发。参数 `context.trigger` 表示触发当前事件的来源,不同的模式触发来源也会不同 | N onConfirm | Function | | TS 类型:`(context: { date: Date, e: MouseEvent }) => void`
如果存在“确定”按钮,则点击“确定”按钮时触发 | N diff --git a/src/date-picker/defaultProps.ts b/src/date-picker/defaultProps.ts index bb653c3c90..c49214ade1 100644 --- a/src/date-picker/defaultProps.ts +++ b/src/date-picker/defaultProps.ts @@ -12,6 +12,7 @@ export const datePickerDefaultProps: TdDatePickerProps = { enableTimePicker: false, format: undefined, mode: 'date', + multiple: false, needConfirm: true, placeholder: undefined, presetsPlacement: 'bottom', @@ -28,6 +29,7 @@ export const dateRangePickerDefaultProps: TdDateRangePickerProps = { defaultTime: ['00:00:00', '23:59:59'], enableTimePicker: false, mode: 'date', + needConfirm: true, panelPreselection: true, presetsPlacement: 'bottom', size: 'medium', diff --git a/src/date-picker/hooks/useSingle.tsx b/src/date-picker/hooks/useSingle.tsx index 505a0d5866..c97d3d29d4 100644 --- a/src/date-picker/hooks/useSingle.tsx +++ b/src/date-picker/hooks/useSingle.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'; import { CalendarIcon as TdCalendarIcon } from 'tdesign-icons-react'; import dayjs from 'dayjs'; import classNames from 'classnames'; +import omit from 'lodash/omit'; import useConfig from '../../hooks/useConfig'; import useGlobalIcon from '../../hooks/useGlobalIcon'; import { TdDatePickerProps } from '../type'; @@ -24,7 +25,7 @@ export default function useSingleInput(props: TdDatePickerProps) { mode: props.mode, format: props.format, valueType: props.valueType, - enableTimePicker: props.enableTimePicker, + enableTimePicker: props.multiple ? false : props.enableTimePicker, }); const inputRef = useRef(); @@ -38,7 +39,7 @@ export default function useSingleInput(props: TdDatePickerProps) { const [inputValue, setInputValue] = useState(formatDate(value, { format })); // input 设置 - const inputProps = { + let inputProps: TdDatePickerProps['inputProps'] & { ref?: React.MutableRefObject } = { ...props.inputProps, ref: inputRef, size: props.size, @@ -99,7 +100,7 @@ export default function useSingleInput(props: TdDatePickerProps) { }; // popup 设置 - const popupProps = { + let popupProps = { expandAnimation: true, ...props.popupProps, trigger: 'mousedown' as TdPopupProps['trigger'], @@ -116,6 +117,24 @@ export default function useSingleInput(props: TdDatePickerProps) { }, }; + // tag-input 设置 + let tagInputProps = {}; + + // multiple + if (props.multiple) { + inputProps = omit(inputProps, ['ref', 'className', 'suffixIcon']); + + popupProps = { + ...popupProps, + trigger: 'click', + }; + + tagInputProps = { + clearable: props.clearable, + suffixIcon: props.suffixIcon ?? , + }; + } + // 输入框响应 value 变化 useEffect(() => { if (!value) { @@ -137,6 +156,7 @@ export default function useSingleInput(props: TdDatePickerProps) { popupVisible, inputProps, popupProps, + tagInputProps, inputRef, cacheValue, onChange, diff --git a/src/date-picker/hooks/useSingleValue.tsx b/src/date-picker/hooks/useSingleValue.tsx index 58faaedcaf..e1bdcecdb9 100644 --- a/src/date-picker/hooks/useSingleValue.tsx +++ b/src/date-picker/hooks/useSingleValue.tsx @@ -17,7 +17,7 @@ export default function useSingleValue(props: TdDatePickerProps) { const { format, timeFormat } = getDefaultFormat({ mode: props.mode, format: props.format, - enableTimePicker: props.enableTimePicker, + enableTimePicker: props.multiple ? false : props.enableTimePicker, }); if (props.enableTimePicker) { @@ -25,10 +25,12 @@ export default function useSingleValue(props: TdDatePickerProps) { log.error('DatePicker', `format: ${format} is invalid,time selection must include time formatting HH:mm:ss`); } - const [time, setTime] = useState(formatTime(value, format, timeFormat, props.defaultTime)); - const [month, setMonth] = useState(parseToDayjs(value, format).month()); - const [year, setYear] = useState(parseToDayjs(value, format).year()); - const [cacheValue, setCacheValue] = useState(formatDate(value, { format })); // 缓存选中值,panel 点击时更改 + const [time, setTime] = useState(() => + formatTime(props.multiple ? value[0] : value, format, timeFormat, props.defaultTime), + ); + const [month, setMonth] = useState(() => parseToDayjs(props.multiple ? value[0] : value, format).month()); + const [year, setYear] = useState(() => parseToDayjs(props.multiple ? value[0] : value, format).year()); + const [cacheValue, setCacheValue] = useState(() => formatDate(props.multiple ? value[0] : value, { format })); // 缓存选中值,panel 点击时更改 // 输入框响应 value 变化 useEffect(() => { diff --git a/src/date-picker/hooks/useTableData.tsx b/src/date-picker/hooks/useTableData.tsx index ea2887410d..8c14453431 100644 --- a/src/date-picker/hooks/useTableData.tsx +++ b/src/date-picker/hooks/useTableData.tsx @@ -3,7 +3,7 @@ import { getWeeks, getQuarters, getYears, getMonths, flagActive } from '../../_c import type { SinglePanelProps } from '../panel/SinglePanel'; export interface TableDataProps extends SinglePanelProps { - isRange?: Boolean; + isRange?: boolean; start: Date | undefined; end?: Date | undefined; hoverStart?: Date | undefined; @@ -32,6 +32,8 @@ export default function useTableData(props: TableDataProps) { minDate, maxDate, isRange, + value, + multiple, } = props; // 列表数据 @@ -61,5 +63,5 @@ export default function useTableData(props: TableDataProps) { data = getYears(year, options); } - return flagActive(data, { start, end, hoverStart, hoverEnd, type: mode, isRange }); + return flagActive(data, { start, end, hoverStart, hoverEnd, type: mode, isRange, value, multiple }); } diff --git a/src/date-picker/panel/ExtraContent.tsx b/src/date-picker/panel/ExtraContent.tsx index d992df5727..2159008c32 100644 --- a/src/date-picker/panel/ExtraContent.tsx +++ b/src/date-picker/panel/ExtraContent.tsx @@ -1,14 +1,14 @@ import React from 'react'; import DateFooter from '../base/Footer'; import type { SinglePanelProps } from './SinglePanel'; -import type { TdDatePickerProps, TdDateRangePickerProps, DateValue } from '../type'; +import type { TdDatePickerProps, TdDateRangePickerProps, DateValue, DateMultipleValue } from '../type'; export interface ExtraContentProps extends Pick< SinglePanelProps, 'enableTimePicker' | 'presetsPlacement' | 'onPresetClick' | 'onConfirmClick' | 'needConfirm' > { - selectedValue?: DateValue; + selectedValue?: DateValue | DateMultipleValue; presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; } diff --git a/src/date-picker/panel/RangePanel.tsx b/src/date-picker/panel/RangePanel.tsx index 33d73a258e..0158910331 100644 --- a/src/date-picker/panel/RangePanel.tsx +++ b/src/date-picker/panel/RangePanel.tsx @@ -4,13 +4,14 @@ import useConfig from '../../hooks/useConfig'; import { StyledProps } from '../../common'; import PanelContent from './PanelContent'; import ExtraContent from './ExtraContent'; -import { TdDateRangePickerProps } from '../type'; -import type { TdTimePickerProps } from '../../time-picker'; import { getDefaultFormat, parseToDayjs } from '../../_common/js/date-picker/format'; import useTableData from '../hooks/useTableData'; import useDisableDate from '../hooks/useDisableDate'; import useDefaultProps from '../../hooks/useDefaultProps'; +import type { TdDateRangePickerProps } from '../type'; +import type { TdTimePickerProps } from '../../time-picker'; + export interface RangePanelProps extends TdDateRangePickerProps, StyledProps { hoverValue?: string[]; activeIndex?: number; diff --git a/src/date-picker/panel/SinglePanel.tsx b/src/date-picker/panel/SinglePanel.tsx index cbe1ec423e..cd116167bb 100644 --- a/src/date-picker/panel/SinglePanel.tsx +++ b/src/date-picker/panel/SinglePanel.tsx @@ -58,11 +58,13 @@ const SinglePanel = forwardRef((originalProps, const disableDateOptions = useDisableDate({ disableDate: props.disableDate, mode: props.mode, format }); const tableData = useTableData({ + value, year, month, mode, - start: value ? parseToDayjs(value, format).toDate() : undefined, + start: value ? parseToDayjs(props.multiple ? value[0] : value, format).toDate() : undefined, firstDayOfWeek, + multiple: props.multiple, ...disableDateOptions, }); @@ -75,7 +77,7 @@ const SinglePanel = forwardRef((originalProps, firstDayOfWeek, tableData, popupVisible: props.popupVisible, - + multiple: props.multiple, time: props.time, timePickerProps: props.timePickerProps, enableTimePicker: props.enableTimePicker, diff --git a/src/date-picker/type.ts b/src/date-picker/type.ts index 9e2dd90eed..f061468427 100644 --- a/src/date-picker/type.ts +++ b/src/date-picker/type.ts @@ -6,6 +6,7 @@ import { InputProps } from '../input'; import { PopupProps } from '../popup'; +import { SelectInputProps } from '../select-input'; import { TimePickerProps } from '../time-picker'; import { Dayjs } from 'dayjs'; import { RangeInputProps } from '../range-input'; @@ -63,6 +64,11 @@ export interface TdDatePickerProps { * @default date */ mode?: 'year' | 'quarter' | 'month' | 'week' | 'date'; + /** + * 支持多选日期,但不支持在range-picker中,或与enableTimePicker、allowInput 一起使用 + * @default false + */ + multiple?: boolean; /** * 决定在日期时间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为`true` * @default true @@ -115,12 +121,12 @@ export interface TdDatePickerProps { * 选中值 * @default '' */ - value?: DateValue; + value?: DateValue | DateMultipleValue; /** * 选中值,非受控属性 * @default '' */ - defaultValue?: DateValue; + defaultValue?: DateValue | DateMultipleValue; /** * 用于格式化日期的值,仅支持部分格式,时间戳、日期等。⚠️ `YYYYMMDD` 这种格式不支持,请勿使用,如果希望支持可以给 `dayjs` 提个 PR。注意和 `format` 的区别,`format` 仅用于处理日期在页面中呈现的格式。`ValueTypeEnum` 即将废弃,请更为使用 `DatePickerValueType` * @default '' @@ -129,11 +135,14 @@ export interface TdDatePickerProps { /** * 当输入框失去焦点时触发 */ - onBlur?: (context: { value: DateValue; e: FocusEvent }) => void; + onBlur?: (context: { value: DateValue | DateMultipleValue; e: FocusEvent }) => void; /** * 选中值发生变化时触发 */ - onChange?: (value: DateValue, context: { dayjsValue?: Dayjs; trigger?: DatePickerTriggerSource }) => void; + onChange?: ( + value: DateValue | DateMultipleValue, + context: { dayjsValue?: Dayjs; trigger?: DatePickerTriggerSource }, + ) => void; /** * 如果存在“确定”按钮,则点击“确定”按钮时触发 */ @@ -141,7 +150,7 @@ export interface TdDatePickerProps { /** * 输入框获得焦点时触发 */ - onFocus?: (context: { value: DateValue; e: FocusEvent }) => void; + onFocus?: (context: { value: DateValue | DateMultipleValue; e: FocusEvent }) => void; /** * 面板选中值后触发 */ @@ -164,7 +173,7 @@ export interface TdDateRangePickerProps { */ borderless?: boolean; /** - * 默认的日期选择交互是根据点击前后日期的顺序来决定并且会加以限制。比如:用户先点击开始时间输入框,选择了一个日期例如2020-05-15,紧接着交互会自动将焦点跳到结束日期输入框,等待用户选择结束时间。此时用户只能选择大于2020-05-15的日期(之前的日期会被灰态禁止点击,限制用户的点击)。当该值传递`true`时,则取消该限制。 + * 默认的日期选择交互是根据点击前后日期的顺序来决定并且会加以限制。比如:用户先点击开始时间输入框,选择了一个日期例如2020-05-15,紧接着交互会自动将焦点跳到结束日期输入框,等待用户选择结束时间。此时用户只能选择大于2020-05-15的日期(之前的日期会被灰态禁止点击,限制用户的点击)。当该值传递`true`时,则取消该限制 * @default false */ cancelRangeSelectLimit?: boolean; @@ -495,6 +504,7 @@ export interface PresetDate { } export type DateValue = string | number | Date; +export type DateMultipleValue = Array; export type DatePickerValueType = | 'time-stamp' diff --git a/src/tag-input/TagInput.tsx b/src/tag-input/TagInput.tsx index 875080bd94..2dd097b912 100644 --- a/src/tag-input/TagInput.tsx +++ b/src/tag-input/TagInput.tsx @@ -100,7 +100,7 @@ const TagInput = forwardRef((originalProps, ref) => { const onInnerClick = (context: { e: MouseEvent }) => { if (!props.disabled && !props.readonly) { - (tagInputRef.current as any).inputElement?.focus?.(); + (tagInputRef.current as any)?.inputElement?.focus?.(); } onClick?.(context); }; diff --git a/src/tag-input/useTagScroll.ts b/src/tag-input/useTagScroll.ts index 50972810da..298e31a9f6 100644 --- a/src/tag-input/useTagScroll.ts +++ b/src/tag-input/useTagScroll.ts @@ -80,7 +80,7 @@ export default function useTagScroll(props: TdTagInputProps) { }; useEffect(() => { - initScroll(tagInputRef?.current.currentElement); + initScroll(tagInputRef?.current?.currentElement); return clearScroll; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index ab3516e646..79c65675b2 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -23089,7 +23089,7 @@ exports[`csr snapshot test > csr test src/color-picker/_example/enable-alpha.tsx - 单色 + Single
csr test src/color-picker/_example/panel.tsx 1`] = - 单色 + Single
csr test src/color-picker/_example/recent-color.tsx - 单色 + Single
csr test src/color-picker/_example/recent-color.tsx - 单色 + Single
csr test src/color-picker/_example/status-readonly. - 单色 + Single
csr test src/color-picker/_example/swatch-color.tsx - 单色 + Single
csr test src/color-picker/_example/swatch-color.tsx - 单色 + Single
csr test src/date-picker/_example/month.tsx 1`] = `
`; +exports[`csr snapshot test > csr test src/date-picker/_example/multiple.tsx 1`] = ` +
+
+
+
+
+
+
+
+ + 2000-01-04 + + + + +
+
+ + 2000-01-03 + + + + +
+
+ + 2000-01-05 + + + + +
+
+ + 可清除、可输入的日期选择器 + + + + + + +
+
+
+
+
+
+`; + exports[`csr snapshot test > csr test src/date-picker/_example/panel.tsx 1`] = `
ssr test src/date-picker/_example/first-day-of-week exports[`ssr snapshot test > ssr test src/date-picker/_example/month.tsx 1`] = `"
~
"`; +exports[`ssr snapshot test > ssr test src/date-picker/_example/multiple.tsx 1`] = `"
2000-01-04
2000-01-03
2000-01-05
可清除、可输入的日期选择器
"`; + exports[`ssr snapshot test > ssr test src/date-picker/_example/panel.tsx 1`] = `"
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
MonTueWedThuFriSatSun
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; exports[`ssr snapshot test > ssr test src/date-picker/_example/quarter.tsx 1`] = `"
~
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index 4f07598f48..b7303dcd26 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -292,6 +292,8 @@ exports[`ssr snapshot test > ssr test src/date-picker/_example/first-day-of-week exports[`ssr snapshot test > ssr test src/date-picker/_example/month.tsx 1`] = `"
~
"`; +exports[`ssr snapshot test > ssr test src/date-picker/_example/multiple.tsx 1`] = `"
2000-01-04
2000-01-03
2000-01-05
可清除、可输入的日期选择器
"`; + exports[`ssr snapshot test > ssr test src/date-picker/_example/panel.tsx 1`] = `"
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
MonTueWedThuFriSatSun
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
MonTueWedThuFriSatSun
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; exports[`ssr snapshot test > ssr test src/date-picker/_example/quarter.tsx 1`] = `"
~
"`;