@progress/kendo-vue-dateinputs
Version:
494 lines (493 loc) • 14.5 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 ie, createVNode as n, h as b, ref as ne, inject as ae, isVNode as oe } from "vue";
import { FloatingLabel as ue } from "@progress/kendo-vue-labels";
import { Button as se } from "@progress/kendo-vue-buttons";
import { Popup as le } from "@progress/kendo-vue-popup";
import { cloneDate as s } from "@progress/kendo-date-math";
import { Keys as a, canUseDOM as re, getDefaultSlots as de, templateRendering as c, getListeners as m, getTemplate as T, classNames as _, kendoThemeMaps as k, guid as V, validatePackage as pe } from "@progress/kendo-vue-common";
import { DateInput as he } from "../dateinput/DateInput.mjs";
import { packageMetadata as ce } from "../package-metadata.mjs";
import { isInDateRange as me, MAX_TIME as B, MAX_DATE as fe, MIN_DATE as ge } from "../utils.mjs";
import { toggleDateTimeSelector as l, messages as C } from "../messages/main.mjs";
import { provideLocalizationService as F } from "@progress/kendo-vue-intl";
import { DateTimeSelector as Se } from "./DateTimeSelector.mjs";
import { isInTimeRange as ve } from "../timepicker/utils.mjs";
import { MIN_TIME as M } from "../defaults.mjs";
import { defaultFormatPlaceholder as we } from "../dateinput/utils.mjs";
import { calendarIcon as Ie } from "@progress/kendo-svg-icons";
function f(e) {
return typeof e == "function" || Object.prototype.toString.call(e) === "[object Object]" && !oe(e);
}
const Pe = /* @__PURE__ */ ie({
name: "KendoDateTimePicker",
emits: {
changemodel: (e) => !0,
"update:modelValue": (e) => !0,
iconclick: (e) => !0,
change: (e) => !0,
focus: (e) => !0,
blur: (e) => !0,
keydown: (e) => !0,
open: (e) => !0,
close: (e) => !0
},
props: {
modelValue: {
type: Date,
default: void 0
},
defaultShow: {
type: Boolean,
default: !1
},
defaultValue: {
type: Date,
default: null
},
disabled: {
type: Boolean,
default: !1
},
dateInput: {
type: [String, Object, Function],
default: function() {
}
},
popup: {
type: [String, Object, Function],
default: function() {
}
},
calendar: {
type: [String, Object, Function],
default: function() {
}
},
focusedDate: Date,
format: {
type: [String, Object],
default: function() {
return "g";
}
},
formatPlaceholder: {
type: [String, Object],
default: function() {
return we;
}
},
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 ge;
}
},
max: {
type: Date,
default: function() {
return fe;
}
},
maxTime: {
type: Date,
default: function() {
return s(B);
}
},
minTime: {
type: Date,
default: function() {
return s(M);
}
},
name: String,
label: String,
placeholder: String,
popupSettings: {
type: Object,
default: function() {
return {};
}
},
show: {
type: Boolean,
default: void 0
},
tabIndex: {
type: Number,
default: 0
},
title: {
type: String,
default: function() {
return "";
}
},
steps: {
type: Object,
default: function() {
return {};
}
},
value: Date,
weekNumber: {
type: Boolean,
default: !1
},
width: String,
validationMessage: String,
required: {
type: Boolean,
default: !1
},
validityStyles: {
type: Boolean,
default: !0
},
validate: Boolean,
valid: {
type: Boolean,
default: void 0
},
cancelButton: {
type: Boolean,
default: !0
},
inputAttributes: Object
},
model: {
event: "changemodel"
},
created() {
this._anchor = V(), this._popupId = "popup" + V(), this._wrapper = null, this._dateInput = null, this._dateTimeSelector = null, pe(ce), 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,
shouldFocusDateInput: !1,
isFocused: !1
};
},
computed: {
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 ? s(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();
const e = this.dateInputElement();
this._dateTimeSelector = this.$refs.dateTimeSelector, this._wrapper = this.kendoAnchorRef, this._dateInput = this.dateInputRef, e && e.setAttribute("aria-haspopup", "true");
},
updated() {
const e = this.dateInputElement();
this._dateTimeSelector = this.$refs.dateTimeSelector, this._wrapper = this.kendoAnchorRef, this._dateTimeSelector && this.computedShow && !this._oldShow && this._dateTimeSelector.focus({
preventScroll: !0
}), e && !this.computedShow && this.shouldFocusDateInput && this._dateInput.focus({
preventScroll: !0
}), this.shouldFocusDateInput = !1;
},
setup() {
const e = ne(null), t = ae("kendoLocalizationService", {});
return {
kendoAnchorRef: e,
kendoLocalizationService: t
};
},
render() {
const e = de(this), {
disabled: t,
tabIndex: i,
title: r,
id: g,
format: S,
formatPlaceholder: O,
min: x,
max: R,
weekNumber: E,
focusedDate: A,
width: v,
name: j,
steps: w,
placeholder: P,
validationMessage: z,
required: L,
validityStyles: N,
cancelButton: K,
minTime: I,
maxTime: D,
ariaLabelledBy: De,
ariaDescribedBy: ye,
size: d,
fillMode: y,
rounded: p,
inputAttributes: q
} = this.$props, {
popupClass: U,
appendTo: X,
animate: H
} = this.$props.popupSettings, $ = !this.$props.validityStyles || this.validity().valid, G = this.$props.dateInput ? c.call(this, this.$props.dateInput, m.call(this)) : void 0, J = n(he, {
ref: (h) => {
this.dateInputRef = h;
},
placeholder: P,
disabled: t,
format: S,
formatPlaceholder: O,
id: g,
max: R,
min: x,
minTime: I,
maxTime: D,
name: j,
size: null,
rounded: null,
fillMode: null,
onChange: this.handleValueChange,
required: L,
steps: w,
tabIndex: this.computedShow ? -1 : i,
title: r,
valid: this.validity().valid,
validationMessage: z,
validityStyles: N,
value: this.computedValue,
ariaHasPopup: "dialog",
ariaExpanded: this.computedShow,
ariaRole: "combobox",
ariaControls: this._popupId,
inputAttributes: q
}, f(e) ? e : {
default: () => [e]
}), Q = T.call(this, {
h: b,
template: G,
defaultRendering: J
}), W = this.$props.calendar ? c.call(this, this.$props.calendar, m.call(this)) : void 0, o = n(Se, {
ref: "dateTimeSelector",
cancelButton: K,
value: this.computedValue,
onChange: this.handleValueChange,
onReject: this.handleReject,
disabled: t,
weekNumber: E,
min: this.$props.min,
max: this.$props.max,
minTime: I,
maxTime: D,
focusedDate: A,
format: S,
calendar: W,
steps: w,
onFocus: this.timeSelectorFocus,
onBlur: this.timeSelectorBlur,
onKeydown: this.handleKeyDown
}, null), Y = _("k-datetime-container k-reset", U), Z = this.$props.popup ? c.call(this, this.$props.popup, m.call(this)) : void 0, ee = n(le, {
show: this.computedShow,
anchor: this._anchor,
popupClass: Y,
id: this._popupId,
anchorAlign: {
horizontal: "left",
vertical: "bottom"
},
popupAlign: {
horizontal: "left",
vertical: "top"
},
appendTo: X,
animate: H
}, f(o) ? o : {
default: () => [o]
}), te = T.call(this, {
h: b,
template: Z,
defaultRendering: ee,
defaultSlots: o
}), u = n("div", {
class: _("k-input", "k-datetimepicker", {
[`k-input-${k.sizeMap[d] || d}`]: d,
[`k-input-${y}`]: y,
[`k-rounded-${k.roundedMap[p] || p}`]: p,
"k-invalid": !$,
"k-required": this.required,
"k-disabled": this.$props.disabled
}),
ref: (h) => {
this.kendoAnchorRef = h;
},
onKeydown: this.handleKeyDown,
style: {
width: v
},
onFocusin: this.handleFocus,
onFocusout: this.handleBlur
}, [Q, n(se, {
type: "button",
tabIndex: -1,
icon: "calendar",
svgIcon: Ie,
onMousedown: this.handleIconMouseDown,
onClick: this.handleDateIconClick,
title: F(this).toLanguageString(l, C[l]),
rounded: null,
class: "k-input-button",
"aria-controls": this._popupId,
"aria-label": F(this).toLanguageString(l, C[l])
}, null), te]);
return this.$props.label ? n(ue, {
label: this.$props.label,
editorId: g,
editorValid: $,
editorValue: this.getDateInputText(),
editorPlaceholder: this.$props.placeholder,
editorDisabled: this.$props.disabled,
style: {
width: v
}
}, f(u) ? u : {
default: () => [u]
}) : u;
},
methods: {
validity() {
const e = me(this.computedValue, this.$props.min, this.$props.max) && ve(this.computedValue, this.$props.minTime || M, this.$props.maxTime || B), t = this.$props.validationMessage !== void 0, i = (!this.$props.required || this.computedValue !== null) && e, r = 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: r,
valueMissing: this.computedValue === null
};
},
getDateInputText() {
return this.computedValue ? !0 : this._dateInput ? this._dateInput._element.value : "";
},
focus() {
const e = this.dateInputElement();
e && e.focus();
},
setShow(e) {
this.computedShow !== e && (this.currentShow = e, this.$emit(e ? "open" : "close", {
component: this
}));
},
handleReject() {
this.setShow(!1);
},
handleValueChange(e) {
this.currentValue = s(e.value || void 0), 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.isFocused = !0, this.$emit("focus", {
event: e
});
},
handleBlur(e) {
this.createBlurTimeout(), this.$emit("blur", {
event: e
});
},
timeSelectorBlur(e) {
this.$emit("blur", {
event: e
}), clearTimeout(this._blurTimeout), this.createBlurTimeout();
},
timeSelectorFocus() {
clearTimeout(this._blurTimeout);
},
createBlurTimeout() {
this._blurTimeout = setTimeout(() => {
this.isFocused = !1;
const e = document.activeElement && document.activeElement.closest(`#${this._popupId}`);
this._dateInput && re && document.activeElement !== this._dateInput.element() && !e && this.setShow(!1);
}, 200);
},
handleDateIconClick(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 === a.tab && this._dateInput && e.target !== this._dateInput._element) {
e.preventDefault(), this.$data.shouldFocusDateInput = !0, this.setShow(!1);
return;
}
if (i === a.esc) {
this.shouldFocusDateInput = !0, this.setShow(!1);
return;
}
t && (i === a.up || i === a.down) && (e.preventDefault(), e.stopPropagation(), this.shouldFocusDateInput = i === a.up, this.setShow(i === a.down)), this.$emit("keydown", e);
},
dateInputElement() {
return this._dateInput && this._dateInput.$el || this._wrapper && this._wrapper.querySelector(".k-dateinput-wrap > input.k-input");
}
}
});
export {
Pe as DateTimePicker
};