UNPKG

@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
/** * @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 };