import * as React from 'react'; import * as moment from 'moment'; import { polyfill } from 'react-lifecycles-compat'; import MonthCalendar from 'rc-calendar/lib/MonthCalendar'; import RcDatePicker from 'rc-calendar/lib/Picker'; import classNames from 'classnames'; import omit from 'omit.js'; import Icon from '../icon'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import warning from '../_util/warning'; import interopDefault from '../_util/interopDefault'; import getDataOrAriaProps from '../_util/getDataOrAriaProps'; import { formatDate } from './utils'; export interface PickerProps { value?: moment.Moment; open?: boolean; prefixCls: string; } export interface PickerState { open: boolean; value: moment.Moment | null; showDate: moment.Moment | null; } export default function createPicker(TheCalendar: React.ComponentClass): any { class CalenderWrapper extends React.Component { static defaultProps = { allowClear: true, showToday: true, }; static getDerivedStateFromProps(nextProps: PickerProps, prevState: PickerState) { const state: Partial = {}; let { open } = prevState; if ('open' in nextProps) { state.open = nextProps.open; open = nextProps.open || false; } if ('value' in nextProps) { state.value = nextProps.value; if ( nextProps.value !== prevState.value || (!open && nextProps.value !== prevState.showDate) ) { state.showDate = nextProps.value; } } return Object.keys(state).length > 0 ? state : null; } private input: any; private prefixCls?: string; constructor(props: any) { super(props); const value = props.value || props.defaultValue; if (value && !interopDefault(moment).isMoment(value)) { throw new Error( 'The value/defaultValue of DatePicker or MonthPicker must be ' + 'a moment object after `antd@2.0`, see: https://u.ant.design/date-picker-value', ); } this.state = { value, showDate: value, open: false, }; } componentDidUpdate(_: PickerProps, prevState: PickerState) { if (!('open' in this.props) && prevState.open && !this.state.open) { this.focus(); } } saveInput = (node: any) => { this.input = node; }; clearSelection = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); this.handleChange(null); }; handleChange = (value: moment.Moment | null) => { const { props } = this; if (!('value' in props)) { this.setState({ value, showDate: value, }); } props.onChange(value, formatDate(value, props.format)); }; handleCalendarChange = (value: moment.Moment) => { this.setState({ showDate: value }); }; handleOpenChange = (open: boolean) => { const { onOpenChange } = this.props; if (!('open' in this.props)) { this.setState({ open }); } if (onOpenChange) { onOpenChange(open); } }; focus() { this.input.focus(); } blur() { this.input.blur(); } renderFooter = (...args: any[]) => { const { renderExtraFooter } = this.props; const { prefixCls } = this; return renderExtraFooter ? (
{renderExtraFooter(...args)}
) : null; }; renderPicker = ({ getPrefixCls }: ConfigConsumerProps) => { const { value, showDate, open } = this.state; const props = omit(this.props, ['onChange']); const { prefixCls: customizePrefixCls, locale, localeCode, suffixIcon } = props; const prefixCls = getPrefixCls('calendar', customizePrefixCls); // To support old version react. // Have to add prefixCls on the instance. // https://github.com/facebook/react/issues/12397 this.prefixCls = prefixCls; const placeholder = 'placeholder' in props ? props.placeholder : locale.lang.placeholder; const disabledTime = props.showTime ? props.disabledTime : null; const calendarClassName = classNames({ [`${prefixCls}-time`]: props.showTime, [`${prefixCls}-month`]: MonthCalendar === TheCalendar, }); if (value && localeCode) { value.locale(localeCode); } let pickerProps: Object = {}; let calendarProps: any = {}; const pickerStyle: { minWidth?: number } = {}; if (props.showTime) { calendarProps = { // fix https://github.com/ant-design/ant-design/issues/1902 onSelect: this.handleChange, }; pickerStyle.minWidth = 195; } else { pickerProps = { onChange: this.handleChange, }; } if ('mode' in props) { calendarProps.mode = props.mode; } warning( !('onOK' in props), 'DatePicker', 'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!', ); const calendar = ( ); const clearIcon = !props.disabled && props.allowClear && value ? ( ) : null; const inputIcon = (suffixIcon && (React.isValidElement<{ className?: string }>(suffixIcon) ? ( React.cloneElement(suffixIcon, { className: classNames({ [suffixIcon.props.className!]: suffixIcon.props.className, [`${prefixCls}-picker-icon`]: true, }), }) ) : ( {suffixIcon} ))) || ; const dataOrAriaProps = getDataOrAriaProps(props); const input = ({ value: inputValue }: { value: moment.Moment | null }) => (
{clearIcon} {inputIcon}
); return ( {input} ); }; render() { return {this.renderPicker}; } } polyfill(CalenderWrapper); return CalenderWrapper; }