UNPKG

@progress/kendo-react-dateinputs

Version:

React DateInput is a perfect input component for handling quick and efficient date values. KendoReact Date Inputs package

368 lines (367 loc) 12.5 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 a from "react"; import e from "prop-types"; import { cloneDate as x, isEqual as Ve } from "@progress/kendo-date-math"; import { Button as J } from "@progress/kendo-react-buttons"; import { caretAltUpIcon as Ne, caretAltDownIcon as _e } from "@progress/kendo-svg-icons"; import { useInternationalization as Fe, useLocalization as He } from "@progress/kendo-react-intl"; import { useId as Be, useUnstyled as qe, usePropsContext as Y, classNames as y, uDateInput as b, createPropsContext as ze, getActiveElement as X } from "@progress/kendo-react-common"; import { FloatingLabel as Ue } from "@progress/kendo-react-labels"; import { DateInput as We } from "@progress/kendo-dateinputs-common"; import { DEFAULT_FORMAT as je, DEFAULT_FORMAT_PLACEHOLDER as Ke, isInRange as Je } from "./utils.mjs"; import { nullable as u, MAX_DATE as Ye, MIN_DATE as Xe, MIN_TIME as Ge, MAX_TIME as Ze } from "../utils.mjs"; import { increaseValue as C, messages as w, decreaseValue as M } from "../messages/index.mjs"; import { isInTimeRange as $e } from "../timepicker/utils.mjs"; import Qe from "../common/ClearButton.mjs"; import { DateInputIntl as et } from "./dateInputIntl.mjs"; const tt = "Please enter a valid value!", Z = a.forwardRef((t, $) => { var j; const Q = Be(t.id), ee = Fe(), h = He(), te = qe(), k = Y(G, t).unstyled || te, { format: T = r.format, size: ne = r.size, rounded: ae = r.rounded, fillMode: re = r.fillMode, formatPlaceholder: ie = r.formatPlaceholder, spinners: le = r.spinners, disabled: O = r.disabled, min: oe = r.min, max: ue = r.max, minTime: se = r.minTime, maxTime: ce = r.maxTime, validityStyles: de = r.validityStyles, validationMessage: p = r.validationMessage, placeholder: f = r.placeholder, enableMouseWheel: me = r.enableMouseWheel, autoCorrectParts: fe = r.autoCorrectParts, autoSwitchParts: ge = r.autoSwitchParts, allowCaretMode: ve = r.allowCaretMode, twoDigitYearMax: ye = r.twoDigitYearMax, ariaHasPopup: be = r.ariaHasPopup, autoFocus: he = r.autoFocus } = Y(G, t), d = () => D.current !== void 0 ? D.current : l.current && l.current.value, A = () => { const n = l.current && l.current.currentText || "", i = d(); return f != null && !Pe.focused && !i ? f : n; }, V = () => t.required !== void 0 ? t.required : !1, R = () => { const n = d() || t.value, i = oe, K = ue, Le = Je(n, i, K) && $e(n, se, ce), ke = p !== void 0, pe = (!V() || n != null) && Le, Ae = t.valid !== void 0 ? t.valid : pe; return { customError: ke, rangeOverflow: n && K.getTime() < n.getTime() || !1, rangeUnderflow: n && n.getTime() < i.getTime() || !1, valid: Ae, valueMissing: n === null }; }, Oe = () => { o.current && o.current.focus(); }, N = () => new et(ee), E = () => { const n = d(); return { format: T, steps: t.steps, formatPlaceholder: ie, placeholder: f, selectPreviousSegmentOnBackspace: !0, value: t.value || n, intlService: N(), autoFill: t.autoFill !== void 0 ? t.autoFill : !1, enableMouseWheel: me, autoCorrectParts: fe, autoSwitchParts: ge, autoSwitchKeys: t.autoSwitchKeys || [], twoDigitYearMax: ye, allowCaretMode: ve }; }, Ee = (n) => { s.current && s.current.classList.add("k-focus"), q({ focused: !0 }); }, Ie = (n) => { s.current && s.current.classList.remove("k-focus"), q({ focused: !1 }); }, De = (n, i) => typeof n != typeof i ? !0 : typeof n == "string" && typeof i == "string" ? n !== i : typeof n == "object" && typeof i == "object" ? JSON.stringify(n) !== JSON.stringify(i) : !1, xe = (n) => typeof n == "string" ? n : { inputFormat: n, displayFormat: n }, _ = (n) => { D.current = d(), Se(), m.current = n, D.current = void 0; }, F = (n) => { t.onChange && t.onChange(n); }, H = (n) => { X(document) === o.current && n.preventDefault(); }, Ce = () => new We(o.current, { ...E(), format: xe(E().format), events: { focus: Ee, blur: Ie, valueChange: _, click: F } }), B = () => { o.current && o.current.setCustomValidity && o.current.setCustomValidity( R().valid ? "" : p || r.validationMessage ); }, we = (n) => { !o.current || !l.current || _(n); }, Me = (n) => { n.preventDefault(); const i = X(document); o.current && i !== o.current && o.current.focus({ preventScroll: !0 }); }, c = (n) => { const i = d(); m.current && t.onChange && !Ve(m.current.oldValue, i) && t.onChange.call(void 0, { syntheticEvent: n, nativeEvent: m.current.event, value: m.current.value, target: I.current }), m.current = null; }, Te = (n) => { var i; (i = l.current) == null || i.modifyDateSegmentValue(1), c(n); }, Re = (n) => { var i; (i = l.current) == null || i.modifyDateSegmentValue(-1), c(n); }, I = a.useRef(null), o = a.useRef(null), s = a.useRef(null); a.useImperativeHandle( I, () => ({ props: t, get options() { return E(); }, get text() { return A(); }, get element() { return o.current; }, get name() { return t.name; }, get value() { return d(); }, get validity() { return R(); }, // hidden methods focus: Oe, updateOnPaste: we }) ), a.useImperativeHandle($, () => I.current); const l = a.useRef(null), P = a.useRef(null), S = a.useRef(!1), D = a.useRef(null), m = a.useRef(null), g = a.useRef(t), [Pe, q] = a.useState({ focused: !1 }), [, Se] = a.useReducer((n) => n + 1, 0); a.useLayoutEffect(() => { S.current || (l.current = Ce(), P.current = l.current.dateObject, S.current = !0); }, []), a.useEffect(() => (B(), S.current || s.current && s.current.addEventListener("wheel", H, { passive: !1 }), () => { s.current && s.current.removeEventListener("wheel", H); }), []), a.useEffect(() => { B(), l.current && ((De(g.current.format, T) || g.current.readonly !== t.readonly || JSON.stringify(g.current.steps) !== JSON.stringify(t.steps) || N().locale !== l.current.options.intlService.locale) && l.current.setOptions(E(), !0), g.current.value !== t.value && (P.current.getValue() !== null || t.value !== null) && P.current.setValue(t.value), t.ariaExpanded !== void 0 && t.ariaExpanded && (l.current.options.placeholder = null), t.ariaExpanded !== void 0 && !t.ariaExpanded && (l.current.options.placeholder = f), l.current.refreshElementValue(), g.current = { format: T, readonly: t.readonly, ariaExpanded: t.ariaExpanded, steps: t.steps, value: t.value }); }); const z = t.id || Q + "-accessibility-id", v = k && k.uDateInput, U = A(), L = !de || R().valid; a.useImperativeHandle(t._ref, () => I.current); const W = /* @__PURE__ */ a.createElement( "span", { ref: (n) => s.current = n, style: t.label ? void 0 : { width: t.width }, dir: t.dir, className: y( b.wrapper({ c: v, size: ne, fillMode: re, rounded: ae, disabled: O, required: V(), invalid: !L }), t.className ) }, /* @__PURE__ */ a.createElement( "input", { ref: (n) => o.current = n, role: t.ariaRole || "textbox", readOnly: t.readonly, tabIndex: t.tabIndex || 0, disabled: O, title: t.title !== void 0 ? t.title : U, type: "text", spellCheck: !1, autoComplete: "off", autoCorrect: "off", autoFocus: he, className: y(b.inputInner({ c: v })), id: z, value: U, "aria-label": t.ariaLabel, "aria-labelledby": t.ariaLabelledBy, "aria-describedby": t.ariaDescribedBy, "aria-haspopup": be, "aria-disabled": O, "aria-expanded": t.ariaExpanded, "aria-controls": t.ariaControls, "aria-required": t.required, "aria-invalid": !L, onKeyDown: c, onChange: c, onWheel: c, onInput: c, onClick: c, name: t.name, ...t.inputAttributes } ), t.children, t.clearButton && t.value && /* @__PURE__ */ a.createElement(Qe, { onClick: F, key: "clearbutton" }), le && /* @__PURE__ */ a.createElement("span", { className: y(b.inputSpinner({ c: v })), onMouseDown: Me }, /* @__PURE__ */ a.createElement( J, { tabIndex: -1, type: "button", rounded: null, className: y(b.spinnerIncrease({ c: v })), icon: "caret-alt-up", svgIcon: Ne, "aria-label": h.toLanguageString(C, w[C]), title: h.toLanguageString(C, w[C]), onClick: Te } ), /* @__PURE__ */ a.createElement( J, { tabIndex: -1, type: "button", rounded: null, className: y(b.spinnerDecrease({ c: v })), icon: "caret-alt-down", svgIcon: _e, "aria-label": h.toLanguageString(M, w[M]), title: h.toLanguageString(M, w[M]), onClick: Re } )) ); return t.label ? /* @__PURE__ */ a.createElement( Ue, { label: t.label, editorId: z, editorValue: (j = o.current) == null ? void 0 : j.value, editorValid: L, editorDisabled: O, children: W, style: { width: t.width } } ) : W; }); Z.propTypes = { value: e.instanceOf(Date), format: e.oneOfType([ u(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"]) }) ]), formatPlaceholder: e.oneOfType([ u( e.oneOf(["wide", "narrow", "short", "formatPattern"]) ), e.shape({ year: u(e.string), month: u(e.string), day: u(e.string), hour: u(e.string), minute: u(e.string), second: u(e.string) }) ]), width: e.oneOfType([e.string, e.number]), tabIndex: e.number, title: e.string, steps: e.shape({ year: u(e.number), month: u(e.number), day: u(e.number), hour: u(e.number), minute: u(e.number), second: u(e.number) }), min: e.instanceOf(Date), max: e.instanceOf(Date), disabled: e.bool, spinners: e.bool, name: e.string, dir: e.string, label: e.string, id: e.string, ariaLabelledBy: e.string, ariaDescribedBy: e.string, ariaLabel: e.string, ariaRole: e.string, ariaHasPopup: e.oneOfType([ e.bool, e.oneOf(["grid", "dialog"]) ]), ariaExpanded: e.oneOfType([e.bool]), onChange: e.func, 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"]), autoFocus: e.bool, inputAttributes: e.object }; const r = { format: je, size: "medium", rounded: "medium", fillMode: "solid", formatPlaceholder: Ke, spinners: !1, disabled: !1, max: x(Ye), min: x(Xe), minTime: x(Ge), maxTime: x(Ze), validityStyles: !0, validationMessage: tt, placeholder: null, enableMouseWheel: !0, autoCorrectParts: !0, autoSwitchParts: !0, allowCaretMode: !1, twoDigitYearMax: 68, ariaHasPopup: "grid", autoFocus: !1 }, G = ze(); Z.displayName = "KendoReactDateInput"; export { Z as DateInput, G as DateInputPropsContext, r as dateInputDefaultProps };