@progress/kendo-vue-inputs
Version:
431 lines (430 loc) • 17 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 P, ref as v, inject as V, h as b, createVNode as i, mergeProps as M } from "vue";
import { validatePackage as w, guid as R, getRef as F, canUseDOM as $, kendoThemeMaps as S, getDefaultSlots as z, templateRendering as _, getListeners as C, getTemplate as k, Icon as u, setRef as T } from "@progress/kendo-vue-common";
import { provideIntlService as U, provideLocalizationService as A } from "@progress/kendo-vue-intl";
import { Button as y } from "@progress/kendo-vue-buttons";
import { numericIncreaseValue as d, messages as h, numericDecreaseValue as c } from "../messages/main.mjs";
import { formatValue as m, getStateOrPropsValue as I, sanitizeNumber as x, rangeValue as f, increaseValue as L, decreaseValue as O } from "./utils/main.mjs";
import { packageMetadata as W } from "../package-metadata.mjs";
import { checkIcon as j, exclamationCircleIcon as q, xIcon as K, caretAltUpIcon as H, caretAltDownIcon as Y } from "@progress/kendo-svg-icons";
const G = "Please enter a valid value!", ae = /* @__PURE__ */ P({
model: {
event: "changemodel"
},
emits: {
change: null,
changemodel: null,
"update:modelValue": null,
focus: null,
blur: null
},
props: {
modelValue: Number,
value: Number,
defaultValue: Number,
step: {
type: Number,
default: 1
},
format: [String, Object],
tabIndex: Number,
accessKey: String,
title: String,
placeholder: String,
min: Number,
max: Number,
spinners: {
type: Boolean,
default: !0
},
disabled: {
type: Boolean,
default: !1
},
dir: String,
name: String,
label: String,
validationMessage: String,
validityStyles: {
type: Boolean,
default: !0
},
valid: {
type: Boolean,
default: void 0
},
size: {
type: String,
default: "medium",
validator: function(t) {
return [null, "small", "medium", "large"].includes(t);
}
},
rounded: {
type: String,
default: "medium",
validator: function(t) {
return [null, "small", "medium", "large", "full"].includes(t);
}
},
fillMode: {
type: String,
default: "solid",
validator: function(t) {
return [null, "solid", "flat", "outline"].includes(t);
}
},
required: {
type: Boolean,
default: !1
},
id: String,
ariaLabel: String,
iconName: String,
inputPrefix: [String, Function],
inputSuffix: [String, Function],
showValidationIcon: Boolean,
showLoadingIcon: Boolean,
showClearButton: Boolean,
inputClass: String,
inputType: {
type: String,
default: "tel"
},
wrapperClass: String,
inputAttributes: Object
},
inject: {
kendoIntlService: {
default: null
},
kendoLocalizationService: {
default: null
}
},
data() {
return {
hasMounted: !1,
isInvalid: !1,
isEmpty: !1,
currentValue: 0,
valueDuringOnChange: 0,
currentLooseValue: "",
selectionStart: 0,
selectionEnd: 0,
decimalSelect: !1,
focused: !1,
forceUpdate: !1
};
},
created() {
w(W), this._textBeforeInput = "", this._inputId = R(), this.$data.currentLooseValue = null, this.$data.valueDuringOnChange = void 0, this._intl = U(this), this._symbols = this._intl.numberSymbols(), this.$props.value !== void 0 ? this.$data.currentValue = this.$props.value : this.$props.modelValue !== void 0 ? this.$data.currentValue = this.$props.modelValue : this.$props.defaultValue !== void 0 ? this.$data.currentValue = this.$props.defaultValue : this.$data.currentValue = null;
},
mounted() {
this._input = F(this, "input"), this._elementWrapper = this.elementWrapperRef, this.$data.hasMounted = !0, this._input && (this._textBeforeInput = this._input.value), this.setValidity();
},
updated() {
!($ && document.activeElement !== this._input || !this._input) && this.$data.currentLooseValue !== null && this.$data.forceUpdate && this._input.type !== "number" && (this._input.selectionStart = this.$data.selectionStart, this._input.selectionEnd = this.$data.selectionEnd, this.$data.forceUpdate = !1), this._input && (this._textBeforeInput = this._input.value), this.setValidity();
},
computed: {
computedValue() {
return this.$data.valueDuringOnChange !== void 0 ? this.$data.valueDuringOnChange : this.$data.currentValue;
},
looseValue() {
return m(this.$data.focused ? this.$data.currentLooseValue : I(this.$props.value, this.$data.currentValue), this.$props.format, this._intl);
},
spanClassNames() {
const t = !this.$data.hasMounted || !this.$props.validityStyles || this.validity().valid, e = this.computedValue;
return {
"k-floating-label-container": !0,
"k-focus": this.$data.focused,
"k-empty": !(e === 0 || e || this.$props.placeholder),
"k-invalid": !t && t !== void 0,
"k-rtl": this.$props.dir === "rtl",
[this.inputClass]: this.inputClass
};
},
wrapperClassNames() {
const {
size: t,
fillMode: e,
rounded: s,
required: a,
disabled: l
} = this.$props, n = !this.$props.validityStyles || this.validity().valid;
return {
"k-input": !0,
"k-numerictextbox": !0,
[`k-input-${S.sizeMap[t] || t}`]: t,
[`k-input-${e}`]: e,
[`k-rounded-${S.roundedMap[s] || s}`]: s,
"k-invalid": !n,
"k-required": a,
"k-disabled": l,
"k-loading": this.showLoadingIcon,
[this.wrapperClass]: this.wrapperClass
};
},
inputInnerClass() {
return {
"k-input-inner": !0,
[this.inputClass]: this.inputClass
};
}
},
methods: {
validity() {
const t = this.$props.validationMessage !== void 0, e = !this.$data.valueIsOutOfRange && (!this.$props.required || this.computedValue !== null), s = this.$props.valid !== void 0 ? this.$props.valid : e;
return {
customError: t,
valid: s,
valueMissing: this.computedValue === null
};
},
clearClick(t) {
this.$props.value !== void 0 ? this.$data.currentValue = this.$props.value : this.$props.modelValue !== void 0 ? this.$data.currentValue = this.$props.modelValue : this.$data.currentValue = null, this.$emit("changemodel", null), this.$emit("update:modelValue", null), this.$emit("change", {
event: t,
value: null,
component: this,
target: {
name: this.$props.name,
value: null
},
validity: this.validity()
});
},
focus() {
this._input && this._input.focus();
},
emitFocus(t) {
this.$data.currentLooseValue = this._prevLooseValue, this.$data.focused = !0, this.$emit("focus", t), this.$data.forceUpdate = !0;
},
emitBlur(t) {
this.$data.eventValue = null, this.$data.prevLooseValue = "", this.$data.currentLooseValue = "", this.$data.focused = !1, this.$data.selectionStart = void 0, this.$data.selectionEnd = void 0, this.$data.decimalSelect = !1, this.$data.valueIsCorrected = !1, this.$data.valueIsOutOfRange = !1, this.$emit("blur", t), this.$data.forceUpdate = !0;
},
handleFocus(t) {
this.$data.focused = !0;
},
handleBlur(t) {
this.$data.focused = !1;
},
setValidity() {
this._input && this._input.setCustomValidity && this._input.setCustomValidity(this.validity().valid ? "" : this.$props.validationMessage || G);
},
getCurrentState() {
return {
eventValue: I(this.$props.value, this.$data.currentValue),
prevLooseValue: this._prevLooseValue,
currentLooseValue: this._input.value,
selectionStart: this._input.selectionStart,
selectionEnd: this._input.selectionEnd,
decimalSelect: !1,
valueIsCorrected: !1,
valueIsOutOfRange: !1,
isPaste: this._isPaste,
focused: this.$data.focused
};
},
parseNumber(t) {
return this._intl.parseNumber(t, this.$props.format);
},
elementChange(t) {
const e = this.getCurrentState();
this._isPaste = !1, this.triggerChange(t, x(e, this.$props.format, this._intl));
},
triggerChange(t, e) {
if (this.$props.disabled)
return;
this.$data.valueDuringOnChange = e.eventValue, this.$data.currentValue = e.eventValue;
const s = m(f(e.eventValue, this.$props.min, this.$props.max), this.$props.format, this._intl), a = f(this.parseNumber(s), this.$props.min, this.$props.max);
if (a !== e.eventValue && (e.valueIsOutOfRange = !0, e.eventValue = a, this.$data.valueDuringOnChange = a, this.$data.currentValue = a), e.valueIsCorrected) {
const n = this._elementWrapper;
n && n.className.indexOf("k-invalid") === -1 && (this.$data.isInvalid = !0, setTimeout(() => {
this.$data.isInvalid = !1;
}, 50));
}
const l = this.$props.value !== e.eventValue;
this.$props.value !== void 0 ? this.$data.currentValue = this.$props.value : this.$props.modelValue !== void 0 ? this.$data.currentValue = this.$props.modelValue : this.$data.currentValue = this.$data.valueDuringOnChange, this.$data.prevLooseValue = e.prevLooseValue, this.$data.currentLooseValue = void 0, this.$data.currentLooseValue = e.currentLooseValue, this.$data.selectionStart = e.selectionStart, this.$data.selectionEnd = e.selectionEnd, this.$data.decimalSelect = e.decimalSelect, this.$data.valueIsCorrected = e.valueIsCorrected, this.$data.valueIsOutOfRange = e.valueIsOutOfRange, this.$data.focused = e.focused, this.$data.isPaste = e.isPaste, this.$data.forceUpdate = !this.$data.forceUpdate, l && (this.$emit("changemodel", this.$data.valueDuringOnChange), this.$emit("update:modelValue", this.$data.valueDuringOnChange), this.$emit("change", {
event: t,
value: this.$data.valueDuringOnChange,
component: this,
target: {
name: this.$props.name,
value: this.$data.valueDuringOnChange
},
validity: this.validity()
})), this.$data.valueDuringOnChange = void 0;
},
onPasteHandler(t) {
this._isPaste = !0;
},
increase(t) {
const e = this.getCurrentState();
L(this.parseNumber(String(e.currentLooseValue)), e, this.$props.step, this.$props.min, this.$props.max, this.$props.format, this._intl), this.triggerChange(t, e);
},
decrease(t) {
const e = this.getCurrentState();
O(this.parseNumber(String(e.currentLooseValue)), e, this.$props.step, this.$props.min, this.$props.max, this.$props.format, this._intl), this.triggerChange(t, e);
},
wheel(t) {
!$ || document.activeElement !== this._input || !this._input || (t.deltaY < 0 && (t.preventDefault(), this.increase(t)), t.deltaY > 0 && (t.preventDefault(), this.decrease(t)));
},
keyDown(t) {
let e = this.getCurrentState(), s, a, l, n;
const r = this.parseNumber(String(e.currentLooseValue));
if (!(e.selectionEnd > e.selectionStart && e.selectionEnd - e.selectionStart === String(e.currentLooseValue).length)) {
switch (t.keyCode) {
case 38:
L(r, e, this.$props.step, this.$props.min, this.$props.max, this.$props.format, this._intl);
break;
case 40:
O(r, e, this.$props.step, this.$props.min, this.$props.max, this.$props.format, this._intl);
break;
case 13:
s = m(f(r, this.$props.min, this.$props.max), this.$props.format, this._intl), a = f(this.parseNumber(s), this.$props.min, this.$props.max), e.eventValue = a, e.currentLooseValue = m(a, this.$props.format, this._intl), e.selectionStart = e.selectionEnd = e.currentLooseValue.length;
break;
case 110:
l = this._input, n = this._intl.numberSymbols(), l && (e.currentLooseValue = e.currentLooseValue.slice(0, e.selectionStart) + n.decimal + e.currentLooseValue.slice(e.selectionEnd), e.selectionStart = e.selectionEnd = e.selectionStart + 1, e = x(e, this.$props.format, this._intl));
break;
default:
return;
}
t.preventDefault(), this.triggerChange(t, e);
}
},
spinnersWrapperMouseDown(t) {
$ && this._input && (t.preventDefault(), document.activeElement !== this._input && this._input.focus());
}
},
setup() {
const t = v(null), e = v(null), s = V("kendoLocalizationService", {}), a = V("kendoIntlService", {});
return {
inputRef: t,
elementWrapperRef: e,
kendoLocalizationService: s,
kendoIntlService: a
};
},
render() {
const {
iconName: t,
showValidationIcon: e,
showLoadingIcon: s,
showClearButton: a,
inputAttributes: l
} = this.$props, n = this.$props.id || this._inputId, r = z(this), o = A(this), p = this.validity().valid;
this.$props.value !== void 0 && this.$props.value !== this.$data.currentValue ? this.$data.currentValue = this.$props.value : this.$props.modelValue !== void 0 && this.$props.modelValue !== this.$data.currentValue && (this.$data.currentValue = this.$props.modelValue), this._prevLooseValue = this.$data.currentLooseValue ? this.looseValue : this.looseValue;
const D = _.call(this, this.$props.inputPrefix, C.call(this)), N = _.call(this, this.$props.inputSuffix, C.call(this)), E = k.call(this, {
h: b,
template: D,
additionalProps: {
value: this.computedValue,
valid: p
}
}), B = k.call(this, {
h: b,
template: N,
additionalProps: {
value: this.computedValue,
valid: p
}
}), g = i("span", {
dir: this.$props.dir,
class: this.wrapperClassNames,
style: this.$attrs.style
}, [t && i(u, {
name: t,
class: "k-input-icon"
}, null), this.$props.inputPrefix && i("span", {
class: "k-input-prefix"
}, [E]), i("input", M({
tabindex: this.$props.tabIndex,
accesskey: this.$props.accessKey,
disabled: this.$props.disabled,
title: this.$props.title,
"aria-label": this.$props.ariaLabel,
"aria-valuemin": this.$props.min,
"aria-valuemax": this.$props.max,
"aria-disabled": this.$props.disabled ? "true" : void 0,
placeholder: this.$props.placeholder,
type: this.$props.inputType,
spellcheck: !1,
autocomplete: "off",
autocorrect: "off",
class: this.inputInnerClass,
id: n,
role: "spinbutton",
value: this.looseValue,
name: this.$props.name,
onWheel: this.wheel,
onKeydown: this.keyDown,
onInput: this.elementChange,
onFocus: this.emitFocus,
onBlur: this.emitBlur,
onPaste: this.onPasteHandler,
ref: T(this, "input")
}, l), null), this.$props.inputSuffix && i("span", {
class: "k-input-suffix"
}, [B]), e && p && i(u, {
name: "check",
icon: j,
class: "k-input-validation-icon"
}, null), e && !p && i(u, {
name: "exclamation-circle",
icon: q,
class: "k-input-validation-icon"
}, null), s && i(u, {
name: "loading",
class: "k-input-loading-icon"
}, null), a && this.computedValue !== void 0 && this.computedValue !== null && i("span", {
onClick: this.clearClick,
class: "k-clear-value"
}, [i(u, {
name: "x",
icon: K
}, null)]), r, this.$props.spinners && i("span", {
class: "k-input-spinner k-spin-button",
onMousedown: this.spinnersWrapperMouseDown
}, [i(y, {
type: "button",
tabIndex: -1,
icon: "caret-alt-up",
svgIcon: H,
class: "k-spinner-increase",
rounded: null,
"aria-label": o.toLanguageString(d, h[d]),
title: o.toLanguageString(d, h[d]),
onClick: this.increase
}, null), i(y, {
type: "button",
tabIndex: -1,
class: "k-spinner-decrease",
icon: "caret-alt-down",
svgIcon: Y,
rounded: null,
"aria-label": o.toLanguageString(c, h[c]),
title: o.toLanguageString(c, h[c]),
onClick: this.decrease
}, null)])]);
return this.$props.label ? i("span", {
class: this.spanClassNames,
onFocusin: this.handleFocus,
onFocusout: this.handleBlur,
dir: this.$props.dir
}, [g, this.$props.label ? n ? i("label", {
for: n,
class: "k-floating-label"
}, [this.$props.label]) : i("span", {
class: "k-label"
}, [this.$props.label]) : null]) : g;
}
});
export {
ae as NumericTextBox
};