Skip to content

Commit

Permalink
chore: merge feature into master (ant-design#41598)
Browse files Browse the repository at this point in the history
* 🦄️ refactor(DatePicker,Calendar): dateRender,monthRender => cellRender (ant-design#41584)

* 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

* test: fix lint error (ant-design#41596) (ant-design#41600)

* test: fix lint error

* chore: fix lint

---------

* feat: Picker luxon support (ant-design#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

---------

Co-authored-by: kiner-tang(文辉) <[email protected]>
Co-authored-by: Sylvain Boulade <[email protected]>
  • Loading branch information
3 people authored Apr 3, 2023
1 parent 9b40680 commit bf9eff6
Show file tree
Hide file tree
Showing 14 changed files with 279 additions and 49 deletions.
61 changes: 61 additions & 0 deletions components/calendar/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -462,6 +463,20 @@ describe('Calendar', () => {
expect(container.querySelectorAll('.bamboo')[0].innerHTML).toEqual('Light');
});

it('fullCellRender in date', () => {
const { container } = render(
<Calendar fullCellRender={() => <div className="light">Bamboo</div>} />,
);
expect(container.querySelectorAll('.light')[0].innerHTML).toEqual('Bamboo');
});

it('fullCellRender in month', () => {
const { container } = render(
<Calendar mode="year" fullCellRender={() => <div className="bamboo">Light</div>} />,
);
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(
Expand All @@ -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(
<Calendar
dateCellRender={() => <div className="bamboo">Light</div>}
monthCellRender={() => <div className="bar">Bar</div>}
/>,
);
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(
<Calendar
dateFullCellRender={() => <div className="bamboo">Light</div>}
monthFullCellRender={() => <div className="bar">Bar</div>}
/>,
);
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();
});
});
9 changes: 8 additions & 1 deletion components/calendar/demo/notice-calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,7 +65,13 @@ const App: React.FC = () => {
);
};

return <Calendar dateCellRender={dateCellRender} monthCellRender={monthCellRender} />;
const cellRender = (current: Dayjs, info: CellRenderInfo<Dayjs>) => {
if (info.type === 'date') return dateCellRender(current);
if (info.type === 'month') return monthCellRender(current);
return info.originNode;
};

return <Calendar cellRender={cellRender} />;
};

export default App;
72 changes: 62 additions & 10 deletions components/calendar/generateCalendar.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<Props> = Omit<
Props,
Expand Down Expand Up @@ -50,10 +51,16 @@ export interface CalendarProps<DateType> {
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<DateType>) => React.ReactNode;
fullCellRender?: (date: DateType, info: CellRenderInfo<DateType>) => React.ReactNode;
headerRender?: HeaderRender<DateType>;
value?: DateType;
defaultValue?: DateType;
Expand Down Expand Up @@ -91,6 +98,8 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
dateCellRender,
monthFullCellRender,
monthCellRender,
cellRender,
fullCellRender,
headerRender,
value,
defaultValue,
Expand All @@ -110,6 +119,30 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {

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
Expand Down Expand Up @@ -187,7 +220,10 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {

// ====================== Render ======================
const dateRender = React.useCallback(
(date: DateType): React.ReactNode => {
(date: DateType, info: CellRenderInfo<DateType>): React.ReactNode => {
if (fullCellRender) {
return fullCellRender(date, info);
}
if (dateFullCellRender) {
return dateFullCellRender(date);
}
Expand All @@ -202,21 +238,25 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
{String(generateConfig.getDate(date)).padStart(2, '0')}
</div>
<div className={`${calendarPrefixCls}-date-content`}>
{dateCellRender && dateCellRender(date)}
{cellRender ? cellRender(date, info) : dateCellRender && dateCellRender(date)}
</div>
</div>
);
},
[dateFullCellRender, dateCellRender],
[dateFullCellRender, dateCellRender, cellRender, fullCellRender],
);

const monthRender = React.useCallback(
(date: DateType, locale: Locale): React.ReactNode => {
(date: DateType, info: CellRenderInfo<DateType>): 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 (
<div
Expand All @@ -228,16 +268,29 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
{months[generateConfig.getMonth(date)]}
</div>
<div className={`${calendarPrefixCls}-date-content`}>
{monthCellRender && monthCellRender(date)}
{cellRender ? cellRender(date, info) : monthCellRender && monthCellRender(date)}
</div>
</div>
);
},
[monthFullCellRender, monthCellRender],
[monthFullCellRender, monthCellRender, cellRender, fullCellRender],
);

const [contextLocale] = useLocale('Calendar', getDefaultLocale);

const mergedCellRender = (current: DateType, info: CellRenderInfo<DateType>) => {
if (info.type === 'date') {
return dateRender(current, info);
}

if (info.type === 'month') {
return monthRender(current, {
...info,
locale: contextLocale?.lang,
});
}
};

return wrapSSR(
<div
className={classNames(
Expand Down Expand Up @@ -278,8 +331,7 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
prefixCls={prefixCls}
locale={contextLocale?.lang}
generateConfig={generateConfig}
dateRender={dateRender}
monthCellRender={(date) => monthRender(date, contextLocale?.lang)}
cellRender={mergedCellRender}
onSelect={onInternalSelect}
mode={panelMode}
picker={panelMode}
Expand Down
12 changes: 8 additions & 4 deletions components/calendar/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | - | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7088,7 +7088,7 @@ exports[`renders components/date-picker/demo/bordered.tsx extend context correct
</div>
`;

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`] = `
<div
class="ant-space ant-space-vertical"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ exports[`renders components/date-picker/demo/bordered.tsx correctly 1`] = `
</div>
`;

exports[`renders components/date-picker/demo/date-render.tsx correctly 1`] = `
exports[`renders components/date-picker/demo/cell-render.tsx correctly 1`] = `
<div
class="ant-space ant-space-vertical"
>
Expand Down
7 changes: 7 additions & 0 deletions components/date-picker/demo/cell-render.md
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import { DatePicker, Space } from 'antd';
import React from 'react';

const { RangePicker } = DatePicker;

const App: React.FC = () => (
<Space direction="vertical" size={12}>
<DatePicker
dateRender={(current) => {
cellRender={(current) => {
const style: React.CSSProperties = {};
if (current.date() === 1) {
style.border = '1px solid #1890ff';
Expand All @@ -20,7 +20,7 @@ const App: React.FC = () => (
}}
/>
<RangePicker
dateRender={(current) => {
cellRender={(current) => {
const style: React.CSSProperties = {};
if (current.date() === 1) {
style.border = '1px solid #1890ff';
Expand Down
7 changes: 0 additions & 7 deletions components/date-picker/demo/date-render.md

This file was deleted.

9 changes: 5 additions & 4 deletions components/date-picker/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ By clicking the input box, you can select a date from a popup calendar.
<code src="./demo/preset-ranges.tsx">Preset Ranges</code>
<code src="./demo/extra-footer.tsx">Extra Footer</code>
<code src="./demo/size.tsx">Three Sizes</code>
<code src="./demo/date-render.tsx">Customized Date Rendering</code>
<code src="./demo/cell-render.tsx">Customized Cell Rendering</code>
<code src="./demo/status.tsx">Status</code>
<code src="./demo/bordered.tsx">Bordered-less</code>
<code src="./demo/placement.tsx">Placement</code>
Expand Down Expand Up @@ -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) | |
Expand Down Expand Up @@ -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) | - | |
Expand All @@ -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] | - | |
Expand Down
Loading

0 comments on commit bf9eff6

Please sign in to comment.