import PropTypes from '../../_util/vue-types' import BaseMixin from '../../_util/BaseMixin' import { getOptionProps, hasProp } from '../../_util/props-util' import { cloneElement } from '../../_util/vnode' import KeyCode from '../../_util/KeyCode' import * as moment from 'moment' import DateTable from './date/DateTable' import CalendarHeader from './calendar/CalendarHeader' import CalendarFooter from './calendar/CalendarFooter' import CalendarMixin from './mixin/CalendarMixin' import CommonMixin from './mixin/CommonMixin' import DateInput from './date/DateInput' import enUs from './locale/en_US' import { getTimeConfig, getTodayTime, syncTime } from './util' function goStartMonth () { const next = this.sValue.clone() next.startOf('month') this.setValue(next) } function goEndMonth () { const next = this.sValue.clone() next.endOf('month') this.setValue(next) } function goTime (direction, unit) { const next = this.sValue.clone() next.add(direction, unit) this.setValue(next) } function goMonth (direction) { return goTime.call(this, direction, 'months') } function goYear (direction) { return goTime.call(this, direction, 'years') } function goWeek (direction) { return goTime.call(this, direction, 'weeks') } function goDay (direction) { return goTime.call(this, direction, 'days') } function isMoment (value) { if (Array.isArray(value)) { return value.length === 0 || !!value.find((val) => val === undefined || moment.isMoment(val)) } else { return value === undefined || moment.isMoment(value) } } const MomentType = PropTypes.custom(isMoment) const Calendar = { props: { locale: PropTypes.object.def(enUs), format: PropTypes.string, visible: PropTypes.bool.def(true), prefixCls: PropTypes.string.def('rc-calendar'), // prefixCls: PropTypes.string, defaultValue: MomentType, value: MomentType, selectedValue: MomentType, mode: PropTypes.oneOf(['time', 'date', 'month', 'year', 'decade']), // locale: PropTypes.object, showDateInput: PropTypes.bool.def(true), showWeekNumber: PropTypes.bool, showToday: PropTypes.bool.def(true), showOk: PropTypes.bool, // onSelect: PropTypes.func, // onOk: PropTypes.func, // onKeyDown: PropTypes.func, timePicker: PropTypes.any, dateInputPlaceholder: PropTypes.any, // onClear: PropTypes.func, // onChange: PropTypes.func, // onPanelChange: PropTypes.func, disabledDate: PropTypes.func, disabledTime: PropTypes.any, renderFooter: PropTypes.func.def(() => null), renderSidebar: PropTypes.func.def(() => null), dateRender: PropTypes.func, }, mixins: [BaseMixin, CommonMixin, CalendarMixin], data () { return { sMode: this.mode || 'date', } }, watch: { mode (val) { this.setState({ sMode: val }) }, }, methods: { onKeyDown (event) { if (event.target.nodeName.toLowerCase() === 'input') { return undefined } const keyCode = event.keyCode // mac const ctrlKey = event.ctrlKey || event.metaKey const { disabledDate, sValue: value } = this switch (keyCode) { case KeyCode.DOWN: goWeek.call(this, 1) event.preventDefault() return 1 case KeyCode.UP: goWeek.call(this, -1) event.preventDefault() return 1 case KeyCode.LEFT: if (ctrlKey) { goYear.call(this, -1) } else { goDay.call(this, -1) } event.preventDefault() return 1 case KeyCode.RIGHT: if (ctrlKey) { goYear.call(this, 1) } else { goDay.call(this, 1) } event.preventDefault() return 1 case KeyCode.HOME: goStartMonth.call(this) event.preventDefault() return 1 case KeyCode.END: goEndMonth.call(this) event.preventDefault() return 1 case KeyCode.PAGE_DOWN: goMonth.call(this, 1) event.preventDefault() return 1 case KeyCode.PAGE_UP: goMonth.call(this, -1) event.preventDefault() return 1 case KeyCode.ENTER: if (!disabledDate || !disabledDate(value)) { this.onSelect(value, { source: 'keyboard', }) } event.preventDefault() return 1 default: this.__emit('keydown', event) return 1 } }, onClear () { this.onSelect(null) this.__emit('clear') }, onOk () { const { sSelectedValue } = this if (this.isAllowedDate(sSelectedValue)) { this.__emit('ok', sSelectedValue) } }, onDateInputChange (value) { this.onSelect(value, { source: 'dateInput', }) }, onDateTableSelect (value) { const { timePicker, sSelectedValue } = this if (!sSelectedValue && timePicker) { const timePickerProps = getOptionProps(timePicker) const timePickerDefaultValue = timePickerProps.defaultValue if (timePickerDefaultValue) { syncTime(timePickerDefaultValue, value) } } this.onSelect(value) }, onToday () { const { sValue } = this const now = getTodayTime(sValue) this.onSelect(now, { source: 'todayButton', }) }, onPanelChange (value, mode) { const { sValue } = this if (!hasProp(this, 'mode')) { this.setState({ sMode: mode }) } this.__emit('panelChange', value || sValue, mode) }, getRootDOMNode () { return this.$el }, openTimePicker () { this.onPanelChange(null, 'time') }, closeTimePicker () { this.onPanelChange(null, 'date') }, }, render () { const { locale, prefixCls, disabledDate, dateInputPlaceholder, timePicker, disabledTime, showDateInput, renderSidebar, sValue, sSelectedValue, sMode, $props: props, } = this const showTimePicker = sMode === 'time' const disabledTimeConfig = showTimePicker && disabledTime && timePicker ? getTimeConfig(sSelectedValue, disabledTime) : null let timePickerEle = null if (timePicker && showTimePicker) { const timePickerOriginProps = getOptionProps(timePicker) const timePickerProps = { props: { showHour: true, showSecond: true, showMinute: true, ...timePickerOriginProps, ...disabledTimeConfig, value: sSelectedValue, disabledTime, }, on: { change: this.onDateInputChange, }, } if (timePickerOriginProps.defaultValue !== undefined) { timePickerProps.props.defaultOpenValue = timePickerOriginProps.defaultValue } timePickerEle = cloneElement(timePicker, timePickerProps) } const dateInputElement = showDateInput ? ( ) : null const children = [ renderSidebar(), (
{dateInputElement}
{timePicker && showTimePicker ? (
{timePickerEle }
) : null}
), ] return this.renderRoot({ children, class: props.showWeekNumber ? `${prefixCls}-week-number` : '', }) }, } export default Calendar