import * as React from 'react'; import classNames from 'classnames'; import RCPicker, { RangePicker as RCRangePicker } from 'rc-picker'; import { GenerateConfig } from 'rc-picker/lib/generate/index'; import { PickerBaseProps as RCPickerBaseProps, PickerDateProps as RCPickerDateProps, PickerTimeProps as RCPickerTimeProps, } from 'rc-picker/lib/Picker'; import { SharedTimeProps } from 'rc-picker/lib/panels/TimePanel'; import { RangePickerBaseProps as RCRangePickerBaseProps, RangePickerDateProps as RCRangePickerDateProps, RangePickerTimeProps as RCRangePickerTimeProps, } from 'rc-picker/lib/RangePicker'; import { PickerMode, Locale as RcPickerLocale } from 'rc-picker/lib/interface'; import CalendarOutlined from '@ant-design/icons/CalendarOutlined'; import ClockCircleOutlined from '@ant-design/icons/ClockCircleOutlined'; import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; import { ConfigContext, ConfigConsumerProps } from '../config-provider'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; import enUS from './locale/en_US'; import { getPlaceholder, getRangePlaceholder } from './util'; import PickerButton from './PickerButton'; import PickerTag from './PickerTag'; import SizeContext, { SizeType } from '../config-provider/SizeContext'; import { TimePickerLocale } from '../time-picker'; const Components = { button: PickerButton, rangeItem: PickerTag }; function toArray(list: T | T[]): T[] { if (!list) { return []; } return Array.isArray(list) ? list : [list]; } function getTimeProps( props: { format?: string; picker?: PickerMode } & SharedTimeProps, ) { const { format, picker, showHour, showMinute, showSecond, use12Hours } = props; const firstFormat = toArray(format)[0]; const showTimeObj: SharedTimeProps = { ...props }; if (firstFormat) { if (!firstFormat.includes('s') && showSecond === undefined) { showTimeObj.showSecond = false; } if (!firstFormat.includes('m') && showMinute === undefined) { showTimeObj.showMinute = false; } if (!firstFormat.includes('H') && !firstFormat.includes('h') && showHour === undefined) { showTimeObj.showHour = false; } if ((firstFormat.includes('a') || firstFormat.includes('A')) && use12Hours === undefined) { showTimeObj.use12Hours = true; } } if (picker === 'time') { return showTimeObj; } return { showTime: showTimeObj, }; } type InjectDefaultProps = Omit< Props, | 'locale' | 'generateConfig' | 'prevIcon' | 'nextIcon' | 'superPrevIcon' | 'superNextIcon' | 'hideHeader' | 'components' > & { locale?: PickerLocale; size?: SizeType; bordered?: boolean; }; export type PickerLocale = { lang: RcPickerLocale & AdditionalPickerLocaleLangProps; timePickerLocale: TimePickerLocale; } & AdditionalPickerLocaleProps; export type AdditionalPickerLocaleProps = { dateFormat?: string; dateTimeFormat?: string; weekFormat?: string; monthFormat?: string; }; export type AdditionalPickerLocaleLangProps = { placeholder: string; yearPlaceholder?: string; quarterPlaceholder?: string; monthPlaceholder?: string; weekPlaceholder?: string; rangeYearPlaceholder?: [string, string]; rangeMonthPlaceholder?: [string, string]; rangeWeekPlaceholder?: [string, string]; rangePlaceholder?: [string, string]; }; // Picker Props export type PickerBaseProps = InjectDefaultProps>; export type PickerDateProps = InjectDefaultProps>; export type PickerTimeProps = InjectDefaultProps>; export type PickerProps = | PickerBaseProps | PickerDateProps | PickerTimeProps; // Range Picker Props export type RangePickerBaseProps = InjectDefaultProps>; export type RangePickerDateProps = InjectDefaultProps>; export type RangePickerTimeProps = InjectDefaultProps>; export type RangePickerProps = | RangePickerBaseProps | RangePickerDateProps | RangePickerTimeProps; function generatePicker(generateConfig: GenerateConfig) { // =========================== Picker =========================== type DatePickerProps = PickerProps; function getPicker( picker?: PickerMode, displayName?: string, ) { class Picker extends React.Component { static contextType = ConfigContext; static displayName: string; context: ConfigConsumerProps; pickerRef = React.createRef>(); focus = () => { if (this.pickerRef.current) { this.pickerRef.current.focus(); } }; blur = () => { if (this.pickerRef.current) { this.pickerRef.current.blur(); } }; getDefaultLocale = () => { const { locale } = this.props; const result = { ...enUS, ...locale, }; result.lang = { ...result.lang, ...((locale || {}) as PickerLocale).lang, }; return result; }; renderPicker = (locale: PickerLocale) => { const { getPrefixCls, direction } = this.context; const { prefixCls: customizePrefixCls, className, size: customizeSize, bordered = true, ...restProps } = this.props; const { format, showTime } = this.props as any; const prefixCls = getPrefixCls('picker', customizePrefixCls); const additionalProps = { showToday: true, }; let additionalOverrideProps: any = {}; if (picker) { additionalOverrideProps.picker = picker; } const mergedPicker = picker || this.props.picker; additionalOverrideProps = { ...additionalOverrideProps, ...(showTime ? getTimeProps({ format, picker: mergedPicker, ...showTime }) : {}), ...(mergedPicker === 'time' ? getTimeProps({ format, ...this.props, picker: mergedPicker }) : {}), }; return ( {size => { const mergedSize = customizeSize || size; return ( ref={this.pickerRef} placeholder={getPlaceholder(mergedPicker, locale)} suffixIcon={ mergedPicker === 'time' ? : } clearIcon={} allowClear transitionName="slide-up" {...additionalProps} {...restProps} {...additionalOverrideProps} locale={locale!.lang} className={classNames(className, { [`${prefixCls}-${mergedSize}`]: mergedSize, [`${prefixCls}-borderless`]: !bordered, })} prefixCls={prefixCls} generateConfig={generateConfig} prevIcon={} nextIcon={} superPrevIcon={} superNextIcon={} components={Components} direction={direction} /> ); }} ); }; render() { return ( {this.renderPicker} ); } } if (displayName) { Picker.displayName = displayName; } return Picker as React.ComponentClass; } const DatePicker = getPicker(); const WeekPicker = getPicker, 'picker'>>('week', 'WeekPicker'); const MonthPicker = getPicker, 'picker'>>('month', 'MonthPicker'); const YearPicker = getPicker, 'picker'>>('year', 'YearPicker'); const TimePicker = getPicker, 'picker'>>('time', 'TimePicker'); // ======================== Range Picker ======================== class RangePicker extends React.Component> { static contextType = ConfigContext; context: ConfigConsumerProps; pickerRef = React.createRef>(); focus = () => { if (this.pickerRef.current) { this.pickerRef.current.focus(); } }; blur = () => { if (this.pickerRef.current) { this.pickerRef.current.blur(); } }; getDefaultLocale = () => { const { locale } = this.props; const result = { ...enUS, ...locale, }; result.lang = { ...result.lang, ...((locale || {}) as PickerLocale).lang, }; return result; }; renderPicker = (locale: PickerLocale) => { const { getPrefixCls, direction } = this.context; const { prefixCls: customizePrefixCls, className, size: customizeSize, bordered = true, ...restProps } = this.props; const { format, showTime, picker } = this.props as any; const prefixCls = getPrefixCls('picker', customizePrefixCls); let additionalOverrideProps: any = {}; additionalOverrideProps = { ...additionalOverrideProps, ...(showTime ? getTimeProps({ format, picker, ...showTime }) : {}), ...(picker === 'time' ? getTimeProps({ format, ...this.props, picker }) : {}), }; return ( {size => { const mergedSize = customizeSize || size; return ( separator={} ref={this.pickerRef} placeholder={getRangePlaceholder(picker, locale)} suffixIcon={picker === 'time' ? : } clearIcon={} allowClear transitionName="slide-up" {...restProps} className={classNames(className, { [`${prefixCls}-${mergedSize}`]: mergedSize, [`${prefixCls}-borderless`]: !bordered, })} {...additionalOverrideProps} locale={locale!.lang} prefixCls={prefixCls} generateConfig={generateConfig} prevIcon={} nextIcon={} superPrevIcon={} superNextIcon={} components={Components} direction={direction} /> ); }} ); }; render() { return ( {this.renderPicker} ); } } // =========================== Export =========================== type MergedDatePicker = typeof DatePicker & { WeekPicker: typeof WeekPicker; MonthPicker: typeof MonthPicker; YearPicker: typeof YearPicker; RangePicker: React.ComponentClass>; TimePicker: typeof TimePicker; }; const MergedDatePicker = DatePicker as MergedDatePicker; MergedDatePicker.WeekPicker = WeekPicker; MergedDatePicker.MonthPicker = MonthPicker; MergedDatePicker.YearPicker = YearPicker; MergedDatePicker.RangePicker = RangePicker; MergedDatePicker.TimePicker = TimePicker; return MergedDatePicker; } export default generatePicker;