ant-design-vue/components/vc-calendar/src/Picker.vue

215 lines
5.4 KiB
Vue

<script>
import PropTypes from '@/components/_util/vue-types'
import BaseMixin from '@/components/_util/BaseMixin'
import { getOptionProps, hasProp, getEvents, getStyle } from '@/components/_util/props-util'
import { cloneElement } from '@/components/_util/vnode'
import createChainedFunction from '@/components/_util/createChainedFunction'
import KeyCode from '@/components/_util/KeyCode'
import placements from './picker/placements'
import Trigger from '@/components/trigger'
const Picker = {
props: {
animation: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
disabled: PropTypes.bool,
transitionName: PropTypes.string,
// 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: PropTypes.oneOfType([
PropTypes.object,
PropTypes.array,
]),
defaultValue: PropTypes.oneOfType([
PropTypes.object,
PropTypes.array,
]),
align: PropTypes.object.def({}),
},
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
},
beforeDestroy () {
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' ||
(!calendarProps.timePicker && cause.source !== 'dateInput') ||
cause.source === 'todayButton') {
this.closeCalendar(this.focus)
}
this.__emit('change', value)
},
onKeyDown (event) {
if (event.keyCode === KeyCode.DOWN && !this.sOpen) {
this.open()
event.preventDefault()
}
},
onCalendarOk () {
this.closeCalendar(this.focus)
},
onCalendarClear () {
this.closeCalendar(this.focus)
},
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),
},
}
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.$refs.calendarInstance) {
this.$refs.calendarInstance.focus()
}
},
},
render () {
const props = getOptionProps(this)
const style = getStyle(this)
const {
prefixCls, placement,
getCalendarContainer,
align, animation,
disabled,
dropdownClassName,
transitionName,
} = props
const state = this.$data
const children = this.$scopedSlots.default
return (<Trigger
popupAlign={align}
builtinPlacements={placements}
popupPlacement={placement}
action={(disabled && !state.sOpen) ? [] : ['click']}
destroyPopupOnHide
getPopupContainer={getCalendarContainer}
popupStyle={style}
popupAnimation={animation}
popupTransitionName={transitionName}
popupVisible={state.sOpen}
onPopupVisibleChange={this.onVisibleChange}
prefixCls={prefixCls}
popupClassName={dropdownClassName}
>
<template slot='popup'>
{this.getCalendarElement()}
</template>
{cloneElement(children(state, props), { on: { keydown: this.onKeyDown }})}
</Trigger>)
},
}
export default Picker
</script>