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