From c621a2e7652fdcf2e6dc3646e0179530031c0c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kiner-tang=28=E6=96=87=E8=BE=89=29?= <1127031143@qq.com> Date: Sun, 2 Apr 2023 13:45:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A6=84=EF=B8=8F=20refactor(DatePicker?= =?UTF-8?q?,Calendar):=20dateRender,monthRender=20=3D>=20cellRender=20(#41?= =?UTF-8?q?584)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: dateRender => cellRender * feat: update snapshots * feat: update snapshots * docs: update docs * docs: update docs * docs: update docs * docs: update docs * feat: update test case * docs: update docs * feat: optimize code * feat: optimize code * feat: update test case * feat: update test case --- components/calendar/__tests__/index.test.tsx | 61 ++++++++++++++++ components/calendar/demo/notice-calendar.tsx | 9 ++- components/calendar/generateCalendar.tsx | 72 ++++++++++++++++--- components/calendar/index.zh-CN.md | 12 ++-- .../__snapshots__/demo-extend.test.ts.snap | 2 +- .../__snapshots__/demo.test.tsx.snap | 2 +- components/date-picker/demo/cell-render.md | 7 ++ .../demo/{date-render.tsx => cell-render.tsx} | 6 +- components/date-picker/demo/date-render.md | 7 -- components/date-picker/index.en-US.md | 9 +-- components/date-picker/index.zh-CN.md | 9 +-- package.json | 2 +- 12 files changed, 162 insertions(+), 36 deletions(-) create mode 100644 components/date-picker/demo/cell-render.md rename components/date-picker/demo/{date-render.tsx => cell-render.tsx} (93%) delete mode 100644 components/date-picker/demo/date-render.md diff --git a/components/calendar/__tests__/index.test.tsx b/components/calendar/__tests__/index.test.tsx index a41fd78020..16fe4c8ced 100644 --- a/components/calendar/__tests__/index.test.tsx +++ b/components/calendar/__tests__/index.test.tsx @@ -4,6 +4,7 @@ import MockDate from 'mockdate'; import { type PickerPanelProps } from 'rc-picker'; import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs'; import type { Locale } from 'rc-picker/lib/interface'; +import { resetWarned } from 'rc-util/lib/warning'; import React from 'react'; import Calendar from '..'; import mountTest from '../../../tests/shared/mountTest'; @@ -462,6 +463,20 @@ describe('Calendar', () => { expect(container.querySelectorAll('.bamboo')[0].innerHTML).toEqual('Light'); }); + it('fullCellRender in date', () => { + const { container } = render( +
Bamboo
} />, + ); + expect(container.querySelectorAll('.light')[0].innerHTML).toEqual('Bamboo'); + }); + + it('fullCellRender in month', () => { + const { container } = render( +
Light
} />, + ); + expect(container.querySelectorAll('.bamboo')[0].innerHTML).toEqual('Light'); + }); + it('when fullscreen is false, the element returned by dateFullCellRender should be interactive', () => { const onClick = jest.fn(); const { container } = render( @@ -477,4 +492,50 @@ describe('Calendar', () => { fireEvent.click(container.querySelectorAll('.bamboo')[0]); expect(onClick).toHaveBeenCalled(); }); + + it('deprecated dateCellRender and monthCellRender', () => { + resetWarned(); + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const { container } = render( +
Light
} + monthCellRender={() =>
Bar
} + />, + ); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Calendar] `monthCellRender` is deprecated. Please use `cellRender` instead.', + ); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Calendar] `dateCellRender` is deprecated. Please use `cellRender` instead.', + ); + + expect(container.querySelector('.bamboo')).toBeTruthy(); + + fireEvent.click(Array.from(container.querySelectorAll(`.ant-radio-button-input`)).at(1)!); + expect(container.querySelector('.bar')).toBeTruthy(); + errSpy.mockRestore(); + }); + + it('deprecated dateFullCellRender and monthFullCellRender', () => { + resetWarned(); + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const { container } = render( +
Light
} + monthFullCellRender={() =>
Bar
} + />, + ); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Calendar] `dateFullCellRender` is deprecated. Please use `fullCellRender` instead.', + ); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Calendar] `monthFullCellRender` is deprecated. Please use `fullCellRender` instead.', + ); + expect(container.querySelector('.bamboo')).toBeTruthy(); + fireEvent.click(Array.from(container.querySelectorAll(`.ant-radio-button-input`)).at(1)!); + expect(container.querySelector('.bar')).toBeTruthy(); + errSpy.mockRestore(); + }); }); diff --git a/components/calendar/demo/notice-calendar.tsx b/components/calendar/demo/notice-calendar.tsx index 77ad053002..df4c769684 100644 --- a/components/calendar/demo/notice-calendar.tsx +++ b/components/calendar/demo/notice-calendar.tsx @@ -2,6 +2,7 @@ import React from 'react'; import type { BadgeProps } from 'antd'; import { Badge, Calendar } from 'antd'; import type { Dayjs } from 'dayjs'; +import type { CellRenderInfo } from 'rc-picker/lib/interface'; const getListData = (value: Dayjs) => { let listData; @@ -64,7 +65,13 @@ const App: React.FC = () => { ); }; - return ; + const cellRender = (current: Dayjs, info: CellRenderInfo) => { + if (info.type === 'date') return dateCellRender(current); + if (info.type === 'month') return monthCellRender(current); + return info.originNode; + }; + + return ; }; export default App; diff --git a/components/calendar/generateCalendar.tsx b/components/calendar/generateCalendar.tsx index ae8fbe595e..278a91253f 100644 --- a/components/calendar/generateCalendar.tsx +++ b/components/calendar/generateCalendar.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; import { PickerPanel as RCPickerPanel } from 'rc-picker'; import type { GenerateConfig } from 'rc-picker/lib/generate'; -import type { Locale } from 'rc-picker/lib/interface'; +import type { CellRenderInfo } from 'rc-picker/lib/interface'; import type { PickerPanelBaseProps as RCPickerPanelBaseProps, PickerPanelDateProps as RCPickerPanelDateProps, @@ -15,6 +15,7 @@ import CalendarHeader from './Header'; import enUS from './locale/en_US'; import useStyle from './style'; +import warning from '../_util/warning'; type InjectDefaultProps = Omit< Props, @@ -50,10 +51,16 @@ export interface CalendarProps { locale?: typeof enUS; validRange?: [DateType, DateType]; disabledDate?: (date: DateType) => boolean; + /** @deprecated Please use fullCellRender instead. */ dateFullCellRender?: (date: DateType) => React.ReactNode; + /** @deprecated Please use cellRender instead. */ dateCellRender?: (date: DateType) => React.ReactNode; + /** @deprecated Please use fullCellRender instead. */ monthFullCellRender?: (date: DateType) => React.ReactNode; + /** @deprecated Please use cellRender instead. */ monthCellRender?: (date: DateType) => React.ReactNode; + cellRender?: (date: DateType, info: CellRenderInfo) => React.ReactNode; + fullCellRender?: (date: DateType, info: CellRenderInfo) => React.ReactNode; headerRender?: HeaderRender; value?: DateType; defaultValue?: DateType; @@ -91,6 +98,8 @@ function generateCalendar(generateConfig: GenerateConfig) { dateCellRender, monthFullCellRender, monthCellRender, + cellRender, + fullCellRender, headerRender, value, defaultValue, @@ -110,6 +119,30 @@ function generateCalendar(generateConfig: GenerateConfig) { const today = generateConfig.getNow(); + // ====================== Warning ======================= + if (process.env.NODE_ENV !== 'production') { + warning( + !dateFullCellRender, + 'Calendar', + '`dateFullCellRender` is deprecated. Please use `fullCellRender` instead.', + ); + warning( + !dateCellRender, + 'Calendar', + '`dateCellRender` is deprecated. Please use `cellRender` instead.', + ); + warning( + !monthFullCellRender, + 'Calendar', + '`monthFullCellRender` is deprecated. Please use `fullCellRender` instead.', + ); + warning( + !monthCellRender, + 'Calendar', + '`monthCellRender` is deprecated. Please use `cellRender` instead.', + ); + } + // ====================== State ======================= // Value @@ -187,7 +220,10 @@ function generateCalendar(generateConfig: GenerateConfig) { // ====================== Render ====================== const dateRender = React.useCallback( - (date: DateType): React.ReactNode => { + (date: DateType, info: CellRenderInfo): React.ReactNode => { + if (fullCellRender) { + return fullCellRender(date, info); + } if (dateFullCellRender) { return dateFullCellRender(date); } @@ -202,21 +238,25 @@ function generateCalendar(generateConfig: GenerateConfig) { {String(generateConfig.getDate(date)).padStart(2, '0')}
- {dateCellRender && dateCellRender(date)} + {cellRender ? cellRender(date, info) : dateCellRender && dateCellRender(date)}
); }, - [dateFullCellRender, dateCellRender], + [dateFullCellRender, dateCellRender, cellRender, fullCellRender], ); const monthRender = React.useCallback( - (date: DateType, locale: Locale): React.ReactNode => { + (date: DateType, info: CellRenderInfo): React.ReactNode => { + if (fullCellRender) { + return fullCellRender(date, info); + } if (monthFullCellRender) { return monthFullCellRender(date); } - const months = locale.shortMonths || generateConfig.locale.getShortMonths!(locale.locale); + const months = + info.locale!.shortMonths || generateConfig.locale.getShortMonths!(info.locale!.locale); return (
(generateConfig: GenerateConfig) { {months[generateConfig.getMonth(date)]}
- {monthCellRender && monthCellRender(date)} + {cellRender ? cellRender(date, info) : monthCellRender && monthCellRender(date)}
); }, - [monthFullCellRender, monthCellRender], + [monthFullCellRender, monthCellRender, cellRender, fullCellRender], ); const [contextLocale] = useLocale('Calendar', getDefaultLocale); + const mergedCellRender = (current: DateType, info: CellRenderInfo) => { + if (info.type === 'date') { + return dateRender(current, info); + } + + if (info.type === 'month') { + return monthRender(current, { + ...info, + locale: contextLocale?.lang, + }); + } + }; + return wrapSSR(
(generateConfig: GenerateConfig) { prefixCls={prefixCls} locale={contextLocale?.lang} generateConfig={generateConfig} - dateRender={dateRender} - monthCellRender={(date) => monthRender(date, contextLocale?.lang)} + cellRender={mergedCellRender} onSelect={onInternalSelect} mode={panelMode} picker={panelMode} diff --git a/components/calendar/index.zh-CN.md b/components/calendar/index.zh-CN.md index d50cf4a36f..83e78a1041 100644 --- a/components/calendar/index.zh-CN.md +++ b/components/calendar/index.zh-CN.md @@ -42,16 +42,20 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*-p-wQLik200AAA | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | -| dateCellRender | 自定义渲染日期单元格,返回内容会被追加到单元格 | function(date: Dayjs): ReactNode | - | | -| dateFullCellRender | 自定义渲染日期单元格,返回内容覆盖单元格 | function(date: Dayjs): ReactNode | - | | +| dateCellRender | 自定义渲染日期单元格,返回内容会被追加到单元格,>= 5.4.0 请用 `cellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 | +| cellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | +| dateFullCellRender | 自定义渲染日期单元格,返回内容覆盖单元格,>= 5.4.0 请用 `fullCellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 | +| fullCellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | defaultValue | 默认展示的日期 | [dayjs](https://day.js.org/) | - | | | disabledDate | 不可选择的日期,参数为当前 `value`,注意使用时[不要直接修改](https://github.com/ant-design/ant-design/issues/30987) | (currentDate: Dayjs) => boolean | - | | | fullscreen | 是否全屏显示 | boolean | true | | | headerRender | 自定义头部内容 | function(object:{value: Dayjs, type: string, onChange: f(), onTypeChange: f()}) | - | | | locale | 国际化配置 | object | [(默认配置)](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | | | mode | 初始模式 | `month` \| `year` | `month` | | -| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格 | function(date: Dayjs): ReactNode | - | | -| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格 | function(date: Dayjs): ReactNode | - | | +| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格,>= 5.4.0 请用 `cellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 | +| cellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | +| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格,>= 5.4.0 请用 `fullCellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 | +| fullCellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | validRange | 设置可以显示的日期 | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | | | value | 展示日期 | [dayjs](https://day.js.org/) | - | | | onChange | 日期变化回调 | function(date: Dayjs) | - | | diff --git a/components/date-picker/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/date-picker/__tests__/__snapshots__/demo-extend.test.ts.snap index a482161be7..6138a5ef56 100644 --- a/components/date-picker/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/date-picker/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -7088,7 +7088,7 @@ exports[`renders components/date-picker/demo/bordered.tsx extend context correct
`; -exports[`renders components/date-picker/demo/date-render.tsx extend context correctly 1`] = ` +exports[`renders components/date-picker/demo/cell-render.tsx extend context correctly 1`] = `
diff --git a/components/date-picker/__tests__/__snapshots__/demo.test.tsx.snap b/components/date-picker/__tests__/__snapshots__/demo.test.tsx.snap index c17594d337..2817dec62c 100644 --- a/components/date-picker/__tests__/__snapshots__/demo.test.tsx.snap +++ b/components/date-picker/__tests__/__snapshots__/demo.test.tsx.snap @@ -752,7 +752,7 @@ exports[`renders components/date-picker/demo/bordered.tsx correctly 1`] = `
`; -exports[`renders components/date-picker/demo/date-render.tsx correctly 1`] = ` +exports[`renders components/date-picker/demo/cell-render.tsx correctly 1`] = `
diff --git a/components/date-picker/demo/cell-render.md b/components/date-picker/demo/cell-render.md new file mode 100644 index 0000000000..a11c4e9e7a --- /dev/null +++ b/components/date-picker/demo/cell-render.md @@ -0,0 +1,7 @@ +## zh-CN + +使用 `cellRender` 可以自定义单元格的内容和样式。 + +## en-US + +We can customize the rendering of the cells in the calendar by providing a `cellRender` function to `DatePicker`. diff --git a/components/date-picker/demo/date-render.tsx b/components/date-picker/demo/cell-render.tsx similarity index 93% rename from components/date-picker/demo/date-render.tsx rename to components/date-picker/demo/cell-render.tsx index 792076ecf3..b3d471410c 100644 --- a/components/date-picker/demo/date-render.tsx +++ b/components/date-picker/demo/cell-render.tsx @@ -1,12 +1,12 @@ -import React from 'react'; import { DatePicker, Space } from 'antd'; +import React from 'react'; const { RangePicker } = DatePicker; const App: React.FC = () => ( { + cellRender={(current) => { const style: React.CSSProperties = {}; if (current.date() === 1) { style.border = '1px solid #1890ff'; @@ -20,7 +20,7 @@ const App: React.FC = () => ( }} /> { + cellRender={(current) => { const style: React.CSSProperties = {}; if (current.date() === 1) { style.border = '1px solid #1890ff'; diff --git a/components/date-picker/demo/date-render.md b/components/date-picker/demo/date-render.md deleted file mode 100644 index e3e2ab3ede..0000000000 --- a/components/date-picker/demo/date-render.md +++ /dev/null @@ -1,7 +0,0 @@ -## zh-CN - -使用 `dateRender` 可以自定义日期单元格的内容和样式。 - -## en-US - -We can customize the rendering of date cells in the calendar by providing a `dateRender` function to `DatePicker`. diff --git a/components/date-picker/index.en-US.md b/components/date-picker/index.en-US.md index bc0e9725d6..57374b060c 100644 --- a/components/date-picker/index.en-US.md +++ b/components/date-picker/index.en-US.md @@ -27,7 +27,7 @@ By clicking the input box, you can select a date from a popup calendar. Preset Ranges Extra Footer Three Sizes -Customized Date Rendering +Customized Cell Rendering Status Bordered-less Placement @@ -81,7 +81,8 @@ The following APIs are shared by DatePicker, RangePicker. | autoFocus | If get focus when component mounted | boolean | false | | | bordered | Whether has border style | boolean | true | | | className | The picker className | string | - | | -| dateRender | Custom rendering function for date cells | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | | +| dateRender | Custom rendering function for date cells, >= 5.4.0 use `cellRender` instead. | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | < 5.4.0 | +| cellRender | Custom rendering function for picker cells | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | disabled | Determine whether the DatePicker is disabled | boolean | false | | | disabledDate | Specify the date that cannot be selected | (currentDate: dayjs) => boolean | - | | | format | To set the date format, support multi-format matching when it is an array, display the first one shall prevail. refer to [dayjs#format](https://day.js.org/docs/en/display/format). for example: [Custom Format](#components-date-picker-demo-format) | [formatType](#formattype) | [rc-picker](https://github.com/react-component/picker/blob/f512f18ed59d6791280d1c3d7d37abbb9867eb0b/src/utils/uiUtil.ts#L155-L177) | | @@ -164,7 +165,6 @@ Added in `4.1.0`. | defaultPickerValue | To set default picker date | [dayjs](https://day.js.org/) | - | | | defaultValue | To set default date | [dayjs](https://day.js.org/) | - | | | format | To set the date format. refer to [dayjs#format](https://day.js.org/docs/en/display/format) | [formatType](#formattype) | `YYYY-MM` | | -| monthCellRender | Custom month cell content render method | function(date, locale): ReactNode | - | | | renderExtraFooter | Render extra footer in panel | () => React.ReactNode | - | | | value | To set date | [dayjs](https://day.js.org/) | - | | | onChange | Callback function, can be executed when the selected time is changing | function(date: dayjs, dateString: string) | - | | @@ -185,7 +185,8 @@ Added in `4.1.0`. | Property | Description | Type | Default | Version | | --- | --- | --- | --- | --- | | allowEmpty | Allow start or end input leave empty | \[boolean, boolean] | \[false, false] | | -| dateRender | Customize date cell. `info` argument is added in 4.3.0 | function(currentDate: dayjs, today: dayjs, info: { range: `start` \| `end` }) => React.ReactNode | - | | +| dateRender | Custom rendering function for date cells, >= 5.4.0 use `cellRender` instead. | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | < 5.4.0 | +| cellRender | Custom rendering function for picker cells | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | defaultPickerValue | To set default picker date | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | | | defaultValue | To set default date | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | | | disabled | If disable start or end | \[boolean, boolean] | - | | diff --git a/components/date-picker/index.zh-CN.md b/components/date-picker/index.zh-CN.md index 9fc993d0cb..fb4f05e2bc 100644 --- a/components/date-picker/index.zh-CN.md +++ b/components/date-picker/index.zh-CN.md @@ -28,7 +28,7 @@ demo: 预设范围 额外的页脚 三种大小 -定制日期单元格 +定制单元格 自定义状态 无边框 弹出位置 @@ -82,7 +82,8 @@ import locale from 'antd/locale/zh_CN'; | autoFocus | 自动获取焦点 | boolean | false | | | bordered | 是否有边框 | boolean | true | | | className | 选择器 className | string | - | | -| dateRender | 自定义日期单元格的内容 | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | | +| dateRender | 自定义日期单元格的内容,5.4.0 起用 `cellRender` 代替 | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | < 5.4.0 | +| cellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | disabled | 禁用 | boolean | false | | | disabledDate | 不可选择的日期 | (currentDate: dayjs) => boolean | - | | | format | 设置日期格式,为数组时支持多格式匹配,展示以第一个为准。配置参考 [dayjs#format](https://day.js.org/docs/zh-CN/display/format#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%8D%A0%E4%BD%8D%E7%AC%A6%E5%88%97%E8%A1%A8)。示例:[自定义格式](#components-date-picker-demo-format) | [formatType](#formattype) | [rc-picker](https://github.com/react-component/picker/blob/f512f18ed59d6791280d1c3d7d37abbb9867eb0b/src/utils/uiUtil.ts#L155-L177) | | @@ -165,7 +166,6 @@ import locale from 'antd/locale/zh_CN'; | defaultPickerValue | 默认面板日期 | [dayjs](https://day.js.org/) | - | | | defaultValue | 默认日期 | [dayjs](https://day.js.org/) | - | | | format | 展示的日期格式,配置参考 [dayjs#format](https://day.js.org/docs/zh-CN/display/format#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%8D%A0%E4%BD%8D%E7%AC%A6%E5%88%97%E8%A1%A8)。 | [formatType](#formattype) | `YYYY-MM` | | -| monthCellRender | 自定义的月份内容渲染方法 | function(date, locale): ReactNode | - | | | renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - | | | value | 日期 | [dayjs](https://day.js.org/) | - | | | onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: dayjs, dateString: string) | - | | @@ -186,7 +186,8 @@ import locale from 'antd/locale/zh_CN'; | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | allowEmpty | 允许起始项部分为空 | \[boolean, boolean] | \[false, false] | | -| dateRender | 自定义日期单元格的内容。`info` 参数自 4.3.0 添加 | function(currentDate: dayjs, today: dayjs, info: { range: `start` \| `end` }) => React.ReactNode | - | | +| dateRender | 自定义日期单元格的内容,5.4.0 起用 `cellRender` 代替 | function(currentDate: dayjs, today: dayjs) => React.ReactNode | - | < 5.4.0 | +| cellRender | 自定义单元格的内容。 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 | | defaultPickerValue | 默认面板日期 | [dayjs](https://day.js.org/)\[] | - | | | defaultValue | 默认日期 | [dayjs](https://day.js.org/)\[] | - | | | disabled | 禁用起始项 | \[boolean, boolean] | - | | diff --git a/package.json b/package.json index c667460321..1971b5c75b 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "rc-motion": "^2.6.1", "rc-notification": "~5.0.0", "rc-pagination": "~3.3.1", - "rc-picker": "~3.3.4", + "rc-picker": "~3.5.0", "rc-progress": "~3.4.1", "rc-rate": "~2.10.0", "rc-resize-observer": "^1.2.0", From 512374734aef30cfa5b5be7a09162dbc472bfa5a Mon Sep 17 00:00:00 2001 From: Amumu Date: Mon, 3 Apr 2023 10:03:22 +0800 Subject: [PATCH 2/3] test: fix lint error (#41596) (#41600) * test: fix lint error * chore: fix lint --------- --- scripts/check-cssinjs.js | 3 +-- scripts/collect-token-statistic.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/check-cssinjs.js b/scripts/check-cssinjs.js index 93feaa256c..45b1b853d5 100644 --- a/scripts/check-cssinjs.js +++ b/scripts/check-cssinjs.js @@ -1,5 +1,4 @@ /* eslint-disable import/no-unresolved,no-console,global-require,import/no-dynamic-require */ - const chalk = require('chalk'); const React = require('react'); const ReactDOMServer = require('react-dom/server'); @@ -30,7 +29,7 @@ const EmptyElement = React.createElement('div'); const styleFiles = glob.globSync( path.join( process.cwd(), - 'components/!(version|config-provider|icon|auto-complete|col|row|time-picker|)/style/index.?(ts|tsx)', + 'components/!(version|config-provider|icon|auto-complete|col|row|time-picker)/style/index.?(ts|tsx)', ), ); diff --git a/scripts/collect-token-statistic.js b/scripts/collect-token-statistic.js index 7a204fe4ac..8a204ccc81 100644 --- a/scripts/collect-token-statistic.js +++ b/scripts/collect-token-statistic.js @@ -18,7 +18,7 @@ const EmptyElement = React.createElement('div'); const styleFiles = glob.globSync( path.join( process.cwd(), - 'components/!(version|config-provider|icon|auto-complete|col|row|time-picker|)/style/index.?(ts|tsx)', + 'components/!(version|config-provider|icon|auto-complete|col|row|time-picker)/style/index.?(ts|tsx)', ), ); From e3e71dfeda3d8dee3aaaae62d96e2cb704221f82 Mon Sep 17 00:00:00 2001 From: Sylvain Boulade Date: Mon, 3 Apr 2023 04:11:42 +0200 Subject: [PATCH 3/3] feat: Picker luxon support (#41580) * chore: add luxon english documentation * chore: add draft chinese documentation This documentation was auto-generated based on the english version so it is only a rough draft and will most likely need to be refined. * fix: improve documentation phrasing --- docs/react/use-custom-date-library.en-US.md | 66 ++++++++++++++++++--- docs/react/use-custom-date-library.zh-CN.md | 64 ++++++++++++++++++-- 2 files changed, 117 insertions(+), 13 deletions(-) diff --git a/docs/react/use-custom-date-library.en-US.md b/docs/react/use-custom-date-library.en-US.md index 7fa4abebe4..e14810090b 100644 --- a/docs/react/use-custom-date-library.en-US.md +++ b/docs/react/use-custom-date-library.en-US.md @@ -3,9 +3,9 @@ order: 7.5 title: Use custom date library --- -By default, Ant Design use [Day.js](https://day.js.org) to handle time and date. Day.js is an immutable date-time library alternative to Moment.js with the same API. +By default, Ant Design uses [Day.js](https://day.js.org) to handle time and date. Day.js is an immutable date-time library alternative to Moment.js with the same API. -You might want to use another date library (**Ant design currently supports [moment](http://momentjs.com/) and [date-fns](https://date-fns.org)**). We provide two ways to customize: +You might want to use another date library (**Ant design currently supports [moment](http://momentjs.com/), [date-fns](https://date-fns.org), and [luxon](https://moment.github.io/luxon/)**). We provide two ways to customize: ## Custom component @@ -20,9 +20,9 @@ Create `src/components/DatePicker.tsx`. For example: ```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; import type { Moment } from 'moment'; import momentGenerateConfig from 'rc-picker/lib/generate/moment'; -import generatePicker from 'antd/es/date-picker/generatePicker'; const DatePicker = generatePicker(momentGenerateConfig); @@ -36,9 +36,9 @@ Create `src/components/TimePicker.tsx`. For example: ```tsx +import type { PickerTimeProps } from 'antd/es/date-picker/generatePicker'; import type { Moment } from 'moment'; import * as React from 'react'; -import type { PickerTimeProps } from 'antd/es/date-picker/generatePicker'; import DatePicker from './DatePicker'; export interface TimePickerProps extends Omit, 'picker'> {} @@ -59,9 +59,9 @@ Create `src/components/Calendar.tsx`. For example: ```tsx +import generateCalendar from 'antd/es/calendar/generateCalendar'; import type { Moment } from 'moment'; import momentGenerateConfig from 'rc-picker/lib/generate/moment'; -import generateCalendar from 'antd/es/calendar/generateCalendar'; const Calendar = generateCalendar(momentGenerateConfig); @@ -75,8 +75,8 @@ Create `src/components/index.tsx`. For example: ```tsx -export { default as DatePicker } from './DatePicker'; export { default as Calendar } from './Calendar'; +export { default as DatePicker } from './DatePicker'; export { default as TimePicker } from './TimePicker'; ``` @@ -119,11 +119,63 @@ Create `src/components/DatePicker.tsx`. Code as follows: ```tsx -import dateFnsGenerateConfig from 'rc-picker/lib/generate/dateFns'; import generatePicker from 'antd/es/date-picker/generatePicker'; import 'antd/es/date-picker/style/index'; +import dateFnsGenerateConfig from 'rc-picker/lib/generate/dateFns'; const DatePicker = generatePicker(dateFnsGenerateConfig); export default DatePicker; ``` + +## Use luxon + +Since `antd 5.4.0`, [luxon](https://moment.github.io/luxon/) can be used instead of `dayjs` and supports the same functionality, but it does introduce some differences in behavior that we will explain below. + +### Implementation + +Create a `src/components/DatePicker.tsx` file, and implement the luxon based picker as follows: + +```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; +import 'antd/es/date-picker/style/index'; +import type { DateTime } from 'luxon'; +import luxonGenerateConfig from 'rc-picker/lib/generate/luxon'; + +const DatePicker = generatePicker(luxonGenerateConfig); + +export default DatePicker; +``` + +### Notable differences with day-js + +luxon users should be familiar with the fact that it does not come with a custom implementation for localization. Instead, it relies on the browser's native [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). + +This introduces some formatting differences with the other date libraries. As of today, the main differences are: + +- First day of the week is always Monday regardless of locale. +- Week of year number is sometimes different (ISO week rules are used to determine it). +- Short week days format will sometimes be different for custom locales (it might have 3 characters instead of 2). +- Selected week label format will be slightly different (e.g. "2021-01" instead of "2021-1st"). + +It is possible to customize these default luxon behaviors by adjusting the luxon config: + +```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; +import 'antd/es/date-picker/style/index'; +import type { DateTime } from 'luxon'; +import luxonGenerateConfig from 'rc-picker/lib/generate/luxon'; + +const customLuxonConfig = { + ...luxonGenerateConfig, + getWeekFirstDay: (locale) => { + // Your custom implementation goes here + }, +}; + +const DatePicker = generatePicker(customLuxonConfig); + +export default DatePicker; +``` + +Note that by doing such customization, the resulting DatePicker behavior might be altered in unexpected ways, so make sure you are testing for edge cases. diff --git a/docs/react/use-custom-date-library.zh-CN.md b/docs/react/use-custom-date-library.zh-CN.md index 7255e549ee..be57d35883 100644 --- a/docs/react/use-custom-date-library.zh-CN.md +++ b/docs/react/use-custom-date-library.zh-CN.md @@ -3,7 +3,7 @@ order: 7.5 title: 使用自定义日期库 --- -Ant Design 默认使用 [Day.js](https://day.js.org) 来处理时间日期问题。Day.js 相比于 moment 使用了不可变数据结构,性能更快,体积仅 2KB,API 设计完全一致。你可以很方便的改用其他自定义日期库如([moment](http://momentjs.com/)、[date-fns](https://date-fns.org))。在这里我们提供了两种方式来实现替换: +Ant Design 默认使用 [Day.js](https://day.js.org) 来处理时间日期问题。Day.js 相比于 moment 使用了不可变数据结构,性能更快,体积仅 2KB,API 设计完全一致。你可以很方便的改用其他自定义日期库如([moment](http://momentjs.com/)、[date-fns](https://date-fns.org)、[luxon](https://moment.github.io/luxon/))。在这里我们提供了两种方式来实现替换: ## 自定义组件 @@ -18,9 +18,9 @@ Ant Design 默认使用 [Day.js](https://day.js.org) 来处理时间日期问题 编写如下代码: ```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; import type { Moment } from 'moment'; import momentGenerateConfig from 'rc-picker/es/generate/moment'; -import generatePicker from 'antd/es/date-picker/generatePicker'; const DatePicker = generatePicker(momentGenerateConfig); @@ -34,9 +34,9 @@ export default DatePicker; 编写如下代码: ```tsx +import type { PickerTimeProps } from 'antd/es/date-picker/generatePicker'; import type { Moment } from 'moment'; import * as React from 'react'; -import type { PickerTimeProps } from 'antd/es/date-picker/generatePicker'; import DatePicker from './DatePicker'; export interface TimePickerProps extends Omit, 'picker'> {} @@ -57,9 +57,9 @@ export default TimePicker; 编写如下代码: ```tsx +import generateCalendar from 'antd/es/calendar/generateCalendar'; import type { Moment } from 'moment'; import momentGenerateConfig from 'rc-picker/es/generate/moment'; -import generateCalendar from 'antd/es/calendar/generateCalendar'; const Calendar = generateCalendar(momentGenerateConfig); @@ -73,8 +73,8 @@ export default Calendar; 编写如下代码: ```tsx -export { default as DatePicker } from './DatePicker'; export { default as Calendar } from './Calendar'; +export { default as DatePicker } from './DatePicker'; export { default as TimePicker } from './TimePicker'; ``` @@ -117,11 +117,63 @@ module.exports = { 编写如下代码: ```tsx -import dateFnsGenerateConfig from 'rc-picker/es/generate/dateFns'; import generatePicker from 'antd/es/date-picker/generatePicker'; import 'antd/es/date-picker/style/index'; +import dateFnsGenerateConfig from 'rc-picker/es/generate/dateFns'; const DatePicker = generatePicker(dateFnsGenerateConfig); export default DatePicker; ``` + +## 使用 luxon + +可以使用 [luxon](https://moment.github.io/luxon/) 代替 dayjs 并支持同样的功能,但它与 dayjs 有一些差异,我们将在下面解释: + +### 执行 + +创建一个 `DatePicker.tsx` 文件,并定义一个基于 luxon 的 DatePicker 组件: + +```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; +import 'antd/es/date-picker/style/index'; +import type { DateTime } from 'luxon'; +import luxonGenerateConfig from 'rc-picker/lib/generate/luxon'; + +const DatePicker = generatePicker(luxonGenerateConfig); + +export default DatePicker; +``` + +### 与 day.js 的差异 + +luxon 用户应该悉知,它不附带用于本地化的自定义实现。 相反,它依赖于浏览器的本机 [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)。 + +这导致了与其他日期库的一些差异, 主要区别是: + +- 无论语言环境如何,一周的第一天总是星期一。 +- 一年中的周数有时不同(ISO 周规则用于确定它)。 +- 短工作日格式有时会因自定义区域而异(可能有 3 个字符而不是 2 个)。 +- 选定的周标签格式会略有不同(例如“2021-01”而不是“2021-1st”)。 + +可以通过调整 luxon 配置来自定义这些默认的 luxon 行为: + +```tsx +import generatePicker from 'antd/es/date-picker/generatePicker'; +import 'antd/es/date-picker/style/index'; +import type { DateTime } from 'luxon'; +import luxonGenerateConfig from 'rc-picker/lib/generate/luxon'; + +const customLuxonConfig = { + ...luxonGenerateConfig, + getWeekFirstDay: (locale) => { + // Your custom implementation goes here + }, +}; + +const DatePicker = generatePicker(customLuxonConfig); + +export default DatePicker; +``` + +请注意,通过进行此类自定义,生成的 DatePicker 行为可能会以意想不到的方式发生变化,因此请确保你测试过一些边界情况。