import * as React from 'react'; import { PureComponent } from 'react'; import cx from 'classnames'; import { Input, Icon } from 'zent'; import getWidth from 'zent/es/utils/getWidth'; import Popover from '../popover'; import { I18nReceiver as Receiver } from '../i18n'; import MonthPanel from './month/MonthPanel'; import PanelFooter from './common/PanelFooter'; import { formatDate, parseDate, dayStart, dayEnd, monthStart } from './utils'; import { CURRENT, popPositionMap, commonProps } from './constants'; import { DatePickers } from './common/types'; import noop from 'lodash-es/noop'; import warning from 'zent/es/utils/warning'; export interface IMonthPickerProps extends DatePickers.ICommonProps { disabled?: boolean; isFooterVisible?: boolean; onBeforeClear?: () => unknown; } function extractStateFromProps(props: IMonthPickerProps) { let showPlaceholder; let selected; let actived; const { format, value, defaultValue } = props; if (value) { const tmp = parseDate(value, format); if (tmp) { showPlaceholder = false; selected = actived = monthStart(tmp); } else { warning(false, "date and format don't match."); showPlaceholder = true; actived = monthStart(); } } else { showPlaceholder = true; if (defaultValue) { actived = monthStart(parseDate(defaultValue, format)); } else { actived = monthStart(); } } return { value: selected && formatDate(selected, format), actived, selected, openPanel: false, showPlaceholder, prevProps: props, }; } export class MonthPicker extends PureComponent { static defaultProps = { ...commonProps, placeholder: '', format: 'YYYY-MM', }; retType = 'string'; picker?: HTMLDivElement | null = null; static getDerivedStateFromProps(props: IMonthPickerProps, state: any) { if (props !== state.prevProps) { return extractStateFromProps(props); } return null; } constructor(props: IMonthPickerProps) { super(props); this.state = extractStateFromProps(props); const { value, valueType } = props; if (valueType) { this.retType = valueType.toLowerCase(); } else if (value) { if (typeof value === 'number') this.retType = 'number'; if (value instanceof Date) this.retType = 'date'; } } getReturnValue = date => { const { format } = this.props; if (this.retType === 'number') { return date.getTime(); } if (this.retType === 'date') { return date; } return formatDate(date, format); }; onChangeMonth = val => { this.setState({ actived: val, }); }; onSelectMonth = (val, isYear = false) => { const { onClick, isFooterVisible } = this.props; const month = val.getMonth(); if (!isYear && this.isDisabled(month)) return; this.setState( { selected: val, actived: val, }, () => { if (!isFooterVisible) { this.onConfirm(); } } ); onClick && onClick(val); }; onClearInput = evt => { evt.stopPropagation(); const { onChange, onBeforeClear, canClear } = this.props; if (onBeforeClear && !onBeforeClear()) return; // 用户可以通过这个函数返回 false 来阻止清空 if (!canClear) return; onChange(''); }; onConfirm = () => { const { props: { format, onChange }, state: { selected }, } = this; let value = ''; if (selected) { value = formatDate(selected, format); } this.setState({ value, openPanel: false, showPlaceholder: false, }); onChange(this.getReturnValue(selected)); }; isDisabled = val => { const year = this.state.actived.getFullYear(); const dateStr = `${year}-${val + 1}`; const ret = parseDate(dateStr, 'YYYY-MM'); const { disabledDate, min, max, format } = this.props; if (disabledDate && disabledDate(ret)) return true; if (min && dayEnd(ret) < parseDate(min, format)) return true; if (max && dayStart(ret) > parseDate(max, format)) return true; return false; }; renderPicker(i18n) { const { props: { confirmText, isFooterVisible }, state: { actived, openPanel, selected }, } = this; let monthPicker; if (openPanel) { const monthPickerCls = cx({ 'month-picker': true, small: isFooterVisible, }); monthPicker = (
{isFooterVisible ? ( this.onSelectMonth(CURRENT)} onClickButton={this.onConfirm} /> ) : null}
); } return monthPicker; } togglePicker = () => { const { onOpen, onClose, disabled } = this.props; const openPanel = !this.state.openPanel; if (disabled) return; openPanel ? onOpen && onOpen() : onClose && onClose(); this.setState({ openPanel: !this.state.openPanel, }); }; render() { const { props: { className, disabled, name, placeholder, popPosition, prefix, width, canClear, autoComplete, }, state: { openPanel, showPlaceholder, value }, } = this; const wrapperCls = cx( `${prefix}-datetime-picker`, `${prefix}-month-picker`, className ); const inputCls = cx({ 'picker-input': true, 'picker-input--show-clear-icon': canClear && !showPlaceholder, 'picker-input--disabled': disabled, }); const widthStyle = getWidth(width); return (
{i18n => (
{canClear && ( )}
{this.renderPicker(i18n)}
)}
); } } export default MonthPicker;