@progress/kendo-react-dateinputs
Version:
React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package
381 lines (380 loc) • 13 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 * as r from "react";
import e from "prop-types";
import { cloneDate as D, isEqual as ke } from "@progress/kendo-date-math";
import { Button as $ } from "@progress/kendo-react-buttons";
import { caretAltUpIcon as _e, caretAltDownIcon as Fe } from "@progress/kendo-svg-icons";
import { useInternationalization as He, useLocalization as Be } from "@progress/kendo-react-intl";
import { useId as qe, useUnstyled as ze, usePropsContext as Q, classNames as h, uDateInput as O, createPropsContext as Ue, getActiveElement as ee } from "@progress/kendo-react-common";
import { FloatingLabel as We } from "@progress/kendo-react-labels";
import { DateInput as je } from "@progress/kendo-dateinputs-common";
import { DEFAULT_FORMAT as Ke, DEFAULT_FORMAT_PLACEHOLDER as Je, isInRange as Ye } from "./utils.mjs";
import { nullable as u, MAX_DATE as Xe, MIN_DATE as Ze, MIN_TIME as Ge, MAX_TIME as $e } from "../utils.mjs";
import { increaseValue as T, messages as M, decreaseValue as S } from "../messages/index.mjs";
import { isInTimeRange as Qe } from "../timepicker/utils.mjs";
import et from "../common/ClearButton.mjs";
import { DateInputIntl as tt } from "./dateInputIntl.mjs";
const nt = "Please enter a valid value!", ne = r.forwardRef((t, re) => {
var G;
const ae = qe(t.id), ie = He(), E = Be(), le = ze(), F = Q(te, t).unstyled || le, {
format: P = l.format,
size: oe = l.size,
rounded: ue = l.rounded,
fillMode: se = l.fillMode,
formatPlaceholder: ce = l.formatPlaceholder,
spinners: de = l.spinners,
disabled: I = l.disabled,
min: me = l.min,
max: fe = l.max,
minTime: ge = l.minTime,
maxTime: ve = l.maxTime,
validityStyles: ye = l.validityStyles,
validationMessage: H = l.validationMessage,
placeholder: f = l.placeholder,
enableMouseWheel: be = l.enableMouseWheel,
autoCorrectParts: he = l.autoCorrectParts,
autoSwitchParts: Oe = l.autoSwitchParts,
allowCaretMode: Ee = l.allowCaretMode,
twoDigitYearMax: Ie = l.twoDigitYearMax,
ariaHasPopup: xe = l.ariaHasPopup,
autoFocus: g = l.autoFocus
} = Q(te, t), d = () => w.current !== void 0 ? w.current : a.current && a.current.value, B = () => {
const n = a.current && a.current.currentText || "", i = d();
return f != null && !Ae.focused && !i ? f : n;
}, q = () => t.required !== void 0 ? t.required : !1, R = () => {
const n = d() || t.value, i = me, b = fe, V = Ye(n, i, b) && Qe(n, ge, ve), k = H !== void 0, _ = (!q() || n != null) && V, Ve = t.valid !== void 0 ? t.valid : _;
return {
customError: k,
rangeOverflow: n && b.getTime() < n.getTime() || !1,
rangeUnderflow: n && n.getTime() < i.getTime() || !1,
valid: Ve,
valueMissing: n === null
};
}, Ce = () => {
o.current && o.current.focus();
}, z = () => new tt(ie), x = () => {
const n = d();
return {
format: P,
steps: t.steps,
formatPlaceholder: ce,
placeholder: f,
selectPreviousSegmentOnBackspace: !0,
value: t.value || n,
intlService: z(),
autoFill: t.autoFill !== void 0 ? t.autoFill : !1,
enableMouseWheel: be,
autoCorrectParts: he,
autoSwitchParts: Oe,
autoSwitchKeys: t.autoSwitchKeys || [],
twoDigitYearMax: Ie,
allowCaretMode: Ee
};
}, we = (n) => {
s.current && s.current.classList.add("k-focus"), A({ focused: !0 }), g && J(!0);
}, De = (n) => {
s.current && s.current.classList.remove("k-focus"), A({ focused: !1 });
}, Te = (n, i) => typeof n != typeof i ? !0 : typeof n == "string" && typeof i == "string" ? n !== i : typeof n == "object" && typeof i == "object" ? JSON.stringify(n) !== JSON.stringify(i) : !1, Me = (n) => typeof n == "string" ? n : {
inputFormat: n,
displayFormat: n
}, U = (n) => {
w.current = d(), Ne(), m.current = n, w.current = void 0;
}, W = (n) => {
t.onChange && t.onChange(n);
}, j = (n) => {
ee(document) === o.current && n.preventDefault();
}, Se = () => new je(o.current, {
...x(),
format: Me(x().format),
events: {
focus: we,
blur: De,
valueChange: U,
click: W
}
}), K = () => {
o.current && o.current.setCustomValidity && o.current.setCustomValidity(
R().valid ? "" : H || l.validationMessage
);
}, J = r.useCallback(
(n) => {
var i;
if (o.current && g && n) {
const b = (a == null ? void 0 : a.current).currentText, V = (a == null ? void 0 : a.current).currentText.search(/[^a-zA-Z]/), k = b[V], _ = b.split(k)[0].length;
s.current && s.current.classList.add("k-focus"), (i = a == null ? void 0 : a.current) == null || i.selectNearestSegment(_);
}
},
[g]
), Pe = (n) => {
!o.current || !a.current || U(n);
}, Re = (n) => {
n.preventDefault();
const i = ee(document);
o.current && i !== o.current && o.current.focus({ preventScroll: !0 });
}, c = (n) => {
const i = d();
m.current && t.onChange && !ke(m.current.oldValue, i) && t.onChange.call(void 0, {
syntheticEvent: n,
nativeEvent: m.current.event,
value: m.current.value,
target: C.current
}), m.current = null;
}, Le = (n) => {
var i;
(i = a.current) == null || i.modifyDateSegmentValue(1), c(n);
}, pe = (n) => {
var i;
(i = a.current) == null || i.modifyDateSegmentValue(-1), c(n);
}, C = r.useRef(null), o = r.useRef(null), s = r.useRef(null);
r.useImperativeHandle(
C,
() => ({
props: t,
get options() {
return x();
},
get text() {
return B();
},
get element() {
return o.current;
},
get name() {
return t.name;
},
get value() {
return d();
},
get validity() {
return R();
},
// hidden methods
focus: Ce,
updateOnPaste: Pe
})
), r.useImperativeHandle(re, () => C.current);
const a = r.useRef(null), L = r.useRef(null), p = r.useRef(!1), w = r.useRef(null), m = r.useRef(null), v = r.useRef(t), [Ae, A] = r.useState({ focused: !1 }), [, Ne] = r.useReducer((n) => n + 1, 0);
r.useLayoutEffect(() => {
p.current || (a.current = Se(), L.current = a.current.dateObject, p.current = !0);
}, []), r.useEffect(() => (K(), p.current || s.current && s.current.addEventListener("wheel", j, { passive: !1 }), g && (A({ focused: !0 }), J(!0)), () => {
s.current && s.current.removeEventListener("wheel", j);
}), []), r.useEffect(() => {
K(), a.current && ((Te(v.current.format, P) || v.current.readonly !== t.readonly || JSON.stringify(v.current.steps) !== JSON.stringify(t.steps) || z().locale !== a.current.options.intlService.locale) && a.current.setOptions(x(), !0), v.current.value !== t.value && (L.current.getValue() !== null || t.value !== null) && L.current.setValue(t.value), t.ariaExpanded !== void 0 && t.ariaExpanded && (a.current.options.placeholder = null), t.ariaExpanded !== void 0 && !t.ariaExpanded && (a.current.options.placeholder = f), a.current.refreshElementValue(), v.current = {
format: P,
readonly: t.readonly,
ariaExpanded: t.ariaExpanded,
steps: t.steps,
value: t.value
});
});
const Y = t.id || ae + "-accessibility-id", y = F && F.uDateInput, X = B(), N = !ye || R().valid;
r.useImperativeHandle(t._ref, () => C.current);
const Z = /* @__PURE__ */ r.createElement(
"span",
{
ref: (n) => {
s.current = n;
},
style: t.label ? void 0 : { width: t.width },
dir: t.dir,
className: h(
O.wrapper({
c: y,
size: oe,
fillMode: se,
rounded: ue,
disabled: I,
required: q(),
invalid: !N
}),
t.className
)
},
/* @__PURE__ */ r.createElement(
"input",
{
ref: (n) => {
o.current = n;
},
role: t.ariaRole || "textbox",
readOnly: t.readonly,
tabIndex: t.tabIndex || 0,
disabled: I,
title: t.title !== void 0 ? t.title : X,
type: "text",
spellCheck: !1,
autoComplete: "off",
autoCorrect: "off",
autoFocus: g,
className: h(O.inputInner({ c: y })),
id: Y,
value: X,
"aria-label": t.ariaLabel,
"aria-labelledby": t.ariaLabelledBy,
"aria-describedby": t.ariaDescribedBy,
"aria-haspopup": xe,
"aria-disabled": I,
"aria-expanded": t.ariaExpanded,
"aria-controls": t.ariaControls,
"aria-required": t.required,
"aria-invalid": !N,
onKeyDown: c,
onChange: c,
onWheel: c,
onInput: c,
onClick: c,
name: t.name,
...t.inputAttributes
}
),
t.children,
t.clearButton && t.value && /* @__PURE__ */ r.createElement(et, { onClick: W, key: "clearbutton" }),
de && /* @__PURE__ */ r.createElement("span", { className: h(O.inputSpinner({ c: y })), onMouseDown: Re }, /* @__PURE__ */ r.createElement(
$,
{
tabIndex: -1,
type: "button",
rounded: null,
className: h(O.spinnerIncrease({ c: y })),
icon: "caret-alt-up",
svgIcon: _e,
"aria-label": E.toLanguageString(T, M[T]),
title: E.toLanguageString(T, M[T]),
onClick: Le
}
), /* @__PURE__ */ r.createElement(
$,
{
tabIndex: -1,
type: "button",
rounded: null,
className: h(O.spinnerDecrease({ c: y })),
icon: "caret-alt-down",
svgIcon: Fe,
"aria-label": E.toLanguageString(S, M[S]),
title: E.toLanguageString(S, M[S]),
onClick: pe
}
))
);
return t.label ? /* @__PURE__ */ r.createElement(
We,
{
label: t.label,
editorId: Y,
editorValue: (G = o.current) == null ? void 0 : G.value,
editorValid: N,
editorDisabled: I,
children: Z,
style: { width: t.width }
}
) : Z;
});
ne.propTypes = {
value: e.instanceOf(Date),
format: e.oneOfType([
u(e.string),
e.shape({
skeleton: e.string,
pattern: e.string,
date: e.oneOf(["short", "medium", "long", "full"]),
time: e.oneOf(["short", "medium", "long", "full"]),
datetime: e.oneOf(["short", "medium", "long", "full"]),
era: e.oneOf(["narrow", "short", "long"]),
year: e.oneOf(["numeric", "2-digit"]),
month: e.oneOf(["numeric", "2-digit", "narrow", "short", "long"]),
day: e.oneOf(["numeric", "2-digit"]),
weekday: e.oneOf(["narrow", "short", "long"]),
hour: e.oneOf(["numeric", "2-digit"]),
hour12: e.bool,
minute: e.oneOf(["numeric", "2-digit"]),
second: e.oneOf(["numeric", "2-digit"]),
timeZoneName: e.oneOf(["short", "long"])
})
]),
formatPlaceholder: e.oneOfType([
u(
e.oneOf(["wide", "narrow", "short", "formatPattern"])
),
e.shape({
year: u(e.string),
month: u(e.string),
day: u(e.string),
hour: u(e.string),
minute: u(e.string),
second: u(e.string)
})
]),
width: e.oneOfType([e.string, e.number]),
tabIndex: e.number,
title: e.string,
steps: e.shape({
year: u(e.number),
month: u(e.number),
day: u(e.number),
hour: u(e.number),
minute: u(e.number),
second: u(e.number)
}),
min: e.instanceOf(Date),
max: e.instanceOf(Date),
disabled: e.bool,
spinners: e.bool,
name: e.string,
dir: e.string,
label: e.node,
id: e.string,
ariaLabelledBy: e.string,
ariaDescribedBy: e.string,
ariaLabel: e.string,
ariaRole: e.string,
ariaHasPopup: e.oneOfType([
e.bool,
e.oneOf(["grid", "dialog"])
]),
ariaExpanded: e.oneOfType([e.bool]),
onChange: e.func,
validationMessage: e.string,
required: e.bool,
valid: e.bool,
size: e.oneOf([null, "small", "medium", "large"]),
rounded: e.oneOf([null, "small", "medium", "large", "full"]),
fillMode: e.oneOf([null, "solid", "flat", "outline"]),
autoFocus: e.bool,
inputAttributes: e.object
};
const l = {
format: Ke,
size: "medium",
rounded: "medium",
fillMode: "solid",
formatPlaceholder: Je,
spinners: !1,
disabled: !1,
max: D(Xe),
min: D(Ze),
minTime: D(Ge),
maxTime: D($e),
validityStyles: !0,
validationMessage: nt,
placeholder: null,
enableMouseWheel: !0,
autoCorrectParts: !0,
autoSwitchParts: !0,
allowCaretMode: !1,
twoDigitYearMax: 68,
ariaHasPopup: "grid",
autoFocus: !1
}, te = Ue();
ne.displayName = "KendoReactDateInput";
export {
ne as DateInput,
te as DateInputPropsContext,
l as dateInputDefaultProps
};