@progress/kendo-react-dateinputs
Version:
React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package
415 lines (414 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 o from "react";
import e from "prop-types";
import { Popup as nt } from "@progress/kendo-react-popup";
import { cloneDate as oe, getDate as ot } from "@progress/kendo-date-math";
import { useId as rt, useAdaptiveModeContext as at, usePropsContext as lt, canUseDOM as re, AsyncFocusBlur as it, classNames as ae, kendoThemeMaps as le, createPropsContext as ut, Keys as k } from "@progress/kendo-react-common";
import { calendarIcon as st } from "@progress/kendo-svg-icons";
import { DateInput as ct } from "../dateinput/DateInput.mjs";
import { Calendar as dt } from "../calendar/components/Calendar.mjs";
import { nullable as a, MAX_DATE as ft, MIN_DATE as mt, isInDateRange as pt, setTime as gt } from "../utils.mjs";
import { toggleCalendar as ie, messages as ht } from "../messages/index.mjs";
import { useLocalization as vt } from "@progress/kendo-react-intl";
import { ToggleButton as wt } from "./ToggleButton.mjs";
import { PickerWrap as bt } from "../common/PickerWrap.mjs";
import { PickerFloatingLabel as yt } from "../hooks/usePickerFloatingLabel.mjs";
import { ActionSheetContent as Ct } from "@progress/kendo-react-layout";
import { AdaptiveMode as Dt } from "../common/AdaptiveMode.mjs";
const ue = o.forwardRef((n, se) => {
const N = rt(n.id), ce = vt(), g = at(), {
defaultShow: de = l.defaultShow,
defaultValue: fe = l.defaultValue,
dateInput: me = l.dateInput,
calendar: pe = l.calendar,
toggleButton: ge = l.toggleButton,
popup: he = l.popup,
pickerWrap: Ot = l.pickerWrap,
disabled: h = l.disabled,
format: ve = l.format,
max: R = l.max,
min: I = l.min,
popupSettings: v = l.popupSettings,
tabIndex: we = l.tabIndex,
weekNumber: be = l.weekNumber,
validityStyles: z = l.validityStyles,
size: S = l.size,
rounded: E = l.rounded,
fillMode: _ = l.fillMode,
autoFocus: ye = l.autoFocus,
show: L,
autoSwitchParts: Ce,
autoSwitchKeys: De,
twoDigitYearMax: ke,
ariaLabel: Oe,
adaptive: Pt,
formatPlaceholder: Pe,
adaptiveTitle: Me,
inputAttributes: Re,
validationMessage: W,
visited: Mt,
value: x,
touched: Rt,
modified: It,
_adaptiveMode: St = g,
valid: K,
focusedDate: Ie,
id: Se,
ariaLabelledBy: Ee,
...q
} = lt(kt, n), B = () => {
if (re)
return b.current && b.current.ownerDocument || window.document;
}, s = () => !!(p.windowWidth && g && p.windowWidth <= (g == null ? void 0 : g.medium) && n.adaptive), d = () => {
const t = O.current !== void 0 ? O.current : x !== void 0 ? x : p.value;
return t !== null ? oe(t) : null;
}, i = () => P.current !== void 0 ? P.current : L !== void 0 ? L : p.show, _e = () => me || l.dateInput, xe = () => ge || l.toggleButton, Be = () => pe || l.calendar, Te = () => he || l.popup, H = () => n.required !== void 0 ? n.required : !1, T = () => {
const t = d() || x || null, r = I, u = R, M = pt(t, r, u), A = W !== void 0, V = (!H() || t != null) && M, F = K !== void 0 ? K : V;
return {
customError: A,
rangeOverflow: t && u.getTime() < t.getTime() || !1,
rangeUnderflow: t && t.getTime() < r.getTime() || !1,
valid: F,
valueMissing: t === null
};
}, Ae = (t) => {
for (const r of t)
D({ windowWidth: r.target.clientWidth });
}, Ve = () => {
c.current && c.current.focus();
}, U = (t) => {
y.current = t;
}, f = (t) => {
i() !== t && (D({ show: t }), t && n.onOpen && n.onOpen.call(void 0, { target: w.current }), !t && n.onClose && n.onClose.call(void 0, { target: w.current }));
}, Fe = (t) => {
const r = d();
return r && t ? gt(t, r) : t;
}, Ne = (t) => {
v != null && v.onMouseDownOutside && v.onMouseDownOutside.call(void 0, t);
}, Y = (t, r) => {
D({ value: oe(t || void 0) }), O.current = t, P.current = !1, s() || (m.current = !0), n.onChange && n.onChange.call(void 0, {
syntheticEvent: r.syntheticEvent,
nativeEvent: r.nativeEvent,
value: d(),
show: i(),
target: w.current
}), O.current = void 0, P.current = void 0, f(!1);
}, ze = (t) => {
const r = Fe(t.value);
Y(r, t);
}, $ = () => {
const { popupClass: t, ...r } = v, u = i(), M = d(), A = M && ot(M), V = ae(t), F = {
popupClass: "k-datepicker-popup",
show: u,
anchor: b.current,
className: V,
id: G,
anchorAlign: {
horizontal: "left",
vertical: "bottom"
},
popupAlign: {
horizontal: "left",
vertical: "top"
},
...r,
onMouseDownOutside: Ne
}, te = {
disabled: h,
value: A,
min: I,
max: R,
weekNumber: be,
focusedDate: Ie,
className: s() ? "k-calendar-lg" : "",
navigation: !s(),
onChange: ze
}, ne = Be(), tt = Te();
return s() ? /* @__PURE__ */ o.createElement(ne, { _ref: U, ...te }) : /* @__PURE__ */ o.createElement(tt, { ...F }, /* @__PURE__ */ o.createElement(ne, { _ref: U, ...te }));
}, j = () => {
D({ focused: !1 }), f(!1);
}, Le = () => {
const { windowWidth: t = 0 } = p, r = {
expand: i(),
onClose: j,
adaptiveTitle: Me,
windowWidth: t
}, u = $();
return /* @__PURE__ */ o.createElement(Dt, { ...r }, /* @__PURE__ */ o.createElement(Ct, { overflowHidden: !0 }, u));
}, We = (t) => {
Y(t.value, t);
}, Ke = () => {
D({ focused: !0 });
}, qe = () => {
f(!i());
}, X = () => {
h || (m.current = !0, f(!i()));
}, He = (t) => {
t.preventDefault();
}, Ue = (t) => {
const { altKey: r, keyCode: u } = t;
if (u === k.esc && i()) {
m.current = !0, f(!1);
return;
}
r && (u === k.up || u === k.down) && (t.preventDefault(), t.stopPropagation(), m.current = u === k.up, f(u === k.down));
}, w = o.useRef(null), b = o.useRef(null), c = o.useRef(null), y = o.useRef(null);
o.useImperativeHandle(
w,
() => ({
props: n,
get element() {
return b.current;
},
get calendar() {
return y.current;
},
get dateInput() {
return c.current;
},
get name() {
return n.name;
},
get show() {
return i();
},
get validity() {
return T();
},
get value() {
return d();
},
get mobileMode() {
return s();
},
togglePopup: qe,
// Hidden Methods but still accessible
focus: Ve
})
), o.useImperativeHandle(se, () => w.current);
const O = o.useRef(void 0), P = o.useRef(void 0), Ye = o.useRef(null), m = o.useRef(!1), Z = o.useRef(!1), C = o.useRef(null), [p, $e] = o.useState({
value: fe,
show: de,
focused: !1
}), [, je] = o.useReducer((t) => t, !0), D = (t) => {
$e((r) => ({ ...r, ...t }));
};
o.useEffect(() => {
y.current && y.current.element && i() && !Z.current && y.current.element.focus({ preventScroll: !0 }), c.current && c.current.element && !i() && m.current && c.current.element.focus({ preventScroll: !0 }), Z.current = i(), m.current = !1;
}), o.useEffect(() => {
var t;
return C.current = re && window.ResizeObserver && new window.ResizeObserver((r) => Ae(r)), i() && je(), (t = B()) != null && t.body && C.current && C.current.observe(B().body), () => {
var r;
clearTimeout(Ye.current), (r = B()) != null && r.body && C.current && C.current.disconnect();
};
}, []);
const G = N + "-popup-id", Xe = $(), Ze = _e(), Ge = d(), Je = xe(), Qe = Le(), J = !z || T().valid, Q = ce.toLanguageString(ie, ht[ie]), et = {
disabled: h,
format: ve,
formatPlaceholder: Pe,
id: Se,
ariaLabelledBy: Ee,
ariaDescribedBy: n.ariaDescribedBy,
ariaLabel: Oe,
max: R,
min: I,
name: n.name,
onChange: We,
required: n.required,
_ref: c,
tabIndex: i() ? -1 : we,
title: n.title,
valid: T().valid,
validationMessage: W,
validityStyles: z,
value: Ge,
label: void 0,
placeholder: p.focused ? null : n.placeholder,
ariaExpanded: i(),
size: null,
fillMode: null,
rounded: null,
autoFill: n.autoFill,
twoDigitYearMax: ke,
enableMouseWheel: n.enableMouseWheel,
autoCorrectParts: n.autoCorrectParts,
autoSwitchParts: Ce,
autoSwitchKeys: De,
allowCaretMode: n.allowCaretMode,
inputAttributes: Re
}, ee = /* @__PURE__ */ o.createElement(
it,
{
onFocus: Ke,
onBlur: s() ? void 0 : j,
onSyncBlur: n.onBlur,
onSyncFocus: n.onFocus
},
(t) => /* @__PURE__ */ o.createElement(o.Fragment, null, /* @__PURE__ */ o.createElement(
"span",
{
...n.label ? {} : q,
ref: b,
className: ae(
"k-input",
"k-datepicker",
{
[`k-input-${le.sizeMap[S] || S}`]: S,
[`k-rounded-${le.roundedMap[E] || E}`]: E,
[`k-input-${_}`]: _,
"k-invalid": !J,
"k-required": H(),
"k-disabled": h
},
n.className
),
onKeyDown: Ue,
style: { width: n.width },
onFocus: t.onFocus,
onBlur: t.onBlur,
onClick: s() ? X : void 0
},
/* @__PURE__ */ o.createElement(
Ze,
{
_ref: c,
ariaRole: "combobox",
ariaExpanded: i(),
ariaControls: G,
autoFocus: ye,
...et
}
),
/* @__PURE__ */ o.createElement(
Je,
{
type: "button",
icon: "calendar",
svgIcon: st,
title: Q,
className: "k-input-button",
rounded: null,
onClick: s() ? void 0 : X,
"aria-label": Q,
fillMode: _,
onMouseDown: He
}
),
!s() && Xe
), s() && Qe)
);
return n.label ? /* @__PURE__ */ o.createElement(
yt,
{
dateInput: c,
label: n.label,
editorId: N,
editorValid: J,
editorDisabled: h,
children: ee,
style: { width: n.width },
...q
}
) : ee;
});
ue.propTypes = {
className: e.string,
defaultShow: e.bool,
defaultValue: e.instanceOf(Date),
disabled: e.bool,
focusedDate: e.instanceOf(Date),
format: e.oneOfType([
e.string,
e.shape({
skeleton: a(e.string),
pattern: a(e.string),
date: a(e.oneOf(["short", "medium", "long", "full"])),
time: a(e.oneOf(["short", "medium", "long", "full"])),
datetime: a(e.oneOf(["short", "medium", "long", "full"])),
era: a(e.oneOf(["narrow", "short", "long"])),
year: a(e.oneOf(["numeric", "2-digit"])),
month: a(e.oneOf(["numeric", "2-digit", "narrow", "short", "long"])),
day: a(e.oneOf(["numeric", "2-digit"])),
weekday: a(e.oneOf(["narrow", "short", "long"])),
hour: a(e.oneOf(["numeric", "2-digit"])),
hour12: a(e.bool),
minute: a(e.oneOf(["numeric", "2-digit"])),
second: a(e.oneOf(["numeric", "2-digit"])),
timeZoneName: a(e.oneOf(["short", "long"]))
})
]),
formatPlaceholder: e.oneOfType([
a(
e.oneOf(["wide", "narrow", "short", "formatPattern"])
),
e.shape({
year: a(e.string),
month: a(e.string),
day: a(e.string),
hour: a(e.string),
minute: a(e.string),
second: a(e.string)
})
]),
id: e.string,
ariaLabelledBy: e.string,
ariaDescribedBy: e.string,
ariaLabel: e.string,
min: e.instanceOf(Date),
max: e.instanceOf(Date),
name: e.string,
popupSettings: e.shape({
animate: a(e.bool),
appendTo: a(e.any),
popupClass: a(e.string)
}),
show: e.bool,
tabIndex: e.number,
title: e.string,
value: e.instanceOf(Date),
weekNumber: e.bool,
width: e.oneOfType([e.number, e.string]),
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"]),
adaptive: e.bool,
adaptiveTitle: e.string,
autoFocus: e.bool,
inputAttributes: e.object
};
const l = {
defaultShow: !1,
defaultValue: null,
dateInput: ct,
calendar: dt,
toggleButton: wt,
popup: nt,
pickerWrap: bt,
disabled: !1,
format: "d",
max: ft,
min: mt,
popupSettings: {},
tabIndex: 0,
weekNumber: !1,
validityStyles: !0,
size: "medium",
rounded: "medium",
fillMode: "solid",
autoFocus: !1
}, kt = ut();
ue.displayName = "KendoReactDatePicker";
export {
ue as DatePicker,
kt as DatePickerPropsContext,
l as datePickerDefaultProps
};