UNPKG

@progress/kendo-react-inputs

Version:

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

331 lines (330 loc) 10.6 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 p from "react"; import e from "prop-types"; import { MaskingService as O } from "./masking.service.mjs"; import { defaultRules as y, maskingChanged as V, returnFalse as b } from "./utils.mjs"; import { useCustomComponent as _, classNames as C, uMaskedTextBox as P, getTabIndex as k, createPropsContext as w, withIdHOC as I, withPropsContext as M, withUnstyledHOC as D } from "@progress/kendo-react-common"; import { FloatingLabel as H } from "@progress/kendo-react-labels"; const a = class a extends p.Component { constructor() { super(...arguments), this.state = {}, this._inputId = `k_${this.props.id}`, this._service = new O(), this._isPasted = !1, this._selection = [null, null], this._input = null, this.focus = () => { this._input && this._input.focus(); }, this.pasteHandler = (t) => { const { selectionStart: s, selectionEnd: i } = t.target; i !== s && (this._isPasted = !0, this._selection = [s || 0, i || 0]); }, this.onChangeHandler = (t) => { const s = t.currentTarget, i = s.value, l = this._selection[0] || 0, o = this._selection[1] || 0; if (!this.props.mask) { this._isPasted = !1, this._selection = [null, null], this.triggerOnChange(i, t); return; } const r = this.value; let n; if (this._isPasted) { this._isPasted = !1; const d = r.length - o, u = i.length - d; n = this._service.maskInRange(i.slice(l, u), r, l, o); } else n = this._service.maskInput(i, r, s.selectionStart || 0); this._selection = [n.selection, n.selection], this.triggerOnChange(n.value, t); }, this.focusHandler = (t) => { this.state.focused || (this.setState({ focused: !0 }), this.props.onFocus && this.props.onFocus.call(void 0, { target: this, syntheticEvent: t, nativeEvent: t.nativeEvent })); }, this.blurHandler = (t) => { this.state.focused && (this.setState({ focused: !1 }), this.props.onBlur && this.props.onBlur.call(void 0, { target: this, syntheticEvent: t, nativeEvent: t.nativeEvent })); }, this.setValidity = () => { this.element && this.element.setCustomValidity(this.validity.valid ? "" : this.props.validationMessage || ""); }; } /** * Gets the element of the MaskedTextBox. * * @return - An `HTMLInputElement`. * * @example * ```jsx * class App extends React.Component { * constructor(props) { * super(props); * } * element = null; * render() { * return ( * <div> * <MaskedTextBox * ref={(component) => * this.element = component ? component.element : null} * /> * <button onClick={() => console.log(this.element)}>console.log the element</button> * </div> * ); * } * } * * ReactDOM.render( * <App />, * document.getElementsByTagName('my-app')[0] * ); * ``` */ get element() { return this._input; } /** * Gets the value with the mask of the MaskedTextBox. */ get value() { return this._valueDuringOnChange !== void 0 ? this._valueDuringOnChange : this.props.value !== void 0 ? this.props.value : this.state.value !== void 0 ? this.state.value : this.props.defaultValue !== void 0 ? this.props.defaultValue : ""; } /** * Gets the raw value without the mask of the MaskedTextBox. */ get rawValue() { return this._service.rawValue(this.value); } /** * Represents the validity state into which the MaskedTextBox is set. */ get validity() { const t = this.value, s = this._service.validationValue(t), i = this.props.validationMessage !== void 0, l = this.props.valid !== void 0 ? this.props.valid : (!this.required || !!s) && (!this.props.maskValidation || !this.props.prompt || t.indexOf(this.props.prompt) === -1); return { customError: i, valid: l, valueMissing: !s }; } /** * @hidden */ get validityStyles() { return this.props.validityStyles !== void 0 ? this.props.validityStyles : a.defaultProps.validityStyles; } /** * @hidden */ get required() { return this.props.required !== void 0 ? this.props.required : !1; } /** * Gets the `name` property of the MaskedTextBox. */ get name() { return this.props.name; } /** * @hidden */ componentDidUpdate(t, s) { if (this.element && this.state.focused && s.focused) { let [i, l] = this._selection; const o = t.selection, r = this.props.selection; (!o && r || o && r && (o.start !== r.start || o.end !== r.end)) && (i = r.start, l = r.end), i !== null && l !== null && this.element.setSelectionRange(i, l); } V(t, this.props) && this.updateService(), this.setValidity(); } /** * @hidden */ componentDidMount() { this.updateService(), this.setValidity(); } /** * @hidden */ render() { const { size: t = a.defaultProps.size, fillMode: s = a.defaultProps.fillMode, rounded: i = a.defaultProps.rounded, autoFocus: l = a.defaultProps.autoFocus, prefix: o = a.defaultProps.prefix, suffix: r = a.defaultProps.suffix, inputAttributes: n, unstyled: d, className: u } = this.props, c = this.props.id || this._inputId, f = !this.validityStyles || this.validity.valid, v = this.props.style || {}, m = d && d.uMaskedTextBox, [x] = _(o), [S] = _(r), g = /* @__PURE__ */ p.createElement( "span", { dir: this.props.dir, className: C( P.wrapper({ c: m, invalid: !f, disabled: this.props.disabled, size: t, fillMode: s, rounded: i }), u ), style: this.props.label ? v : { width: this.props.width, ...v } }, /* @__PURE__ */ p.createElement(x, null), /* @__PURE__ */ p.createElement( "input", { type: "text", autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", autoFocus: l, spellCheck: !1, className: C(P.inputInner({ c: m })), value: this.value, id: c, "aria-labelledby": this.props.ariaLabelledBy, "aria-describedby": this.props.ariaDescribedBy, "aria-placeholder": this.props.mask, "aria-required": this.props.required, name: this.props.name, tabIndex: k(this.props.tabIndex, this.props.disabled, !0), accessKey: this.props.accessKey, title: this.props.title, disabled: this.props.disabled || void 0, readOnly: this.props.readonly || void 0, placeholder: this.props.placeholder, ref: (E) => this._input = E, onChange: this.onChangeHandler, onPaste: this.pasteHandler, onFocus: this.focusHandler, onBlur: this.blurHandler, onDragStart: b, onDrop: b, ...n } ), /* @__PURE__ */ p.createElement(S, null) ); return this.props.label ? /* @__PURE__ */ p.createElement( H, { label: this.props.label, editorId: c, editorValue: this.value, editorValid: f, editorDisabled: this.props.disabled, editorPlaceholder: this.props.placeholder, children: g, style: { width: this.props.width }, dir: this.props.dir } ) : g; } triggerOnChange(t, s) { if (this.setState({ value: t }), this.props.onChange) { this._valueDuringOnChange = t; const i = { syntheticEvent: s, nativeEvent: s.nativeEvent, selectionStart: this._selection[0], selectionEnd: this._selection[1], target: this, value: this.value }; this.props.onChange.call(void 0, i), this._valueDuringOnChange = void 0; } } updateService(t) { const s = Object.assign( { includeLiterals: this.props.includeLiterals, mask: this.props.mask, prompt: this.props.prompt, promptPlaceholder: this.props.promptPlaceholder, rules: this.rules }, t ); this._service.update(s); } get rules() { return Object.assign({}, y, this.props.rules); } }; a.displayName = "MaskedTextBox", a.propTypes = { value: e.string, defaultValue: e.string, placeholder: e.string, title: e.string, dir: e.string, id: e.string, style: e.object, className: e.string, prefix: e.any, suffix: e.any, ariaLabelledBy: e.string, ariaDescribedBy: e.string, width: e.oneOfType([e.string, e.number]), tabIndex: e.number, accessKey: e.string, disabled: e.bool, readonly: e.bool, prompt: e.string, promptPlaceholder: e.string, includeLiterals: e.bool, maskValidation: e.bool, mask: e.string, rules: function(t, s, i) { const l = t.rules; return l !== void 0 && !Object.entries(l).some((r) => typeof r != "string" || !(l[r] instanceof RegExp)) ? new Error( "Invalid prop `" + s + "` supplied to `" + i + "`. Validation failed." ) : null; }, selection: e.shape({ start: e.number.isRequired, end: e.number.isRequired }), name: e.string, label: e.string, validationMessage: e.string, required: e.bool, valid: e.bool, validityStyles: e.bool, onChange: e.func, 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 }, a.defaultProps = { prompt: "_", promptPlaceholder: " ", includeLiterals: !1, maskValidation: !0, rules: y, validityStyles: !0, prefix: (t) => null, suffix: (t) => null, size: "medium", rounded: "medium", fillMode: "solid", autoFocus: !1 }; let h = a; const q = w(), B = I( M( q, D(h) ) ); B.displayName = "KendoReactMaskedTextBox"; export { B as MaskedTextBox, q as MaskedTextBoxPropsContext, h as MaskedTextBoxWithoutContext };