Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-number-format

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-number-format - npm Package Compare versions

Comparing version 4.9.3 to 5.0.0-beta.1

example/src/index.js

2347

dist/react-number-format.cjs.js
/**
* react-number-format - 4.9.3
* react-number-format - 5.0.0-beta.1
* Author : Sudhanshu Yadav

@@ -10,85 +10,118 @@ * Copyright (c) 2016, 2022 to Sudhanshu Yadav, released under the MIT license.

Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = _interopDefault(require('react'));
var React = require('react');
var React__default = _interopDefault(React);
//
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
// basic noop function
function noop() {}
function returnTrue() {
return true;
}
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function charIsNumber(char ) {
return !!(char || '').match(/\d/);
function __rest(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;
}
function isNil(val ) {
return val === null || val === undefined;
}
var SourceType;
(function (SourceType) {
SourceType["event"] = "event";
SourceType["props"] = "prop";
})(SourceType || (SourceType = {}));
function escapeRegExp(str ) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
// basic noop function
function noop() { }
function charIsNumber(char) {
return !!(char || '').match(/\d/);
}
function getThousandsGroupRegex(thousandsGroupStyle ) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
function isNil(val) {
return val === null || val === undefined;
}
function isNanValue(val) {
return typeof val === 'number' && isNaN(val);
}
function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function getThousandsGroupRegex(thousandsGroupStyle) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
}
function applyThousandSeparator(str, thousandSeparator, thousandsGroupStyle) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator));
}
function usePersistentCallback(cb) {
var callbackRef = React.useRef(cb);
// keep the callback ref upto date
callbackRef.current = cb;
/**
* initialize a persistent callback which never changes
* through out the component lifecycle
*/
var persistentCbRef = React.useRef(function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
function applyThousandSeparator(
str ,
thousandSeparator ,
thousandsGroupStyle
) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (
str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator)
);
return callbackRef.current.apply(callbackRef, args);
});
return persistentCbRef.current;
}
//spilt a float number into different parts beforeDecimal, afterDecimal, and negation
function splitDecimal(numStr , allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
function splitDecimal(numStr, allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
var hasNagation = numStr[0] === '-';
var addNegation = hasNagation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNagation: hasNagation,
addNegation: addNegation,
};
var hasNegation = numStr[0] === '-';
var addNegation = hasNegation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNegation: hasNegation,
addNegation: addNegation,
};
}
function fixLeadingZero(numStr ) {
if (!numStr) { return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative) { numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
function fixLeadingZero(numStr) {
if (!numStr)
{ return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative)
{ numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
}
/**

@@ -98,59 +131,51 @@ * limit decimal numbers to given scale

*/
function limitToScale(numStr , scale , fixedDecimalScale ) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
function limitToScale(numStr, scale, fixedDecimalScale) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
}
function repeat(str, count) {
return Array(count + 1).join(str);
return Array(count + 1).join(str);
}
function toNumericString(num) {
num += ''; // typecast number to string
// store the sign and remove it from the number.
var sign = num[0] === '-' ? '-' : '';
if (sign) { num = num.substring(1); }
// split the number into cofficient and exponent
var ref = num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent) { return sign + coefficient; }
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
} else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
} else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
var _num = num + ''; // typecast number to string
// store the sign and remove it from the number.
var sign = _num[0] === '-' ? '-' : '';
if (sign)
{ _num = _num.substring(1); }
// split the number into cofficient and exponent
var ref = _num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent)
{ return sign + coefficient; }
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
}
else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
}
else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
}
/**

@@ -160,1232 +185,1000 @@ * This method is required to round prop value to given scale.

*/
function roundToPrecision(numStr , scale , fixedDecimalScale ) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1) { return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNagation = ref.hasNagation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr =
afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (
(Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length)
);
}
return current + roundedStr;
function roundToPrecision(numStr, scale, fixedDecimalScale) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1)
{ return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNegation = ref.hasNegation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr = afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return ((Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length));
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = limitToScale(
roundedDecimalParts[1] || '',
Math.min(scale, afterDecimal.length),
fixedDecimalScale
);
var negation = hasNagation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
var decimalPart = limitToScale(roundedDecimalParts[1] || '', scale, fixedDecimalScale);
var negation = hasNegation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
}
/** set the caret positon in an input field **/
function setCaretPosition(el , caretPos ) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
function setCaretPosition(el, caretPos) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
/* @ts-ignore */
if (el.createTextRange) {
/* @ts-ignore */
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
function findChangeRange(prevValue, newValue) {
var i = 0, j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength)
{ i++; }
//check what has been changed from last
while (prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i) {
j++;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
return {
from: { start: i, end: prevLength - j },
to: { start: i, end: newLength - j },
};
}
/**
Given previous value and newValue it returns the index
start - end to which values have changed.
This function makes assumption about only consecutive
characters are changed which is correct assumption for caret input.
*/
function findChangedIndex(prevValue , newValue ) {
var i = 0,
j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength) { i++; }
//check what has been changed from last
while (
prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i
) {
j++;
}
return { start: i, end: prevLength - j };
}
/*
Returns a number whose value is limited to the given range
*/
function clamp(num , min , max ) {
return Math.min(Math.max(num, min), max);
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function getCurrentCaretPosition(el ) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
function geInputCaretPosition(el) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
}
function addInputMode(format ) {
return (
format ||
(typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)))
);
function addInputMode() {
return (typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)));
}
//
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
var defaultProps = {
displayType: 'input',
decimalSeparator: '.',
thousandsGroupStyle: 'thousand',
fixedDecimalScale: false,
prefix: '',
suffix: '',
allowNegative: true,
allowEmptyFormatting: false,
allowLeadingZeros: false,
isNumericString: false,
type: 'text',
onValueChange: noop,
onChange: noop,
onKeyDown: noop,
onMouseUp: noop,
onFocus: noop,
onBlur: noop,
isAllowed: returnTrue,
};
var NumberFormat = /*@__PURE__*/(function (superclass) {
function NumberFormat(props ) {
superclass.call(this, props);
var defaultValue = props.defaultValue;
//validate props
this.validateProps();
var formattedValue = this.formatValueProp(defaultValue);
this.state = {
value: formattedValue,
numAsString: this.removeFormatting(formattedValue),
mounted: false,
};
this.selectionBeforeInput = {
selectionStart: 0,
selectionEnd: 0,
};
this.onChange = this.onChange.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
if ( superclass ) NumberFormat.__proto__ = superclass;
NumberFormat.prototype = Object.create( superclass && superclass.prototype );
NumberFormat.prototype.constructor = NumberFormat;
NumberFormat.prototype.componentDidMount = function componentDidMount () {
// set mounted state
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
mounted: true,
});
};
NumberFormat.prototype.componentDidUpdate = function componentDidUpdate (prevProps ) {
this.updateValueIfRequired(prevProps);
};
NumberFormat.prototype.componentWillUnmount = function componentWillUnmount () {
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
};
NumberFormat.prototype.updateValueIfRequired = function updateValueIfRequired (prevProps ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var focusedElm = ref.focusedElm;
var stateValue = state.value;
var lastNumStr = state.numAsString; if ( lastNumStr === void 0 ) lastNumStr = '';
// If only state changed no need to do any thing
if (prevProps !== props) {
//validate props
this.validateProps();
var lastValueWithNewFormat = this.formatNumString(lastNumStr);
var formattedValue = isNil(props.value) ? lastValueWithNewFormat : this.formatValueProp();
var numAsString = this.removeFormatting(formattedValue);
var floatValue = parseFloat(numAsString);
var lastFloatValue = parseFloat(lastNumStr);
if (
//while typing set state only when float value changes
((!isNaN(floatValue) || !isNaN(lastFloatValue)) && floatValue !== lastFloatValue) ||
//can also set state when float value is same and the format props changes
lastValueWithNewFormat !== stateValue ||
//set state always when not in focus and formatted value is changed
(focusedElm === null && formattedValue !== stateValue)
) {
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: focusedElm,
source: 'prop',
event: null,
});
}
}
};
/** Misc methods **/
NumberFormat.prototype.getFloatString = function getFloatString (num) {
if ( num === void 0 ) num = '';
var ref = this.props;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var numRegex = this.getNumberRegex(true);
//remove negation for regex check
var hasNegation = num[0] === '-';
if (hasNegation) { num = num.replace('-', ''); }
//if decimal scale is zero remove decimal and number after decimalSeparator
if (decimalSeparator && decimalScale === 0) {
num = num.split(decimalSeparator)[0];
}
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.');
//remove extra decimals
var firstDecimalIndex = num.indexOf('.');
if (firstDecimalIndex !== -1) {
num = (num.substring(0, firstDecimalIndex)) + "." + (num
.substring(firstDecimalIndex + 1, num.length)
.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), ''));
}
//add negation back
if (hasNegation) { num = '-' + num; }
return num;
};
//returned regex assumes decimalSeparator is as per prop
NumberFormat.prototype.getNumberRegex = function getNumberRegex (g , ignoreDecimalSeparator ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var customNumerals = ref.customNumerals;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
return new RegExp(
'[0-9' +
(customNumerals ? customNumerals.join('') : '') +
']' +
(decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format
? '|' + escapeRegExp(decimalSeparator)
: ''),
g ? 'g' : undefined
);
};
NumberFormat.prototype.getSeparators = function getSeparators () {
var ref = this.props;
var decimalSeparator = ref.decimalSeparator;
var ref$1 = this.props;
var thousandSeparator = ref$1.thousandSeparator;
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
function getDefaultChangeMeta(value) {
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
from: {
start: 0,
end: 0,
},
to: {
start: 0,
end: value.length,
},
lastValue: '',
};
};
}
function getMaskAtIndex(mask, index) {
if ( mask === void 0 ) mask = ' ';
NumberFormat.prototype.getMaskAtIndex = function getMaskAtIndex (index ) {
var ref = this.props;
var mask = ref.mask; if ( mask === void 0 ) mask = ' ';
if (typeof mask === 'string') {
return mask;
return mask;
}
return mask[index] || ' ';
};
NumberFormat.prototype.getValueObject = function getValueObject (formattedValue , numAsString ) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
NumberFormat.prototype.validateProps = function validateProps () {
var ref = this.props;
var mask = ref.mask;
//validate decimalSeparator and thousandSeparator
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var thousandSeparator = ref$1.thousandSeparator;
if (decimalSeparator === thousandSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
function getCaretPosition(formattedValue, curValue, curCaretPos) {
var curValLn = curValue.length;
var formattedValueLn = formattedValue.length;
// create index map
var addedIndexMap = {};
var indexMap = new Array(curValLn);
for (var i = 0; i < curValLn; i++) {
indexMap[i] = -1;
for (var j = 0, jLn = formattedValueLn; j < jLn; j++) {
if (curValue[i] === formattedValue[j] && addedIndexMap[j] !== true) {
indexMap[i] = j;
addedIndexMap[j] = true;
break;
}
}
}
//validate mask
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("\n Mask " + mask + " should not contain numeric character;\n "));
}
/**
* For current caret position find closest characters (left and right side)
* which are properly mapped to formatted value.
* The idea is that the new caret position will exist always in the boundary of
* that mapped index
*/
var pos = curCaretPos;
while (pos < curValLn && (indexMap[pos] === -1 || !charIsNumber(curValue[pos]))) {
pos++;
}
};
/** Misc methods end **/
/** caret specific methods **/
NumberFormat.prototype.setPatchedCaretPosition = function setPatchedCaretPosition (el , caretPos , currentValue ) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
this.caretPositionTimeout = setTimeout(function () {
if (el.value === currentValue) { setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
NumberFormat.prototype.correctCaretPosition = function correctCaretPosition (value , caretPos , direction ) {
var ref = this.props;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
//if value is empty return 0
if (value === '') { return 0; }
//caret position should be between 0 and value length
caretPos = clamp(caretPos, 0, value.length);
//in case of format as number limit between prefix and suffix
if (!format) {
var hasNegation = value[0] === '-';
return clamp(caretPos, prefix.length + (hasNegation ? 1 : 0), value.length - suffix.length);
// if the caret position is on last keep the endIndex as last for formatted value
var endIndex = pos === curValLn || indexMap[pos] === -1 ? formattedValueLn : indexMap[pos];
pos = curCaretPos - 1;
while (pos > 0 && (indexMap[pos] === -1 || !charIsNumber(curValue[pos])))
{ pos--; }
var startIndex = pos === -1 || indexMap[pos] === -1 ? 0 : indexMap[pos] + 1;
/**
* case where a char is added on suffix and removed from middle, example 2sq345 becoming $2,345 sq
* there is still a mapping but the order of start index and end index is changed
*/
if (startIndex > endIndex)
{ return endIndex; }
/**
* given the current caret position if it closer to startIndex
* keep the new caret position on start index or keep it closer to endIndex
*/
return curCaretPos - startIndex < endIndex - curCaretPos ? startIndex : endIndex;
}
function caretUnknownFormatBoundary(formattedValue) {
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
boundaryAry[i] = Boolean(charIsNumber(formattedValue[i]) || charIsNumber(formattedValue[i - 1]));
}
return boundaryAry;
}
function useInternalValues(value, defaultValue, isNumericString, format, removeFormatting, onValueChange) {
if ( onValueChange === void 0 ) onValueChange = noop;
//in case if custom format method don't do anything
if (typeof format === 'function') { return caretPos; }
var propValues = React.useRef();
var getValues = usePersistentCallback(function (value) {
var formattedValue, numAsString;
if (isNil(value) || isNanValue(value)) {
numAsString = '';
formattedValue = '';
}
else if (typeof value === 'number' || isNumericString) {
numAsString = typeof value === 'number' ? toNumericString(value) : value;
formattedValue = format(numAsString);
}
else {
numAsString = removeFormatting(value, undefined);
formattedValue = value;
}
return { formattedValue: formattedValue, numAsString: numAsString };
});
var ref = React.useState(function () {
return getValues(defaultValue);
});
var values = ref[0];
var setValues = ref[1];
var _onValueChange = function (values, sourceInfo) {
setValues({
formattedValue: values.formattedValue,
numAsString: values.value,
});
onValueChange(values, sourceInfo);
};
React.useMemo(function () {
//if element is moved to uncontrolled mode, don't reset the value
if (!isNil(value)) {
propValues.current = getValues(value);
setValues(propValues.current);
}
else {
propValues.current = undefined;
}
}, [value, getValues]);
return [values, _onValueChange];
}
/* in case format is string find the closest # position from the caret position */
//in case the caretPos have input value on it don't do anything
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) {
return caretPos;
function defaultRemoveFormatting(value) {
return value.replace(/[^0-9]/g, '');
}
function defaultFormat(value) {
return value;
}
function NumberFormatBase(props) {
var type = props.type; if ( type === void 0 ) type = 'text';
var displayType = props.displayType; if ( displayType === void 0 ) displayType = 'input';
var customInput = props.customInput;
var renderText = props.renderText;
var getInputRef = props.getInputRef;
var format = props.format; if ( format === void 0 ) format = defaultFormat;
var removeFormatting = props.removeFormatting; if ( removeFormatting === void 0 ) removeFormatting = defaultRemoveFormatting;
var defaultValue = props.defaultValue;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var isAllowed = props.isAllowed;
var onChange = props.onChange; if ( onChange === void 0 ) onChange = noop;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onMouseUp = props.onMouseUp; if ( onMouseUp === void 0 ) onMouseUp = noop;
var onFocus = props.onFocus; if ( onFocus === void 0 ) onFocus = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var propValue = props.value;
var getCaretBoundary = props.getCaretBoundary; if ( getCaretBoundary === void 0 ) getCaretBoundary = caretUnknownFormatBoundary;
var otherProps = __rest(props, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "removeFormatting", "defaultValue", "isNumericString", "onValueChange", "isAllowed", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value", "getCaretBoundary"]);
var ref = useInternalValues(propValue, defaultValue, isNumericString, format, removeFormatting, onValueChange);
var ref_0 = ref[0];
var formattedValue = ref_0.formattedValue;
var numAsString = ref_0.numAsString;
var onFormattedValueChange = ref[1];
var lastUpdatedValue = React.useRef();
var _onValueChange = function (values, source) {
lastUpdatedValue.current = values.formattedValue;
onFormattedValueChange(values, source);
};
// check if there is any change in the value due to props change
React.useEffect(function () {
var newFormattedValue = format(numAsString);
// if the formatted value is not synced to parent, or if the formatted value is different
if (lastUpdatedValue.current === undefined || newFormattedValue !== lastUpdatedValue.current) {
var input = focusedElm.current;
updateValue({
formattedValue: newFormattedValue,
numAsString: numAsString,
input: input,
setCaretPosition: true,
source: SourceType.props,
event: null,
});
}
});
var ref$1 = React.useState(false);
var mounted = ref$1[0];
var setMounted = ref$1[1];
var focusedElm = React.useRef(null);
var timeout = React.useRef({
setCaretTimeout: null,
focusTimeout: null,
});
React.useEffect(function () {
setMounted(true);
return function () {
clearTimeout(timeout.current.setCaretTimeout);
clearTimeout(timeout.current.focusTimeout);
};
}, []);
var _format = format;
var getValueObject = function (formattedValue, numAsString) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
var setPatchedCaretPosition = function (el, caretPos, currentValue) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
timeout.current.setCaretTimeout = setTimeout(function () {
if (el.value === currentValue)
{ setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
var correctCaretPosition = function (value, caretPos, direction) {
var valLn = value.length;
// clamp caret position to [0, value.length]
caretPos = clamp(caretPos, 0, valLn);
var boundary = getCaretBoundary(value);
if (direction === 'left') {
while (caretPos >= 0 && !boundary[caretPos])
{ caretPos--; }
// if we don't find any suitable caret position on left, set it on first allowed position
if (caretPos === -1)
{ caretPos = boundary.indexOf(true); }
}
else {
while (caretPos <= valLn && !boundary[caretPos])
{ caretPos++; }
// if we don't find any suitable caret position on right, set it on last allowed position
if (caretPos > valLn)
{ caretPos = boundary.lastIndexOf(true); }
}
// if we still don't find caret position, set it at the end of value
if (caretPos === -1)
{ caretPos = valLn; }
return caretPos;
};
var getNewCaretPosition = function (inputValue, formattedValue, caretPos) {
var updatedCaretPos = getCaretPosition(formattedValue, inputValue, caretPos);
//correct caret position if its outside of editable area
updatedCaretPos = correctCaretPosition(formattedValue, updatedCaretPos);
return updatedCaretPos;
};
var updateValue = function (params) {
var newFormattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = geInputCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = newFormattedValue;
//get the caret position
caretPos = getNewCaretPosition(inputValue, newFormattedValue, currentCaretPosition);
}
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
*/
input.value = newFormattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
setPatchedCaretPosition(input, caretPos, newFormattedValue);
}
}
if (newFormattedValue !== formattedValue) {
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
_onValueChange(getValueObject(newFormattedValue, numAsString), { event: event, source: source });
}
};
var formatInputValue = function (inputValue, event, source) {
var changeRange = findChangeRange(formattedValue, inputValue);
var changeMeta = Object.assign(Object.assign({}, changeRange), { lastValue: formattedValue });
var _numAsString = removeFormatting(inputValue, changeMeta);
var _formattedValue = _format(_numAsString);
if (isAllowed && !isAllowed(getValueObject(_formattedValue, _numAsString))) {
return false;
}
updateValue({
formattedValue: _formattedValue,
numAsString: _numAsString,
inputValue: inputValue,
event: event,
source: source,
setCaretPosition: true,
input: event.target,
});
};
var _onChange = function (e) {
var el = e.target;
var inputValue = el.value;
var changed = formatInputValue(inputValue, e, SourceType.event);
if (changed)
{ onChange(e); }
};
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = Math.max(selectionStart - 1, 0);
}
else if (key === 'ArrowRight') {
expectedCaretPosition = Math.min(selectionStart + 1, value.length);
}
else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
// also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, direction);
}
else if (key === 'Delete' && !charIsNumber(value[expectedCaretPosition])) {
// in case of delete go to closest caret boundary on the right side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'right');
}
else if (key === 'Backspace' && !charIsNumber(value[expectedCaretPosition])) {
// in case of backspace go to closest caret boundary on the left side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'left');
}
if (newCaretPosition !== expectedCaretPosition) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
/* @ts-ignore */
if (e.isUnitTestRun) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
var _onMouseUp = function (e) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
setPatchedCaretPosition(el, caretPosition, value);
}
}
onMouseUp(e);
};
var _onFocus = function (e) {
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
var el = e.target;
focusedElm.current = el;
timeout.current.focusTimeout = setTimeout(function () {
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)) {
setPatchedCaretPosition(el, caretPosition, value);
}
onFocus(e);
}, 0);
};
var _onBlur = function (e) {
focusedElm.current = null;
clearTimeout(timeout.current.focusTimeout);
clearTimeout(timeout.current.setCaretTimeout);
onBlur(e);
};
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode() ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: formattedValue,
onChange: _onChange,
onKeyDown: _onKeyDown,
onMouseUp: _onMouseUp,
onFocus: _onFocus,
onBlur: _onBlur,
});
if (displayType === 'text') {
return renderText ? (React__default.createElement(React__default.Fragment, null, renderText(formattedValue, otherProps) || null)) : (React__default.createElement("span", Object.assign({}, otherProps, { ref: getInputRef }), formattedValue));
}
//if caretPos is just after input value don't do anything
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) {
return caretPos;
else if (customInput) {
var CustomInput = customInput;
/* @ts-ignore */
return React__default.createElement(CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
}
return React__default.createElement("input", Object.assign({}, inputProps, { ref: getInputRef }));
}
//find the nearest caret position
var firstHashPosition = format.indexOf('#');
var lastHashPosition = format.lastIndexOf('#');
//limit the cursor between the first # position and the last # position
caretPos = clamp(caretPos, firstHashPosition, lastHashPosition + 1);
var nextPos = format.substring(caretPos, format.length).indexOf('#');
var caretLeftBound = caretPos;
var caretRightBound = caretPos + (nextPos === -1 ? 0 : nextPos);
//get the position where the last number is present
while (
caretLeftBound > firstHashPosition &&
(format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))
) {
caretLeftBound -= 1;
function format(numStr, props) {
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var thousandsGroupStyle = props.thousandsGroupStyle; if ( thousandsGroupStyle === void 0 ) thousandsGroupStyle = 'thousand';
// don't apply formatting on empty string or '-'
if (numStr === '' || numStr === '-') {
return numStr;
}
var goToLeft =
!charIsNumber(value[caretRightBound]) ||
(direction === 'left' && caretPos !== firstHashPosition) ||
caretPos - caretLeftBound < caretRightBound - caretPos;
if (goToLeft) {
//check if number should be taken after the bound or after it
//if number preceding a valid number keep it after
return charIsNumber(value[caretLeftBound]) ? caretLeftBound + 1 : caretLeftBound;
}
return caretRightBound;
};
NumberFormat.prototype.getCaretPosition = function getCaretPosition (inputValue , formattedValue , caretPos ) {
var ref = this.props;
var format = ref.format;
var stateValue = this.state.value;
var numRegex = this.getNumberRegex(true);
var inputNumber = (inputValue.match(numRegex) || []).join('');
var formattedNumber = (formattedValue.match(numRegex) || []).join('');
var j, i;
j = 0;
for (i = 0; i < caretPos; i++) {
var currentInputChar = inputValue[i] || '';
var currentFormatChar = formattedValue[j] || '';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if (!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) {
continue;
}
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (
currentInputChar === '0' &&
currentFormatChar.match(numRegex) &&
currentFormatChar !== '0' &&
inputNumber.length !== formattedNumber.length
) {
continue;
}
//we are not using currentFormatChar because j can change here
while (currentInputChar !== formattedValue[j] && j < formattedValue.length) {
j++;
}
j++;
}
if (typeof format === 'string' && !stateValue) {
//set it to the maximum value so it goes after the last number
j = formattedValue.length;
}
//correct caret position if its outside of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;
};
/** caret specific methods ends **/
/** methods to remove formattting **/
NumberFormat.prototype.removePrefixAndSuffix = function removePrefixAndSuffix (val ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
//remove prefix and suffix
if (!format && val) {
var isNegative = val[0] === '-';
//remove negation sign
if (isNegative) { val = val.substring(1, val.length); }
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
var suffixLastIndex = val.lastIndexOf(suffix);
val =
suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length
? val.substring(0, suffixLastIndex)
: val;
//add negation sign back
if (isNegative) { val = '-' + val; }
}
return val;
};
NumberFormat.prototype.removePatternFormatting = function removePatternFormatting (val ) {
var ref = this.props;
var format = ref.format;
var formatArray = format.split('#').filter(function (str) { return str !== ''; });
var start = 0;
var numStr = '';
for (var i = 0, ln = formatArray.length; i <= ln; i++) {
var part = formatArray[i] || '';
//if i is the last fragment take the index of end of the value
//For case like +1 (911) 911 91 91 having pattern +1 (###) ### ## ##
var index = i === ln ? val.length : val.indexOf(part, start);
/* in any case if we don't find the pattern part in the value assume the val as numeric string
This will be also in case if user has started typing, in any other case it will not be -1
unless wrong prop value is provided */
if (index === -1) {
numStr = val;
break;
} else {
numStr += val.substring(start, index);
start = index + part.length;
}
}
return (numStr.match(this.getNumberRegex(true)) || []).join('');
};
NumberFormat.prototype.removeFormatting = function removeFormatting (val ) {
var ref = this.props;
var format = ref.format;
var removeFormatting = ref.removeFormatting;
if (!val) { return val; }
if (!format) {
val = this.removePrefixAndSuffix(val);
val = this.getFloatString(val);
} else if (typeof format === 'string') {
val = this.removePatternFormatting(val);
} else if (typeof removeFormatting === 'function') {
//condition need to be handled if format method is provide,
val = removeFormatting(val);
} else {
val = (val.match(this.getNumberRegex(true)) || []).join('');
}
return val;
};
/** methods to remove formattting end **/
/*** format specific methods start ***/
/**
* Format when # based string is provided
* @param {string} numStr Numeric String
* @return {string} formatted Value
*/
NumberFormat.prototype.formatWithPattern = function formatWithPattern (numStr ) {
var ref = this.props;
var format = ref.format;
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || this.getMaskAtIndex(hashCount);
hashCount += 1;
}
}
return formattedNumberAry.join('');
};
/**
* @param {string} numStr Numeric string/floatString] It always have decimalSeparator as .
* @return {string} formatted Value
*/
NumberFormat.prototype.formatAsNumber = function formatAsNumber (numStr ) {
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var allowNegative = ref.allowNegative;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var ref$1 = this.getSeparators();
var thousandSeparator = ref$1.thousandSeparator;
var decimalSeparator = ref$1.decimalSeparator;
var hasDecimalSeparator = numStr.indexOf('.') !== -1 || (decimalScale && fixedDecimalScale);
var ref$2 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$2.beforeDecimal;
var afterDecimal = ref$2.afterDecimal;
var addNegation = ref$2.addNegation; // eslint-disable-line prefer-const
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
/**
* Keep the decimal separator
* when decimalScale is not defined or non zero and the numStr has decimal in it
* Or if decimalScale is > 0 and fixeDecimalScale is true (even if numStr has no decimal)
*/
var hasDecimalSeparator = (decimalScale !== 0 && numStr.indexOf('.') !== -1) || (decimalScale && fixedDecimalScale);
var ref$1 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//apply decimal precision if its defined
if (decimalScale !== undefined) {
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
}
if (thousandSeparator) {
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
}
//add prefix and suffix
if (prefix) { beforeDecimal = prefix + beforeDecimal; }
if (suffix) { afterDecimal = afterDecimal + suffix; }
//add prefix and suffix when there is a number present
if (prefix)
{ beforeDecimal = prefix + beforeDecimal; }
if (suffix)
{ afterDecimal = afterDecimal + suffix; }
//restore negation sign
if (addNegation) { beforeDecimal = '-' + beforeDecimal; }
if (addNegation)
{ beforeDecimal = '-' + beforeDecimal; }
numStr = beforeDecimal + ((hasDecimalSeparator && decimalSeparator) || '') + afterDecimal;
return numStr;
};
NumberFormat.prototype.formatNumString = function formatNumString (numStr) {
if ( numStr === void 0 ) numStr = '';
var ref = this.props;
var format = ref.format;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var customNumerals = ref.customNumerals;
var formattedValue = numStr;
if (customNumerals && customNumerals.length === 10) {
var customNumeralRegex = new RegExp('[' + customNumerals.join('') + ']', 'g');
formattedValue = numStr.replace(customNumeralRegex, function (digit) { return customNumerals.indexOf(digit).toString(); }
);
}
function getSeparators(props) {
var decimalSeparator = props.decimalSeparator; if ( decimalSeparator === void 0 ) decimalSeparator = '.';
var thousandSeparator = props.thousandSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (numStr === '' && !allowEmptyFormatting) {
formattedValue = '';
} else if (numStr === '-' && !format) {
formattedValue = '-';
} else if (typeof format === 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format === 'function') {
formattedValue = format(formattedValue);
} else {
formattedValue = this.formatAsNumber(formattedValue);
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
};
}
function handleNegation(value, allowNegative) {
if ( value === void 0 ) value = '';
return formattedValue;
};
NumberFormat.prototype.formatValueProp = function formatValueProp (defaultValue ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var ref$1 = this.props;
var value = ref$1.value;
var isNumericString = ref$1.isNumericString;
// if value is undefined or null, use defaultValue instead
value = isNil(value) ? defaultValue : value;
var isNonNumericFalsy = !value && value !== 0;
if (isNonNumericFalsy && allowEmptyFormatting) {
value = '';
}
// if value is not defined return empty string
if (isNonNumericFalsy && !allowEmptyFormatting) { return ''; }
if (typeof value === 'number') {
value = toNumericString(value);
isNumericString = true;
}
//change infinity value to empty string
if (value === 'Infinity' && isNumericString) {
value = '';
}
//round the number based on decimalScale
//format only if non formatted value is provided
if (isNumericString && !format && typeof decimalScale === 'number') {
value = roundToPrecision(value, decimalScale, fixedDecimalScale);
}
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value);
return formattedValue;
};
NumberFormat.prototype.formatNegation = function formatNegation (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var allowNegative = ref.allowNegative;
var negationRegex = new RegExp('(-)');
var doubleNegationRegex = new RegExp('(-)(.)*(-)');
// Check number has '-' value
var hasNegation = negationRegex.test(value);
// Check number has 2 or more '-' values
var removeNegation = doubleNegationRegex.test(value);
//remove negation
value = value.replace(/-/g, '');
if (hasNegation && !removeNegation && allowNegative) {
value = '-' + value;
value = '-' + value;
}
return value;
};
}
function getNumberRegex(decimalSeparator, decimalScale, global) {
return new RegExp(("(^-)|[0-9]|" + (escapeRegExp(decimalSeparator))), global ? 'g' : undefined);
}
function removeFormatting(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
NumberFormat.prototype.formatInput = function formatInput (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var format = ref.format;
//format negation only if we are formatting as number
if (!format) {
value = this.removePrefixAndSuffix(value);
value = this.formatNegation(value);
}
//remove formatting from number
value = this.removeFormatting(value);
return this.formatNumString(value);
};
/*** format specific methods end ***/
NumberFormat.prototype.isCharacterAFormat = function isCharacterAFormat (caretPos , value ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
//check within format pattern
if (typeof format === 'string' && format[caretPos] !== '#') { return true; }
//check in number format
if (
!format &&
(caretPos < prefix.length ||
caretPos >= value.length - suffix.length ||
(decimalScale && fixedDecimalScale && value[caretPos] === decimalSeparator))
) {
return true;
}
return false;
};
/**
* This will check if any formatting got removed by the delete or backspace and reset the value
* It will also work as fallback if android chome keyDown handler does not work
**/
NumberFormat.prototype.correctInputValue = function correctInputValue (caretPos , lastValue , value ) {
var this$1 = this;
var ref = this.props;
var format = ref.format;
var allowNegative = ref.allowNegative;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
var decimalSeparator = ref$1.decimalSeparator;
var lastNumStr = this.state.numAsString || '';
var ref$2 = this.selectionBeforeInput;
var selectionStart = ref$2.selectionStart;
var selectionEnd = ref$2.selectionEnd;
var ref$3 = findChangedIndex(lastValue, value);
var start = ref$3.start;
var end = ref$3.end;
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var decimalScale = props.decimalScale;
var from = changeMeta.from;
var to = changeMeta.to;
var start = to.start;
var end = to.end;
var ref = getSeparators(props);
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var decimalSeparator = ref.decimalSeparator;
var isBeforeDecimalSeparator = value[end] === decimalSeparator;
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */
if (
!format &&
start === end &&
allowedDecimalSeparators.indexOf(value[selectionStart]) !== -1
) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
return (
value.substr(0, selectionStart) + separator + value.substr(selectionStart + 1, value.length)
);
if (end - start === 1 && allowedDecimalSeparators.indexOf(value[start]) !== -1) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
value = value.substring(0, start) + separator + value.substring(start + 1, value.length);
}
var leftBound = !!format ? 0 : prefix.length;
var rightBound = lastValue.length - (!!format ? 0 : suffix.length);
if (
// don't do anything if something got added
value.length > lastValue.length ||
// or if the new value is an empty string
!value.length ||
// or if nothing has changed, in which case start will be same as end
start === end ||
// or in case if whole input is selected and new value is typed
(selectionStart === 0 && selectionEnd === lastValue.length) ||
// or in case if the whole content is replaced by browser, example (autocomplete)
(start === 0 && end === lastValue.length) ||
// or if charcters between prefix and suffix is selected.
// For numeric inputs we apply the format so, prefix and suffix can be ignored
(selectionStart === leftBound && selectionEnd === rightBound)
) {
return value;
var hasNegation = false;
/**
* if prefix starts with - the number hast to have two - at the start
* if suffix starts with - and the value length is same as suffix length, then the - sign is from the suffix
* In other cases, if the value starts with - then it is a negation
*/
if (prefix.startsWith('-'))
{ hasNegation = value.startsWith('--'); }
else if (suffix.startsWith('-') && value.length === suffix.length)
{ hasNegation = false; }
else if (value[0] === '-')
{ hasNegation = true; }
// remove negation from start to simplify prefix logic as negation comes before prefix
if (hasNegation) {
value = value.substring(1);
// account for the removal of the negation for start and end index
start -= 1;
end -= 1;
}
// check whether the deleted portion has a character that is part of a format
var deletedValues = lastValue.substr(start, end - start);
var formatGotDeleted = !![].concat( deletedValues ).find(function (deletedVal, idx) { return this$1.isCharacterAFormat(idx + start, lastValue); }
);
// if it has, only remove characters that are not part of the format
if (formatGotDeleted) {
var deletedValuePortion = lastValue.substr(start);
var recordIndexOfFormatCharacters = {};
var resolvedPortion = [];
[].concat( deletedValuePortion ).forEach(function (currentPortion, idx) {
if (this$1.isCharacterAFormat(idx + start, lastValue)) {
recordIndexOfFormatCharacters[idx] = currentPortion;
} else if (idx > deletedValues.length - 1) {
resolvedPortion.push(currentPortion);
}
});
Object.keys(recordIndexOfFormatCharacters).forEach(function (idx) {
if (resolvedPortion.length > idx) {
resolvedPortion.splice(idx, 0, recordIndexOfFormatCharacters[idx]);
} else {
resolvedPortion.push(recordIndexOfFormatCharacters[idx]);
}
});
value = lastValue.substr(0, start) + resolvedPortion.join('');
}
//for numbers check if beforeDecimal got deleted and there is nothing after decimal,
/**
* remove prefix
* Remove whole prefix part if its present on the value
* If the prefix is partially deleted (in which case change start index will be less the prefix length)
* Remove only partial part of prefix.
*/
var startIndex = 0;
if (value.startsWith(prefix))
{ startIndex += prefix.length; }
else if (start < prefix.length)
{ startIndex = start; }
value = value.substring(startIndex);
// account for deleted prefix for end index
end -= startIndex;
/**
* Remove suffix
* Remove whole suffix part if its present on the value
* If the suffix is partially deleted (in which case change end index will be greater than the suffixStartIndex)
* remove the partial part of suffix
*/
var endIndex = value.length;
var suffixStartIndex = value.length - suffix.length;
if (value.endsWith(suffix))
{ endIndex = suffixStartIndex; }
else if (end > value.length - suffix.length)
{ endIndex = end; }
value = value.substring(0, endIndex);
// add the negation back and handle for double negation
value = handleNegation(hasNegation ? ("-" + value) : value, allowNegative);
// remove non numeric characters
value = (value.match(getNumberRegex(decimalSeparator, decimalScale, true)) || []).join('');
// replace the decimalSeparator with ., and only keep the first separator, ignore following ones
var firstIndex = value.indexOf(decimalSeparator);
value = value.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), function (match, index) {
return index === firstIndex ? '.' : '';
});
//check if beforeDecimal got deleted and there is nothing after decimal,
//clear all numbers in such case while keeping the - sign
if (!format) {
var numericString = this.removeFormatting(value);
var ref$4 = splitDecimal(
numericString,
allowNegative
);
var beforeDecimal = ref$4.beforeDecimal;
var afterDecimal = ref$4.afterDecimal;
var addNegation = ref$4.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1;
if (
numericString.length < lastNumStr.length &&
isBeforeDecimalPoint &&
var ref$1 = splitDecimal(value, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted before decimal (cursor is before decimal)
if (to.end - to.start < from.end - from.start &&
beforeDecimal === '' &&
!parseFloat(afterDecimal)
) {
return addNegation ? '-' : '';
}
isBeforeDecimalSeparator &&
!parseFloat(afterDecimal)) {
value = addNegation ? '-' : '';
}
return value;
};
/** Update value and caret position */
NumberFormat.prototype.updateValue = function updateValue (params
) {
var formattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
var ref = this.props;
var onValueChange = ref.onValueChange;
var ref$1 = this.state;
var lastValue = ref$1.value;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = getCurrentCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = formattedValue;
//get the caret position
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
}
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
*/
input.value = formattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
this.setPatchedCaretPosition(input, caretPos, formattedValue);
}
}
function getCaretBoundary(formattedValue, props) {
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hasNegation = formattedValue[0] === '-';
// fill for prefix and negation
boundaryAry.fill(false, 0, prefix.length + (hasNegation ? 1 : 0));
// fill for suffix
var valLn = formattedValue.length;
boundaryAry.fill(false, valLn - suffix.length + 1, valLn + 1);
return boundaryAry;
}
function validateProps(props) {
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
if (thousandSeparator === decimalSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
//calculate numeric string if not passed
if (numAsString === undefined) {
numAsString = this.removeFormatting(formattedValue);
}
function useNumericFormat(props) {
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
// validate props
validateProps(props);
var _format = function (numStr) { return format(numStr, props); };
var _removeFormatting = function (inputValue, changeMeta) { return removeFormatting(inputValue, changeMeta, props); };
var _isNumericString = isNumericString;
if (!isNil(value)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof value === 'number';
}
//update state if value is changed
if (formattedValue !== lastValue) {
this.setState({ value: formattedValue, numAsString: numAsString });
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
onValueChange(this.getValueObject(formattedValue, numAsString), { event: event, source: source });
else if (!isNil(defaultValue)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof defaultValue === 'number';
}
};
var roundIncomingValueToPrecision = function (value) {
if (isNil(value) || isNanValue(value))
{ return value; }
if (typeof value === 'number') {
value = toNumericString(value);
}
/**
* only round numeric or float string values coming through props,
* we don't need to do it for onChange events, as we want to prevent typing there
*/
if (_isNumericString && typeof decimalScale === 'number') {
return roundToPrecision(value, decimalScale, fixedDecimalScale);
}
return value;
};
var ref = useInternalValues(roundIncomingValueToPrecision(value), roundIncomingValueToPrecision(defaultValue), _isNumericString, _format, _removeFormatting, onValueChange);
var ref_0 = ref[0];
var numAsString = ref_0.numAsString;
var formattedValue = ref_0.formattedValue;
var _onValueChange = ref[1];
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if user hits backspace, while the cursor is before prefix, and the input has negation, remove the negation
if (key === 'Backspace' && value[0] === '-' && selectionStart === prefix.length + 1) {
// bring the cursor to after negation
setCaretPosition(el, 1);
}
// don't allow user to delete decimal separator when decimalScale and fixedDecimalScale is set
var ref = getSeparators(props);
var decimalSeparator = ref.decimalSeparator;
if (key === 'Backspace' &&
value[selectionStart - 1] === decimalSeparator &&
decimalScale &&
fixedDecimalScale) {
setCaretPosition(el, selectionStart - 1);
e.preventDefault();
}
// move cursor when delete or backspace is pressed before/after thousand separator
if (key === 'Backspace' && value[selectionStart - 1] === thousandSeparator) {
setCaretPosition(el, selectionStart - 1);
}
if (key === 'Delete' && value[selectionStart] === thousandSeparator) {
setCaretPosition(el, selectionStart + 1);
}
onKeyDown(e);
};
var _onBlur = function (e) {
var _value = numAsString;
// if there no no numeric value, clear the input
if (!_value.match(/\d/g)) {
_value = '';
}
// clear leading 0s
if (!allowLeadingZeros) {
_value = fixLeadingZero(_value);
}
// apply fixedDecimalScale on blur event
if (fixedDecimalScale && decimalScale) {
_value = roundToPrecision(_value, decimalScale, fixedDecimalScale);
}
if (_value !== numAsString) {
var formattedValue = format(_value, props);
_onValueChange({
formattedValue: formattedValue,
value: _value,
floatValue: parseFloat(_value),
}, {
event: e,
source: SourceType.event,
});
}
onBlur(e);
};
return {
value: formattedValue,
isNumericString: false,
onValueChange: _onValueChange,
format: _format,
removeFormatting: _removeFormatting,
getCaretBoundary: function (formattedValue) { return getCaretBoundary(formattedValue, props); },
onKeyDown: _onKeyDown,
onBlur: _onBlur,
};
}
function NumericFormat(props) {
var decimalSeparator = props.decimalSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
var thousandsGroupStyle = props.thousandsGroupStyle;
var suffix = props.suffix;
var allowNegative = props.allowNegative;
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown;
var onBlur = props.onBlur;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var restProps = __rest(props, ["decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "suffix", "allowNegative", "allowLeadingZeros", "onKeyDown", "onBlur", "thousandSeparator", "decimalScale", "fixedDecimalScale", "prefix", "defaultValue", "value", "isNumericString", "onValueChange"]);
var numericFormatProps = useNumericFormat(props);
return React__default.createElement(NumberFormatBase, Object.assign({}, restProps, numericFormatProps));
}
NumberFormat.prototype.onChange = function onChange (e ) {
var el = e.target;
var inputValue = el.value;
var ref = this;
var state = ref.state;
var props = ref.props;
var isAllowed = props.isAllowed;
var lastValue = state.value || '';
var currentCaretPosition = getCurrentCaretPosition(el);
inputValue = this.correctInputValue(currentCaretPosition, lastValue, inputValue);
var formattedValue = this.formatInput(inputValue) || '';
var numAsString = this.removeFormatting(formattedValue);
var valueObj = this.getValueObject(formattedValue, numAsString);
var isChangeAllowed = isAllowed(valueObj);
if (!isChangeAllowed) {
formattedValue = lastValue;
function format$1(numStr, props) {
var format = props.format;
var allowEmptyFormatting = props.allowEmptyFormatting;
var mask = props.mask;
if (numStr === '' && !allowEmptyFormatting)
{ return ''; }
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || getMaskAtIndex(mask, hashCount);
hashCount += 1;
}
}
return formattedNumberAry.join('');
}
function removeFormatting$1(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
inputValue: inputValue,
input: el,
event: e,
source: 'event',
});
if (isChangeAllowed) {
props.onChange(e);
}
};
NumberFormat.prototype.onBlur = function onBlur (e ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var format = props.format;
var onBlur = props.onBlur;
var allowLeadingZeros = props.allowLeadingZeros;
var numAsString = state.numAsString;
var lastValue = state.value;
this.focusedElm = null;
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
if (!format) {
// if the numAsString is not a valid number reset it to empty
if (isNaN(parseFloat(numAsString))) {
numAsString = '';
}
if (!allowLeadingZeros) {
numAsString = fixLeadingZero(numAsString);
}
var formattedValue = this.formatNumString(numAsString);
//change the state
if (formattedValue !== lastValue) {
// the event needs to be persisted because its properties can be accessed in an asynchronous way
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: e.target,
setCaretPosition: false,
event: e,
source: 'event',
});
onBlur(e);
return;
}
}
onBlur(e);
};
NumberFormat.prototype.onKeyDown = function onKeyDown (e ) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
var onKeyDown = ref.onKeyDown;
var ignoreDecimalSeparator = decimalScale !== undefined && fixedDecimalScale;
var numRegex = this.getNumberRegex(false, ignoreDecimalSeparator);
var negativeRegex = new RegExp('-');
var isPatternFormat = typeof format === 'string';
this.selectionBeforeInput = {
selectionStart: selectionStart,
selectionEnd: selectionEnd,
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var from = changeMeta.from;
var to = changeMeta.to;
var lastValue = changeMeta.lastValue; if ( lastValue === void 0 ) lastValue = '';
var isNumericSlot = function (caretPos) { return format[caretPos] === patternChar; };
var removeFormatChar = function (string, startIndex) {
var str = '';
for (var i = 0; i < string.length; i++) {
if (isNumericSlot(startIndex + i)) {
str += string[i];
}
}
return str;
};
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = selectionStart - 1;
} else if (key === 'ArrowRight') {
expectedCaretPosition = selectionStart + 1;
} else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
var extractNumbers = function (str) { return str.replace(/[^0-9]/g, ''); };
// if format doesn't have any number, remove all the non numeric characters
if (!format.match(/\d/)) {
return extractNumbers(value);
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
//also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
var leftBound = isPatternFormat ? format.indexOf('#') : prefix.length;
var rightBound = isPatternFormat ? format.lastIndexOf('#') + 1 : value.length - suffix.length;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = this.correctCaretPosition(value, expectedCaretPosition, direction);
} else if (
key === 'Delete' &&
!numRegex.test(value[expectedCaretPosition]) &&
!negativeRegex.test(value[expectedCaretPosition])
) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < rightBound) {
newCaretPosition++;
}
} else if (key === 'Backspace' && !numRegex.test(value[expectedCaretPosition])) {
/* NOTE: This is special case when backspace is pressed on a
negative value while the cursor position is after prefix. We can't handle it on onChange because
we will not have any information of keyPress
*/
if (selectionStart <= leftBound + 1 && value[0] === '-' && typeof format === 'undefined') {
var newValue = value.substring(1);
this.updateValue({
formattedValue: newValue,
caretPos: newCaretPosition,
input: el,
event: e,
source: 'event',
});
} else if (!negativeRegex.test(value[expectedCaretPosition])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound) {
newCaretPosition--;
/**
* if user paste the whole formatted text in an empty input, check if matches to the pattern
* and remove the format characters, if there is a mismatch on the pattern, do plane number extract
*/
if (lastValue === '' && value.length === format.length) {
var str = '';
for (var i = 0; i < value.length; i++) {
if (isNumericSlot(i)) {
str += value[i];
}
else if (value[i] !== format[i]) {
// if there is a mismatch on the pattern, do plane number extract
return extractNumbers(value);
}
}
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left');
}
return str;
}
if (
newCaretPosition !== expectedCaretPosition ||
expectedCaretPosition < leftBound ||
expectedCaretPosition > rightBound
) {
e.preventDefault();
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
if (e.isUnitTestRun) {
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
NumberFormat.prototype.onMouseUp = function onMouseUp (e ) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
* For partial change,
* where ever there is a change on the input, we can break the number in three parts
* 1st: left part which is unchanged
* 2nd: middle part which is changed
* 3rd: right part which is unchanged
*
* The first and third section will be same as last value, only the middle part will change
* We can consider on the change part all the new characters are non format characters.
* And on the first and last section it can have partial format characters.
*
* We pick first and last section from the lastValue (as that has 1-1 mapping with format)
* and middle one from the update value.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = this.correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
this.setPatchedCaretPosition(el, caretPosition, value);
}
}
this.props.onMouseUp(e);
};
NumberFormat.prototype.onFocus = function onFocus (e ) {
var this$1 = this;
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
this.focusedElm = e.target;
this.focusTimeout = setTimeout(function () {
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = this$1.correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (
caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)
) {
this$1.setPatchedCaretPosition(el, caretPosition, value);
}
this$1.props.onFocus(e);
}, 0);
};
NumberFormat.prototype.render = function render () {
var ref = this.props;
var type = ref.type;
var displayType = ref.displayType;
var customInput = ref.customInput;
var renderText = ref.renderText;
var getInputRef = ref.getInputRef;
var format = ref.format;
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var removeFormatting = ref.removeFormatting;
var mask = ref.mask;
var defaultValue = ref.defaultValue;
var isNumericString = ref.isNumericString;
var allowNegative = ref.allowNegative;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var allowLeadingZeros = ref.allowLeadingZeros;
var onValueChange = ref.onValueChange;
var isAllowed = ref.isAllowed;
var customNumerals = ref.customNumerals;
var onChange = ref.onChange;
var onKeyDown = ref.onKeyDown;
var onMouseUp = ref.onMouseUp;
var onFocus = ref.onFocus;
var onBlur = ref.onBlur;
var propValue = ref.value;
var rest = objectWithoutProperties( ref, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "thousandSeparator", "decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "decimalScale", "fixedDecimalScale", "prefix", "suffix", "removeFormatting", "mask", "defaultValue", "isNumericString", "allowNegative", "allowEmptyFormatting", "allowLeadingZeros", "onValueChange", "isAllowed", "customNumerals", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value"] );
var otherProps = rest;
var ref$1 = this.state;
var value = ref$1.value;
var mounted = ref$1.mounted;
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: value,
onChange: this.onChange,
onKeyDown: this.onKeyDown,
onMouseUp: this.onMouseUp,
onFocus: this.onFocus,
onBlur: this.onBlur,
var firstSection = lastValue.substring(0, from.start);
var middleSection = value.substring(to.start, to.end);
var lastSection = lastValue.substring(from.end);
return ("" + (removeFormatChar(firstSection, 0)) + (extractNumbers(middleSection)) + (removeFormatChar(lastSection, from.end)));
}
function getCaretBoundary$1(formattedValue, props) {
var format = props.format;
var mask = props.mask;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hashCount = 0;
var maskAndFormatMap = format.split('').map(function (char) {
if (char === patternChar) {
hashCount++;
return getMaskAtIndex(mask, hashCount - 1);
}
return undefined;
});
if (displayType === 'text') {
return renderText ? (
renderText(value, otherProps) || null
) : (
React.createElement( 'span', Object.assign({}, otherProps, { ref: getInputRef }),
value
)
);
} else if (customInput) {
var CustomInput = customInput;
return React.createElement( CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
var isPosAllowed = function (pos) {
// the position is allowed if the position is not masked and valid number area
return format[pos] === patternChar && formattedValue[pos] !== maskAndFormatMap[pos];
};
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
// Note: on pattern based format its denoted by patternCharacter
boundaryAry[i] = isPosAllowed(i) || isPosAllowed(i - 1);
}
// the first patternChar position is always allowed
boundaryAry[format.indexOf(patternChar)] = true;
return boundaryAry;
}
function validateProps$1(props) {
var mask = props.mask;
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("Mask " + mask + " should not contain numeric character;"));
}
}
}
function usePatternFormat(props) {
var formatProp = props.format;
var inputMode = props.inputMode; if ( inputMode === void 0 ) inputMode = 'numeric';
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
// validate props
validateProps$1(props);
var _onKeyDown = function (e) {
var key = e.key;
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if backspace is pressed after the format characters, bring it to numeric section
// if delete is pressed before the format characters, bring it to numeric section
if (key === 'Backspace' || key === 'Delete') {
// bring the cursor to closest numeric section
var index = selectionStart;
if (key === 'Backspace') {
while (index > 0 && formatProp[index - 1] !== patternChar) {
index--;
}
}
else {
var formatLn = formatProp.length;
while (index < formatLn && formatProp[index] !== patternChar) {
index++;
}
}
if (index !== selectionStart) {
setCaretPosition(el, index);
}
}
onKeyDown(e);
};
return {
inputMode: inputMode,
format: function (numStr) { return format$1(numStr, props); },
removeFormatting: function (inputValue, changeMeta) { return removeFormatting$1(inputValue, changeMeta, props); },
getCaretBoundary: function (formattedValue) { return getCaretBoundary$1(formattedValue, props); },
onKeyDown: _onKeyDown,
};
}
function PatternFormat(props) {
var mask = props.mask;
var allowEmptyFormatting = props.allowEmptyFormatting;
var formatProp = props.format;
var inputMode = props.inputMode;
var onKeyDown = props.onKeyDown;
var patternChar = props.patternChar;
var restProps = __rest(props, ["mask", "allowEmptyFormatting", "format", "inputMode", "onKeyDown", "patternChar"]);
var patternFormatProps = usePatternFormat(props);
return React__default.createElement(NumberFormatBase, Object.assign({}, restProps, patternFormatProps));
}
return React.createElement( 'input', Object.assign({}, inputProps, { ref: getInputRef }));
};
return NumberFormat;
}(React.Component));
NumberFormat.defaultProps = defaultProps;
module.exports = NumberFormat;
exports.NumberFormatBase = NumberFormatBase;
exports.NumericFormat = NumericFormat;
exports.PatternFormat = PatternFormat;
exports.getNumericCaretBoundary = getCaretBoundary;
exports.getPatternCaretBoundary = getCaretBoundary$1;
exports.numericFormatter = format;
exports.patterFormatter = format$1;
exports.removeNumericFormat = removeFormatting;
exports.removePatternFormat = removeFormatting$1;
exports.useNumericFormat = useNumericFormat;
exports.usePatternFormat = usePatternFormat;
/**
* react-number-format - 4.9.3
* react-number-format - 5.0.0-beta.1
* Author : Sudhanshu Yadav

@@ -8,83 +8,113 @@ * Copyright (c) 2016, 2022 to Sudhanshu Yadav, released under the MIT license.

import React from 'react';
import React, { useRef, useState, useMemo, useEffect } from 'react';
//
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
// basic noop function
function noop() {}
function returnTrue() {
return true;
}
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function charIsNumber(char ) {
return !!(char || '').match(/\d/);
function __rest(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;
}
function isNil(val ) {
return val === null || val === undefined;
}
var SourceType;
(function (SourceType) {
SourceType["event"] = "event";
SourceType["props"] = "prop";
})(SourceType || (SourceType = {}));
function escapeRegExp(str ) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
// basic noop function
function noop() { }
function charIsNumber(char) {
return !!(char || '').match(/\d/);
}
function getThousandsGroupRegex(thousandsGroupStyle ) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
function isNil(val) {
return val === null || val === undefined;
}
function isNanValue(val) {
return typeof val === 'number' && isNaN(val);
}
function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function getThousandsGroupRegex(thousandsGroupStyle) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
}
function applyThousandSeparator(str, thousandSeparator, thousandsGroupStyle) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator));
}
function usePersistentCallback(cb) {
var callbackRef = useRef(cb);
// keep the callback ref upto date
callbackRef.current = cb;
/**
* initialize a persistent callback which never changes
* through out the component lifecycle
*/
var persistentCbRef = useRef(function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
function applyThousandSeparator(
str ,
thousandSeparator ,
thousandsGroupStyle
) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (
str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator)
);
return callbackRef.current.apply(callbackRef, args);
});
return persistentCbRef.current;
}
//spilt a float number into different parts beforeDecimal, afterDecimal, and negation
function splitDecimal(numStr , allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
function splitDecimal(numStr, allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
var hasNagation = numStr[0] === '-';
var addNegation = hasNagation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNagation: hasNagation,
addNegation: addNegation,
};
var hasNegation = numStr[0] === '-';
var addNegation = hasNegation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNegation: hasNegation,
addNegation: addNegation,
};
}
function fixLeadingZero(numStr ) {
if (!numStr) { return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative) { numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
function fixLeadingZero(numStr) {
if (!numStr)
{ return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative)
{ numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
}
/**

@@ -94,59 +124,51 @@ * limit decimal numbers to given scale

*/
function limitToScale(numStr , scale , fixedDecimalScale ) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
function limitToScale(numStr, scale, fixedDecimalScale) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
}
function repeat(str, count) {
return Array(count + 1).join(str);
return Array(count + 1).join(str);
}
function toNumericString(num) {
num += ''; // typecast number to string
// store the sign and remove it from the number.
var sign = num[0] === '-' ? '-' : '';
if (sign) { num = num.substring(1); }
// split the number into cofficient and exponent
var ref = num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent) { return sign + coefficient; }
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
} else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
} else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
var _num = num + ''; // typecast number to string
// store the sign and remove it from the number.
var sign = _num[0] === '-' ? '-' : '';
if (sign)
{ _num = _num.substring(1); }
// split the number into cofficient and exponent
var ref = _num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent)
{ return sign + coefficient; }
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
}
else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
}
else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
}
/**

@@ -156,1232 +178,990 @@ * This method is required to round prop value to given scale.

*/
function roundToPrecision(numStr , scale , fixedDecimalScale ) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1) { return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNagation = ref.hasNagation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr =
afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (
(Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length)
);
}
return current + roundedStr;
function roundToPrecision(numStr, scale, fixedDecimalScale) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1)
{ return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNegation = ref.hasNegation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr = afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return ((Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length));
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = limitToScale(
roundedDecimalParts[1] || '',
Math.min(scale, afterDecimal.length),
fixedDecimalScale
);
var negation = hasNagation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
var decimalPart = limitToScale(roundedDecimalParts[1] || '', scale, fixedDecimalScale);
var negation = hasNegation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
}
/** set the caret positon in an input field **/
function setCaretPosition(el , caretPos ) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
function setCaretPosition(el, caretPos) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
/* @ts-ignore */
if (el.createTextRange) {
/* @ts-ignore */
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
function findChangeRange(prevValue, newValue) {
var i = 0, j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength)
{ i++; }
//check what has been changed from last
while (prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i) {
j++;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
return {
from: { start: i, end: prevLength - j },
to: { start: i, end: newLength - j },
};
}
/**
Given previous value and newValue it returns the index
start - end to which values have changed.
This function makes assumption about only consecutive
characters are changed which is correct assumption for caret input.
*/
function findChangedIndex(prevValue , newValue ) {
var i = 0,
j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength) { i++; }
//check what has been changed from last
while (
prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i
) {
j++;
}
return { start: i, end: prevLength - j };
}
/*
Returns a number whose value is limited to the given range
*/
function clamp(num , min , max ) {
return Math.min(Math.max(num, min), max);
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function getCurrentCaretPosition(el ) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
function geInputCaretPosition(el) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
}
function addInputMode(format ) {
return (
format ||
(typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)))
);
function addInputMode() {
return (typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)));
}
//
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
var defaultProps = {
displayType: 'input',
decimalSeparator: '.',
thousandsGroupStyle: 'thousand',
fixedDecimalScale: false,
prefix: '',
suffix: '',
allowNegative: true,
allowEmptyFormatting: false,
allowLeadingZeros: false,
isNumericString: false,
type: 'text',
onValueChange: noop,
onChange: noop,
onKeyDown: noop,
onMouseUp: noop,
onFocus: noop,
onBlur: noop,
isAllowed: returnTrue,
};
var NumberFormat = /*@__PURE__*/(function (superclass) {
function NumberFormat(props ) {
superclass.call(this, props);
var defaultValue = props.defaultValue;
//validate props
this.validateProps();
var formattedValue = this.formatValueProp(defaultValue);
this.state = {
value: formattedValue,
numAsString: this.removeFormatting(formattedValue),
mounted: false,
};
this.selectionBeforeInput = {
selectionStart: 0,
selectionEnd: 0,
};
this.onChange = this.onChange.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
if ( superclass ) NumberFormat.__proto__ = superclass;
NumberFormat.prototype = Object.create( superclass && superclass.prototype );
NumberFormat.prototype.constructor = NumberFormat;
NumberFormat.prototype.componentDidMount = function componentDidMount () {
// set mounted state
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
mounted: true,
});
};
NumberFormat.prototype.componentDidUpdate = function componentDidUpdate (prevProps ) {
this.updateValueIfRequired(prevProps);
};
NumberFormat.prototype.componentWillUnmount = function componentWillUnmount () {
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
};
NumberFormat.prototype.updateValueIfRequired = function updateValueIfRequired (prevProps ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var focusedElm = ref.focusedElm;
var stateValue = state.value;
var lastNumStr = state.numAsString; if ( lastNumStr === void 0 ) lastNumStr = '';
// If only state changed no need to do any thing
if (prevProps !== props) {
//validate props
this.validateProps();
var lastValueWithNewFormat = this.formatNumString(lastNumStr);
var formattedValue = isNil(props.value) ? lastValueWithNewFormat : this.formatValueProp();
var numAsString = this.removeFormatting(formattedValue);
var floatValue = parseFloat(numAsString);
var lastFloatValue = parseFloat(lastNumStr);
if (
//while typing set state only when float value changes
((!isNaN(floatValue) || !isNaN(lastFloatValue)) && floatValue !== lastFloatValue) ||
//can also set state when float value is same and the format props changes
lastValueWithNewFormat !== stateValue ||
//set state always when not in focus and formatted value is changed
(focusedElm === null && formattedValue !== stateValue)
) {
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: focusedElm,
source: 'prop',
event: null,
});
}
}
};
/** Misc methods **/
NumberFormat.prototype.getFloatString = function getFloatString (num) {
if ( num === void 0 ) num = '';
var ref = this.props;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var numRegex = this.getNumberRegex(true);
//remove negation for regex check
var hasNegation = num[0] === '-';
if (hasNegation) { num = num.replace('-', ''); }
//if decimal scale is zero remove decimal and number after decimalSeparator
if (decimalSeparator && decimalScale === 0) {
num = num.split(decimalSeparator)[0];
}
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.');
//remove extra decimals
var firstDecimalIndex = num.indexOf('.');
if (firstDecimalIndex !== -1) {
num = (num.substring(0, firstDecimalIndex)) + "." + (num
.substring(firstDecimalIndex + 1, num.length)
.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), ''));
}
//add negation back
if (hasNegation) { num = '-' + num; }
return num;
};
//returned regex assumes decimalSeparator is as per prop
NumberFormat.prototype.getNumberRegex = function getNumberRegex (g , ignoreDecimalSeparator ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var customNumerals = ref.customNumerals;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
return new RegExp(
'[0-9' +
(customNumerals ? customNumerals.join('') : '') +
']' +
(decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format
? '|' + escapeRegExp(decimalSeparator)
: ''),
g ? 'g' : undefined
);
};
NumberFormat.prototype.getSeparators = function getSeparators () {
var ref = this.props;
var decimalSeparator = ref.decimalSeparator;
var ref$1 = this.props;
var thousandSeparator = ref$1.thousandSeparator;
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
function getDefaultChangeMeta(value) {
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
from: {
start: 0,
end: 0,
},
to: {
start: 0,
end: value.length,
},
lastValue: '',
};
};
}
function getMaskAtIndex(mask, index) {
if ( mask === void 0 ) mask = ' ';
NumberFormat.prototype.getMaskAtIndex = function getMaskAtIndex (index ) {
var ref = this.props;
var mask = ref.mask; if ( mask === void 0 ) mask = ' ';
if (typeof mask === 'string') {
return mask;
return mask;
}
return mask[index] || ' ';
};
NumberFormat.prototype.getValueObject = function getValueObject (formattedValue , numAsString ) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
NumberFormat.prototype.validateProps = function validateProps () {
var ref = this.props;
var mask = ref.mask;
//validate decimalSeparator and thousandSeparator
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var thousandSeparator = ref$1.thousandSeparator;
if (decimalSeparator === thousandSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
function getCaretPosition(formattedValue, curValue, curCaretPos) {
var curValLn = curValue.length;
var formattedValueLn = formattedValue.length;
// create index map
var addedIndexMap = {};
var indexMap = new Array(curValLn);
for (var i = 0; i < curValLn; i++) {
indexMap[i] = -1;
for (var j = 0, jLn = formattedValueLn; j < jLn; j++) {
if (curValue[i] === formattedValue[j] && addedIndexMap[j] !== true) {
indexMap[i] = j;
addedIndexMap[j] = true;
break;
}
}
}
//validate mask
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("\n Mask " + mask + " should not contain numeric character;\n "));
}
/**
* For current caret position find closest characters (left and right side)
* which are properly mapped to formatted value.
* The idea is that the new caret position will exist always in the boundary of
* that mapped index
*/
var pos = curCaretPos;
while (pos < curValLn && (indexMap[pos] === -1 || !charIsNumber(curValue[pos]))) {
pos++;
}
};
/** Misc methods end **/
/** caret specific methods **/
NumberFormat.prototype.setPatchedCaretPosition = function setPatchedCaretPosition (el , caretPos , currentValue ) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
this.caretPositionTimeout = setTimeout(function () {
if (el.value === currentValue) { setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
NumberFormat.prototype.correctCaretPosition = function correctCaretPosition (value , caretPos , direction ) {
var ref = this.props;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
//if value is empty return 0
if (value === '') { return 0; }
//caret position should be between 0 and value length
caretPos = clamp(caretPos, 0, value.length);
//in case of format as number limit between prefix and suffix
if (!format) {
var hasNegation = value[0] === '-';
return clamp(caretPos, prefix.length + (hasNegation ? 1 : 0), value.length - suffix.length);
// if the caret position is on last keep the endIndex as last for formatted value
var endIndex = pos === curValLn || indexMap[pos] === -1 ? formattedValueLn : indexMap[pos];
pos = curCaretPos - 1;
while (pos > 0 && (indexMap[pos] === -1 || !charIsNumber(curValue[pos])))
{ pos--; }
var startIndex = pos === -1 || indexMap[pos] === -1 ? 0 : indexMap[pos] + 1;
/**
* case where a char is added on suffix and removed from middle, example 2sq345 becoming $2,345 sq
* there is still a mapping but the order of start index and end index is changed
*/
if (startIndex > endIndex)
{ return endIndex; }
/**
* given the current caret position if it closer to startIndex
* keep the new caret position on start index or keep it closer to endIndex
*/
return curCaretPos - startIndex < endIndex - curCaretPos ? startIndex : endIndex;
}
function caretUnknownFormatBoundary(formattedValue) {
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
boundaryAry[i] = Boolean(charIsNumber(formattedValue[i]) || charIsNumber(formattedValue[i - 1]));
}
return boundaryAry;
}
function useInternalValues(value, defaultValue, isNumericString, format, removeFormatting, onValueChange) {
if ( onValueChange === void 0 ) onValueChange = noop;
//in case if custom format method don't do anything
if (typeof format === 'function') { return caretPos; }
var propValues = useRef();
var getValues = usePersistentCallback(function (value) {
var formattedValue, numAsString;
if (isNil(value) || isNanValue(value)) {
numAsString = '';
formattedValue = '';
}
else if (typeof value === 'number' || isNumericString) {
numAsString = typeof value === 'number' ? toNumericString(value) : value;
formattedValue = format(numAsString);
}
else {
numAsString = removeFormatting(value, undefined);
formattedValue = value;
}
return { formattedValue: formattedValue, numAsString: numAsString };
});
var ref = useState(function () {
return getValues(defaultValue);
});
var values = ref[0];
var setValues = ref[1];
var _onValueChange = function (values, sourceInfo) {
setValues({
formattedValue: values.formattedValue,
numAsString: values.value,
});
onValueChange(values, sourceInfo);
};
useMemo(function () {
//if element is moved to uncontrolled mode, don't reset the value
if (!isNil(value)) {
propValues.current = getValues(value);
setValues(propValues.current);
}
else {
propValues.current = undefined;
}
}, [value, getValues]);
return [values, _onValueChange];
}
/* in case format is string find the closest # position from the caret position */
//in case the caretPos have input value on it don't do anything
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) {
return caretPos;
function defaultRemoveFormatting(value) {
return value.replace(/[^0-9]/g, '');
}
function defaultFormat(value) {
return value;
}
function NumberFormatBase(props) {
var type = props.type; if ( type === void 0 ) type = 'text';
var displayType = props.displayType; if ( displayType === void 0 ) displayType = 'input';
var customInput = props.customInput;
var renderText = props.renderText;
var getInputRef = props.getInputRef;
var format = props.format; if ( format === void 0 ) format = defaultFormat;
var removeFormatting = props.removeFormatting; if ( removeFormatting === void 0 ) removeFormatting = defaultRemoveFormatting;
var defaultValue = props.defaultValue;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var isAllowed = props.isAllowed;
var onChange = props.onChange; if ( onChange === void 0 ) onChange = noop;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onMouseUp = props.onMouseUp; if ( onMouseUp === void 0 ) onMouseUp = noop;
var onFocus = props.onFocus; if ( onFocus === void 0 ) onFocus = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var propValue = props.value;
var getCaretBoundary = props.getCaretBoundary; if ( getCaretBoundary === void 0 ) getCaretBoundary = caretUnknownFormatBoundary;
var otherProps = __rest(props, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "removeFormatting", "defaultValue", "isNumericString", "onValueChange", "isAllowed", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value", "getCaretBoundary"]);
var ref = useInternalValues(propValue, defaultValue, isNumericString, format, removeFormatting, onValueChange);
var ref_0 = ref[0];
var formattedValue = ref_0.formattedValue;
var numAsString = ref_0.numAsString;
var onFormattedValueChange = ref[1];
var lastUpdatedValue = useRef();
var _onValueChange = function (values, source) {
lastUpdatedValue.current = values.formattedValue;
onFormattedValueChange(values, source);
};
// check if there is any change in the value due to props change
useEffect(function () {
var newFormattedValue = format(numAsString);
// if the formatted value is not synced to parent, or if the formatted value is different
if (lastUpdatedValue.current === undefined || newFormattedValue !== lastUpdatedValue.current) {
var input = focusedElm.current;
updateValue({
formattedValue: newFormattedValue,
numAsString: numAsString,
input: input,
setCaretPosition: true,
source: SourceType.props,
event: null,
});
}
});
var ref$1 = useState(false);
var mounted = ref$1[0];
var setMounted = ref$1[1];
var focusedElm = useRef(null);
var timeout = useRef({
setCaretTimeout: null,
focusTimeout: null,
});
useEffect(function () {
setMounted(true);
return function () {
clearTimeout(timeout.current.setCaretTimeout);
clearTimeout(timeout.current.focusTimeout);
};
}, []);
var _format = format;
var getValueObject = function (formattedValue, numAsString) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
var setPatchedCaretPosition = function (el, caretPos, currentValue) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
timeout.current.setCaretTimeout = setTimeout(function () {
if (el.value === currentValue)
{ setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
var correctCaretPosition = function (value, caretPos, direction) {
var valLn = value.length;
// clamp caret position to [0, value.length]
caretPos = clamp(caretPos, 0, valLn);
var boundary = getCaretBoundary(value);
if (direction === 'left') {
while (caretPos >= 0 && !boundary[caretPos])
{ caretPos--; }
// if we don't find any suitable caret position on left, set it on first allowed position
if (caretPos === -1)
{ caretPos = boundary.indexOf(true); }
}
else {
while (caretPos <= valLn && !boundary[caretPos])
{ caretPos++; }
// if we don't find any suitable caret position on right, set it on last allowed position
if (caretPos > valLn)
{ caretPos = boundary.lastIndexOf(true); }
}
// if we still don't find caret position, set it at the end of value
if (caretPos === -1)
{ caretPos = valLn; }
return caretPos;
};
var getNewCaretPosition = function (inputValue, formattedValue, caretPos) {
var updatedCaretPos = getCaretPosition(formattedValue, inputValue, caretPos);
//correct caret position if its outside of editable area
updatedCaretPos = correctCaretPosition(formattedValue, updatedCaretPos);
return updatedCaretPos;
};
var updateValue = function (params) {
var newFormattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = geInputCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = newFormattedValue;
//get the caret position
caretPos = getNewCaretPosition(inputValue, newFormattedValue, currentCaretPosition);
}
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
*/
input.value = newFormattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
setPatchedCaretPosition(input, caretPos, newFormattedValue);
}
}
if (newFormattedValue !== formattedValue) {
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
_onValueChange(getValueObject(newFormattedValue, numAsString), { event: event, source: source });
}
};
var formatInputValue = function (inputValue, event, source) {
var changeRange = findChangeRange(formattedValue, inputValue);
var changeMeta = Object.assign(Object.assign({}, changeRange), { lastValue: formattedValue });
var _numAsString = removeFormatting(inputValue, changeMeta);
var _formattedValue = _format(_numAsString);
if (isAllowed && !isAllowed(getValueObject(_formattedValue, _numAsString))) {
return false;
}
updateValue({
formattedValue: _formattedValue,
numAsString: _numAsString,
inputValue: inputValue,
event: event,
source: source,
setCaretPosition: true,
input: event.target,
});
};
var _onChange = function (e) {
var el = e.target;
var inputValue = el.value;
var changed = formatInputValue(inputValue, e, SourceType.event);
if (changed)
{ onChange(e); }
};
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = Math.max(selectionStart - 1, 0);
}
else if (key === 'ArrowRight') {
expectedCaretPosition = Math.min(selectionStart + 1, value.length);
}
else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
// also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, direction);
}
else if (key === 'Delete' && !charIsNumber(value[expectedCaretPosition])) {
// in case of delete go to closest caret boundary on the right side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'right');
}
else if (key === 'Backspace' && !charIsNumber(value[expectedCaretPosition])) {
// in case of backspace go to closest caret boundary on the left side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'left');
}
if (newCaretPosition !== expectedCaretPosition) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
/* @ts-ignore */
if (e.isUnitTestRun) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
var _onMouseUp = function (e) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
setPatchedCaretPosition(el, caretPosition, value);
}
}
onMouseUp(e);
};
var _onFocus = function (e) {
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
var el = e.target;
focusedElm.current = el;
timeout.current.focusTimeout = setTimeout(function () {
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)) {
setPatchedCaretPosition(el, caretPosition, value);
}
onFocus(e);
}, 0);
};
var _onBlur = function (e) {
focusedElm.current = null;
clearTimeout(timeout.current.focusTimeout);
clearTimeout(timeout.current.setCaretTimeout);
onBlur(e);
};
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode() ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: formattedValue,
onChange: _onChange,
onKeyDown: _onKeyDown,
onMouseUp: _onMouseUp,
onFocus: _onFocus,
onBlur: _onBlur,
});
if (displayType === 'text') {
return renderText ? (React.createElement(React.Fragment, null, renderText(formattedValue, otherProps) || null)) : (React.createElement("span", Object.assign({}, otherProps, { ref: getInputRef }), formattedValue));
}
//if caretPos is just after input value don't do anything
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) {
return caretPos;
else if (customInput) {
var CustomInput = customInput;
/* @ts-ignore */
return React.createElement(CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
}
return React.createElement("input", Object.assign({}, inputProps, { ref: getInputRef }));
}
//find the nearest caret position
var firstHashPosition = format.indexOf('#');
var lastHashPosition = format.lastIndexOf('#');
//limit the cursor between the first # position and the last # position
caretPos = clamp(caretPos, firstHashPosition, lastHashPosition + 1);
var nextPos = format.substring(caretPos, format.length).indexOf('#');
var caretLeftBound = caretPos;
var caretRightBound = caretPos + (nextPos === -1 ? 0 : nextPos);
//get the position where the last number is present
while (
caretLeftBound > firstHashPosition &&
(format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))
) {
caretLeftBound -= 1;
function format(numStr, props) {
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var thousandsGroupStyle = props.thousandsGroupStyle; if ( thousandsGroupStyle === void 0 ) thousandsGroupStyle = 'thousand';
// don't apply formatting on empty string or '-'
if (numStr === '' || numStr === '-') {
return numStr;
}
var goToLeft =
!charIsNumber(value[caretRightBound]) ||
(direction === 'left' && caretPos !== firstHashPosition) ||
caretPos - caretLeftBound < caretRightBound - caretPos;
if (goToLeft) {
//check if number should be taken after the bound or after it
//if number preceding a valid number keep it after
return charIsNumber(value[caretLeftBound]) ? caretLeftBound + 1 : caretLeftBound;
}
return caretRightBound;
};
NumberFormat.prototype.getCaretPosition = function getCaretPosition (inputValue , formattedValue , caretPos ) {
var ref = this.props;
var format = ref.format;
var stateValue = this.state.value;
var numRegex = this.getNumberRegex(true);
var inputNumber = (inputValue.match(numRegex) || []).join('');
var formattedNumber = (formattedValue.match(numRegex) || []).join('');
var j, i;
j = 0;
for (i = 0; i < caretPos; i++) {
var currentInputChar = inputValue[i] || '';
var currentFormatChar = formattedValue[j] || '';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if (!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) {
continue;
}
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (
currentInputChar === '0' &&
currentFormatChar.match(numRegex) &&
currentFormatChar !== '0' &&
inputNumber.length !== formattedNumber.length
) {
continue;
}
//we are not using currentFormatChar because j can change here
while (currentInputChar !== formattedValue[j] && j < formattedValue.length) {
j++;
}
j++;
}
if (typeof format === 'string' && !stateValue) {
//set it to the maximum value so it goes after the last number
j = formattedValue.length;
}
//correct caret position if its outside of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;
};
/** caret specific methods ends **/
/** methods to remove formattting **/
NumberFormat.prototype.removePrefixAndSuffix = function removePrefixAndSuffix (val ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
//remove prefix and suffix
if (!format && val) {
var isNegative = val[0] === '-';
//remove negation sign
if (isNegative) { val = val.substring(1, val.length); }
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
var suffixLastIndex = val.lastIndexOf(suffix);
val =
suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length
? val.substring(0, suffixLastIndex)
: val;
//add negation sign back
if (isNegative) { val = '-' + val; }
}
return val;
};
NumberFormat.prototype.removePatternFormatting = function removePatternFormatting (val ) {
var ref = this.props;
var format = ref.format;
var formatArray = format.split('#').filter(function (str) { return str !== ''; });
var start = 0;
var numStr = '';
for (var i = 0, ln = formatArray.length; i <= ln; i++) {
var part = formatArray[i] || '';
//if i is the last fragment take the index of end of the value
//For case like +1 (911) 911 91 91 having pattern +1 (###) ### ## ##
var index = i === ln ? val.length : val.indexOf(part, start);
/* in any case if we don't find the pattern part in the value assume the val as numeric string
This will be also in case if user has started typing, in any other case it will not be -1
unless wrong prop value is provided */
if (index === -1) {
numStr = val;
break;
} else {
numStr += val.substring(start, index);
start = index + part.length;
}
}
return (numStr.match(this.getNumberRegex(true)) || []).join('');
};
NumberFormat.prototype.removeFormatting = function removeFormatting (val ) {
var ref = this.props;
var format = ref.format;
var removeFormatting = ref.removeFormatting;
if (!val) { return val; }
if (!format) {
val = this.removePrefixAndSuffix(val);
val = this.getFloatString(val);
} else if (typeof format === 'string') {
val = this.removePatternFormatting(val);
} else if (typeof removeFormatting === 'function') {
//condition need to be handled if format method is provide,
val = removeFormatting(val);
} else {
val = (val.match(this.getNumberRegex(true)) || []).join('');
}
return val;
};
/** methods to remove formattting end **/
/*** format specific methods start ***/
/**
* Format when # based string is provided
* @param {string} numStr Numeric String
* @return {string} formatted Value
*/
NumberFormat.prototype.formatWithPattern = function formatWithPattern (numStr ) {
var ref = this.props;
var format = ref.format;
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || this.getMaskAtIndex(hashCount);
hashCount += 1;
}
}
return formattedNumberAry.join('');
};
/**
* @param {string} numStr Numeric string/floatString] It always have decimalSeparator as .
* @return {string} formatted Value
*/
NumberFormat.prototype.formatAsNumber = function formatAsNumber (numStr ) {
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var allowNegative = ref.allowNegative;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var ref$1 = this.getSeparators();
var thousandSeparator = ref$1.thousandSeparator;
var decimalSeparator = ref$1.decimalSeparator;
var hasDecimalSeparator = numStr.indexOf('.') !== -1 || (decimalScale && fixedDecimalScale);
var ref$2 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$2.beforeDecimal;
var afterDecimal = ref$2.afterDecimal;
var addNegation = ref$2.addNegation; // eslint-disable-line prefer-const
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
/**
* Keep the decimal separator
* when decimalScale is not defined or non zero and the numStr has decimal in it
* Or if decimalScale is > 0 and fixeDecimalScale is true (even if numStr has no decimal)
*/
var hasDecimalSeparator = (decimalScale !== 0 && numStr.indexOf('.') !== -1) || (decimalScale && fixedDecimalScale);
var ref$1 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//apply decimal precision if its defined
if (decimalScale !== undefined) {
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
}
if (thousandSeparator) {
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
}
//add prefix and suffix
if (prefix) { beforeDecimal = prefix + beforeDecimal; }
if (suffix) { afterDecimal = afterDecimal + suffix; }
//add prefix and suffix when there is a number present
if (prefix)
{ beforeDecimal = prefix + beforeDecimal; }
if (suffix)
{ afterDecimal = afterDecimal + suffix; }
//restore negation sign
if (addNegation) { beforeDecimal = '-' + beforeDecimal; }
if (addNegation)
{ beforeDecimal = '-' + beforeDecimal; }
numStr = beforeDecimal + ((hasDecimalSeparator && decimalSeparator) || '') + afterDecimal;
return numStr;
};
NumberFormat.prototype.formatNumString = function formatNumString (numStr) {
if ( numStr === void 0 ) numStr = '';
var ref = this.props;
var format = ref.format;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var customNumerals = ref.customNumerals;
var formattedValue = numStr;
if (customNumerals && customNumerals.length === 10) {
var customNumeralRegex = new RegExp('[' + customNumerals.join('') + ']', 'g');
formattedValue = numStr.replace(customNumeralRegex, function (digit) { return customNumerals.indexOf(digit).toString(); }
);
}
function getSeparators(props) {
var decimalSeparator = props.decimalSeparator; if ( decimalSeparator === void 0 ) decimalSeparator = '.';
var thousandSeparator = props.thousandSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (numStr === '' && !allowEmptyFormatting) {
formattedValue = '';
} else if (numStr === '-' && !format) {
formattedValue = '-';
} else if (typeof format === 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format === 'function') {
formattedValue = format(formattedValue);
} else {
formattedValue = this.formatAsNumber(formattedValue);
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
};
}
function handleNegation(value, allowNegative) {
if ( value === void 0 ) value = '';
return formattedValue;
};
NumberFormat.prototype.formatValueProp = function formatValueProp (defaultValue ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var ref$1 = this.props;
var value = ref$1.value;
var isNumericString = ref$1.isNumericString;
// if value is undefined or null, use defaultValue instead
value = isNil(value) ? defaultValue : value;
var isNonNumericFalsy = !value && value !== 0;
if (isNonNumericFalsy && allowEmptyFormatting) {
value = '';
}
// if value is not defined return empty string
if (isNonNumericFalsy && !allowEmptyFormatting) { return ''; }
if (typeof value === 'number') {
value = toNumericString(value);
isNumericString = true;
}
//change infinity value to empty string
if (value === 'Infinity' && isNumericString) {
value = '';
}
//round the number based on decimalScale
//format only if non formatted value is provided
if (isNumericString && !format && typeof decimalScale === 'number') {
value = roundToPrecision(value, decimalScale, fixedDecimalScale);
}
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value);
return formattedValue;
};
NumberFormat.prototype.formatNegation = function formatNegation (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var allowNegative = ref.allowNegative;
var negationRegex = new RegExp('(-)');
var doubleNegationRegex = new RegExp('(-)(.)*(-)');
// Check number has '-' value
var hasNegation = negationRegex.test(value);
// Check number has 2 or more '-' values
var removeNegation = doubleNegationRegex.test(value);
//remove negation
value = value.replace(/-/g, '');
if (hasNegation && !removeNegation && allowNegative) {
value = '-' + value;
value = '-' + value;
}
return value;
};
}
function getNumberRegex(decimalSeparator, decimalScale, global) {
return new RegExp(("(^-)|[0-9]|" + (escapeRegExp(decimalSeparator))), global ? 'g' : undefined);
}
function removeFormatting(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
NumberFormat.prototype.formatInput = function formatInput (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var format = ref.format;
//format negation only if we are formatting as number
if (!format) {
value = this.removePrefixAndSuffix(value);
value = this.formatNegation(value);
}
//remove formatting from number
value = this.removeFormatting(value);
return this.formatNumString(value);
};
/*** format specific methods end ***/
NumberFormat.prototype.isCharacterAFormat = function isCharacterAFormat (caretPos , value ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
//check within format pattern
if (typeof format === 'string' && format[caretPos] !== '#') { return true; }
//check in number format
if (
!format &&
(caretPos < prefix.length ||
caretPos >= value.length - suffix.length ||
(decimalScale && fixedDecimalScale && value[caretPos] === decimalSeparator))
) {
return true;
}
return false;
};
/**
* This will check if any formatting got removed by the delete or backspace and reset the value
* It will also work as fallback if android chome keyDown handler does not work
**/
NumberFormat.prototype.correctInputValue = function correctInputValue (caretPos , lastValue , value ) {
var this$1 = this;
var ref = this.props;
var format = ref.format;
var allowNegative = ref.allowNegative;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
var decimalSeparator = ref$1.decimalSeparator;
var lastNumStr = this.state.numAsString || '';
var ref$2 = this.selectionBeforeInput;
var selectionStart = ref$2.selectionStart;
var selectionEnd = ref$2.selectionEnd;
var ref$3 = findChangedIndex(lastValue, value);
var start = ref$3.start;
var end = ref$3.end;
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var decimalScale = props.decimalScale;
var from = changeMeta.from;
var to = changeMeta.to;
var start = to.start;
var end = to.end;
var ref = getSeparators(props);
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var decimalSeparator = ref.decimalSeparator;
var isBeforeDecimalSeparator = value[end] === decimalSeparator;
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */
if (
!format &&
start === end &&
allowedDecimalSeparators.indexOf(value[selectionStart]) !== -1
) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
return (
value.substr(0, selectionStart) + separator + value.substr(selectionStart + 1, value.length)
);
if (end - start === 1 && allowedDecimalSeparators.indexOf(value[start]) !== -1) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
value = value.substring(0, start) + separator + value.substring(start + 1, value.length);
}
var leftBound = !!format ? 0 : prefix.length;
var rightBound = lastValue.length - (!!format ? 0 : suffix.length);
if (
// don't do anything if something got added
value.length > lastValue.length ||
// or if the new value is an empty string
!value.length ||
// or if nothing has changed, in which case start will be same as end
start === end ||
// or in case if whole input is selected and new value is typed
(selectionStart === 0 && selectionEnd === lastValue.length) ||
// or in case if the whole content is replaced by browser, example (autocomplete)
(start === 0 && end === lastValue.length) ||
// or if charcters between prefix and suffix is selected.
// For numeric inputs we apply the format so, prefix and suffix can be ignored
(selectionStart === leftBound && selectionEnd === rightBound)
) {
return value;
var hasNegation = false;
/**
* if prefix starts with - the number hast to have two - at the start
* if suffix starts with - and the value length is same as suffix length, then the - sign is from the suffix
* In other cases, if the value starts with - then it is a negation
*/
if (prefix.startsWith('-'))
{ hasNegation = value.startsWith('--'); }
else if (suffix.startsWith('-') && value.length === suffix.length)
{ hasNegation = false; }
else if (value[0] === '-')
{ hasNegation = true; }
// remove negation from start to simplify prefix logic as negation comes before prefix
if (hasNegation) {
value = value.substring(1);
// account for the removal of the negation for start and end index
start -= 1;
end -= 1;
}
// check whether the deleted portion has a character that is part of a format
var deletedValues = lastValue.substr(start, end - start);
var formatGotDeleted = !![].concat( deletedValues ).find(function (deletedVal, idx) { return this$1.isCharacterAFormat(idx + start, lastValue); }
);
// if it has, only remove characters that are not part of the format
if (formatGotDeleted) {
var deletedValuePortion = lastValue.substr(start);
var recordIndexOfFormatCharacters = {};
var resolvedPortion = [];
[].concat( deletedValuePortion ).forEach(function (currentPortion, idx) {
if (this$1.isCharacterAFormat(idx + start, lastValue)) {
recordIndexOfFormatCharacters[idx] = currentPortion;
} else if (idx > deletedValues.length - 1) {
resolvedPortion.push(currentPortion);
}
});
Object.keys(recordIndexOfFormatCharacters).forEach(function (idx) {
if (resolvedPortion.length > idx) {
resolvedPortion.splice(idx, 0, recordIndexOfFormatCharacters[idx]);
} else {
resolvedPortion.push(recordIndexOfFormatCharacters[idx]);
}
});
value = lastValue.substr(0, start) + resolvedPortion.join('');
}
//for numbers check if beforeDecimal got deleted and there is nothing after decimal,
/**
* remove prefix
* Remove whole prefix part if its present on the value
* If the prefix is partially deleted (in which case change start index will be less the prefix length)
* Remove only partial part of prefix.
*/
var startIndex = 0;
if (value.startsWith(prefix))
{ startIndex += prefix.length; }
else if (start < prefix.length)
{ startIndex = start; }
value = value.substring(startIndex);
// account for deleted prefix for end index
end -= startIndex;
/**
* Remove suffix
* Remove whole suffix part if its present on the value
* If the suffix is partially deleted (in which case change end index will be greater than the suffixStartIndex)
* remove the partial part of suffix
*/
var endIndex = value.length;
var suffixStartIndex = value.length - suffix.length;
if (value.endsWith(suffix))
{ endIndex = suffixStartIndex; }
else if (end > value.length - suffix.length)
{ endIndex = end; }
value = value.substring(0, endIndex);
// add the negation back and handle for double negation
value = handleNegation(hasNegation ? ("-" + value) : value, allowNegative);
// remove non numeric characters
value = (value.match(getNumberRegex(decimalSeparator, decimalScale, true)) || []).join('');
// replace the decimalSeparator with ., and only keep the first separator, ignore following ones
var firstIndex = value.indexOf(decimalSeparator);
value = value.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), function (match, index) {
return index === firstIndex ? '.' : '';
});
//check if beforeDecimal got deleted and there is nothing after decimal,
//clear all numbers in such case while keeping the - sign
if (!format) {
var numericString = this.removeFormatting(value);
var ref$4 = splitDecimal(
numericString,
allowNegative
);
var beforeDecimal = ref$4.beforeDecimal;
var afterDecimal = ref$4.afterDecimal;
var addNegation = ref$4.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1;
if (
numericString.length < lastNumStr.length &&
isBeforeDecimalPoint &&
var ref$1 = splitDecimal(value, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted before decimal (cursor is before decimal)
if (to.end - to.start < from.end - from.start &&
beforeDecimal === '' &&
!parseFloat(afterDecimal)
) {
return addNegation ? '-' : '';
}
isBeforeDecimalSeparator &&
!parseFloat(afterDecimal)) {
value = addNegation ? '-' : '';
}
return value;
};
/** Update value and caret position */
NumberFormat.prototype.updateValue = function updateValue (params
) {
var formattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
var ref = this.props;
var onValueChange = ref.onValueChange;
var ref$1 = this.state;
var lastValue = ref$1.value;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = getCurrentCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = formattedValue;
//get the caret position
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
}
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
*/
input.value = formattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
this.setPatchedCaretPosition(input, caretPos, formattedValue);
}
}
function getCaretBoundary(formattedValue, props) {
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hasNegation = formattedValue[0] === '-';
// fill for prefix and negation
boundaryAry.fill(false, 0, prefix.length + (hasNegation ? 1 : 0));
// fill for suffix
var valLn = formattedValue.length;
boundaryAry.fill(false, valLn - suffix.length + 1, valLn + 1);
return boundaryAry;
}
function validateProps(props) {
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
if (thousandSeparator === decimalSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
//calculate numeric string if not passed
if (numAsString === undefined) {
numAsString = this.removeFormatting(formattedValue);
}
function useNumericFormat(props) {
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
// validate props
validateProps(props);
var _format = function (numStr) { return format(numStr, props); };
var _removeFormatting = function (inputValue, changeMeta) { return removeFormatting(inputValue, changeMeta, props); };
var _isNumericString = isNumericString;
if (!isNil(value)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof value === 'number';
}
//update state if value is changed
if (formattedValue !== lastValue) {
this.setState({ value: formattedValue, numAsString: numAsString });
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
onValueChange(this.getValueObject(formattedValue, numAsString), { event: event, source: source });
else if (!isNil(defaultValue)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof defaultValue === 'number';
}
};
var roundIncomingValueToPrecision = function (value) {
if (isNil(value) || isNanValue(value))
{ return value; }
if (typeof value === 'number') {
value = toNumericString(value);
}
/**
* only round numeric or float string values coming through props,
* we don't need to do it for onChange events, as we want to prevent typing there
*/
if (_isNumericString && typeof decimalScale === 'number') {
return roundToPrecision(value, decimalScale, fixedDecimalScale);
}
return value;
};
var ref = useInternalValues(roundIncomingValueToPrecision(value), roundIncomingValueToPrecision(defaultValue), _isNumericString, _format, _removeFormatting, onValueChange);
var ref_0 = ref[0];
var numAsString = ref_0.numAsString;
var formattedValue = ref_0.formattedValue;
var _onValueChange = ref[1];
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if user hits backspace, while the cursor is before prefix, and the input has negation, remove the negation
if (key === 'Backspace' && value[0] === '-' && selectionStart === prefix.length + 1) {
// bring the cursor to after negation
setCaretPosition(el, 1);
}
// don't allow user to delete decimal separator when decimalScale and fixedDecimalScale is set
var ref = getSeparators(props);
var decimalSeparator = ref.decimalSeparator;
if (key === 'Backspace' &&
value[selectionStart - 1] === decimalSeparator &&
decimalScale &&
fixedDecimalScale) {
setCaretPosition(el, selectionStart - 1);
e.preventDefault();
}
// move cursor when delete or backspace is pressed before/after thousand separator
if (key === 'Backspace' && value[selectionStart - 1] === thousandSeparator) {
setCaretPosition(el, selectionStart - 1);
}
if (key === 'Delete' && value[selectionStart] === thousandSeparator) {
setCaretPosition(el, selectionStart + 1);
}
onKeyDown(e);
};
var _onBlur = function (e) {
var _value = numAsString;
// if there no no numeric value, clear the input
if (!_value.match(/\d/g)) {
_value = '';
}
// clear leading 0s
if (!allowLeadingZeros) {
_value = fixLeadingZero(_value);
}
// apply fixedDecimalScale on blur event
if (fixedDecimalScale && decimalScale) {
_value = roundToPrecision(_value, decimalScale, fixedDecimalScale);
}
if (_value !== numAsString) {
var formattedValue = format(_value, props);
_onValueChange({
formattedValue: formattedValue,
value: _value,
floatValue: parseFloat(_value),
}, {
event: e,
source: SourceType.event,
});
}
onBlur(e);
};
return {
value: formattedValue,
isNumericString: false,
onValueChange: _onValueChange,
format: _format,
removeFormatting: _removeFormatting,
getCaretBoundary: function (formattedValue) { return getCaretBoundary(formattedValue, props); },
onKeyDown: _onKeyDown,
onBlur: _onBlur,
};
}
function NumericFormat(props) {
var decimalSeparator = props.decimalSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
var thousandsGroupStyle = props.thousandsGroupStyle;
var suffix = props.suffix;
var allowNegative = props.allowNegative;
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown;
var onBlur = props.onBlur;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var restProps = __rest(props, ["decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "suffix", "allowNegative", "allowLeadingZeros", "onKeyDown", "onBlur", "thousandSeparator", "decimalScale", "fixedDecimalScale", "prefix", "defaultValue", "value", "isNumericString", "onValueChange"]);
var numericFormatProps = useNumericFormat(props);
return React.createElement(NumberFormatBase, Object.assign({}, restProps, numericFormatProps));
}
NumberFormat.prototype.onChange = function onChange (e ) {
var el = e.target;
var inputValue = el.value;
var ref = this;
var state = ref.state;
var props = ref.props;
var isAllowed = props.isAllowed;
var lastValue = state.value || '';
var currentCaretPosition = getCurrentCaretPosition(el);
inputValue = this.correctInputValue(currentCaretPosition, lastValue, inputValue);
var formattedValue = this.formatInput(inputValue) || '';
var numAsString = this.removeFormatting(formattedValue);
var valueObj = this.getValueObject(formattedValue, numAsString);
var isChangeAllowed = isAllowed(valueObj);
if (!isChangeAllowed) {
formattedValue = lastValue;
function format$1(numStr, props) {
var format = props.format;
var allowEmptyFormatting = props.allowEmptyFormatting;
var mask = props.mask;
if (numStr === '' && !allowEmptyFormatting)
{ return ''; }
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || getMaskAtIndex(mask, hashCount);
hashCount += 1;
}
}
return formattedNumberAry.join('');
}
function removeFormatting$1(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
inputValue: inputValue,
input: el,
event: e,
source: 'event',
});
if (isChangeAllowed) {
props.onChange(e);
}
};
NumberFormat.prototype.onBlur = function onBlur (e ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var format = props.format;
var onBlur = props.onBlur;
var allowLeadingZeros = props.allowLeadingZeros;
var numAsString = state.numAsString;
var lastValue = state.value;
this.focusedElm = null;
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
if (!format) {
// if the numAsString is not a valid number reset it to empty
if (isNaN(parseFloat(numAsString))) {
numAsString = '';
}
if (!allowLeadingZeros) {
numAsString = fixLeadingZero(numAsString);
}
var formattedValue = this.formatNumString(numAsString);
//change the state
if (formattedValue !== lastValue) {
// the event needs to be persisted because its properties can be accessed in an asynchronous way
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: e.target,
setCaretPosition: false,
event: e,
source: 'event',
});
onBlur(e);
return;
}
}
onBlur(e);
};
NumberFormat.prototype.onKeyDown = function onKeyDown (e ) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
var onKeyDown = ref.onKeyDown;
var ignoreDecimalSeparator = decimalScale !== undefined && fixedDecimalScale;
var numRegex = this.getNumberRegex(false, ignoreDecimalSeparator);
var negativeRegex = new RegExp('-');
var isPatternFormat = typeof format === 'string';
this.selectionBeforeInput = {
selectionStart: selectionStart,
selectionEnd: selectionEnd,
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var from = changeMeta.from;
var to = changeMeta.to;
var lastValue = changeMeta.lastValue; if ( lastValue === void 0 ) lastValue = '';
var isNumericSlot = function (caretPos) { return format[caretPos] === patternChar; };
var removeFormatChar = function (string, startIndex) {
var str = '';
for (var i = 0; i < string.length; i++) {
if (isNumericSlot(startIndex + i)) {
str += string[i];
}
}
return str;
};
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = selectionStart - 1;
} else if (key === 'ArrowRight') {
expectedCaretPosition = selectionStart + 1;
} else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
var extractNumbers = function (str) { return str.replace(/[^0-9]/g, ''); };
// if format doesn't have any number, remove all the non numeric characters
if (!format.match(/\d/)) {
return extractNumbers(value);
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
//also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
var leftBound = isPatternFormat ? format.indexOf('#') : prefix.length;
var rightBound = isPatternFormat ? format.lastIndexOf('#') + 1 : value.length - suffix.length;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = this.correctCaretPosition(value, expectedCaretPosition, direction);
} else if (
key === 'Delete' &&
!numRegex.test(value[expectedCaretPosition]) &&
!negativeRegex.test(value[expectedCaretPosition])
) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < rightBound) {
newCaretPosition++;
}
} else if (key === 'Backspace' && !numRegex.test(value[expectedCaretPosition])) {
/* NOTE: This is special case when backspace is pressed on a
negative value while the cursor position is after prefix. We can't handle it on onChange because
we will not have any information of keyPress
*/
if (selectionStart <= leftBound + 1 && value[0] === '-' && typeof format === 'undefined') {
var newValue = value.substring(1);
this.updateValue({
formattedValue: newValue,
caretPos: newCaretPosition,
input: el,
event: e,
source: 'event',
});
} else if (!negativeRegex.test(value[expectedCaretPosition])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound) {
newCaretPosition--;
/**
* if user paste the whole formatted text in an empty input, check if matches to the pattern
* and remove the format characters, if there is a mismatch on the pattern, do plane number extract
*/
if (lastValue === '' && value.length === format.length) {
var str = '';
for (var i = 0; i < value.length; i++) {
if (isNumericSlot(i)) {
str += value[i];
}
else if (value[i] !== format[i]) {
// if there is a mismatch on the pattern, do plane number extract
return extractNumbers(value);
}
}
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left');
}
return str;
}
if (
newCaretPosition !== expectedCaretPosition ||
expectedCaretPosition < leftBound ||
expectedCaretPosition > rightBound
) {
e.preventDefault();
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
if (e.isUnitTestRun) {
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
NumberFormat.prototype.onMouseUp = function onMouseUp (e ) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
* For partial change,
* where ever there is a change on the input, we can break the number in three parts
* 1st: left part which is unchanged
* 2nd: middle part which is changed
* 3rd: right part which is unchanged
*
* The first and third section will be same as last value, only the middle part will change
* We can consider on the change part all the new characters are non format characters.
* And on the first and last section it can have partial format characters.
*
* We pick first and last section from the lastValue (as that has 1-1 mapping with format)
* and middle one from the update value.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = this.correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
this.setPatchedCaretPosition(el, caretPosition, value);
}
}
this.props.onMouseUp(e);
};
NumberFormat.prototype.onFocus = function onFocus (e ) {
var this$1 = this;
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
this.focusedElm = e.target;
this.focusTimeout = setTimeout(function () {
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = this$1.correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (
caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)
) {
this$1.setPatchedCaretPosition(el, caretPosition, value);
}
this$1.props.onFocus(e);
}, 0);
};
NumberFormat.prototype.render = function render () {
var ref = this.props;
var type = ref.type;
var displayType = ref.displayType;
var customInput = ref.customInput;
var renderText = ref.renderText;
var getInputRef = ref.getInputRef;
var format = ref.format;
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var removeFormatting = ref.removeFormatting;
var mask = ref.mask;
var defaultValue = ref.defaultValue;
var isNumericString = ref.isNumericString;
var allowNegative = ref.allowNegative;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var allowLeadingZeros = ref.allowLeadingZeros;
var onValueChange = ref.onValueChange;
var isAllowed = ref.isAllowed;
var customNumerals = ref.customNumerals;
var onChange = ref.onChange;
var onKeyDown = ref.onKeyDown;
var onMouseUp = ref.onMouseUp;
var onFocus = ref.onFocus;
var onBlur = ref.onBlur;
var propValue = ref.value;
var rest = objectWithoutProperties( ref, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "thousandSeparator", "decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "decimalScale", "fixedDecimalScale", "prefix", "suffix", "removeFormatting", "mask", "defaultValue", "isNumericString", "allowNegative", "allowEmptyFormatting", "allowLeadingZeros", "onValueChange", "isAllowed", "customNumerals", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value"] );
var otherProps = rest;
var ref$1 = this.state;
var value = ref$1.value;
var mounted = ref$1.mounted;
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: value,
onChange: this.onChange,
onKeyDown: this.onKeyDown,
onMouseUp: this.onMouseUp,
onFocus: this.onFocus,
onBlur: this.onBlur,
var firstSection = lastValue.substring(0, from.start);
var middleSection = value.substring(to.start, to.end);
var lastSection = lastValue.substring(from.end);
return ("" + (removeFormatChar(firstSection, 0)) + (extractNumbers(middleSection)) + (removeFormatChar(lastSection, from.end)));
}
function getCaretBoundary$1(formattedValue, props) {
var format = props.format;
var mask = props.mask;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hashCount = 0;
var maskAndFormatMap = format.split('').map(function (char) {
if (char === patternChar) {
hashCount++;
return getMaskAtIndex(mask, hashCount - 1);
}
return undefined;
});
if (displayType === 'text') {
return renderText ? (
renderText(value, otherProps) || null
) : (
React.createElement( 'span', Object.assign({}, otherProps, { ref: getInputRef }),
value
)
);
} else if (customInput) {
var CustomInput = customInput;
return React.createElement( CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
var isPosAllowed = function (pos) {
// the position is allowed if the position is not masked and valid number area
return format[pos] === patternChar && formattedValue[pos] !== maskAndFormatMap[pos];
};
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
// Note: on pattern based format its denoted by patternCharacter
boundaryAry[i] = isPosAllowed(i) || isPosAllowed(i - 1);
}
// the first patternChar position is always allowed
boundaryAry[format.indexOf(patternChar)] = true;
return boundaryAry;
}
function validateProps$1(props) {
var mask = props.mask;
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("Mask " + mask + " should not contain numeric character;"));
}
}
}
function usePatternFormat(props) {
var formatProp = props.format;
var inputMode = props.inputMode; if ( inputMode === void 0 ) inputMode = 'numeric';
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
// validate props
validateProps$1(props);
var _onKeyDown = function (e) {
var key = e.key;
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if backspace is pressed after the format characters, bring it to numeric section
// if delete is pressed before the format characters, bring it to numeric section
if (key === 'Backspace' || key === 'Delete') {
// bring the cursor to closest numeric section
var index = selectionStart;
if (key === 'Backspace') {
while (index > 0 && formatProp[index - 1] !== patternChar) {
index--;
}
}
else {
var formatLn = formatProp.length;
while (index < formatLn && formatProp[index] !== patternChar) {
index++;
}
}
if (index !== selectionStart) {
setCaretPosition(el, index);
}
}
onKeyDown(e);
};
return {
inputMode: inputMode,
format: function (numStr) { return format$1(numStr, props); },
removeFormatting: function (inputValue, changeMeta) { return removeFormatting$1(inputValue, changeMeta, props); },
getCaretBoundary: function (formattedValue) { return getCaretBoundary$1(formattedValue, props); },
onKeyDown: _onKeyDown,
};
}
function PatternFormat(props) {
var mask = props.mask;
var allowEmptyFormatting = props.allowEmptyFormatting;
var formatProp = props.format;
var inputMode = props.inputMode;
var onKeyDown = props.onKeyDown;
var patternChar = props.patternChar;
var restProps = __rest(props, ["mask", "allowEmptyFormatting", "format", "inputMode", "onKeyDown", "patternChar"]);
var patternFormatProps = usePatternFormat(props);
return React.createElement(NumberFormatBase, Object.assign({}, restProps, patternFormatProps));
}
return React.createElement( 'input', Object.assign({}, inputProps, { ref: getInputRef }));
};
return NumberFormat;
}(React.Component));
NumberFormat.defaultProps = defaultProps;
export default NumberFormat;
export { NumberFormatBase, NumericFormat, PatternFormat, getCaretBoundary as getNumericCaretBoundary, getCaretBoundary$1 as getPatternCaretBoundary, format as numericFormatter, format$1 as patterFormatter, removeFormatting as removeNumericFormat, removeFormatting$1 as removePatternFormat, useNumericFormat, usePatternFormat };
/**
* react-number-format - 4.9.3
* react-number-format - 5.0.0-beta.1
* Author : Sudhanshu Yadav

@@ -9,1385 +9,1177 @@ * Copyright (c) 2016, 2022 to Sudhanshu Yadav, released under the MIT license.

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
typeof define === 'function' && define.amd ? define(['react'], factory) :
(global = global || self, global.NumberFormat = factory(global.React));
}(this, function (React) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
(global = global || self, factory(global.NumberFormat = {}, global.React));
}(this, (function (exports, React) { 'use strict';
React = React && React.hasOwnProperty('default') ? React['default'] : React;
var React__default = 'default' in React ? React['default'] : React;
//
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
// basic noop function
function noop() {}
function returnTrue() {
return true;
}
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function charIsNumber(char ) {
return !!(char || '').match(/\d/);
}
function __rest(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;
}
function isNil(val ) {
return val === null || val === undefined;
}
var SourceType;
(function (SourceType) {
SourceType["event"] = "event";
SourceType["props"] = "prop";
})(SourceType || (SourceType = {}));
function escapeRegExp(str ) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
// basic noop function
function noop() { }
function charIsNumber(char) {
return !!(char || '').match(/\d/);
}
function isNil(val) {
return val === null || val === undefined;
}
function isNanValue(val) {
return typeof val === 'number' && isNaN(val);
}
function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function getThousandsGroupRegex(thousandsGroupStyle) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
}
function applyThousandSeparator(str, thousandSeparator, thousandsGroupStyle) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator));
}
function usePersistentCallback(cb) {
var callbackRef = React.useRef(cb);
// keep the callback ref upto date
callbackRef.current = cb;
/**
* initialize a persistent callback which never changes
* through out the component lifecycle
*/
var persistentCbRef = React.useRef(function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
function getThousandsGroupRegex(thousandsGroupStyle ) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
return callbackRef.current.apply(callbackRef, args);
});
return persistentCbRef.current;
}
}
//spilt a float number into different parts beforeDecimal, afterDecimal, and negation
function splitDecimal(numStr, allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
function applyThousandSeparator(
str ,
thousandSeparator ,
thousandsGroupStyle
) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return (
str.substring(0, index) +
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator)
);
}
//spilt a float number into different parts beforeDecimal, afterDecimal, and negation
function splitDecimal(numStr , allowNegative) {
if ( allowNegative === void 0 ) allowNegative = true;
var hasNagation = numStr[0] === '-';
var addNegation = hasNagation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNagation: hasNagation,
addNegation: addNegation,
};
}
function fixLeadingZero(numStr ) {
if (!numStr) { return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative) { numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
}
/**
* limit decimal numbers to given scale
* Not used .fixedTo because that will break with big numbers
*/
function limitToScale(numStr , scale , fixedDecimalScale ) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
var hasNegation = numStr[0] === '-';
var addNegation = hasNegation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNegation: hasNegation,
addNegation: addNegation,
};
}
return str;
}
function repeat(str, count) {
return Array(count + 1).join(str);
}
function toNumericString(num) {
num += ''; // typecast number to string
// store the sign and remove it from the number.
var sign = num[0] === '-' ? '-' : '';
if (sign) { num = num.substring(1); }
// split the number into cofficient and exponent
var ref = num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent) { return sign + coefficient; }
coefficient = coefficient.replace('.', '');
function fixLeadingZero(numStr) {
if (!numStr)
{ return numStr; }
var isNegative = numStr[0] === '-';
if (isNegative)
{ numStr = numStr.substring(1, numStr.length); }
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : ''));
}
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
* limit decimal numbers to given scale
* Not used .fixedTo because that will break with big numbers
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
} else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
} else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
function limitToScale(numStr, scale, fixedDecimalScale) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
}
return sign + coefficient;
}
/**
* This method is required to round prop value to given scale.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr , scale , fixedDecimalScale ) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1) { return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNagation = ref.hasNagation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr =
afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (
(Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length)
);
function repeat(str, count) {
return Array(count + 1).join(str);
}
function toNumericString(num) {
var _num = num + ''; // typecast number to string
// store the sign and remove it from the number.
var sign = _num[0] === '-' ? '-' : '';
if (sign)
{ _num = _num.substring(1); }
// split the number into cofficient and exponent
var ref = _num.split(/[eE]/g);
var coefficient = ref[0];
var exponent = ref[1];
// covert exponent to number;
exponent = Number(exponent);
// if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent)
{ return sign + coefficient; }
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = limitToScale(
roundedDecimalParts[1] || '',
Math.min(scale, afterDecimal.length),
fixedDecimalScale
);
var negation = hasNagation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
}
/** set the caret positon in an input field **/
function setCaretPosition(el , caretPos ) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
}
else {
// else add decimal point at proper index
coefficient =
(coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
}
}
/**
Given previous value and newValue it returns the index
start - end to which values have changed.
This function makes assumption about only consecutive
characters are changed which is correct assumption for caret input.
*/
function findChangedIndex(prevValue , newValue ) {
var i = 0,
j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength) { i++; }
//check what has been changed from last
while (
prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i
) {
j++;
/**
* This method is required to round prop value to given scale.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr, scale, fixedDecimalScale) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1)
{ return numStr; }
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var ref = splitDecimal(numStr);
var beforeDecimal = ref.beforeDecimal;
var afterDecimal = ref.afterDecimal;
var hasNegation = ref.hasNegation;
var floatValue = parseFloat(("0." + (afterDecimal || '0')));
var floatValueStr = afterDecimal.length <= scale ? ("0." + afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal
.split('')
.reverse()
.reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return ((Number(roundedStr[0]) + Number(current)).toString() +
roundedStr.substring(1, roundedStr.length));
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = limitToScale(roundedDecimalParts[1] || '', scale, fixedDecimalScale);
var negation = hasNegation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return ("" + negation + intPart + decimalSeparator + decimalPart);
}
return { start: i, end: prevLength - j };
}
/*
Returns a number whose value is limited to the given range
*/
function clamp(num , min , max ) {
return Math.min(Math.max(num, min), max);
}
function getCurrentCaretPosition(el ) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
}
function addInputMode(format ) {
return (
format ||
(typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)))
);
}
//
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
var defaultProps = {
displayType: 'input',
decimalSeparator: '.',
thousandsGroupStyle: 'thousand',
fixedDecimalScale: false,
prefix: '',
suffix: '',
allowNegative: true,
allowEmptyFormatting: false,
allowLeadingZeros: false,
isNumericString: false,
type: 'text',
onValueChange: noop,
onChange: noop,
onKeyDown: noop,
onMouseUp: noop,
onFocus: noop,
onBlur: noop,
isAllowed: returnTrue,
};
var NumberFormat = /*@__PURE__*/(function (superclass) {
function NumberFormat(props ) {
superclass.call(this, props);
var defaultValue = props.defaultValue;
//validate props
this.validateProps();
var formattedValue = this.formatValueProp(defaultValue);
this.state = {
value: formattedValue,
numAsString: this.removeFormatting(formattedValue),
mounted: false,
};
this.selectionBeforeInput = {
selectionStart: 0,
selectionEnd: 0,
};
this.onChange = this.onChange.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
/** set the caret positon in an input field **/
function setCaretPosition(el, caretPos) {
el.value = el.value;
// ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
/* @ts-ignore */
if (el.createTextRange) {
/* @ts-ignore */
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
}
if ( superclass ) NumberFormat.__proto__ = superclass;
NumberFormat.prototype = Object.create( superclass && superclass.prototype );
NumberFormat.prototype.constructor = NumberFormat;
NumberFormat.prototype.componentDidMount = function componentDidMount () {
// set mounted state
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
mounted: true,
});
};
NumberFormat.prototype.componentDidUpdate = function componentDidUpdate (prevProps ) {
this.updateValueIfRequired(prevProps);
};
NumberFormat.prototype.componentWillUnmount = function componentWillUnmount () {
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
};
NumberFormat.prototype.updateValueIfRequired = function updateValueIfRequired (prevProps ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var focusedElm = ref.focusedElm;
var stateValue = state.value;
var lastNumStr = state.numAsString; if ( lastNumStr === void 0 ) lastNumStr = '';
// If only state changed no need to do any thing
if (prevProps !== props) {
//validate props
this.validateProps();
var lastValueWithNewFormat = this.formatNumString(lastNumStr);
var formattedValue = isNil(props.value) ? lastValueWithNewFormat : this.formatValueProp();
var numAsString = this.removeFormatting(formattedValue);
var floatValue = parseFloat(numAsString);
var lastFloatValue = parseFloat(lastNumStr);
if (
//while typing set state only when float value changes
((!isNaN(floatValue) || !isNaN(lastFloatValue)) && floatValue !== lastFloatValue) ||
//can also set state when float value is same and the format props changes
lastValueWithNewFormat !== stateValue ||
//set state always when not in focus and formatted value is changed
(focusedElm === null && formattedValue !== stateValue)
) {
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: focusedElm,
source: 'prop',
event: null,
});
function findChangeRange(prevValue, newValue) {
var i = 0, j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength)
{ i++; }
//check what has been changed from last
while (prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i) {
j++;
}
}
};
return {
from: { start: i, end: prevLength - j },
to: { start: i, end: newLength - j },
};
}
/*
Returns a number whose value is limited to the given range
*/
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function geInputCaretPosition(el) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
}
function addInputMode() {
return (typeof navigator !== 'undefined' &&
!(navigator.platform && /iPhone|iPod/.test(navigator.platform)));
}
function getDefaultChangeMeta(value) {
return {
from: {
start: 0,
end: 0,
},
to: {
start: 0,
end: value.length,
},
lastValue: '',
};
}
function getMaskAtIndex(mask, index) {
if ( mask === void 0 ) mask = ' ';
/** Misc methods **/
NumberFormat.prototype.getFloatString = function getFloatString (num) {
if ( num === void 0 ) num = '';
var ref = this.props;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var numRegex = this.getNumberRegex(true);
//remove negation for regex check
var hasNegation = num[0] === '-';
if (hasNegation) { num = num.replace('-', ''); }
//if decimal scale is zero remove decimal and number after decimalSeparator
if (decimalSeparator && decimalScale === 0) {
num = num.split(decimalSeparator)[0];
}
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.');
//remove extra decimals
var firstDecimalIndex = num.indexOf('.');
if (firstDecimalIndex !== -1) {
num = (num.substring(0, firstDecimalIndex)) + "." + (num
.substring(firstDecimalIndex + 1, num.length)
.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), ''));
}
//add negation back
if (hasNegation) { num = '-' + num; }
return num;
};
//returned regex assumes decimalSeparator is as per prop
NumberFormat.prototype.getNumberRegex = function getNumberRegex (g , ignoreDecimalSeparator ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var customNumerals = ref.customNumerals;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
return new RegExp(
'[0-9' +
(customNumerals ? customNumerals.join('') : '') +
']' +
(decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format
? '|' + escapeRegExp(decimalSeparator)
: ''),
g ? 'g' : undefined
);
};
NumberFormat.prototype.getSeparators = function getSeparators () {
var ref = this.props;
var decimalSeparator = ref.decimalSeparator;
var ref$1 = this.props;
var thousandSeparator = ref$1.thousandSeparator;
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
};
};
NumberFormat.prototype.getMaskAtIndex = function getMaskAtIndex (index ) {
var ref = this.props;
var mask = ref.mask; if ( mask === void 0 ) mask = ' ';
if (typeof mask === 'string') {
return mask;
}
return mask[index] || ' ';
};
NumberFormat.prototype.getValueObject = function getValueObject (formattedValue , numAsString ) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
NumberFormat.prototype.validateProps = function validateProps () {
var ref = this.props;
var mask = ref.mask;
//validate decimalSeparator and thousandSeparator
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
var thousandSeparator = ref$1.thousandSeparator;
if (decimalSeparator === thousandSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
//validate mask
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("\n Mask " + mask + " should not contain numeric character;\n "));
if (typeof mask === 'string') {
return mask;
}
}
};
/** Misc methods end **/
/** caret specific methods **/
NumberFormat.prototype.setPatchedCaretPosition = function setPatchedCaretPosition (el , caretPos , currentValue ) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
this.caretPositionTimeout = setTimeout(function () {
if (el.value === currentValue) { setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
NumberFormat.prototype.correctCaretPosition = function correctCaretPosition (value , caretPos , direction ) {
var ref = this.props;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
//if value is empty return 0
if (value === '') { return 0; }
//caret position should be between 0 and value length
caretPos = clamp(caretPos, 0, value.length);
//in case of format as number limit between prefix and suffix
if (!format) {
var hasNegation = value[0] === '-';
return clamp(caretPos, prefix.length + (hasNegation ? 1 : 0), value.length - suffix.length);
}
//in case if custom format method don't do anything
if (typeof format === 'function') { return caretPos; }
/* in case format is string find the closest # position from the caret position */
//in case the caretPos have input value on it don't do anything
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) {
return caretPos;
}
//if caretPos is just after input value don't do anything
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) {
return caretPos;
}
//find the nearest caret position
var firstHashPosition = format.indexOf('#');
var lastHashPosition = format.lastIndexOf('#');
//limit the cursor between the first # position and the last # position
caretPos = clamp(caretPos, firstHashPosition, lastHashPosition + 1);
var nextPos = format.substring(caretPos, format.length).indexOf('#');
var caretLeftBound = caretPos;
var caretRightBound = caretPos + (nextPos === -1 ? 0 : nextPos);
//get the position where the last number is present
while (
caretLeftBound > firstHashPosition &&
(format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))
) {
caretLeftBound -= 1;
}
var goToLeft =
!charIsNumber(value[caretRightBound]) ||
(direction === 'left' && caretPos !== firstHashPosition) ||
caretPos - caretLeftBound < caretRightBound - caretPos;
if (goToLeft) {
//check if number should be taken after the bound or after it
//if number preceding a valid number keep it after
return charIsNumber(value[caretLeftBound]) ? caretLeftBound + 1 : caretLeftBound;
}
return caretRightBound;
};
NumberFormat.prototype.getCaretPosition = function getCaretPosition (inputValue , formattedValue , caretPos ) {
var ref = this.props;
var format = ref.format;
var stateValue = this.state.value;
var numRegex = this.getNumberRegex(true);
var inputNumber = (inputValue.match(numRegex) || []).join('');
var formattedNumber = (formattedValue.match(numRegex) || []).join('');
var j, i;
j = 0;
for (i = 0; i < caretPos; i++) {
var currentInputChar = inputValue[i] || '';
var currentFormatChar = formattedValue[j] || '';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if (!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) {
continue;
return mask[index] || ' ';
}
function getCaretPosition(formattedValue, curValue, curCaretPos) {
var curValLn = curValue.length;
var formattedValueLn = formattedValue.length;
// create index map
var addedIndexMap = {};
var indexMap = new Array(curValLn);
for (var i = 0; i < curValLn; i++) {
indexMap[i] = -1;
for (var j = 0, jLn = formattedValueLn; j < jLn; j++) {
if (curValue[i] === formattedValue[j] && addedIndexMap[j] !== true) {
indexMap[i] = j;
addedIndexMap[j] = true;
break;
}
}
}
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (
currentInputChar === '0' &&
currentFormatChar.match(numRegex) &&
currentFormatChar !== '0' &&
inputNumber.length !== formattedNumber.length
) {
continue;
/**
* For current caret position find closest characters (left and right side)
* which are properly mapped to formatted value.
* The idea is that the new caret position will exist always in the boundary of
* that mapped index
*/
var pos = curCaretPos;
while (pos < curValLn && (indexMap[pos] === -1 || !charIsNumber(curValue[pos]))) {
pos++;
}
//we are not using currentFormatChar because j can change here
while (currentInputChar !== formattedValue[j] && j < formattedValue.length) {
j++;
// if the caret position is on last keep the endIndex as last for formatted value
var endIndex = pos === curValLn || indexMap[pos] === -1 ? formattedValueLn : indexMap[pos];
pos = curCaretPos - 1;
while (pos > 0 && (indexMap[pos] === -1 || !charIsNumber(curValue[pos])))
{ pos--; }
var startIndex = pos === -1 || indexMap[pos] === -1 ? 0 : indexMap[pos] + 1;
/**
* case where a char is added on suffix and removed from middle, example 2sq345 becoming $2,345 sq
* there is still a mapping but the order of start index and end index is changed
*/
if (startIndex > endIndex)
{ return endIndex; }
/**
* given the current caret position if it closer to startIndex
* keep the new caret position on start index or keep it closer to endIndex
*/
return curCaretPos - startIndex < endIndex - curCaretPos ? startIndex : endIndex;
}
function caretUnknownFormatBoundary(formattedValue) {
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
boundaryAry[i] = Boolean(charIsNumber(formattedValue[i]) || charIsNumber(formattedValue[i - 1]));
}
j++;
}
return boundaryAry;
}
function useInternalValues(value, defaultValue, isNumericString, format, removeFormatting, onValueChange) {
if ( onValueChange === void 0 ) onValueChange = noop;
if (typeof format === 'string' && !stateValue) {
//set it to the maximum value so it goes after the last number
j = formattedValue.length;
}
var propValues = React.useRef();
var getValues = usePersistentCallback(function (value) {
var formattedValue, numAsString;
if (isNil(value) || isNanValue(value)) {
numAsString = '';
formattedValue = '';
}
else if (typeof value === 'number' || isNumericString) {
numAsString = typeof value === 'number' ? toNumericString(value) : value;
formattedValue = format(numAsString);
}
else {
numAsString = removeFormatting(value, undefined);
formattedValue = value;
}
return { formattedValue: formattedValue, numAsString: numAsString };
});
var ref = React.useState(function () {
return getValues(defaultValue);
});
var values = ref[0];
var setValues = ref[1];
var _onValueChange = function (values, sourceInfo) {
setValues({
formattedValue: values.formattedValue,
numAsString: values.value,
});
onValueChange(values, sourceInfo);
};
React.useMemo(function () {
//if element is moved to uncontrolled mode, don't reset the value
if (!isNil(value)) {
propValues.current = getValues(value);
setValues(propValues.current);
}
else {
propValues.current = undefined;
}
}, [value, getValues]);
return [values, _onValueChange];
}
//correct caret position if its outside of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;
};
/** caret specific methods ends **/
/** methods to remove formattting **/
NumberFormat.prototype.removePrefixAndSuffix = function removePrefixAndSuffix (val ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
//remove prefix and suffix
if (!format && val) {
var isNegative = val[0] === '-';
//remove negation sign
if (isNegative) { val = val.substring(1, val.length); }
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
var suffixLastIndex = val.lastIndexOf(suffix);
val =
suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length
? val.substring(0, suffixLastIndex)
: val;
//add negation sign back
if (isNegative) { val = '-' + val; }
}
return val;
};
NumberFormat.prototype.removePatternFormatting = function removePatternFormatting (val ) {
var ref = this.props;
var format = ref.format;
var formatArray = format.split('#').filter(function (str) { return str !== ''; });
var start = 0;
var numStr = '';
for (var i = 0, ln = formatArray.length; i <= ln; i++) {
var part = formatArray[i] || '';
//if i is the last fragment take the index of end of the value
//For case like +1 (911) 911 91 91 having pattern +1 (###) ### ## ##
var index = i === ln ? val.length : val.indexOf(part, start);
/* in any case if we don't find the pattern part in the value assume the val as numeric string
This will be also in case if user has started typing, in any other case it will not be -1
unless wrong prop value is provided */
if (index === -1) {
numStr = val;
break;
} else {
numStr += val.substring(start, index);
start = index + part.length;
}
}
return (numStr.match(this.getNumberRegex(true)) || []).join('');
};
NumberFormat.prototype.removeFormatting = function removeFormatting (val ) {
var ref = this.props;
var format = ref.format;
var removeFormatting = ref.removeFormatting;
if (!val) { return val; }
if (!format) {
val = this.removePrefixAndSuffix(val);
val = this.getFloatString(val);
} else if (typeof format === 'string') {
val = this.removePatternFormatting(val);
} else if (typeof removeFormatting === 'function') {
//condition need to be handled if format method is provide,
val = removeFormatting(val);
} else {
val = (val.match(this.getNumberRegex(true)) || []).join('');
}
return val;
};
/** methods to remove formattting end **/
/*** format specific methods start ***/
/**
* Format when # based string is provided
* @param {string} numStr Numeric String
* @return {string} formatted Value
*/
NumberFormat.prototype.formatWithPattern = function formatWithPattern (numStr ) {
var ref = this.props;
var format = ref.format;
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || this.getMaskAtIndex(hashCount);
hashCount += 1;
}
}
return formattedNumberAry.join('');
};
/**
* @param {string} numStr Numeric string/floatString] It always have decimalSeparator as .
* @return {string} formatted Value
*/
NumberFormat.prototype.formatAsNumber = function formatAsNumber (numStr ) {
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var allowNegative = ref.allowNegative;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var ref$1 = this.getSeparators();
var thousandSeparator = ref$1.thousandSeparator;
var decimalSeparator = ref$1.decimalSeparator;
var hasDecimalSeparator = numStr.indexOf('.') !== -1 || (decimalScale && fixedDecimalScale);
var ref$2 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$2.beforeDecimal;
var afterDecimal = ref$2.afterDecimal;
var addNegation = ref$2.addNegation; // eslint-disable-line prefer-const
//apply decimal precision if its defined
if (decimalScale !== undefined) {
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
}
if (thousandSeparator) {
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
}
//add prefix and suffix
if (prefix) { beforeDecimal = prefix + beforeDecimal; }
if (suffix) { afterDecimal = afterDecimal + suffix; }
//restore negation sign
if (addNegation) { beforeDecimal = '-' + beforeDecimal; }
numStr = beforeDecimal + ((hasDecimalSeparator && decimalSeparator) || '') + afterDecimal;
return numStr;
};
NumberFormat.prototype.formatNumString = function formatNumString (numStr) {
if ( numStr === void 0 ) numStr = '';
var ref = this.props;
var format = ref.format;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var customNumerals = ref.customNumerals;
var formattedValue = numStr;
if (customNumerals && customNumerals.length === 10) {
var customNumeralRegex = new RegExp('[' + customNumerals.join('') + ']', 'g');
formattedValue = numStr.replace(customNumeralRegex, function (digit) { return customNumerals.indexOf(digit).toString(); }
);
}
if (numStr === '' && !allowEmptyFormatting) {
formattedValue = '';
} else if (numStr === '-' && !format) {
formattedValue = '-';
} else if (typeof format === 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format === 'function') {
formattedValue = format(formattedValue);
} else {
formattedValue = this.formatAsNumber(formattedValue);
}
return formattedValue;
};
NumberFormat.prototype.formatValueProp = function formatValueProp (defaultValue ) {
var ref = this.props;
var format = ref.format;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var ref$1 = this.props;
var value = ref$1.value;
var isNumericString = ref$1.isNumericString;
// if value is undefined or null, use defaultValue instead
value = isNil(value) ? defaultValue : value;
var isNonNumericFalsy = !value && value !== 0;
if (isNonNumericFalsy && allowEmptyFormatting) {
value = '';
}
// if value is not defined return empty string
if (isNonNumericFalsy && !allowEmptyFormatting) { return ''; }
if (typeof value === 'number') {
value = toNumericString(value);
isNumericString = true;
}
//change infinity value to empty string
if (value === 'Infinity' && isNumericString) {
value = '';
}
//round the number based on decimalScale
//format only if non formatted value is provided
if (isNumericString && !format && typeof decimalScale === 'number') {
value = roundToPrecision(value, decimalScale, fixedDecimalScale);
}
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value);
return formattedValue;
};
NumberFormat.prototype.formatNegation = function formatNegation (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var allowNegative = ref.allowNegative;
var negationRegex = new RegExp('(-)');
var doubleNegationRegex = new RegExp('(-)(.)*(-)');
// Check number has '-' value
var hasNegation = negationRegex.test(value);
// Check number has 2 or more '-' values
var removeNegation = doubleNegationRegex.test(value);
//remove negation
value = value.replace(/-/g, '');
if (hasNegation && !removeNegation && allowNegative) {
value = '-' + value;
}
return value;
};
NumberFormat.prototype.formatInput = function formatInput (value) {
if ( value === void 0 ) value = '';
var ref = this.props;
var format = ref.format;
//format negation only if we are formatting as number
if (!format) {
value = this.removePrefixAndSuffix(value);
value = this.formatNegation(value);
}
//remove formatting from number
value = this.removeFormatting(value);
return this.formatNumString(value);
};
/*** format specific methods end ***/
NumberFormat.prototype.isCharacterAFormat = function isCharacterAFormat (caretPos , value ) {
var ref = this.props;
var format = ref.format;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var ref$1 = this.getSeparators();
var decimalSeparator = ref$1.decimalSeparator;
//check within format pattern
if (typeof format === 'string' && format[caretPos] !== '#') { return true; }
//check in number format
if (
!format &&
(caretPos < prefix.length ||
caretPos >= value.length - suffix.length ||
(decimalScale && fixedDecimalScale && value[caretPos] === decimalSeparator))
) {
return true;
}
return false;
};
/**
* This will check if any formatting got removed by the delete or backspace and reset the value
* It will also work as fallback if android chome keyDown handler does not work
**/
NumberFormat.prototype.correctInputValue = function correctInputValue (caretPos , lastValue , value ) {
var this$1 = this;
var ref = this.props;
var format = ref.format;
var allowNegative = ref.allowNegative;
var prefix = ref.prefix;
var suffix = ref.suffix;
var decimalScale = ref.decimalScale;
var ref$1 = this.getSeparators();
var allowedDecimalSeparators = ref$1.allowedDecimalSeparators;
var decimalSeparator = ref$1.decimalSeparator;
var lastNumStr = this.state.numAsString || '';
var ref$2 = this.selectionBeforeInput;
var selectionStart = ref$2.selectionStart;
var selectionEnd = ref$2.selectionEnd;
var ref$3 = findChangedIndex(lastValue, value);
var start = ref$3.start;
var end = ref$3.end;
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */
if (
!format &&
start === end &&
allowedDecimalSeparators.indexOf(value[selectionStart]) !== -1
) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
return (
value.substr(0, selectionStart) + separator + value.substr(selectionStart + 1, value.length)
);
}
var leftBound = !!format ? 0 : prefix.length;
var rightBound = lastValue.length - (!!format ? 0 : suffix.length);
if (
// don't do anything if something got added
value.length > lastValue.length ||
// or if the new value is an empty string
!value.length ||
// or if nothing has changed, in which case start will be same as end
start === end ||
// or in case if whole input is selected and new value is typed
(selectionStart === 0 && selectionEnd === lastValue.length) ||
// or in case if the whole content is replaced by browser, example (autocomplete)
(start === 0 && end === lastValue.length) ||
// or if charcters between prefix and suffix is selected.
// For numeric inputs we apply the format so, prefix and suffix can be ignored
(selectionStart === leftBound && selectionEnd === rightBound)
) {
function defaultRemoveFormatting(value) {
return value.replace(/[^0-9]/g, '');
}
function defaultFormat(value) {
return value;
}
// check whether the deleted portion has a character that is part of a format
var deletedValues = lastValue.substr(start, end - start);
var formatGotDeleted = !![].concat( deletedValues ).find(function (deletedVal, idx) { return this$1.isCharacterAFormat(idx + start, lastValue); }
);
// if it has, only remove characters that are not part of the format
if (formatGotDeleted) {
var deletedValuePortion = lastValue.substr(start);
var recordIndexOfFormatCharacters = {};
var resolvedPortion = [];
[].concat( deletedValuePortion ).forEach(function (currentPortion, idx) {
if (this$1.isCharacterAFormat(idx + start, lastValue)) {
recordIndexOfFormatCharacters[idx] = currentPortion;
} else if (idx > deletedValues.length - 1) {
resolvedPortion.push(currentPortion);
}
}
function NumberFormatBase(props) {
var type = props.type; if ( type === void 0 ) type = 'text';
var displayType = props.displayType; if ( displayType === void 0 ) displayType = 'input';
var customInput = props.customInput;
var renderText = props.renderText;
var getInputRef = props.getInputRef;
var format = props.format; if ( format === void 0 ) format = defaultFormat;
var removeFormatting = props.removeFormatting; if ( removeFormatting === void 0 ) removeFormatting = defaultRemoveFormatting;
var defaultValue = props.defaultValue;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var isAllowed = props.isAllowed;
var onChange = props.onChange; if ( onChange === void 0 ) onChange = noop;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onMouseUp = props.onMouseUp; if ( onMouseUp === void 0 ) onMouseUp = noop;
var onFocus = props.onFocus; if ( onFocus === void 0 ) onFocus = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var propValue = props.value;
var getCaretBoundary = props.getCaretBoundary; if ( getCaretBoundary === void 0 ) getCaretBoundary = caretUnknownFormatBoundary;
var otherProps = __rest(props, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "removeFormatting", "defaultValue", "isNumericString", "onValueChange", "isAllowed", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value", "getCaretBoundary"]);
var ref = useInternalValues(propValue, defaultValue, isNumericString, format, removeFormatting, onValueChange);
var ref_0 = ref[0];
var formattedValue = ref_0.formattedValue;
var numAsString = ref_0.numAsString;
var onFormattedValueChange = ref[1];
var lastUpdatedValue = React.useRef();
var _onValueChange = function (values, source) {
lastUpdatedValue.current = values.formattedValue;
onFormattedValueChange(values, source);
};
// check if there is any change in the value due to props change
React.useEffect(function () {
var newFormattedValue = format(numAsString);
// if the formatted value is not synced to parent, or if the formatted value is different
if (lastUpdatedValue.current === undefined || newFormattedValue !== lastUpdatedValue.current) {
var input = focusedElm.current;
updateValue({
formattedValue: newFormattedValue,
numAsString: numAsString,
input: input,
setCaretPosition: true,
source: SourceType.props,
event: null,
});
}
});
Object.keys(recordIndexOfFormatCharacters).forEach(function (idx) {
if (resolvedPortion.length > idx) {
resolvedPortion.splice(idx, 0, recordIndexOfFormatCharacters[idx]);
} else {
resolvedPortion.push(recordIndexOfFormatCharacters[idx]);
}
var ref$1 = React.useState(false);
var mounted = ref$1[0];
var setMounted = ref$1[1];
var focusedElm = React.useRef(null);
var timeout = React.useRef({
setCaretTimeout: null,
focusTimeout: null,
});
value = lastValue.substr(0, start) + resolvedPortion.join('');
}
//for numbers check if beforeDecimal got deleted and there is nothing after decimal,
//clear all numbers in such case while keeping the - sign
if (!format) {
var numericString = this.removeFormatting(value);
var ref$4 = splitDecimal(
numericString,
allowNegative
);
var beforeDecimal = ref$4.beforeDecimal;
var afterDecimal = ref$4.afterDecimal;
var addNegation = ref$4.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1;
if (
numericString.length < lastNumStr.length &&
isBeforeDecimalPoint &&
beforeDecimal === '' &&
!parseFloat(afterDecimal)
) {
return addNegation ? '-' : '';
React.useEffect(function () {
setMounted(true);
return function () {
clearTimeout(timeout.current.setCaretTimeout);
clearTimeout(timeout.current.focusTimeout);
};
}, []);
var _format = format;
var getValueObject = function (formattedValue, numAsString) {
var floatValue = parseFloat(numAsString);
return {
formattedValue: formattedValue,
value: numAsString,
floatValue: isNaN(floatValue) ? undefined : floatValue,
};
};
var setPatchedCaretPosition = function (el, caretPos, currentValue) {
/* setting caret position within timeout of 0ms is required for mobile chrome,
otherwise browser resets the caret position after we set it
We are also setting it without timeout so that in normal browser we don't see the flickering */
setCaretPosition(el, caretPos);
timeout.current.setCaretTimeout = setTimeout(function () {
if (el.value === currentValue)
{ setCaretPosition(el, caretPos); }
}, 0);
};
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
var correctCaretPosition = function (value, caretPos, direction) {
var valLn = value.length;
// clamp caret position to [0, value.length]
caretPos = clamp(caretPos, 0, valLn);
var boundary = getCaretBoundary(value);
if (direction === 'left') {
while (caretPos >= 0 && !boundary[caretPos])
{ caretPos--; }
// if we don't find any suitable caret position on left, set it on first allowed position
if (caretPos === -1)
{ caretPos = boundary.indexOf(true); }
}
else {
while (caretPos <= valLn && !boundary[caretPos])
{ caretPos++; }
// if we don't find any suitable caret position on right, set it on last allowed position
if (caretPos > valLn)
{ caretPos = boundary.lastIndexOf(true); }
}
// if we still don't find caret position, set it at the end of value
if (caretPos === -1)
{ caretPos = valLn; }
return caretPos;
};
var getNewCaretPosition = function (inputValue, formattedValue, caretPos) {
var updatedCaretPos = getCaretPosition(formattedValue, inputValue, caretPos);
//correct caret position if its outside of editable area
updatedCaretPos = correctCaretPosition(formattedValue, updatedCaretPos);
return updatedCaretPos;
};
var updateValue = function (params) {
var newFormattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = geInputCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = newFormattedValue;
//get the caret position
caretPos = getNewCaretPosition(inputValue, newFormattedValue, currentCaretPosition);
}
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
*/
input.value = newFormattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
setPatchedCaretPosition(input, caretPos, newFormattedValue);
}
}
if (newFormattedValue !== formattedValue) {
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
_onValueChange(getValueObject(newFormattedValue, numAsString), { event: event, source: source });
}
};
var formatInputValue = function (inputValue, event, source) {
var changeRange = findChangeRange(formattedValue, inputValue);
var changeMeta = Object.assign(Object.assign({}, changeRange), { lastValue: formattedValue });
var _numAsString = removeFormatting(inputValue, changeMeta);
var _formattedValue = _format(_numAsString);
if (isAllowed && !isAllowed(getValueObject(_formattedValue, _numAsString))) {
return false;
}
updateValue({
formattedValue: _formattedValue,
numAsString: _numAsString,
inputValue: inputValue,
event: event,
source: source,
setCaretPosition: true,
input: event.target,
});
};
var _onChange = function (e) {
var el = e.target;
var inputValue = el.value;
var changed = formatInputValue(inputValue, e, SourceType.event);
if (changed)
{ onChange(e); }
};
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = Math.max(selectionStart - 1, 0);
}
else if (key === 'ArrowRight') {
expectedCaretPosition = Math.min(selectionStart + 1, value.length);
}
else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
// also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, direction);
}
else if (key === 'Delete' && !charIsNumber(value[expectedCaretPosition])) {
// in case of delete go to closest caret boundary on the right side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'right');
}
else if (key === 'Backspace' && !charIsNumber(value[expectedCaretPosition])) {
// in case of backspace go to closest caret boundary on the left side
newCaretPosition = correctCaretPosition(value, expectedCaretPosition, 'left');
}
if (newCaretPosition !== expectedCaretPosition) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
/* @ts-ignore */
if (e.isUnitTestRun) {
setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
var _onMouseUp = function (e) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
setPatchedCaretPosition(el, caretPosition, value);
}
}
onMouseUp(e);
};
var _onFocus = function (e) {
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
var el = e.target;
focusedElm.current = el;
timeout.current.focusTimeout = setTimeout(function () {
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)) {
setPatchedCaretPosition(el, caretPosition, value);
}
onFocus(e);
}, 0);
};
var _onBlur = function (e) {
focusedElm.current = null;
clearTimeout(timeout.current.focusTimeout);
clearTimeout(timeout.current.setCaretTimeout);
onBlur(e);
};
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode() ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: formattedValue,
onChange: _onChange,
onKeyDown: _onKeyDown,
onMouseUp: _onMouseUp,
onFocus: _onFocus,
onBlur: _onBlur,
});
if (displayType === 'text') {
return renderText ? (React__default.createElement(React__default.Fragment, null, renderText(formattedValue, otherProps) || null)) : (React__default.createElement("span", Object.assign({}, otherProps, { ref: getInputRef }), formattedValue));
}
}
else if (customInput) {
var CustomInput = customInput;
/* @ts-ignore */
return React__default.createElement(CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
}
return React__default.createElement("input", Object.assign({}, inputProps, { ref: getInputRef }));
}
return value;
};
/** Update value and caret position */
NumberFormat.prototype.updateValue = function updateValue (params
) {
var formattedValue = params.formattedValue;
var input = params.input;
var setCaretPosition = params.setCaretPosition; if ( setCaretPosition === void 0 ) setCaretPosition = true;
var source = params.source;
var event = params.event;
var numAsString = params.numAsString;
var caretPos = params.caretPos;
var ref = this.props;
var onValueChange = ref.onValueChange;
var ref$1 = this.state;
var lastValue = ref$1.value;
if (input) {
//calculate caret position if not defined
if (caretPos === undefined && setCaretPosition) {
var inputValue = params.inputValue || input.value;
var currentCaretPosition = getCurrentCaretPosition(input);
/**
* set the value imperatively, this is required for IE fix
* This is also required as if new caret position is beyond the previous value.
* Caret position will not be set correctly
*/
input.value = formattedValue;
//get the caret position
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
function format(numStr, props) {
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var thousandsGroupStyle = props.thousandsGroupStyle; if ( thousandsGroupStyle === void 0 ) thousandsGroupStyle = 'thousand';
// don't apply formatting on empty string or '-'
if (numStr === '' || numStr === '-') {
return numStr;
}
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
/**
* set the value imperatively, as we set the caret position as well imperatively.
* This is to keep value and caret position in sync
* Keep the decimal separator
* when decimalScale is not defined or non zero and the numStr has decimal in it
* Or if decimalScale is > 0 and fixeDecimalScale is true (even if numStr has no decimal)
*/
input.value = formattedValue;
//set caret position, and value imperatively when element is provided
if (setCaretPosition) {
//set caret position
this.setPatchedCaretPosition(input, caretPos, formattedValue);
var hasDecimalSeparator = (decimalScale !== 0 && numStr.indexOf('.') !== -1) || (decimalScale && fixedDecimalScale);
var ref$1 = splitDecimal(numStr, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//apply decimal precision if its defined
if (decimalScale !== undefined) {
afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale);
}
}
//calculate numeric string if not passed
if (numAsString === undefined) {
numAsString = this.removeFormatting(formattedValue);
}
//update state if value is changed
if (formattedValue !== lastValue) {
this.setState({ value: formattedValue, numAsString: numAsString });
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287
onValueChange(this.getValueObject(formattedValue, numAsString), { event: event, source: source });
}
};
NumberFormat.prototype.onChange = function onChange (e ) {
var el = e.target;
var inputValue = el.value;
var ref = this;
var state = ref.state;
var props = ref.props;
var isAllowed = props.isAllowed;
var lastValue = state.value || '';
var currentCaretPosition = getCurrentCaretPosition(el);
inputValue = this.correctInputValue(currentCaretPosition, lastValue, inputValue);
var formattedValue = this.formatInput(inputValue) || '';
var numAsString = this.removeFormatting(formattedValue);
var valueObj = this.getValueObject(formattedValue, numAsString);
var isChangeAllowed = isAllowed(valueObj);
if (!isChangeAllowed) {
formattedValue = lastValue;
}
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
inputValue: inputValue,
input: el,
event: e,
source: 'event',
});
if (isChangeAllowed) {
props.onChange(e);
}
};
NumberFormat.prototype.onBlur = function onBlur (e ) {
var ref = this;
var props = ref.props;
var state = ref.state;
var format = props.format;
var onBlur = props.onBlur;
var allowLeadingZeros = props.allowLeadingZeros;
var numAsString = state.numAsString;
var lastValue = state.value;
this.focusedElm = null;
clearTimeout(this.focusTimeout);
clearTimeout(this.caretPositionTimeout);
if (!format) {
// if the numAsString is not a valid number reset it to empty
if (isNaN(parseFloat(numAsString))) {
numAsString = '';
if (thousandSeparator) {
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle);
}
if (!allowLeadingZeros) {
numAsString = fixLeadingZero(numAsString);
//add prefix and suffix when there is a number present
if (prefix)
{ beforeDecimal = prefix + beforeDecimal; }
if (suffix)
{ afterDecimal = afterDecimal + suffix; }
//restore negation sign
if (addNegation)
{ beforeDecimal = '-' + beforeDecimal; }
numStr = beforeDecimal + ((hasDecimalSeparator && decimalSeparator) || '') + afterDecimal;
return numStr;
}
function getSeparators(props) {
var decimalSeparator = props.decimalSeparator; if ( decimalSeparator === void 0 ) decimalSeparator = '.';
var thousandSeparator = props.thousandSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
if (!allowedDecimalSeparators) {
allowedDecimalSeparators = [decimalSeparator, '.'];
}
return {
decimalSeparator: decimalSeparator,
thousandSeparator: thousandSeparator,
allowedDecimalSeparators: allowedDecimalSeparators,
};
}
function handleNegation(value, allowNegative) {
if ( value === void 0 ) value = '';
var formattedValue = this.formatNumString(numAsString);
//change the state
if (formattedValue !== lastValue) {
// the event needs to be persisted because its properties can be accessed in an asynchronous way
this.updateValue({
formattedValue: formattedValue,
numAsString: numAsString,
input: e.target,
setCaretPosition: false,
event: e,
source: 'event',
});
onBlur(e);
return;
var negationRegex = new RegExp('(-)');
var doubleNegationRegex = new RegExp('(-)(.)*(-)');
// Check number has '-' value
var hasNegation = negationRegex.test(value);
// Check number has 2 or more '-' values
var removeNegation = doubleNegationRegex.test(value);
//remove negation
value = value.replace(/-/g, '');
if (hasNegation && !removeNegation && allowNegative) {
value = '-' + value;
}
}
onBlur(e);
};
return value;
}
function getNumberRegex(decimalSeparator, decimalScale, global) {
return new RegExp(("(^-)|[0-9]|" + (escapeRegExp(decimalSeparator))), global ? 'g' : undefined);
}
function removeFormatting(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
NumberFormat.prototype.onKeyDown = function onKeyDown (e ) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var expectedCaretPosition;
var ref = this.props;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var format = ref.format;
var onKeyDown = ref.onKeyDown;
var ignoreDecimalSeparator = decimalScale !== undefined && fixedDecimalScale;
var numRegex = this.getNumberRegex(false, ignoreDecimalSeparator);
var negativeRegex = new RegExp('-');
var isPatternFormat = typeof format === 'string';
this.selectionBeforeInput = {
selectionStart: selectionStart,
selectionEnd: selectionEnd,
};
//Handle backspace and delete against non numerical/decimal characters or arrow keys
if (key === 'ArrowLeft' || key === 'Backspace') {
expectedCaretPosition = selectionStart - 1;
} else if (key === 'ArrowRight') {
expectedCaretPosition = selectionStart + 1;
} else if (key === 'Delete') {
expectedCaretPosition = selectionStart;
}
//if expectedCaretPosition is not set it means we don't want to Handle keyDown
//also if multiple characters are selected don't handle
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
var newCaretPosition = expectedCaretPosition;
var leftBound = isPatternFormat ? format.indexOf('#') : prefix.length;
var rightBound = isPatternFormat ? format.lastIndexOf('#') + 1 : value.length - suffix.length;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
var direction = key === 'ArrowLeft' ? 'left' : 'right';
newCaretPosition = this.correctCaretPosition(value, expectedCaretPosition, direction);
} else if (
key === 'Delete' &&
!numRegex.test(value[expectedCaretPosition]) &&
!negativeRegex.test(value[expectedCaretPosition])
) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < rightBound) {
newCaretPosition++;
var allowNegative = props.allowNegative; if ( allowNegative === void 0 ) allowNegative = true;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var decimalScale = props.decimalScale;
var from = changeMeta.from;
var to = changeMeta.to;
var start = to.start;
var end = to.end;
var ref = getSeparators(props);
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var decimalSeparator = ref.decimalSeparator;
var isBeforeDecimalSeparator = value[end] === decimalSeparator;
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */
if (end - start === 1 && allowedDecimalSeparators.indexOf(value[start]) !== -1) {
var separator = decimalScale === 0 ? '' : decimalSeparator;
value = value.substring(0, start) + separator + value.substring(start + 1, value.length);
}
} else if (key === 'Backspace' && !numRegex.test(value[expectedCaretPosition])) {
/* NOTE: This is special case when backspace is pressed on a
negative value while the cursor position is after prefix. We can't handle it on onChange because
we will not have any information of keyPress
*/
if (selectionStart <= leftBound + 1 && value[0] === '-' && typeof format === 'undefined') {
var newValue = value.substring(1);
this.updateValue({
formattedValue: newValue,
caretPos: newCaretPosition,
input: el,
event: e,
source: 'event',
});
} else if (!negativeRegex.test(value[expectedCaretPosition])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound) {
newCaretPosition--;
}
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left');
var hasNegation = false;
/**
* if prefix starts with - the number hast to have two - at the start
* if suffix starts with - and the value length is same as suffix length, then the - sign is from the suffix
* In other cases, if the value starts with - then it is a negation
*/
if (prefix.startsWith('-'))
{ hasNegation = value.startsWith('--'); }
else if (suffix.startsWith('-') && value.length === suffix.length)
{ hasNegation = false; }
else if (value[0] === '-')
{ hasNegation = true; }
// remove negation from start to simplify prefix logic as negation comes before prefix
if (hasNegation) {
value = value.substring(1);
// account for the removal of the negation for start and end index
start -= 1;
end -= 1;
}
}
/**
* remove prefix
* Remove whole prefix part if its present on the value
* If the prefix is partially deleted (in which case change start index will be less the prefix length)
* Remove only partial part of prefix.
*/
var startIndex = 0;
if (value.startsWith(prefix))
{ startIndex += prefix.length; }
else if (start < prefix.length)
{ startIndex = start; }
value = value.substring(startIndex);
// account for deleted prefix for end index
end -= startIndex;
/**
* Remove suffix
* Remove whole suffix part if its present on the value
* If the suffix is partially deleted (in which case change end index will be greater than the suffixStartIndex)
* remove the partial part of suffix
*/
var endIndex = value.length;
var suffixStartIndex = value.length - suffix.length;
if (value.endsWith(suffix))
{ endIndex = suffixStartIndex; }
else if (end > value.length - suffix.length)
{ endIndex = end; }
value = value.substring(0, endIndex);
// add the negation back and handle for double negation
value = handleNegation(hasNegation ? ("-" + value) : value, allowNegative);
// remove non numeric characters
value = (value.match(getNumberRegex(decimalSeparator, decimalScale, true)) || []).join('');
// replace the decimalSeparator with ., and only keep the first separator, ignore following ones
var firstIndex = value.indexOf(decimalSeparator);
value = value.replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), function (match, index) {
return index === firstIndex ? '.' : '';
});
//check if beforeDecimal got deleted and there is nothing after decimal,
//clear all numbers in such case while keeping the - sign
var ref$1 = splitDecimal(value, allowNegative);
var beforeDecimal = ref$1.beforeDecimal;
var afterDecimal = ref$1.afterDecimal;
var addNegation = ref$1.addNegation; // eslint-disable-line prefer-const
//clear only if something got deleted before decimal (cursor is before decimal)
if (to.end - to.start < from.end - from.start &&
beforeDecimal === '' &&
isBeforeDecimalSeparator &&
!parseFloat(afterDecimal)) {
value = addNegation ? '-' : '';
}
return value;
}
function getCaretBoundary(formattedValue, props) {
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var suffix = props.suffix; if ( suffix === void 0 ) suffix = '';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hasNegation = formattedValue[0] === '-';
// fill for prefix and negation
boundaryAry.fill(false, 0, prefix.length + (hasNegation ? 1 : 0));
// fill for suffix
var valLn = formattedValue.length;
boundaryAry.fill(false, valLn - suffix.length + 1, valLn + 1);
return boundaryAry;
}
function validateProps(props) {
var ref = getSeparators(props);
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
if (thousandSeparator === decimalSeparator) {
throw new Error(("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: " + thousandSeparator + " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: " + decimalSeparator + " (default value for decimalSeparator is .)\n "));
}
}
function useNumericFormat(props) {
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var onBlur = props.onBlur; if ( onBlur === void 0 ) onBlur = noop;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
// validate props
validateProps(props);
var _format = function (numStr) { return format(numStr, props); };
var _removeFormatting = function (inputValue, changeMeta) { return removeFormatting(inputValue, changeMeta, props); };
var _isNumericString = isNumericString;
if (!isNil(value)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof value === 'number';
}
else if (!isNil(defaultValue)) {
_isNumericString = isNumericString !== null && isNumericString !== void 0 ? isNumericString : typeof defaultValue === 'number';
}
var roundIncomingValueToPrecision = function (value) {
if (isNil(value) || isNanValue(value))
{ return value; }
if (typeof value === 'number') {
value = toNumericString(value);
}
/**
* only round numeric or float string values coming through props,
* we don't need to do it for onChange events, as we want to prevent typing there
*/
if (_isNumericString && typeof decimalScale === 'number') {
return roundToPrecision(value, decimalScale, fixedDecimalScale);
}
return value;
};
var ref = useInternalValues(roundIncomingValueToPrecision(value), roundIncomingValueToPrecision(defaultValue), _isNumericString, _format, _removeFormatting, onValueChange);
var ref_0 = ref[0];
var numAsString = ref_0.numAsString;
var formattedValue = ref_0.formattedValue;
var _onValueChange = ref[1];
var _onKeyDown = function (e) {
var el = e.target;
var key = e.key;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if user hits backspace, while the cursor is before prefix, and the input has negation, remove the negation
if (key === 'Backspace' && value[0] === '-' && selectionStart === prefix.length + 1) {
// bring the cursor to after negation
setCaretPosition(el, 1);
}
// don't allow user to delete decimal separator when decimalScale and fixedDecimalScale is set
var ref = getSeparators(props);
var decimalSeparator = ref.decimalSeparator;
if (key === 'Backspace' &&
value[selectionStart - 1] === decimalSeparator &&
decimalScale &&
fixedDecimalScale) {
setCaretPosition(el, selectionStart - 1);
e.preventDefault();
}
// move cursor when delete or backspace is pressed before/after thousand separator
if (key === 'Backspace' && value[selectionStart - 1] === thousandSeparator) {
setCaretPosition(el, selectionStart - 1);
}
if (key === 'Delete' && value[selectionStart] === thousandSeparator) {
setCaretPosition(el, selectionStart + 1);
}
onKeyDown(e);
};
var _onBlur = function (e) {
var _value = numAsString;
// if there no no numeric value, clear the input
if (!_value.match(/\d/g)) {
_value = '';
}
// clear leading 0s
if (!allowLeadingZeros) {
_value = fixLeadingZero(_value);
}
// apply fixedDecimalScale on blur event
if (fixedDecimalScale && decimalScale) {
_value = roundToPrecision(_value, decimalScale, fixedDecimalScale);
}
if (_value !== numAsString) {
var formattedValue = format(_value, props);
_onValueChange({
formattedValue: formattedValue,
value: _value,
floatValue: parseFloat(_value),
}, {
event: e,
source: SourceType.event,
});
}
onBlur(e);
};
return {
value: formattedValue,
isNumericString: false,
onValueChange: _onValueChange,
format: _format,
removeFormatting: _removeFormatting,
getCaretBoundary: function (formattedValue) { return getCaretBoundary(formattedValue, props); },
onKeyDown: _onKeyDown,
onBlur: _onBlur,
};
}
function NumericFormat(props) {
var decimalSeparator = props.decimalSeparator;
var allowedDecimalSeparators = props.allowedDecimalSeparators;
var thousandsGroupStyle = props.thousandsGroupStyle;
var suffix = props.suffix;
var allowNegative = props.allowNegative;
var allowLeadingZeros = props.allowLeadingZeros;
var onKeyDown = props.onKeyDown;
var onBlur = props.onBlur;
var thousandSeparator = props.thousandSeparator;
var decimalScale = props.decimalScale;
var fixedDecimalScale = props.fixedDecimalScale;
var prefix = props.prefix; if ( prefix === void 0 ) prefix = '';
var defaultValue = props.defaultValue;
var value = props.value;
var isNumericString = props.isNumericString;
var onValueChange = props.onValueChange;
var restProps = __rest(props, ["decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "suffix", "allowNegative", "allowLeadingZeros", "onKeyDown", "onBlur", "thousandSeparator", "decimalScale", "fixedDecimalScale", "prefix", "defaultValue", "value", "isNumericString", "onValueChange"]);
var numericFormatProps = useNumericFormat(props);
return React__default.createElement(NumberFormatBase, Object.assign({}, restProps, numericFormatProps));
}
if (
newCaretPosition !== expectedCaretPosition ||
expectedCaretPosition < leftBound ||
expectedCaretPosition > rightBound
) {
e.preventDefault();
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
/* NOTE: this is just required for unit test as we need to get the newCaretPosition,
Remove this when you find different solution */
if (e.isUnitTestRun) {
this.setPatchedCaretPosition(el, newCaretPosition, value);
}
onKeyDown(e);
};
/** required to handle the caret position when click anywhere within the input **/
NumberFormat.prototype.onMouseUp = function onMouseUp (e ) {
var el = e.target;
/**
* NOTE: we have to give default value for value as in case when custom input is provided
* value can come as undefined when nothing is provided on value prop.
*/
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
if (selectionStart === selectionEnd) {
var caretPosition = this.correctCaretPosition(value, selectionStart);
if (caretPosition !== selectionStart) {
this.setPatchedCaretPosition(el, caretPosition, value);
function format$1(numStr, props) {
var format = props.format;
var allowEmptyFormatting = props.allowEmptyFormatting;
var mask = props.mask;
if (numStr === '' && !allowEmptyFormatting)
{ return ''; }
var hashCount = 0;
var formattedNumberAry = format.split('');
for (var i = 0, ln = format.length; i < ln; i++) {
if (format[i] === '#') {
formattedNumberAry[i] = numStr[hashCount] || getMaskAtIndex(mask, hashCount);
hashCount += 1;
}
}
}
return formattedNumberAry.join('');
}
function removeFormatting$1(value, changeMeta, props) {
if ( changeMeta === void 0 ) changeMeta = getDefaultChangeMeta(value);
this.props.onMouseUp(e);
};
NumberFormat.prototype.onFocus = function onFocus (e ) {
var this$1 = this;
// Workaround Chrome and Safari bug https://bugs.chromium.org/p/chromium/issues/detail?id=779328
// (onFocus event target selectionStart is always 0 before setTimeout)
e.persist();
this.focusedElm = e.target;
this.focusTimeout = setTimeout(function () {
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
var value = el.value; if ( value === void 0 ) value = '';
var caretPosition = this$1.correctCaretPosition(value, selectionStart);
//setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field)
if (
caretPosition !== selectionStart &&
!(selectionStart === 0 && selectionEnd === value.length)
) {
this$1.setPatchedCaretPosition(el, caretPosition, value);
var format = props.format;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var from = changeMeta.from;
var to = changeMeta.to;
var lastValue = changeMeta.lastValue; if ( lastValue === void 0 ) lastValue = '';
var isNumericSlot = function (caretPos) { return format[caretPos] === patternChar; };
var removeFormatChar = function (string, startIndex) {
var str = '';
for (var i = 0; i < string.length; i++) {
if (isNumericSlot(startIndex + i)) {
str += string[i];
}
}
return str;
};
var extractNumbers = function (str) { return str.replace(/[^0-9]/g, ''); };
// if format doesn't have any number, remove all the non numeric characters
if (!format.match(/\d/)) {
return extractNumbers(value);
}
/**
* if user paste the whole formatted text in an empty input, check if matches to the pattern
* and remove the format characters, if there is a mismatch on the pattern, do plane number extract
*/
if (lastValue === '' && value.length === format.length) {
var str = '';
for (var i = 0; i < value.length; i++) {
if (isNumericSlot(i)) {
str += value[i];
}
else if (value[i] !== format[i]) {
// if there is a mismatch on the pattern, do plane number extract
return extractNumbers(value);
}
}
return str;
}
/**
* For partial change,
* where ever there is a change on the input, we can break the number in three parts
* 1st: left part which is unchanged
* 2nd: middle part which is changed
* 3rd: right part which is unchanged
*
* The first and third section will be same as last value, only the middle part will change
* We can consider on the change part all the new characters are non format characters.
* And on the first and last section it can have partial format characters.
*
* We pick first and last section from the lastValue (as that has 1-1 mapping with format)
* and middle one from the update value.
*/
var firstSection = lastValue.substring(0, from.start);
var middleSection = value.substring(to.start, to.end);
var lastSection = lastValue.substring(from.end);
return ("" + (removeFormatChar(firstSection, 0)) + (extractNumbers(middleSection)) + (removeFormatChar(lastSection, from.end)));
}
function getCaretBoundary$1(formattedValue, props) {
var format = props.format;
var mask = props.mask;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
var boundaryAry = Array.from({ length: formattedValue.length + 1 }).map(function () { return true; });
var hashCount = 0;
var maskAndFormatMap = format.split('').map(function (char) {
if (char === patternChar) {
hashCount++;
return getMaskAtIndex(mask, hashCount - 1);
}
return undefined;
});
var isPosAllowed = function (pos) {
// the position is allowed if the position is not masked and valid number area
return format[pos] === patternChar && formattedValue[pos] !== maskAndFormatMap[pos];
};
for (var i = 0, ln = boundaryAry.length; i < ln; i++) {
// consider caret to be in boundary if it is before or after numeric value
// Note: on pattern based format its denoted by patternCharacter
boundaryAry[i] = isPosAllowed(i) || isPosAllowed(i - 1);
}
// the first patternChar position is always allowed
boundaryAry[format.indexOf(patternChar)] = true;
return boundaryAry;
}
function validateProps$1(props) {
var mask = props.mask;
if (mask) {
var maskAsStr = mask === 'string' ? mask : mask.toString();
if (maskAsStr.match(/\d/g)) {
throw new Error(("Mask " + mask + " should not contain numeric character;"));
}
}
}
function usePatternFormat(props) {
var formatProp = props.format;
var inputMode = props.inputMode; if ( inputMode === void 0 ) inputMode = 'numeric';
var onKeyDown = props.onKeyDown; if ( onKeyDown === void 0 ) onKeyDown = noop;
var patternChar = props.patternChar; if ( patternChar === void 0 ) patternChar = '#';
// validate props
validateProps$1(props);
var _onKeyDown = function (e) {
var key = e.key;
var el = e.target;
var selectionStart = el.selectionStart;
var selectionEnd = el.selectionEnd;
// if multiple characters are selected and user hits backspace, no need to handle anything manually
if (selectionStart !== selectionEnd) {
onKeyDown(e);
return;
}
// if backspace is pressed after the format characters, bring it to numeric section
// if delete is pressed before the format characters, bring it to numeric section
if (key === 'Backspace' || key === 'Delete') {
// bring the cursor to closest numeric section
var index = selectionStart;
if (key === 'Backspace') {
while (index > 0 && formatProp[index - 1] !== patternChar) {
index--;
}
}
else {
var formatLn = formatProp.length;
while (index < formatLn && formatProp[index] !== patternChar) {
index++;
}
}
if (index !== selectionStart) {
setCaretPosition(el, index);
}
}
onKeyDown(e);
};
return {
inputMode: inputMode,
format: function (numStr) { return format$1(numStr, props); },
removeFormatting: function (inputValue, changeMeta) { return removeFormatting$1(inputValue, changeMeta, props); },
getCaretBoundary: function (formattedValue) { return getCaretBoundary$1(formattedValue, props); },
onKeyDown: _onKeyDown,
};
}
function PatternFormat(props) {
var mask = props.mask;
var allowEmptyFormatting = props.allowEmptyFormatting;
var formatProp = props.format;
var inputMode = props.inputMode;
var onKeyDown = props.onKeyDown;
var patternChar = props.patternChar;
var restProps = __rest(props, ["mask", "allowEmptyFormatting", "format", "inputMode", "onKeyDown", "patternChar"]);
var patternFormatProps = usePatternFormat(props);
return React__default.createElement(NumberFormatBase, Object.assign({}, restProps, patternFormatProps));
}
this$1.props.onFocus(e);
}, 0);
};
exports.NumberFormatBase = NumberFormatBase;
exports.NumericFormat = NumericFormat;
exports.PatternFormat = PatternFormat;
exports.getNumericCaretBoundary = getCaretBoundary;
exports.getPatternCaretBoundary = getCaretBoundary$1;
exports.numericFormatter = format;
exports.patterFormatter = format$1;
exports.removeNumericFormat = removeFormatting;
exports.removePatternFormat = removeFormatting$1;
exports.useNumericFormat = useNumericFormat;
exports.usePatternFormat = usePatternFormat;
NumberFormat.prototype.render = function render () {
var ref = this.props;
var type = ref.type;
var displayType = ref.displayType;
var customInput = ref.customInput;
var renderText = ref.renderText;
var getInputRef = ref.getInputRef;
var format = ref.format;
var thousandSeparator = ref.thousandSeparator;
var decimalSeparator = ref.decimalSeparator;
var allowedDecimalSeparators = ref.allowedDecimalSeparators;
var thousandsGroupStyle = ref.thousandsGroupStyle;
var decimalScale = ref.decimalScale;
var fixedDecimalScale = ref.fixedDecimalScale;
var prefix = ref.prefix;
var suffix = ref.suffix;
var removeFormatting = ref.removeFormatting;
var mask = ref.mask;
var defaultValue = ref.defaultValue;
var isNumericString = ref.isNumericString;
var allowNegative = ref.allowNegative;
var allowEmptyFormatting = ref.allowEmptyFormatting;
var allowLeadingZeros = ref.allowLeadingZeros;
var onValueChange = ref.onValueChange;
var isAllowed = ref.isAllowed;
var customNumerals = ref.customNumerals;
var onChange = ref.onChange;
var onKeyDown = ref.onKeyDown;
var onMouseUp = ref.onMouseUp;
var onFocus = ref.onFocus;
var onBlur = ref.onBlur;
var propValue = ref.value;
var rest = objectWithoutProperties( ref, ["type", "displayType", "customInput", "renderText", "getInputRef", "format", "thousandSeparator", "decimalSeparator", "allowedDecimalSeparators", "thousandsGroupStyle", "decimalScale", "fixedDecimalScale", "prefix", "suffix", "removeFormatting", "mask", "defaultValue", "isNumericString", "allowNegative", "allowEmptyFormatting", "allowLeadingZeros", "onValueChange", "isAllowed", "customNumerals", "onChange", "onKeyDown", "onMouseUp", "onFocus", "onBlur", "value"] );
var otherProps = rest;
var ref$1 = this.state;
var value = ref$1.value;
var mounted = ref$1.mounted;
Object.defineProperty(exports, '__esModule', { value: true });
// add input mode on element based on format prop and device once the component is mounted
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined;
var inputProps = Object.assign({ inputMode: inputMode }, otherProps, {
type: type,
value: value,
onChange: this.onChange,
onKeyDown: this.onKeyDown,
onMouseUp: this.onMouseUp,
onFocus: this.onFocus,
onBlur: this.onBlur,
});
if (displayType === 'text') {
return renderText ? (
renderText(value, otherProps) || null
) : (
React.createElement( 'span', Object.assign({}, otherProps, { ref: getInputRef }),
value
)
);
} else if (customInput) {
var CustomInput = customInput;
return React.createElement( CustomInput, Object.assign({}, inputProps, { ref: getInputRef }));
}
return React.createElement( 'input', Object.assign({}, inputProps, { ref: getInputRef }));
};
return NumberFormat;
}(React.Component));
NumberFormat.defaultProps = defaultProps;
return NumberFormat;
}));
})));

@@ -1,1 +0,1 @@

!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):(t=t||self).NumberFormat=e(t.React)}(this,function(h){"use strict";function t(){}function f(t){return!!(t||"").match(/\d/)}function c(t){return null==t}function s(t){return t.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&")}function j(t,e){void 0===e&&(e=!0);var r="-"===t[0],o=r&&e,n=(t=t.replace("-","")).split(".");return{beforeDecimal:n[0],afterDecimal:n[1]||"",hasNagation:r,addNegation:o}}function d(t,e,r){for(var o="",n=r?"0":"",a=0;a<=e-1;a++)o+=t[a]||n;return o}function p(t,e){return Array(e+1).join(t)}function n(t,e){if(t.value=t.value,null!==t){if(t.createTextRange){var r=t.createTextRange();return r.move("character",e),r.select(),!0}return t.selectionStart||0===t.selectionStart?(t.focus(),t.setSelectionRange(e,e),!0):(t.focus(),!1)}}function m(t,e,r){return Math.min(Math.max(t,e),r)}function g(t){return Math.max(t.selectionStart,t.selectionEnd)}var e={displayType:"input",decimalSeparator:".",thousandsGroupStyle:"thousand",fixedDecimalScale:!1,prefix:"",suffix:"",allowNegative:!0,allowEmptyFormatting:!1,allowLeadingZeros:!1,isNumericString:!1,type:"text",onValueChange:t,onChange:t,onKeyDown:t,onMouseUp:t,onFocus:t,onBlur:t,isAllowed:function(){return!0}},r=function(o){function t(t){o.call(this,t);var e=t.defaultValue;this.validateProps();var r=this.formatValueProp(e);this.state={value:r,numAsString:this.removeFormatting(r),mounted:!1},this.selectionBeforeInput={selectionStart:0,selectionEnd:0},this.onChange=this.onChange.bind(this),this.onKeyDown=this.onKeyDown.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onFocus=this.onFocus.bind(this),this.onBlur=this.onBlur.bind(this)}return o&&(t.__proto__=o),((t.prototype=Object.create(o&&o.prototype)).constructor=t).prototype.componentDidMount=function(){this.setState({mounted:!0})},t.prototype.componentDidUpdate=function(t){this.updateValueIfRequired(t)},t.prototype.componentWillUnmount=function(){clearTimeout(this.focusTimeout),clearTimeout(this.caretPositionTimeout)},t.prototype.updateValueIfRequired=function(t){var e=this.props,r=this.state,o=this.focusedElm,n=r.value,a=r.numAsString;if(void 0===a&&(a=""),t!==e){this.validateProps();var i=this.formatNumString(a),s=c(e.value)?i:this.formatValueProp(),u=this.removeFormatting(s),l=parseFloat(u),p=parseFloat(a);(isNaN(l)&&isNaN(p)||l===p)&&i===n&&(null!==o||s===n)||this.updateValue({formattedValue:s,numAsString:u,input:o,source:"prop",event:null})}},t.prototype.getFloatString=function(t){void 0===t&&(t="");var e=this.props.decimalScale,r=this.getSeparators().decimalSeparator,o=this.getNumberRegex(!0),n="-"===t[0];n&&(t=t.replace("-","")),r&&0===e&&(t=t.split(r)[0]);var a=(t=(t.match(o)||[]).join("").replace(r,".")).indexOf(".");return-1!==a&&(t=t.substring(0,a)+"."+t.substring(a+1,t.length).replace(new RegExp(s(r),"g"),"")),n&&(t="-"+t),t},t.prototype.getNumberRegex=function(t,e){var r=this.props,o=r.format,n=r.decimalScale,a=r.customNumerals,i=this.getSeparators().decimalSeparator;return new RegExp("[0-9"+(a?a.join(""):"")+"]"+(!i||0===n||e||o?"":"|"+s(i)),t?"g":void 0)},t.prototype.getSeparators=function(){var t=this.props.decimalSeparator,e=this.props,r=e.thousandSeparator,o=e.allowedDecimalSeparators;return!0===r&&(r=","),{decimalSeparator:t,thousandSeparator:r,allowedDecimalSeparators:o=o||[t,"."]}},t.prototype.getMaskAtIndex=function(t){var e=this.props.mask;return void 0===e&&(e=" "),"string"==typeof e?e:e[t]||" "},t.prototype.getValueObject=function(t,e){var r=parseFloat(e);return{formattedValue:t,value:e,floatValue:isNaN(r)?void 0:r}},t.prototype.validateProps=function(){var t=this.props.mask,e=this.getSeparators(),r=e.decimalSeparator,o=e.thousandSeparator;if(r===o)throw new Error("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: "+o+' (thousandSeparator = {true} is same as thousandSeparator = ",")\n decimalSeparator: '+r+" (default value for decimalSeparator is .)\n ");if(t&&("string"===t?t:t.toString()).match(/\d/g))throw new Error("\n Mask "+t+" should not contain numeric character;\n ")},t.prototype.setPatchedCaretPosition=function(t,e,r){n(t,e),this.caretPositionTimeout=setTimeout(function(){t.value===r&&n(t,e)},0)},t.prototype.correctCaretPosition=function(t,e,r){var o=this.props,n=o.prefix,a=o.suffix,i=o.format;if(""===t)return 0;if(e=m(e,0,t.length),!i){var s="-"===t[0];return m(e,n.length+(s?1:0),t.length-a.length)}if("function"==typeof i)return e;if("#"===i[e]&&f(t[e]))return e;if("#"===i[e-1]&&f(t[e-1]))return e;var u=i.indexOf("#");e=m(e,u,i.lastIndexOf("#")+1);for(var l=i.substring(e,i.length).indexOf("#"),p=e,c=e+(-1===l?0:l);u<p&&("#"!==i[p]||!f(t[p]));)p-=1;return!f(t[c])||"left"===r&&e!==u||e-p<c-e?f(t[p])?p+1:p:c},t.prototype.getCaretPosition=function(t,e,r){var o,n,a=this.props.format,i=this.state.value,s=this.getNumberRegex(!0),u=(t.match(s)||[]).join(""),l=(e.match(s)||[]).join("");for(n=o=0;n<r;n++){var p=t[n]||"",c=e[o]||"";if((p.match(s)||p===c)&&("0"!==p||!c.match(s)||"0"===c||u.length===l.length)){for(;p!==e[o]&&o<e.length;)o++;o++}}return"string"!=typeof a||i||(o=e.length),o=this.correctCaretPosition(e,o)},t.prototype.removePrefixAndSuffix=function(t){var e=this.props,r=e.format,o=e.prefix,n=e.suffix;if(!r&&t){var a="-"===t[0];a&&(t=t.substring(1,t.length));var i=(t=o&&0===t.indexOf(o)?t.substring(o.length,t.length):t).lastIndexOf(n);t=n&&-1!==i&&i===t.length-n.length?t.substring(0,i):t,a&&(t="-"+t)}return t},t.prototype.removePatternFormatting=function(t){for(var e=this.props.format.split("#").filter(function(t){return""!==t}),r=0,o="",n=0,a=e.length;n<=a;n++){var i=e[n]||"",s=n===a?t.length:t.indexOf(i,r);if(-1===s){o=t;break}o+=t.substring(r,s),r=s+i.length}return(o.match(this.getNumberRegex(!0))||[]).join("")},t.prototype.removeFormatting=function(t){var e=this.props,r=e.format,o=e.removeFormatting;return t?t=r?"string"==typeof r?this.removePatternFormatting(t):"function"==typeof o?o(t):(t.match(this.getNumberRegex(!0))||[]).join(""):(t=this.removePrefixAndSuffix(t),this.getFloatString(t)):t},t.prototype.formatWithPattern=function(t){for(var e=this.props.format,r=0,o=e.split(""),n=0,a=e.length;n<a;n++)"#"===e[n]&&(o[n]=t[r]||this.getMaskAtIndex(r),r+=1);return o.join("")},t.prototype.formatAsNumber=function(t){var e=this.props,r=e.decimalScale,o=e.fixedDecimalScale,n=e.prefix,a=e.suffix,i=e.allowNegative,s=e.thousandsGroupStyle,u=this.getSeparators(),l=u.thousandSeparator,p=u.decimalSeparator,c=-1!==t.indexOf(".")||r&&o,f=j(t,i),h=f.beforeDecimal,m=f.afterDecimal,g=f.addNegation;return void 0!==r&&(m=d(m,r,o)),l&&(h=function(t,e,r){var o=function(t){switch(t){case"lakh":return/(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;case"wan":return/(\d)(?=(\d{4})+(?!\d))/g;case"thousand":default:return/(\d)(?=(\d{3})+(?!\d))/g}}(r),n=t.search(/[1-9]/);return n=-1===n?t.length:n,t.substring(0,n)+t.substring(n,t.length).replace(o,"$1"+e)}(h,l,s)),n&&(h=n+h),a&&(m+=a),g&&(h="-"+h),t=h+(c&&p||"")+m},t.prototype.formatNumString=function(t){void 0===t&&(t="");var e=this.props,r=e.format,o=e.allowEmptyFormatting,n=e.customNumerals,a=t;if(n&&10===n.length){var i=new RegExp("["+n.join("")+"]","g");a=t.replace(i,function(t){return n.indexOf(t).toString()})}return a=""!==t||o?"-"!==t||r?"string"==typeof r?this.formatWithPattern(a):"function"==typeof r?r(a):this.formatAsNumber(a):"-":""},t.prototype.formatValueProp=function(t){var e=this.props,r=e.format,o=e.decimalScale,n=e.fixedDecimalScale,a=e.allowEmptyFormatting,i=this.props,s=i.value,u=i.isNumericString,l=!(s=c(s)?t:s)&&0!==s;return l&&a&&(s=""),l&&!a?"":("number"==typeof s&&(s=function(t){var e="-"===(t+="")[0]?"-":"";e&&(t=t.substring(1));var r=t.split(/[eE]/g),o=r[0],n=r[1];if(!(n=Number(n)))return e+o;var a=1+n,i=(o=o.replace(".","")).length;return a<0?o="0."+p("0",Math.abs(a))+o:i<=a?o+=p("0",a-i):o=(o.substring(0,a)||"0")+"."+o.substring(a),e+o}(s),u=!0),"Infinity"===s&&u&&(s=""),u&&!r&&"number"==typeof o&&(s=function(t,e,r){if(-1!==["","-"].indexOf(t))return t;var o=-1!==t.indexOf(".")&&e,n=j(t),a=n.beforeDecimal,i=n.afterDecimal,s=n.hasNagation,u=parseFloat("0."+(i||"0")),l=(i.length<=e?"0."+i:u.toFixed(e)).split(".");return(s?"-":"")+a.split("").reverse().reduce(function(t,e,r){return t.length>r?(Number(t[0])+Number(e)).toString()+t.substring(1,t.length):e+t},l[0])+(o?".":"")+d(l[1]||"",Math.min(e,i.length),r)}(s,o,n)),u?this.formatNumString(s):this.formatInput(s))},t.prototype.formatNegation=function(t){void 0===t&&(t="");var e=this.props.allowNegative,r=new RegExp("(-)"),o=new RegExp("(-)(.)*(-)"),n=r.test(t),a=o.test(t);return t=t.replace(/-/g,""),n&&!a&&e&&(t="-"+t),t},t.prototype.formatInput=function(t){return void 0===t&&(t=""),this.props.format||(t=this.removePrefixAndSuffix(t),t=this.formatNegation(t)),t=this.removeFormatting(t),this.formatNumString(t)},t.prototype.isCharacterAFormat=function(t,e){var r=this.props,o=r.format,n=r.prefix,a=r.suffix,i=r.decimalScale,s=r.fixedDecimalScale,u=this.getSeparators().decimalSeparator;return"string"==typeof o&&"#"!==o[t]||!(o||!(t<n.length||t>=e.length-a.length||i&&s&&e[t]===u))},t.prototype.correctInputValue=function(t,r,e){var o=this,n=this.props,a=n.format,i=n.allowNegative,s=n.prefix,u=n.suffix,l=n.decimalScale,p=this.getSeparators(),c=p.allowedDecimalSeparators,f=p.decimalSeparator,h=this.state.numAsString||"",m=this.selectionBeforeInput,g=m.selectionStart,d=m.selectionEnd,v=function(t,e){for(var r=0,o=0,n=t.length,a=e.length;t[r]===e[r]&&r<n;)r++;for(;t[n-1-o]===e[a-1-o]&&r<a-o&&r<n-o;)o++;return{start:r,end:n-o}}(r,e),S=v.start,y=v.end;if(!a&&S===y&&-1!==c.indexOf(e[g])){var x=0===l?"":f;return e.substr(0,g)+x+e.substr(g+1,e.length)}var b=a?0:s.length,w=r.length-(a?0:u.length);if(e.length>r.length||!e.length||S===y||0===g&&d===r.length||0===S&&y===r.length||g===b&&d===w)return e;var N=r.substr(S,y-S);if(!![].concat(N).find(function(t,e){return o.isCharacterAFormat(e+S,r)})){var P=r.substr(S),F={},D=[];[].concat(P).forEach(function(t,e){o.isCharacterAFormat(e+S,r)?F[e]=t:e>N.length-1&&D.push(t)}),Object.keys(F).forEach(function(t){D.length>t?D.splice(t,0,F[t]):D.push(F[t])}),e=r.substr(0,S)+D.join("")}if(!a){var C=this.removeFormatting(e),V=j(C,i),A=V.beforeDecimal,E=V.afterDecimal,O=V.addNegation,R=t<e.indexOf(f)+1;if(C.length<h.length&&R&&""===A&&!parseFloat(E))return O?"-":""}return e},t.prototype.updateValue=function(t){var e=t.formattedValue,r=t.input,o=t.setCaretPosition;void 0===o&&(o=!0);var n=t.source,a=t.event,i=t.numAsString,s=t.caretPos,u=this.props.onValueChange,l=this.state.value;if(r){if(void 0===s&&o){var p=t.inputValue||r.value,c=g(r);r.value=e,s=this.getCaretPosition(p,e,c)}r.value=e,o&&this.setPatchedCaretPosition(r,s,e)}void 0===i&&(i=this.removeFormatting(e)),e!==l&&(this.setState({value:e,numAsString:i}),u(this.getValueObject(e,i),{event:a,source:n}))},t.prototype.onChange=function(t){var e=t.target,r=e.value,o=this.state,n=this.props,a=n.isAllowed,i=o.value||"",s=g(e);r=this.correctInputValue(s,i,r);var u=this.formatInput(r)||"",l=this.removeFormatting(u),p=a(this.getValueObject(u,l));p||(u=i),this.updateValue({formattedValue:u,numAsString:l,inputValue:r,input:e,event:t,source:"event"}),p&&n.onChange(t)},t.prototype.onBlur=function(t){var e=this.props,r=this.state,o=e.format,n=e.onBlur,a=e.allowLeadingZeros,i=r.numAsString,s=r.value;if(this.focusedElm=null,clearTimeout(this.focusTimeout),clearTimeout(this.caretPositionTimeout),!o){isNaN(parseFloat(i))&&(i=""),a||(i=function(t){if(!t)return t;var e="-"===t[0];e&&(t=t.substring(1,t.length));var r=t.split("."),o=r[0].replace(/^0+/,"")||"0",n=r[1]||"";return(e?"-":"")+o+(n?"."+n:"")}(i));var u=this.formatNumString(i);if(u!==s)return this.updateValue({formattedValue:u,numAsString:i,input:t.target,setCaretPosition:!1,event:t,source:"event"}),void n(t)}n(t)},t.prototype.onKeyDown=function(t){var e,r=t.target,o=t.key,n=r.selectionStart,a=r.selectionEnd,i=r.value;void 0===i&&(i="");var s=this.props,u=s.decimalScale,l=s.fixedDecimalScale,p=s.prefix,c=s.suffix,f=s.format,h=s.onKeyDown,m=void 0!==u&&l,g=this.getNumberRegex(!1,m),d=new RegExp("-"),v="string"==typeof f;if(this.selectionBeforeInput={selectionStart:n,selectionEnd:a},"ArrowLeft"===o||"Backspace"===o?e=n-1:"ArrowRight"===o?e=n+1:"Delete"===o&&(e=n),void 0!==e&&n===a){var S=e,y=v?f.indexOf("#"):p.length,x=v?f.lastIndexOf("#")+1:i.length-c.length;if("ArrowLeft"===o||"ArrowRight"===o){var b="ArrowLeft"===o?"left":"right";S=this.correctCaretPosition(i,e,b)}else if("Delete"!==o||g.test(i[e])||d.test(i[e])){if("Backspace"===o&&!g.test(i[e]))if(n<=y+1&&"-"===i[0]&&void 0===f){var w=i.substring(1);this.updateValue({formattedValue:w,caretPos:S,input:r,event:t,source:"event"})}else if(!d.test(i[e])){for(;!g.test(i[S-1])&&y<S;)S--;S=this.correctCaretPosition(i,S,"left")}}else for(;!g.test(i[S])&&S<x;)S++;(S!==e||e<y||x<e)&&(t.preventDefault(),this.setPatchedCaretPosition(r,S,i)),t.isUnitTestRun&&this.setPatchedCaretPosition(r,S,i),h(t)}else h(t)},t.prototype.onMouseUp=function(t){var e=t.target,r=e.selectionStart,o=e.selectionEnd,n=e.value;if(void 0===n&&(n=""),r===o){var a=this.correctCaretPosition(n,r);a!==r&&this.setPatchedCaretPosition(e,a,n)}this.props.onMouseUp(t)},t.prototype.onFocus=function(a){var i=this;a.persist(),this.focusedElm=a.target,this.focusTimeout=setTimeout(function(){var t=a.target,e=t.selectionStart,r=t.selectionEnd,o=t.value;void 0===o&&(o="");var n=i.correctCaretPosition(o,e);n===e||0===e&&r===o.length||i.setPatchedCaretPosition(t,n,o),i.props.onFocus(a)},0)},t.prototype.render=function(){var t=this.props,e=t.type,r=t.displayType,o=t.customInput,n=t.renderText,a=t.getInputRef,i=t.format,s=(t.thousandSeparator,t.decimalSeparator,t.allowedDecimalSeparators,t.thousandsGroupStyle,t.decimalScale,t.fixedDecimalScale,t.prefix,t.suffix,t.removeFormatting,t.mask,t.defaultValue,t.isNumericString,t.allowNegative,t.allowEmptyFormatting,t.allowLeadingZeros,t.onValueChange,t.isAllowed,t.customNumerals,t.onChange,t.onKeyDown,t.onMouseUp,t.onFocus,t.onBlur,t.value,function(t,e){var r={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&-1===e.indexOf(o)&&(r[o]=t[o]);return r}(t,["type","displayType","customInput","renderText","getInputRef","format","thousandSeparator","decimalSeparator","allowedDecimalSeparators","thousandsGroupStyle","decimalScale","fixedDecimalScale","prefix","suffix","removeFormatting","mask","defaultValue","isNumericString","allowNegative","allowEmptyFormatting","allowLeadingZeros","onValueChange","isAllowed","customNumerals","onChange","onKeyDown","onMouseUp","onFocus","onBlur","value"])),u=this.state,l=u.value,p=u.mounted&&function(t){return t||"undefined"!=typeof navigator&&!(navigator.platform&&/iPhone|iPod/.test(navigator.platform))}(i)?"numeric":void 0,c=Object.assign({inputMode:p},s,{type:e,value:l,onChange:this.onChange,onKeyDown:this.onKeyDown,onMouseUp:this.onMouseUp,onFocus:this.onFocus,onBlur:this.onBlur});if("text"===r)return n?n(l,s)||null:h.createElement("span",Object.assign({},s,{ref:a}),l);if(o){var f=o;return h.createElement(f,Object.assign({},c,{ref:a}))}return h.createElement("input",Object.assign({},c,{ref:a}))},t}((h=h&&h.hasOwnProperty("default")?h.default:h).Component);return r.defaultProps=e,r});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e=e||self).NumberFormat={},e.React)}(this,function(e,R){"use strict";var k,t,j="default"in R?R.default:R;function M(e,t){var r={};for(a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.indexOf(a)<0&&(r[a]=e[a]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,a=Object.getOwnPropertySymbols(e);n<a.length;n++)t.indexOf(a[n])<0&&Object.prototype.propertyIsEnumerable.call(e,a[n])&&(r[a[n]]=e[a[n]]);return r}function P(){}function K(e){return!!(e||"").match(/\d/)}function b(e){return null==e}function w(e){return"number"==typeof e&&isNaN(e)}function m(e){return e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&")}function d(e,t,r){var r=function(e){switch(e){case"lakh":return/(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;case"wan":return/(\d)(?=(\d{4})+(?!\d))/g;default:return/(\d)(?=(\d{3})+(?!\d))/g}}(r),n=-1===(n=e.search(/[1-9]/))?e.length:n;return e.substring(0,n)+e.substring(n,e.length).replace(r,"$1"+t)}function g(e,t){void 0===t&&(t=!0);var r="-"===e[0],t=r&&t,e=(e=e.replace("-","")).split(".");return{beforeDecimal:e[0],afterDecimal:e[1]||"",hasNegation:r,addNegation:t}}function v(e,t,r){for(var n="",a=r?"0":"",o=0;o<=t-1;o++)n+=e[o]||a;return n}function a(e,t){return Array(t+1).join(e)}function x(e){var e=e+"",t="-"===e[0]?"-":"",e=(e=t?e.substring(1):e).split(/[eE]/g),r=e[0],e=e[1];if(!(e=Number(e)))return t+r;var e=1+e,n=(r=r.replace(".","")).length;return e<0?r="0."+a("0",Math.abs(e))+r:n<=e?r+=a("0",e-n):r=(r.substring(0,e)||"0")+"."+r.substring(e),t+r}function D(e,t,r){if(-1!==["","-"].indexOf(e))return e;var n=-1!==e.indexOf(".")&&t,e=g(e),a=e.beforeDecimal,o=e.afterDecimal,e=e.hasNegation,u=parseFloat("0."+(o||"0")),o=(o.length<=t?"0."+o:u.toFixed(t)).split(".");return(e?"-":"")+a.split("").reverse().reduce(function(e,t,r){return e.length>r?(Number(e[0])+Number(t)).toString()+e.substring(1,e.length):t+e},o[0])+(n?".":"")+v(o[1]||"",t,r)}function I(e,t){var r;if(e.value=e.value,null!==e)return e.createTextRange?((r=e.createTextRange()).move("character",t),void r.select()):e.selectionStart||0===e.selectionStart?(e.focus(),void e.setSelectionRange(t,t)):void e.focus()}function p(e){return{from:{start:0,end:0},to:{start:0,end:e.length},lastValue:""}}function s(e,t){return"string"==typeof(e=void 0===e?" ":e)?e:e[t]||" "}function L(e){for(var t=Array.from({length:e.length+1}).map(function(){return!0}),r=0,n=t.length;r<n;r++)t[r]=Boolean(K(e[r])||K(e[r-1]));return t}function W(e,t,r,n,a,o){void 0===o&&(o=P);var u,i=R.useRef(),l=(c=function(e){var t,e=b(e)||w(e)?t="":"number"==typeof e||r?(t="number"==typeof e?x(e):e,n(t)):(t=a(e,void 0),e);return{formattedValue:e,numAsString:t}},(u=R.useRef(c)).current=c,R.useRef(function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];return u.current.apply(u,e)}).current),c=R.useState(function(){return l(t)}),f=c[0],s=c[1];return R.useMemo(function(){b(e)?i.current=void 0:(i.current=l(e),s(i.current))},[e,l]),[f,function(e,t){s({formattedValue:e.formattedValue,numAsString:e.value}),o(e,t)}]}function U(e){return e.replace(/[^0-9]/g,"")}function G(e){return e}function r(e){function c(e,t,r){I(e,t),O.current.setCaretTimeout=setTimeout(function(){e.value===r&&I(e,t)},0)}function f(e,t,r){return e=function(e,t,r){for(var n=t.length,a=e.length,o={},u=new Array(n),i=0;i<n;i++){u[i]=-1;for(var l=0,c=a;l<c;l++)if(t[i]===e[l]&&!0!==o[l]){o[u[i]=l]=!0;break}}for(var f=r;f<n&&(-1===u[f]||!K(t[f]));)f++;for(var s=f===n||-1===u[f]?a:u[f],f=r-1;0<f&&(-1===u[f]||!K(t[f]));)f--;var d=-1===f||-1===u[f]?0:u[f]+1;return!(s<d)&&r-d<s-r?d:s}(t,e,r),T(t,e)}function r(e,t,r){var n=function(e,t){for(var r=0,n=0,a=e.length,o=t.length;e[r]===t[r]&&r<a;)r++;for(;e[a-1-n]===t[o-1-n]&&r<o-n&&r<a-n;)n++;return{from:{start:r,end:a-n},to:{start:r,end:o-n}}}(x,e),n=Object.assign(Object.assign({},n),{lastValue:x}),n=l(e,n),a=E(n);if(g&&!g(B(a,n)))return!1;A({formattedValue:a,numAsString:n,inputValue:e,event:t,source:r,setCaretPosition:!0,input:t.target})}var t=e.type,n=(void 0===t&&(t="text"),e.displayType),a=(void 0===n&&(n="input"),e.customInput),o=e.renderText,u=e.getInputRef,i=e.format,l=(void 0===i&&(i=G),e.removeFormatting),s=(void 0===l&&(l=U),e.defaultValue),d=e.isNumericString,m=e.onValueChange,g=e.isAllowed,v=e.onChange,p=(void 0===v&&(v=P),e.onKeyDown),h=(void 0===p&&(p=P),e.onMouseUp),S=(void 0===h&&(h=P),e.onFocus),y=(void 0===S&&(S=P),e.onBlur),b=(void 0===y&&(y=P),e.value),w=e.getCaretBoundary,e=(void 0===w&&(w=L),M(e,["type","displayType","customInput","renderText","getInputRef","format","removeFormatting","defaultValue","isNumericString","onValueChange","isAllowed","onChange","onKeyDown","onMouseUp","onFocus","onBlur","value","getCaretBoundary"])),b=W(b,s,d,i,l,m),s=b[0],x=s.formattedValue,D=s.numAsString,V=b[1],N=R.useRef(),d=(R.useEffect(function(){var e,t=i(D);void 0!==N.current&&t===N.current||(e=F.current,A({formattedValue:t,numAsString:D,input:e,setCaretPosition:!0,source:k.props,event:null}))}),R.useState(!1)),m=d[0],C=d[1],F=R.useRef(null),O=R.useRef({setCaretTimeout:null,focusTimeout:null}),E=(R.useEffect(function(){return C(!0),function(){clearTimeout(O.current.setCaretTimeout),clearTimeout(O.current.focusTimeout)}},[]),i),B=function(e,t){var r=parseFloat(t);return{formattedValue:e,value:t,floatValue:isNaN(r)?void 0:r}},T=function(e,t,r){var n,a,o,u=e.length,i=(n=t,a=0,o=u,t=Math.min(Math.max(n,a),o),w(e));if("left"===r){for(;0<=t&&!i[t];)t--;-1===t&&(t=i.indexOf(!0))}else{for(;t<=u&&!i[t];)t++;u<t&&(t=i.lastIndexOf(!0))}return t=-1===t?u:t},A=function(e){var t,r=e.formattedValue,n=e.input,a=e.setCaretPosition,o=(void 0===a&&(a=!0),e.source),u=e.event,i=e.numAsString,l=e.caretPos;n&&(void 0===l&&a&&(e=e.inputValue||n.value,t=Math.max(n.selectionStart,n.selectionEnd),n.value=r,l=f(e,r,t)),n.value=r,a&&c(n,l,r)),r!==x&&(e=B(r,i),t={event:u,source:o},N.current=e.formattedValue,V(e,t))},s=m&&!("undefined"==typeof navigator||navigator.platform&&/iPhone|iPod/.test(navigator.platform))?"numeric":void 0,b=Object.assign({inputMode:s},e,{type:t,value:x,onChange:function(e){var t=e.target.value;r(t,e,k.event)&&v(e)},onKeyDown:function(e){var t,r=e.target,n=e.key,a=r.selectionStart,o=r.selectionEnd,u=r.value;void 0===u&&(u=""),"ArrowLeft"===n||"Backspace"===n?t=Math.max(a-1,0):"ArrowRight"===n?t=Math.min(a+1,u.length):"Delete"===n&&(t=a),void 0!==t&&a===o&&(a=t,"ArrowLeft"===n||"ArrowRight"===n?a=T(u,t,"ArrowLeft"===n?"left":"right"):"Delete"!==n||K(u[t])?"Backspace"!==n||K(u[t])||(a=T(u,t,"left")):a=T(u,t,"right"),a!==t&&c(r,a,u),e.isUnitTestRun&&c(r,a,u)),p(e)},onMouseUp:function(e){var t=e.target,r=t.selectionStart,n=t.selectionEnd,a=t.value;void 0===a&&(a=""),r===n&&(n=T(a,r))!==r&&c(t,n,a),h(e)},onFocus:function(a){a.persist();var o=a.target;F.current=o,O.current.focusTimeout=setTimeout(function(){var e=o.selectionStart,t=o.selectionEnd,r=o.value,n=T(r=void 0===r?"":r,e);n===e||0===e&&t===r.length||c(o,n,r),S(a)},0)},onBlur:function(e){F.current=null,clearTimeout(O.current.focusTimeout),clearTimeout(O.current.setCaretTimeout),y(e)}});return"text"===n?o?j.createElement(j.Fragment,null,o(x,e)||null):j.createElement("span",Object.assign({},e,{ref:u}),x):a?j.createElement(a,Object.assign({},b,{ref:u})):j.createElement("input",Object.assign({},b,{ref:u}))}function V(e,t){var r=t.decimalScale,n=t.fixedDecimalScale,a=t.prefix,o=(void 0===a&&(a=""),t.suffix),u=(void 0===o&&(o=""),t.allowNegative),i=(void 0===u&&(u=!0),t.thousandsGroupStyle);if(void 0===i&&(i="thousand"),""===e||"-"===e)return e;var t=N(t),l=t.thousandSeparator,t=t.decimalSeparator,c=0!==r&&-1!==e.indexOf(".")||r&&n,u=g(e,u),f=u.beforeDecimal,s=u.afterDecimal,u=u.addNegation;return void 0!==r&&(s=v(s,r,n)),l&&(f=d(f,l,i)),a&&(f=a+f),o&&(s+=o),e=(f=u?"-"+f:f)+(c&&t||"")+s}function N(e){var t=e.decimalSeparator,r=e.thousandSeparator,e=e.allowedDecimalSeparators;return{decimalSeparator:t=void 0===t?".":t,thousandSeparator:r=!0===r?",":r,allowedDecimalSeparators:e=e||[t,"."]}}function C(e,t,r){void 0===t&&(t=p(e));var n=r.allowNegative,a=(void 0===n&&(n=!0),r.prefix),o=(void 0===a&&(a=""),r.suffix),u=(void 0===o&&(o=""),r.decimalScale),i=t.from,t=t.to,l=t.start,c=t.end,r=N(r),f=r.allowedDecimalSeparators,r=r.decimalSeparator,s=e[c]===r,u=(c-l==1&&-1!==f.indexOf(e[l])&&(f=0===u?"":r,e=e.substring(0,l)+f+e.substring(l+1,e.length)),!1),f=(a.startsWith("-")?u=e.startsWith("--"):o.startsWith("-")&&e.length===o.length?u=!1:"-"===e[0]&&(u=!0),u&&(e=e.substring(1),--l,--c),0),a=(e.startsWith(a)?f+=a.length:l<a.length&&(f=l),c-=f,(e=e.substring(f)).length),l=e.length-o.length,d=(e.endsWith(o)?a=l:c>e.length-o.length&&(a=c),e=e.substring(0,a),f=n,void 0===(l=u?"-"+e:e)&&(l=""),o=new RegExp("(-)"),c=new RegExp("(-)(.)*(-)"),o=o.test(l),c=c.test(l),l=l.replace(/-/g,""),(e=((e=l=o&&!c&&f?"-"+l:l).match((a=!0,new RegExp("(^-)|[0-9]|"+m(r),a?"g":void 0)))||[]).join("")).indexOf(r)),u=g(e=e.replace(new RegExp(m(r),"g"),function(e,t){return t===d?".":""}),n),o=u.beforeDecimal,c=u.afterDecimal,f=u.addNegation;return e=t.end-t.start<i.end-i.start&&""===o&&s&&!parseFloat(c)?f?"-":"":e}function F(e,t){var r=t.prefix,t=(void 0===r&&(r=""),t.suffix),n=(void 0===t&&(t=""),Array.from({length:e.length+1}).map(function(){return!0})),a="-"===e[0],r=(n.fill(!1,0,r.length+(a?1:0)),e.length);return n.fill(!1,r-t.length+1,r+1),n}function n(u){var n=u.allowLeadingZeros,i=u.onKeyDown,a=(void 0===i&&(i=P),u.onBlur),l=(void 0===a&&(a=P),u.thousandSeparator),c=u.decimalScale,f=u.fixedDecimalScale,s=u.prefix,e=(void 0===s&&(s=""),u.defaultValue),t=u.value,r=u.isNumericString,o=u.onValueChange,d=(m=N(m=u)).thousandSeparator,m=m.decimalSeparator;if(d===m)throw new Error("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: "+d+' (thousandSeparator = {true} is same as thousandSeparator = ",")\n decimalSeparator: '+m+" (default value for decimalSeparator is .)\n ");function g(e){return V(e,u)}function v(e,t){return C(e,t,u)}function p(e){return b(e)||w(e)?e:("number"==typeof e&&(e=x(e)),h&&"number"==typeof c?D(e,c,f):e)}var h=r,d=(b(t)?b(e)||(h=null!=r?r:"number"==typeof e):h=null!=r?r:"number"==typeof t,W(p(t),p(e),h,g,v,o)),m=d[0],S=m.numAsString,r=m.formattedValue,y=d[1];return{value:r,isNumericString:!1,onValueChange:y,format:g,removeFormatting:v,getCaretBoundary:function(e){return F(e,u)},onKeyDown:function(e){var t=e.target,r=e.key,n=t.selectionStart,a=t.selectionEnd,o=t.value;void 0===o&&(o=""),n===a&&("Backspace"===r&&"-"===o[0]&&n===s.length+1&&I(t,1),a=N(u).decimalSeparator,"Backspace"===r&&o[n-1]===a&&c&&f&&(I(t,n-1),e.preventDefault()),"Backspace"===r&&o[n-1]===l&&I(t,n-1),"Delete"===r&&o[n]===l&&I(t,n+1)),i(e)},onBlur:function(e){var t,r=S;r.match(/\d/g)||(r=""),n||(r=function(e){if(!e)return e;var t="-"===e[0],r=(e=(e=t?e.substring(1,e.length):e).split("."))[0].replace(/^0+/,"")||"0",e=e[1]||"";return(t?"-":"")+r+(e?"."+e:"")}(r)),(r=f&&c?D(r,c,f):r)!==S&&(t=V(r,u),y({formattedValue:t,value:r,floatValue:parseFloat(r)},{event:e,source:k.event})),a(e)}}}function o(e,t){var r=t.format,n=t.allowEmptyFormatting,a=t.mask;if(""===e&&!n)return"";for(var o=0,u=r.split(""),i=0,l=r.length;i<l;i++)"#"===r[i]&&(u[i]=e[o]||s(a,o),o+=1);return u.join("")}function c(e,t,r){void 0===t&&(t=p(e));function a(e){return u[e]===i}function n(e,t){for(var r="",n=0;n<e.length;n++)a(t+n)&&(r+=e[n]);return r}function o(e){return e.replace(/[^0-9]/g,"")}var u=r.format,i=r.patternChar,r=(void 0===i&&(i="#"),t.from),l=t.to,t=t.lastValue;void 0===t&&(t="");if(!u.match(/\d/))return o(e);if(""===t&&e.length===u.length){for(var c="",f=0;f<e.length;f++)if(a(f))c+=e[f];else if(e[f]!==u[f])return o(e);return c}var s=t.substring(0,r.start),l=e.substring(l.start,l.end),t=t.substring(r.end);return""+n(s,0)+o(l)+n(t,r.end)}function f(t,e){for(var r=e.format,n=e.mask,a=e.patternChar,o=(void 0===a&&(a="#"),Array.from({length:t.length+1}).map(function(){return!0})),u=0,i=r.split("").map(function(e){if(e===a)return s(n,++u-1)}),l=function(e){return r[e]===a&&t[e]!==i[e]},c=0,f=o.length;c<f;c++)o[c]=l(c)||l(c-1);return o[r.indexOf(a)]=!0,o}function u(r){var u=r.format,e=r.inputMode,i=(void 0===e&&(e="numeric"),r.onKeyDown),l=(void 0===i&&(i=P),r.patternChar),t=(void 0===l&&(l="#"),r);if((t=t.mask)&&("string"===t?t:t.toString()).match(/\d/g))throw new Error("Mask "+t+" should not contain numeric character;");return{inputMode:e,format:function(e){return o(e,r)},removeFormatting:function(e,t){return c(e,t,r)},getCaretBoundary:function(e){return f(e,r)},onKeyDown:function(e){var t=e.key,r=e.target,n=r.selectionStart;if(n!==r.selectionEnd)i(e);else{if("Backspace"===t||"Delete"===t){var a=n;if("Backspace"===t)for(;0<a&&u[a-1]!==l;)a--;else for(var o=u.length;a<o&&u[a]!==l;)a++;a!==n&&I(r,a)}i(e)}}}}(t=k=k||{}).event="event",t.props="prop",e.NumberFormatBase=r,e.NumericFormat=function(e){e.decimalSeparator,e.allowedDecimalSeparators,e.thousandsGroupStyle,e.suffix,e.allowNegative,e.allowLeadingZeros,e.onKeyDown,e.onBlur,e.thousandSeparator,e.decimalScale,e.fixedDecimalScale,e.prefix,e.defaultValue,e.value,e.isNumericString,e.onValueChange;var t=M(e,["decimalSeparator","allowedDecimalSeparators","thousandsGroupStyle","suffix","allowNegative","allowLeadingZeros","onKeyDown","onBlur","thousandSeparator","decimalScale","fixedDecimalScale","prefix","defaultValue","value","isNumericString","onValueChange"]),e=n(e);return j.createElement(r,Object.assign({},t,e))},e.PatternFormat=function(e){e.mask,e.allowEmptyFormatting,e.format,e.inputMode,e.onKeyDown,e.patternChar;var t=M(e,["mask","allowEmptyFormatting","format","inputMode","onKeyDown","patternChar"]),e=u(e);return j.createElement(r,Object.assign({},t,e))},e.getNumericCaretBoundary=F,e.getPatternCaretBoundary=f,e.numericFormatter=V,e.patterFormatter=o,e.removeNumericFormat=C,e.removePatternFormat=c,e.useNumericFormat=n,e.usePatternFormat=u,Object.defineProperty(e,"__esModule",{value:!0})});
{
"name": "react-number-format",
"description": "React component to format number in an input or as a text.",
"version": "4.9.3",
"version": "5.0.0-beta.1",
"main": "dist/react-number-format.cjs.js",
"module": "dist/react-number-format.es.js",
"types": "types/index.d.ts",
"author": "Sudhanshu Yadav",
"license": "MIT",
"types": "typings/number_format.d.ts",
"repository": {

@@ -29,9 +29,9 @@ "type": "git",

"start": "webpack-dev-server --hot",
"format": "prettier --write ./src ./typings ./test ./example",
"bundle": "cross-env yarn compile && yarn bundle-dist && yarn test-build && yarn test-ts && yarn format",
"bundle-dist": "cross-env NODE_ENV=production rollup -c rollup.config.js",
"compile": "cross-env NODE_ENV=production babel src --out-dir lib",
"format": "prettier --write ./src ./test ./example",
"build": "cross-env yarn build-dist && yarn test-build && yarn test-ts && yarn format",
"build-dist": "cross-env NODE_ENV=production rollup -c rollup.config.js",
"build-types": "tsc -p tsconfig.build.json",
"test": "cross-env NODE_ENV=test karma start && yarn test-ts",
"test-build": "cross-env NODE_ENV=production TEST_BROWSER=ChromeHeadless karma start",
"test-ts": "yarn tsc -p typings",
"test-ts": "yarn tsc --noEmit",
"lint": "cross-env eslint src/**"

@@ -49,5 +49,7 @@ },

"@rollup/plugin-buble": "^0.21.3",
"@rollup/plugin-typescript": "^8.3.0",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"@types/react": "^18.0.6",
"@typescript-eslint/parser": "^5.15.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.7",

@@ -67,3 +69,2 @@ "babel-eslint": "^10.0.3",

"eslint-plugin-react": "^7.15.1",
"flow-bin": "^0.118.0",
"jasmine": "^2.4.1",

@@ -79,8 +80,8 @@ "jasmine-core": "^2.4.1",

"karma-spec-reporter": "^0.0.32",
"karma-webpack": "^4.0.2",
"karma-webpack": "^5.0.0",
"material-ui": "^0.20.2",
"pascal-case": "3.1.2",
"prettier": "^2.2.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router": "5",
"react-transform-hmr": "^1.0.4",

@@ -91,3 +92,2 @@ "rollup": "^1.22.0",

"rollup-plugin-filesize": "^6.2.0",
"rollup-plugin-flow": "^1.1.1",
"rollup-plugin-license": "^0.12.1",

@@ -97,6 +97,7 @@ "rollup-plugin-node-resolve": "^5.2.0",

"rollup-plugin-uglify": "^6.0.3",
"ts-loader": "^9.2.6",
"typescript": "^4.6.3",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2"
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
},

@@ -103,0 +104,0 @@ "peerDependencies": {

@@ -431,3 +431,3 @@ [![Actions Status](https://github.com/s-yadav/react-number-format/workflows/CI/badge.svg)](https://github.com/s-yadav/react-number-format/actions)

- `yarn test` to test changes
- `yarn bundle` to bundle files
- `yarn build` to bundle files

@@ -434,0 +434,0 @@ #### Testing

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc