@vectara/vectara-ui
Version:
Vectara's design system, codified as a React and Sass component library
75 lines (74 loc) • 3.13 kB
JavaScript
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 }));
});