UNPKG

@progress/kendo-react-inputs

Version:

React Inputs offer a customizable interface for users to enter and pick different information. KendoReact Input package

410 lines (409 loc) 12.9 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 t from "prop-types"; import { useInternationalization as Xe, useLocalization as Ze } from "@progress/kendo-react-intl"; import { createPropsContext as et, usePropsContext as tt, useId as nt, useCustomComponent as pe, dispatchEvent as Q, getActiveElement as be, useIsomorphicLayoutEffect as rt, classNames as at, kendoThemeMaps as ge, getTabIndex as lt } from "@progress/kendo-react-common"; import { caretAltUpIcon as st, caretAltDownIcon as ut } from "@progress/kendo-svg-icons"; import { FloatingLabel as ot } from "@progress/kendo-react-labels"; import { numericIncreaseValue as M, messages as T, numericDecreaseValue as z } from "../messages/index.mjs"; import { getInitialState as ve, formatValue as q, getStateOrPropsValue as X, rangeValue as A, sanitizeNumber as ye, decreaseValue as Ve, increaseValue as ke } from "./utils/index.mjs"; import { Button as Ce } from "@progress/kendo-react-buttons"; const it = "Please enter a valid value!", ct = et(), Ee = n.forwardRef( (C, Se) => { const G = tt( ct, C ), { className: xe, value: g, defaultValue: he, format: l, width: Z, tabIndex: Ie, accessKey: Oe, title: Le, placeholder: ee, min: c, max: d, dir: te, name: j, label: I, id: Pe, ariaDescribedBy: Ne, ariaLabelledBy: De, ariaLabel: Re, inputType: Fe, readOnly: f, validationMessage: _, children: Be, // Removed to support direct use in Form Field component touched: dt, visited: mt, modified: ft, style: ne, inputStyle: Me, valid: H, step: v = o.step, spinners: Te = o.spinners, disabled: u = o.disabled, required: O = o.required, validityStyles: re = o.validityStyles, prefix: ze = o.prefix, suffix: qe = o.suffix, onChange: E = o.onChange, onFocus: ae = o.onFocus, onBlur: le = o.onBlur, rangeOnEnter: se = o.rangeOnEnter, size: K = o.size, rounded: w = o.rounded, fillMode: L = o.fillMode, autoFocus: Ae = o.autoFocus, inputAttributes: Ge, ...ue } = G, je = nt(), oe = Pe || je, s = Xe(), P = Ze(), a = n.useRef(null), N = n.useRef(void 0), [_e, S] = n.useState(!1), i = n.useRef(ve()), D = n.useRef(!1), U = n.useRef(void 0), x = n.useRef(he), h = q( i.current.focused && !u ? i.current.currentLooseValue : X(g, x.current), l, s ); U.current = h; const [He] = pe(ze), [Ke] = pe(qe); n.useEffect(() => { a.current && a.current.setCustomValidity && a.current.setCustomValidity( B().valid ? "" : _ || it ); }); const ie = n.useCallback(() => { a.current && a.current.focus(); }, []), R = n.useCallback(() => N.current !== void 0 ? N.current : X(g, x.current), [g]), ce = n.useCallback(() => j, [j]), F = n.useCallback(() => O, [O]), B = n.useCallback(() => { const r = _ !== void 0, e = R(), V = H !== void 0 ? H : !i.current.valueIsOutOfRange && (!F() || e != null); return { customError: r, valid: V, valueMissing: e == null }; }, [_, H, R, F]), $ = n.useCallback(() => re, [re]), de = n.useCallback(() => G, [G]), y = n.useCallback(() => { const r = { element: a.current, focus: ie }; return Object.defineProperty(r, "name", { get: ce }), Object.defineProperty(r, "value", { get: R }), Object.defineProperty(r, "validity", { get: B }), Object.defineProperty(r, "validityStyles", { get: $ }), Object.defineProperty(r, "required", { get: F }), Object.defineProperty(r, "props", { get: de }), r; }, [ce, R, B, $, F, ie, de]); n.useImperativeHandle(Se, y); const p = n.useCallback(() => ({ eventValue: X(g, x.current), prevLooseValue: U.current, currentLooseValue: a.current.value, selectionStart: a.current.selectionStart, selectionEnd: a.current.selectionEnd, decimalSelect: !1, valueIsCorrected: !1, valueIsOutOfRange: !1, isPaste: D.current, focused: i.current.focused }), [g]), b = n.useCallback( (r, e) => { if (u) return; N.current = e.eventValue, x.current = e.eventValue; const V = q(A(e.eventValue, c, d), l, s), m = A(s.parseNumber(V, l), c, d); m !== e.eventValue && (e.valueIsOutOfRange = !0, e.eventValue = m, x.current = m), g !== e.eventValue && Q(E, r, y(), { value: e.eventValue }), N.current = void 0, i.current = e, S((J) => !J); }, [g, E, u, S, y] ), we = n.useCallback( (r) => { const e = p(); D.current = !1, b(r, ye(e, l, s)); }, [l, E, s, b, p] ), Ue = n.useCallback( (r) => { if (f || u) return; let e = p(); const V = s.parseNumber(String(e.currentLooseValue), l); if (e.selectionEnd > e.selectionStart && e.selectionEnd - e.selectionStart === String(e.currentLooseValue).length) { const m = s.numberSymbols(), k = m && r.key === m.minusSign, J = m && r.key === m.decimal; D.current = !k && !J; return; } switch (r.keyCode) { case 38: ke(V, e, v, c, d, l, s); break; case 40: Ve(V, e, v, c, d, l, s); break; case 13: { if (se === !1) return; const m = q(A(V, c, d), l, s), k = A(s.parseNumber(m, l), c, d); e.eventValue = k, e.currentLooseValue = q(k, l, s), e.selectionStart = e.selectionEnd = e.currentLooseValue.length; break; } case 110: { const m = a.current, k = s.numberSymbols(); m && (e.currentLooseValue = e.currentLooseValue.slice(0, e.selectionStart) + k.decimal + e.currentLooseValue.slice(e.selectionEnd), e.selectionStart = e.selectionEnd = e.selectionStart + 1, e = ye(e, l, s)); break; } default: return; } r.preventDefault(), b(r, e); }, [l, c, d, v, E, se, b, p] ), $e = n.useCallback(() => { D.current = !0; }, []), W = n.useCallback( (r) => { if (f || u) return; const e = p(); ke( s.parseNumber(String(e.currentLooseValue), l), e, v, c, d, l, s ), b(r, e); }, [l, c, d, v, E, f, u, b, p] ), Y = n.useCallback( (r) => { if (f || u) return; const e = p(); Ve( s.parseNumber(String(e.currentLooseValue), l), e, v, c, d, l, s ), b(r, e); }, [l, c, d, v, E, f, u, b, p] ), We = n.useCallback( (r) => { const e = be(document); !document || e !== a.current || !a.current || f || u || (r.nativeEvent.deltaY < 0 && W(r), r.nativeEvent.deltaY > 0 && Y(r)); }, [W, Y, u, f] ), Ye = n.useCallback( (r) => { i.current.currentLooseValue = U.current, i.current.focused = !0, Q(ae, r, y(), {}), S((e) => !e); }, [ae, S, y] ), Je = n.useCallback( (r) => { i.current = ve(), Q(le, r, y(), {}), S((e) => !e); }, [le, S, y] ), Qe = n.useCallback((r) => { if (document && a.current) { const e = be(document); r.preventDefault(), e !== a.current && a.current.focus(); } }, []); rt(() => { a.current && a.current.type !== "number" && i.current.selectionStart !== void 0 && i.current.selectionEnd !== void 0 && (a.current.selectionStart = i.current.selectionStart, a.current.selectionEnd = i.current.selectionEnd, i.current.selectionStart = void 0, i.current.selectionEnd = void 0); }, [_e]); const me = !$() || B().valid, fe = /* @__PURE__ */ n.createElement( "span", { dir: te, style: I ? ne : { width: Z, ...ne }, className: at( "k-input", "k-numerictextbox", { [`k-input-${ge.sizeMap[K] || K}`]: K, [`k-input-${L}`]: L, [`k-rounded-${ge.roundedMap[w] || w}`]: w, "k-invalid": !me, "k-required": O, "k-disabled": u }, xe ), "aria-disabled": u ? "true" : void 0, ...I ? {} : ue }, /* @__PURE__ */ n.createElement(He, null), /* @__PURE__ */ n.createElement( "input", { role: "spinbutton", value: h === null ? "" : h, tabIndex: lt(Ie, u), accessKey: Oe, disabled: u, title: Le, "aria-disabled": u ? "true" : void 0, "aria-valuemin": c, "aria-valuemax": d, "aria-label": Re, "aria-labelledby": De, "aria-describedby": Ne, "aria-required": O, placeholder: ee, spellCheck: !1, autoComplete: "off", autoCorrect: "off", autoFocus: Ae, type: Fe || "tel", className: "k-input-inner", id: oe, name: j, readOnly: f, style: Me, onChange: we, onFocus: Ye, onBlur: Je, onKeyDown: Ue, onPaste: $e, onWheel: We, ref: a, ...Ge } ), /* @__PURE__ */ n.createElement(Ke, null), Be, Te && /* @__PURE__ */ n.createElement("span", { className: "k-input-spinner k-spin-button", onMouseDown: Qe }, /* @__PURE__ */ n.createElement( Ce, { tabIndex: -1, type: "button", icon: "caret-alt-up", svgIcon: st, rounded: null, fillMode: L, className: "k-spinner-increase", "aria-label": P.toLanguageString( M, T[M] ), title: P.toLanguageString( M, T[M] ), onClick: W } ), /* @__PURE__ */ n.createElement( Ce, { tabIndex: -1, type: "button", icon: "caret-alt-down", svgIcon: ut, rounded: null, fillMode: L, className: "k-spinner-decrease", "aria-label": P.toLanguageString( z, T[z] ), title: P.toLanguageString( z, T[z] ), onClick: Y } )) ); return I ? /* @__PURE__ */ n.createElement( ot, { label: I, editorId: oe, editorValue: h === null ? "" : h, editorValid: me, editorDisabled: u, editorPlaceholder: ee, children: fe, style: { width: Z }, dir: te, ...ue } ) : fe; } ); Ee.propTypes = { value: t.number, defaultValue: t.number, step: t.number, format: t.oneOfType([ t.string, t.shape({ style: t.oneOf(["decimal", "currency", "percent", "scientific", "accounting"]), currency: t.string, currencyDisplay: t.oneOf(["symbol", "code", "name"]), useGrouping: t.bool, minimumIntegerDigits: t.number, minimumFractionDigits: t.number, maximumFractionDigits: t.number }) ]), width: t.oneOfType([t.string, t.number]), tabIndex: t.number, accessKey: t.string, title: t.string, placeholder: t.string, min: t.number, max: t.number, spinners: t.bool, disabled: t.bool, readOnly: t.bool, dir: t.string, name: t.string, label: t.string, validationMessage: t.string, required: t.bool, id: t.string, rangeOnEnter: t.bool, ariaLabelledBy: t.string, ariaDescribedBy: t.string, ariaLabel: t.string, onChange: t.func, onFocus: t.func, onBlur: t.func, size: t.oneOf([null, "small", "medium", "large"]), rounded: t.oneOf([null, "small", "medium", "large", "full"]), fillMode: t.oneOf([null, "solid", "flat", "outline"]), inputAttributes: t.object }; const o = { prefix: (C) => null, suffix: (C) => null, step: 1, spinners: !0, disabled: !1, required: !1, validityStyles: !0, rangeOnEnter: !0, autoFocus: !1, onChange: (C) => { }, onFocus: (C) => { }, onBlur: (C) => { }, size: "medium", rounded: "medium", fillMode: "solid" }; Ee.displayName = "KendoNumericTextBox"; export { Ee as NumericTextBox, ct as NumericTextBoxPropsContext };