diff --git a/examples/panelRender.tsx b/examples/panelRender.tsx new file mode 100644 index 000000000..cfecee66b --- /dev/null +++ b/examples/panelRender.tsx @@ -0,0 +1,71 @@ +import React from 'react'; +import moment, { Moment } from 'moment'; +import Picker from '../src/Picker'; +import RangePicker from '../src/RangePicker'; +import momentGenerateConfig from '../src/generate/moment'; +import zhCN from '../src/locale/zh_CN'; +import '../assets/index.less'; +import './common.less'; + +const defaultStartValue = moment('2019-09-03 05:02:03'); +const defaultEndValue = moment('2019-11-28 01:02:03'); +const defaultValue: [Moment, Moment] = [defaultStartValue, defaultEndValue]; + +export default () => { + const [customizeNode, setCustomizeNode] = React.useState(false); + + return ( + <> + {String(customizeNode)} +
+
+

Picker

+ + generateConfig={momentGenerateConfig} + locale={zhCN} + allowClear + defaultValue={defaultStartValue} + panelRender={node => ( + <> + + + {customizeNode ? My Panel : node} + + )} + /> +
+
+

RangePicker

+ + generateConfig={momentGenerateConfig} + locale={zhCN} + allowClear + defaultValue={defaultValue} + panelRender={node => ( + <> + + {customizeNode ? My Panel : node} + + )} + /> +
+
+ + ); +}; diff --git a/src/Picker.tsx b/src/Picker.tsx index 5b5d37528..89aee099d 100644 --- a/src/Picker.tsx +++ b/src/Picker.tsx @@ -63,6 +63,7 @@ export interface PickerSharedProps extends React.AriaAttributes { superPrevIcon?: React.ReactNode; superNextIcon?: React.ReactNode; getPopupContainer?: (node: HTMLElement) => HTMLElement; + panelRender?: (originPanel: React.ReactNode) => React.ReactNode; // Events onChange?: (value: DateType | null, dateString: string) => void; @@ -157,6 +158,7 @@ function InnerPicker(props: PickerProps) { placeholder, getPopupContainer, pickerRef, + panelRender, onChange, onOpenChange, onFocus, @@ -359,6 +361,25 @@ function InnerPicker(props: PickerProps) { onPickerValueChange: undefined, }; + let panelNode: React.ReactNode = ( + + {...panelProps} + generateConfig={generateConfig} + className={classNames({ + [`${prefixCls}-panel-focused`]: !typing, + })} + value={selectedValue} + locale={locale} + tabIndex={-1} + onChange={setSelectedValue} + direction={direction} + /> + ); + + if (panelRender) { + panelNode = panelRender(panelNode); + } + const panel = (
(props: PickerProps) { e.preventDefault(); }} > - - {...panelProps} - generateConfig={generateConfig} - className={classNames({ - [`${prefixCls}-panel-focused`]: !typing, - })} - value={selectedValue} - locale={locale} - tabIndex={-1} - onChange={setSelectedValue} - direction={direction} - /> + {panelNode}
); diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index fa8d41885..19378e8e4 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -96,6 +96,7 @@ export interface RangePickerSharedProps { /** @private Internal control of active picker. Do not use since it's private usage */ activePickerIndex?: 0 | 1; dateRender?: RangeDateRender; + panelRender?: (originPanel: React.ReactNode) => React.ReactNode; } type OmitPickerProps = Omit< @@ -181,6 +182,7 @@ function InnerRangePicker(props: RangePickerProps) { disabledDate, disabledTime, dateRender, + panelRender, ranges, allowEmpty, allowClear, @@ -869,6 +871,22 @@ function InnerRangePicker(props: RangePickerProps) { panels = renderPanel(); } + let mergedNodes: React.ReactNode = ( + <> +
{panels}
+ {(extraNode || rangesNode) && ( +
+ {extraNode} + {rangesNode} +
+ )} + + ); + + if (panelRender) { + mergedNodes = panelRender(mergedNodes); + } + return (
(props: RangePickerProps) { e.preventDefault(); }} > -
{panels}
- {(extraNode || rangesNode) && ( -
- {extraNode} - {rangesNode} -
- )} + {mergedNodes}
); } diff --git a/tests/__snapshots__/picker.spec.tsx.snap b/tests/__snapshots__/picker.spec.tsx.snap index 7ff4b2300..dacf55ac3 100644 --- a/tests/__snapshots__/picker.spec.tsx.snap +++ b/tests/__snapshots__/picker.spec.tsx.snap @@ -28,6 +28,40 @@ exports[`Picker.Basic icon 1`] = ` `; +exports[`Picker.Basic panelRender 1`] = ` +Array [ +
+
+ +
+
, +
+
+
+

+ Light +

+
+
+
, +] +`; + exports[`Picker.Basic pass data- & aria- & role 1`] = `
`; + +exports[`Picker.Range panelRender 1`] = ` +Array [ +
+
+ +
+
+ ~ +
+
+ +
+
+
, +
+
+
+
+
+

+ Light +

+
+
+
+
, +] +`; diff --git a/tests/picker.spec.tsx b/tests/picker.spec.tsx index 9055ff750..b1f603cf9 100644 --- a/tests/picker.spec.tsx +++ b/tests/picker.spec.tsx @@ -724,4 +724,9 @@ describe('Picker.Basic', () => { wrapper.closePicker(); expect(wrapper.find('input').prop('value')).toEqual('20000101'); }); + + it('panelRender', () => { + const wrapper = mount(

Light

} />); + expect(wrapper.render()).toMatchSnapshot(); + }); }); diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index f6053a7a1..bec2bd7b9 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -1382,4 +1382,9 @@ describe('Picker.Range', () => { jest.useRealTimers(); }); }); + + it('panelRender', () => { + const wrapper = mount(

Light

} />); + expect(wrapper.render()).toMatchSnapshot(); + }); });