react-number-format
Advanced tools
Comparing version 4.5.3 to 4.5.4
/** | ||
* react-number-format - 4.5.3 | ||
* react-number-format - 4.5.4 | ||
* Author : Sudhanshu Yadav | ||
@@ -10,89 +10,2 @@ * Copyright (c) 2016, 2021 to Sudhanshu Yadav, released under the MIT license. | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inherits(subClass, superClass) { | ||
if (typeof superClass !== "function" && superClass !== null) { | ||
throw new TypeError("Super expression must either be null or a function"); | ||
} | ||
subClass.prototype = Object.create(superClass && superClass.prototype, { | ||
constructor: { | ||
value: subClass, | ||
writable: true, | ||
configurable: true | ||
} | ||
}); | ||
if (superClass) _setPrototypeOf(subClass, superClass); | ||
} | ||
function _getPrototypeOf(o) { | ||
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { | ||
return o.__proto__ || Object.getPrototypeOf(o); | ||
}; | ||
return _getPrototypeOf(o); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
} | ||
return self; | ||
} | ||
function _possibleConstructorReturn(self, call) { | ||
if (call && (typeof call === "object" || typeof call === "function")) { | ||
return call; | ||
} | ||
return _assertThisInitialized(self); | ||
} | ||
function createCommonjsModule(fn, module) { | ||
@@ -180,2 +93,6 @@ return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
// | ||
// basic noop function | ||
@@ -186,19 +103,21 @@ function noop() {} | ||
} | ||
function charIsNumber(_char) { | ||
return !!(_char || '').match(/\d/); | ||
function charIsNumber(char ) { | ||
return !!(char || '').match(/\d/); | ||
} | ||
function isNil(val) { | ||
function isNil(val ) { | ||
return val === null || val === undefined; | ||
} | ||
function escapeRegExp(str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); | ||
function escapeRegExp(str ) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
function getThousandsGroupRegex(thousandsGroupStyle) { | ||
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': | ||
@@ -209,17 +128,29 @@ default: | ||
} | ||
function applyThousandSeparator(str, thousandSeparator, thousandsGroupStyle) { | ||
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 | ||
return ( | ||
str.substring(0, index) + | ||
str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator) | ||
); | ||
} | ||
function splitDecimal(numStr) { | ||
var allowNegative = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
//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 { | ||
@@ -229,14 +160,17 @@ beforeDecimal: beforeDecimal, | ||
hasNagation: hasNagation, | ||
addNegation: addNegation | ||
addNegation: addNegation, | ||
}; | ||
} | ||
function fixLeadingZero(numStr) { | ||
if (!numStr) return numStr; | ||
function fixLeadingZero(numStr ) { | ||
if (!numStr) { return numStr; } | ||
var isNegative = numStr[0] === '-'; | ||
if (isNegative) numStr = numStr.substring(1, numStr.length); | ||
if (isNegative) { numStr = numStr.substring(1, numStr.length); } | ||
var parts = numStr.split('.'); | ||
var beforeDecimal = parts[0].replace(/^0+/, '') || '0'; | ||
var afterDecimal = parts[1] || ''; | ||
return "".concat(isNegative ? '-' : '').concat(beforeDecimal).concat(afterDecimal ? ".".concat(afterDecimal) : ''); | ||
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : '')); | ||
} | ||
/** | ||
@@ -246,13 +180,58 @@ * limit decimal numbers to given scale | ||
*/ | ||
function limitToScale(numStr, scale, fixedDecimalScale) { | ||
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) | ||
} | ||
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; | ||
} | ||
/** | ||
@@ -262,42 +241,52 @@ * 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; } | ||
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 _splitDecimal = splitDecimal(numStr), | ||
beforeDecimal = _splitDecimal.beforeDecimal, | ||
afterDecimal = _splitDecimal.afterDecimal, | ||
hasNagation = _splitDecimal.hasNagation; | ||
var floatValue = parseFloat("0.".concat(afterDecimal || '0')); | ||
var floatValueStr = afterDecimal.length <= scale ? floatValue.toString() : floatValue.toFixed(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 ? toNumericString(floatValue) : 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); | ||
} | ||
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]); | ||
return current + roundedStr; | ||
}, roundedDecimalParts[0]); | ||
var decimalPart = limitToScale(roundedDecimalParts[1] || '', Math.min(scale, afterDecimal.length), fixedDecimalScale); | ||
var decimalPart = limitToScale( | ||
roundedDecimalParts[1] || '', | ||
Math.min(scale, afterDecimal.length), | ||
fixedDecimalScale | ||
); | ||
var negation = hasNagation ? '-' : ''; | ||
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : ''; | ||
return "".concat(negation).concat(intPart).concat(decimalSeparator).concat(decimalPart); | ||
return ("" + negation + intPart + decimalSeparator + decimalPart); | ||
} | ||
function omit(obj, keyMaps) { | ||
function omit(obj , keyMaps ) { | ||
var filteredObj = {}; | ||
Object.keys(obj).forEach(function (key) { | ||
if (!keyMaps[key]) filteredObj[key] = obj[key]; | ||
if (!keyMaps[key]) { filteredObj[key] = obj[key]; } | ||
}); | ||
return filteredObj; | ||
} | ||
/** 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 | ||
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) { | ||
@@ -309,5 +298,4 @@ if (el.createTextRange) { | ||
return true; | ||
} // (el.selectionStart === 0 added for Firefox bug) | ||
} | ||
// (el.selectionStart === 0 added for Firefox bug) | ||
if (el.selectionStart || el.selectionStart === 0) { | ||
@@ -317,5 +305,5 @@ el.focus(); | ||
return true; | ||
} // fail city, fortunately this never happens (as far as I've tested) :) | ||
} | ||
// fail city, fortunately this never happens (as far as I've tested) :) | ||
el.focus(); | ||
@@ -325,2 +313,3 @@ return false; | ||
} | ||
/** | ||
@@ -332,38 +321,40 @@ Given previous value and newValue it returns the index | ||
*/ | ||
function findChangedIndex(prevValue, newValue) { | ||
function findChangedIndex(prevValue , newValue ) { | ||
var i = 0, | ||
j = 0; | ||
j = 0; | ||
var prevLength = prevValue.length; | ||
var newLength = newValue.length; | ||
while (prevValue[i] === newValue[i] && i < prevLength) { i++; } | ||
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) { | ||
//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 | ||
}; | ||
return { start: i, end: prevLength - j }; | ||
} | ||
/* | ||
Returns a number whose value is limited to the given range | ||
*/ | ||
function clamp(num, min, max) { | ||
function clamp(num , min , max ) { | ||
return Math.min(Math.max(num, min), max); | ||
} | ||
function getCurrentCaretPosition(el) { | ||
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) { | ||
function addInputMode(format ) { | ||
return format || !(navigator.platform && /iPhone|iPod/.test(navigator.platform)); | ||
} | ||
// | ||
var propTypes$1 = { | ||
@@ -379,7 +370,16 @@ thousandSeparator: propTypes.oneOfType([propTypes.string, propTypes.oneOf([true])]), | ||
suffix: propTypes.string, | ||
format: propTypes.oneOfType([propTypes.string, propTypes.func]), | ||
format: propTypes.oneOfType([ | ||
propTypes.string, | ||
propTypes.func | ||
]), | ||
removeFormatting: propTypes.func, | ||
mask: propTypes.oneOfType([propTypes.string, propTypes.arrayOf(propTypes.string)]), | ||
value: propTypes.oneOfType([propTypes.number, propTypes.string]), | ||
defaultValue: propTypes.oneOfType([propTypes.number, propTypes.string]), | ||
value: propTypes.oneOfType([ | ||
propTypes.number, | ||
propTypes.string | ||
]), | ||
defaultValue: propTypes.oneOfType([ | ||
propTypes.number, | ||
propTypes.string | ||
]), | ||
isNumericString: propTypes.bool, | ||
@@ -399,7 +399,8 @@ customInput: propTypes.elementType, | ||
renderText: propTypes.func, | ||
getInputRef: propTypes.oneOfType([propTypes.func, // for legacy refs | ||
propTypes.shape({ | ||
current: propTypes.any | ||
})]) | ||
getInputRef: propTypes.oneOfType([ | ||
propTypes.func, // for legacy refs | ||
propTypes.shape({ current: propTypes.any }) | ||
]) | ||
}; | ||
var defaultProps = { | ||
@@ -425,969 +426,965 @@ displayType: 'input', | ||
}; | ||
var NumberFormat = /*@__PURE__*/(function (superclass) { | ||
function NumberFormat(props ) { | ||
superclass.call(this, props); | ||
var NumberFormat = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(NumberFormat, _React$Component); | ||
var defaultValue = props.defaultValue; | ||
function NumberFormat(props) { | ||
var _this; | ||
//validate props | ||
this.validateProps(); | ||
_classCallCheck(this, NumberFormat); | ||
var formattedValue = this.formatValueProp(defaultValue); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(NumberFormat).call(this, props)); | ||
var defaultValue = props.defaultValue; //validate props | ||
_this.validateProps(); | ||
var formattedValue = _this.formatValueProp(defaultValue); | ||
_this.state = { | ||
this.state = { | ||
value: formattedValue, | ||
numAsString: _this.removeFormatting(formattedValue), | ||
mounted: false | ||
numAsString: this.removeFormatting(formattedValue), | ||
mounted: false, | ||
}; | ||
_this.selectionBeforeInput = { | ||
this.selectionBeforeInput = { | ||
selectionStart: 0, | ||
selectionEnd: 0 | ||
}; | ||
_this.onChange = _this.onChange.bind(_assertThisInitialized(_this)); | ||
_this.onKeyDown = _this.onKeyDown.bind(_assertThisInitialized(_this)); | ||
_this.onMouseUp = _this.onMouseUp.bind(_assertThisInitialized(_this)); | ||
_this.onFocus = _this.onFocus.bind(_assertThisInitialized(_this)); | ||
_this.onBlur = _this.onBlur.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
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); | ||
} | ||
_createClass(NumberFormat, [{ | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
// set mounted state | ||
// eslint-disable-next-line react/no-did-mount-set-state | ||
this.setState({ | ||
mounted: true | ||
}); | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate(prevProps) { | ||
this.updateValueIfRequired(prevProps); | ||
} | ||
}, { | ||
key: "componentWillUnmount", | ||
value: function componentWillUnmount() { | ||
clearTimeout(this.focusTimeout); | ||
} | ||
}, { | ||
key: "updateValueIfRequired", | ||
value: function updateValueIfRequired(prevProps) { | ||
var props = this.props, | ||
state = this.state, | ||
focusedElm = this.focusedElm; | ||
var stateValue = state.value, | ||
_state$numAsString = state.numAsString, | ||
lastNumStr = _state$numAsString === void 0 ? '' : _state$numAsString; // If only state changed no need to do any thing | ||
if ( superclass ) NumberFormat.__proto__ = superclass; | ||
NumberFormat.prototype = Object.create( superclass && superclass.prototype ); | ||
NumberFormat.prototype.constructor = NumberFormat; | ||
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); | ||
NumberFormat.prototype.componentDidMount = function componentDidMount () { | ||
// set mounted state | ||
// eslint-disable-next-line react/no-did-mount-set-state | ||
this.setState({ | ||
mounted: true | ||
}); | ||
}; | ||
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 | ||
}); | ||
} | ||
} | ||
} | ||
/** Misc methods **/ | ||
NumberFormat.prototype.componentDidUpdate = function componentDidUpdate (prevProps ) { | ||
this.updateValueIfRequired(prevProps); | ||
}; | ||
}, { | ||
key: "getFloatString", | ||
value: function getFloatString() { | ||
var num = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var decimalScale = this.props.decimalScale; | ||
NumberFormat.prototype.componentWillUnmount = function componentWillUnmount () { | ||
clearTimeout(this.focusTimeout); | ||
}; | ||
var _this$getSeparators = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators.decimalSeparator; | ||
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 = ''; | ||
var numRegex = this.getNumberRegex(true); //remove negation for regex check | ||
// If only state changed no need to do any thing | ||
if(prevProps !== props) { | ||
//validate props | ||
this.validateProps(); | ||
var hasNegation = num[0] === '-'; | ||
if (hasNegation) num = num.replace('-', ''); //if decimal scale is zero remove decimal and number after decimalSeparator | ||
var lastValueWithNewFormat = this.formatNumString(lastNumStr); | ||
if (decimalSeparator && decimalScale === 0) { | ||
num = num.split(decimalSeparator)[0]; | ||
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 }); | ||
} | ||
} | ||
}; | ||
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.'); //remove extra decimals | ||
/** Misc methods **/ | ||
NumberFormat.prototype.getFloatString = function getFloatString (num) { | ||
if ( num === void 0 ) num = ''; | ||
var firstDecimalIndex = num.indexOf('.'); | ||
var ref = this.props; | ||
var decimalScale = ref.decimalScale; | ||
var ref$1 = this.getSeparators(); | ||
var decimalSeparator = ref$1.decimalSeparator; | ||
var numRegex = this.getNumberRegex(true); | ||
if (firstDecimalIndex !== -1) { | ||
num = "".concat(num.substring(0, firstDecimalIndex), ".").concat(num.substring(firstDecimalIndex + 1, num.length).replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), '')); | ||
} //add negation back | ||
//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]; | ||
} | ||
if (hasNegation) num = '-' + num; | ||
return num; | ||
} //returned regex assumes decimalSeparator is as per prop | ||
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.'); | ||
}, { | ||
key: "getNumberRegex", | ||
value: function getNumberRegex(g, ignoreDecimalSeparator) { | ||
var _this$props = this.props, | ||
format = _this$props.format, | ||
decimalScale = _this$props.decimalScale; | ||
//remove extra decimals | ||
var firstDecimalIndex = num.indexOf('.'); | ||
var _this$getSeparators2 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators2.decimalSeparator; | ||
return new RegExp('\\d' + (decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined); | ||
if (firstDecimalIndex !== -1) { | ||
num = (num.substring(0, firstDecimalIndex)) + "." + (num.substring(firstDecimalIndex + 1, num.length).replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), '')); | ||
} | ||
}, { | ||
key: "getSeparators", | ||
value: function getSeparators() { | ||
var decimalSeparator = this.props.decimalSeparator; | ||
var _this$props2 = this.props, | ||
thousandSeparator = _this$props2.thousandSeparator, | ||
allowedDecimalSeparators = _this$props2.allowedDecimalSeparators; | ||
if (thousandSeparator === true) { | ||
thousandSeparator = ','; | ||
} | ||
//add negation back | ||
if(hasNegation) { num = '-' + num; } | ||
if (!allowedDecimalSeparators) { | ||
allowedDecimalSeparators = [decimalSeparator, '.']; | ||
} | ||
return num; | ||
}; | ||
return { | ||
decimalSeparator: decimalSeparator, | ||
thousandSeparator: thousandSeparator, | ||
allowedDecimalSeparators: allowedDecimalSeparators | ||
}; | ||
} | ||
}, { | ||
key: "getMaskAtIndex", | ||
value: function getMaskAtIndex(index) { | ||
var _this$props$mask = this.props.mask, | ||
mask = _this$props$mask === void 0 ? ' ' : _this$props$mask; | ||
//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 ref$1 = this.getSeparators(); | ||
var decimalSeparator = ref$1.decimalSeparator; | ||
return new RegExp('\\d' + (decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined); | ||
}; | ||
if (typeof mask === 'string') { | ||
return mask; | ||
} | ||
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; | ||
return mask[index] || ' '; | ||
if (thousandSeparator === true) { | ||
thousandSeparator = ','; | ||
} | ||
}, { | ||
key: "getValueObject", | ||
value: function getValueObject(formattedValue, numAsString) { | ||
var floatValue = parseFloat(numAsString); | ||
return { | ||
formattedValue: formattedValue, | ||
value: numAsString, | ||
floatValue: isNaN(floatValue) ? undefined : floatValue | ||
}; | ||
if (!allowedDecimalSeparators) { | ||
allowedDecimalSeparators = [decimalSeparator, '.']; | ||
} | ||
}, { | ||
key: "validateProps", | ||
value: function validateProps() { | ||
var mask = this.props.mask; //validate decimalSeparator and thousandSeparator | ||
var _this$getSeparators3 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators3.decimalSeparator, | ||
thousandSeparator = _this$getSeparators3.thousandSeparator; | ||
return { | ||
decimalSeparator: decimalSeparator, | ||
thousandSeparator: thousandSeparator, | ||
allowedDecimalSeparators: allowedDecimalSeparators, | ||
} | ||
}; | ||
if (decimalSeparator === thousandSeparator) { | ||
throw new Error("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: ".concat(thousandSeparator, " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: ").concat(decimalSeparator, " (default value for decimalSeparator is .)\n ")); | ||
} //validate 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[index] || ' '; | ||
}; | ||
if (mask) { | ||
var maskAsStr = mask === 'string' ? mask : mask.toString(); | ||
NumberFormat.prototype.getValueObject = function getValueObject (formattedValue , numAsString ) { | ||
var floatValue = parseFloat(numAsString); | ||
if (maskAsStr.match(/\d/g)) { | ||
throw new Error("\n Mask ".concat(mask, " should not contain numeric character;\n ")); | ||
} | ||
} | ||
} | ||
/** Misc methods end **/ | ||
return { | ||
formattedValue: formattedValue, | ||
value: numAsString, | ||
floatValue: isNaN(floatValue) ? undefined : floatValue | ||
}; | ||
/** caret specific methods **/ | ||
}; | ||
}, { | ||
key: "setPatchedCaretPosition", | ||
value: 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); | ||
setTimeout(function () { | ||
if (el.value === currentValue) setCaretPosition(el, caretPos); | ||
}, 0); | ||
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 ")); | ||
} | ||
/* This keeps the caret within typing area so people can't type in between prefix or suffix */ | ||
}, { | ||
key: "correctCaretPosition", | ||
value: function correctCaretPosition(value, caretPos, direction) { | ||
var _this$props3 = this.props, | ||
prefix = _this$props3.prefix, | ||
suffix = _this$props3.suffix, | ||
format = _this$props3.format; //if value is empty return 0 | ||
//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 (value === '') return 0; //caret position should be between 0 and value length | ||
}; | ||
/** Misc methods end **/ | ||
caretPos = clamp(caretPos, 0, value.length); //in case of format as number limit between prefix and suffix | ||
/** 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); | ||
setTimeout(function () { | ||
if(el.value === currentValue) { setCaretPosition(el, caretPos); } | ||
}, 0); | ||
}; | ||
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 | ||
/* 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; } | ||
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 | ||
//caret position should be between 0 and value length | ||
caretPos = clamp(caretPos, 0, value.length); | ||
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) return caretPos; //if caretPos is just after input value don't do anything | ||
//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 (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) return caretPos; //find the nearest caret position | ||
//in case if custom format method don't do anything | ||
if (typeof format === 'function') { return caretPos; } | ||
var firstHashPosition = format.indexOf('#'); | ||
var lastHashPosition = format.lastIndexOf('#'); //limit the cursor between the first # position and the last # position | ||
/* in case format is string find the closest # position from the caret 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 | ||
//in case the caretPos have input value on it don't do anything | ||
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) { return caretPos; } | ||
while (caretLeftBound > firstHashPosition && (format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))) { | ||
caretLeftBound -= 1; | ||
} | ||
//if caretPos is just after input value don't do anything | ||
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) { return caretPos; } | ||
var goToLeft = !charIsNumber(value[caretRightBound]) || direction === 'left' && caretPos !== firstHashPosition || caretPos - caretLeftBound < caretRightBound - caretPos; | ||
//find the nearest caret position | ||
var firstHashPosition = format.indexOf('#'); | ||
var lastHashPosition = format.lastIndexOf('#'); | ||
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; | ||
} | ||
//limit the cursor between the first # position and the last # position | ||
caretPos = clamp(caretPos, firstHashPosition, lastHashPosition + 1); | ||
return caretRightBound; | ||
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; | ||
} | ||
}, { | ||
key: "getCaretPosition", | ||
value: function getCaretPosition(inputValue, formattedValue, caretPos) { | ||
var format = this.props.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 | ||
var goToLeft = !charIsNumber(value[caretRightBound]) | ||
|| (direction === 'left' && caretPos !== firstHashPosition) | ||
|| (caretPos - caretLeftBound < caretRightBound - caretPos); | ||
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 (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; | ||
} | ||
if (currentInputChar === '0' && currentFormatChar.match(numRegex) && currentFormatChar !== '0' && inputNumber.length !== formattedNumber.length) continue; //we are not using currentFormatChar because j can change here | ||
return caretRightBound; | ||
}; | ||
while (currentInputChar !== formattedValue[j] && j < formattedValue.length) { | ||
j++; | ||
} | ||
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++; | ||
} | ||
j = 0; | ||
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 | ||
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; } | ||
j = this.correctCaretPosition(formattedValue, j); | ||
return j; | ||
//we are not using currentFormatChar because j can change here | ||
while(currentInputChar !== formattedValue[j] && j < formattedValue.length) { j++; } | ||
j++; | ||
} | ||
/** caret specific methods ends **/ | ||
/** methods to remove formattting **/ | ||
if ((typeof format === 'string' && !stateValue)) { | ||
//set it to the maximum value so it goes after the last number | ||
j = formattedValue.length; | ||
} | ||
}, { | ||
key: "removePrefixAndSuffix", | ||
value: function removePrefixAndSuffix(val) { | ||
var _this$props4 = this.props, | ||
format = _this$props4.format, | ||
prefix = _this$props4.prefix, | ||
suffix = _this$props4.suffix; //remove prefix and suffix | ||
//correct caret position if its outside of editable area | ||
j = this.correctCaretPosition(formattedValue, j); | ||
if (!format && val) { | ||
var isNegative = val[0] === '-'; //remove negation sign | ||
return j; | ||
}; | ||
/** caret specific methods ends **/ | ||
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 | ||
/** 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; | ||
var suffixLastIndex = val.lastIndexOf(suffix); | ||
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val; //add negation sign back | ||
//remove prefix and suffix | ||
if (!format && val) { | ||
var isNegative = val[0] === '-'; | ||
if (isNegative) val = '-' + val; | ||
} | ||
//remove negation sign | ||
if (isNegative) { val = val.substring(1, val.length); } | ||
return val; | ||
//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; } | ||
} | ||
}, { | ||
key: "removePatternFormatting", | ||
value: function removePatternFormatting(val) { | ||
var format = this.props.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 (###) ### ## ## | ||
return val; | ||
}; | ||
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 */ | ||
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 = ''; | ||
if (index === -1) { | ||
numStr = val; | ||
break; | ||
} else { | ||
numStr += val.substring(start, index); | ||
start = index + part.length; | ||
} | ||
} | ||
for (var i=0, ln=formatArray.length; i <= ln; i++) { | ||
var part = formatArray[i] || ''; | ||
return (numStr.match(/\d/g) || []).join(''); | ||
} | ||
}, { | ||
key: "removeFormatting", | ||
value: function removeFormatting(val) { | ||
var _this$props5 = this.props, | ||
format = _this$props5.format, | ||
removeFormatting = _this$props5.removeFormatting; | ||
if (!val) return val; | ||
//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); | ||
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); | ||
/* 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 { | ||
val = (val.match(/\d/g) || []).join(''); | ||
numStr += val.substring(start, index); | ||
start = index + part.length; | ||
} | ||
return val; | ||
} | ||
/** methods to remove formattting end **/ | ||
/*** format specific methods start ***/ | ||
return (numStr.match(/\d/g) || []).join(''); | ||
}; | ||
/** | ||
* Format when # based string is provided | ||
* @param {string} numStr Numeric String | ||
* @return {string} formatted Value | ||
*/ | ||
NumberFormat.prototype.removeFormatting = function removeFormatting (val ) { | ||
var ref = this.props; | ||
var format = ref.format; | ||
var removeFormatting = ref.removeFormatting; | ||
if (!val) { return val; } | ||
}, { | ||
key: "formatWithPattern", | ||
value: function formatWithPattern(numStr) { | ||
var format = this.props.format; | ||
var hashCount = 0; | ||
var formattedNumberAry = format.split(''); | ||
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(/\d/g) || []).join(''); | ||
} | ||
return val; | ||
}; | ||
/** methods to remove formattting end **/ | ||
for (var i = 0, ln = format.length; i < ln; i++) { | ||
if (format[i] === '#') { | ||
formattedNumberAry[i] = numStr[hashCount] || this.getMaskAtIndex(hashCount); | ||
hashCount += 1; | ||
} | ||
/*** 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 | ||
*/ | ||
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; | ||
}, { | ||
key: "formatAsNumber", | ||
value: function formatAsNumber(numStr) { | ||
var _this$props6 = this.props, | ||
decimalScale = _this$props6.decimalScale, | ||
fixedDecimalScale = _this$props6.fixedDecimalScale, | ||
prefix = _this$props6.prefix, | ||
suffix = _this$props6.suffix, | ||
allowNegative = _this$props6.allowNegative, | ||
thousandsGroupStyle = _this$props6.thousandsGroupStyle; | ||
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 _this$getSeparators4 = this.getSeparators(), | ||
thousandSeparator = _this$getSeparators4.thousandSeparator, | ||
decimalSeparator = _this$getSeparators4.decimalSeparator; | ||
//apply decimal precision if its defined | ||
if (decimalScale !== undefined) { afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale); } | ||
var hasDecimalSeparator = numStr.indexOf('.') !== -1 || decimalScale && fixedDecimalScale; | ||
if(thousandSeparator) { | ||
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle); | ||
} | ||
var _splitDecimal = splitDecimal(numStr, allowNegative), | ||
beforeDecimal = _splitDecimal.beforeDecimal, | ||
afterDecimal = _splitDecimal.afterDecimal, | ||
addNegation = _splitDecimal.addNegation; // eslint-disable-line prefer-const | ||
//apply decimal precision if its defined | ||
//add prefix and suffix | ||
if(prefix) { beforeDecimal = prefix + beforeDecimal; } | ||
if(suffix) { afterDecimal = afterDecimal + suffix; } | ||
//restore negation sign | ||
if (addNegation) { beforeDecimal = '-' + beforeDecimal; } | ||
if (decimalScale !== undefined) afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale); | ||
numStr = beforeDecimal + (hasDecimalSeparator && decimalSeparator || '') + afterDecimal; | ||
if (thousandSeparator) { | ||
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle); | ||
} //add prefix and suffix | ||
return numStr; | ||
}; | ||
NumberFormat.prototype.formatNumString = function formatNumString (numStr) { | ||
if ( numStr === void 0 ) numStr = ''; | ||
if (prefix) beforeDecimal = prefix + beforeDecimal; | ||
if (suffix) afterDecimal = afterDecimal + suffix; //restore negation sign | ||
var ref = this.props; | ||
var format = ref.format; | ||
var allowEmptyFormatting = ref.allowEmptyFormatting; | ||
var formattedValue = numStr; | ||
if (addNegation) beforeDecimal = '-' + beforeDecimal; | ||
numStr = beforeDecimal + (hasDecimalSeparator && decimalSeparator || '') + afterDecimal; | ||
return numStr; | ||
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); | ||
} | ||
}, { | ||
key: "formatNumString", | ||
value: function formatNumString() { | ||
var numStr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var _this$props7 = this.props, | ||
format = _this$props7.format, | ||
allowEmptyFormatting = _this$props7.allowEmptyFormatting; | ||
var formattedValue = numStr; | ||
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; | ||
}; | ||
return formattedValue; | ||
} | ||
}, { | ||
key: "formatValueProp", | ||
value: function formatValueProp(defaultValue) { | ||
var _this$props8 = this.props, | ||
format = _this$props8.format, | ||
decimalScale = _this$props8.decimalScale, | ||
fixedDecimalScale = _this$props8.fixedDecimalScale, | ||
allowEmptyFormatting = _this$props8.allowEmptyFormatting; | ||
var _this$props9 = this.props, | ||
value = _this$props9.value, | ||
isNumericString = _this$props9.isNumericString; // if value is undefined or null, use defaultValue instead | ||
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; | ||
value = isNil(value) ? defaultValue : value; | ||
var isNonNumericFalsy = !value && value !== 0; | ||
// if value is undefined or null, use defaultValue instead | ||
value = isNil(value) ? defaultValue : value; | ||
if (isNonNumericFalsy && allowEmptyFormatting) { | ||
value = ''; | ||
} // if value is not defined return empty string | ||
var isNonNumericFalsy = !value && value !== 0; | ||
if (isNonNumericFalsy && allowEmptyFormatting) { | ||
value = ''; | ||
} | ||
if (isNonNumericFalsy && !allowEmptyFormatting) return ''; | ||
// if value is not defined return empty string | ||
if (isNonNumericFalsy && !allowEmptyFormatting) { return ''; } | ||
if (typeof value === 'number') { | ||
value = value.toString(); | ||
isNumericString = true; | ||
} //change infinity value to empty string | ||
if (typeof value === 'number') { | ||
value = toNumericString(value); | ||
isNumericString = true; | ||
} | ||
//change infinity value to empty string | ||
if (value === 'Infinity' && isNumericString) { | ||
value = ''; | ||
} | ||
if (value === 'Infinity' && isNumericString) { | ||
value = ''; | ||
} //round the number based on decimalScale | ||
//format only if non formatted value is provided | ||
//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); | ||
if (isNumericString && !format && typeof decimalScale === 'number') { | ||
value = roundToPrecision(value, decimalScale, fixedDecimalScale); | ||
} | ||
return formattedValue; | ||
}; | ||
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value); | ||
return formattedValue; | ||
} | ||
}, { | ||
key: "formatNegation", | ||
value: function formatNegation() { | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var allowNegative = this.props.allowNegative; | ||
var negationRegex = new RegExp('(-)'); | ||
var doubleNegationRegex = new RegExp('(-)(.)*(-)'); // Check number has '-' value | ||
NumberFormat.prototype.formatNegation = function formatNegation (value) { | ||
if ( value === void 0 ) value = ''; | ||
var hasNegation = negationRegex.test(value); // Check number has 2 or more '-' values | ||
var ref = this.props; | ||
var allowNegative = ref.allowNegative; | ||
var negationRegex = new RegExp('(-)'); | ||
var doubleNegationRegex = new RegExp('(-)(.)*(-)'); | ||
var removeNegation = doubleNegationRegex.test(value); //remove negation | ||
// Check number has '-' value | ||
var hasNegation = negationRegex.test(value); | ||
value = value.replace(/-/g, ''); | ||
// Check number has 2 or more '-' values | ||
var removeNegation = doubleNegationRegex.test(value); | ||
if (hasNegation && !removeNegation && allowNegative) { | ||
value = '-' + value; | ||
} | ||
//remove negation | ||
value = value.replace(/-/g, ''); | ||
return value; | ||
if (hasNegation && !removeNegation && allowNegative) { | ||
value = '-' + value; | ||
} | ||
}, { | ||
key: "formatInput", | ||
value: function formatInput() { | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var format = this.props.format; //format negation only if we are formatting as number | ||
if (!format) { | ||
value = this.removePrefixAndSuffix(value); | ||
value = this.formatNegation(value); | ||
} //remove formatting from number | ||
return value; | ||
}; | ||
NumberFormat.prototype.formatInput = function formatInput (value) { | ||
if ( value === void 0 ) value = ''; | ||
value = this.removeFormatting(value); | ||
return this.formatNumString(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); | ||
} | ||
/*** format specific methods end ***/ | ||
}, { | ||
key: "isCharacterAFormat", | ||
value: function isCharacterAFormat(caretPos, value) { | ||
var _this$props10 = this.props, | ||
format = _this$props10.format, | ||
prefix = _this$props10.prefix, | ||
suffix = _this$props10.suffix, | ||
decimalScale = _this$props10.decimalScale, | ||
fixedDecimalScale = _this$props10.fixedDecimalScale; | ||
//remove formatting from number | ||
value = this.removeFormatting(value); | ||
var _this$getSeparators5 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators5.decimalSeparator; //check within format pattern | ||
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; | ||
if (typeof format === 'string' && format[caretPos] !== '#') return true; //check in number format | ||
//check within format pattern | ||
if (typeof format === 'string' && format[caretPos] !== '#') { return true; } | ||
if (!format && (caretPos < prefix.length || caretPos >= value.length - suffix.length || decimalScale && fixedDecimalScale && value[caretPos] === decimalSeparator)) { | ||
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; | ||
return false; | ||
}; | ||
NumberFormat.prototype.checkIfFormatGotDeleted = function checkIfFormatGotDeleted (start , end , value ) { | ||
for (var i = start; i < end; i++) { | ||
if (this.isCharacterAFormat(i, value)) { return true; } | ||
} | ||
}, { | ||
key: "checkIfFormatGotDeleted", | ||
value: function checkIfFormatGotDeleted(start, end, value) { | ||
for (var i = start; i < end; i++) { | ||
if (this.isCharacterAFormat(i, value)) return true; | ||
} | ||
return false; | ||
}; | ||
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 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); | ||
} | ||
/** | ||
* 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 | ||
**/ | ||
}, { | ||
key: "correctInputValue", | ||
value: function correctInputValue(caretPos, lastValue, value) { | ||
var _this$props11 = this.props, | ||
format = _this$props11.format, | ||
allowNegative = _this$props11.allowNegative, | ||
prefix = _this$props11.prefix, | ||
suffix = _this$props11.suffix, | ||
decimalScale = _this$props11.decimalScale; | ||
var _this$getSeparators6 = this.getSeparators(), | ||
allowedDecimalSeparators = _this$getSeparators6.allowedDecimalSeparators, | ||
decimalSeparator = _this$getSeparators6.decimalSeparator; | ||
var leftBound = !!format ? 0 : prefix.length; | ||
var rightBound = lastValue.length - (!!format ? 0 : suffix.length); | ||
var lastNumStr = this.state.numAsString || ''; | ||
var _this$selectionBefore = this.selectionBeforeInput, | ||
selectionStart = _this$selectionBefore.selectionStart, | ||
selectionEnd = _this$selectionBefore.selectionEnd; | ||
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 _findChangedIndex = findChangedIndex(lastValue, value), | ||
start = _findChangedIndex.start, | ||
end = _findChangedIndex.end; | ||
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */ | ||
//if format got deleted reset the value to last value | ||
if (this.checkIfFormatGotDeleted(start, end, lastValue)) { | ||
value = lastValue; | ||
} | ||
//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 | ||
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); | ||
//clear only if something got deleted | ||
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1; | ||
if (numericString.length < lastNumStr.length && isBeforeDecimalPoint && beforeDecimal === '' && !parseFloat(afterDecimal)) { | ||
return addNegation ? '-' : ''; | ||
} | ||
/* don't do anyhting if something got added, | ||
or if value is empty string (when whole input is cleared) | ||
or whole input is replace with a number | ||
*/ | ||
} | ||
return value; | ||
}; | ||
var leftBound = !!format ? 0 : prefix.length; | ||
var rightBound = lastValue.length - (!!format ? 0 : suffix.length); | ||
/** 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 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 (value.length > lastValue.length || !value.length || start === end || selectionStart === 0 && selectionEnd === lastValue.length || start === 0 && end === lastValue.length || selectionStart === leftBound && selectionEnd === rightBound) { | ||
return value; | ||
} //if format got deleted reset the value to last value | ||
if (input) { | ||
//set caret position, and value imperatively when element is provided | ||
if (setCaretPosition) { | ||
//calculate caret position if not defined | ||
if (!caretPos) { | ||
var inputValue = params.inputValue || input.value; | ||
if (this.checkIfFormatGotDeleted(start, end, lastValue)) { | ||
value = lastValue; | ||
} //for numbers check if beforeDecimal got deleted and there is nothing after decimal, | ||
//clear all numbers in such case while keeping the - sign | ||
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; | ||
if (!format) { | ||
var numericString = this.removeFormatting(value); | ||
//get the caret position | ||
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition); | ||
} | ||
var _splitDecimal2 = splitDecimal(numericString, allowNegative), | ||
beforeDecimal = _splitDecimal2.beforeDecimal, | ||
afterDecimal = _splitDecimal2.afterDecimal, | ||
addNegation = _splitDecimal2.addNegation; // eslint-disable-line prefer-const | ||
//clear only if something got deleted | ||
//set caret position | ||
this.setPatchedCaretPosition(input, caretPos, formattedValue); | ||
} else { | ||
/** | ||
* if we are not setting caret position set the value imperatively. | ||
* This is required on onBlur method | ||
*/ | ||
input.value = formattedValue; | ||
} | ||
} | ||
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1; | ||
//calculate numeric string if not passed | ||
if (numAsString === undefined) { | ||
numAsString = this.removeFormatting(formattedValue); | ||
} | ||
if (numericString.length < lastNumStr.length && isBeforeDecimalPoint && beforeDecimal === '' && !parseFloat(afterDecimal)) { | ||
return addNegation ? '-' : ''; | ||
} | ||
} | ||
//update state if value is changed | ||
if (formattedValue !== lastValue) { | ||
this.setState({ value : formattedValue, numAsString: numAsString }); | ||
return value; | ||
// trigger onValueChange synchronously, so parent is updated along with the number format. Fix for #277, #287 | ||
onValueChange(this.getValueObject(formattedValue, numAsString)); | ||
} | ||
/** Update value and caret position */ | ||
}; | ||
}, { | ||
key: "updateValue", | ||
value: function updateValue(params) { | ||
var formattedValue = params.formattedValue, | ||
input = params.input, | ||
_params$setCaretPosit = params.setCaretPosition, | ||
setCaretPosition = _params$setCaretPosit === void 0 ? true : _params$setCaretPosit; | ||
var numAsString = params.numAsString, | ||
caretPos = params.caretPos; | ||
var onValueChange = this.props.onValueChange; | ||
var lastValue = this.state.value; | ||
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 || ''; | ||
if (input) { | ||
//set caret position, and value imperatively when element is provided | ||
if (setCaretPosition) { | ||
//calculate caret position if not defined | ||
if (!caretPos) { | ||
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 | ||
*/ | ||
var currentCaretPosition = getCurrentCaretPosition(el); | ||
input.value = formattedValue; //get the caret position | ||
inputValue = this.correctInputValue(currentCaretPosition, lastValue, inputValue); | ||
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition); | ||
} //set caret position | ||
var formattedValue = this.formatInput(inputValue) || ''; | ||
var numAsString = this.removeFormatting(formattedValue); | ||
var valueObj = this.getValueObject(formattedValue, numAsString); | ||
var isChangeAllowed = isAllowed(valueObj); | ||
this.setPatchedCaretPosition(input, caretPos, formattedValue); | ||
} else { | ||
/** | ||
* if we are not setting caret position set the value imperatively. | ||
* This is required on onBlur method | ||
*/ | ||
input.value = formattedValue; | ||
} | ||
} //calculate numeric string if not passed | ||
if (!isChangeAllowed) { | ||
formattedValue = lastValue; | ||
} | ||
this.updateValue({ formattedValue: formattedValue, numAsString: numAsString, inputValue: inputValue, input: el }); | ||
if (numAsString === undefined) { | ||
numAsString = this.removeFormatting(formattedValue); | ||
} //update state if value is changed | ||
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; | ||
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 | ||
clearTimeout(this.focusTimeout); | ||
onValueChange(this.getValueObject(formattedValue, numAsString)); | ||
if (!format) { | ||
// if the numAsString is not a valid number reset it to empty | ||
if (isNaN(parseFloat(numAsString))) { | ||
numAsString = ''; | ||
} | ||
} | ||
}, { | ||
key: "onChange", | ||
value: function onChange(e) { | ||
var el = e.target; | ||
var inputValue = el.value; | ||
var state = this.state, | ||
props = this.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; | ||
if (!allowLeadingZeros) { | ||
numAsString = fixLeadingZero(numAsString); | ||
} | ||
this.updateValue({ | ||
formattedValue: formattedValue, | ||
numAsString: numAsString, | ||
inputValue: inputValue, | ||
input: el | ||
}); | ||
var formattedValue = this.formatNumString(numAsString); | ||
if (isChangeAllowed) { | ||
props.onChange(e); | ||
//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 }); | ||
onBlur(e); | ||
return; | ||
} | ||
} | ||
}, { | ||
key: "onBlur", | ||
value: function onBlur(e) { | ||
var props = this.props, | ||
state = this.state; | ||
var format = props.format, | ||
onBlur = props.onBlur, | ||
allowLeadingZeros = props.allowLeadingZeros; | ||
var numAsString = state.numAsString; | ||
var lastValue = state.value; | ||
this.focusedElm = null; | ||
clearTimeout(this.focusTimeout); | ||
onBlur(e); | ||
}; | ||
if (!format) { | ||
// if the numAsString is not a valid number reset it to empty | ||
if (isNaN(parseFloat(numAsString))) { | ||
numAsString = ''; | ||
} | ||
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'; | ||
if (!allowLeadingZeros) { | ||
numAsString = fixLeadingZero(numAsString); | ||
} | ||
this.selectionBeforeInput = { | ||
selectionStart: selectionStart, | ||
selectionEnd: selectionEnd | ||
}; | ||
var formattedValue = this.formatNumString(numAsString); //change the state | ||
//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 (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 | ||
}); | ||
onBlur(e); | ||
return; | ||
} | ||
//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}); | ||
} else if (!negativeRegex.test(value[expectedCaretPosition])) { | ||
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound){ newCaretPosition--; } | ||
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left'); | ||
} | ||
} | ||
onBlur(e); | ||
if (newCaretPosition !== expectedCaretPosition || expectedCaretPosition < leftBound || expectedCaretPosition > rightBound) { | ||
e.preventDefault(); | ||
this.setPatchedCaretPosition(el, newCaretPosition, value); | ||
} | ||
}, { | ||
key: "onKeyDown", | ||
value: function onKeyDown(e) { | ||
var el = e.target; | ||
var key = e.key; | ||
var selectionStart = el.selectionStart, | ||
selectionEnd = el.selectionEnd, | ||
_el$value = el.value, | ||
value = _el$value === void 0 ? '' : _el$value; | ||
var expectedCaretPosition; | ||
var _this$props12 = this.props, | ||
decimalScale = _this$props12.decimalScale, | ||
fixedDecimalScale = _this$props12.fixedDecimalScale, | ||
prefix = _this$props12.prefix, | ||
suffix = _this$props12.suffix, | ||
format = _this$props12.format, | ||
onKeyDown = _this$props12.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 | ||
/* 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); | ||
} | ||
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) { | ||
onKeyDown(e); | ||
return; | ||
} | ||
onKeyDown(e); | ||
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 | ||
}); | ||
} else if (!negativeRegex.test(value[expectedCaretPosition])) { | ||
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound) { | ||
newCaretPosition--; | ||
} | ||
/** required to handle the caret position when click anywhere within the input **/ | ||
NumberFormat.prototype.onMouseUp = function onMouseUp (e ) { | ||
var el = e.target; | ||
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left'); | ||
} | ||
} | ||
/** | ||
* 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 (newCaretPosition !== expectedCaretPosition || expectedCaretPosition < leftBound || expectedCaretPosition > rightBound) { | ||
e.preventDefault(); | ||
this.setPatchedCaretPosition(el, newCaretPosition, value); | ||
if (selectionStart === selectionEnd) { | ||
var caretPosition = this.correctCaretPosition(value, selectionStart); | ||
if (caretPosition !== selectionStart) { | ||
this.setPatchedCaretPosition(el, caretPosition, value); | ||
} | ||
/* NOTE: this is just required for unit test as we need to get the newCaretPosition, | ||
Remove this when you find different solution */ | ||
} | ||
this.props.onMouseUp(e); | ||
}; | ||
if (e.isUnitTestRun) { | ||
this.setPatchedCaretPosition(el, newCaretPosition, value); | ||
} | ||
NumberFormat.prototype.onFocus = function onFocus (e ) { | ||
var this$1 = this; | ||
onKeyDown(e); | ||
} | ||
/** required to handle the caret position when click anywhere within the input **/ | ||
// 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(); | ||
}, { | ||
key: "onMouseUp", | ||
value: function onMouseUp(e) { | ||
this.focusedElm = e.target; | ||
this.focusTimeout = setTimeout(function () { | ||
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 = ''; | ||
var selectionStart = el.selectionStart, | ||
selectionEnd = el.selectionEnd, | ||
_el$value2 = el.value, | ||
value = _el$value2 === void 0 ? '' : _el$value2; | ||
var caretPosition = this$1.correctCaretPosition(value, selectionStart); | ||
if (selectionStart === selectionEnd) { | ||
var caretPosition = this.correctCaretPosition(value, selectionStart); | ||
if (caretPosition !== selectionStart) { | ||
this.setPatchedCaretPosition(el, caretPosition, value); | ||
} | ||
//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.props.onMouseUp(e); | ||
} | ||
}, { | ||
key: "onFocus", | ||
value: function onFocus(e) { | ||
var _this2 = this; | ||
this$1.props.onFocus(e); | ||
}, 0); | ||
}; | ||
// 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, | ||
selectionEnd = el.selectionEnd, | ||
_el$value3 = el.value, | ||
value = _el$value3 === void 0 ? '' : _el$value3; | ||
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 ref$1 = this.state; | ||
var value = ref$1.value; | ||
var mounted = ref$1.mounted; | ||
var caretPosition = _this2.correctCaretPosition(value, selectionStart); //setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field) | ||
var otherProps = omit(this.props, propTypes$1); | ||
// add input mode on element based on format prop and device once the component is mounted | ||
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined; | ||
if (caretPosition !== selectionStart && !(selectionStart === 0 && selectionEnd === value.length)) { | ||
_this2.setPatchedCaretPosition(el, caretPosition, value); | ||
} | ||
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 | ||
}); | ||
_this2.props.onFocus(e); | ||
}, 0); | ||
if( displayType === 'text'){ | ||
return renderText ? (renderText(value, otherProps) || null) : React.createElement( 'span', Object.assign({}, otherProps, { ref: getInputRef }), value); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this$props13 = this.props, | ||
type = _this$props13.type, | ||
displayType = _this$props13.displayType, | ||
customInput = _this$props13.customInput, | ||
renderText = _this$props13.renderText, | ||
getInputRef = _this$props13.getInputRef, | ||
format = _this$props13.format; | ||
var _this$state = this.state, | ||
value = _this$state.value, | ||
mounted = _this$state.mounted; | ||
var otherProps = omit(this.props, propTypes$1); // add input mode on element based on format prop and device once the component is mounted | ||
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined; | ||
else if (customInput) { | ||
var CustomInput = customInput; | ||
return ( | ||
React.createElement( CustomInput, Object.assign({}, | ||
inputProps, { ref: getInputRef })) | ||
) | ||
} | ||
var inputProps = _extends({ | ||
inputMode: inputMode | ||
}, otherProps, { | ||
type: type, | ||
value: value, | ||
onChange: this.onChange, | ||
onKeyDown: this.onKeyDown, | ||
onMouseUp: this.onMouseUp, | ||
onFocus: this.onFocus, | ||
onBlur: this.onBlur | ||
}); | ||
return ( | ||
React.createElement( 'input', Object.assign({}, | ||
inputProps, { ref: getInputRef })) | ||
) | ||
}; | ||
if (displayType === 'text') { | ||
return renderText ? renderText(value, otherProps) || null : React.createElement("span", _extends({}, otherProps, { | ||
ref: getInputRef | ||
}), value); | ||
} else if (customInput) { | ||
var CustomInput = customInput; | ||
return React.createElement(CustomInput, _extends({}, inputProps, { | ||
ref: getInputRef | ||
})); | ||
} | ||
return React.createElement("input", _extends({}, inputProps, { | ||
ref: getInputRef | ||
})); | ||
} | ||
}]); | ||
return NumberFormat; | ||
}(React.Component); | ||
}(React.Component)); | ||
@@ -1394,0 +1391,0 @@ NumberFormat.propTypes = propTypes$1; |
/** | ||
* react-number-format - 4.5.3 | ||
* react-number-format - 4.5.4 | ||
* Author : Sudhanshu Yadav | ||
@@ -9,1384 +9,1381 @@ * Copyright (c) 2016, 2021 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)); | ||
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'; | ||
React = React && React.hasOwnProperty('default') ? React['default'] : React; | ||
React = React && React.hasOwnProperty('default') ? React['default'] : React; | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
/** | ||
* Copyright (c) 2013-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
var ReactPropTypesSecret_1 = ReactPropTypesSecret; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
function emptyFunction() {} | ||
function emptyFunctionWithReset() {} | ||
emptyFunctionWithReset.resetWarningCache = emptyFunction; | ||
return target; | ||
}; | ||
var factoryWithThrowingShims = function() { | ||
function shim(props, propName, componentName, location, propFullName, secret) { | ||
if (secret === ReactPropTypesSecret_1) { | ||
// It is still safe when called from React. | ||
return; | ||
} | ||
var err = new Error( | ||
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + | ||
'Use PropTypes.checkPropTypes() to call them. ' + | ||
'Read more at http://fb.me/use-check-prop-types' | ||
); | ||
err.name = 'Invariant Violation'; | ||
throw err; | ||
} shim.isRequired = shim; | ||
function getShim() { | ||
return shim; | ||
} // Important! | ||
// Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. | ||
var ReactPropTypes = { | ||
array: shim, | ||
bool: shim, | ||
func: shim, | ||
number: shim, | ||
object: shim, | ||
string: shim, | ||
symbol: shim, | ||
return _extends.apply(this, arguments); | ||
} | ||
any: shim, | ||
arrayOf: getShim, | ||
element: shim, | ||
elementType: shim, | ||
instanceOf: getShim, | ||
node: shim, | ||
objectOf: getShim, | ||
oneOf: getShim, | ||
oneOfType: getShim, | ||
shape: getShim, | ||
exact: getShim, | ||
function _inherits(subClass, superClass) { | ||
if (typeof superClass !== "function" && superClass !== null) { | ||
throw new TypeError("Super expression must either be null or a function"); | ||
} | ||
checkPropTypes: emptyFunctionWithReset, | ||
resetWarningCache: emptyFunction | ||
}; | ||
subClass.prototype = Object.create(superClass && superClass.prototype, { | ||
constructor: { | ||
value: subClass, | ||
writable: true, | ||
configurable: true | ||
} | ||
}); | ||
if (superClass) _setPrototypeOf(subClass, superClass); | ||
} | ||
ReactPropTypes.PropTypes = ReactPropTypes; | ||
function _getPrototypeOf(o) { | ||
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { | ||
return o.__proto__ || Object.getPrototypeOf(o); | ||
}; | ||
return _getPrototypeOf(o); | ||
} | ||
return ReactPropTypes; | ||
}; | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
var propTypes = createCommonjsModule(function (module) { | ||
/** | ||
* Copyright (c) 2013-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
return _setPrototypeOf(o, p); | ||
} | ||
{ | ||
// By explicitly using `prop-types` you are opting into new production behavior. | ||
// http://fb.me/prop-types-in-prod | ||
module.exports = factoryWithThrowingShims(); | ||
} | ||
}); | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
} | ||
// | ||
return self; | ||
} | ||
function _possibleConstructorReturn(self, call) { | ||
if (call && (typeof call === "object" || typeof call === "function")) { | ||
return call; | ||
} | ||
// basic noop function | ||
function noop() {} | ||
function returnTrue() { | ||
return true; | ||
} | ||
return _assertThisInitialized(self); | ||
} | ||
function charIsNumber(char ) { | ||
return !!(char || '').match(/\d/); | ||
} | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
function isNil(val ) { | ||
return val === null || val === undefined; | ||
} | ||
/** | ||
* Copyright (c) 2013-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
function escapeRegExp(str ) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; | ||
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; | ||
} | ||
} | ||
var ReactPropTypesSecret_1 = ReactPropTypesSecret; | ||
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 emptyFunction() {} | ||
function emptyFunctionWithReset() {} | ||
emptyFunctionWithReset.resetWarningCache = emptyFunction; | ||
//spilt a float number into different parts beforeDecimal, afterDecimal, and negation | ||
function splitDecimal(numStr , allowNegative) { | ||
if ( allowNegative === void 0 ) allowNegative = true; | ||
var factoryWithThrowingShims = function() { | ||
function shim(props, propName, componentName, location, propFullName, secret) { | ||
if (secret === ReactPropTypesSecret_1) { | ||
// It is still safe when called from React. | ||
return; | ||
} | ||
var err = new Error( | ||
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + | ||
'Use PropTypes.checkPropTypes() to call them. ' + | ||
'Read more at http://fb.me/use-check-prop-types' | ||
); | ||
err.name = 'Invariant Violation'; | ||
throw err; | ||
} shim.isRequired = shim; | ||
function getShim() { | ||
return shim; | ||
} // Important! | ||
// Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. | ||
var ReactPropTypes = { | ||
array: shim, | ||
bool: shim, | ||
func: shim, | ||
number: shim, | ||
object: shim, | ||
string: shim, | ||
symbol: shim, | ||
var hasNagation = numStr[0] === '-'; | ||
var addNegation = hasNagation && allowNegative; | ||
numStr = numStr.replace('-', ''); | ||
any: shim, | ||
arrayOf: getShim, | ||
element: shim, | ||
elementType: shim, | ||
instanceOf: getShim, | ||
node: shim, | ||
objectOf: getShim, | ||
oneOf: getShim, | ||
oneOfType: getShim, | ||
shape: getShim, | ||
exact: getShim, | ||
var parts = numStr.split('.'); | ||
var beforeDecimal = parts[0]; | ||
var afterDecimal = parts[1] || ''; | ||
checkPropTypes: emptyFunctionWithReset, | ||
resetWarningCache: emptyFunction | ||
}; | ||
return { | ||
beforeDecimal: beforeDecimal, | ||
afterDecimal: afterDecimal, | ||
hasNagation: hasNagation, | ||
addNegation: addNegation, | ||
}; | ||
} | ||
ReactPropTypes.PropTypes = ReactPropTypes; | ||
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 ReactPropTypes; | ||
}; | ||
return ("" + (isNegative ? '-' : '') + beforeDecimal + (afterDecimal ? ("." + afterDecimal) : '')); | ||
} | ||
var propTypes = createCommonjsModule(function (module) { | ||
/** | ||
* Copyright (c) 2013-present, Facebook, Inc. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
/** | ||
* 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; | ||
} | ||
return str; | ||
} | ||
{ | ||
// By explicitly using `prop-types` you are opting into new production behavior. | ||
// http://fb.me/prop-types-in-prod | ||
module.exports = factoryWithThrowingShims(); | ||
} | ||
}); | ||
function repeat(str, count) { | ||
return Array(count + 1).join(str) | ||
} | ||
// basic noop function | ||
function noop() {} | ||
function returnTrue() { | ||
return true; | ||
} | ||
function charIsNumber(_char) { | ||
return !!(_char || '').match(/\d/); | ||
} | ||
function isNil(val) { | ||
return val === null || val === undefined; | ||
} | ||
function escapeRegExp(str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); | ||
} | ||
function getThousandsGroupRegex(thousandsGroupStyle) { | ||
switch (thousandsGroupStyle) { | ||
case 'lakh': | ||
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g; | ||
function toNumericString(num) { | ||
num += ''; // typecast number to string | ||
case 'wan': | ||
return /(\d)(?=(\d{4})+(?!\d))/g; | ||
// store the sign and remove it from the number. | ||
var sign = num[0] === '-' ? '-' : ''; | ||
if (sign) { num = num.substring(1); } | ||
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); | ||
} //spilt a float number into different parts beforeDecimal, afterDecimal, and negation | ||
// split the number into cofficient and exponent | ||
var ref = num.split(/[eE]/g); | ||
var coefficient = ref[0]; | ||
var exponent = ref[1]; | ||
function splitDecimal(numStr) { | ||
var allowNegative = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 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 "".concat(isNegative ? '-' : '').concat(beforeDecimal).concat(afterDecimal ? ".".concat(afterDecimal) : ''); | ||
} | ||
/** | ||
* limit decimal numbers to given scale | ||
* Not used .fixedTo because that will break with big numbers | ||
*/ | ||
// covert exponent to number; | ||
exponent = Number(exponent); | ||
function limitToScale(numStr, scale, fixedDecimalScale) { | ||
var str = ''; | ||
var filler = fixedDecimalScale ? '0' : ''; | ||
// if there is no exponent part or its 0, return the coffiecient with sign | ||
if (!exponent) { return sign + coefficient; } | ||
for (var i = 0; i <= scale - 1; i++) { | ||
str += numStr[i] || filler; | ||
} | ||
coefficient = coefficient.replace('.', ''); | ||
return str; | ||
} | ||
/** | ||
* This method is required to round prop value to given scale. | ||
* Not used .round or .fixedTo because that will break with big numbers | ||
*/ | ||
/** | ||
* 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; | ||
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 coffiecientLn = coefficient.length; | ||
var _splitDecimal = splitDecimal(numStr), | ||
beforeDecimal = _splitDecimal.beforeDecimal, | ||
afterDecimal = _splitDecimal.afterDecimal, | ||
hasNagation = _splitDecimal.hasNagation; | ||
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); | ||
} | ||
var floatValue = parseFloat("0.".concat(afterDecimal || '0')); | ||
var floatValueStr = afterDecimal.length <= scale ? floatValue.toString() : 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 sign + coefficient; | ||
} | ||
return current + roundedStr; | ||
}, roundedDecimalParts[0]); | ||
var decimalPart = limitToScale(roundedDecimalParts[1] || '', Math.min(scale, afterDecimal.length), fixedDecimalScale); | ||
var negation = hasNagation ? '-' : ''; | ||
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : ''; | ||
return "".concat(negation).concat(intPart).concat(decimalSeparator).concat(decimalPart); | ||
} | ||
function omit(obj, keyMaps) { | ||
var filteredObj = {}; | ||
Object.keys(obj).forEach(function (key) { | ||
if (!keyMaps[key]) filteredObj[key] = obj[key]; | ||
}); | ||
return filteredObj; | ||
} | ||
/** set the caret positon in an input field **/ | ||
/** | ||
* 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; } | ||
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) | ||
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 ? toNumericString(floatValue) : 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]); | ||
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) | ||
var decimalPart = limitToScale( | ||
roundedDecimalParts[1] || '', | ||
Math.min(scale, afterDecimal.length), | ||
fixedDecimalScale | ||
); | ||
var negation = hasNagation ? '-' : ''; | ||
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : ''; | ||
return ("" + negation + intPart + decimalSeparator + decimalPart); | ||
} | ||
function omit(obj , keyMaps ) { | ||
var filteredObj = {}; | ||
Object.keys(obj).forEach(function (key) { | ||
if (!keyMaps[key]) { filteredObj[key] = obj[key]; } | ||
}); | ||
return filteredObj; | ||
} | ||
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) :) | ||
/** 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; | ||
} | ||
} | ||
el.focus(); | ||
return false; | ||
} | ||
} | ||
/** | ||
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. | ||
*/ | ||
/** | ||
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++; } | ||
function findChangedIndex(prevValue, newValue) { | ||
var i = 0, | ||
j = 0; | ||
var prevLength = prevValue.length; | ||
var newLength = newValue.length; | ||
//check what has been changed from last | ||
while ( | ||
prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] && | ||
newLength - j > i && | ||
prevLength - j > i | ||
) { | ||
j++; | ||
} | ||
while (prevValue[i] === newValue[i] && i < prevLength) { | ||
i++; | ||
} //check what has been changed from last | ||
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); | ||
} | ||
while (prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] && newLength - j > i && prevLength - j > i) { | ||
j++; | ||
} | ||
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); | ||
} | ||
return { | ||
start: i, | ||
end: prevLength - j | ||
}; | ||
} | ||
/* | ||
Returns a number whose value is limited to the given range | ||
*/ | ||
function addInputMode(format ) { | ||
return format || !(navigator.platform && /iPhone|iPod/.test(navigator.platform)); | ||
} | ||
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 || !(navigator.platform && /iPhone|iPod/.test(navigator.platform)); | ||
} | ||
// | ||
var propTypes$1 = { | ||
thousandSeparator: propTypes.oneOfType([propTypes.string, propTypes.oneOf([true])]), | ||
decimalSeparator: propTypes.string, | ||
allowedDecimalSeparators: propTypes.arrayOf(propTypes.string), | ||
thousandsGroupStyle: propTypes.oneOf(['thousand', 'lakh', 'wan']), | ||
decimalScale: propTypes.number, | ||
fixedDecimalScale: propTypes.bool, | ||
displayType: propTypes.oneOf(['input', 'text']), | ||
prefix: propTypes.string, | ||
suffix: propTypes.string, | ||
format: propTypes.oneOfType([propTypes.string, propTypes.func]), | ||
removeFormatting: propTypes.func, | ||
mask: propTypes.oneOfType([propTypes.string, propTypes.arrayOf(propTypes.string)]), | ||
value: propTypes.oneOfType([propTypes.number, propTypes.string]), | ||
defaultValue: propTypes.oneOfType([propTypes.number, propTypes.string]), | ||
isNumericString: propTypes.bool, | ||
customInput: propTypes.elementType, | ||
allowNegative: propTypes.bool, | ||
allowEmptyFormatting: propTypes.bool, | ||
allowLeadingZeros: propTypes.bool, | ||
onValueChange: propTypes.func, | ||
onKeyDown: propTypes.func, | ||
onMouseUp: propTypes.func, | ||
onChange: propTypes.func, | ||
onFocus: propTypes.func, | ||
onBlur: propTypes.func, | ||
type: propTypes.oneOf(['text', 'tel', 'password']), | ||
isAllowed: propTypes.func, | ||
renderText: propTypes.func, | ||
getInputRef: propTypes.oneOfType([propTypes.func, // for legacy refs | ||
propTypes.shape({ | ||
current: propTypes.any | ||
})]) | ||
}; | ||
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 (_React$Component) { | ||
_inherits(NumberFormat, _React$Component); | ||
var propTypes$1 = { | ||
thousandSeparator: propTypes.oneOfType([propTypes.string, propTypes.oneOf([true])]), | ||
decimalSeparator: propTypes.string, | ||
allowedDecimalSeparators: propTypes.arrayOf(propTypes.string), | ||
thousandsGroupStyle: propTypes.oneOf(['thousand', 'lakh', 'wan']), | ||
decimalScale: propTypes.number, | ||
fixedDecimalScale: propTypes.bool, | ||
displayType: propTypes.oneOf(['input', 'text']), | ||
prefix: propTypes.string, | ||
suffix: propTypes.string, | ||
format: propTypes.oneOfType([ | ||
propTypes.string, | ||
propTypes.func | ||
]), | ||
removeFormatting: propTypes.func, | ||
mask: propTypes.oneOfType([propTypes.string, propTypes.arrayOf(propTypes.string)]), | ||
value: propTypes.oneOfType([ | ||
propTypes.number, | ||
propTypes.string | ||
]), | ||
defaultValue: propTypes.oneOfType([ | ||
propTypes.number, | ||
propTypes.string | ||
]), | ||
isNumericString: propTypes.bool, | ||
customInput: propTypes.elementType, | ||
allowNegative: propTypes.bool, | ||
allowEmptyFormatting: propTypes.bool, | ||
allowLeadingZeros: propTypes.bool, | ||
onValueChange: propTypes.func, | ||
onKeyDown: propTypes.func, | ||
onMouseUp: propTypes.func, | ||
onChange: propTypes.func, | ||
onFocus: propTypes.func, | ||
onBlur: propTypes.func, | ||
type: propTypes.oneOf(['text', 'tel', 'password']), | ||
isAllowed: propTypes.func, | ||
renderText: propTypes.func, | ||
getInputRef: propTypes.oneOfType([ | ||
propTypes.func, // for legacy refs | ||
propTypes.shape({ current: propTypes.any }) | ||
]) | ||
}; | ||
function NumberFormat(props) { | ||
var _this; | ||
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); | ||
_classCallCheck(this, NumberFormat); | ||
var defaultValue = props.defaultValue; | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(NumberFormat).call(this, props)); | ||
var defaultValue = props.defaultValue; //validate props | ||
//validate props | ||
this.validateProps(); | ||
_this.validateProps(); | ||
var formattedValue = this.formatValueProp(defaultValue); | ||
var formattedValue = _this.formatValueProp(defaultValue); | ||
this.state = { | ||
value: formattedValue, | ||
numAsString: this.removeFormatting(formattedValue), | ||
mounted: false, | ||
}; | ||
_this.state = { | ||
value: formattedValue, | ||
numAsString: _this.removeFormatting(formattedValue), | ||
mounted: false | ||
}; | ||
_this.selectionBeforeInput = { | ||
selectionStart: 0, | ||
selectionEnd: 0 | ||
}; | ||
_this.onChange = _this.onChange.bind(_assertThisInitialized(_this)); | ||
_this.onKeyDown = _this.onKeyDown.bind(_assertThisInitialized(_this)); | ||
_this.onMouseUp = _this.onMouseUp.bind(_assertThisInitialized(_this)); | ||
_this.onFocus = _this.onFocus.bind(_assertThisInitialized(_this)); | ||
_this.onBlur = _this.onBlur.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
} | ||
this.selectionBeforeInput = { | ||
selectionStart: 0, | ||
selectionEnd: 0 | ||
}; | ||
_createClass(NumberFormat, [{ | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
// set mounted state | ||
// eslint-disable-next-line react/no-did-mount-set-state | ||
this.setState({ | ||
mounted: true | ||
}); | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate(prevProps) { | ||
this.updateValueIfRequired(prevProps); | ||
} | ||
}, { | ||
key: "componentWillUnmount", | ||
value: function componentWillUnmount() { | ||
clearTimeout(this.focusTimeout); | ||
} | ||
}, { | ||
key: "updateValueIfRequired", | ||
value: function updateValueIfRequired(prevProps) { | ||
var props = this.props, | ||
state = this.state, | ||
focusedElm = this.focusedElm; | ||
var stateValue = state.value, | ||
_state$numAsString = state.numAsString, | ||
lastNumStr = _state$numAsString === void 0 ? '' : _state$numAsString; // If only state changed no need to do any thing | ||
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 (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 ( superclass ) NumberFormat.__proto__ = superclass; | ||
NumberFormat.prototype = Object.create( superclass && superclass.prototype ); | ||
NumberFormat.prototype.constructor = NumberFormat; | ||
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 | ||
}); | ||
} | ||
} | ||
} | ||
/** Misc methods **/ | ||
NumberFormat.prototype.componentDidMount = function componentDidMount () { | ||
// set mounted state | ||
// eslint-disable-next-line react/no-did-mount-set-state | ||
this.setState({ | ||
mounted: true | ||
}); | ||
}; | ||
}, { | ||
key: "getFloatString", | ||
value: function getFloatString() { | ||
var num = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var decimalScale = this.props.decimalScale; | ||
NumberFormat.prototype.componentDidUpdate = function componentDidUpdate (prevProps ) { | ||
this.updateValueIfRequired(prevProps); | ||
}; | ||
var _this$getSeparators = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators.decimalSeparator; | ||
NumberFormat.prototype.componentWillUnmount = function componentWillUnmount () { | ||
clearTimeout(this.focusTimeout); | ||
}; | ||
var numRegex = this.getNumberRegex(true); //remove negation for regex check | ||
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 = ''; | ||
var hasNegation = num[0] === '-'; | ||
if (hasNegation) num = num.replace('-', ''); //if decimal scale is zero remove decimal and number after decimalSeparator | ||
// If only state changed no need to do any thing | ||
if(prevProps !== props) { | ||
//validate props | ||
this.validateProps(); | ||
if (decimalSeparator && decimalScale === 0) { | ||
num = num.split(decimalSeparator)[0]; | ||
} | ||
var lastValueWithNewFormat = this.formatNumString(lastNumStr); | ||
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.'); //remove extra decimals | ||
var formattedValue = isNil(props.value) ? lastValueWithNewFormat : this.formatValueProp(); | ||
var numAsString = this.removeFormatting(formattedValue); | ||
var firstDecimalIndex = num.indexOf('.'); | ||
var floatValue = parseFloat(numAsString); | ||
var lastFloatValue = parseFloat(lastNumStr); | ||
if (firstDecimalIndex !== -1) { | ||
num = "".concat(num.substring(0, firstDecimalIndex), ".").concat(num.substring(firstDecimalIndex + 1, num.length).replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), '')); | ||
} //add negation back | ||
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 }); | ||
} | ||
} | ||
}; | ||
/** Misc methods **/ | ||
NumberFormat.prototype.getFloatString = function getFloatString (num) { | ||
if ( num === void 0 ) num = ''; | ||
if (hasNegation) num = '-' + num; | ||
return num; | ||
} //returned regex assumes decimalSeparator is as per prop | ||
var ref = this.props; | ||
var decimalScale = ref.decimalScale; | ||
var ref$1 = this.getSeparators(); | ||
var decimalSeparator = ref$1.decimalSeparator; | ||
var numRegex = this.getNumberRegex(true); | ||
}, { | ||
key: "getNumberRegex", | ||
value: function getNumberRegex(g, ignoreDecimalSeparator) { | ||
var _this$props = this.props, | ||
format = _this$props.format, | ||
decimalScale = _this$props.decimalScale; | ||
//remove negation for regex check | ||
var hasNegation = num[0] === '-'; | ||
if(hasNegation) { num = num.replace('-', ''); } | ||
var _this$getSeparators2 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators2.decimalSeparator; | ||
//if decimal scale is zero remove decimal and number after decimalSeparator | ||
if (decimalSeparator && decimalScale === 0) { | ||
num = num.split(decimalSeparator)[0]; | ||
} | ||
return new RegExp('\\d' + (decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined); | ||
} | ||
}, { | ||
key: "getSeparators", | ||
value: function getSeparators() { | ||
var decimalSeparator = this.props.decimalSeparator; | ||
var _this$props2 = this.props, | ||
thousandSeparator = _this$props2.thousandSeparator, | ||
allowedDecimalSeparators = _this$props2.allowedDecimalSeparators; | ||
num = (num.match(numRegex) || []).join('').replace(decimalSeparator, '.'); | ||
if (thousandSeparator === true) { | ||
thousandSeparator = ','; | ||
} | ||
//remove extra decimals | ||
var firstDecimalIndex = num.indexOf('.'); | ||
if (!allowedDecimalSeparators) { | ||
allowedDecimalSeparators = [decimalSeparator, '.']; | ||
} | ||
if (firstDecimalIndex !== -1) { | ||
num = (num.substring(0, firstDecimalIndex)) + "." + (num.substring(firstDecimalIndex + 1, num.length).replace(new RegExp(escapeRegExp(decimalSeparator), 'g'), '')); | ||
} | ||
return { | ||
decimalSeparator: decimalSeparator, | ||
thousandSeparator: thousandSeparator, | ||
allowedDecimalSeparators: allowedDecimalSeparators | ||
}; | ||
} | ||
}, { | ||
key: "getMaskAtIndex", | ||
value: function getMaskAtIndex(index) { | ||
var _this$props$mask = this.props.mask, | ||
mask = _this$props$mask === void 0 ? ' ' : _this$props$mask; | ||
//add negation back | ||
if(hasNegation) { num = '-' + num; } | ||
if (typeof mask === 'string') { | ||
return mask; | ||
} | ||
return num; | ||
}; | ||
return mask[index] || ' '; | ||
} | ||
}, { | ||
key: "getValueObject", | ||
value: function getValueObject(formattedValue, numAsString) { | ||
var floatValue = parseFloat(numAsString); | ||
return { | ||
formattedValue: formattedValue, | ||
value: numAsString, | ||
floatValue: isNaN(floatValue) ? undefined : floatValue | ||
}; | ||
} | ||
}, { | ||
key: "validateProps", | ||
value: function validateProps() { | ||
var mask = this.props.mask; //validate decimalSeparator and thousandSeparator | ||
//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 ref$1 = this.getSeparators(); | ||
var decimalSeparator = ref$1.decimalSeparator; | ||
return new RegExp('\\d' + (decimalSeparator && decimalScale !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined); | ||
}; | ||
var _this$getSeparators3 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators3.decimalSeparator, | ||
thousandSeparator = _this$getSeparators3.thousandSeparator; | ||
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 (decimalSeparator === thousandSeparator) { | ||
throw new Error("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: ".concat(thousandSeparator, " (thousandSeparator = {true} is same as thousandSeparator = \",\")\n decimalSeparator: ").concat(decimalSeparator, " (default value for decimalSeparator is .)\n ")); | ||
} //validate mask | ||
if (thousandSeparator === true) { | ||
thousandSeparator = ','; | ||
} | ||
if (!allowedDecimalSeparators) { | ||
allowedDecimalSeparators = [decimalSeparator, '.']; | ||
} | ||
return { | ||
decimalSeparator: decimalSeparator, | ||
thousandSeparator: thousandSeparator, | ||
allowedDecimalSeparators: allowedDecimalSeparators, | ||
} | ||
}; | ||
if (mask) { | ||
var maskAsStr = mask === 'string' ? mask : mask.toString(); | ||
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; | ||
} | ||
if (maskAsStr.match(/\d/g)) { | ||
throw new Error("\n Mask ".concat(mask, " should not contain numeric character;\n ")); | ||
} | ||
} | ||
} | ||
/** Misc methods end **/ | ||
return mask[index] || ' '; | ||
}; | ||
/** caret specific methods **/ | ||
NumberFormat.prototype.getValueObject = function getValueObject (formattedValue , numAsString ) { | ||
var floatValue = parseFloat(numAsString); | ||
}, { | ||
key: "setPatchedCaretPosition", | ||
value: 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); | ||
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 */ | ||
return { | ||
formattedValue: formattedValue, | ||
value: numAsString, | ||
floatValue: isNaN(floatValue) ? undefined : floatValue | ||
}; | ||
}, { | ||
key: "correctCaretPosition", | ||
value: function correctCaretPosition(value, caretPos, direction) { | ||
var _this$props3 = this.props, | ||
prefix = _this$props3.prefix, | ||
suffix = _this$props3.suffix, | ||
format = _this$props3.format; //if value is empty return 0 | ||
}; | ||
if (value === '') return 0; //caret position should be between 0 and value length | ||
NumberFormat.prototype.validateProps = function validateProps () { | ||
var ref = this.props; | ||
var mask = ref.mask; | ||
caretPos = clamp(caretPos, 0, value.length); //in case of format as number limit between prefix and suffix | ||
//validate decimalSeparator and thousandSeparator | ||
var ref$1 = this.getSeparators(); | ||
var decimalSeparator = ref$1.decimalSeparator; | ||
var thousandSeparator = ref$1.thousandSeparator; | ||
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 (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 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 | ||
}; | ||
/** Misc methods end **/ | ||
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) return caretPos; //if caretPos is just after input value don't do anything | ||
/** 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); | ||
setTimeout(function () { | ||
if(el.value === currentValue) { setCaretPosition(el, caretPos); } | ||
}, 0); | ||
}; | ||
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) return caretPos; //find the nearest caret position | ||
/* 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; | ||
var firstHashPosition = format.indexOf('#'); | ||
var lastHashPosition = format.lastIndexOf('#'); //limit the cursor between the first # position and the last # position | ||
//if value is empty return 0 | ||
if (value === '') { return 0; } | ||
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 | ||
//caret position should be between 0 and value length | ||
caretPos = clamp(caretPos, 0, value.length); | ||
while (caretLeftBound > firstHashPosition && (format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))) { | ||
caretLeftBound -= 1; | ||
} | ||
//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); | ||
} | ||
var goToLeft = !charIsNumber(value[caretRightBound]) || direction === 'left' && caretPos !== firstHashPosition || caretPos - caretLeftBound < caretRightBound - caretPos; | ||
//in case if custom format method don't do anything | ||
if (typeof format === 'function') { return 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; | ||
} | ||
/* in case format is string find the closest # position from the caret position */ | ||
return caretRightBound; | ||
} | ||
}, { | ||
key: "getCaretPosition", | ||
value: function getCaretPosition(inputValue, formattedValue, caretPos) { | ||
var format = this.props.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; | ||
//in case the caretPos have input value on it don't do anything | ||
if (format[caretPos] === '#' && charIsNumber(value[caretPos])) { return caretPos; } | ||
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 caretPos is just after input value don't do anything | ||
if (format[caretPos - 1] === '#' && charIsNumber(value[caretPos - 1])) { return caretPos; } | ||
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; | ||
//find the nearest caret position | ||
var firstHashPosition = format.indexOf('#'); | ||
var lastHashPosition = format.lastIndexOf('#'); | ||
if (currentInputChar === '0' && currentFormatChar.match(numRegex) && currentFormatChar !== '0' && inputNumber.length !== formattedNumber.length) continue; //we are not using currentFormatChar because j can change here | ||
//limit the cursor between the first # position and the last # position | ||
caretPos = clamp(caretPos, firstHashPosition, lastHashPosition + 1); | ||
while (currentInputChar !== formattedValue[j] && j < formattedValue.length) { | ||
j++; | ||
} | ||
var nextPos = format.substring(caretPos, format.length).indexOf('#'); | ||
var caretLeftBound = caretPos; | ||
var caretRightBound = caretPos + (nextPos === -1 ? 0 : nextPos); | ||
j++; | ||
} | ||
//get the position where the last number is present | ||
while (caretLeftBound > firstHashPosition && (format[caretLeftBound] !== '#' || !charIsNumber(value[caretLeftBound]))) { | ||
caretLeftBound -= 1; | ||
} | ||
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 | ||
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; | ||
} | ||
j = this.correctCaretPosition(formattedValue, j); | ||
return j; | ||
} | ||
/** caret specific methods ends **/ | ||
return caretRightBound; | ||
}; | ||
/** methods to remove formattting **/ | ||
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; | ||
}, { | ||
key: "removePrefixAndSuffix", | ||
value: function removePrefixAndSuffix(val) { | ||
var _this$props4 = this.props, | ||
format = _this$props4.format, | ||
prefix = _this$props4.prefix, | ||
suffix = _this$props4.suffix; //remove prefix and suffix | ||
j = 0; | ||
if (!format && val) { | ||
var isNegative = val[0] === '-'; //remove negation sign | ||
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; } | ||
if (isNegative) val = val.substring(1, val.length); //remove prefix | ||
//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; } | ||
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val; //remove suffix | ||
//we are not using currentFormatChar because j can change here | ||
while(currentInputChar !== formattedValue[j] && j < formattedValue.length) { j++; } | ||
j++; | ||
} | ||
var suffixLastIndex = val.lastIndexOf(suffix); | ||
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val; //add negation sign back | ||
if ((typeof format === 'string' && !stateValue)) { | ||
//set it to the maximum value so it goes after the last number | ||
j = formattedValue.length; | ||
} | ||
if (isNegative) val = '-' + val; | ||
} | ||
//correct caret position if its outside of editable area | ||
j = this.correctCaretPosition(formattedValue, j); | ||
return val; | ||
} | ||
}, { | ||
key: "removePatternFormatting", | ||
value: function removePatternFormatting(val) { | ||
var format = this.props.format; | ||
var formatArray = format.split('#').filter(function (str) { | ||
return str !== ''; | ||
}); | ||
var start = 0; | ||
var numStr = ''; | ||
return j; | ||
}; | ||
/** caret specific methods ends **/ | ||
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 */ | ||
/** 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; | ||
if (index === -1) { | ||
numStr = val; | ||
break; | ||
} else { | ||
numStr += val.substring(start, index); | ||
start = index + part.length; | ||
} | ||
} | ||
//remove prefix and suffix | ||
if (!format && val) { | ||
var isNegative = val[0] === '-'; | ||
return (numStr.match(/\d/g) || []).join(''); | ||
} | ||
}, { | ||
key: "removeFormatting", | ||
value: function removeFormatting(val) { | ||
var _this$props5 = this.props, | ||
format = _this$props5.format, | ||
removeFormatting = _this$props5.removeFormatting; | ||
if (!val) return val; | ||
//remove negation sign | ||
if (isNegative) { val = val.substring(1, val.length); } | ||
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(/\d/g) || []).join(''); | ||
} | ||
//remove prefix | ||
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val; | ||
return val; | ||
} | ||
/** methods to remove formattting end **/ | ||
//remove suffix | ||
var suffixLastIndex = val.lastIndexOf(suffix); | ||
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val; | ||
/*** format specific methods start ***/ | ||
//add negation sign back | ||
if (isNegative) { val = '-' + val; } | ||
} | ||
/** | ||
* Format when # based string is provided | ||
* @param {string} numStr Numeric String | ||
* @return {string} formatted Value | ||
*/ | ||
return val; | ||
}; | ||
}, { | ||
key: "formatWithPattern", | ||
value: function formatWithPattern(numStr) { | ||
var format = this.props.format; | ||
var hashCount = 0; | ||
var formattedNumberAry = format.split(''); | ||
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 = format.length; i < ln; i++) { | ||
if (format[i] === '#') { | ||
formattedNumberAry[i] = numStr[hashCount] || this.getMaskAtIndex(hashCount); | ||
hashCount += 1; | ||
} | ||
} | ||
for (var i=0, ln=formatArray.length; i <= ln; i++) { | ||
var part = formatArray[i] || ''; | ||
return formattedNumberAry.join(''); | ||
} | ||
/** | ||
* @param {string} numStr Numeric string/floatString] It always have decimalSeparator as . | ||
* @return {string} formatted Value | ||
*/ | ||
//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); | ||
}, { | ||
key: "formatAsNumber", | ||
value: function formatAsNumber(numStr) { | ||
var _this$props6 = this.props, | ||
decimalScale = _this$props6.decimalScale, | ||
fixedDecimalScale = _this$props6.fixedDecimalScale, | ||
prefix = _this$props6.prefix, | ||
suffix = _this$props6.suffix, | ||
allowNegative = _this$props6.allowNegative, | ||
thousandsGroupStyle = _this$props6.thousandsGroupStyle; | ||
/* 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; | ||
} | ||
} | ||
var _this$getSeparators4 = this.getSeparators(), | ||
thousandSeparator = _this$getSeparators4.thousandSeparator, | ||
decimalSeparator = _this$getSeparators4.decimalSeparator; | ||
return (numStr.match(/\d/g) || []).join(''); | ||
}; | ||
var hasDecimalSeparator = numStr.indexOf('.') !== -1 || decimalScale && fixedDecimalScale; | ||
NumberFormat.prototype.removeFormatting = function removeFormatting (val ) { | ||
var ref = this.props; | ||
var format = ref.format; | ||
var removeFormatting = ref.removeFormatting; | ||
if (!val) { return val; } | ||
var _splitDecimal = splitDecimal(numStr, allowNegative), | ||
beforeDecimal = _splitDecimal.beforeDecimal, | ||
afterDecimal = _splitDecimal.afterDecimal, | ||
addNegation = _splitDecimal.addNegation; // eslint-disable-line prefer-const | ||
//apply decimal precision if its defined | ||
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(/\d/g) || []).join(''); | ||
} | ||
return val; | ||
}; | ||
/** methods to remove formattting end **/ | ||
if (decimalScale !== undefined) afterDecimal = limitToScale(afterDecimal, decimalScale, fixedDecimalScale); | ||
/*** 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; | ||
if (thousandSeparator) { | ||
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle); | ||
} //add prefix and suffix | ||
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 (prefix) beforeDecimal = prefix + beforeDecimal; | ||
if (suffix) afterDecimal = afterDecimal + suffix; //restore negation sign | ||
if(thousandSeparator) { | ||
beforeDecimal = applyThousandSeparator(beforeDecimal, thousandSeparator, thousandsGroupStyle); | ||
} | ||
if (addNegation) beforeDecimal = '-' + beforeDecimal; | ||
numStr = beforeDecimal + (hasDecimalSeparator && decimalSeparator || '') + afterDecimal; | ||
return numStr; | ||
} | ||
}, { | ||
key: "formatNumString", | ||
value: function formatNumString() { | ||
var numStr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var _this$props7 = this.props, | ||
format = _this$props7.format, | ||
allowEmptyFormatting = _this$props7.allowEmptyFormatting; | ||
var formattedValue = numStr; | ||
//add prefix and suffix | ||
if(prefix) { beforeDecimal = prefix + beforeDecimal; } | ||
if(suffix) { afterDecimal = afterDecimal + suffix; } | ||
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); | ||
} | ||
//restore negation sign | ||
if (addNegation) { beforeDecimal = '-' + beforeDecimal; } | ||
return formattedValue; | ||
} | ||
}, { | ||
key: "formatValueProp", | ||
value: function formatValueProp(defaultValue) { | ||
var _this$props8 = this.props, | ||
format = _this$props8.format, | ||
decimalScale = _this$props8.decimalScale, | ||
fixedDecimalScale = _this$props8.fixedDecimalScale, | ||
allowEmptyFormatting = _this$props8.allowEmptyFormatting; | ||
var _this$props9 = this.props, | ||
value = _this$props9.value, | ||
isNumericString = _this$props9.isNumericString; // if value is undefined or null, use defaultValue instead | ||
numStr = beforeDecimal + (hasDecimalSeparator && decimalSeparator || '') + afterDecimal; | ||
value = isNil(value) ? defaultValue : value; | ||
var isNonNumericFalsy = !value && value !== 0; | ||
return numStr; | ||
}; | ||
if (isNonNumericFalsy && allowEmptyFormatting) { | ||
value = ''; | ||
} // if value is not defined return empty string | ||
NumberFormat.prototype.formatNumString = function formatNumString (numStr) { | ||
if ( numStr === void 0 ) numStr = ''; | ||
var ref = this.props; | ||
var format = ref.format; | ||
var allowEmptyFormatting = ref.allowEmptyFormatting; | ||
var formattedValue = numStr; | ||
if (isNonNumericFalsy && !allowEmptyFormatting) return ''; | ||
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 (typeof value === 'number') { | ||
value = value.toString(); | ||
isNumericString = true; | ||
} //change infinity value to empty string | ||
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 === 'Infinity' && isNumericString) { | ||
value = ''; | ||
} //round the number based on decimalScale | ||
//format only if non formatted value is provided | ||
// if value is undefined or null, use defaultValue instead | ||
value = isNil(value) ? defaultValue : value; | ||
var isNonNumericFalsy = !value && value !== 0; | ||
if (isNumericString && !format && typeof decimalScale === 'number') { | ||
value = roundToPrecision(value, decimalScale, fixedDecimalScale); | ||
} | ||
if (isNonNumericFalsy && allowEmptyFormatting) { | ||
value = ''; | ||
} | ||
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value); | ||
return formattedValue; | ||
} | ||
}, { | ||
key: "formatNegation", | ||
value: function formatNegation() { | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var allowNegative = this.props.allowNegative; | ||
var negationRegex = new RegExp('(-)'); | ||
var doubleNegationRegex = new RegExp('(-)(.)*(-)'); // Check number has '-' value | ||
// if value is not defined return empty string | ||
if (isNonNumericFalsy && !allowEmptyFormatting) { return ''; } | ||
var hasNegation = negationRegex.test(value); // Check number has 2 or more '-' values | ||
if (typeof value === 'number') { | ||
value = toNumericString(value); | ||
isNumericString = true; | ||
} | ||
var removeNegation = doubleNegationRegex.test(value); //remove negation | ||
//change infinity value to empty string | ||
if (value === 'Infinity' && isNumericString) { | ||
value = ''; | ||
} | ||
value = value.replace(/-/g, ''); | ||
//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); | ||
} | ||
if (hasNegation && !removeNegation && allowNegative) { | ||
value = '-' + value; | ||
} | ||
var formattedValue = isNumericString ? this.formatNumString(value) : this.formatInput(value); | ||
return value; | ||
} | ||
}, { | ||
key: "formatInput", | ||
value: function formatInput() { | ||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; | ||
var format = this.props.format; //format negation only if we are formatting as number | ||
return formattedValue; | ||
}; | ||
if (!format) { | ||
value = this.removePrefixAndSuffix(value); | ||
value = this.formatNegation(value); | ||
} //remove formatting from number | ||
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('(-)(.)*(-)'); | ||
value = this.removeFormatting(value); | ||
return this.formatNumString(value); | ||
} | ||
/*** format specific methods end ***/ | ||
// Check number has '-' value | ||
var hasNegation = negationRegex.test(value); | ||
}, { | ||
key: "isCharacterAFormat", | ||
value: function isCharacterAFormat(caretPos, value) { | ||
var _this$props10 = this.props, | ||
format = _this$props10.format, | ||
prefix = _this$props10.prefix, | ||
suffix = _this$props10.suffix, | ||
decimalScale = _this$props10.decimalScale, | ||
fixedDecimalScale = _this$props10.fixedDecimalScale; | ||
// Check number has 2 or more '-' values | ||
var removeNegation = doubleNegationRegex.test(value); | ||
var _this$getSeparators5 = this.getSeparators(), | ||
decimalSeparator = _this$getSeparators5.decimalSeparator; //check within format pattern | ||
//remove negation | ||
value = value.replace(/-/g, ''); | ||
if (hasNegation && !removeNegation && allowNegative) { | ||
value = '-' + value; | ||
} | ||
if (typeof format === 'string' && format[caretPos] !== '#') return true; //check in number format | ||
return value; | ||
}; | ||
if (!format && (caretPos < prefix.length || caretPos >= value.length - suffix.length || decimalScale && fixedDecimalScale && value[caretPos] === decimalSeparator)) { | ||
return true; | ||
} | ||
NumberFormat.prototype.formatInput = function formatInput (value) { | ||
if ( value === void 0 ) value = ''; | ||
return false; | ||
} | ||
}, { | ||
key: "checkIfFormatGotDeleted", | ||
value: function checkIfFormatGotDeleted(start, end, value) { | ||
for (var i = start; i < end; i++) { | ||
if (this.isCharacterAFormat(i, value)) return true; | ||
} | ||
var ref = this.props; | ||
var format = ref.format; | ||
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 | ||
**/ | ||
//format negation only if we are formatting as number | ||
if (!format) { | ||
value = this.removePrefixAndSuffix(value); | ||
value = this.formatNegation(value); | ||
} | ||
}, { | ||
key: "correctInputValue", | ||
value: function correctInputValue(caretPos, lastValue, value) { | ||
var _this$props11 = this.props, | ||
format = _this$props11.format, | ||
allowNegative = _this$props11.allowNegative, | ||
prefix = _this$props11.prefix, | ||
suffix = _this$props11.suffix, | ||
decimalScale = _this$props11.decimalScale; | ||
//remove formatting from number | ||
value = this.removeFormatting(value); | ||
var _this$getSeparators6 = this.getSeparators(), | ||
allowedDecimalSeparators = _this$getSeparators6.allowedDecimalSeparators, | ||
decimalSeparator = _this$getSeparators6.decimalSeparator; | ||
return this.formatNumString(value); | ||
}; | ||
var lastNumStr = this.state.numAsString || ''; | ||
var _this$selectionBefore = this.selectionBeforeInput, | ||
selectionStart = _this$selectionBefore.selectionStart, | ||
selectionEnd = _this$selectionBefore.selectionEnd; | ||
/*** 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; | ||
var _findChangedIndex = findChangedIndex(lastValue, value), | ||
start = _findChangedIndex.start, | ||
end = _findChangedIndex.end; | ||
/** Check for any allowed decimal separator is added in the numeric format and replace it with decimal separator */ | ||
//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; | ||
} | ||
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); | ||
} | ||
/* don't do anyhting if something got added, | ||
or if value is empty string (when whole input is cleared) | ||
or whole input is replace with a number | ||
*/ | ||
return false; | ||
}; | ||
NumberFormat.prototype.checkIfFormatGotDeleted = function checkIfFormatGotDeleted (start , end , value ) { | ||
for (var i = start; i < end; i++) { | ||
if (this.isCharacterAFormat(i, value)) { return true; } | ||
} | ||
return false; | ||
}; | ||
var leftBound = !!format ? 0 : prefix.length; | ||
var rightBound = lastValue.length - (!!format ? 0 : suffix.length); | ||
/** | ||
* 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 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; | ||
if (value.length > lastValue.length || !value.length || start === end || selectionStart === 0 && selectionEnd === lastValue.length || start === 0 && end === lastValue.length || selectionStart === leftBound && selectionEnd === rightBound) { | ||
return value; | ||
} //if format got deleted reset the value to last value | ||
/** 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 (this.checkIfFormatGotDeleted(start, end, lastValue)) { | ||
value = lastValue; | ||
} //for numbers check if beforeDecimal got deleted and there is nothing after decimal, | ||
//clear all numbers in such case while keeping the - sign | ||
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; | ||
} | ||
if (!format) { | ||
var numericString = this.removeFormatting(value); | ||
//if format got deleted reset the value to last value | ||
if (this.checkIfFormatGotDeleted(start, end, lastValue)) { | ||
value = lastValue; | ||
} | ||
var _splitDecimal2 = splitDecimal(numericString, allowNegative), | ||
beforeDecimal = _splitDecimal2.beforeDecimal, | ||
afterDecimal = _splitDecimal2.afterDecimal, | ||
addNegation = _splitDecimal2.addNegation; // eslint-disable-line prefer-const | ||
//clear only if something got deleted | ||
//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 ? '-' : ''; | ||
} | ||
} | ||
var isBeforeDecimalPoint = caretPos < value.indexOf(decimalSeparator) + 1; | ||
return value; | ||
}; | ||
if (numericString.length < lastNumStr.length && isBeforeDecimalPoint && beforeDecimal === '' && !parseFloat(afterDecimal)) { | ||
return addNegation ? '-' : ''; | ||
} | ||
} | ||
/** 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 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; | ||
return value; | ||
} | ||
/** Update value and caret position */ | ||
if (input) { | ||
//set caret position, and value imperatively when element is provided | ||
if (setCaretPosition) { | ||
}, { | ||
key: "updateValue", | ||
value: function updateValue(params) { | ||
var formattedValue = params.formattedValue, | ||
input = params.input, | ||
_params$setCaretPosit = params.setCaretPosition, | ||
setCaretPosition = _params$setCaretPosit === void 0 ? true : _params$setCaretPosit; | ||
var numAsString = params.numAsString, | ||
caretPos = params.caretPos; | ||
var onValueChange = this.props.onValueChange; | ||
var lastValue = this.state.value; | ||
//calculate caret position if not defined | ||
if (!caretPos) { | ||
var inputValue = params.inputValue || input.value; | ||
if (input) { | ||
//set caret position, and value imperatively when element is provided | ||
if (setCaretPosition) { | ||
//calculate caret position if not defined | ||
if (!caretPos) { | ||
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 | ||
*/ | ||
var currentCaretPosition = getCurrentCaretPosition(input); | ||
input.value = formattedValue; //get the caret position | ||
/** | ||
* 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; | ||
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition); | ||
} //set caret position | ||
//get the caret position | ||
caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition); | ||
} | ||
//set caret position | ||
this.setPatchedCaretPosition(input, caretPos, formattedValue); | ||
} else { | ||
/** | ||
* if we are not setting caret position set the value imperatively. | ||
* This is required on onBlur method | ||
*/ | ||
input.value = formattedValue; | ||
} | ||
} | ||
this.setPatchedCaretPosition(input, caretPos, formattedValue); | ||
} else { | ||
/** | ||
* if we are not setting caret position set the value imperatively. | ||
* This is required on onBlur method | ||
*/ | ||
input.value = formattedValue; | ||
} | ||
} //calculate numeric string if not passed | ||
//calculate numeric string if not passed | ||
if (numAsString === undefined) { | ||
numAsString = this.removeFormatting(formattedValue); | ||
} | ||
if (numAsString === undefined) { | ||
numAsString = this.removeFormatting(formattedValue); | ||
} //update state if value is changed | ||
//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)); | ||
} | ||
}; | ||
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 | ||
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 || ''; | ||
onValueChange(this.getValueObject(formattedValue, numAsString)); | ||
} | ||
} | ||
}, { | ||
key: "onChange", | ||
value: function onChange(e) { | ||
var el = e.target; | ||
var inputValue = el.value; | ||
var state = this.state, | ||
props = this.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); | ||
var currentCaretPosition = getCurrentCaretPosition(el); | ||
if (!isChangeAllowed) { | ||
formattedValue = lastValue; | ||
} | ||
inputValue = this.correctInputValue(currentCaretPosition, lastValue, inputValue); | ||
this.updateValue({ | ||
formattedValue: formattedValue, | ||
numAsString: numAsString, | ||
inputValue: inputValue, | ||
input: el | ||
}); | ||
var formattedValue = this.formatInput(inputValue) || ''; | ||
var numAsString = this.removeFormatting(formattedValue); | ||
if (isChangeAllowed) { | ||
props.onChange(e); | ||
} | ||
} | ||
}, { | ||
key: "onBlur", | ||
value: function onBlur(e) { | ||
var props = this.props, | ||
state = this.state; | ||
var format = props.format, | ||
onBlur = props.onBlur, | ||
allowLeadingZeros = props.allowLeadingZeros; | ||
var numAsString = state.numAsString; | ||
var lastValue = state.value; | ||
this.focusedElm = null; | ||
clearTimeout(this.focusTimeout); | ||
var valueObj = this.getValueObject(formattedValue, numAsString); | ||
var isChangeAllowed = isAllowed(valueObj); | ||
if (!format) { | ||
// if the numAsString is not a valid number reset it to empty | ||
if (isNaN(parseFloat(numAsString))) { | ||
numAsString = ''; | ||
} | ||
if (!isChangeAllowed) { | ||
formattedValue = lastValue; | ||
} | ||
if (!allowLeadingZeros) { | ||
numAsString = fixLeadingZero(numAsString); | ||
} | ||
this.updateValue({ formattedValue: formattedValue, numAsString: numAsString, inputValue: inputValue, input: el }); | ||
var formattedValue = this.formatNumString(numAsString); //change the state | ||
if(isChangeAllowed) { | ||
props.onChange(e); | ||
} | ||
}; | ||
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 | ||
}); | ||
onBlur(e); | ||
return; | ||
} | ||
} | ||
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; | ||
onBlur(e); | ||
} | ||
}, { | ||
key: "onKeyDown", | ||
value: function onKeyDown(e) { | ||
var el = e.target; | ||
var key = e.key; | ||
var selectionStart = el.selectionStart, | ||
selectionEnd = el.selectionEnd, | ||
_el$value = el.value, | ||
value = _el$value === void 0 ? '' : _el$value; | ||
var expectedCaretPosition; | ||
var _this$props12 = this.props, | ||
decimalScale = _this$props12.decimalScale, | ||
fixedDecimalScale = _this$props12.fixedDecimalScale, | ||
prefix = _this$props12.prefix, | ||
suffix = _this$props12.suffix, | ||
format = _this$props12.format, | ||
onKeyDown = _this$props12.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 | ||
clearTimeout(this.focusTimeout); | ||
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 (!format) { | ||
// if the numAsString is not a valid number reset it to empty | ||
if (isNaN(parseFloat(numAsString))) { | ||
numAsString = ''; | ||
} | ||
if (expectedCaretPosition === undefined || selectionStart !== selectionEnd) { | ||
onKeyDown(e); | ||
return; | ||
} | ||
if (!allowLeadingZeros) { | ||
numAsString = fixLeadingZero(numAsString); | ||
} | ||
var newCaretPosition = expectedCaretPosition; | ||
var leftBound = isPatternFormat ? format.indexOf('#') : prefix.length; | ||
var rightBound = isPatternFormat ? format.lastIndexOf('#') + 1 : value.length - suffix.length; | ||
var formattedValue = this.formatNumString(numAsString); | ||
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 | ||
}); | ||
} else if (!negativeRegex.test(value[expectedCaretPosition])) { | ||
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound) { | ||
newCaretPosition--; | ||
} | ||
//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 }); | ||
onBlur(e); | ||
return; | ||
} | ||
} | ||
onBlur(e); | ||
}; | ||
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left'); | ||
} | ||
} | ||
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'; | ||
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 */ | ||
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 (e.isUnitTestRun) { | ||
this.setPatchedCaretPosition(el, newCaretPosition, 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; | ||
} | ||
onKeyDown(e); | ||
} | ||
/** required to handle the caret position when click anywhere within the input **/ | ||
var newCaretPosition = expectedCaretPosition; | ||
var leftBound = isPatternFormat ? format.indexOf('#') : prefix.length; | ||
var rightBound = isPatternFormat ? format.lastIndexOf('#') + 1 : value.length - suffix.length; | ||
}, { | ||
key: "onMouseUp", | ||
value: 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. | ||
*/ | ||
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}); | ||
} else if (!negativeRegex.test(value[expectedCaretPosition])) { | ||
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > leftBound){ newCaretPosition--; } | ||
newCaretPosition = this.correctCaretPosition(value, newCaretPosition, 'left'); | ||
} | ||
} | ||
var selectionStart = el.selectionStart, | ||
selectionEnd = el.selectionEnd, | ||
_el$value2 = el.value, | ||
value = _el$value2 === void 0 ? '' : _el$value2; | ||
if (selectionStart === selectionEnd) { | ||
var caretPosition = this.correctCaretPosition(value, selectionStart); | ||
if (newCaretPosition !== expectedCaretPosition || expectedCaretPosition < leftBound || expectedCaretPosition > rightBound) { | ||
e.preventDefault(); | ||
this.setPatchedCaretPosition(el, newCaretPosition, value); | ||
} | ||
if (caretPosition !== selectionStart) { | ||
this.setPatchedCaretPosition(el, caretPosition, 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); | ||
} | ||
this.props.onMouseUp(e); | ||
} | ||
}, { | ||
key: "onFocus", | ||
value: function onFocus(e) { | ||
var _this2 = 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, | ||
selectionEnd = el.selectionEnd, | ||
_el$value3 = el.value, | ||
value = _el$value3 === void 0 ? '' : _el$value3; | ||
onKeyDown(e); | ||
var caretPosition = _this2.correctCaretPosition(value, selectionStart); //setPatchedCaretPosition only when everything is not selected on focus (while tabbing into the field) | ||
}; | ||
/** required to handle the caret position when click anywhere within the input **/ | ||
NumberFormat.prototype.onMouseUp = function onMouseUp (e ) { | ||
var el = e.target; | ||
if (caretPosition !== selectionStart && !(selectionStart === 0 && selectionEnd === value.length)) { | ||
_this2.setPatchedCaretPosition(el, caretPosition, value); | ||
} | ||
/** | ||
* 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 = ''; | ||
_this2.props.onFocus(e); | ||
}, 0); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this$props13 = this.props, | ||
type = _this$props13.type, | ||
displayType = _this$props13.displayType, | ||
customInput = _this$props13.customInput, | ||
renderText = _this$props13.renderText, | ||
getInputRef = _this$props13.getInputRef, | ||
format = _this$props13.format; | ||
var _this$state = this.state, | ||
value = _this$state.value, | ||
mounted = _this$state.mounted; | ||
var otherProps = omit(this.props, propTypes$1); // add input mode on element based on format prop and device once the component is mounted | ||
if (selectionStart === selectionEnd) { | ||
var caretPosition = this.correctCaretPosition(value, selectionStart); | ||
if (caretPosition !== selectionStart) { | ||
this.setPatchedCaretPosition(el, caretPosition, value); | ||
} | ||
} | ||
var inputMode = mounted && addInputMode(format) ? 'numeric' : undefined; | ||
this.props.onMouseUp(e); | ||
}; | ||
var inputProps = _extends({ | ||
inputMode: inputMode | ||
}, otherProps, { | ||
type: type, | ||
value: value, | ||
onChange: this.onChange, | ||
onKeyDown: this.onKeyDown, | ||
onMouseUp: this.onMouseUp, | ||
onFocus: this.onFocus, | ||
onBlur: this.onBlur | ||
}); | ||
NumberFormat.prototype.onFocus = function onFocus (e ) { | ||
var this$1 = this; | ||
if (displayType === 'text') { | ||
return renderText ? renderText(value, otherProps) || null : React.createElement("span", _extends({}, otherProps, { | ||
ref: getInputRef | ||
}), value); | ||
} else if (customInput) { | ||
var CustomInput = customInput; | ||
return React.createElement(CustomInput, _extends({}, inputProps, { | ||
ref: getInputRef | ||
})); | ||
} | ||
// 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(); | ||
return React.createElement("input", _extends({}, inputProps, { | ||
ref: getInputRef | ||
})); | ||
} | ||
}]); | ||
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 = ''; | ||
return NumberFormat; | ||
}(React.Component); | ||
var caretPosition = this$1.correctCaretPosition(value, selectionStart); | ||
NumberFormat.propTypes = propTypes$1; | ||
NumberFormat.defaultProps = defaultProps; | ||
//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); | ||
} | ||
return NumberFormat; | ||
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 ref$1 = this.state; | ||
var value = ref$1.value; | ||
var mounted = ref$1.mounted; | ||
var otherProps = omit(this.props, propTypes$1); | ||
// 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.propTypes = propTypes$1; | ||
NumberFormat.defaultProps = defaultProps; | ||
return NumberFormat; | ||
})); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):(e=e||self).NumberFormat=t(e.React)}(this,function(h){"use strict";function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function g(){return(g=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function o(e){return(o=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function r(e,t){return(r=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function i(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}h=h&&h.hasOwnProperty("default")?h.default:h;function a(){}function s(){}s.resetWarningCache=a;var e,t=(function(e){e.exports=function(){function e(e,t,r,n,a,o){if("SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"!==o){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}var r={array:e.isRequired=e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:s,resetWarningCache:a};return r.PropTypes=r}()}(e={exports:{}},e.exports),e.exports);function u(){}function p(e){return!!(e||"").match(/\d/)}function m(e){return null==e}function l(e){return e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&")}function D(e,t){var r=!(1<arguments.length&&void 0!==t)||t,n="-"===e[0],a=n&&r,o=(e=e.replace("-","")).split(".");return{beforeDecimal:o[0],afterDecimal:o[1]||"",hasNagation:n,addNegation:a}}function d(e,t,r){for(var n="",a=r?"0":"",o=0;o<=t-1;o++)n+=e[o]||a;return n}function c(e,t){if(e.value=e.value,null!==e){if(e.createTextRange){var r=e.createTextRange();return r.move("character",t),r.select(),!0}return e.selectionStart||0===e.selectionStart?(e.focus(),e.setSelectionRange(t,t),!0):(e.focus(),!1)}}function v(e,t,r){return Math.min(Math.max(e,t),r)}function f(e){return Math.max(e.selectionStart,e.selectionEnd)}var y={thousandSeparator:t.oneOfType([t.string,t.oneOf([!0])]),decimalSeparator:t.string,allowedDecimalSeparators:t.arrayOf(t.string),thousandsGroupStyle:t.oneOf(["thousand","lakh","wan"]),decimalScale:t.number,fixedDecimalScale:t.bool,displayType:t.oneOf(["input","text"]),prefix:t.string,suffix:t.string,format:t.oneOfType([t.string,t.func]),removeFormatting:t.func,mask:t.oneOfType([t.string,t.arrayOf(t.string)]),value:t.oneOfType([t.number,t.string]),defaultValue:t.oneOfType([t.number,t.string]),isNumericString:t.bool,customInput:t.elementType,allowNegative:t.bool,allowEmptyFormatting:t.bool,allowLeadingZeros:t.bool,onValueChange:t.func,onKeyDown:t.func,onMouseUp:t.func,onChange:t.func,onFocus:t.func,onBlur:t.func,type:t.oneOf(["text","tel","password"]),isAllowed:t.func,renderText:t.func,getInputRef:t.oneOfType([t.func,t.shape({current:t.any})])},S={displayType:"input",decimalSeparator:".",thousandsGroupStyle:"thousand",fixedDecimalScale:!1,prefix:"",suffix:"",allowNegative:!0,allowEmptyFormatting:!1,allowLeadingZeros:!1,isNumericString:!1,type:"text",onValueChange:u,onChange:u,onKeyDown:u,onMouseUp:u,onFocus:u,onBlur:u,isAllowed:function(){return!0}},b=function(){function a(e){var t;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,a),t=function(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?i(e):t}(this,o(a).call(this,e));var r=e.defaultValue;t.validateProps();var n=t.formatValueProp(r);return t.state={value:n,numAsString:t.removeFormatting(n),mounted:!1},t.selectionBeforeInput={selectionStart:0,selectionEnd:0},t.onChange=t.onChange.bind(i(t)),t.onKeyDown=t.onKeyDown.bind(i(t)),t.onMouseUp=t.onMouseUp.bind(i(t)),t.onFocus=t.onFocus.bind(i(t)),t.onBlur=t.onBlur.bind(i(t)),t}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}(a,h.Component),function(e,t,r){t&&n(e.prototype,t),r&&n(e,r)}(a,[{key:"componentDidMount",value:function(){this.setState({mounted:!0})}},{key:"componentDidUpdate",value:function(e){this.updateValueIfRequired(e)}},{key:"componentWillUnmount",value:function(){clearTimeout(this.focusTimeout)}},{key:"updateValueIfRequired",value:function(e){var t=this.props,r=this.state,n=this.focusedElm,a=r.value,o=r.numAsString,i=void 0===o?"":o;if(e!==t){this.validateProps();var s=this.formatNumString(i),u=m(t.value)?s:this.formatValueProp(),l=this.removeFormatting(u),c=parseFloat(l),f=parseFloat(i);(isNaN(c)&&isNaN(f)||c===f)&&s===a&&(null!==n||u===a)||this.updateValue({formattedValue:u,numAsString:l,input:n})}}},{key:"getFloatString",value:function(e){var t=0<arguments.length&&void 0!==e?e:"",r=this.props.decimalScale,n=this.getSeparators().decimalSeparator,a=this.getNumberRegex(!0),o="-"===t[0];o&&(t=t.replace("-","")),n&&0===r&&(t=t.split(n)[0]);var i=(t=(t.match(a)||[]).join("").replace(n,".")).indexOf(".");return-1!==i&&(t="".concat(t.substring(0,i),".").concat(t.substring(i+1,t.length).replace(new RegExp(l(n),"g"),""))),o&&(t="-"+t),t}},{key:"getNumberRegex",value:function(e,t){var r=this.props,n=r.format,a=r.decimalScale,o=this.getSeparators().decimalSeparator;return new RegExp("\\d"+(!o||0===a||t||n?"":"|"+l(o)),e?"g":void 0)}},{key:"getSeparators",value:function(){var e=this.props.decimalSeparator,t=this.props,r=t.thousandSeparator,n=t.allowedDecimalSeparators;return!0===r&&(r=","),{decimalSeparator:e,thousandSeparator:r,allowedDecimalSeparators:n=n||[e,"."]}}},{key:"getMaskAtIndex",value:function(e){var t=this.props.mask,r=void 0===t?" ":t;return"string"==typeof r?r:r[e]||" "}},{key:"getValueObject",value:function(e,t){var r=parseFloat(t);return{formattedValue:e,value:t,floatValue:isNaN(r)?void 0:r}}},{key:"validateProps",value:function(){var e=this.props.mask,t=this.getSeparators(),r=t.decimalSeparator,n=t.thousandSeparator;if(r===n)throw new Error("\n Decimal separator can't be same as thousand separator.\n thousandSeparator: ".concat(n,' (thousandSeparator = {true} is same as thousandSeparator = ",")\n decimalSeparator: ').concat(r," (default value for decimalSeparator is .)\n "));if(e&&("string"===e?e:e.toString()).match(/\d/g))throw new Error("\n Mask ".concat(e," should not contain numeric character;\n "))}},{key:"setPatchedCaretPosition",value:function(e,t,r){c(e,t),setTimeout(function(){e.value===r&&c(e,t)},0)}},{key:"correctCaretPosition",value:function(e,t,r){var n=this.props,a=n.prefix,o=n.suffix,i=n.format;if(""===e)return 0;if(t=v(t,0,e.length),!i){var s="-"===e[0];return v(t,a.length+(s?1:0),e.length-o.length)}if("function"==typeof i)return t;if("#"===i[t]&&p(e[t]))return t;if("#"===i[t-1]&&p(e[t-1]))return t;var u=i.indexOf("#");t=v(t,u,i.lastIndexOf("#")+1);for(var l=i.substring(t,i.length).indexOf("#"),c=t,f=t+(-1===l?0:l);u<c&&("#"!==i[c]||!p(e[c]));)c-=1;return!p(e[f])||"left"===r&&t!==u||t-c<f-t?p(e[c])?c+1:c:f}},{key:"getCaretPosition",value:function(e,t,r){var n,a,o=this.props.format,i=this.state.value,s=this.getNumberRegex(!0),u=(e.match(s)||[]).join(""),l=(t.match(s)||[]).join("");for(a=n=0;a<r;a++){var c=e[a]||"",f=t[n]||"";if((c.match(s)||c===f)&&("0"!==c||!f.match(s)||"0"===f||u.length===l.length)){for(;c!==t[n]&&n<t.length;)n++;n++}}return"string"!=typeof o||i||(n=t.length),n=this.correctCaretPosition(t,n)}},{key:"removePrefixAndSuffix",value:function(e){var t=this.props,r=t.format,n=t.prefix,a=t.suffix;if(!r&&e){var o="-"===e[0];o&&(e=e.substring(1,e.length));var i=(e=n&&0===e.indexOf(n)?e.substring(n.length,e.length):e).lastIndexOf(a);e=a&&-1!==i&&i===e.length-a.length?e.substring(0,i):e,o&&(e="-"+e)}return e}},{key:"removePatternFormatting",value:function(e){for(var t=this.props.format.split("#").filter(function(e){return""!==e}),r=0,n="",a=0,o=t.length;a<=o;a++){var i=t[a]||"",s=a===o?e.length:e.indexOf(i,r);if(-1===s){n=e;break}n+=e.substring(r,s),r=s+i.length}return(n.match(/\d/g)||[]).join("")}},{key:"removeFormatting",value:function(e){var t=this.props,r=t.format,n=t.removeFormatting;return e?e=r?"string"==typeof r?this.removePatternFormatting(e):"function"==typeof n?n(e):(e.match(/\d/g)||[]).join(""):(e=this.removePrefixAndSuffix(e),this.getFloatString(e)):e}},{key:"formatWithPattern",value:function(e){for(var t=this.props.format,r=0,n=t.split(""),a=0,o=t.length;a<o;a++)"#"===t[a]&&(n[a]=e[r]||this.getMaskAtIndex(r),r+=1);return n.join("")}},{key:"formatAsNumber",value:function(e){var t=this.props,r=t.decimalScale,n=t.fixedDecimalScale,a=t.prefix,o=t.suffix,i=t.allowNegative,s=t.thousandsGroupStyle,u=this.getSeparators(),l=u.thousandSeparator,c=u.decimalSeparator,f=-1!==e.indexOf(".")||r&&n,p=D(e,i),h=p.beforeDecimal,g=p.afterDecimal,m=p.addNegation;return void 0!==r&&(g=d(g,r,n)),l&&(h=function(e,t,r){var n=function(e){switch(e){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),a=e.search(/[1-9]/);return a=-1===a?e.length:a,e.substring(0,a)+e.substring(a,e.length).replace(n,"$1"+t)}(h,l,s)),a&&(h=a+h),o&&(g+=o),m&&(h="-"+h),e=h+(f&&c||"")+g}},{key:"formatNumString",value:function(e){var t=0<arguments.length&&void 0!==e?e:"",r=this.props,n=r.format,a=r.allowEmptyFormatting,o=t;return o=""!==t||a?"-"!==t||n?"string"==typeof n?this.formatWithPattern(o):"function"==typeof n?n(o):this.formatAsNumber(o):"-":""}},{key:"formatValueProp",value:function(e){var t=this.props,r=t.format,n=t.decimalScale,a=t.fixedDecimalScale,o=t.allowEmptyFormatting,i=this.props,s=i.value,u=i.isNumericString,l=!(s=m(s)?e:s)&&0!==s;return l&&o&&(s=""),l&&!o?"":("number"==typeof s&&(s=s.toString(),u=!0),"Infinity"===s&&u&&(s=""),u&&!r&&"number"==typeof n&&(s=function(e,t,r){if(-1!==["","-"].indexOf(e))return e;var n=-1!==e.indexOf(".")&&t,a=D(e),o=a.beforeDecimal,i=a.afterDecimal,s=a.hasNagation,u=parseFloat("0.".concat(i||"0")),l=(i.length<=t?u.toString():u.toFixed(t)).split("."),c=o.split("").reverse().reduce(function(e,t,r){return e.length>r?(Number(e[0])+Number(t)).toString()+e.substring(1,e.length):t+e},l[0]),f=d(l[1]||"",Math.min(t,i.length),r),p=n?".":"";return"".concat(s?"-":"").concat(c).concat(p).concat(f)}(s,n,a)),u?this.formatNumString(s):this.formatInput(s))}},{key:"formatNegation",value:function(e){var t=0<arguments.length&&void 0!==e?e:"",r=this.props.allowNegative,n=new RegExp("(-)"),a=new RegExp("(-)(.)*(-)"),o=n.test(t),i=a.test(t);return t=t.replace(/-/g,""),o&&!i&&r&&(t="-"+t),t}},{key:"formatInput",value:function(e){var t=0<arguments.length&&void 0!==e?e:"";return this.props.format||(t=this.removePrefixAndSuffix(t),t=this.formatNegation(t)),t=this.removeFormatting(t),this.formatNumString(t)}},{key:"isCharacterAFormat",value:function(e,t){var r=this.props,n=r.format,a=r.prefix,o=r.suffix,i=r.decimalScale,s=r.fixedDecimalScale,u=this.getSeparators().decimalSeparator;return"string"==typeof n&&"#"!==n[e]||!(n||!(e<a.length||e>=t.length-o.length||i&&s&&t[e]===u))}},{key:"checkIfFormatGotDeleted",value:function(e,t,r){for(var n=e;n<t;n++)if(this.isCharacterAFormat(n,r))return!0;return!1}},{key:"correctInputValue",value:function(e,t,r){var n=this.props,a=n.format,o=n.allowNegative,i=n.prefix,s=n.suffix,u=n.decimalScale,l=this.getSeparators(),c=l.allowedDecimalSeparators,f=l.decimalSeparator,p=this.state.numAsString||"",h=this.selectionBeforeInput,g=h.selectionStart,m=h.selectionEnd,d=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{start:r,end:a-n}}(t,r),v=d.start,y=d.end;if(!a&&v===y&&-1!==c.indexOf(r[g])){var S=0===u?"":f;return r.substr(0,g)+S+r.substr(g+1,r.length)}var b=a?0:i.length,x=t.length-(a?0:s.length);if(r.length>t.length||!r.length||v===y||0===g&&m===t.length||0===v&&y===t.length||g===b&&m===x)return r;if(this.checkIfFormatGotDeleted(v,y,t)&&(r=t),!a){var w=this.removeFormatting(r),O=D(w,o),P=O.beforeDecimal,k=O.afterDecimal,F=O.addNegation,N=e<r.indexOf(f)+1;if(w.length<p.length&&N&&""===P&&!parseFloat(k))return F?"-":""}return r}},{key:"updateValue",value:function(e){var t=e.formattedValue,r=e.input,n=e.setCaretPosition,a=void 0===n||n,o=e.numAsString,i=e.caretPos,s=this.props.onValueChange,u=this.state.value;if(r)if(a){if(!i){var l=e.inputValue||r.value,c=f(r);r.value=t,i=this.getCaretPosition(l,t,c)}this.setPatchedCaretPosition(r,i,t)}else r.value=t;void 0===o&&(o=this.removeFormatting(t)),t!==u&&(this.setState({value:t,numAsString:o}),s(this.getValueObject(t,o)))}},{key:"onChange",value:function(e){var t=e.target,r=t.value,n=this.state,a=this.props,o=a.isAllowed,i=n.value||"",s=f(t);r=this.correctInputValue(s,i,r);var u=this.formatInput(r)||"",l=this.removeFormatting(u),c=o(this.getValueObject(u,l));c||(u=i),this.updateValue({formattedValue:u,numAsString:l,inputValue:r,input:t}),c&&a.onChange(e)}},{key:"onBlur",value:function(e){var t=this.props,r=this.state,n=t.format,a=t.onBlur,o=t.allowLeadingZeros,i=r.numAsString,s=r.value;if(this.focusedElm=null,clearTimeout(this.focusTimeout),!n){isNaN(parseFloat(i))&&(i=""),o||(i=function(e){if(!e)return e;var t="-"===e[0];t&&(e=e.substring(1,e.length));var r=e.split("."),n=r[0].replace(/^0+/,"")||"0",a=r[1]||"";return"".concat(t?"-":"").concat(n).concat(a?".".concat(a):"")}(i));var u=this.formatNumString(i);if(u!==s)return this.updateValue({formattedValue:u,numAsString:i,input:e.target,setCaretPosition:!1}),void a(e)}a(e)}},{key:"onKeyDown",value:function(e){var t,r=e.target,n=e.key,a=r.selectionStart,o=r.selectionEnd,i=r.value,s=void 0===i?"":i,u=this.props,l=u.decimalScale,c=u.fixedDecimalScale,f=u.prefix,p=u.suffix,h=u.format,g=u.onKeyDown,m=void 0!==l&&c,d=this.getNumberRegex(!1,m),v=new RegExp("-"),y="string"==typeof h;if(this.selectionBeforeInput={selectionStart:a,selectionEnd:o},"ArrowLeft"===n||"Backspace"===n?t=a-1:"ArrowRight"===n?t=a+1:"Delete"===n&&(t=a),void 0!==t&&a===o){var S=t,b=y?h.indexOf("#"):f.length,x=y?h.lastIndexOf("#")+1:s.length-p.length;if("ArrowLeft"===n||"ArrowRight"===n){var w="ArrowLeft"===n?"left":"right";S=this.correctCaretPosition(s,t,w)}else if("Delete"!==n||d.test(s[t])||v.test(s[t])){if("Backspace"===n&&!d.test(s[t]))if(a<=b+1&&"-"===s[0]&&void 0===h){var O=s.substring(1);this.updateValue({formattedValue:O,caretPos:S,input:r})}else if(!v.test(s[t])){for(;!d.test(s[S-1])&&b<S;)S--;S=this.correctCaretPosition(s,S,"left")}}else for(;!d.test(s[S])&&S<x;)S++;(S!==t||t<b||x<t)&&(e.preventDefault(),this.setPatchedCaretPosition(r,S,s)),e.isUnitTestRun&&this.setPatchedCaretPosition(r,S,s),g(e)}else g(e)}},{key:"onMouseUp",value:function(e){var t=e.target,r=t.selectionStart,n=t.selectionEnd,a=t.value,o=void 0===a?"":a;if(r===n){var i=this.correctCaretPosition(o,r);i!==r&&this.setPatchedCaretPosition(t,i,o)}this.props.onMouseUp(e)}},{key:"onFocus",value:function(i){var s=this;i.persist(),this.focusedElm=i.target,this.focusTimeout=setTimeout(function(){var e=i.target,t=e.selectionStart,r=e.selectionEnd,n=e.value,a=void 0===n?"":n,o=s.correctCaretPosition(a,t);o===t||0===t&&r===a.length||s.setPatchedCaretPosition(e,o,a),s.props.onFocus(i)},0)}},{key:"render",value:function(){var e=this.props,t=e.type,r=e.displayType,n=e.customInput,a=e.renderText,o=e.getInputRef,i=e.format,s=this.state,u=s.value,l=s.mounted,c=function(t,r){var n={};return Object.keys(t).forEach(function(e){r[e]||(n[e]=t[e])}),n}(this.props,y),f=g({inputMode:l&&function(e){return e||!(navigator.platform&&/iPhone|iPod/.test(navigator.platform))}(i)?"numeric":void 0},c,{type:t,value:u,onChange:this.onChange,onKeyDown:this.onKeyDown,onMouseUp:this.onMouseUp,onFocus:this.onFocus,onBlur:this.onBlur});if("text"===r)return a?a(u,c)||null:h.createElement("span",g({},c,{ref:o}),u);if(n){var p=n;return h.createElement(p,g({},f,{ref:o}))}return h.createElement("input",g({},f,{ref:o}))}}]),a}();return b.propTypes=y,b.defaultProps=S,b}); | ||
!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(g){"use strict";g=g&&g.hasOwnProperty("default")?g.default:g;function o(){}function n(){}n.resetWarningCache=o;var t,e=(function(t){t.exports=function(){function t(t,e,r,o,n,a){if("SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"!==a){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function e(){return t}var r={array:t.isRequired=t,bool:t,func:t,number:t,object:t,string:t,symbol:t,any:t,arrayOf:e,element:t,elementType:t,instanceOf:e,node:t,objectOf:e,oneOf:e,oneOfType:e,shape:e,exact:e,checkPropTypes:n,resetWarningCache:o};return r.PropTypes=r}()}(t={exports:{}},t.exports),t.exports);function r(){}function c(t){return!!(t||"").match(/\d/)}function f(t){return null==t}function i(t){return t.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&")}function C(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 s(t,e){return Array(e+1).join(t)}function p(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."+s("0",Math.abs(a))+o:i<=a?o+=s("0",a-i):o=(o.substring(0,a)||"0")+"."+o.substring(a),e+o}function a(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 h(t,e,r){return Math.min(Math.max(t,e),r)}function m(t){return Math.max(t.selectionStart,t.selectionEnd)}var v={thousandSeparator:e.oneOfType([e.string,e.oneOf([!0])]),decimalSeparator:e.string,allowedDecimalSeparators:e.arrayOf(e.string),thousandsGroupStyle:e.oneOf(["thousand","lakh","wan"]),decimalScale:e.number,fixedDecimalScale:e.bool,displayType:e.oneOf(["input","text"]),prefix:e.string,suffix:e.string,format:e.oneOfType([e.string,e.func]),removeFormatting:e.func,mask:e.oneOfType([e.string,e.arrayOf(e.string)]),value:e.oneOfType([e.number,e.string]),defaultValue:e.oneOfType([e.number,e.string]),isNumericString:e.bool,customInput:e.elementType,allowNegative:e.bool,allowEmptyFormatting:e.bool,allowLeadingZeros:e.bool,onValueChange:e.func,onKeyDown:e.func,onMouseUp:e.func,onChange:e.func,onFocus:e.func,onBlur:e.func,type:e.oneOf(["text","tel","password"]),isAllowed:e.func,renderText:e.func,getInputRef:e.oneOfType([e.func,e.shape({current:e.any})])},u={displayType:"input",decimalSeparator:".",thousandsGroupStyle:"thousand",fixedDecimalScale:!1,prefix:"",suffix:"",allowNegative:!0,allowEmptyFormatting:!1,allowLeadingZeros:!1,isNumericString:!1,type:"text",onValueChange:r,onChange:r,onKeyDown:r,onMouseUp:r,onFocus:r,onBlur:r,isAllowed:function(){return!0}},l=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)},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=f(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})}},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(i(r),"g"),"")),n&&(t="-"+t),t},t.prototype.getNumberRegex=function(t,e){var r=this.props,o=r.format,n=r.decimalScale,a=this.getSeparators().decimalSeparator;return new RegExp("\\d"+(!a||0===n||e||o?"":"|"+i(a)),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){a(t,e),setTimeout(function(){t.value===r&&a(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=h(e,0,t.length),!i){var s="-"===t[0];return h(e,n.length+(s?1:0),t.length-a.length)}if("function"==typeof i)return e;if("#"===i[e]&&c(t[e]))return e;if("#"===i[e-1]&&c(t[e-1]))return e;var u=i.indexOf("#");e=h(e,u,i.lastIndexOf("#")+1);for(var l=i.substring(e,i.length).indexOf("#"),p=e,f=e+(-1===l?0:l);u<p&&("#"!==i[p]||!c(t[p]));)p-=1;return!c(t[f])||"left"===r&&e!==u||e-p<f-e?c(t[p])?p+1:p:f},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]||"",f=e[o]||"";if((p.match(s)||p===f)&&("0"!==p||!f.match(s)||"0"===f||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(/\d/g)||[]).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(/\d/g)||[]).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,f=-1!==t.indexOf(".")||r&&o,c=C(t,i),h=c.beforeDecimal,g=c.afterDecimal,m=c.addNegation;return void 0!==r&&(g=d(g,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&&(g+=a),m&&(h="-"+h),t=h+(f&&p||"")+g},t.prototype.formatNumString=function(t){void 0===t&&(t="");var e=this.props,r=e.format,o=e.allowEmptyFormatting,n=t;return n=""!==t||o?"-"!==t||r?"string"==typeof r?this.formatWithPattern(n):"function"==typeof r?r(n):this.formatAsNumber(n):"-":""},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=f(s)?t:s)&&0!==s;return l&&a&&(s=""),l&&!a?"":("number"==typeof s&&(s=p(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=C(t),a=n.beforeDecimal,i=n.afterDecimal,s=n.hasNagation,u=parseFloat("0."+(i||"0")),l=(i.length<=e?p(u):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.checkIfFormatGotDeleted=function(t,e,r){for(var o=t;o<e;o++)if(this.isCharacterAFormat(o,r))return!0;return!1},t.prototype.correctInputValue=function(t,e,r){var o=this.props,n=o.format,a=o.allowNegative,i=o.prefix,s=o.suffix,u=o.decimalScale,l=this.getSeparators(),p=l.allowedDecimalSeparators,f=l.decimalSeparator,c=this.state.numAsString||"",h=this.selectionBeforeInput,g=h.selectionStart,m=h.selectionEnd,d=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}}(e,r),v=d.start,y=d.end;if(!n&&v===y&&-1!==p.indexOf(r[g])){var S=0===u?"":f;return r.substr(0,g)+S+r.substr(g+1,r.length)}var x=n?0:i.length,b=e.length-(n?0:s.length);if(r.length>e.length||!r.length||v===y||0===g&&m===e.length||0===v&&y===e.length||g===x&&m===b)return r;if(this.checkIfFormatGotDeleted(v,y,e)&&(r=e),!n){var w=this.removeFormatting(r),P=C(w,a),O=P.beforeDecimal,N=P.afterDecimal,F=P.addNegation,D=t<r.indexOf(f)+1;if(w.length<c.length&&D&&""===O&&!parseFloat(N))return F?"-":""}return r},t.prototype.updateValue=function(t){var e=t.formattedValue,r=t.input,o=t.setCaretPosition;void 0===o&&(o=!0);var n=t.numAsString,a=t.caretPos,i=this.props.onValueChange,s=this.state.value;if(r)if(o){if(!a){var u=t.inputValue||r.value,l=m(r);r.value=e,a=this.getCaretPosition(u,e,l)}this.setPatchedCaretPosition(r,a,e)}else r.value=e;void 0===n&&(n=this.removeFormatting(e)),e!==s&&(this.setState({value:e,numAsString:n}),i(this.getValueObject(e,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=m(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}),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),!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}),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,f=s.suffix,c=s.format,h=s.onKeyDown,g=void 0!==u&&l,m=this.getNumberRegex(!1,g),d=new RegExp("-"),v="string"==typeof c;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 y=e,S=v?c.indexOf("#"):p.length,x=v?c.lastIndexOf("#")+1:i.length-f.length;if("ArrowLeft"===o||"ArrowRight"===o){var b="ArrowLeft"===o?"left":"right";y=this.correctCaretPosition(i,e,b)}else if("Delete"!==o||m.test(i[e])||d.test(i[e])){if("Backspace"===o&&!m.test(i[e]))if(n<=S+1&&"-"===i[0]&&void 0===c){var w=i.substring(1);this.updateValue({formattedValue:w,caretPos:y,input:r})}else if(!d.test(i[e])){for(;!m.test(i[y-1])&&S<y;)y--;y=this.correctCaretPosition(i,y,"left")}}else for(;!m.test(i[y])&&y<x;)y++;(y!==e||e<S||x<e)&&(t.preventDefault(),this.setPatchedCaretPosition(r,y,i)),t.isUnitTestRun&&this.setPatchedCaretPosition(r,y,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=this.state,u=s.value,l=s.mounted,p=function(e,r){var o={};return Object.keys(e).forEach(function(t){r[t]||(o[t]=e[t])}),o}(this.props,v),f=l&&function(t){return t||!(navigator.platform&&/iPhone|iPod/.test(navigator.platform))}(i)?"numeric":void 0,c=Object.assign({inputMode:f},p,{type:e,value:u,onChange:this.onChange,onKeyDown:this.onKeyDown,onMouseUp:this.onMouseUp,onFocus:this.onFocus,onBlur:this.onBlur});if("text"===r)return n?n(u,p)||null:g.createElement("span",Object.assign({},p,{ref:a}),u);if(o){var h=o;return g.createElement(h,Object.assign({},c,{ref:a}))}return g.createElement("input",Object.assign({},c,{ref:a}))},t}(g.Component);return l.propTypes=v,l.defaultProps=u,l}); |
@@ -582,3 +582,3 @@ "use strict"; | ||
if (typeof value === 'number') { | ||
value = value.toString(); | ||
value = (0, _utils.toNumericString)(value); | ||
isNumericString = true; | ||
@@ -703,12 +703,14 @@ } //change infinity value to empty string | ||
} | ||
/* don't do anyhting if something got added, | ||
or if value is empty string (when whole input is cleared) | ||
or whole input is replace with a number | ||
*/ | ||
var leftBound = !!format ? 0 : prefix.length; | ||
var rightBound = lastValue.length - (!!format ? 0 : suffix.length); | ||
if (value.length > lastValue.length || !value.length || start === end || selectionStart === 0 && selectionEnd === lastValue.length || start === 0 && end === lastValue.length || selectionStart === leftBound && selectionEnd === rightBound) { | ||
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; | ||
@@ -715,0 +717,0 @@ } //if format got deleted reset the value to last value |
@@ -16,2 +16,3 @@ "use strict"; | ||
exports.limitToScale = limitToScale; | ||
exports.toNumericString = toNumericString; | ||
exports.roundToPrecision = roundToPrecision; | ||
@@ -25,2 +26,10 @@ exports.omit = omit; | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
// basic noop function | ||
@@ -42,3 +51,3 @@ function noop() {} | ||
function escapeRegExp(str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
@@ -109,2 +118,46 @@ | ||
} | ||
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 _num$split = num.split(/[eE]/g), | ||
_num$split2 = _slicedToArray(_num$split, 2), | ||
coefficient = _num$split2[0], | ||
exponent = _num$split2[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; | ||
} | ||
/** | ||
@@ -127,3 +180,3 @@ * This method is required to round prop value to given scale. | ||
var floatValue = parseFloat("0.".concat(afterDecimal || '0')); | ||
var floatValueStr = afterDecimal.length <= scale ? floatValue.toString() : floatValue.toFixed(scale); | ||
var floatValueStr = afterDecimal.length <= scale ? toNumericString(floatValue) : floatValue.toFixed(scale); | ||
var roundedDecimalParts = floatValueStr.split('.'); | ||
@@ -154,3 +207,3 @@ var intPart = beforeDecimal.split('').reverse().reduce(function (roundedStr, current, idx) { | ||
function setCaretPosition(el, caretPos) { | ||
el.value = el.value; // ^ this is used to not only get "focus", but | ||
el.value = el.value; // ^ this is used to not only get 'focus', but | ||
// to make sure we don't have it everything -selected- | ||
@@ -157,0 +210,0 @@ // (it causes an issue in chrome, and having it doesn't hurt any other browser) |
{ | ||
"name": "react-number-format", | ||
"description": "React component to format number in an input or as a text.", | ||
"version": "4.5.3", | ||
"main": "lib/number_format.js", | ||
"version": "4.5.4", | ||
"main": "dist/react-number-format.cjs.js", | ||
"module": "dist/react-number-format.es.js", | ||
@@ -46,2 +46,3 @@ "author": "Sudhanshu Yadav", | ||
"@babel/register": "^7.6.2", | ||
"@rollup/plugin-buble": "^0.21.3", | ||
"@types/react": "^16.9.4", | ||
@@ -57,2 +58,3 @@ "babel-eslint": "^10.0.3", | ||
"eslint": "^6.5.1", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-loader": "^3.0.2", | ||
@@ -74,2 +76,3 @@ "eslint-plugin-import": "^2.18.2", | ||
"material-ui": "^0.20.2", | ||
"prettier": "^2.2.1", | ||
"react": "^15.4.0 || ^16.0.0", | ||
@@ -83,2 +86,3 @@ "react-dom": "^15.4.0 || ^16.0.0", | ||
"rollup-plugin-filesize": "^6.2.0", | ||
"rollup-plugin-flow": "^1.1.1", | ||
"rollup-plugin-license": "^0.12.1", | ||
@@ -85,0 +89,0 @@ "rollup-plugin-node-resolve": "^5.2.0", |
@@ -249,3 +249,9 @@ [![Actions Status](https://github.com/s-yadav/react-number-format/workflows/CI/badge.svg)](https://github.com/s-yadav/react-number-format/actions) | ||
``` | ||
Or using React.createRef() | ||
```jsx | ||
const inputRef = React.createRef(); | ||
<NumberFormat getInputRef = {inputRef} customInput={TextField} format="#### #### #### ####"/> | ||
``` | ||
In case you have provided custom input you can pass there props to get the input reference (getInputRef will not work in that case). | ||
@@ -262,2 +268,3 @@ For ex in material-ui component. | ||
### Live Demo | ||
@@ -264,0 +271,0 @@ [http://codepen.io/s-yadav/pen/bpKNMa](http://codepen.io/s-yadav/pen/bpKNMa) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
246065
23
5018
329
54