ant-design-vue/components/calendar/index.jsx

262 lines
6.6 KiB
Vue
Raw Normal View History

2018-03-19 02:16:27 +00:00
2018-03-19 02:25:42 +00:00
import PropTypes from '../_util/vue-types'
import BaseMixin from '../_util/BaseMixin'
import { getOptionProps, hasProp, initDefaultProps } from '../_util/props-util'
2018-03-13 14:40:13 +00:00
import * as moment from 'moment'
import FullCalendar from '../vc-calendar/src/FullCalendar'
import LocaleReceiver from '../locale-provider/LocaleReceiver'
import { PREFIX_CLS } from './Constants'
import Header from './Header'
2018-04-06 12:56:19 +00:00
import interopDefault from '../_util/interopDefault'
2018-03-13 14:40:13 +00:00
import enUS from './locale/en_US'
export { HeaderProps } from './Header'
function noop () { return null }
function zerofixed (v) {
if (v < 10) {
return `0${v}`
}
return `${v}`
}
export const MomentType = {
type: Object,
validator: function (value) {
return moment.isMoment(value)
},
}
2018-04-06 12:56:19 +00:00
function isMomentArray (value) {
return Array.isArray(value) && !!value.find((val) => moment.isMoment(val))
}
2018-03-13 14:40:13 +00:00
export const CalendarMode = PropTypes.oneOf(['month', 'year'])
export const CalendarProps = () => ({
prefixCls: PropTypes.string,
value: MomentType,
defaultValue: MomentType,
mode: CalendarMode,
fullscreen: PropTypes.bool,
2018-03-14 14:00:43 +00:00
// dateCellRender: PropTypes.func,
// monthCellRender: PropTypes.func,
// dateFullCellRender: PropTypes.func,
// monthFullCellRender: PropTypes.func,
locale: PropTypes.object,
2018-03-13 14:40:13 +00:00
// onPanelChange?: (date?: moment.Moment, mode?: CalendarMode) => void;
// onSelect?: (date?: moment.Moment) => void;
disabledDate: PropTypes.func,
2018-04-06 12:56:19 +00:00
validRange: PropTypes.custom(isMomentArray),
2018-03-13 14:40:13 +00:00
})
const Calendar = {
2018-04-08 13:17:20 +00:00
name: 'ACalendar',
2018-03-13 14:40:13 +00:00
mixins: [BaseMixin],
props: initDefaultProps(CalendarProps(), {
locale: {},
fullscreen: true,
prefixCls: PREFIX_CLS,
mode: 'month',
}),
2018-03-14 14:00:43 +00:00
model: {
prop: 'value',
event: 'change',
},
2018-03-13 14:40:13 +00:00
data () {
2018-04-06 12:56:19 +00:00
const value = this.value || this.defaultValue || interopDefault(moment)()
if (!interopDefault(moment).isMoment(value)) {
2018-03-13 14:40:13 +00:00
throw new Error(
'The value/defaultValue of Calendar must be a moment object, ',
)
}
return {
sValue: value,
sMode: this.mode,
}
},
watch: {
value (val) {
this.setState({
sValue: val,
})
},
mode (val) {
this.setState({
sMode: val,
})
},
},
methods: {
2018-03-14 14:00:43 +00:00
monthCellRender2 (value) {
const { prefixCls, $scopedSlots } = this
const monthCellRender = this.monthCellRender || $scopedSlots.monthCellRender || noop
2018-03-13 14:40:13 +00:00
return (
<div class={`${prefixCls}-month`}>
<div class={`${prefixCls}-value`}>
{value.localeData().monthsShort(value)}
</div>
<div class={`${prefixCls}-content`}>
{monthCellRender(value)}
</div>
</div>
)
},
2018-03-14 14:00:43 +00:00
dateCellRender2 (value) {
const { prefixCls, $scopedSlots } = this
const dateCellRender = this.dateCellRender || $scopedSlots.dateCellRender || noop
2018-03-13 14:40:13 +00:00
return (
<div class={`${prefixCls}-date`}>
<div class={`${prefixCls}-value`}>
{zerofixed(value.date())}
</div>
<div class={`${prefixCls}-content`}>
{dateCellRender(value)}
</div>
</div>
)
},
setValue (value, way) {
if (way === 'select') {
this.$emit('select', value)
} else if (way === 'changePanel') {
2018-03-14 14:00:43 +00:00
this.onPanelChange(value, this.sMode)
2018-03-13 14:40:13 +00:00
}
if (!hasProp(this, 'value')) {
this.setState({ sValue: value })
}
2018-03-13 14:40:13 +00:00
},
setType (type) {
const mode = (type === 'date') ? 'month' : 'year'
if (this.sMode !== mode) {
this.setState({ sMode: mode })
2018-03-14 14:00:43 +00:00
this.onPanelChange(this.sValue, mode)
2018-03-13 14:40:13 +00:00
}
},
onHeaderValueChange (value) {
this.setValue(value, 'changePanel')
},
onHeaderTypeChange (type) {
this.setType(type)
},
onPanelChange (value, mode) {
this.$emit('panelChange', value, mode)
2018-03-14 14:00:43 +00:00
if (value !== this.sValue) {
this.$emit('change', value)
}
2018-03-13 14:40:13 +00:00
},
onSelect (value) {
this.setValue(value, 'select')
},
2018-04-06 12:56:19 +00:00
getDateRange (
validRange,
disabledDate,
) {
return (current) => {
if (!current) {
return false
}
const [startDate, endDate] = validRange
const inRange = !current.isBetween(startDate, endDate, 'days', '[]')
if (disabledDate) {
return (disabledDate(current) || inRange)
}
return inRange
}
},
2018-03-13 14:40:13 +00:00
renderCalendar (locale, localeCode) {
const props = getOptionProps(this)
2018-03-14 14:00:43 +00:00
const { sValue: value, sMode: mode, $listeners, $scopedSlots } = this
2018-03-13 14:40:13 +00:00
if (value && localeCode) {
value.locale(localeCode)
}
const { prefixCls, fullscreen, dateFullCellRender, monthFullCellRender } = props
const type = (mode === 'year') ? 'month' : 'date'
let cls = ''
if (fullscreen) {
cls += (` ${prefixCls}-fullscreen`)
}
2018-03-14 14:00:43 +00:00
const monthCellRender = monthFullCellRender || $scopedSlots.monthFullCellRender || this.monthCellRender2
const dateCellRender = dateFullCellRender || $scopedSlots.dateFullCellRender || this.dateCellRender2
2018-04-06 12:56:19 +00:00
let disabledDate = props.disabledDate
if (props.validRange) {
disabledDate = this.getDateRange(props.validRange, disabledDate)
}
2018-03-13 14:40:13 +00:00
const fullCalendarProps = {
props: {
...props,
2018-03-14 14:00:43 +00:00
Select: {},
2018-03-13 14:40:13 +00:00
locale: locale.lang,
type: type,
prefixCls: prefixCls,
showHeader: false,
value: value,
monthCellRender: monthCellRender,
dateCellRender: dateCellRender,
2018-04-06 12:56:19 +00:00
disabledDate,
2018-03-13 14:40:13 +00:00
},
on: {
...$listeners,
select: this.onSelect,
},
}
return (
<div class={cls}>
<Header
fullscreen={fullscreen}
type={type}
value={value}
locale={locale.lang}
prefixCls={prefixCls}
onTypeChange={this.onHeaderTypeChange}
onValueChange={this.onHeaderValueChange}
2018-04-06 12:56:19 +00:00
validRange={props.validRange}
2018-03-13 14:40:13 +00:00
/>
<FullCalendar {...fullCalendarProps}/>
</div>
)
},
getDefaultLocale () {
const result = {
...enUS,
...this.$props.locale,
}
result.lang = {
...result.lang,
...(this.$props.locale || {}).lang,
}
return result
},
2018-03-13 14:40:13 +00:00
},
render () {
return (
<LocaleReceiver
componentName='Calendar'
defaultLocale={this.getDefaultLocale}
2018-03-15 13:52:58 +00:00
scopedSlots={
{ default: this.renderCalendar }
}
2018-03-13 14:40:13 +00:00
/>
)
},
}
2018-03-19 02:16:27 +00:00
/* istanbul ignore next */
Calendar.install = function (Vue) {
Vue.component(Calendar.name, Calendar)
}
export default Calendar