@progress/kendo-react-dateinputs
Version:
React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package
250 lines (249 loc) • 9.2 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 n from "react";
import m from "prop-types";
import { cloneDate as O } from "@progress/kendo-date-math";
import { Keys as c, getActiveElement as I, noop as H, classNames as u, uTime as l } from "@progress/kendo-react-common";
import { provideIntlService as y, registerForIntl as E } from "@progress/kendo-react-intl";
import { Virtualization as M } from "../virtualization/Virtualization.mjs";
import { TIME_PART as f } from "./models/TimePart.mjs";
import { DayPeriodService as D } from "./services/DayPeriodService.mjs";
import { DOMService as w } from "./services/DOMService.mjs";
import { HoursService as R } from "./services/HoursService.mjs";
import { MinutesService as C } from "./services/MinutesService.mjs";
import { SecondsService as P } from "./services/SecondsService.mjs";
import { debounce as _, MAX_TIME as z, MIDNIGHT_DATE as A } from "../utils.mjs";
const F = 2, S = 0.05, N = 100, k = 0, T = 9, B = {
[c.end]: (h, i) => h[h.length - 1],
[c.home]: (h, i) => h[0],
[c.up]: (h, i) => h[i - 1],
[c.down]: (h, i) => h[i + 1]
}, g = {
[f.dayperiod]: D,
[f.hour]: R,
[f.minute]: C,
[f.second]: P
}, r = class r extends n.Component {
constructor(i) {
super(i), this.intl = null, this._element = null, this.service = null, this.virtualization = null, this.topOffset = 0, this.bottomOffset = 0, this.itemHeight = 0, this.listHeight = 0, this.topThreshold = 0, this.bottomThreshold = 0, this.animateToIndex = !1, this.focus = (t) => {
Promise.resolve().then(() => {
this.element && this.element.focus(t);
});
}, this.itemOffset = (t) => {
if (!this.virtualization || !this.service)
return -1;
const s = this.service.selectedIndex(this.props.value), e = this.virtualization.activeIndex(), o = this.virtualization.itemOffset(e), a = Math.abs(Math.ceil(t) - o);
if (s === e && a < F)
return o;
const d = s > e;
return d && a >= this.bottomThreshold || !d && a > this.topThreshold ? this.virtualization.itemOffset(e + 1) : o;
}, this.calculateHeights = () => {
this.dom.didCalculate && (this.itemHeight = this.dom.itemHeight, this.listHeight = this.dom.timeListHeight, this.topOffset = (this.listHeight - this.itemHeight) / 2, this.bottomOffset = this.listHeight - this.itemHeight, this.props.mobileMode && (this.topOffset += T, this.bottomOffset += T * 2), this.topThreshold = this.itemHeight * S, this.bottomThreshold = this.itemHeight * (1 - S));
}, this.configureServices = ({ min: t, max: s, value: e } = this.props) => {
if (this.service) {
const [o, a] = this.service.limitRange(
t || this.min,
s || this.max,
e || this.props.value
);
this.service.configure(this.serviceSettings({ min: o, max: a }));
}
}, this.serviceSettings = (t) => {
const s = {
boundRange: this.props.boundRange || r.defaultProps.boundRange,
insertUndividedMax: !1,
min: O(this.min),
max: O(this.max),
part: this.props.part,
step: this.step
}, e = Object.assign({}, s, t);
return e.boundRange = e.part.type !== "hour" || this.props.boundRange || r.defaultProps.boundRange, e;
}, this.handleScrollAction = ({ target: t, animationInProgress: s }) => {
if (!(!this.virtualization || !this.service) && t && !s) {
this.animateToIndex = !1;
const e = this.virtualization.itemIndex(this.itemOffset(t.scrollTop)), o = this.service.data(this.props.value)[e];
this.handleChange(o);
}
}, this.handleFocus = (t) => {
const { onFocus: s } = this.props;
s && s.call(void 0, t);
}, this.handleBlur = (t) => {
const { onBlur: s } = this.props;
s && s.call(void 0, t);
}, this.handleMouseOver = () => {
if (!this._element)
return;
const t = I(document);
document && t !== this._element && this.props.show && this._element.focus({ preventScroll: !0 });
}, this.handleKeyDown = (t) => {
if (!this.service)
return;
const { keyCode: s } = t;
(s === c.down || s === c.up || s === c.end || s === c.home) && t.preventDefault();
const o = (B[t.keyCode] || H)(this.service.data(this.props.value), this.service.selectedIndex(this.props.value));
o && this.handleChange(o);
}, this.handleChange = _((t) => {
if (!this.service)
return;
const s = this.service.apply(this.props.value, t.value);
if (this.props.value.getTime() === s.getTime())
return;
const { onChange: e } = this.props;
e && e.call(void 0, s);
}, N), this.dom = new w();
}
get element() {
return this._element;
}
get animate() {
return !!(this.props.smoothScroll && this.animateToIndex);
}
get min() {
return this.props.min || r.defaultProps.min;
}
get max() {
return this.props.max || r.defaultProps.max;
}
get step() {
return this.props.step !== void 0 && this.props.step !== 0 ? Math.floor(this.props.step) : r.defaultProps.step;
}
/**
* @hidden
*/
componentDidMount() {
Promise.resolve().then(() => {
const { unstyled: i } = this.props;
this._element && (this.dom.calculateHeights(this._element, i), this.forceUpdate());
});
}
/**
* @hidden
*/
componentDidUpdate() {
if (!this.virtualization || !this.service)
return;
const i = this.service.selectedIndex(this.props.value);
if (this.virtualization[this.animate ? "animateToIndex" : "scrollToIndex"](i), this.animateToIndex = !0, !this.topOffset && this._element) {
const { unstyled: t } = this.props;
this.dom.calculateHeights(this._element, t);
}
}
/**
* @hidden
*/
render() {
const { part: i, value: t, unstyled: s } = this.props;
if (!i.type || !g[i.type])
return;
const e = s && s.uTime;
this.calculateHeights(), this.intl = y(this), this.service = new g[i.type](this.intl), this.configureServices();
const o = this.service.data(t), a = "translateY(" + this.topOffset + "px)", d = this.service.total(t), v = /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement(
"ul",
{
style: { transform: a, msTransform: a },
className: u(l.ul({ c: e }))
},
o.map((p, b) => /* @__PURE__ */ n.createElement(
"li",
{
key: b,
className: u(l.li({ c: e })),
onClick: () => {
this.handleChange(p);
}
},
/* @__PURE__ */ n.createElement("span", null, p.text)
))
), /* @__PURE__ */ n.createElement("div", { className: u(l.scrollablePlaceholder({ c: e })) }));
return /* @__PURE__ */ n.createElement(
"div",
{
className: u(l.list({ c: e })),
id: String(this.props.id || ""),
tabIndex: this.props.disabled ? -1 : 0,
ref: (p) => {
this._element = p;
},
onKeyDown: this.handleKeyDown,
onFocus: this.handleFocus,
onBlur: this.handleBlur,
onMouseOver: this.handleMouseOver
},
this.dom.didCalculate ? /* @__PURE__ */ n.createElement(
M,
{
bottomOffset: this.bottomOffset,
children: v,
className: u(
l.containerSelector({ c: e }),
l.container({ c: e })
),
itemHeight: this.itemHeight,
maxScrollDifference: this.listHeight,
onScrollAction: this.handleScrollAction,
ref: (p) => {
this.virtualization = p;
},
role: "presentation",
skip: k,
tabIndex: -1,
take: d,
topOffset: this.topOffset,
total: d,
unstyled: s
}
) : /* @__PURE__ */ n.createElement(
"div",
{
className: u(
l.containerSelector({ c: e }),
l.container({ c: e, content: !0, scrollable: !0 })
)
},
v
)
);
}
};
r.propTypes = {
id: m.number,
max: m.instanceOf(Date),
min: m.instanceOf(Date),
part: function(i, t, s) {
const e = i[t];
if (!e || !g[e.type])
throw new Error(`
Invalid prop '${t}' supplied to ${s}.
Supported part types are hour|minute|second|dayperiod.
`);
return null;
},
step: function(i, t, s) {
const e = i[t];
if (e !== void 0 && e <= 0)
throw new Error(`
Invalid prop '${t}' supplied to ${s}.
${t} cannot be less than 1.
`);
return null;
},
value: m.instanceOf(Date),
smoothScroll: m.bool,
show: m.bool
}, r.defaultProps = {
boundRange: !1,
max: z,
min: A,
step: 1,
smoothScroll: !0
};
let x = r;
E(x);
export {
x as TimeList
};