@progress/kendo-vue-dateinputs
Version:
484 lines (483 loc) • 15.2 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, 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
};