New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-number-format

Package Overview
Dependencies
Maintainers
1
Versions
121
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-number-format - npm Package Compare versions

Comparing version 2.0.0-alpha5 to 2.0.0-beta1

custom_formatters/card_expiry.js

249

dist/react-number-format.js
/*!
* react-number-format - 2.0.0-alpha5
* react-number-format - 2.0.0-beta1
* Author : Sudhanshu Yadav

@@ -100,2 +100,4 @@ * Copyright (c) 2016,2017 to Sudhanshu Yadav - ignitersworld.com , released under the MIT license.

* 10. isAllowed props to validate input and block if returns false
* 11. Round to precision for passed value
* 12. It should always move cursor to type area ignoring prefix and suffix
*/

@@ -115,2 +117,6 @@

/**
* limit decimal numbers to given precision
* Not used .fixedTo because that will break with big numbers
*/
function limitToPrecision(numStr, precision) {

@@ -124,2 +130,21 @@ var str = '';

/**
* This method is required to round prop value to given precision.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr, precision) {
var numberParts = numStr.split('.');
var roundedDecimalParts = parseFloat('0.' + (numberParts[1] || '0')).toFixed(precision).split('.');
var intPart = numberParts[0].split('').reverse().reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (Number(roundedStr[0]) + Number(current)).toString() + roundedStr.substring(1, roundedStr.length);
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = roundedDecimalParts[1];
return intPart + (decimalPart ? '.' + decimalPart : '');
}
function omit(obj, keyMaps) {

@@ -146,2 +171,3 @@ var filteredObj = {};

onKeyDown: _propTypes2.default.func,
onMouseUp: _propTypes2.default.func,
onChange: _propTypes2.default.func,

@@ -155,2 +181,4 @@ type: _propTypes2.default.oneOf(['text', 'tel']),

decimalSeparator: '.',
prefix: '',
suffix: '',
allowNegative: true,

@@ -160,2 +188,3 @@ type: 'text',

onKeyDown: noop,
onMouseUp: noop,
isAllowed: function isAllowed() {

@@ -180,2 +209,3 @@ return true;

_this.onKeyDown = _this.onKeyDown.bind(_this);
_this.onMouseUp = _this.onMouseUp.bind(_this);
return _this;

@@ -213,13 +243,23 @@ }

}, {
key: 'getFloatValue',
value: function getFloatValue(num) {
var decimalSeparator = this.props.decimalSeparator;
key: 'getFloatString',
value: function getFloatString(num, props) {
props = props || this.props;
return parseFloat(num.replace(decimalSeparator, '.')) || 0;
var _getSeparators = this.getSeparators(props),
decimalSeparator = _getSeparators.decimalSeparator,
thousandSeparator = _getSeparators.thousandSeparator;
return num.replace(new RegExp(escapeRegExp(thousandSeparator || ''), 'g'), '').replace(decimalSeparator, '.');
}
}, {
key: 'getFloatValue',
value: function getFloatValue(num, props) {
props = props || this.props;
return parseFloat(this.getFloatString(num, props)) || 0;
}
}, {
key: 'optimizeValueProp',
value: function optimizeValueProp(props) {
var _getSeparators = this.getSeparators(props),
decimalSeparator = _getSeparators.decimalSeparator;
var _getSeparators2 = this.getSeparators(props),
decimalSeparator = _getSeparators2.decimalSeparator;

@@ -237,7 +277,17 @@ var decimalPrecision = props.decimalPrecision,

value = this.removePrefixAndSuffix(isNumber ? value : this.getFloatString(value, props), props);
//round off value
if (typeof decimalPrecision === 'number') value = roundToPrecision(value, decimalPrecision);
//correct decimal separator
if (decimalSeparator && isNumber) {
if (decimalSeparator) {
value = value.replace('.', decimalSeparator);
}
//throw error if value has two decimal seperators
if (value.split(decimalSeparator).length > 2) {
throw new Error('\n Wrong input for value props.\n\n More than one decimalSeparator found\n ');
}
//if decimalPrecision is 0 remove decimalNumbers

@@ -249,2 +299,30 @@ if (decimalPrecision === 0) return value.split(decimalSeparator)[0];

}, {
key: 'removePrefixAndSuffix',
value: function removePrefixAndSuffix(val, props) {
var format = props.format,
prefix = props.prefix,
suffix = props.suffix;
//remove prefix and suffix
if (!format && val) {
var isNegative = val[0] === '-';
//remove negation sign
if (isNegative) val = val.substring(1, val.length);
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
var suffixLastIndex = val.lastIndexOf(suffix);
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val;
//add negation sign back
if (isNegative) val = '-' + val;
}
return val;
}
}, {
key: 'getSeparators',

@@ -280,4 +358,4 @@ value: function getSeparators(props) {

var _getSeparators2 = this.getSeparators(),
decimalSeparator = _getSeparators2.decimalSeparator;
var _getSeparators3 = this.getSeparators(),
decimalSeparator = _getSeparators3.decimalSeparator;

@@ -327,8 +405,20 @@ return new RegExp('\\d' + (decimalSeparator && decimalPrecision !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined);

}
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
}, {
key: 'correctCaretPosition',
value: function correctCaretPosition(value, caretPos) {
var _props4 = this.props,
prefix = _props4.prefix,
suffix = _props4.suffix;
return Math.min(Math.max(caretPos, prefix.length), value.length - suffix.length);
}
}, {
key: 'formatWithPattern',
value: function formatWithPattern(str) {
var _props4 = this.props,
format = _props4.format,
mask = _props4.mask;
var _props5 = this.props,
format = _props5.format,
mask = _props5.mask;

@@ -357,13 +447,14 @@ if (!format) return str;

value: function formatInput(val) {
var _props5 = this.props,
prefix = _props5.prefix,
suffix = _props5.suffix,
mask = _props5.mask,
format = _props5.format,
allowNegative = _props5.allowNegative,
decimalPrecision = _props5.decimalPrecision;
var props = this.props,
removePrefixAndSuffix = this.removePrefixAndSuffix;
var prefix = props.prefix,
suffix = props.suffix,
mask = props.mask,
format = props.format,
allowNegative = props.allowNegative,
decimalPrecision = props.decimalPrecision;
var _getSeparators3 = this.getSeparators(),
thousandSeparator = _getSeparators3.thousandSeparator,
decimalSeparator = _getSeparators3.decimalSeparator;
var _getSeparators4 = this.getSeparators(),
thousandSeparator = _getSeparators4.thousandSeparator,
decimalSeparator = _getSeparators4.decimalSeparator;

@@ -381,2 +472,3 @@ var maskPattern = format && typeof format == 'string' && !!mask;

//check if it has negative numbers
if (allowNegative && !format) {

@@ -389,2 +481,5 @@ // Check number has '-' value

//remove prefix and suffix
val = removePrefixAndSuffix(val, props);
var valMatch = val && val.match(numRegex);

@@ -437,3 +532,3 @@

return {
value: (hasNegative && !removeNegative ? '-' : '') + formattedValue.match(numRegex).join(''),
value: (hasNegative && !removeNegative ? '-' : '') + removePrefixAndSuffix(formattedValue, props).match(numRegex).join(''),
formattedValue: formattedValue

@@ -443,5 +538,7 @@ };

}, {
key: 'getCursorPosition',
value: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var numRegex = this.getNumberRegex();
key: 'getCaretPosition',
value: function getCaretPosition(inputValue, formattedValue, caretPos) {
var numRegex = this.getNumberRegex(true);
var inputNumber = (inputValue.match(numRegex) || []).join('');
var formattedNumber = (formattedValue.match(numRegex) || []).join('');
var j = void 0,

@@ -452,6 +549,15 @@ i = void 0;

for (i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
if (inputValue[i] === '0' && (formattedValue[j] || '').match(numRegex) && formattedValue[j] !== '0') continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
for (i = 0; i < caretPos; i++) {
var currentInputChar = inputValue[i];
var currentFormatChar = formattedValue[j] || '';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if (!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) continue;
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (currentInputChar === '0' && currentFormatChar.match(numRegex) && currentFormatChar !== '0' && inputNumber.length !== formattedNumber.length) continue;
//we are not using currentFormatChar because j can change here
while (currentInputChar !== formattedValue[j] && !(formattedValue[j] || '').match(numRegex) && j < formattedValue.length) {
j++;

@@ -461,2 +567,5 @@ }j++;

//correct caret position if its outsize of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;

@@ -480,10 +589,14 @@ }

/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device cursor bug*/
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
var currentCursorPosition = Math.max(el.selectionStart, el.selectionEnd);
var currentCaretPosition = Math.max(el.selectionStart, el.selectionEnd);
var cursorPos = this.getCursorPosition(inputValue, formattedValue, currentCursorPosition);
var valueObj = {
formattedValue: formattedValue,
value: value,
floatValue: this.getFloatValue(value)
};
if (!isAllowed(formattedValue, value, this.getFloatValue(value))) {
if (!isAllowed(valueObj)) {
formattedValue = lastValue;

@@ -495,4 +608,7 @@ }

//get the caret position
var caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
//set caret position
this.setPatchedCaretPosition(el, cursorPos, formattedValue);
this.setPatchedCaretPosition(el, caretPos, formattedValue);

@@ -502,3 +618,3 @@ //change the state

this.setState({ value: formattedValue }, function () {
props.onChange(e, value);
props.onChange(e, valueObj);
});

@@ -513,6 +629,9 @@ }

var el = e.target;
var selectionStart = el.selectionStart,
selectionEnd = el.selectionEnd,
var selectionEnd = el.selectionEnd,
value = el.value;
var decimalPrecision = this.props.decimalPrecision;
var selectionStart = el.selectionStart;
var _props6 = this.props,
decimalPrecision = _props6.decimalPrecision,
prefix = _props6.prefix,
suffix = _props6.suffix;
var key = e.key;

@@ -522,16 +641,23 @@

var negativeRegex = new RegExp('-');
//Handle backspace and delete against non numerical/decimal characters
if (selectionEnd - selectionStart === 0) {
if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
e.preventDefault();
var nextCursorPosition = selectionStart;
while (!numRegex.test(value[nextCursorPosition]) && nextCursorPosition < value.length) {
nextCursorPosition++;
}this.setPatchedCaretPosition(el, nextCursorPosition, value);
if (selectionStart === selectionEnd) {
var newCaretPosition = selectionStart;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
selectionStart += key === 'ArrowLeft' ? -1 : +1;
newCaretPosition = this.correctCaretPosition(value, selectionStart);
} else if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < value.length - suffix.length) {
newCaretPosition++;
}
} else if (key === 'Backspace' && !numRegex.test(value[selectionStart - 1]) && !negativeRegex.test(value[selectionStart - 1])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > prefix.length) {
newCaretPosition--;
}
}
if (newCaretPosition !== selectionStart) {
e.preventDefault();
var prevCursorPosition = selectionStart;
while (!numRegex.test(value[prevCursorPosition - 1]) && prevCursorPosition > 0) {
prevCursorPosition--;
}this.setPatchedCaretPosition(el, prevCursorPosition, value);
this.setPatchedCaretPosition(el, newCaretPosition, value);
}

@@ -543,2 +669,20 @@ }

}, {
key: 'onMouseUp',
value: function onMouseUp(e) {
var el = e.target;
var selectionStart = el.selectionStart,
selectionEnd = el.selectionEnd,
value = el.value;
if (selectionStart === selectionEnd) {
var caretPostion = this.correctCaretPosition(value, selectionStart);
if (caretPostion !== selectionStart) {
this.setPatchedCaretPosition(el, caretPostion, value);
}
}
this.props.onMouseUp(e);
}
}, {
key: 'render',

@@ -552,3 +696,4 @@ value: function render() {

onChange: this.onChange,
onKeyDown: this.onKeyDown
onKeyDown: this.onKeyDown,
onMouseUp: this.onMouseUp
});

@@ -555,0 +700,0 @@

/*!
* react-number-format - 2.0.0-alpha5
* react-number-format - 2.0.0-beta1
* Author : Sudhanshu Yadav
* Copyright (c) 2016,2017 to Sudhanshu Yadav - ignitersworld.com , released under the MIT license.
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.NumberFormat=t(require("react")):e.NumberFormat=t(e.React)}(this,function(e){return function(e){function t(n){if(r[n])return r[n].exports;var a=r[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){e.exports=r(1)},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function u(){}function s(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}function f(e){return e.replace(/^0+/,"")||"0"}function l(e,t){for(var r="",n=0;n<=t-1;n++)r+=e[n]||"0";return r}function p(e,t){var r={};return Object.keys(e).forEach(function(n){t[n]||(r[n]=e[n])}),r}var c=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},d=function(){function e(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)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),h=r(2),v=n(h),m=r(7),y=n(m),g={thousandSeparator:v.default.oneOfType([v.default.string,v.default.oneOf([!0])]),decimalSeparator:v.default.string,decimalPrecision:v.default.number,displayType:v.default.oneOf(["input","text"]),prefix:v.default.string,suffix:v.default.string,format:v.default.oneOfType([v.default.string,v.default.func]),mask:v.default.string,value:v.default.oneOfType([v.default.number,v.default.string]),customInput:v.default.func,allowNegative:v.default.bool,onKeyDown:v.default.func,onChange:v.default.func,type:v.default.oneOf(["text","tel"]),isAllowed:v.default.func},b={displayType:"input",decimalSeparator:".",allowNegative:!0,type:"text",onChange:u,onKeyDown:u,isAllowed:function(){return!0}},x=function(e){function t(e){a(this,t);var r=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),n=r.optimizeValueProp(e);return r.state={value:r.formatInput(n).formattedValue},r.onChange=r.onChange.bind(r),r.onKeyDown=r.onKeyDown.bind(r),r}return i(t,e),d(t,[{key:"componentDidUpdate",value:function(e,t){this.updateValueIfRequired(e,t)}},{key:"updateValueIfRequired",value:function(e){var t=this.props,r=this.state;if(e!==t){var n=r.value,a=this.optimizeValueProp(t);void 0===a&&(a=n);var o=this.formatInput(a),i=o.formattedValue;i!==n&&this.setState({value:i})}}},{key:"getFloatValue",value:function(e){var t=this.props.decimalSeparator;return parseFloat(e.replace(t,"."))||0}},{key:"optimizeValueProp",value:function(e){var t=this.getSeparators(e),r=t.decimalSeparator,n=e.decimalPrecision,a=e.format,o=e.value;if(a||void 0===o)return o;var i="number"==typeof o;return i&&(o=o.toString()),r&&i&&(o=o.replace(".",r)),0===n?o.split(r)[0]:o}},{key:"getSeparators",value:function(e){e=e||this.props;var t=e,r=t.decimalSeparator,n=e,a=n.thousandSeparator;if(a===!0&&(a=","),r===a)throw new Error("\n Decimal separator can't be same as thousand separator.\n\n thousandSeparator: "+a+' (thousandSeparator = {true} is same as thousandSeparator = ",")\n decimalSeparator: '+r+" (default value for decimalSeparator is .)\n ");return{decimalSeparator:r,thousandSeparator:a}}},{key:"getNumberRegex",value:function(e,t){var r=this.props,n=r.format,a=r.decimalPrecision,o=this.getSeparators(),i=o.decimalSeparator;return new RegExp("\\d"+(!i||0===a||t||n?"":"|"+s(i)),e?"g":void 0)}},{key:"setCaretPosition",value:function(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)}}},{key:"setPatchedCaretPosition",value:function(e,t,r){var n=this;this.setCaretPosition(e,t),setTimeout(function(){e.value===r&&n.setCaretPosition(e,t)},0)}},{key:"formatWithPattern",value:function(e){var t=this.props,r=t.format,n=t.mask;if(!r)return e;for(var a=r.split("#").length-1,o=0,i=r,u=0,s=e.length;u<s;u++)u<a&&(o=i.indexOf("#"),i=i.replace("#",e[u]));var f=i.lastIndexOf("#");return n?i.replace(/#/g,n):i.substring(0,o+1)+(f!==-1?i.substring(f+1,i.length):"")}},{key:"formatInput",value:function(e){var t=this.props,r=t.prefix,n=t.suffix,a=(t.mask,t.format),o=t.allowNegative,i=t.decimalPrecision,u=this.getSeparators(),s=u.thousandSeparator,p=u.decimalSeparator,c=this.getNumberRegex(!0),d=void 0,h=void 0;"number"==typeof e&&(e+="");var v=new RegExp("(-)"),m=new RegExp("(-)(.)*(-)");o&&!a&&(d=v.test(e),h=m.test(e));var y=e&&e.match(c);if(!y&&h)return{value:"",formattedValue:""};if(!y&&d)return{value:"",formattedValue:"-"};if(!y)return{value:"",formattedValue:""};var g=e.match(c).join(""),b=g;if(a)"string"==typeof a?b=this.formatWithPattern(b):"function"==typeof a&&(b=a(b));else{var x=b.indexOf(p)!==-1||i,P=b.split(p),S=P[0],w=P[1]||"";S=f(S),void 0!==i&&(w=l(w,i)),s&&(S=S.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1"+s)),r&&(S=r+S),n&&(w+=n),d&&!h&&(S="-"+S),b=S+(x&&p||"")+w}return{value:(d&&!h?"-":"")+b.match(c).join(""),formattedValue:b}}},{key:"getCursorPosition",value:function(e,t,r){var n=this.getNumberRegex(),a=void 0,o=void 0;for(a=0,o=0;o<r;o++)if((e[o].match(n)||e[o]===t[a])&&("0"!==e[o]||!(t[a]||"").match(n)||"0"===t[a])){for(;e[o]!==t[a]&&a<t.length;)a++;a++}return a}},{key:"onChange",value:function(e){e.persist();var t=e.target,r=t.value,n=this.state,a=this.props,o=a.isAllowed,i=n.value,u=this.formatInput(r),s=u.formattedValue,f=u.value,l=Math.max(t.selectionStart,t.selectionEnd),p=this.getCursorPosition(r,s,l);return o(s,f,this.getFloatValue(f))||(s=i),t.value=s,this.setPatchedCaretPosition(t,p,s),s!==i&&this.setState({value:s},function(){a.onChange(e,f)}),f}},{key:"onKeyDown",value:function(e){var t=e.target,r=t.selectionStart,n=t.selectionEnd,a=t.value,o=this.props.decimalPrecision,i=e.key,u=this.getNumberRegex(!1,void 0!==o),s=new RegExp("-");if(n-r===0)if("Delete"!==i||u.test(a[r])||s.test(a[r])){if("Backspace"===i&&!u.test(a[r-1])&&!s.test(a[r-1])){e.preventDefault();for(var f=r;!u.test(a[f-1])&&f>0;)f--;this.setPatchedCaretPosition(t,f,a)}}else{e.preventDefault();for(var l=r;!u.test(a[l])&&l<a.length;)l++;this.setPatchedCaretPosition(t,l,a)}this.props.onKeyDown(e)}},{key:"render",value:function(){var e=p(this.props,g),t=c({},e,{type:this.props.type,value:this.state.value,onChange:this.onChange,onKeyDown:this.onKeyDown});if("text"===this.props.displayType)return y.default.createElement("span",e,this.state.value);if(this.props.customInput){var r=this.props.customInput;return y.default.createElement(r,t)}return y.default.createElement("input",t)}}]),t}(y.default.Component);x.propTypes=g,x.defaultProps=b,e.exports=x},function(e,t,r){e.exports=r(3)()},function(e,t,r){"use strict";var n=r(4),a=r(5),o=r(6);e.exports=function(){function e(e,t,r,n,i,u){u!==o&&a(!1,"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")}function t(){return e}e.isRequired=e;var r={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t};return r.checkPropTypes=n,r.PropTypes=r,r}},function(e,t){"use strict";function r(e){return function(){return e}}var n=function(){};n.thatReturns=r,n.thatReturnsFalse=r(!1),n.thatReturnsTrue=r(!0),n.thatReturnsNull=r(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(e){return e},e.exports=n},function(e,t,r){"use strict";function n(e,t,r,n,o,i,u,s){if(a(t),!e){var f;if(void 0===t)f=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[r,n,o,i,u,s],p=0;f=new Error(t.replace(/%s/g,function(){return l[p++]})),f.name="Invariant Violation"}throw f.framesToPop=1,f}}var a=function(e){};e.exports=n},function(e,t){"use strict";var r="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=r},function(t,r){t.exports=e}])});
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.NumberFormat=t(require("react")):e.NumberFormat=t(e.React)}(this,function(e){return function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return e[n].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){e.exports=r(1)},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function u(){}function s(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}function f(e){return e.replace(/^0+/,"")||"0"}function l(e,t){for(var r="",n=0;n<=t-1;n++)r+=e[n]||"0";return r}function p(e,t){var r=e.split("."),n=parseFloat("0."+(r[1]||"0")).toFixed(t).split("."),o=r[0].split("").reverse().reduce(function(e,t,r){return e.length>r?(Number(e[0])+Number(t)).toString()+e.substring(1,e.length):t+e},n[0]),a=n[1];return o+(a?"."+a:"")}function c(e,t){var r={};return Object.keys(e).forEach(function(n){t[n]||(r[n]=e[n])}),r}var h=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},d=function(){function e(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)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),v=r(2),m=n(v),g=r(7),y=n(g),x={thousandSeparator:m.default.oneOfType([m.default.string,m.default.oneOf([!0])]),decimalSeparator:m.default.string,decimalPrecision:m.default.number,displayType:m.default.oneOf(["input","text"]),prefix:m.default.string,suffix:m.default.string,format:m.default.oneOfType([m.default.string,m.default.func]),mask:m.default.string,value:m.default.oneOfType([m.default.number,m.default.string]),customInput:m.default.func,allowNegative:m.default.bool,onKeyDown:m.default.func,onMouseUp:m.default.func,onChange:m.default.func,type:m.default.oneOf(["text","tel"]),isAllowed:m.default.func},b={displayType:"input",decimalSeparator:".",prefix:"",suffix:"",allowNegative:!0,type:"text",onChange:u,onKeyDown:u,onMouseUp:u,isAllowed:function(){return!0}},S=function(e){function t(e){o(this,t);var r=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),n=r.optimizeValueProp(e);return r.state={value:r.formatInput(n).formattedValue},r.onChange=r.onChange.bind(r),r.onKeyDown=r.onKeyDown.bind(r),r.onMouseUp=r.onMouseUp.bind(r),r}return i(t,e),d(t,[{key:"componentDidUpdate",value:function(e,t){this.updateValueIfRequired(e,t)}},{key:"updateValueIfRequired",value:function(e){var t=this.props,r=this.state;if(e!==t){var n=r.value,o=this.optimizeValueProp(t);void 0===o&&(o=n);var a=this.formatInput(o),i=a.formattedValue;i!==n&&this.setState({value:i})}}},{key:"getFloatString",value:function(e,t){t=t||this.props;var r=this.getSeparators(t),n=r.decimalSeparator,o=r.thousandSeparator;return e.replace(new RegExp(s(o||""),"g"),"").replace(n,".")}},{key:"getFloatValue",value:function(e,t){return t=t||this.props,parseFloat(this.getFloatString(e,t))||0}},{key:"optimizeValueProp",value:function(e){var t=this.getSeparators(e),r=t.decimalSeparator,n=e.decimalPrecision,o=e.format,a=e.value;if(o||void 0===a)return a;var i="number"==typeof a;if(i&&(a=a.toString()),a=this.removePrefixAndSuffix(i?a:this.getFloatString(a,e),e),"number"==typeof n&&(a=p(a,n)),r&&(a=a.replace(".",r)),a.split(r).length>2)throw new Error("\n Wrong input for value props.\n\n More than one decimalSeparator found\n ");return 0===n?a.split(r)[0]:a}},{key:"removePrefixAndSuffix",value:function(e,t){var r=t.format,n=t.prefix,o=t.suffix;if(!r&&e){var a="-"===e[0];a&&(e=e.substring(1,e.length)),e=n&&0===e.indexOf(n)?e.substring(n.length,e.length):e;var i=e.lastIndexOf(o);e=o&&i!==-1&&i===e.length-o.length?e.substring(0,i):e,a&&(e="-"+e)}return e}},{key:"getSeparators",value:function(e){e=e||this.props;var t=e,r=t.decimalSeparator,n=e,o=n.thousandSeparator;if(o===!0&&(o=","),r===o)throw new Error("\n Decimal separator can't be same as thousand separator.\n\n thousandSeparator: "+o+' (thousandSeparator = {true} is same as thousandSeparator = ",")\n decimalSeparator: '+r+" (default value for decimalSeparator is .)\n ");return{decimalSeparator:r,thousandSeparator:o}}},{key:"getNumberRegex",value:function(e,t){var r=this.props,n=r.format,o=r.decimalPrecision,a=this.getSeparators(),i=a.decimalSeparator;return new RegExp("\\d"+(!i||0===o||t||n?"":"|"+s(i)),e?"g":void 0)}},{key:"setCaretPosition",value:function(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)}}},{key:"setPatchedCaretPosition",value:function(e,t,r){var n=this;this.setCaretPosition(e,t),setTimeout(function(){e.value===r&&n.setCaretPosition(e,t)},0)}},{key:"correctCaretPosition",value:function(e,t){var r=this.props,n=r.prefix,o=r.suffix;return Math.min(Math.max(t,n.length),e.length-o.length)}},{key:"formatWithPattern",value:function(e){var t=this.props,r=t.format,n=t.mask;if(!r)return e;for(var o=r.split("#").length-1,a=0,i=r,u=0,s=e.length;u<s;u++)u<o&&(a=i.indexOf("#"),i=i.replace("#",e[u]));var f=i.lastIndexOf("#");return n?i.replace(/#/g,n):i.substring(0,a+1)+(f!==-1?i.substring(f+1,i.length):"")}},{key:"formatInput",value:function(e){var t=this.props,r=this.removePrefixAndSuffix,n=t.prefix,o=t.suffix,a=(t.mask,t.format),i=t.allowNegative,u=t.decimalPrecision,s=this.getSeparators(),p=s.thousandSeparator,c=s.decimalSeparator,h=this.getNumberRegex(!0),d=void 0,v=void 0;"number"==typeof e&&(e+="");var m=new RegExp("(-)"),g=new RegExp("(-)(.)*(-)");i&&!a&&(d=m.test(e),v=g.test(e)),e=r(e,t);var y=e&&e.match(h);if(!y&&v)return{value:"",formattedValue:""};if(!y&&d)return{value:"",formattedValue:"-"};if(!y)return{value:"",formattedValue:""};var x=e.match(h).join(""),b=x;if(a)"string"==typeof a?b=this.formatWithPattern(b):"function"==typeof a&&(b=a(b));else{var S=b.indexOf(c)!==-1||u,P=b.split(c),w=P[0],O=P[1]||"";w=f(w),void 0!==u&&(O=l(O,u)),p&&(w=w.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1"+p)),n&&(w=n+w),o&&(O+=o),d&&!v&&(w="-"+w),b=w+(S&&c||"")+O}return{value:(d&&!v?"-":"")+r(b,t).match(h).join(""),formattedValue:b}}},{key:"getCaretPosition",value:function(e,t,r){var n=this.getNumberRegex(!0),o=(e.match(n)||[]).join(""),a=(t.match(n)||[]).join(""),i=void 0,u=void 0;for(i=0,u=0;u<r;u++){var s=e[u],f=t[i]||"";if((s.match(n)||s===f)&&("0"!==s||!f.match(n)||"0"===f||o.length===a.length)){for(;s!==t[i]&&!(t[i]||"").match(n)&&i<t.length;)i++;i++}}return i=this.correctCaretPosition(t,i)}},{key:"onChange",value:function(e){e.persist();var t=e.target,r=t.value,n=this.state,o=this.props,a=o.isAllowed,i=n.value,u=this.formatInput(r),s=u.formattedValue,f=u.value,l=Math.max(t.selectionStart,t.selectionEnd),p={formattedValue:s,value:f,floatValue:this.getFloatValue(f)};a(p)||(s=i),t.value=s;var c=this.getCaretPosition(r,s,l);return this.setPatchedCaretPosition(t,c,s),s!==i&&this.setState({value:s},function(){o.onChange(e,p)}),f}},{key:"onKeyDown",value:function(e){var t=e.target,r=t.selectionEnd,n=t.value,o=t.selectionStart,a=this.props,i=a.decimalPrecision,u=a.prefix,s=a.suffix,f=e.key,l=this.getNumberRegex(!1,void 0!==i),p=new RegExp("-");if(o===r){var c=o;if("ArrowLeft"===f||"ArrowRight"===f)o+="ArrowLeft"===f?-1:1,c=this.correctCaretPosition(n,o);else if("Delete"!==f||l.test(n[o])||p.test(n[o])){if("Backspace"===f&&!l.test(n[o-1])&&!p.test(n[o-1]))for(;!l.test(n[c-1])&&c>u.length;)c--}else for(;!l.test(n[c])&&c<n.length-s.length;)c++;c!==o&&(e.preventDefault(),this.setPatchedCaretPosition(t,c,n))}this.props.onKeyDown(e)}},{key:"onMouseUp",value:function(e){var t=e.target,r=t.selectionStart,n=t.selectionEnd,o=t.value;if(r===n){var a=this.correctCaretPosition(o,r);a!==r&&this.setPatchedCaretPosition(t,a,o)}this.props.onMouseUp(e)}},{key:"render",value:function(){var e=c(this.props,x),t=h({},e,{type:this.props.type,value:this.state.value,onChange:this.onChange,onKeyDown:this.onKeyDown,onMouseUp:this.onMouseUp});if("text"===this.props.displayType)return y.default.createElement("span",e,this.state.value);if(this.props.customInput){var r=this.props.customInput;return y.default.createElement(r,t)}return y.default.createElement("input",t)}}]),t}(y.default.Component);S.propTypes=x,S.defaultProps=b,e.exports=S},function(e,t,r){e.exports=r(3)()},function(e,t,r){"use strict";var n=r(4),o=r(5),a=r(6);e.exports=function(){function e(e,t,r,n,i,u){u!==a&&o(!1,"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")}function t(){return e}e.isRequired=e;var r={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t};return r.checkPropTypes=n,r.PropTypes=r,r}},function(e,t){"use strict";function r(e){return function(){return e}}var n=function(){};n.thatReturns=r,n.thatReturnsFalse=r(!1),n.thatReturnsTrue=r(!0),n.thatReturnsNull=r(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(e){return e},e.exports=n},function(e,t,r){"use strict";function n(e,t,r,n,a,i,u,s){if(o(t),!e){var f;if(void 0===t)f=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[r,n,a,i,u,s],p=0;f=new Error(t.replace(/%s/g,function(){return l[p++]})),f.name="Invariant Violation"}throw f.framesToPop=1,f}}var o=function(e){};e.exports=n},function(e,t){"use strict";var r="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=r},function(t,r){t.exports=e}])});

@@ -6,24 +6,12 @@ import React from 'react';

import TextField from 'material-ui/TextField';
import {cardExpiry} from '../../custom_formatters/card_expiry';
class App extends React.Component {
constructor() {
super();
this.state = {};
this.formatExpiryChange = this.formatExpiryChange.bind(this);
this.state = {test: 1232323.780023};
}
formatExpiryChange(val) {
if(val && val.length > 1 && Number(val[0]) < 1 && Number(val[1]) < 1){
val = '01'+val.substring(2,val.length);
}
if(val && Number(val[0]) > 1){
val = '0'+val;
}
if(val && val.length >1 && Number(val[0]+val[1]) > 12){
val = '12'+val.substring(2,val.length);
}
val = val.substring(0,2)+ (val.length > 2 ? '/'+val.substring(2,4) : '');
return val;
}
render() {

@@ -36,3 +24,3 @@ return (

</h3>
<NumberFormat value={2456981} displayType={'text'} thousandSeparator={true} prefix={'$'} />
<NumberFormat value={2456981} displayType={'text'} thousandSeparator={true} prefix={'$'}/>
</div>

@@ -51,3 +39,3 @@

</h3>
<NumberFormat thousandSeparator={true} value={this.state.test} prefix={'$'} onChange={(e, val) => this.setState({test: val})} />
<NumberFormat thousandSeparator={'.'} decimalSeparator="," isAllowed={(values) => { return values.floatValue > 5}} value={this.state.test} prefix={'$'} decimalPrecision={3} onChange={(e, val) => this.setState({test: e.target.value})}/>
</div>

@@ -119,3 +107,3 @@

</h3>
<NumberFormat format={this.formatExpiryChange}/>
<NumberFormat format={cardExpiry}/>
</div>

@@ -122,0 +110,0 @@

@@ -9,7 +9,7 @@ var webpack = require('webpack');

files: [
'./test/input_test.js'
'./test/**/*.spec.js'
],
reporters: ['kjhtml'],
preprocessors: {
'./test/*.js': [ 'webpack','sourcemap'] //preprocess with webpack
'./test/**/*.js': [ 'webpack','sourcemap'] //preprocess with webpack
},

@@ -16,0 +16,0 @@ webpack: {

@@ -32,2 +32,4 @@ 'use strict';

* 10. isAllowed props to validate input and block if returns false
* 11. Round to precision for passed value
* 12. It should always move cursor to type area ignoring prefix and suffix
*/

@@ -47,2 +49,6 @@

/**
* limit decimal numbers to given precision
* Not used .fixedTo because that will break with big numbers
*/
function limitToPrecision(numStr, precision) {

@@ -56,2 +62,21 @@ var str = '';

/**
* This method is required to round prop value to given precision.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr, precision) {
var numberParts = numStr.split('.');
var roundedDecimalParts = parseFloat('0.' + (numberParts[1] || '0')).toFixed(precision).split('.');
var intPart = numberParts[0].split('').reverse().reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (Number(roundedStr[0]) + Number(current)).toString() + roundedStr.substring(1, roundedStr.length);
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = roundedDecimalParts[1];
return intPart + (decimalPart ? '.' + decimalPart : '');
}
function omit(obj, keyMaps) {

@@ -78,2 +103,3 @@ var filteredObj = {};

onKeyDown: _propTypes2.default.func,
onMouseUp: _propTypes2.default.func,
onChange: _propTypes2.default.func,

@@ -87,2 +113,4 @@ type: _propTypes2.default.oneOf(['text', 'tel']),

decimalSeparator: '.',
prefix: '',
suffix: '',
allowNegative: true,

@@ -92,2 +120,3 @@ type: 'text',

onKeyDown: noop,
onMouseUp: noop,
isAllowed: function isAllowed() {

@@ -112,2 +141,3 @@ return true;

_this.onKeyDown = _this.onKeyDown.bind(_this);
_this.onMouseUp = _this.onMouseUp.bind(_this);
return _this;

@@ -145,13 +175,23 @@ }

}, {
key: 'getFloatValue',
value: function getFloatValue(num) {
var decimalSeparator = this.props.decimalSeparator;
key: 'getFloatString',
value: function getFloatString(num, props) {
props = props || this.props;
return parseFloat(num.replace(decimalSeparator, '.')) || 0;
var _getSeparators = this.getSeparators(props),
decimalSeparator = _getSeparators.decimalSeparator,
thousandSeparator = _getSeparators.thousandSeparator;
return num.replace(new RegExp(escapeRegExp(thousandSeparator || ''), 'g'), '').replace(decimalSeparator, '.');
}
}, {
key: 'getFloatValue',
value: function getFloatValue(num, props) {
props = props || this.props;
return parseFloat(this.getFloatString(num, props)) || 0;
}
}, {
key: 'optimizeValueProp',
value: function optimizeValueProp(props) {
var _getSeparators = this.getSeparators(props),
decimalSeparator = _getSeparators.decimalSeparator;
var _getSeparators2 = this.getSeparators(props),
decimalSeparator = _getSeparators2.decimalSeparator;

@@ -169,7 +209,17 @@ var decimalPrecision = props.decimalPrecision,

value = this.removePrefixAndSuffix(isNumber ? value : this.getFloatString(value, props), props);
//round off value
if (typeof decimalPrecision === 'number') value = roundToPrecision(value, decimalPrecision);
//correct decimal separator
if (decimalSeparator && isNumber) {
if (decimalSeparator) {
value = value.replace('.', decimalSeparator);
}
//throw error if value has two decimal seperators
if (value.split(decimalSeparator).length > 2) {
throw new Error('\n Wrong input for value props.\n\n More than one decimalSeparator found\n ');
}
//if decimalPrecision is 0 remove decimalNumbers

@@ -181,2 +231,30 @@ if (decimalPrecision === 0) return value.split(decimalSeparator)[0];

}, {
key: 'removePrefixAndSuffix',
value: function removePrefixAndSuffix(val, props) {
var format = props.format,
prefix = props.prefix,
suffix = props.suffix;
//remove prefix and suffix
if (!format && val) {
var isNegative = val[0] === '-';
//remove negation sign
if (isNegative) val = val.substring(1, val.length);
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
var suffixLastIndex = val.lastIndexOf(suffix);
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val;
//add negation sign back
if (isNegative) val = '-' + val;
}
return val;
}
}, {
key: 'getSeparators',

@@ -212,4 +290,4 @@ value: function getSeparators(props) {

var _getSeparators2 = this.getSeparators(),
decimalSeparator = _getSeparators2.decimalSeparator;
var _getSeparators3 = this.getSeparators(),
decimalSeparator = _getSeparators3.decimalSeparator;

@@ -259,8 +337,20 @@ return new RegExp('\\d' + (decimalSeparator && decimalPrecision !== 0 && !ignoreDecimalSeparator && !format ? '|' + escapeRegExp(decimalSeparator) : ''), g ? 'g' : undefined);

}
/* This keeps the caret within typing area so people can't type in between prefix or suffix */
}, {
key: 'correctCaretPosition',
value: function correctCaretPosition(value, caretPos) {
var _props4 = this.props,
prefix = _props4.prefix,
suffix = _props4.suffix;
return Math.min(Math.max(caretPos, prefix.length), value.length - suffix.length);
}
}, {
key: 'formatWithPattern',
value: function formatWithPattern(str) {
var _props4 = this.props,
format = _props4.format,
mask = _props4.mask;
var _props5 = this.props,
format = _props5.format,
mask = _props5.mask;

@@ -289,13 +379,14 @@ if (!format) return str;

value: function formatInput(val) {
var _props5 = this.props,
prefix = _props5.prefix,
suffix = _props5.suffix,
mask = _props5.mask,
format = _props5.format,
allowNegative = _props5.allowNegative,
decimalPrecision = _props5.decimalPrecision;
var props = this.props,
removePrefixAndSuffix = this.removePrefixAndSuffix;
var prefix = props.prefix,
suffix = props.suffix,
mask = props.mask,
format = props.format,
allowNegative = props.allowNegative,
decimalPrecision = props.decimalPrecision;
var _getSeparators3 = this.getSeparators(),
thousandSeparator = _getSeparators3.thousandSeparator,
decimalSeparator = _getSeparators3.decimalSeparator;
var _getSeparators4 = this.getSeparators(),
thousandSeparator = _getSeparators4.thousandSeparator,
decimalSeparator = _getSeparators4.decimalSeparator;

@@ -313,2 +404,3 @@ var maskPattern = format && typeof format == 'string' && !!mask;

//check if it has negative numbers
if (allowNegative && !format) {

@@ -321,2 +413,5 @@ // Check number has '-' value

//remove prefix and suffix
val = removePrefixAndSuffix(val, props);
var valMatch = val && val.match(numRegex);

@@ -369,3 +464,3 @@

return {
value: (hasNegative && !removeNegative ? '-' : '') + formattedValue.match(numRegex).join(''),
value: (hasNegative && !removeNegative ? '-' : '') + removePrefixAndSuffix(formattedValue, props).match(numRegex).join(''),
formattedValue: formattedValue

@@ -375,5 +470,7 @@ };

}, {
key: 'getCursorPosition',
value: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var numRegex = this.getNumberRegex();
key: 'getCaretPosition',
value: function getCaretPosition(inputValue, formattedValue, caretPos) {
var numRegex = this.getNumberRegex(true);
var inputNumber = (inputValue.match(numRegex) || []).join('');
var formattedNumber = (formattedValue.match(numRegex) || []).join('');
var j = void 0,

@@ -384,6 +481,15 @@ i = void 0;

for (i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
if (inputValue[i] === '0' && (formattedValue[j] || '').match(numRegex) && formattedValue[j] !== '0') continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
for (i = 0; i < caretPos; i++) {
var currentInputChar = inputValue[i];
var currentFormatChar = formattedValue[j] || '';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if (!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) continue;
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (currentInputChar === '0' && currentFormatChar.match(numRegex) && currentFormatChar !== '0' && inputNumber.length !== formattedNumber.length) continue;
//we are not using currentFormatChar because j can change here
while (currentInputChar !== formattedValue[j] && !(formattedValue[j] || '').match(numRegex) && j < formattedValue.length) {
j++;

@@ -393,2 +499,5 @@ }j++;

//correct caret position if its outsize of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;

@@ -412,10 +521,14 @@ }

/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device cursor bug*/
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
var currentCursorPosition = Math.max(el.selectionStart, el.selectionEnd);
var currentCaretPosition = Math.max(el.selectionStart, el.selectionEnd);
var cursorPos = this.getCursorPosition(inputValue, formattedValue, currentCursorPosition);
var valueObj = {
formattedValue: formattedValue,
value: value,
floatValue: this.getFloatValue(value)
};
if (!isAllowed(formattedValue, value, this.getFloatValue(value))) {
if (!isAllowed(valueObj)) {
formattedValue = lastValue;

@@ -427,4 +540,7 @@ }

//get the caret position
var caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
//set caret position
this.setPatchedCaretPosition(el, cursorPos, formattedValue);
this.setPatchedCaretPosition(el, caretPos, formattedValue);

@@ -434,3 +550,3 @@ //change the state

this.setState({ value: formattedValue }, function () {
props.onChange(e, value);
props.onChange(e, valueObj);
});

@@ -445,6 +561,9 @@ }

var el = e.target;
var selectionStart = el.selectionStart,
selectionEnd = el.selectionEnd,
var selectionEnd = el.selectionEnd,
value = el.value;
var decimalPrecision = this.props.decimalPrecision;
var selectionStart = el.selectionStart;
var _props6 = this.props,
decimalPrecision = _props6.decimalPrecision,
prefix = _props6.prefix,
suffix = _props6.suffix;
var key = e.key;

@@ -454,16 +573,23 @@

var negativeRegex = new RegExp('-');
//Handle backspace and delete against non numerical/decimal characters
if (selectionEnd - selectionStart === 0) {
if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
e.preventDefault();
var nextCursorPosition = selectionStart;
while (!numRegex.test(value[nextCursorPosition]) && nextCursorPosition < value.length) {
nextCursorPosition++;
}this.setPatchedCaretPosition(el, nextCursorPosition, value);
if (selectionStart === selectionEnd) {
var newCaretPosition = selectionStart;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
selectionStart += key === 'ArrowLeft' ? -1 : +1;
newCaretPosition = this.correctCaretPosition(value, selectionStart);
} else if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < value.length - suffix.length) {
newCaretPosition++;
}
} else if (key === 'Backspace' && !numRegex.test(value[selectionStart - 1]) && !negativeRegex.test(value[selectionStart - 1])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > prefix.length) {
newCaretPosition--;
}
}
if (newCaretPosition !== selectionStart) {
e.preventDefault();
var prevCursorPosition = selectionStart;
while (!numRegex.test(value[prevCursorPosition - 1]) && prevCursorPosition > 0) {
prevCursorPosition--;
}this.setPatchedCaretPosition(el, prevCursorPosition, value);
this.setPatchedCaretPosition(el, newCaretPosition, value);
}

@@ -475,2 +601,20 @@ }

}, {
key: 'onMouseUp',
value: function onMouseUp(e) {
var el = e.target;
var selectionStart = el.selectionStart,
selectionEnd = el.selectionEnd,
value = el.value;
if (selectionStart === selectionEnd) {
var caretPostion = this.correctCaretPosition(value, selectionStart);
if (caretPostion !== selectionStart) {
this.setPatchedCaretPosition(el, caretPostion, value);
}
}
this.props.onMouseUp(e);
}
}, {
key: 'render',

@@ -484,3 +628,4 @@ value: function render() {

onChange: this.onChange,
onKeyDown: this.onKeyDown
onKeyDown: this.onKeyDown,
onMouseUp: this.onMouseUp
});

@@ -487,0 +632,0 @@

{
"name": "react-number-format",
"description": "React component to format number in an input or as a text.",
"version": "2.0.0-alpha5",
"version": "2.0.0-beta1",
"main": "lib/number_format.js",

@@ -6,0 +6,0 @@ "author": "Sudhanshu Yadav",

@@ -5,7 +5,7 @@ # react-number-format

### Features
1. Allow prefix, suffix and thousand separator.
2. Allow format pattern.
3. Allow masking.
4. Allow custom formatting handler.
5. Allow formatting a input or a simple text
1. Prefix, suffix and thousand separator.
2. Custom format pattern.
3. Masking.
4. Custom formatting handler.
5. Formatting a input or a simple text.

@@ -21,5 +21,5 @@ ### Install

| ------------- |-------------| -----| -------- |
| thousandSeparator | mixed: single character string or true/false (boolean) | false | Add thousand separators on number |
| decimalSeparator | mixed: single character string or true/false (boolean)| . | Support decimal point on a number |
| decimalPrecision | mixed: number or boolean | false (2 if true)| If false it does not limit decimal place, if true default precision is 2 or else limits to provided decimal place |
| thousandSeparator | mixed: single character string or boolean true (true is default to ,) |none| Add thousand separators on number |
| decimalSeparator | single character string| . | Support decimal point on a number |
| decimalPrecision | number| none| If defined it limits to given decimal precision |
| allowNegative | boolean | true | allow negative numbers (Only when format option is not provided) |

@@ -30,9 +30,21 @@ | prefix | String (ex : $) | none | Add a prefix before the number |

| displayType | String: text / input | input | If input it renders a input element where formatting happens as you input characters. If text it renders it as a normal text in a span formatting the given value |
| type | One of ['text', 'tel'] | text | Input type attribute
| format | String : Hash based ex (#### #### #### ####) <br/> Or Function| none | If format given as hash string allow number input inplace of hash. If format given as function, component calls the function with unformatted number and expects formatted number.
| mask | String (ex : _) | none | If mask defined, component will show non entered placed with masked value.
| customInput | Component Reference | input | This allow supporting custom inputs with number format.
| onChange | (e, value) => {} | none | onChange handler accepts event object through which you can get formattedValue (e.targe.value # $2,223) and second parameter non formatted value (ie: 2223)
| onChange | (e, values) => {} | none | onChange handler accepts event object and [values object](#values-object)
| isAllowed | ([values](#values-object)) => true or false | none | A checker function to check if input value is valid or not
**Other than this it accepts all the props which can be given to a input or span based on displayType you selected.**
#### values object
values object is on following format
```js
{
formattedValue: '$23,234,235.56', //value after applying formatting
value: '23234235.56', //non formatted value as string, but it maintains the decimalSeparator provided, so if , is decimal separator then value will be 23234235,56
floatValue: 23234235.56 //floating point representation. For big numbers it can have exponential syntax
}
```
### Examples

@@ -82,14 +94,28 @@ #### Prefix and thousand separator : Format currency as text

```jsx
function formatExpiryChange(val){
if(val && Number(val[0]) > 1){
val = '0'+val;
function limit(val, max) {
if (val.length === 1 && val[0] > max[0]) {
val = '0' + val;
}
if (val.length === 2) {
if (Number(val) === 0) {
val = '01';
//this can happen when user paste number
} else if (val > max) {
val = max;
}
if(val && val.length >1 && Number(val[0]+val[1]) > 12){
val = '12'+val.substring(2,val.length);
}
val = val.substring(0,2)+ (val.length > 2 ? '/'+val.substring(2,4) : '');
return val;
}
<NumberFormat format={formatExpiryChange}/>
return val;
}
function cardExpiry(val) {
let month = limit(val.substring(0, 2), '12');
let date = limit(val.substring(2, 4), '31');
return month + (date.length ? '/' + date : '');
}
<NumberFormat format={cardExpiry}/>
```

@@ -96,0 +122,0 @@ ![Screencast example](https://i.imgur.com/9wwdyFF.gif)

@@ -12,2 +12,4 @@ /**

* 10. isAllowed props to validate input and block if returns false
* 11. Round to precision for passed value
* 12. It should always move cursor to type area ignoring prefix and suffix
*/

@@ -28,2 +30,6 @@ import PropTypes from 'prop-types';

/**
* limit decimal numbers to given precision
* Not used .fixedTo because that will break with big numbers
*/
function limitToPrecision(numStr, precision) {

@@ -37,2 +43,22 @@ let str = ''

/**
* This method is required to round prop value to given precision.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr, precision) {
const numberParts = numStr.split('.');
const roundedDecimalParts = parseFloat(`0.${numberParts[1] || '0'}`).toFixed(precision).split('.');
const intPart = numberParts[0].split('').reverse().reduce((roundedStr, current, idx) => {
if (roundedStr.length > idx) {
return (Number(roundedStr[0]) + Number(current)).toString() + roundedStr.substring(1, roundedStr.length);
}
return current + roundedStr;
}, roundedDecimalParts[0])
const decimalPart = roundedDecimalParts[1];
return intPart + (decimalPart ? '.' + decimalPart : '');
}
function omit(obj, keyMaps) {

@@ -65,2 +91,3 @@ const filteredObj = {};

onKeyDown: PropTypes.func,
onMouseUp: PropTypes.func,
onChange: PropTypes.func,

@@ -74,2 +101,4 @@ type: PropTypes.oneOf(['text', 'tel']),

decimalSeparator: '.',
prefix: '',
suffix: '',
allowNegative: true,

@@ -79,2 +108,3 @@ type: 'text',

onKeyDown: noop,
onMouseUp: noop,
isAllowed: function() {return true;}

@@ -92,2 +122,3 @@ };

this.onKeyDown = this.onKeyDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
}

@@ -118,7 +149,13 @@

getFloatValue(num) {
const {decimalSeparator} = this.props;
return parseFloat(num.replace(decimalSeparator, '.')) || 0;
getFloatString(num, props) {
props = props || this.props;
const {decimalSeparator, thousandSeparator} = this.getSeparators(props);
return num.replace(new RegExp(escapeRegExp(thousandSeparator || ''), 'g'), '').replace(decimalSeparator, '.');
}
getFloatValue(num, props) {
props = props || this.props;
return parseFloat(this.getFloatString(num, props)) || 0;
}
optimizeValueProp(props) {

@@ -136,7 +173,20 @@ const {decimalSeparator} = this.getSeparators(props);

value = this.removePrefixAndSuffix(isNumber ? value: this.getFloatString(value, props), props);
//round off value
if(typeof decimalPrecision === 'number') value = roundToPrecision(value, decimalPrecision);
//correct decimal separator
if (decimalSeparator && isNumber) {
if (decimalSeparator) {
value = value.replace('.', decimalSeparator);
}
//throw error if value has two decimal seperators
if (value.split(decimalSeparator).length > 2) {
throw new Error(`
Wrong input for value props.\n
More than one decimalSeparator found
`);
}
//if decimalPrecision is 0 remove decimalNumbers

@@ -148,2 +198,26 @@ if (decimalPrecision === 0) return value.split(decimalSeparator)[0]

removePrefixAndSuffix(val, props) {
const {format, prefix, suffix} = props;
//remove prefix and suffix
if (!format && val) {
const isNegative = val[0] === '-';
//remove negation sign
if (isNegative) val = val.substring(1, val.length);
//remove prefix
val = prefix && val.indexOf(prefix) === 0 ? val.substring(prefix.length, val.length) : val;
//remove suffix
const suffixLastIndex = val.lastIndexOf(suffix);
val = suffix && suffixLastIndex !== -1 && suffixLastIndex === val.length - suffix.length ? val.substring(0, suffixLastIndex) : val;
//add negation sign back
if (isNegative) val = '-' + val;
}
return val;
}
getSeparators(props) {

@@ -217,2 +291,8 @@ props = props || this.props;

/* This keeps the caret within typing area so people can't type in between prefix or suffix */
correctCaretPosition(value, caretPos) {
const {prefix, suffix} = this.props;
return Math.min(Math.max(caretPos, prefix.length), (value.length - suffix.length));
}
formatWithPattern(str) {

@@ -241,3 +321,4 @@ const {format,mask} = this.props;

formatInput(val) {
const {prefix, suffix, mask, format, allowNegative, decimalPrecision} = this.props;
const {props, removePrefixAndSuffix} = this;
const {prefix, suffix, mask, format, allowNegative, decimalPrecision} = props;
const {thousandSeparator, decimalSeparator} = this.getSeparators();

@@ -254,2 +335,3 @@ const maskPattern = format && typeof format == 'string' && !!mask;

//check if it has negative numbers
if (allowNegative && !format) {

@@ -262,2 +344,5 @@ // Check number has '-' value

//remove prefix and suffix
val = removePrefixAndSuffix(val, props);
const valMatch = val && val.match(numRegex);

@@ -312,9 +397,10 @@

return {
value : (hasNegative && !removeNegative ? '-' : '') + formattedValue.match(numRegex).join(''),
value : (hasNegative && !removeNegative ? '-' : '') + removePrefixAndSuffix(formattedValue, props).match(numRegex).join(''),
formattedValue : formattedValue
}
}
getCursorPosition(inputValue, formattedValue, cursorPos) {
const numRegex = this.getNumberRegex();
getCaretPosition(inputValue, formattedValue, caretPos) {
const numRegex = this.getNumberRegex(true);
const inputNumber = (inputValue.match(numRegex) || []).join('');
const formattedNumber = (formattedValue.match(numRegex) || []).join('');
let j, i;

@@ -324,9 +410,21 @@

for(i=0; i<cursorPos; i++){
if(!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
if (inputValue[i] === '0' && (formattedValue[j]||'').match(numRegex) && formattedValue[j] !== '0') continue;
while(inputValue[i] !== formattedValue[j] && j<formattedValue.length) j++;
for(i=0; i<caretPos; i++){
const currentInputChar = inputValue[i];
const currentFormatChar = formattedValue[j]||'';
//no need to increase new cursor position if formatted value does not have those characters
//case inputValue = 1a23 and formattedValue = 123
if(!currentInputChar.match(numRegex) && currentInputChar !== currentFormatChar) continue;
//When we are striping out leading zeros maintain the new cursor position
//Case inputValue = 00023 and formattedValue = 23;
if (currentInputChar === '0' && currentFormatChar.match(numRegex) && currentFormatChar !== '0' && inputNumber.length !== formattedNumber.length) continue;
//we are not using currentFormatChar because j can change here
while(currentInputChar !== formattedValue[j] && !(formattedValue[j]||'').match(numRegex) && j<formattedValue.length) j++;
j++;
}
//correct caret position if its outsize of editable area
j = this.correctCaretPosition(formattedValue, j);
return j;

@@ -344,8 +442,12 @@ }

/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device cursor bug*/
const currentCursorPosition = Math.max(el.selectionStart, el.selectionEnd);
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
const currentCaretPosition = Math.max(el.selectionStart, el.selectionEnd);
const cursorPos = this.getCursorPosition(inputValue, formattedValue, currentCursorPosition);
const valueObj = {
formattedValue,
value,
floatValue: this.getFloatValue(value)
};
if (!isAllowed(formattedValue, value, this.getFloatValue(value))) {
if (!isAllowed(valueObj)) {
formattedValue = lastValue;

@@ -357,4 +459,7 @@ }

//get the caret position
const caretPos = this.getCaretPosition(inputValue, formattedValue, currentCaretPosition);
//set caret position
this.setPatchedCaretPosition(el, cursorPos, formattedValue);
this.setPatchedCaretPosition(el, caretPos, formattedValue);

@@ -364,3 +469,3 @@ //change the state

this.setState({value : formattedValue},()=>{
props.onChange(e, value);
props.onChange(e, valueObj);
});

@@ -374,19 +479,25 @@ }

const el = e.target;
const {selectionStart, selectionEnd, value} = el;
const {decimalPrecision} = this.props;
const {selectionEnd, value} = el;
let {selectionStart} = el;
const {decimalPrecision, prefix, suffix} = this.props;
const {key} = e;
const numRegex = this.getNumberRegex(false, decimalPrecision !== undefined);
const negativeRegex = new RegExp('-');
//Handle backspace and delete against non numerical/decimal characters
if(selectionEnd - selectionStart === 0) {
if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
e.preventDefault();
let nextCursorPosition = selectionStart;
while (!numRegex.test(value[nextCursorPosition]) && nextCursorPosition < value.length) nextCursorPosition++;
this.setPatchedCaretPosition(el, nextCursorPosition, value);
if(selectionStart === selectionEnd) {
let newCaretPosition = selectionStart;
if (key === 'ArrowLeft' || key === 'ArrowRight') {
selectionStart += key === 'ArrowLeft' ? -1 : +1;
newCaretPosition = this.correctCaretPosition(value, selectionStart);
} else if (key === 'Delete' && !numRegex.test(value[selectionStart]) && !negativeRegex.test(value[selectionStart])) {
while (!numRegex.test(value[newCaretPosition]) && newCaretPosition < (value.length - suffix.length)) newCaretPosition++;
} else if (key === 'Backspace' && !numRegex.test(value[selectionStart - 1]) && !negativeRegex.test(value[selectionStart-1])) {
while (!numRegex.test(value[newCaretPosition - 1]) && newCaretPosition > prefix.length) newCaretPosition--;
}
if (newCaretPosition !== selectionStart) {
e.preventDefault();
let prevCursorPosition = selectionStart;
while (!numRegex.test(value[prevCursorPosition - 1]) && prevCursorPosition > 0) prevCursorPosition--;
this.setPatchedCaretPosition(el, prevCursorPosition, value);
this.setPatchedCaretPosition(el, newCaretPosition, value);
}

@@ -397,2 +508,17 @@ }

}
onMouseUp(e) {
const el = e.target;
const {selectionStart, selectionEnd, value} = el;
if (selectionStart === selectionEnd) {
const caretPostion = this.correctCaretPosition(value, selectionStart);
if (caretPostion !== selectionStart) {
this.setPatchedCaretPosition(el, caretPostion, value);
}
}
this.props.onMouseUp(e);
}
render() {

@@ -406,2 +532,3 @@ const props = omit(this.props, propTypes);

onKeyDown:this.onKeyDown,
onMouseUp: this.onMouseUp
})

@@ -408,0 +535,0 @@

@@ -7,3 +7,3 @@ module.exports = {

},
devtool: "cheap-module-eval-source-map",
devtool: "eval-source-map",
debug: true,

@@ -10,0 +10,0 @@ output: {

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc