@progress/kendo-react-dateinputs
Version:
React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package
253 lines (252 loc) • 8.63 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 t from "prop-types";
import { cloneDate as O } from "@progress/kendo-date-math";
import { Keys as T, classNames as l, uTime as h, getActiveElement as R } from "@progress/kendo-react-common";
import { provideIntlService as k, provideLocalizationService as S, registerForIntl as C, registerForLocalization as M } from "@progress/kendo-react-intl";
import { selectNow as L, messages as x, now as I } from "../messages/index.mjs";
import { TimeList as P } from "./TimeList.mjs";
import { MIN_TIME as A, MAX_TIME as K, MIDNIGHT_DATE as _ } from "../utils.mjs";
import { TIME_PART as d } from "./models/TimePart.mjs";
import { isInTimeRange as $, getNow as z, snapTime as N, generateSnappers as B, timeInRange as W } from "./utils.mjs";
import { Button as j } from "@progress/kendo-react-buttons";
const v = new RegExp(
`${d.hour}|${d.minute}|${d.second}|${d.dayperiod}|literal`
), a = class a extends n.Component {
constructor(i) {
super(i), this._element = null, this._nowButton = null, this.dateFormatParts = [], this.timeLists = [], this.focus = (s, e) => {
Promise.resolve().then(() => {
e && this._nowButton && this._nowButton.element && this._nowButton.element.focus();
const o = this.timeLists[0];
!e && this.state.activeListIndex === -1 && !this.hasActiveButton() && o && o.element && o.focus(s);
});
}, this.timeFormatReducer = (s, e) => s + e.pattern, this.timeFormatFilter = (s, e, o) => {
const r = e >= 1 && o[e - 1];
return r && r && s.type === "literal" ? v.test(r.type || "") : v.test(s.type || "");
}, this.focusList = (s) => {
this.timeLists.length && this.timeLists.reduce(this.listReducer, []).map((e) => s === 1 ? e.next : e.prev).map((e) => e && e.element && e.element.focus({ preventScroll: !0 }));
}, this.listReducer = (s, e, o, r) => s.length || e.props.id !== this.state.activeListIndex ? s : [
{
next: r[o + 1] || e,
prev: r[o - 1] || e
}
], this.showNowButton = () => !this.hasSteps() && this.props.nowButton && $(z(), this.min, this.max), this.handleKeyDown = (s) => {
const { keyCode: e } = s;
switch (e) {
case T.left:
s.preventDefault(), this.focusList(
0
/* Left */
);
return;
case T.right:
s.preventDefault(), this.focusList(
1
/* Right */
);
return;
default:
return;
}
}, this.handleListBlur = () => {
this.nextTick(() => {
this.setState({ activeListIndex: -1 });
});
}, this.handleListFocus = (s) => {
clearTimeout(this.nextTickId), this.setState({
activeListIndex: s
});
}, this.handleChange = (s) => {
const { onChange: e } = this.props;
e && e.call(void 0, s);
}, this.snapTime = N(B(this.props.steps, this.props.min || a.defaultProps.min)), this.state = {
activeListIndex: -1
}, this.hasActiveButton = this.hasActiveButton.bind(this);
}
/**
* @hidden
*/
get element() {
return this._element;
}
get value() {
return W(this.snapTime(O(this.props.value || _)), this.min, this.max);
}
get intl() {
return k(this);
}
get min() {
return this.snapTime(this.props.min || a.defaultProps.min);
}
get max() {
return this.snapTime(this.props.max || a.defaultProps.max);
}
get steps() {
return this.props.steps || a.defaultProps.steps;
}
get boundRange() {
return this.props.boundRange !== void 0 ? this.props.boundRange : a.defaultProps.boundRange;
}
/**
* @hidden
*/
componentWillUnmount() {
clearTimeout(this.nextTickId);
}
componentDidMount() {
const { onMount: i } = this.props;
i && i.call(void 0, this.value);
}
/**
* @hidden
*/
render() {
const { format: i, smoothScroll: s, onNowClick: e, className: o, disabled: r, mobileMode: w, show: D, onNowKeyDown: E, unstyled: g } = this.props, m = g && g.uTime;
this.snapTime = N(B(this.steps, this.min)), this.dateFormatParts = this.intl.splitDateFormat(i || a.defaultProps.format).filter(this.timeFormatFilter);
const F = l(
h.part({
c: m,
mobileMode: w,
disabled: r
}),
o
);
this.timeLists = [];
const b = S(this), y = b.toLanguageString(L, x[L]);
return /* @__PURE__ */ n.createElement("div", { className: F }, /* @__PURE__ */ n.createElement("div", { className: l(h.header({ c: m })) }, /* @__PURE__ */ n.createElement("span", { className: l(h.title({ c: m })) }, this.intl.formatDate(this.value, this.dateFormatParts.reduce(this.timeFormatReducer, ""))), this.showNowButton() && /* @__PURE__ */ n.createElement(
j,
{
type: "button",
ref: (u) => {
this._nowButton = u;
},
className: l(h.now({ c: m })),
fillMode: "flat",
themeColor: "base",
title: y,
onKeyDown: E,
"aria-label": y,
onClick: e,
tabIndex: r ? -1 : 0
},
b.toLanguageString(I, x[I])
)), /* @__PURE__ */ n.createElement("div", { className: l(h.listContainer({ c: m })), onKeyDown: this.handleKeyDown }, /* @__PURE__ */ n.createElement("span", { className: l(h.highlight({ c: m })) }), this.dateFormatParts.map((u, c) => u.type !== "literal" ? /* @__PURE__ */ n.createElement(
"div",
{
key: c,
className: l(
h.listWrapper({
c: m,
focused: c === this.state.activeListIndex
})
),
role: "presentation",
tabIndex: -1
},
/* @__PURE__ */ n.createElement(
"span",
{
className: l(h.title({ c: m })),
onMouseDown: (p) => {
p.preventDefault();
}
},
this.intl.dateFieldName(u)
),
/* @__PURE__ */ n.createElement(
P,
{
min: this.min,
max: this.max,
boundRange: this.boundRange,
part: u,
step: u.type ? this.steps[u.type] : 1,
smoothScroll: s,
ref: (p) => {
p && this.timeLists.push(p);
},
id: c,
onFocus: () => {
this.handleListFocus(c);
},
onBlur: this.handleListBlur,
onChange: this.handleChange,
value: this.value,
disabled: r,
show: D,
mobileMode: w,
unstyled: g
}
)
) : /* @__PURE__ */ n.createElement("div", { key: c, className: l(h.separator({ c: m })) }, u.pattern))));
}
nextTick(i) {
clearTimeout(this.nextTickId), this.nextTickId = window.setTimeout(() => i());
}
hasActiveButton() {
const i = R(document);
return this._nowButton && i === this._nowButton.element;
}
hasSteps() {
const i = Object.keys(this.steps);
return i.length !== i.reduce((s, e) => s + this.steps[e], 0);
}
};
a.propTypes = {
cancelButton: t.bool,
disabled: t.bool,
format: t.oneOfType([
t.string,
t.shape({
skeleton: t.string,
pattern: t.string,
date: t.oneOf(["short", "medium", "long", "full"]),
time: t.oneOf(["short", "medium", "long", "full"]),
datetime: t.oneOf(["short", "medium", "long", "full"]),
era: t.oneOf(["narrow", "short", "long"]),
year: t.oneOf(["numeric", "2-digit"]),
month: t.oneOf(["numeric", "2-digit", "narrow", "short", "long"]),
day: t.oneOf(["numeric", "2-digit"]),
weekday: t.oneOf(["narrow", "short", "long"]),
hour: t.oneOf(["numeric", "2-digit"]),
hour12: t.bool,
minute: t.oneOf(["numeric", "2-digit"]),
second: t.oneOf(["numeric", "2-digit"]),
timeZoneName: t.oneOf(["short", "long"])
})
]),
max: t.instanceOf(Date),
min: t.instanceOf(Date),
nowButton: t.bool,
steps: t.shape({
hour: t.number,
minute: t.number,
second: t.number
}),
smoothScroll: t.bool,
tabIndex: t.number,
value: t.instanceOf(Date),
show: t.bool
}, a.defaultProps = {
value: null,
disabled: !1,
nowButton: !0,
cancelButton: !0,
format: "hh:mm a",
min: A,
max: K,
steps: {},
boundRange: !1
};
let f = a;
C(f);
M(f);
export {
f as TimePart
};