UNPKG

@progress/kendo-vue-dateinputs

Version:
480 lines (479 loc) 15.1 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import { defineComponent as T, ref as _, inject as S, createVNode as r, mergeProps as O, isVNode as P } from "vue"; import { cloneDate as u, isEqual as B } from "@progress/kendo-date-math"; import { provideIntlService as E, provideLocalizationService as A } from "@progress/kendo-vue-intl"; import { KendoDate as z } from "./models/kendo-date.mjs"; import { validatePackage as L, guid as j, kendoThemeMaps as D, canUseDOM as c, getRef as R, getDefaultSlots as N, noop as K, setRef as q } from "@progress/kendo-vue-common"; import { Button as b } from "@progress/kendo-vue-buttons"; import { packageMetadata as H } from "../package-metadata.mjs"; import { defaultFormat as U, defaultFormatPlaceholder as X, approximateStringMatching as Y, isInRange as G } from "./utils.mjs"; import { MAX_DATE as W, MIN_DATE as J } from "../utils.mjs"; import { increaseValue as h, messages as m, decreaseValue as p } from "../messages/main.mjs"; import { isInTimeRange as Q } from "../timepicker/utils.mjs"; import { MAX_TIME as Z, MIN_TIME as ee } from "../defaults.mjs"; import { FloatingLabel as te } from "@progress/kendo-vue-labels"; import { caretAltUpIcon as ie, caretAltDownIcon as ae } from "@progress/kendo-svg-icons"; function ne(e) { return typeof e == "function" || Object.prototype.toString.call(e) === "[object Object]" && !P(e); } const se = "Please enter a valid value!", be = /* @__PURE__ */ T({ name: "DateInput", model: { event: "changemodel" }, inject: { kendoIntlService: { default: null }, kendoLocalizationService: { default: null } }, emits: { change: null, changemodel: null, "update:modelValue": null, focus: null, blur: null }, props: { modelValue: Date, value: Date, defaultValue: Date, format: { type: [String, Object], default: function() { return U; } }, formatPlaceholder: { type: [String, Object], default: function() { return X; } }, rounded: { type: String, default: "medium", validator: function(e) { return ["small", "medium", "large", "full"].includes(e); } }, fillMode: { type: String, default: "solid", validator: function(e) { return ["solid", "flat", "outline"].includes(e); } }, size: { type: String, default: "medium", validator: function(e) { return ["small", "medium", "large"].includes(e); } }, tabIndex: Number, title: String, steps: Object, placeholder: String, max: { type: Date, default: function() { return u(W); } }, min: { type: Date, default: function() { return u(J); } }, maxTime: { type: Date, default: function() { return u(Z); } }, minTime: { type: Date, default: function() { return u(ee); } }, disabled: { type: Boolean, default: !1 }, spinners: { type: Boolean, default: !1 }, name: String, dir: String, label: String, id: String, validationMessage: { type: String, default: se }, required: { type: Boolean, default: !1 }, validityStyles: { type: Boolean, default: !0 }, validate: Boolean, valid: { type: Boolean, default: void 0 }, ariaRole: { type: String, default: "textbox" }, ariaControls: String, ariaLabel: String, ariaExpanded: { type: Boolean, default: void 0 }, ariaHasPopup: { type: String, default: void 0 }, inputAttributes: Object }, data() { return { kendoDate: null, currentFormat: void 0, valueDuringOnChange: void 0, hasMounted: !1, isEmpty: void 0, lastSelectedSymbol: void 0, isFocused: !1 }; }, created() { L(H); const { formatPlaceholder: e, format: t, value: i, defaultValue: a } = this.$props; this.kendoDate = new z(this.intl, e, t), this.kendoDate.setValue(null), this._emptyText = this.kendoDate.getTextAndFormat().text, this.kendoDate.setValue(i || a || null), this._element = null, this._inputId = j(); }, computed: { computedValue() { return this.$data.valueDuringOnChange !== void 0 ? this.$data.valueDuringOnChange : this.kendoDate && this.kendoDate.getDateObject(); }, wrapperClassNames() { const e = !this.$data.hasMounted || !this.$props.validityStyles || this.validity().valid, t = this.$props.disabled, { size: i, fillMode: a, rounded: n } = this.$props; return { "k-dateinput": !0, "k-input": !0, [`k-input-${D.sizeMap[i] || i}`]: i, [`k-input-${a}`]: a, [`k-rounded-${D.roundedMap[n] || n}`]: n, "k-disabled": t, "k-invalid": !e && e !== void 0, "k-focus": this.isFocused, "k-rtl": this.$props.dir === "rtl" }; } }, methods: { selection() { let e = { start: 0, end: 0 }; const t = this.element(); return t !== null && t.selectionStart !== void 0 && (e = { start: t.selectionStart, end: t.selectionEnd }), e; }, element() { return this._element; }, focus(e) { this._element && this._element.focus(e); }, handleFocus(e) { this.$data.isFocused = !0, this.$emit("focus", e); }, handleBlur(e) { this.$data.isFocused = !1, this.$emit("blur", e); }, intl() { return E(this); }, setValidity() { const e = this.element(); e && e.setCustomValidity && e.setCustomValidity(this.validity().valid ? "" : this.$props.validationMessage); }, spinnersMouseDown(e) { const t = this.element(); e.preventDefault(), t && c && document.activeElement !== t && t.focus({ preventScroll: !0 }); }, elementChange(e) { const t = this.element(); if (!t || !this.kendoDate) return; const { text: i, format: a } = this.kendoDate.getTextAndFormat(); this.$data.currentFormat = a; const n = this.computedValue, s = Y(i, this.$data.currentFormat, t.value, this.selection().start), o = s.length === 1 && s[0][1] === "_"; if (!o) for (let l = 0; l < s.length; l++) this.kendoDate.parsePart(s[l][0], s[l][1]); s.length && s[0][0] !== "_" && this.setSelection(this.selectionBySymbol(s[0][0])), o && this.switchDateSegment(1), this.triggerChange(e, n); }, elementClick(e) { this.setSelection(this.selectionByIndex(this.selection().start)); }, wheel(e) { const t = this.element(); c && document.activeElement !== t || (e.deltaY < 0 && (e.preventDefault(), this.increasePart(e)), e.deltaY > 0 && (e.preventDefault(), this.decreasePart(e))); }, increasePart(e) { e.preventDefault(), this.modifyDateSegmentValue(1, e); }, decreasePart(e) { e.preventDefault(), this.modifyDateSegmentValue(-1, e); }, elementKeyDown(e) { if (!e.altKey) { switch (e.keyCode) { case 37: this.switchDateSegment(-1); break; case 38: this.modifyDateSegmentValue(1, e); break; case 39: this.switchDateSegment(1); break; case 40: this.modifyDateSegmentValue(-1, e); break; default: return; } e.preventDefault(); } }, setSelection(e) { const t = this.element(); this.$data.lastSelectedSymbol = this.$data.currentFormat[e.start], c && window.requestAnimationFrame(() => { t && c && document.activeElement === t && t.setSelectionRange(e.start, e.end); }); }, triggerChange(e, t) { this.$data.valueDuringOnChange = this.computedValue, B(t, this.computedValue) || (this.$emit("changemodel", this.computedValue), this.$emit("update:modelValue", this.computedValue), this.$emit("change", { event: e, value: this.computedValue, component: this, target: { name: this.$props.name, value: this.$data.valueDuringOnChange, valueAsDate: this.$data.valueDuringOnChange }, validity: this.validity() })), this.$data.valueDuringOnChange = void 0; }, selectionBySymbol(e) { let t = -1, i = 0; for (let a = 0; a < this.$data.currentFormat.length; a++) this.$data.currentFormat[a] === e && (i = a + 1, t === -1 && (t = a)); return t < 0 && (t = 0), { start: t, end: i }; }, selectionByIndex(e) { let t = { start: e, end: e }; for (let i = e, a = e - 1; i < this.$data.currentFormat.length || a >= 0; i++, a--) { if (i < this.$data.currentFormat.length && this.$data.currentFormat[i] !== "_") { t = this.selectionBySymbol(this.$data.currentFormat[i]); break; } if (a >= 0 && this.$data.currentFormat[a] !== "_") { t = this.selectionBySymbol(this.$data.currentFormat[a]); break; } } return t; }, switchDateSegment(e) { const { start: t, end: i } = this.selection(); if (t < i && this.$data.currentFormat[t] !== this.$data.currentFormat[i - 1]) { this.setSelection(this.selectionByIndex(e > 0 ? t : i - 1)); return; } const a = this.$data.currentFormat[t]; let n = t + e; for (; n > 0 && n < this.$data.currentFormat.length && !(this.$data.currentFormat[n] !== a && this.$data.currentFormat[n] !== "_"); ) n += e; if (this.$data.currentFormat[n] === "_") return; let s = n; for (; s >= 0 && s < this.$data.currentFormat.length && this.$data.currentFormat[s] === this.$data.currentFormat[n]; ) s += e; n > s && (s + 1 !== t || n + 1 !== i) ? this.setSelection({ start: s + 1, end: n + 1 }) : n < s && (n !== t || s !== i) && this.setSelection({ start: n, end: s }); }, modifyDateSegmentValue(e, t) { if (!this.kendoDate) return; const i = this.computedValue, a = this.$data.currentFormat[this.selection().start], n = this.kendoDate.symbolMap(a), s = ((this.$props.steps || {})[n] || 1) * e; this.kendoDate.modifyPart(a, s), this.setSelection(this.selectionBySymbol(a)), this.triggerChange(t, i); }, validity() { const e = G(this.computedValue, this.$props.min, this.$props.max) && Q(this.computedValue, this.$props.minTime, this.$props.maxTime), t = this.$props.validationMessage !== void 0, i = (!this.$props.required || this.computedValue !== null) && e, a = this.$props.valid !== void 0 ? this.$props.valid : i; return { customError: t, rangeOverflow: this.computedValue && this.$props.max.getTime() < this.computedValue.getTime() || !1, rangeUnderflow: this.computedValue && this.computedValue.getTime() < this.$props.min.getTime() || !1, valid: a, valueMissing: this.computedValue === null }; } }, mounted() { this._element = R(this, "input"), this.setValidity(), this.$data.hasMounted = !0; }, updated() { this.$data.lastSelectedSymbol && this.setSelection(this.selectionBySymbol(this.$data.lastSelectedSymbol)), this.setValidity(); }, setup() { const e = _(null), t = S("kendoIntlService", {}), i = S("kendoLocalizationService", {}); return { inputRef: e, kendoIntlService: t, kendoLocalizationService: i }; }, render() { const e = N(this), t = A(this), { formatPlaceholder: i, format: a, value: n, modelValue: s, name: o, label: l, id: v, ariaLabel: k, ariaExpanded: V, ariaHasPopup: F, ariaRole: C, ariaControls: I, inputAttributes: M } = this.$props, f = n !== void 0 ? n : s; this.kendoDate.format = a, this.kendoDate.formatPlaceholder = i, this.valueDuringOnChange = this.valueDuringOnChange ? this.valueDuringOnChange : void 0, f !== void 0 && this.computedValue !== f && this.kendoDate.setValue(f); const { text: g, format: x } = this.kendoDate.getTextAndFormat(); this.$data.currentFormat = x, this.$data.isEmpty = g === this._emptyText; const $ = this.$props.placeholder !== void 0 && this.$data.isEmpty && !this.$data.isFocused ? null : g, y = v || this._inputId, w = !this.$props.validityStyles || this.validity().valid, d = r("span", { class: this.wrapperClassNames, dir: this.$props.dir }, [r("input", O({ role: C, tabindex: this.$props.tabIndex, disabled: this.$props.disabled, title: this.$props.title !== void 0 ? this.$props.title : g, type: "text", spellcheck: !1, autocomplete: "off", autocorrect: "off", class: "k-input-inner", id: y, placeholder: this.$props.placeholder, onWheel: this.wheel, onClick: this.elementClick, onInput: this.elementChange, onKeydown: this.elementKeyDown, onChange: K, onFocusin: this.handleFocus, onFocusout: this.handleBlur, value: $, name: o, "aria-label": k, "aria-expanded": V, "aria-haspopup": F, "aria-controls": I, "aria-disabled": this.$props.disabled, ref: q(this, "input") }, M), null), e, this.$props.spinners && r("span", { class: "k-input-spinner k-spin-button", onMousedown: this.spinnersMouseDown }, [r(b, { type: "button", tabIndex: -1, icon: "caret-alt-up", svgIcon: ie, size: this.$props.size, fillMode: this.$props.fillMode, class: "k-spinner-increase", "aria-label": t.toLanguageString(h, m[h]), title: t.toLanguageString(h, m[h]), onClick: this.increasePart }, null), r(b, { type: "button", tabIndex: -1, class: "k-spinner-decrease", icon: "caret-alt-down", svgIcon: ae, size: this.$props.size, fillMode: this.$props.fillMode, "aria-label": t.toLanguageString(p, m[p]), title: t.toLanguageString(p, m[p]), onClick: this.decreasePart }, null)])]); return l ? r(te, { label: l, editorId: y, editorValue: $, editorPlaceholder: this.$props.placeholder, editorValid: w, editorDisabled: this.$props.disabled }, ne(d) ? d : { default: () => [d] }) : d; } }); export { be as DateInput };