@progress/kendo-vue-dateinputs
Version:
480 lines (479 loc) • 15.1 kB
JavaScript
/**
* @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
};