@progress/kendo-react-dateinputs
Version:
React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package
443 lines (442 loc) • 16.9 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 i from "react";
import e from "prop-types";
import { Popup as _ } from "@progress/kendo-react-popup";
import { cloneDate as w } from "@progress/kendo-date-math";
import { classNames as D, Keys as c, validatePackage as F, canUseDOM as b, IconWrap as P, WatermarkOverlay as z, getActiveElement as B, createPropsContext as L, withIdHOC as N, withPropsContext as V, withAdaptiveModeContext as W } from "@progress/kendo-react-common";
import { provideLocalizationService as m, registerForLocalization as K } from "@progress/kendo-react-intl";
import { arrowsSwapIcon as U } from "@progress/kendo-svg-icons";
import { packageMetadata as q } from "../package-metadata.mjs";
import { DateInput as f } from "../dateinput/DateInput.mjs";
import { MultiViewCalendar as H } from "../calendar/components/MultiViewCalendar.mjs";
import { EMPTY_SELECTIONRANGE as r } from "../calendar/models/SelectionRange.mjs";
import { nullable as h, MAX_DATE as j, MIN_DATE as G } from "../utils.mjs";
import { dateRangePickerCancel as I, messages as l, dateRangePickerSet as C, start as S, end as y, separator as E, swapStartEnd as p } from "../messages/index.mjs";
import { Button as X } from "@progress/kendo-react-buttons";
import { AdaptiveMode as Y } from "../common/AdaptiveMode.mjs";
import { ActionSheetContent as Z } from "@progress/kendo-react-layout";
const o = class o extends i.Component {
constructor(a) {
super(a), this._element = null, this._calendar = null, this._startDateInput = i.createRef(), this._endDateInput = i.createRef(), this.shouldFocusDateInput = !1, this.shouldFocusCalendar = !1, this.showLicenseWatermark = !1, this.focus = () => {
this.startDateInput && this.startDateInput.focus();
}, this.setCalendarRef = (t) => {
this._calendar = t;
}, this.focusCalendarElement = () => {
this._calendar && this._calendar.element && this._calendar.element.focus({ preventScroll: !0 });
}, this.calculateValue = (t, s) => (t.value !== void 0 ? t.value : s.value) || r, this.calculateShow = (t, s) => t.show !== void 0 ? t.show : s.show, this.renderCalendar = () => {
const t = this.value || r, s = {
min: this.min,
max: this.max,
allowReverse: this.props.allowReverse,
mode: "range",
focusedDate: this.props.focusedDate,
disabled: this.props.disabled,
className: this.mobileMode ? "k-calendar-lg" : "",
mobileMode: this.mobileMode,
...this.props.calendarSettings,
value: t,
dir: this.props.dir,
onChange: this.handleCalendarChange
};
return this.props.calendar ? /* @__PURE__ */ i.createElement(this.props.calendar, { ...s }) : /* @__PURE__ */ i.createElement(H, { ...s, ref: this.setCalendarRef });
}, this.renderPopup = () => {
const t = {
popupClass: D("k-calendar-container", "k-daterangepicker-popup"),
animate: this._element !== null,
anchor: this._element,
id: this._popupId,
anchorAlign: {
horizontal: "left",
vertical: "bottom"
},
popupAlign: {
horizontal: "left",
vertical: "top"
},
...this.props.popupSettings,
show: this.show
};
return this.props.popup ? /* @__PURE__ */ i.createElement(this.props.popup, { ...t }, this.renderCalendar()) : /* @__PURE__ */ i.createElement(_, { ...t }, this.renderCalendar());
}, this.renderAdaptivePopup = () => {
const { windowWidth: t = 0 } = this.state, s = {
expand: this.show,
onClose: (n) => this.handleCancel(n),
title: this.props.adaptiveTitle,
windowWidth: t,
footer: {
cancelText: this.localizationService.toLanguageString(
I,
l[I]
),
onCancel: this.handleCancel,
applyText: this.localizationService.toLanguageString(C, l[C]),
onApply: this.handleBlur
}
};
return /* @__PURE__ */ i.createElement(Y, { ...s }, /* @__PURE__ */ i.createElement(Z, { overflowHidden: !0 }, /* @__PURE__ */ i.createElement("div", { className: "k-scrollable-wrap" }, this.renderCalendar())));
}, this.handleReverseClick = (t) => {
const s = {
start: this.value.end,
end: this.value.start
}, n = {
syntheticEvent: t,
nativeEvent: t.nativeEvent
};
this.handleChange(s, n);
}, this.handleReverseMouseDown = (t) => {
t.preventDefault();
}, this.handleFocus = (t) => {
clearTimeout(this.nextTickId), this.shouldFocusDateInput || this.mobileMode && this.setState({ currentValue: this.value });
const { onFocus: s } = this.props;
s && s.call(void 0, t);
}, this.handleClick = () => {
this.shouldFocusDateInput || this.setShow(!0);
}, this.handleBlur = (t) => {
this.nextTick(() => {
this.setShow(!1);
});
const { onBlur: s } = this.props;
s && s.call(void 0, t);
}, this.handleCancel = (t) => {
this.nextTick(() => {
this.setShow(!1), this.setState({ currentValue: r });
});
const { onCancel: s } = this.props;
s && s.call(void 0, t);
}, this.handleEndChange = (t) => {
const s = {
start: this.value.start,
end: w(t.value || void 0)
};
this.handleChange(s, t);
}, this.handleStartChange = (t) => {
const s = {
start: w(t.value || void 0),
end: this.value.end
};
this.handleChange(s, t);
}, this.extractRangeFromValue = (t) => {
if (!Array.isArray(t.value) && !(t.value instanceof Date))
return t.value || r;
const s = Array.isArray(t.value) ? t.value[0] : t.value;
return {
start: this.value.end !== null ? s : this.value.start,
end: this.value.start !== null ? s : this.value.end
};
}, this.handleCalendarChange = (t) => {
const s = this.extractRangeFromValue(t);
this.handleChange(s, t);
}, this.handleKeyDown = (t) => {
const { keyCode: s, altKey: n } = t;
s === c.esc ? (t.preventDefault(), this.shouldFocusDateInput = !0, this.setShow(!1)) : n && s === c.down ? (t.preventDefault(), this.shouldFocusCalendar = !0, this.setShow(!0), this.focusCalendarElement()) : n && s === c.up && (t.preventDefault(), this.shouldFocusDateInput = !0, this.setShow(!1));
}, this.handleChange = (t, s) => {
this.setState({ value: t }), this.valueDuringOnChange = t;
const { onChange: n } = this.props;
if (n) {
const d = {
syntheticEvent: s.syntheticEvent,
nativeEvent: s.nativeEvent,
value: this.value,
show: this.show,
target: this
};
n.call(void 0, d);
}
this.valueDuringOnChange = void 0;
}, this.showLicenseWatermark = !F(q, { component: "DateRangePicker" }), this.state = {
show: this.props.show || this.props.defaultShow || o.defaultProps.defaultShow,
value: this.props.value || this.props.defaultValue || o.defaultProps.defaultValue,
currentValue: r
}, this.nextTick = this.nextTick.bind(this), this.setShow = this.setShow.bind(this), this.focusCalendarElement = this.focusCalendarElement.bind(this), this.focusDateInputElement = this.focusDateInputElement.bind(this);
}
get _popupId() {
return this.props.id + "-popup-id";
}
get _startInputId() {
return this.props.id + "-start-input-id";
}
get _endInputId() {
return this.props.id + "-end-input-id";
}
/**
* Gets the wrapping element of the DateRangePicker.
*/
get element() {
return this._element;
}
/**
* Gets the start DateInput component inside the DatePicker component.
*/
get startDateInput() {
return this._startDateInput.current;
}
/**
* Gets the end DateInput component inside the DatePicker component.
*/
get endDateInput() {
return this._endDateInput.current;
}
/**
* Gets the MultiVieCalendar inside the DateRangePicker.
*/
get calendar() {
return this._calendar;
}
/**
* Gets the value of the DateRangePicker.
*/
get value() {
return (this.valueDuringOnChange !== void 0 ? this.valueDuringOnChange : this.props.value !== void 0 ? this.props.value : this.state.value) || r;
}
/**
* Gets the popup state of the DateRangePicker.
*/
get show() {
return this.showDuringOnChange !== void 0 ? this.showDuringOnChange : this.props.show !== void 0 ? this.props.show : this.state.show;
}
get min() {
return this.props.min !== void 0 ? this.props.min : o.defaultProps.min;
}
get max() {
return this.props.max !== void 0 ? this.props.max : o.defaultProps.max;
}
get document() {
if (b)
return this.element && this.element.ownerDocument || document;
}
get localizationService() {
return m(this);
}
/**
* The mobile mode of the DateRangePicker.
*/
get mobileMode() {
var t;
return !!(this.state.windowWidth && this.props._adaptiveMode && this.state.windowWidth <= ((t = this.props._adaptiveMode) == null ? void 0 : t.medium) && this.props.adaptive);
}
/**
* @hidden
*/
componentDidMount() {
var a;
this.observerResize = b && window.ResizeObserver && new window.ResizeObserver(this.calculateMedia.bind(this)), this.show && this.forceUpdate(), (a = this.document) != null && a.body && this.observerResize && this.observerResize.observe(this.document.body);
}
/**
* @hidden
*/
componentDidUpdate() {
this.shouldFocusCalendar && this.focusCalendarElement(), this.shouldFocusDateInput && this.focusDateInputElement(), this.shouldFocusCalendar = !1, this.shouldFocusDateInput = !1;
}
/**
* @hidden
*/
componentWillUnmount() {
var a;
clearTimeout(this.nextTickId), (a = this.document) != null && a.body && this.observerResize && this.observerResize.disconnect();
}
/**
* @hidden
*/
render() {
const { autoFocus: a, inputAttributes: t } = this.props, s = this.value || r, n = this.mobileMode && this.show ? this.state.currentValue : s, d = (this.props.startDateInputSettings || {}).id || this._startInputId, x = (this.props.endDateInputSettings || {}).id || this._endInputId, k = D(
"k-daterangepicker",
{
"k-disabled": this.props.disabled
},
this.props.className
), O = this.localizationService.toLanguageString(S, l[S]), R = this.localizationService.toLanguageString(y, l[y]), M = this.localizationService.toLanguageString(E, l[E]), g = {
disableSelection: this.mobileMode && !0,
label: O,
format: this.props.format,
min: this.min,
max: this.max,
id: this._startInputId,
disabled: this.props.disabled,
valid: this.props.valid,
tabIndex: this.props.tabIndex,
ariaExpanded: this.show,
clearButton: this.props.clearButton,
...this.props.startDateInputSettings,
value: n.start,
onChange: this.handleStartChange,
inputAttributes: this.props.inputAttributes
}, v = {
disableSelection: this.mobileMode && !0,
label: R,
format: this.props.format,
min: this.min,
max: this.max,
id: this._endInputId,
disabled: this.props.disabled,
valid: this.props.valid,
tabIndex: this.props.tabIndex,
ariaExpanded: this.show,
clearButton: this.props.clearButton,
...this.props.endDateInputSettings,
value: n.end,
onChange: this.handleEndChange,
inputAttributes: this.props.inputAttributes
}, A = /* @__PURE__ */ i.createElement(
X,
{
type: "button",
className: "k-select",
fillMode: "flat",
title: m(this).toLanguageString(p, l[p]),
onMouseDown: this.handleReverseMouseDown,
onClick: this.handleReverseClick,
"aria-controls": d + " " + x,
"aria-label": m(this).toLanguageString(
p,
l[p]
)
},
/* @__PURE__ */ i.createElement(P, { style: { transform: "rotate(90deg)" }, name: "arrows-swap", icon: U })
);
return /* @__PURE__ */ i.createElement(i.Fragment, null, /* @__PURE__ */ i.createElement(
"span",
{
ref: (T) => {
this._element = T;
},
className: k,
style: this.props.style,
id: this.props.id,
"aria-labelledby": this.props.ariaLabelledBy,
"aria-describedby": this.props.ariaDescribedBy,
tabIndex: this.props.tabIndex,
onFocus: this.handleFocus,
onClick: this.handleClick,
onKeyDown: this.handleKeyDown,
onBlur: this.mobileMode ? void 0 : this.handleBlur,
dir: this.props.dir
},
this.props.startDateInput ? /* @__PURE__ */ i.createElement(this.props.startDateInput, { ...g }) : /* @__PURE__ */ i.createElement(
f,
{
...g,
autoFocus: a,
ref: this._startDateInput,
ariaRole: "combobox",
ariaControls: this._popupId
}
),
(this.props.allowReverse || this.props.calendarSettings && this.props.calendarSettings.allowReverse) && this.props.swapButton ? A : M,
this.props.endDateInput ? /* @__PURE__ */ i.createElement(this.props.endDateInput, { ...v }) : /* @__PURE__ */ i.createElement(
f,
{
...v,
ref: this._endDateInput,
ariaRole: "combobox",
ariaControls: this._popupId
}
),
!this.mobileMode && this.renderPopup()
), this.mobileMode && this.renderAdaptivePopup(), this.showLicenseWatermark && /* @__PURE__ */ i.createElement(z, null));
}
focusDateInputElement() {
if (!document || !this.startDateInput || !this.startDateInput.element || !this.endDateInput || !this.endDateInput.element)
return;
const a = B(document);
(this.value.start === null || this.value.end !== null) && a !== this.endDateInput.element ? this.startDateInput.element.focus({ preventScroll: !0 }) : a !== this.startDateInput.element && this.endDateInput.element.focus({ preventScroll: !0 });
}
nextTick(a) {
clearTimeout(this.nextTickId), this.nextTickId = window.setTimeout(() => a());
}
setShow(a) {
const { onOpen: t, onClose: s } = this.props;
this.show !== a && (this.setState({ show: a }), a && t && t.call(void 0, {
target: this
}), !a && s && s.call(void 0, {
target: this
}));
}
calculateMedia(a) {
for (const t of a)
this.setState({ windowWidth: t.target.clientWidth });
}
};
o.displayName = "DateRangePicker", o.propTypes = {
allowReverse: e.bool,
calendarSettings: e.any,
className: e.string,
defaultShow: e.bool,
defaultValue: e.shape({
start: h(e.instanceOf(Date).isRequired),
end: h(e.instanceOf(Date).isRequired)
}),
disabled: e.bool,
endDateInputSettings: e.shape(f.propTypes),
focusedDate: e.instanceOf(Date),
format: e.oneOfType([
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"])
})
]),
id: e.string,
ariaLabelledBy: e.string,
ariaDescribedBy: e.string,
max: e.instanceOf(Date),
min: e.instanceOf(Date),
onBlur: e.func,
onChange: e.func,
onFocus: e.func,
popupSettings: e.any,
show: e.bool,
startDateInputSettings: e.any,
style: e.any,
swapButton: e.any,
tabIndex: e.number,
dir: e.string,
value: e.shape({
start: h(e.instanceOf(Date)),
end: h(e.instanceOf(Date))
}),
autoFocus: e.bool,
inputAttributes: e.object
}, o.defaultProps = {
allowReverse: !1,
defaultShow: !1,
defaultValue: r,
disabled: !1,
format: "d",
max: j,
min: G,
swapButton: !1,
autoFocus: !1
};
let u = o;
const J = L(), Q = N(
V(
J,
W(u)
)
);
Q.displayName = "KendoReactDateRangePicker";
K(u);
export {
Q as DateRangePicker,
J as DateRangePickerPropsContext,
u as DateRangePickerWithoutContext
};