import PropTypes from '../../_util/vue-types'; import BaseMixin from '../../_util/BaseMixin'; import { getOptionProps, hasProp, getEvents, getStyle } from '../../_util/props-util'; import { cloneElement } from '../../_util/vnode'; import createChainedFunction from '../../_util/createChainedFunction'; import KeyCode from '../../_util/KeyCode'; import placements from './picker/placements'; import Trigger from '../../vc-trigger'; import moment from 'moment'; import isNil from 'lodash/isNil'; const TimeType = { validator(value) { if (Array.isArray(value)) { return ( value.length === 0 || value.findIndex(val => !isNil(val) && !moment.isMoment(val)) === -1 ); } else { return isNil(value) || moment.isMoment(value); } }, }; const Picker = { name: 'Picker', props: { animation: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), disabled: PropTypes.bool, transitionName: PropTypes.string, format: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.func]), // onChange: PropTypes.func, // onOpenChange: PropTypes.func, children: PropTypes.func, getCalendarContainer: PropTypes.func, calendar: PropTypes.any, open: PropTypes.bool, defaultOpen: PropTypes.bool.def(false), prefixCls: PropTypes.string.def('rc-calendar-picker'), placement: PropTypes.any.def('bottomLeft'), value: TimeType, defaultValue: TimeType, align: PropTypes.object.def(() => ({})), dropdownClassName: PropTypes.string, dateRender: PropTypes.func, }, mixins: [BaseMixin], data() { const props = this.$props; let open; if (hasProp(this, 'open')) { open = props.open; } else { open = props.defaultOpen; } const value = props.value || props.defaultValue; return { sOpen: open, sValue: value, }; }, watch: { value(val) { this.setState({ sValue: val, }); }, open(val) { this.setState({ sOpen: val, }); }, }, mounted() { this.preSOpen = this.sOpen; }, updated() { if (!this.preSOpen && this.sOpen) { // setTimeout is for making sure saveCalendarRef happen before focusCalendar this.focusTimeout = setTimeout(this.focusCalendar, 0); } this.preSOpen = this.sOpen; }, beforeUnmount() { clearTimeout(this.focusTimeout); }, methods: { onCalendarKeyDown(event) { if (event.keyCode === KeyCode.ESC) { event.stopPropagation(); this.closeCalendar(this.focus); } }, onCalendarSelect(value, cause = {}) { const props = this.$props; if (!hasProp(this, 'value')) { this.setState({ sValue: value, }); } const calendarProps = getOptionProps(props.calendar); if ( cause.source === 'keyboard' || cause.source === 'dateInputSelect' || (!calendarProps.timePicker && cause.source !== 'dateInput') || cause.source === 'todayButton' ) { this.closeCalendar(this.focus); } this.__emit('change', value); }, onKeyDown(event) { if (!this.sOpen && (event.keyCode === KeyCode.DOWN || event.keyCode === KeyCode.ENTER)) { this.openCalendar(); event.preventDefault(); } }, onCalendarOk() { this.closeCalendar(this.focus); }, onCalendarClear() { this.closeCalendar(this.focus); }, onCalendarBlur() { this.setOpen(false); }, onVisibleChange(open) { this.setOpen(open); }, getCalendarElement() { const props = this.$props; const calendarProps = getOptionProps(props.calendar); const calendarEvents = getEvents(props.calendar); const { sValue: value } = this; const defaultValue = value; const extraProps = { ref: 'calendarInstance', props: { defaultValue: defaultValue || calendarProps.defaultValue, selectedValue: value, }, on: { keydown: this.onCalendarKeyDown, ok: createChainedFunction(calendarEvents.ok, this.onCalendarOk), select: createChainedFunction(calendarEvents.select, this.onCalendarSelect), clear: createChainedFunction(calendarEvents.clear, this.onCalendarClear), blur: createChainedFunction(calendarEvents.blur, this.onCalendarBlur), }, }; return cloneElement(props.calendar, extraProps); }, setOpen(open, callback) { if (this.sOpen !== open) { if (!hasProp(this, 'open')) { this.setState( { sOpen: open, }, callback, ); } this.__emit('openChange', open); } }, openCalendar(callback) { this.setOpen(true, callback); }, closeCalendar(callback) { this.setOpen(false, callback); }, focus() { if (!this.sOpen) { this.$el.focus(); } }, focusCalendar() { if (this.sOpen && this.calendarInstance && this.calendarInstance.componentInstance) { this.calendarInstance.componentInstance.focus(); } }, }, render() { const props = getOptionProps(this); const style = getStyle(this); const { prefixCls, placement, getCalendarContainer, align, animation, disabled, dropdownClassName, transitionName, } = props; const { sValue, sOpen } = this; const children = this.$scopedSlots.default; const childrenState = { value: sValue, open: sOpen, }; if (this.sOpen || !this.calendarInstance) { this.calendarInstance = this.getCalendarElement(); } return ( {cloneElement(children(childrenState, props), { on: { keydown: this.onKeyDown } })} ); }, }; export default Picker;