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 [
+ ,
+ ,
+]
+`;
+
exports[`Picker.Basic pass data- & aria- & role 1`] = `
`;
+
+exports[`Picker.Range panelRender 1`] = `
+Array [
+ ,
+ ,
+]
+`;
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();
+ });
});