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

react-number-format

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-number-format - npm Package Compare versions

Comparing version 0.1.3 to 1.0.0

386

dist/react-number-format.js
/*!
* react-number-format - 0.1.3
* react-number-format - 1.0.0
* Author : Sudhanshu Yadav

@@ -73,170 +73,284 @@ * Copyright (c) 2016 to Sudhanshu Yadav - ignitersworld.com , released under the MIT license.

var React = __webpack_require__(2);
var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var NumberFormat = React.createClass({
displayName: 'NumberFormat',
getInitialState: function getInitialState() {
return {
value: this.formatInput(this.props.value).formattedValue
var _react = __webpack_require__(2);
var _react2 = _interopRequireDefault(_react);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } //const React = require('react');
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
var propTypes = {
thousandSeparator: _react.PropTypes.oneOf([',', '.', true, false]),
decimalSeperator: _react.PropTypes.oneOf([',', '.', true, false]),
displayType: _react.PropTypes.oneOf(['input', 'text']),
prefix: _react.PropTypes.string,
suffix: _react.PropTypes.string,
format: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]),
mask: _react.PropTypes.string,
value: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string])
};
var defaultProps = {
displayType: 'input',
decimalSeperator: '.'
};
var NumberFormat = function (_React$Component) {
_inherits(NumberFormat, _React$Component);
function NumberFormat(props) {
_classCallCheck(this, NumberFormat);
var _this = _possibleConstructorReturn(this, (NumberFormat.__proto__ || Object.getPrototypeOf(NumberFormat)).call(this, props));
_this.state = {
value: _this.formatInput(props.value).formattedValue
};
},
getDefaultProps: function getDefaultProps() {
return {
displayType: 'input'
};
},
componentWillReceiveProps: function componentWillReceiveProps(newProps) {
this.setState({
value: this.formatInput(newProps.value).formattedValue
});
},
setCaretPosition: function setCaretPosition(caretPos) {
var el = this.refs.input;
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;
_this.onChange = _this.onChange.bind(_this);
_this.onInput = _this.onInput.bind(_this);
return _this;
}
_createClass(NumberFormat, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(newProps) {
this.setState({
value: this.formatInput(newProps.value).formattedValue
});
}
}, {
key: 'getSeperators',
value: function getSeperators() {
var _props = this.props;
var thousandSeparator = _props.thousandSeparator;
var decimalSeperator = _props.decimalSeperator;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
if (decimalSeperator && thousandSeparator) {
decimalSeperator = thousandSeparator === ',' ? '.' : ',';
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
if (decimalSeperator === true) {
decimalSeperator = '.';
}
return {
decimalSeperator: decimalSeperator,
thousandSeparator: thousandSeparator
};
}
},
formatWithPattern: function formatWithPattern(str) {
var _props = this.props;
var format = _props.format;
var mask = _props.mask;
}, {
key: 'getNumberRegex',
value: function getNumberRegex(g) {
var _getSeperators = this.getSeperators();
if (!format) return str;
var hashCount = format.split('#').length - 1;
var hashIdx = 0;
var frmtdStr = format;
var decimalSeperator = _getSeperators.decimalSeperator;
for (var i = 0, ln = str.length; i < ln; i++) {
if (i < hashCount) {
hashIdx = frmtdStr.indexOf('#');
frmtdStr = frmtdStr.replace('#', str[i]);
return new RegExp('\\d' + (decimalSeperator ? '|' + escapeRegExp(decimalSeperator) : ''), g ? 'g' : undefined);
}
}, {
key: 'setCaretPosition',
value: function setCaretPosition(caretPos) {
var el = this.refs.input;
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;
}
}
}, {
key: 'formatWithPattern',
value: function formatWithPattern(str) {
var _props2 = this.props;
var format = _props2.format;
var mask = _props2.mask;
var lastIdx = frmtdStr.lastIndexOf('#');
if (!format) return str;
var hashCount = format.split('#').length - 1;
var hashIdx = 0;
var frmtdStr = format;
if (mask) {
return frmtdStr.replace(/#/g, mask);
for (var i = 0, ln = str.length; i < ln; i++) {
if (i < hashCount) {
hashIdx = frmtdStr.indexOf('#');
frmtdStr = frmtdStr.replace('#', str[i]);
}
}
var lastIdx = frmtdStr.lastIndexOf('#');
if (mask) {
return frmtdStr.replace(/#/g, mask);
}
return frmtdStr.substring(0, hashIdx + 1) + (lastIdx !== -1 ? frmtdStr.substring(lastIdx + 1, frmtdStr.length) : '');
}
return frmtdStr.substring(0, hashIdx + 1) + (lastIdx !== -1 ? frmtdStr.substring(lastIdx + 1, frmtdStr.length) : '');
},
formatInput: function formatInput(val) {
var _props2 = this.props;
var prefix = _props2.prefix;
var thousandSeparator = _props2.thousandSeparator;
var suffix = _props2.suffix;
var mask = _props2.mask;
var format = _props2.format;
}, {
key: 'formatInput',
value: function formatInput(val) {
var _props3 = this.props;
var prefix = _props3.prefix;
var suffix = _props3.suffix;
var mask = _props3.mask;
var format = _props3.format;
var maskPattern = format && typeof format == "string" && !!mask;
var _getSeperators2 = this.getSeperators();
if (!val || !(val + "").match(/\d/g)) return { value: "", formattedValue: maskPattern ? "" : "" };
var num = (val + "").match(/\d/g).join("");
var thousandSeparator = _getSeperators2.thousandSeparator;
var decimalSeperator = _getSeperators2.decimalSeperator;
var formattedValue = num;
var maskPattern = format && typeof format == 'string' && !!mask;
if (format) {
if (typeof format == 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format == "function") {
formattedValue = format(formattedValue);
var numRegex = this.getNumberRegex(true);
if (!val || !(val + '').match(numRegex)) return { value: '', formattedValue: maskPattern ? '' : '' };
var num = (val + '').match(numRegex).join('');
var formattedValue = num;
if (format) {
if (typeof format == 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format == 'function') {
formattedValue = format(formattedValue);
}
} else {
var beforeDecimal = formattedValue,
afterDecimal = '';
var hasDecimals = formattedValue.indexOf(decimalSeperator) !== -1;
if (decimalSeperator && hasDecimals) {
var parts = formattedValue.split(decimalSeperator);
beforeDecimal = parts[0];
afterDecimal = parts[1];
}
if (thousandSeparator) {
beforeDecimal = beforeDecimal.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + thousandSeparator);
}
//add prefix and suffix
if (prefix) beforeDecimal = prefix + beforeDecimal;
if (suffix) afterDecimal = afterDecimal + suffix;
formattedValue = beforeDecimal + (hasDecimals && decimalSeperator || '') + afterDecimal;
}
} else {
if (thousandSeparator) formattedValue = formattedValue.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
//add prefix and suffix
if (prefix) formattedValue = prefix + formattedValue;
if (suffix) formattedValue = formattedValue + suffix;
return {
value: formattedValue.match(numRegex).join(''),
formattedValue: formattedValue
};
}
}, {
key: 'getCursorPosition',
value: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var numRegex = this.getNumberRegex();
return {
value: formattedValue.match(/\d/g).join(""),
formattedValue: formattedValue
};
},
getCursorPosition: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var j = 0;
for (var i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(/\d/) && inputValue[i] !== formattedValue[j]) continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
j++;
}j++;
}
var j = 0;
for (var i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
j++;
}j++;
}
//check if there is no number before caret position
while (j > 0 && formattedValue[j]) {
if (!formattedValue[j - 1].match(/\d/)) j--;else break;
//check if there is no number before caret position
while (j > 0 && formattedValue[j]) {
if (!formattedValue[j - 1].match(numRegex)) j--;else break;
}
return j;
}
return j;
},
onChangeHandler: function onChangeHandler(e, callback) {
var _this = this;
}, {
key: 'onChangeHandler',
value: function onChangeHandler(e, callback) {
var _this2 = this;
var inputValue = e.target.value;
e.persist();
var inputValue = e.target.value + '';
var _formatInput = this.formatInput(inputValue);
var _formatInput = this.formatInput(inputValue);
var formattedValue = _formatInput.formattedValue;
var value = _formatInput.value;
var formattedValue = _formatInput.formattedValue;
var value = _formatInput.value;
var cursorPos = this.refs.input.selectionStart;
var cursorPos = this.refs.input.selectionStart;
//change the state
this.setState({ value: formattedValue }, function () {
cursorPos = _this.getCursorPosition(inputValue, formattedValue, cursorPos);
_this.setCaretPosition(cursorPos);
if (callback) callback(e, value);
});
//change the state
this.setState({ value: formattedValue }, function () {
cursorPos = _this2.getCursorPosition(inputValue, formattedValue, cursorPos);
_this2.setCaretPosition(cursorPos);
if (callback) callback(e, value);
});
return value;
},
onChange: function onChange(e) {
this.onChangeHandler(e, this.props.onChange);
},
onInput: function onInput(e) {
this.onChangeHandler(e, this.props.onInput);
},
render: function render() {
var props = _extends({}, this.props);
return value;
}
}, {
key: 'onChange',
value: function onChange(e) {
this.onChangeHandler(e, this.props.onChange);
}
}, {
key: 'onInput',
value: function onInput(e) {
this.onChangeHandler(e, this.props.onInput);
}
}, {
key: 'render',
value: function render() {
var props = _extends({}, this.props);
['thousandSeparator', 'displayType', 'prefix', 'suffix', 'format', 'mask', 'value'].forEach(function (key) {
delete props[key];
});
Object.keys(propTypes).forEach(function (key) {
delete props[key];
});
if (this.props.displayType === "text") {
return React.createElement(
'span',
props,
this.state.value
);
if (this.props.displayType === 'text') {
return _react2.default.createElement(
'span',
props,
this.state.value
);
}
return _react2.default.createElement('input', _extends({}, props, {
type: 'tel',
value: this.state.value,
ref: 'input',
onInput: this.onChange,
onChange: this.onChange
}));
}
return React.createElement('input', _extends({}, props, {
type: 'tel',
value: this.state.value,
ref: 'input',
onInput: this.onChange,
onChange: this.onChange
}));
}
});
}]);
return NumberFormat;
}(_react2.default.Component);
NumberFormat.propTypes = propTypes;
NumberFormat.defaultProps = defaultProps;
module.exports = NumberFormat;

@@ -243,0 +357,0 @@

/*!
* react-number-format - 0.1.3
* react-number-format - 1.0.0
* Author : Sudhanshu Yadav
* Copyright (c) 2016 to Sudhanshu Yadav - ignitersworld.com , released under the MIT license.
*/
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):"object"==typeof exports?exports.NumberFormat=e(require("react")):t.NumberFormat=e(t.React)}(this,function(t){return function(t){function e(n){if(r[n])return r[n].exports;var a=r[n]={exports:{},id:n,loaded:!1};return t[n].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){t.exports=r(1)},function(t,e,r){"use strict";var n=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},a=r(2),o=a.createClass({displayName:"NumberFormat",getInitialState:function(){return{value:this.formatInput(this.props.value).formattedValue}},getDefaultProps:function(){return{displayType:"input"}},componentWillReceiveProps:function(t){this.setState({value:this.formatInput(t.value).formattedValue})},setCaretPosition:function(t){var e=this.refs.input;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)}},formatWithPattern:function(t){var e=this.props,r=e.format,n=e.mask;if(!r)return t;for(var a=r.split("#").length-1,o=0,i=r,s=0,u=t.length;s<u;s++)s<a&&(o=i.indexOf("#"),i=i.replace("#",t[s]));var f=i.lastIndexOf("#");return n?i.replace(/#/g,n):i.substring(0,o+1)+(f!==-1?i.substring(f+1,i.length):"")},formatInput:function(t){var e=this.props,r=e.prefix,n=e.thousandSeparator,a=e.suffix,o=(e.mask,e.format);if(!t||!(t+"").match(/\d/g))return{value:"",formattedValue:""};var i=(t+"").match(/\d/g).join(""),s=i;return o?"string"==typeof o?s=this.formatWithPattern(s):"function"==typeof o&&(s=o(s)):(n&&(s=s.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1,")),r&&(s=r+s),a&&(s+=a)),{value:s.match(/\d/g).join(""),formattedValue:s}},getCursorPosition:function(t,e,r){for(var n=0,a=0;a<r;a++)if(t[a].match(/\d/)||t[a]===e[n]){for(;t[a]!==e[n]&&n<e.length;)n++;n++}for(;n>0&&e[n]&&!e[n-1].match(/\d/);)n--;return n},onChangeHandler:function(t,e){var r=this,n=t.target.value,a=this.formatInput(n),o=a.formattedValue,i=a.value,s=this.refs.input.selectionStart;return this.setState({value:o},function(){s=r.getCursorPosition(n,o,s),r.setCaretPosition(s),e&&e(t,i)}),i},onChange:function(t){this.onChangeHandler(t,this.props.onChange)},onInput:function(t){this.onChangeHandler(t,this.props.onInput)},render:function(){var t=n({},this.props);return["thousandSeparator","displayType","prefix","suffix","format","mask","value"].forEach(function(e){delete t[e]}),"text"===this.props.displayType?a.createElement("span",t,this.state.value):a.createElement("input",n({},t,{type:"tel",value:this.state.value,ref:"input",onInput:this.onChange,onChange:this.onChange}))}});t.exports=o},function(e,r){e.exports=t}])});
!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(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}var s=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},p=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}}(),f=r(2),l=n(f),c={thousandSeparator:f.PropTypes.oneOf([",",".",!0,!1]),decimalSeperator:f.PropTypes.oneOf([",",".",!0,!1]),displayType:f.PropTypes.oneOf(["input","text"]),prefix:f.PropTypes.string,suffix:f.PropTypes.string,format:f.PropTypes.oneOfType([f.PropTypes.string,f.PropTypes.func]),mask:f.PropTypes.string,value:f.PropTypes.oneOfType([f.PropTypes.number,f.PropTypes.string])},h={displayType:"input",decimalSeperator:"."},y=function(e){function t(e){o(this,t);var r=a(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.state={value:r.formatInput(e.value).formattedValue},r.onChange=r.onChange.bind(r),r.onInput=r.onInput.bind(r),r}return i(t,e),p(t,[{key:"componentWillReceiveProps",value:function(e){this.setState({value:this.formatInput(e.value).formattedValue})}},{key:"getSeperators",value:function(){var e=this.props,t=e.thousandSeparator,r=e.decimalSeperator;return t===!0&&(t=","),r&&t&&(r=","===t?".":","),r===!0&&(r="."),{decimalSeperator:r,thousandSeparator:t}}},{key:"getNumberRegex",value:function(e){var t=this.getSeperators(),r=t.decimalSeperator;return new RegExp("\\d"+(r?"|"+u(r):""),e?"g":void 0)}},{key:"setCaretPosition",value:function(e){var t=this.refs.input;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)}}},{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 p=i.lastIndexOf("#");return n?i.replace(/#/g,n):i.substring(0,a+1)+(p!==-1?i.substring(p+1,i.length):"")}},{key:"formatInput",value:function(e){var t=this.props,r=t.prefix,n=t.suffix,o=(t.mask,t.format),a=this.getSeperators(),i=a.thousandSeparator,u=a.decimalSeperator,s=this.getNumberRegex(!0);if(!e||!(e+"").match(s))return{value:"",formattedValue:""};var p=(e+"").match(s).join(""),f=p;if(o)"string"==typeof o?f=this.formatWithPattern(f):"function"==typeof o&&(f=o(f));else{var l=f,c="",h=f.indexOf(u)!==-1;if(u&&h){var y=f.split(u);l=y[0],c=y[1]}i&&(l=l.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1"+i)),r&&(l=r+l),n&&(c+=n),f=l+(h&&u||"")+c}return{value:f.match(s).join(""),formattedValue:f}}},{key:"getCursorPosition",value:function(e,t,r){for(var n=this.getNumberRegex(),o=0,a=0;a<r;a++)if(e[a].match(n)||e[a]===t[o]){for(;e[a]!==t[o]&&o<t.length;)o++;o++}for(;o>0&&t[o]&&!t[o-1].match(n);)o--;return o}},{key:"onChangeHandler",value:function(e,t){var r=this;e.persist();var n=e.target.value+"",o=this.formatInput(n),a=o.formattedValue,i=o.value,u=this.refs.input.selectionStart;return this.setState({value:a},function(){u=r.getCursorPosition(n,a,u),r.setCaretPosition(u),t&&t(e,i)}),i}},{key:"onChange",value:function(e){this.onChangeHandler(e,this.props.onChange)}},{key:"onInput",value:function(e){this.onChangeHandler(e,this.props.onInput)}},{key:"render",value:function(){var e=s({},this.props);return Object.keys(c).forEach(function(t){delete e[t]}),"text"===this.props.displayType?l["default"].createElement("span",e,this.state.value):l["default"].createElement("input",s({},e,{type:"tel",value:this.state.value,ref:"input",onInput:this.onChange,onChange:this.onChange}))}}]),t}(l["default"].Component);y.propTypes=c,y.defaultProps=h,e.exports=y},function(t,r){t.exports=e}])});

@@ -1,10 +0,13 @@

const React = require('react');
const ReactDOM = require('react-dom');
const NumberFormat = require('../../src/number_format');
import React from 'react';
import ReactDOM from 'react-dom';
import NumberFormat from '../../src/number_format';
const App = React.createClass({
getInitialState : function(){
return {};
},
formatExpiryChange: function(val){
class App extends React.Component {
constructor() {
super();
this.state = {};
this.formatExpiryChange = this.formatExpiryChange.bind(this);
}
formatExpiryChange(val) {
if(val && Number(val[0]) > 1){

@@ -18,4 +21,5 @@ val = '0'+val;

return val;
},
render : function(){
}
render() {
return (

@@ -46,2 +50,9 @@ <div>

<h3>
Custom thousand seperator : Format currency in input
</h3>
<NumberFormat thousandSeparator={'.'} decimalSeperator={','} prefix={'$'} />
</div>
<div className="example">
<h3>
Format with pattern : Format credit card in an input

@@ -68,4 +79,5 @@ </h3>

}
});
}
ReactDOM.render(<App />, document.getElementById('app'));

@@ -5,170 +5,284 @@ 'use strict';

var React = require('react');
var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var NumberFormat = React.createClass({
displayName: 'NumberFormat',
getInitialState: function getInitialState() {
return {
value: this.formatInput(this.props.value).formattedValue
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } //const React = require('react');
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
var propTypes = {
thousandSeparator: _react.PropTypes.oneOf([',', '.', true, false]),
decimalSeperator: _react.PropTypes.oneOf([',', '.', true, false]),
displayType: _react.PropTypes.oneOf(['input', 'text']),
prefix: _react.PropTypes.string,
suffix: _react.PropTypes.string,
format: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.func]),
mask: _react.PropTypes.string,
value: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string])
};
var defaultProps = {
displayType: 'input',
decimalSeperator: '.'
};
var NumberFormat = function (_React$Component) {
_inherits(NumberFormat, _React$Component);
function NumberFormat(props) {
_classCallCheck(this, NumberFormat);
var _this = _possibleConstructorReturn(this, (NumberFormat.__proto__ || Object.getPrototypeOf(NumberFormat)).call(this, props));
_this.state = {
value: _this.formatInput(props.value).formattedValue
};
},
getDefaultProps: function getDefaultProps() {
return {
displayType: 'input'
};
},
componentWillReceiveProps: function componentWillReceiveProps(newProps) {
this.setState({
value: this.formatInput(newProps.value).formattedValue
});
},
setCaretPosition: function setCaretPosition(caretPos) {
var el = this.refs.input;
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;
_this.onChange = _this.onChange.bind(_this);
_this.onInput = _this.onInput.bind(_this);
return _this;
}
_createClass(NumberFormat, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(newProps) {
this.setState({
value: this.formatInput(newProps.value).formattedValue
});
}
}, {
key: 'getSeperators',
value: function getSeperators() {
var _props = this.props;
var thousandSeparator = _props.thousandSeparator;
var decimalSeperator = _props.decimalSeperator;
if (thousandSeparator === true) {
thousandSeparator = ',';
}
// (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
if (decimalSeperator && thousandSeparator) {
decimalSeperator = thousandSeparator === ',' ? '.' : ',';
}
// fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
if (decimalSeperator === true) {
decimalSeperator = '.';
}
return {
decimalSeperator: decimalSeperator,
thousandSeparator: thousandSeparator
};
}
},
formatWithPattern: function formatWithPattern(str) {
var _props = this.props;
var format = _props.format;
var mask = _props.mask;
}, {
key: 'getNumberRegex',
value: function getNumberRegex(g) {
var _getSeperators = this.getSeperators();
if (!format) return str;
var hashCount = format.split('#').length - 1;
var hashIdx = 0;
var frmtdStr = format;
var decimalSeperator = _getSeperators.decimalSeperator;
for (var i = 0, ln = str.length; i < ln; i++) {
if (i < hashCount) {
hashIdx = frmtdStr.indexOf('#');
frmtdStr = frmtdStr.replace('#', str[i]);
return new RegExp('\\d' + (decimalSeperator ? '|' + escapeRegExp(decimalSeperator) : ''), g ? 'g' : undefined);
}
}, {
key: 'setCaretPosition',
value: function setCaretPosition(caretPos) {
var el = this.refs.input;
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;
}
}
}, {
key: 'formatWithPattern',
value: function formatWithPattern(str) {
var _props2 = this.props;
var format = _props2.format;
var mask = _props2.mask;
var lastIdx = frmtdStr.lastIndexOf('#');
if (!format) return str;
var hashCount = format.split('#').length - 1;
var hashIdx = 0;
var frmtdStr = format;
if (mask) {
return frmtdStr.replace(/#/g, mask);
for (var i = 0, ln = str.length; i < ln; i++) {
if (i < hashCount) {
hashIdx = frmtdStr.indexOf('#');
frmtdStr = frmtdStr.replace('#', str[i]);
}
}
var lastIdx = frmtdStr.lastIndexOf('#');
if (mask) {
return frmtdStr.replace(/#/g, mask);
}
return frmtdStr.substring(0, hashIdx + 1) + (lastIdx !== -1 ? frmtdStr.substring(lastIdx + 1, frmtdStr.length) : '');
}
return frmtdStr.substring(0, hashIdx + 1) + (lastIdx !== -1 ? frmtdStr.substring(lastIdx + 1, frmtdStr.length) : '');
},
formatInput: function formatInput(val) {
var _props2 = this.props;
var prefix = _props2.prefix;
var thousandSeparator = _props2.thousandSeparator;
var suffix = _props2.suffix;
var mask = _props2.mask;
var format = _props2.format;
}, {
key: 'formatInput',
value: function formatInput(val) {
var _props3 = this.props;
var prefix = _props3.prefix;
var suffix = _props3.suffix;
var mask = _props3.mask;
var format = _props3.format;
var maskPattern = format && typeof format == "string" && !!mask;
var _getSeperators2 = this.getSeperators();
if (!val || !(val + "").match(/\d/g)) return { value: "", formattedValue: maskPattern ? "" : "" };
var num = (val + "").match(/\d/g).join("");
var thousandSeparator = _getSeperators2.thousandSeparator;
var decimalSeperator = _getSeperators2.decimalSeperator;
var formattedValue = num;
var maskPattern = format && typeof format == 'string' && !!mask;
if (format) {
if (typeof format == 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format == "function") {
formattedValue = format(formattedValue);
var numRegex = this.getNumberRegex(true);
if (!val || !(val + '').match(numRegex)) return { value: '', formattedValue: maskPattern ? '' : '' };
var num = (val + '').match(numRegex).join('');
var formattedValue = num;
if (format) {
if (typeof format == 'string') {
formattedValue = this.formatWithPattern(formattedValue);
} else if (typeof format == 'function') {
formattedValue = format(formattedValue);
}
} else {
var beforeDecimal = formattedValue,
afterDecimal = '';
var hasDecimals = formattedValue.indexOf(decimalSeperator) !== -1;
if (decimalSeperator && hasDecimals) {
var parts = formattedValue.split(decimalSeperator);
beforeDecimal = parts[0];
afterDecimal = parts[1];
}
if (thousandSeparator) {
beforeDecimal = beforeDecimal.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + thousandSeparator);
}
//add prefix and suffix
if (prefix) beforeDecimal = prefix + beforeDecimal;
if (suffix) afterDecimal = afterDecimal + suffix;
formattedValue = beforeDecimal + (hasDecimals && decimalSeperator || '') + afterDecimal;
}
} else {
if (thousandSeparator) formattedValue = formattedValue.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
//add prefix and suffix
if (prefix) formattedValue = prefix + formattedValue;
if (suffix) formattedValue = formattedValue + suffix;
return {
value: formattedValue.match(numRegex).join(''),
formattedValue: formattedValue
};
}
}, {
key: 'getCursorPosition',
value: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var numRegex = this.getNumberRegex();
return {
value: formattedValue.match(/\d/g).join(""),
formattedValue: formattedValue
};
},
getCursorPosition: function getCursorPosition(inputValue, formattedValue, cursorPos) {
var j = 0;
for (var i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(/\d/) && inputValue[i] !== formattedValue[j]) continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
j++;
}j++;
}
var j = 0;
for (var i = 0; i < cursorPos; i++) {
if (!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
while (inputValue[i] !== formattedValue[j] && j < formattedValue.length) {
j++;
}j++;
}
//check if there is no number before caret position
while (j > 0 && formattedValue[j]) {
if (!formattedValue[j - 1].match(/\d/)) j--;else break;
//check if there is no number before caret position
while (j > 0 && formattedValue[j]) {
if (!formattedValue[j - 1].match(numRegex)) j--;else break;
}
return j;
}
return j;
},
onChangeHandler: function onChangeHandler(e, callback) {
var _this = this;
}, {
key: 'onChangeHandler',
value: function onChangeHandler(e, callback) {
var _this2 = this;
var inputValue = e.target.value;
e.persist();
var inputValue = e.target.value + '';
var _formatInput = this.formatInput(inputValue);
var _formatInput = this.formatInput(inputValue);
var formattedValue = _formatInput.formattedValue;
var value = _formatInput.value;
var formattedValue = _formatInput.formattedValue;
var value = _formatInput.value;
var cursorPos = this.refs.input.selectionStart;
var cursorPos = this.refs.input.selectionStart;
//change the state
this.setState({ value: formattedValue }, function () {
cursorPos = _this.getCursorPosition(inputValue, formattedValue, cursorPos);
_this.setCaretPosition(cursorPos);
if (callback) callback(e, value);
});
//change the state
this.setState({ value: formattedValue }, function () {
cursorPos = _this2.getCursorPosition(inputValue, formattedValue, cursorPos);
_this2.setCaretPosition(cursorPos);
if (callback) callback(e, value);
});
return value;
},
onChange: function onChange(e) {
this.onChangeHandler(e, this.props.onChange);
},
onInput: function onInput(e) {
this.onChangeHandler(e, this.props.onInput);
},
render: function render() {
var props = _extends({}, this.props);
return value;
}
}, {
key: 'onChange',
value: function onChange(e) {
this.onChangeHandler(e, this.props.onChange);
}
}, {
key: 'onInput',
value: function onInput(e) {
this.onChangeHandler(e, this.props.onInput);
}
}, {
key: 'render',
value: function render() {
var props = _extends({}, this.props);
['thousandSeparator', 'displayType', 'prefix', 'suffix', 'format', 'mask', 'value'].forEach(function (key) {
delete props[key];
});
Object.keys(propTypes).forEach(function (key) {
delete props[key];
});
if (this.props.displayType === "text") {
return React.createElement(
'span',
props,
this.state.value
);
if (this.props.displayType === 'text') {
return _react2.default.createElement(
'span',
props,
this.state.value
);
}
return _react2.default.createElement('input', _extends({}, props, {
type: 'tel',
value: this.state.value,
ref: 'input',
onInput: this.onChange,
onChange: this.onChange
}));
}
return React.createElement('input', _extends({}, props, {
type: 'tel',
value: this.state.value,
ref: 'input',
onInput: this.onChange,
onChange: this.onChange
}));
}
});
}]);
return NumberFormat;
}(_react2.default.Component);
NumberFormat.propTypes = propTypes;
NumberFormat.defaultProps = defaultProps;
module.exports = NumberFormat;
{
"name": "react-number-format",
"description": "React component to format number in an input or as a text.",
"version": "0.1.3",
"version": "1.0.0",
"main": "lib/number_format.js",

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

@@ -20,3 +20,4 @@ # react-number-format

| ------------- |-------------| -----| -------- |
| thousandSeparator | Boolean: true/false | false | Add thousand separators on number |
| thousandSeparator | mixed: true/false (boolean) or ,/. (string) | false | Add thousand separators on number |
| decimalSeperator | mixed: ./, (string) or true/false (boolean)| . | Suppor decimal point on a number |
| prefix | String (ex : $) | none | Add a prefix before the number |

@@ -82,2 +83,10 @@ | suffix | String (ex : /-) | none | Add a prefix after the number |

### Major Updates
### v1.0.0
- Support decimals
- Support changing thousandSeparator to ','
- Updated complete code to ES6
- Added propTypes validation
- Fixed #1, #7, #8, #9
### Development

@@ -84,0 +93,0 @@ - Download the zip

@@ -1,21 +0,72 @@

const React = require('react');
//const React = require('react');
import React, {PropTypes} from 'react';
const NumberFormat = React.createClass({
displayName : 'NumberFormat',
getInitialState : function(){
return {
value : this.formatInput(this.props.value).formattedValue
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
const propTypes = {
thousandSeparator: PropTypes.oneOf([',', '.', true, false]),
decimalSeperator: PropTypes.oneOf([',', '.', true, false]),
displayType: PropTypes.oneOf(['input', 'text']),
prefix: PropTypes.string,
suffix: PropTypes.string,
format: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func
]),
mask: PropTypes.string,
value: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string
])
};
const defaultProps = {
displayType: 'input',
decimalSeperator: '.'
};
class NumberFormat extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.formatInput(props.value).formattedValue
}
},
getDefaultProps : function(){
return {
displayType : 'input'
}
},
componentWillReceiveProps: function(newProps){
this.onChange = this.onChange.bind(this);
this.onInput = this.onInput.bind(this);
}
componentWillReceiveProps(newProps) {
this.setState({
value : this.formatInput(newProps.value).formattedValue
});
},
setCaretPosition : function(caretPos) {
}
getSeperators() {
let {thousandSeparator, decimalSeperator} = this.props;
if (thousandSeparator === true) {
thousandSeparator = ','
}
if (decimalSeperator && thousandSeparator) {
decimalSeperator = thousandSeparator === ',' ? '.' : ',';
}
if (decimalSeperator === true) {
decimalSeperator = '.'
}
return {
decimalSeperator,
thousandSeparator
}
}
getNumberRegex(g) {
const {decimalSeperator} = this.getSeperators();
return new RegExp('\\d' + (decimalSeperator ? '|' + escapeRegExp(decimalSeperator) : ''), g ? 'g' : undefined);
}
setCaretPosition(caretPos) {
const el = this.refs.input;

@@ -45,4 +96,5 @@ el.value = el.value;

}
},
formatWithPattern : function(str){
}
formatWithPattern(str) {
const {format,mask} = this.props;

@@ -67,10 +119,14 @@ if (!format) return str;

return frmtdStr.substring(0,hashIdx + 1) + (lastIdx!==-1 ? frmtdStr.substring(lastIdx + 1, frmtdStr.length) :'');
},
formatInput : function(val){
const {prefix, thousandSeparator, suffix, mask,format} = this.props;
const maskPattern = format && typeof format == "string" && !!mask;
}
if(!val || !((val+"").match(/\d/g))) return {value :"", formattedValue: (maskPattern ? "" : "")}
const num = (val+"").match(/\d/g).join("");
formatInput(val) {
const {prefix, suffix, mask, format} = this.props;
const {thousandSeparator, decimalSeperator} = this.getSeperators()
const maskPattern = format && typeof format == 'string' && !!mask;
const numRegex = this.getNumberRegex(true);
if(!val || !((val+'').match(numRegex))) return {value :'', formattedValue: (maskPattern ? '' : '')}
const num = (val+'').match(numRegex).join('');
let formattedValue = num;

@@ -82,3 +138,3 @@

}
else if(typeof format == "function"){
else if(typeof format == 'function'){
formattedValue = format(formattedValue);

@@ -88,18 +144,31 @@ }

else{
if(thousandSeparator) formattedValue = formattedValue.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
let beforeDecimal = formattedValue, afterDecimal = '';
const hasDecimals = formattedValue.indexOf(decimalSeperator) !== -1;
if(decimalSeperator && hasDecimals) {
const parts = formattedValue.split(decimalSeperator)
beforeDecimal = parts[0];
afterDecimal = parts[1];
}
if(thousandSeparator) {
beforeDecimal = beforeDecimal.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + thousandSeparator);
}
//add prefix and suffix
if(prefix) beforeDecimal = prefix + beforeDecimal;
if(suffix) afterDecimal = afterDecimal + suffix;
//add prefix and suffix
if(prefix) formattedValue = prefix + formattedValue;
if(suffix) formattedValue = formattedValue + suffix;
formattedValue = beforeDecimal + (hasDecimals && decimalSeperator || '') + afterDecimal;
}
return {
value : formattedValue.match(/\d/g).join(""),
value : formattedValue.match(numRegex).join(''),
formattedValue : formattedValue
}
},
getCursorPosition : function(inputValue,formattedValue,cursorPos){
}
getCursorPosition(inputValue, formattedValue, cursorPos) {
const numRegex = this.getNumberRegex();
let j=0;
for(let i=0; i<cursorPos; i++){
if(!inputValue[i].match(/\d/) && inputValue[i] !== formattedValue[j]) continue;
if(!inputValue[i].match(numRegex) && inputValue[i] !== formattedValue[j]) continue;
while(inputValue[i] !== formattedValue[j] && j<formattedValue.length) j++;

@@ -111,9 +180,11 @@ j++;

while(j > 0 && formattedValue[j]){
if(!formattedValue[j-1].match(/\d/)) j--;
if(!formattedValue[j-1].match(numRegex)) j--;
else break;
}
return j;
},
onChangeHandler : function(e,callback){
const inputValue = e.target.value;
}
onChangeHandler(e,callback) {
e.persist();
const inputValue = e.target.value + '';
const {formattedValue,value} = this.formatInput(inputValue);

@@ -124,3 +195,3 @@ let cursorPos = this.refs.input.selectionStart;

this.setState({value : formattedValue},()=>{
cursorPos = this.getCursorPosition(inputValue, formattedValue,cursorPos );
cursorPos = this.getCursorPosition(inputValue, formattedValue, cursorPos );
this.setCaretPosition(cursorPos);

@@ -131,13 +202,14 @@ if(callback) callback(e,value);

return value;
},
onChange : function(e){
}
onChange(e) {
this.onChangeHandler(e,this.props.onChange);
},
onInput : function(e){
}
onInput(e) {
this.onChangeHandler(e,this.props.onInput);
},
render : function(){
}
render() {
const props = Object.assign({}, this.props);
['thousandSeparator', 'displayType', 'prefix', 'suffix', 'format', 'mask', 'value'].forEach((key) => {
Object.keys(propTypes).forEach((key) => {
delete props[key];

@@ -147,3 +219,3 @@ });

if(this.props.displayType === "text"){
if(this.props.displayType === 'text'){
return (<span {...props}>{this.state.value}</span>);

@@ -154,3 +226,3 @@ }

{...props}
type='tel'
type="tel"
value={this.state.value}

@@ -163,4 +235,7 @@ ref="input"

}
});
}
module.exports = NumberFormat;
NumberFormat.propTypes = propTypes;
NumberFormat.defaultProps = defaultProps;
module.exports = NumberFormat;

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

const React = require('react');
const ReactTestUtils = require('react-addons-test-utils');
const FormatNumberInput = require('../src/number_format');
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import FormatNumberInput from '../src/number_format';

@@ -28,2 +28,3 @@ /*** format_number input as input ****/

it('should listen change event and formmat currency properly', () => {

@@ -42,2 +43,29 @@ const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput thousandSeparator={true} prefix={'$'} />);

it('should maintain decimal points', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput thousandSeparator={true} prefix={'$'} />);
const input = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'input'
);
input.value = "2456981.89";
ReactTestUtils.Simulate.input(input);
expect(input.value).toEqual("$2,456,981.89");
});
it('should support custom thousand seperator', () => {
const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput thousandSeparator={'.'} decimalSeperator={','} prefix={'$'} />);
const input = ReactTestUtils.findRenderedDOMComponentWithTag(
component, 'input'
);
input.value = "2456981,89";
ReactTestUtils.Simulate.input(input);
expect(input.value).toEqual("$2.456.981,89");
});
it('should have proper intermediate formatting', () => {

@@ -44,0 +72,0 @@ const component = ReactTestUtils.renderIntoDocument(<FormatNumberInput format="#### #### #### ####" />);

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