UNPKG

@vectara/vectara-ui

Version:

Vectara's design system, codified as a React and Sass component library

75 lines (74 loc) 3.13 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { jsx as _jsx } from "react/jsx-runtime"; import { forwardRef, useEffect, useRef, useState } from "react"; import { VuiBasicInput } from "./BasicInput"; export const VuiNumberInput = forwardRef((_a, ref) => { var { value, onChange, max, min, step, allowUndefined } = _a, rest = __rest(_a, ["value", "onChange", "max", "min", "step", "allowUndefined"]); // localValue (rather than binding to `value` directly) sidesteps a // Firefox quirk: `<input type="number">` reports "" mid-decimal when the // the user types "1,0", which would round-trip through the parent and // erase the user's input. const [localValue, setLocalValue] = useState(value); // Last value exchanged with the parent. The resync effect ignores echoes // of our own emits — without it, a stale prop ("6" arriving after the // user has already typed "65") would clobber the in-flight edit. const lastSyncedRef = useRef(value); useEffect(() => { if (value !== lastSyncedRef.current) { lastSyncedRef.current = value; setLocalValue(value); } }, [value]); const emit = (next) => { const outgoing = allowUndefined ? next : next !== null && next !== void 0 ? next : 0; lastSyncedRef.current = outgoing; onChange(outgoing); }; const onChangeValue = (e) => { if (e.target.value === "") { setLocalValue(undefined); emit(undefined); return; } const numberValue = Number(e.target.value); if (isNaN(numberValue)) { setLocalValue(undefined); emit(undefined); return; } setLocalValue(numberValue); emit(numberValue); }; const onBlur = () => { // Clamp against the effective emitted value so empty + !allowUndefined // (which emits 0) still clamps to min. const current = allowUndefined ? localValue : localValue !== null && localValue !== void 0 ? localValue : 0; if (current === undefined) return; if (min !== undefined && current < min) { // Clamp min. setLocalValue(min); emit(min); } else if (max !== undefined && current > max) { // Clamp max. setLocalValue(max); emit(max); } }; const props = Object.assign({ type: "number", value: localValue !== null && localValue !== void 0 ? localValue : "", onChange: onChangeValue, onBlur, max, min, step }, rest); return _jsx(VuiBasicInput, Object.assign({}, props, { ref: ref })); });