@progress/kendo-vue-dateinputs
Version:
485 lines (484 loc) • 14.3 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 Z, ref as ee, inject as te, createVNode as n, h as y, isVNode as ie } from "vue";
import { FloatingLabel as ne } from "@progress/kendo-vue-labels";
import { Popup as oe } from "@progress/kendo-vue-popup";
import { cloneDate as b } from "@progress/kendo-date-math";
import { guid as _, getDefaultSlots as le, classNames as f, templateRendering as $, getListeners as D, getTemplate as k, kendoThemeMaps as V, canUseDOM as se, Keys as o } from "@progress/kendo-vue-common";
import { provideLocalizationService as ae } from "@progress/kendo-vue-intl";
import { Button as ue } from "@progress/kendo-vue-buttons";
import { toggleClock as T, messages as B, toggleTimeSelector as C } from "../messages/main.mjs";
import { DateInput as re } from "../dateinput/DateInput.mjs";
import { TimeSelector as de } from "./TimeSelector.mjs";
import { MIN_TIME as he, MAX_TIME as pe, setTime as F, MIDNIGHT_DATE as ce } from "../utils.mjs";
import { isInRange as me, isBiggerThanMax as fe, isSmallerThanMin as ge } from "./utils.mjs";
import { defaultFormatPlaceholder as Se } from "../dateinput/utils.mjs";
import { clockIcon as we } from "@progress/kendo-svg-icons";
function g(e) {
return typeof e == "function" || Object.prototype.toString.call(e) === "[object Object]" && !ie(e);
}
const ze = /* @__PURE__ */ Z({
name: "KendoTimePicker",
emits: {
changemodel: null,
"update:modelValue": null,
iconclick: null,
change: null,
focus: null,
blur: null,
keydown: null,
open: null,
close: null
},
model: {
event: "changemodel"
},
props: {
cancelButton: {
type: Boolean,
default: !0
},
nowButton: {
type: Boolean,
default: void 0
},
defaultShow: {
type: Boolean,
default: !1
},
modelValue: {
type: Date,
default: void 0
},
defaultValue: {
type: Date,
default: function() {
return null;
}
},
dateInput: {
type: [String, Object, Function],
default: function() {
}
},
popup: {
type: [String, Object, Function],
default: function() {
}
},
disabled: {
type: Boolean,
default: !1
},
format: {
type: [String, Object],
default: function() {
return "t";
}
},
formatPlaceholder: {
type: [String, Object],
default: function() {
return Se;
}
},
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);
}
},
id: String,
ariaLabelledBy: String,
ariaDescribedBy: String,
min: {
type: Date,
default: function() {
return he;
}
},
max: {
type: Date,
default: function() {
return pe;
}
},
name: String,
label: String,
placeholder: String,
popupSettings: {
type: Object,
default: function() {
return {};
}
},
show: {
type: Boolean,
default: void 0
},
tabIndex: {
type: Number,
default: 0
},
steps: {
type: Object,
default: function() {
return {};
}
},
smoothScroll: {
type: Boolean,
default: !0
},
title: {
type: String,
default: function() {
return "";
}
},
value: {
type: Date,
default: function() {
}
},
width: [Number, String],
validationMessage: String,
required: {
type: Boolean,
default: !1
},
validityStyles: {
type: Boolean,
default: !0
},
validate: Boolean,
valid: {
type: Boolean,
default: void 0
},
inputAttributes: Object
},
created() {
this._anchor = _(), this._popupId = "popup" + _(), this._element = null, this._wrapper = null, this._dateInput = null, this._timeSelector = null, this.shouldFocusDateInput = !1, this.currentValue = this.$props.defaultValue, this.currentShow = this.$props.defaultShow;
},
inject: {
kendoLocalizationService: {
default: null
}
},
data() {
return {
currentValue: null,
currentShow: !1,
valueDuringOnChange: void 0,
showDuringOnChange: void 0,
isFocused: !1
};
},
computed: {
timeSelector() {
return this._timeSelector;
},
computedValue() {
const e = this.valueDuringOnChange !== void 0 ? this.valueDuringOnChange : this.$props.value !== void 0 ? this.$props.value : this.$props.modelValue !== void 0 ? this.$props.modelValue : this.$data.currentValue;
return e !== null ? b(e) : null;
},
computedShow() {
return this.showDuringOnChange !== void 0 ? this.showDuringOnChange : this.$props.show !== void 0 ? this.$props.show : this.currentShow;
}
},
watch: {
show: function(e, t) {
this._oldShow = t;
},
currentShow: function(e, t) {
this._oldShow = t;
}
},
mounted() {
this.computedShow && this.$forceUpdate(), this._dateInput = this.dateInputRef, this._timeSelector = this.$refs.timeSelector, this._wrapper = this.kendoAnchorRef, this._dateInput && this._dateInput.element() && this._dateInput.element().setAttribute("aria-haspopup", "true");
},
updated() {
this._dateInput = this.dateInputRef, this._timeSelector = this.$refs.timeSelector, this._wrapper = this.kendoAnchorRef, this._timeSelector && this.computedShow && !this._oldShow ? this._timeSelector.focusActiveList() : this._dateInput && this._dateInput.element() && !this.computedShow && this.shouldFocusDateInput && this._dateInput.element().focus({
preventScroll: !0
}), this.shouldFocusDateInput = !1;
},
setup() {
const e = ee(null), t = te("kendoLocalizationService", {});
return {
kendoAnchorRef: e,
kendoLocalizationService: t
};
},
render() {
const e = le(this), {
disabled: t,
tabIndex: i,
title: r,
id: l,
placeholder: d,
format: s,
formatPlaceholder: M,
smoothScroll: O,
width: S,
name: R,
steps: w,
cancelButton: z,
nowButton: x,
validationMessage: A,
required: j,
validityStyles: L,
ariaLabelledBy: Ie,
ariaDescribedBy: ve,
size: h,
rounded: p,
fillMode: I,
inputAttributes: P
} = this.$props, {
popupClass: E,
appendTo: K,
animate: N
} = this.$props.popupSettings, c = !this.$props.validityStyles || this.validity().valid;
f("k-picker-wrap", {
"k-invalid": !c,
"k-disabled": t,
"k-focus": this.isFocused
});
const q = f("k-group k-reset", E), v = ae(this), U = v.toLanguageString(T, B[T]), H = v.toLanguageString(C, B[C]), G = this.$props.dateInput ? $.call(this, this.$props.dateInput, D.call(this)) : void 0, X = n(re, {
ref: (m) => {
this.dateInputRef = m;
},
placeholder: d,
disabled: t,
format: s,
formatPlaceholder: M,
id: l,
size: null,
rounded: null,
fillMode: null,
max: this.normalizeTime(this.$props.max),
min: this.normalizeTime(this.$props.min),
name: R,
onChange: this.handleInputValueChange,
required: j,
steps: w,
tabIndex: this.computedShow ? -1 : i,
title: r,
valid: this.validity().valid,
validationMessage: A,
validityStyles: L,
value: this.computedValue && this.normalizeTime(this.computedValue),
ariaHasPopup: "grid",
ariaExpanded: this.computedShow,
ariaRole: "combobox",
ariaControls: this._popupId,
inputAttributes: P
}, g(e) ? e : {
default: () => [e]
}), a = n(de, {
ref: "timeSelector",
cancelButton: z,
disabled: t,
nowButton: x,
format: s,
min: this.$props.min,
max: this.$props.max,
steps: w,
smoothScroll: O,
value: this.computedValue,
onChange: this.handleValueChange,
onReject: this.handleValueReject,
onFocus: this.timeFocus,
onBlur: this.timeBlur,
onKeydown: this.handleKeyDown
}, null), J = k.call(this, {
h: y,
template: G,
defaultRendering: X,
additionalListeners: {
change: this.handleInputValueChange
}
}), Q = this.$props.popup ? $.call(this, this.$props.popup, D.call(this)) : void 0, W = n(oe, {
show: this.computedShow,
anchor: this._anchor,
class: q,
id: this._popupId,
anchorAlign: {
horizontal: "left",
vertical: "bottom"
},
popupAlign: {
horizontal: "left",
vertical: "top"
},
appendTo: K,
animate: N
}, g(a) ? a : {
default: () => [a]
}), Y = k.call(this, {
h: y,
template: Q,
defaultRendering: W,
defaultSlots: a
}), u = n("div", {
class: f("k-input", "k-timepicker", {
[`k-input-${V.sizeMap[h] || h}`]: h,
[`k-input-${I}`]: I,
[`k-rounded-${V.roundedMap[p] || p}`]: p,
"k-invalid": !c,
"k-required": this.required,
"k-disabled": this.$props.disabled,
"k-focus": this.isFocused
}),
onKeydown: this.handleKeyDown,
style: {
width: S
},
onFocusin: this.handleFocus,
onFocusout: this.handleBlur,
ref: (m) => {
this.kendoAnchorRef = m;
}
}, [J, n(ue, {
type: "button",
tabIndex: -1,
icon: "clock",
svgIcon: we,
onMousedown: this.handleIconMouseDown,
onClick: this.handleIconClick,
title: H,
rounded: null,
class: "k-input-button",
"aria-controls": this._popupId,
"aria-label": U
}, null), Y]);
return this.$props.label ? n(ne, {
label: this.$props.label,
editorId: l,
editorValid: c,
editorValue: this.getDateInputText(),
editorPlaceholder: this.$props.placeholder,
editorDisabled: this.$props.disabled,
style: {
width: S
}
}, g(u) ? u : {
default: () => [u]
}) : u;
},
methods: {
validity() {
const e = this.computedValue && this.normalizeTime(this.computedValue), t = this.normalizeTime(this.$props.min), i = this.normalizeTime(this.$props.max), r = me(e, t, i), l = this.$props.validationMessage !== void 0, d = (!this.$props.required || this.computedValue !== null) && r, s = this.$props.valid !== void 0 ? this.$props.valid : d;
return {
customError: l,
rangeOverflow: fe(e, i),
rangeUnderflow: ge(e, t),
valid: s,
valueMissing: this.computedValue === null
};
},
getDateInputText() {
return this.computedValue ? !0 : this._dateInput ? this._dateInput._element.value : "";
},
focus() {
this._dateInput && this._dateInput.focus();
},
normalizeTime(e) {
return F(ce, e);
},
setShow(e) {
this.computedShow !== e && (this.currentShow = e, this.$emit(e ? "open" : "close", {
component: this
}));
},
mergeTime(e) {
return this.computedValue && e ? F(this.computedValue, e) : e;
},
handleInputValueChange(e) {
const t = this.mergeTime(e.value);
this.handleValueChange({
...e,
value: t
});
},
handleValueChange(e) {
this.currentValue = b(e.value), this.valueDuringOnChange = e.value, this.showDuringOnChange = !1, this.shouldFocusDateInput = !0, this.$emit("changemodel", this.computedValue), this.$emit("update:modelValue", this.computedValue), this.$emit("change", {
event: e.event,
value: this.computedValue,
show: this.computedShow,
component: this,
target: {
name: this.$props.name,
value: this.computedValue,
valueAsDate: this.computedValue
}
}), this.valueDuringOnChange = void 0, this.showDuringOnChange = void 0, this.setShow(!1);
},
handleFocus(e) {
this._oldShow = this.computedShow, this.isFocused = !0, this.$emit("focus", e);
},
handleBlur(e) {
this.createBlurTimeout(), this.$emit("blur", e);
},
timeBlur(e) {
this.$emit("blur", e), clearTimeout(this._blurTimeout), this.createBlurTimeout();
},
timeFocus() {
clearTimeout(this._blurTimeout);
},
createBlurTimeout() {
this._blurTimeout = setTimeout(() => {
this.isFocused = !1;
const e = document.activeElement && document.activeElement.closest(`#${this._popupId}`);
this._dateInput && se && document.activeElement !== this._dateInput.element() && !e && this.setShow(!1);
}, 200);
},
handleValueReject(e) {
this.setShow(!1);
},
handleIconClick(e) {
this.$props.disabled || (this.shouldFocusDateInput = !0, this.setShow(!this.computedShow), this.$emit("iconclick", e));
},
handleIconMouseDown(e) {
e.preventDefault();
},
handleKeyDown(e) {
const {
altKey: t,
keyCode: i
} = e;
if (i === o.tab && this._dateInput && e.target !== this._dateInput._element) {
e.preventDefault(), this.shouldFocusDateInput = !0, this.setShow(!1);
return;
}
if (i === o.esc) {
this.shouldFocusDateInput = !0, this.setShow(!1);
return;
}
t && (i === o.up || i === o.down) && (e.preventDefault(), e.stopPropagation(), this.shouldFocusDateInput = i === o.up, this.setShow(i === o.down)), this.$emit("keydown", e);
}
}
});
export {
ze as TimePicker
};