UNPKG

@progress/kendo-vue-dateinputs

Version:
484 lines (483 loc) 15.2 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, createVNode as o, mergeProps as _, ref as O, inject as S, isVNode as P } from "vue"; import { isEqual as B, cloneDate as u } from "@progress/kendo-date-math"; import { provideLocalizationService as E, provideIntlService as A } from "@progress/kendo-vue-intl"; import { KendoDate as z } from "./models/kendo-date.mjs"; import { getDefaultSlots as L, setRef as j, noop as R, getRef as N, canUseDOM as c, kendoThemeMaps as v, validatePackage as K, guid as q } from "@progress/kendo-vue-common"; import { Button as D } from "@progress/kendo-vue-buttons"; import { packageMetadata as H } from "../package-metadata.mjs"; import { isInRange as U, approximateStringMatching as X, defaultFormatPlaceholder as Y, defaultFormat as G } from "./utils.mjs"; import { MIN_DATE as W, MAX_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 { MIN_TIME as Z, MAX_TIME as ee } from "../defaults.mjs"; import { FloatingLabel as te } from "@progress/kendo-vue-labels"; import { caretAltUpIcon as ae, caretAltDownIcon as ie } 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!", De = /* @__PURE__ */ T({ name: "DateInput", model: { event: "changemodel" }, inject: { kendoIntlService: { default: null }, kendoLocalizationService: { default: null } }, emits: { change: (e) => !0, changemodel: (e) => !0, "update:modelValue": (e) => !0, focus: (e) => !0, blur: (e) => !0 }, props: { modelValue: Date, value: Date, defaultValue: Date, format: { type: [String, Object], default: function() { return G; } }, formatPlaceholder: { type: [String, Object], default: function() { return Y; } }, 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(J); } }, min: { type: Date, default: function() { return u(W); } }, maxTime: { type: Date, default: function() { return u(ee); } }, minTime: { type: Date, default: function() { return u(Z); } }, 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() { K(H); const { formatPlaceholder: e, format: t, value: a, defaultValue: i } = this.$props; this.kendoDate = new z(this.intl, e, t), this.kendoDate.setValue(null), this._emptyText = this.kendoDate.getTextAndFormat().text, this.kendoDate.setValue(a || i || null), this._element = null, this._inputId = q(); }, 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: a, fillMode: i, rounded: n } = this.$props; return { "k-dateinput": !0, "k-input": !0, [`k-input-${v.sizeMap[a] || a}`]: a, [`k-input-${i}`]: i, [`k-rounded-${v.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", { event: e }); }, handleBlur(e) { this.$data.isFocused = !1, this.$emit("blur", { event: e }); }, intl() { return A(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: a, format: i } = this.kendoDate.getTextAndFormat(); this.$data.currentFormat = i; const n = this.computedValue, s = X(a, this.$data.currentFormat, t.value, this.selection().start), l = s.length === 1 && s[0][1] === "_"; if (!l) for (let r = 0; r < s.length; r++) this.kendoDate.parsePart(s[r][0], s[r][1]); s.length && s[0][0] !== "_" && this.setSelection(this.selectionBySymbol(s[0][0])), l && 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, a = 0; for (let i = 0; i < this.$data.currentFormat.length; i++) this.$data.currentFormat[i] === e && (a = i + 1, t === -1 && (t = i)); return t < 0 && (t = 0), { start: t, end: a }; }, selectionByIndex(e) { let t = { start: e, end: e }; for (let a = e, i = e - 1; a < this.$data.currentFormat.length || i >= 0; a++, i--) { if (a < this.$data.currentFormat.length && this.$data.currentFormat[a] !== "_") { t = this.selectionBySymbol(this.$data.currentFormat[a]); break; } if (i >= 0 && this.$data.currentFormat[i] !== "_") { t = this.selectionBySymbol(this.$data.currentFormat[i]); break; } } return t; }, switchDateSegment(e) { const { start: t, end: a } = this.selection(); if (t < a && this.$data.currentFormat[t] !== this.$data.currentFormat[a - 1]) { this.setSelection(this.selectionByIndex(e > 0 ? t : a - 1)); return; } const i = this.$data.currentFormat[t]; let n = t + e; for (; n > 0 && n < this.$data.currentFormat.length && !(this.$data.currentFormat[n] !== i && 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 !== a) ? this.setSelection({ start: s + 1, end: n + 1 }) : n < s && (n !== t || s !== a) && this.setSelection({ start: n, end: s }); }, modifyDateSegmentValue(e, t) { if (!this.kendoDate) return; const a = this.computedValue, i = this.$data.currentFormat[this.selection().start], n = this.kendoDate.symbolMap(i), s = ((this.$props.steps || {})[n] || 1) * e; this.kendoDate.modifyPart(i, s), this.setSelection(this.selectionBySymbol(i)), this.triggerChange(t, a); }, validity() { const e = U(this.computedValue, this.$props.min, this.$props.max) && Q(this.computedValue, this.$props.minTime, this.$props.maxTime), t = this.$props.validationMessage !== void 0, a = (!this.$props.required || this.computedValue !== null) && e, i = this.$props.valid !== void 0 ? this.$props.valid : a; 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: i, valueMissing: this.computedValue === null }; } }, mounted() { this._element = N(this, "input"), this.setValidity(), this.$data.hasMounted = !0; }, updated() { this.$data.lastSelectedSymbol && this.setSelection(this.selectionBySymbol(this.$data.lastSelectedSymbol)), this.setValidity(); }, setup() { const e = O(null), t = S("kendoIntlService", {}), a = S("kendoLocalizationService", {}); return { inputRef: e, kendoIntlService: t, kendoLocalizationService: a }; }, render() { const e = L(this), t = E(this), { formatPlaceholder: a, format: i, value: n, modelValue: s, name: l, label: r, id: b, ariaLabel: k, ariaExpanded: V, ariaHasPopup: F, ariaRole: C, ariaControls: I, inputAttributes: M } = this.$props, f = n !== void 0 ? n : s; this.kendoDate.format = i, this.kendoDate.formatPlaceholder = a, 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 = b || this._inputId, w = !this.$props.validityStyles || this.validity().valid, d = o("span", { class: this.wrapperClassNames, dir: this.$props.dir }, [o("input", _({ 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: R, onFocusin: this.handleFocus, onFocusout: this.handleBlur, value: $, name: l, "aria-label": k, "aria-expanded": V, "aria-haspopup": F, "aria-controls": I, "aria-disabled": this.$props.disabled, ref: j(this, "input") }, M), null), e, this.$props.spinners && o("span", { class: "k-input-spinner k-spin-button", onMousedown: this.spinnersMouseDown }, [o(D, { type: "button", tabIndex: -1, icon: "caret-alt-up", svgIcon: ae, 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), o(D, { type: "button", tabIndex: -1, class: "k-spinner-decrease", icon: "caret-alt-down", svgIcon: ie, 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 r ? o(te, { label: r, editorId: y, editorValue: $, editorPlaceholder: this.$props.placeholder, editorValid: w, editorDisabled: this.$props.disabled }, ne(d) ? d : { default: () => [d] }) : d; } }); export { De as DateInput };