UNPKG

vuetify

Version:

Vue Material Component Framework

264 lines (262 loc) 10.9 kB
import { createVNode as _createVNode, mergeProps as _mergeProps } from "vue"; // Styles import "./VTimePicker.css"; // Components import { pad } from "./util.js"; import { VTimePickerClock } from "./VTimePickerClock.js"; import { VTimePickerControls } from "./VTimePickerControls.js"; import { makeVPickerProps, VPicker } from "../VPicker/VPicker.js"; // Composables import { useLocale } from "../../composables/locale.js"; import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities import { computed, onMounted, ref, watch } from 'vue'; import { createRange, genericComponent, omit, propsFactory, useRender } from "../../util/index.js"; // Types const rangeHours24 = createRange(24); const rangeHours12am = createRange(12); const rangeHours12pm = rangeHours12am.map(v => v + 12); const range60 = createRange(60); export const makeVTimePickerProps = propsFactory({ allowedHours: [Function, Array], allowedMinutes: [Function, Array], allowedSeconds: [Function, Array], ampmInTitle: Boolean, disabled: Boolean, format: { type: String, default: 'ampm' }, max: String, min: String, viewMode: { type: String, default: 'hour' }, modelValue: null, readonly: Boolean, scrollable: Boolean, useSeconds: Boolean, ...omit(makeVPickerProps({ title: '$vuetify.timePicker.title' }), ['landscape']) }, 'VTimePicker'); export const VTimePicker = genericComponent()({ name: 'VTimePicker', props: makeVTimePickerProps(), emits: { 'update:hour': val => true, 'update:minute': val => true, 'update:period': val => true, 'update:second': val => true, 'update:modelValue': val => true, 'update:viewMode': val => true }, setup(props, _ref) { let { emit, slots } = _ref; const { t } = useLocale(); const inputHour = ref(null); const inputMinute = ref(null); const inputSecond = ref(null); const lazyInputHour = ref(null); const lazyInputMinute = ref(null); const lazyInputSecond = ref(null); const period = ref('am'); const viewMode = useProxiedModel(props, 'viewMode', 'hour'); const controlsRef = ref(null); const clockRef = ref(null); const isAllowedHourCb = computed(() => { let cb; if (props.allowedHours instanceof Array) { cb = val => props.allowedHours.includes(val); } else { cb = props.allowedHours; } if (!props.min && !props.max) return cb; const minHour = props.min ? Number(props.min.split(':')[0]) : 0; const maxHour = props.max ? Number(props.max.split(':')[0]) : 23; return val => { return val >= Number(minHour) && val <= Number(maxHour) && (!cb || cb(val)); }; }); const isAllowedMinuteCb = computed(() => { let cb; const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value); if (props.allowedMinutes instanceof Array) { cb = val => props.allowedMinutes.includes(val); } else { cb = props.allowedMinutes; } if (!props.min && !props.max) { return isHourAllowed ? cb : () => false; } const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0]; const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59]; const minTime = minHour * 60 + Number(minMinute); const maxTime = maxHour * 60 + Number(maxMinute); return val => { const time = 60 * inputHour.value + val; return time >= minTime && time <= maxTime && isHourAllowed && (!cb || cb(val)); }; }); const isAllowedSecondCb = computed(() => { let cb; const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value); const isMinuteAllowed = isHourAllowed && (!isAllowedMinuteCb.value || inputMinute.value === null || isAllowedMinuteCb.value(inputMinute.value)); if (props.allowedSeconds instanceof Array) { cb = val => props.allowedSeconds.includes(val); } else { cb = props.allowedSeconds; } if (!props.min && !props.max) { return isMinuteAllowed ? cb : () => false; } const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0]; const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59]; const minTime = minHour * 3600 + minMinute * 60 + Number(minSecond || 0); const maxTime = maxHour * 3600 + maxMinute * 60 + Number(maxSecond || 0); return val => { const time = 3600 * inputHour.value + 60 * inputMinute.value + val; return time >= minTime && time <= maxTime && isMinuteAllowed && (!cb || cb(val)); }; }); const isAmPm = computed(() => { return props.format === 'ampm'; }); watch(() => props.modelValue, val => setInputData(val)); onMounted(() => { setInputData(props.modelValue); }); function genValue() { if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) { return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : ''); } return null; } function emitValue() { const value = genValue(); if (value !== null) emit('update:modelValue', value); } function convert24to12(hour) { return hour ? (hour - 1) % 12 + 1 : 12; } function convert12to24(hour, period) { return hour % 12 + (period === 'pm' ? 12 : 0); } function setInputData(value) { if (value == null || value === '') { inputHour.value = null; inputMinute.value = null; inputSecond.value = null; } else if (value instanceof Date) { inputHour.value = value.getHours(); inputMinute.value = value.getMinutes(); inputSecond.value = value.getSeconds(); } else { const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6); inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10); inputMinute.value = parseInt(minute, 10); inputSecond.value = parseInt(second || 0, 10); } period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm'; } function firstAllowed(type, value) { const allowedFn = type === 'hour' ? isAllowedHourCb.value : type === 'minute' ? isAllowedMinuteCb.value : isAllowedSecondCb.value; if (!allowedFn) return value; // TODO: clean up (Note from V2 code) const range = type === 'minute' ? range60 : type === 'second' ? range60 : isAmPm.value ? 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]; } function setPeriod(val) { period.value = val; if (inputHour.value != null) { const newHour = inputHour.value + (period.value === 'am' ? -12 : 12); inputHour.value = firstAllowed('hour', newHour); } emit('update:period', val); emitValue(); return true; } function onInput(value) { if (viewMode.value === 'hour') { inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value; } else if (viewMode.value === 'minute') { inputMinute.value = value; } else { inputSecond.value = value; } } function onChange(value) { switch (viewMode.value || 'hour') { case 'hour': emit('update:hour', value); break; case 'minute': emit('update:minute', value); break; case 'second': emit('update:second', value); break; default: break; } const emitChange = inputHour.value !== null && inputMinute.value !== null && (props.useSeconds ? inputSecond.value !== null : true); if (viewMode.value === 'hour') { viewMode.value = 'minute'; } else if (props.useSeconds && viewMode.value === 'minute') { viewMode.value = 'second'; } if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return; const time = genValue(); if (time === null) return; lazyInputHour.value = inputHour.value; lazyInputMinute.value = inputMinute.value; props.useSeconds && (lazyInputSecond.value = inputSecond.value); emitChange && emitValue(); } useRender(() => { const pickerProps = VPicker.filterProps(props); const timePickerControlsProps = VTimePickerControls.filterProps(props); const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max'])); return _createVNode(VPicker, _mergeProps(pickerProps, { "color": undefined, "class": ['v-time-picker', props.class], "style": props.style }), { title: () => slots.title?.() ?? _createVNode("div", { "class": "v-time-picker__title" }, [t(props.title)]), header: () => _createVNode(VTimePickerControls, _mergeProps(timePickerControlsProps, { "ampm": isAmPm.value || props.ampmInTitle, "ampmReadonly": isAmPm.value && !props.ampmInTitle, "hour": inputHour.value, "minute": inputMinute.value, "period": period.value, "second": inputSecond.value, "viewMode": viewMode.value, "onUpdate:period": val => setPeriod(val), "onUpdate:viewMode": value => viewMode.value = value, "ref": controlsRef }), null), default: () => _createVNode(VTimePickerClock, _mergeProps(timePickerClockProps, { "allowedValues": viewMode.value === 'hour' ? isAllowedHourCb.value : viewMode.value === 'minute' ? isAllowedMinuteCb.value : isAllowedSecondCb.value, "double": viewMode.value === 'hour' && !isAmPm.value, "format": viewMode.value === 'hour' ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2), "max": viewMode.value === 'hour' ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59, "min": viewMode.value === 'hour' && isAmPm.value && period.value === 'pm' ? 12 : 0, "size": 20, "step": viewMode.value === 'hour' ? 1 : 5, "modelValue": viewMode.value === 'hour' ? inputHour.value : viewMode.value === 'minute' ? inputMinute.value : inputSecond.value, "onChange": onChange, "onInput": onInput, "ref": clockRef }), null), actions: slots.actions }); }); } }); //# sourceMappingURL=VTimePicker.js.map