UNPKG

vuetify

Version:

Vue.js 2 Semantic Component Framework

217 lines (196 loc) 6.17 kB
// Components import VTimePickerTitle from './VTimePickerTitle' import VTimePickerClock from './VTimePickerClock' // Mixins import Picker from '../../mixins/picker' // Utils import { createRange } from '../../util/helpers' import pad from '../VDatePicker/util/pad' const rangeHours24 = createRange(24) const rangeHours12am = createRange(12) const rangeHours12pm = rangeHours12am.map(v => v + 12) const rangeMinutes = createRange(60) /* @vue/component */ export default { name: 'v-time-picker', mixins: [Picker], props: { allowedHours: Function, allowedMinutes: Function, format: { type: String, default: 'ampm', validator (val) { return ['ampm', '24hr'].includes(val) } }, min: String, max: String, readonly: Boolean, scrollable: Boolean, value: null }, data () { return { inputHour: null, inputMinute: null, period: 'am', selectingHour: true } }, computed: { isAllowedHourCb () { if (!this.min && !this.max) return this.allowedHours const minHour = this.min ? this.min.split(':')[0] : 0 const maxHour = this.max ? this.max.split(':')[0] : 23 return val => { return val >= minHour * 1 && val <= maxHour * 1 && (!this.allowedHours || this.allowedHours(val)) } }, isAllowedMinuteCb () { const isHourAllowed = !this.allowedHours || this.allowedHours(this.inputHour) if (!this.min && !this.max) { return isHourAllowed ? this.allowedMinutes : () => false } const [minHour, minMinute] = this.min ? this.min.split(':') : [0, 0] const [maxHour, maxMinute] = this.max ? this.max.split(':') : [23, 59] const minTime = minHour * 60 + minMinute * 1 const maxTime = maxHour * 60 + maxMinute * 1 return val => { const time = 60 * this.inputHour + val return time >= minTime && time <= maxTime && isHourAllowed && (!this.allowedMinutes || this.allowedMinutes(val)) } }, isAmPm () { return this.format === 'ampm' } }, watch: { value: 'setInputData' }, mounted () { this.setInputData(this.value) }, methods: { emitValue () { if (this.inputHour != null && this.inputMinute != null) { this.$emit('input', `${pad(this.inputHour)}:${pad(this.inputMinute)}`) } }, setPeriod (period) { this.period = period if (this.inputHour != null) { const newHour = this.inputHour + (period === 'am' ? -12 : 12) this.inputHour = this.firstAllowed('hour', newHour) this.emitValue() } }, setInputData (value) { if (value == null || value === '') { this.inputHour = null this.inputMinute = null return } if (value instanceof Date) { this.inputHour = value.getHours() this.inputMinute = value.getMinutes() } else { const [, hour, minute, , period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:\d+)?([ap]m)?$/, '') || [] this.inputHour = period ? this.convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10) this.inputMinute = parseInt(minute, 10) } this.period = this.inputHour < 12 ? 'am' : 'pm' }, convert24to12 (hour) { return hour ? ((hour - 1) % 12 + 1) : 12 }, convert12to24 (hour, period) { return hour % 12 + (period === 'pm' ? 12 : 0) }, onInput (value) { if (this.selectingHour) { this.inputHour = this.isAmPm ? this.convert12to24(value, this.period) : value } else { this.inputMinute = value } this.emitValue() }, onChange () { if (!this.selectingHour) { this.$emit('change', this.value) } else { this.selectingHour = false } }, firstAllowed (type, value) { const allowedFn = type === 'hour' ? this.isAllowedHourCb : this.isAllowedMinuteCb if (!allowedFn) return value // TODO: clean up const range = type === 'minute' ? rangeMinutes : (this.isAmPm ? (value < 12 ? rangeHours12am : rangeHours12pm) : rangeHours24) const first = range.find(v => allowedFn((v + value) % range.length + range[0])) return ((first || 0) + value) % range.length + range[0] }, genClock () { return this.$createElement(VTimePickerClock, { props: { allowedValues: this.selectingHour ? this.isAllowedHourCb : this.isAllowedMinuteCb, color: this.color, dark: this.dark, double: this.selectingHour && !this.isAmPm, format: this.selectingHour ? (this.isAmPm ? this.convert24to12 : val => val) : val => pad(val, 2), light: this.light, max: this.selectingHour ? (this.isAmPm && this.period === 'am' ? 11 : 23) : 59, min: this.selectingHour && this.isAmPm && this.period === 'pm' ? 12 : 0, readonly: this.readonly, scrollable: this.scrollable, size: this.width - ((!this.fullWidth && this.landscape) ? 80 : 20), step: this.selectingHour ? 1 : 5, value: this.selectingHour ? this.inputHour : this.inputMinute }, on: { input: this.onInput, change: this.onChange }, ref: 'clock' }) }, genPickerBody () { return this.$createElement('div', { staticClass: 'v-time-picker-clock__container', key: this.selectingHour }, [this.genClock()]) }, genPickerTitle () { return this.$createElement(VTimePickerTitle, { props: { ampm: this.isAmPm, hour: this.inputHour, minute: this.inputMinute, period: this.period, readonly: this.readonly, selectingHour: this.selectingHour }, on: { 'update:selectingHour': value => (this.selectingHour = value), 'update:period': this.setPeriod }, ref: 'title', slot: 'title' }) } }, render () { return this.genPicker('v-picker--time') } }