UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

153 lines (149 loc) 6.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _numberInput = require("../../constants/numberInput"); var _numberInput2 = require("../../utils/numberInput"); var _Input = _interopRequireDefault(require("../input/Input")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } const NumberInput = ({ isDecimalInput, isMoneyInput, isTimeInput, isInvalid, maxNumber = Infinity, value, shouldTriggerChangeOnFormat = true, placeholder, onBlur, isDisabled, onChange, shouldShowOnlyBottomBorder, minNumber = -Infinity }) => { // the plainText will be shown in the input, when it is in focus const [plainText, setPlainText] = (0, _react.useState)(''); // the formattedValue will be shown in the input, when it is not in focus const [formattedValue, setFormattedValue] = (0, _react.useState)(''); const [hasFocus, setHasFocus] = (0, _react.useState)(false); const [shouldRemainPlaceholder, setShouldRemainPlaceholder] = (0, _react.useState)(false); const [isValueInvalid, setIsValueInvalid] = (0, _react.useState)(false); const localPlaceholder = placeholder ?? (isMoneyInput ? '€' : undefined); const onLocalChange = event => { const newValue = event.target.value; const sanitizedValueString = newValue // Removes everything except numbers, commas and points .replace(_numberInput.NUMBER_CLEAR_REGEX, ''); if (isTimeInput && (sanitizedValueString.includes(':') && sanitizedValueString.length > 5 || !sanitizedValueString.includes(':') && sanitizedValueString.length > 4)) { return; } const valueToCheck = sanitizedValueString.replaceAll(',', '.'); if (!(0, _numberInput2.isValidString)({ string: valueToCheck, isMoneyInput, isDecimalInput, isTimeInput })) { return; } if (maxNumber && Number(valueToCheck) > maxNumber || minNumber && Number(valueToCheck) < minNumber) { return; } if (newValue.length === 1 && newValue.match(/^[0-9]+$/) === null) { setShouldRemainPlaceholder(true); } else { setShouldRemainPlaceholder(false); } setPlainText(sanitizedValueString.replaceAll('.', ',')); if (typeof onChange === 'function') { onChange(sanitizedValueString.replaceAll('.', ',')); } }; const onLocalBlur = () => { const sanitizedValue = plainText.length === 0 ? '0' : plainText; let newIsInvalid = false; let parsedNumber = null; if (!isTimeInput) { parsedNumber = (0, _numberInput2.parseFloatWithDecimals)({ stringValue: sanitizedValue.replace(',', '.').replaceAll(':', '').replace('€', ''), decimals: isMoneyInput ? 2 : undefined }); if (parsedNumber !== 0 && (parsedNumber > maxNumber || parsedNumber < minNumber)) { newIsInvalid = true; } setIsValueInvalid(newIsInvalid); } const newStringValue = plainText.length === 0 ? '' : (0, _numberInput2.formateNumber)({ number: isTimeInput ? sanitizedValue : parsedNumber, isMoneyInput, isTimeInput }); setFormattedValue(`${newStringValue} ${isMoneyInput ? '€' : ''}`); setPlainText(newStringValue.replaceAll('.', '')); setHasFocus(false); if (typeof onChange === 'function' && shouldTriggerChangeOnFormat) { onChange(newStringValue.replaceAll('.', '')); } if (typeof onBlur === 'function') { if (isTimeInput) { onBlur(newStringValue, newIsInvalid); } else { onBlur(parsedNumber === 0 ? null : parsedNumber, newIsInvalid); } } }; const onLocalFocus = () => { // formattedValue will be a number string with german number format (e.g. 1.000,00) // It will remove all dots, so that the user can type in the number setPlainText(formattedValue.replaceAll('.', '').replace('€', '').replaceAll(' ', '')); // This will update the external state if (typeof onChange === 'function' && shouldTriggerChangeOnFormat) { onChange(formattedValue.replaceAll('.', '').replace('€', '').replaceAll(' ', '')); } setIsValueInvalid(false); setHasFocus(true); }; // updates the formattedValue, when the value changes (0, _react.useEffect)(() => { let parsedNumber = null; if (!isTimeInput) { parsedNumber = (0, _numberInput2.parseFloatWithDecimals)({ stringValue: plainText.replace(',', '.').replaceAll(':', '').replace('€', '').replaceAll(' ', ''), decimals: isMoneyInput ? 2 : undefined }); // checks, if a given number is invalid, if the input is not in focus if (!hasFocus) { setIsValueInvalid(parsedNumber > maxNumber || parsedNumber < minNumber); } } setFormattedValue(plainText.length === 0 ? '' : `${(0, _numberInput2.formateNumber)({ number: isTimeInput ? plainText : parsedNumber, isMoneyInput, isTimeInput })}${isMoneyInput ? ' €' : ''}`); }, [hasFocus, isMoneyInput, isTimeInput, maxNumber, minNumber, plainText]); (0, _react.useEffect)(() => { if (typeof value === 'string') { setPlainText(value.replace('€', '').replaceAll(' ', '')); } }, [value]); return /*#__PURE__*/_react.default.createElement(_Input.default, { shouldRemainPlaceholder: shouldRemainPlaceholder, shouldShowOnlyBottomBorder: shouldShowOnlyBottomBorder, inputMode: "decimal", onChange: onLocalChange, value: hasFocus ? plainText : formattedValue, placeholder: localPlaceholder, onBlur: onLocalBlur, onFocus: onLocalFocus, isDisabled: isDisabled, isInvalid: typeof isInvalid === 'boolean' ? isInvalid : isValueInvalid, shouldShowCenteredContent: shouldShowOnlyBottomBorder }); }; NumberInput.displayName = 'NumberInput'; var _default = exports.default = NumberInput; //# sourceMappingURL=NumberInput.js.map