UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

424 lines (416 loc) 17.2 kB
import { defineComponent, resolveComponent, createVNode, mergeProps, withCtx, renderSlot, createCommentVNode } from 'vue'; import { getValueByPath, isMobile, matchWithGroups } from './helpers.mjs'; import { getOptions } from './config.mjs'; import { B as BaseComponentMixin } from './BaseComponentMixin-d78ed3dc.mjs'; import { F as FormElementMixin } from './FormElementMixin-386fdfd0.mjs'; import { s as script$1 } from './Datepicker-fba608d1.mjs'; import { s as script$2 } from './Timepicker-1cd721c9.mjs'; const AM = 'AM'; const PM = 'PM'; /** * An input with a simple dropdown/modal for selecting a date and time, uses native datetimepicker for mobile * @displayName Datetimepicker * @style _datetimepicker.scss */ var script = defineComponent({ name: 'ODatetimepicker', components: { [script$1.name]: script$1, [script$2.name]: script$2 }, configField: 'datetimepicker', mixins: [FormElementMixin, BaseComponentMixin], inheritAttrs: false, emits: ['update:modelValue', 'change-year', 'change-month', 'icon-right-click', 'active-change'], props: { modelValue: { type: Date }, editable: { type: Boolean, default: false }, size: String, placeholder: String, disabled: Boolean, iconRight: String, iconRightClickable: Boolean, inline: Boolean, openOnFocus: Boolean, position: String, mobileNative: { type: Boolean, default: true }, minDatetime: Date, maxDatetime: Date, datetimeFormatter: { type: Function }, datetimeParser: { type: Function }, datetimeCreator: { type: Function, default: (date) => { const datetimeCreator = getValueByPath(getOptions(), 'datetimepicker.datetimeCreator', undefined); if (typeof datetimeCreator === 'function') { return datetimeCreator(date); } else { return date; } } }, datepicker: Object, timepicker: Object, locale: { type: [String, Array], default: () => { return getValueByPath(getOptions(), 'locale'); } }, appendToBody: Boolean, datepickerWrapperClass: [String, Function, Array], timepickerWrapperClass: [String, Function, Array], }, data() { return { newValue: this.modelValue }; }, computed: { datepickerWrapperClasses() { return [ this.computedClass('datepickerWrapperClass', 'o-dtpck__date') ]; }, timepickerWrapperClasses() { return [ this.computedClass('timepickerWrapperClass', 'o-dtpck__time') ]; }, computedValue: { get() { return this.newValue; }, set(value) { if (value) { let val = new Date(value.getTime()); if (this.newValue) { // restore time part if ((value.getDate() !== this.newValue.getDate() || value.getMonth() !== this.newValue.getMonth() || value.getFullYear() !== this.newValue.getFullYear()) && value.getHours() === 0 && value.getMinutes() === 0 && value.getSeconds() === 0) { val.setHours(this.newValue.getHours(), this.newValue.getMinutes(), this.newValue.getSeconds(), 0); } } else { val = this.datetimeCreator(value); } // check min and max range if (this.minDatetime && val < this.minDatetime) { val = this.minDatetime; } else if (this.maxDatetime && val > this.maxDatetime) { val = this.maxDatetime; } this.newValue = new Date(val.getTime()); } else { this.newValue = value; } this.$emit('update:modelValue', this.newValue); } }, localeOptions() { return new Intl.DateTimeFormat(this.locale, { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: this.enableSeconds() ? 'numeric' : undefined }).resolvedOptions(); }, dtf() { return new Intl.DateTimeFormat(this.locale, { year: this.localeOptions.year || 'numeric', month: this.localeOptions.month || 'numeric', day: this.localeOptions.day || 'numeric', hour: this.localeOptions.hour || 'numeric', minute: this.localeOptions.minute || 'numeric', second: this.enableSeconds() ? this.localeOptions.second || 'numeric' : undefined, // @ts-ignore to update types hourCycle: !this.isHourFormat24() ? 'h12' : 'h23' }); }, isMobileNative() { return this.mobileNative; }, isMobile() { return this.isMobileNative && isMobile.any(); }, minDate() { if (!this.minDatetime) { return this.datepicker ? this.datepicker.minDate : null; } return new Date(this.minDatetime.getFullYear(), this.minDatetime.getMonth(), this.minDatetime.getDate(), 0, 0, 0, 0); }, maxDate() { if (!this.maxDatetime) { return this.datepicker ? this.datepicker.maxDate : null; } return new Date(this.maxDatetime.getFullYear(), this.maxDatetime.getMonth(), this.maxDatetime.getDate(), 0, 0, 0, 0); }, minTime() { if (!this.minDatetime || (this.newValue === null || typeof this.newValue === 'undefined')) { return this.timepicker ? this.timepicker.minTime : null; } return this.minDatetime; }, maxTime() { if (!this.maxDatetime || (this.newValue === null || typeof this.newValue === 'undefined')) { return this.timepicker ? this.timepicker.maxTime : null; } return this.maxDatetime; }, datepickerSize() { return this.datepicker && this.datepicker.size ? this.datepicker.size : this.size; }, timepickerSize() { return this.timepicker && this.timepicker.size ? this.timepicker.size : this.size; }, timepickerDisabled() { return this.timepicker && this.timepicker.disabled ? this.timepicker.disabled : this.disabled; } }, watch: { modelValue(value) { this.newValue = value; } }, methods: { enableSeconds() { if (this.$refs.timepicker) { return this.$refs.timepicker.enableSeconds; } return false; }, isHourFormat24() { if (this.$refs.timepicker) { return this.$refs.timepicker.isHourFormat24; } return !this.localeOptions.hour12; }, defaultDatetimeParser(date) { const datetimeParser = getValueByPath(getOptions(), 'datetimepicker.datetimeParser', undefined); if (typeof this.datetimeParser === 'function') { return this.datetimeParser(date); } else if (typeof datetimeParser === 'function') { return datetimeParser(date); } else { if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') { let dayPeriods = [AM, PM, AM.toLowerCase(), PM.toLowerCase()]; if (this.$refs.timepicker) { dayPeriods.push(this.$refs.timepicker.amString); dayPeriods.push(this.$refs.timepicker.pmString); } const parts = this.dtf.formatToParts(new Date()); const formatRegex = parts.map((part, idx) => { if (part.type === 'literal') { if (idx + 1 < parts.length && parts[idx + 1].type === 'hour') { return `[^\\d]+`; } return part.value.replace(/ /g, '\\s?'); } else if (part.type === 'dayPeriod') { return `((?!=<${part.type}>)(${dayPeriods.join('|')})?)`; } return `((?!=<${part.type}>)\\d+)`; }).join(''); const datetimeGroups = matchWithGroups(formatRegex, date); // We do a simple validation for the group. // If it is not valid, it will fallback to Date.parse below if (datetimeGroups.year && datetimeGroups.year.length === 4 && datetimeGroups.month && datetimeGroups.month <= 12 && datetimeGroups.day && datetimeGroups.day <= 31 && datetimeGroups.hour && datetimeGroups.hour >= 0 && datetimeGroups.hour < 24 && datetimeGroups.minute && datetimeGroups.minute >= 0 && datetimeGroups.minute <= 59) { const d = new Date(datetimeGroups.year, datetimeGroups.month - 1, datetimeGroups.day, datetimeGroups.hour, datetimeGroups.minute, datetimeGroups.second || 0); return d; } } return new Date(Date.parse(date)); } }, defaultDatetimeFormatter(date) { const datetimeFormatter = getValueByPath(getOptions(), 'datetimepicker.datetimeFormatter', undefined); if (typeof this.datetimeFormatter === 'function') { return this.datetimeFormatter(date); } else if (typeof datetimeFormatter === 'function') { return datetimeFormatter(date); } else { return this.dtf.format(date); } }, /* * Parse date from string */ onChangeNativePicker(event) { const date = event.target.value; const s = date ? date.split(/\D/) : []; if (s.length >= 5) { const year = parseInt(s[0], 10); const month = parseInt(s[1], 10) - 1; const day = parseInt(s[2], 10); const hours = parseInt(s[3], 10); const minutes = parseInt(s[4], 10); // Seconds are omitted intentionally; they are unsupported by input // type=datetime-local and cause the control to fail native validation this.computedValue = new Date(year, month, day, hours, minutes); } else { this.computedValue = null; } }, formatNative(value) { const date = new Date(value); if (value && !isNaN(date.getTime())) { const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const hours = date.getHours(); const minutes = date.getMinutes(); const seconds = date.getSeconds(); return year + '-' + ((month < 10 ? '0' : '') + month) + '-' + ((day < 10 ? '0' : '') + day) + 'T' + ((hours < 10 ? '0' : '') + hours) + ':' + ((minutes < 10 ? '0' : '') + minutes) + ':' + ((seconds < 10 ? '0' : '') + seconds); } return ''; }, toggle() { this.$refs.datepicker.toggle(); } }, mounted() { if (!this.isMobile || this.inline) { // $refs attached, it's time to refresh datepicker (input) if (this.newValue) { this.$refs.datepicker.$forceUpdate(); } } } }); function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_o_timepicker = resolveComponent("o-timepicker"); const _component_o_datepicker = resolveComponent("o-datepicker"); const _component_o_input = resolveComponent("o-input"); return !_ctx.isMobile || _ctx.inline ? createVNode(_component_o_datepicker, mergeProps({ key: 0, ref: "datepicker", modelValue: _ctx.computedValue, "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => _ctx.computedValue = $event) }, _ctx.datepicker, { class: _ctx.datepickerWrapperClasses, rounded: _ctx.rounded, "open-on-focus": _ctx.openOnFocus, position: _ctx.position, inline: _ctx.inline, editable: _ctx.editable, expanded: _ctx.expanded, "close-on-click": false, "date-formatter": _ctx.defaultDatetimeFormatter, "date-parser": _ctx.defaultDatetimeParser, "min-date": _ctx.minDate, "max-date": _ctx.maxDate, icon: _ctx.icon, "icon-right": _ctx.iconRight, "icon-right-clickable": _ctx.iconRightClickable, "icon-pack": _ctx.iconPack, size: _ctx.datepickerSize, placeholder: _ctx.placeholder, range: false, disabled: _ctx.disabled, "mobile-native": _ctx.isMobileNative, locale: _ctx.locale, "append-to-body": _ctx.appendToBody, onFocus: _ctx.onFocus, onBlur: _ctx.onBlur, "onActive-change": _cache[3] || (_cache[3] = $event => _ctx.$emit('active-change', $event)), "onIcon-right-click": _cache[4] || (_cache[4] = $event => _ctx.$emit('icon-right-click')), "onChange-month": _cache[5] || (_cache[5] = $event => _ctx.$emit('change-month', $event)), "onChange-year": _cache[6] || (_cache[6] = $event => _ctx.$emit('change-year', $event)) }), { footer: withCtx(() => [createVNode("div", { class: _ctx.timepickerWrapperClasses }, [createVNode(_component_o_timepicker, mergeProps({ ref: "timepicker" }, _ctx.timepicker, { modelValue: _ctx.computedValue, "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => _ctx.computedValue = $event), inline: "", editable: _ctx.editable, "min-time": _ctx.minTime, "max-time": _ctx.maxTime, size: _ctx.timepickerSize, disabled: _ctx.timepickerDisabled, "mobile-native": _ctx.isMobileNative, locale: _ctx.locale }), null, 16 /* FULL_PROPS */ , ["modelValue", "editable", "min-time", "max-time", "size", "disabled", "mobile-native", "locale"])], 2 /* CLASS */ ), _ctx.$slots.footer !== undefined ? renderSlot(_ctx.$slots, "footer", { key: 0 }) : createCommentVNode("v-if", true)]), _: 1 }, 16 /* FULL_PROPS */ , ["modelValue", "class", "rounded", "open-on-focus", "position", "inline", "editable", "expanded", "date-formatter", "date-parser", "min-date", "max-date", "icon", "icon-right", "icon-right-clickable", "icon-pack", "size", "placeholder", "disabled", "mobile-native", "locale", "append-to-body", "onFocus", "onBlur"]) : createVNode(_component_o_input, mergeProps({ key: 1, ref: "input", type: "datetime-local", autocomplete: "off", value: _ctx.formatNative(_ctx.computedValue), placeholder: _ctx.placeholder, size: _ctx.datepickerSize, icon: _ctx.icon, "icon-pack": _ctx.iconPack, rounded: _ctx.rounded, max: _ctx.formatNative(_ctx.maxDate), min: _ctx.formatNative(_ctx.minDate), disabled: _ctx.disabled, readonly: false }, _ctx.$attrs, { "use-html5-validation": _ctx.useHtml5Validation, onChange: _ctx.onChangeNativePicker, onFocus: _ctx.onFocus, onBlur: _ctx.onBlur }), null, 16 /* FULL_PROPS */ , ["value", "placeholder", "size", "icon", "icon-pack", "rounded", "max", "min", "disabled", "use-html5-validation", "onChange", "onFocus", "onBlur"]); } script.render = render; script.__file = "src/components/datetimepicker/Datetimepicker.vue"; export { script as s };