react-number-format-datagrid-stable-version
Version:
React component to format number in an input or as a text.
261 lines (208 loc) • 8.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.noop = noop;
exports.returnTrue = returnTrue;
exports.charIsNumber = charIsNumber;
exports.isNil = isNil;
exports.escapeRegExp = escapeRegExp;
exports.getThousandsGroupRegex = getThousandsGroupRegex;
exports.applyThousandSeparator = applyThousandSeparator;
exports.splitDecimal = splitDecimal;
exports.fixLeadingZero = fixLeadingZero;
exports.limitToScale = limitToScale;
exports.toNumericString = toNumericString;
exports.roundToPrecision = roundToPrecision;
exports.setCaretPosition = setCaretPosition;
exports.findChangedIndex = findChangedIndex;
exports.clamp = clamp;
exports.getCurrentCaretPosition = getCurrentCaretPosition;
exports.addInputMode = addInputMode;
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
// basic noop function
function noop() {}
function returnTrue() {
return true;
}
function charIsNumber(_char) {
return !!(_char || '').match(/\d/);
}
function isNil(val) {
return val === null || val === undefined;
}
function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function getThousandsGroupRegex(thousandsGroupStyle) {
switch (thousandsGroupStyle) {
case 'lakh':
return /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/g;
case 'wan':
return /(\d)(?=(\d{4})+(?!\d))/g;
case 'thousand':
default:
return /(\d)(?=(\d{3})+(?!\d))/g;
}
}
function applyThousandSeparator(str, thousandSeparator, thousandsGroupStyle) {
var thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
var index = str.search(/[1-9]/);
index = index === -1 ? str.length : index;
return str.substring(0, index) + str.substring(index, str.length).replace(thousandsGroupRegex, '$1' + thousandSeparator);
} //spilt a float number into different parts beforeDecimal, afterDecimal, and negation
function splitDecimal(numStr) {
var allowNegative = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var hasNagation = numStr[0] === '-';
var addNegation = hasNagation && allowNegative;
numStr = numStr.replace('-', '');
var parts = numStr.split('.');
var beforeDecimal = parts[0];
var afterDecimal = parts[1] || '';
return {
beforeDecimal: beforeDecimal,
afterDecimal: afterDecimal,
hasNagation: hasNagation,
addNegation: addNegation
};
}
function fixLeadingZero(numStr) {
if (!numStr) return numStr;
var isNegative = numStr[0] === '-';
if (isNegative) numStr = numStr.substring(1, numStr.length);
var parts = numStr.split('.');
var beforeDecimal = parts[0].replace(/^0+/, '') || '0';
var afterDecimal = parts[1] || '';
return "".concat(isNegative ? '-' : '').concat(beforeDecimal).concat(afterDecimal ? ".".concat(afterDecimal) : '');
}
/**
* limit decimal numbers to given scale
* Not used .fixedTo because that will break with big numbers
*/
function limitToScale(numStr, scale, fixedDecimalScale) {
var str = '';
var filler = fixedDecimalScale ? '0' : '';
for (var i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
}
function repeat(str, count) {
return Array(count + 1).join(str);
}
function toNumericString(num) {
num += ''; // typecast number to string
// store the sign and remove it from the number.
var sign = num[0] === '-' ? '-' : '';
if (sign) num = num.substring(1); // split the number into cofficient and exponent
var _num$split = num.split(/[eE]/g),
_num$split2 = _slicedToArray(_num$split, 2),
coefficient = _num$split2[0],
exponent = _num$split2[1]; // covert exponent to number;
exponent = Number(exponent); // if there is no exponent part or its 0, return the coffiecient with sign
if (!exponent) return sign + coefficient;
coefficient = coefficient.replace('.', '');
/**
* for scientific notation the current decimal index will be after first number (index 0)
* So effective decimal index will always be 1 + exponent value
*/
var decimalIndex = 1 + exponent;
var coffiecientLn = coefficient.length;
if (decimalIndex < 0) {
// if decimal index is less then 0 add preceding 0s
// add 1 as join will have
coefficient = '0.' + repeat('0', Math.abs(decimalIndex)) + coefficient;
} else if (decimalIndex >= coffiecientLn) {
// if decimal index is less then 0 add leading 0s
coefficient = coefficient + repeat('0', decimalIndex - coffiecientLn);
} else {
// else add decimal point at proper index
coefficient = (coefficient.substring(0, decimalIndex) || '0') + '.' + coefficient.substring(decimalIndex);
}
return sign + coefficient;
}
/**
* This method is required to round prop value to given scale.
* Not used .round or .fixedTo because that will break with big numbers
*/
function roundToPrecision(numStr, scale, fixedDecimalScale) {
//if number is empty don't do anything return empty string
if (['', '-'].indexOf(numStr) !== -1) return numStr;
var shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
var _splitDecimal = splitDecimal(numStr),
beforeDecimal = _splitDecimal.beforeDecimal,
afterDecimal = _splitDecimal.afterDecimal,
hasNagation = _splitDecimal.hasNagation;
var floatValue = parseFloat("0.".concat(afterDecimal || '0'));
var floatValueStr = afterDecimal.length <= scale ? "0.".concat(afterDecimal) : floatValue.toFixed(scale);
var roundedDecimalParts = floatValueStr.split('.');
var intPart = beforeDecimal.split('').reverse().reduce(function (roundedStr, current, idx) {
if (roundedStr.length > idx) {
return (Number(roundedStr[0]) + Number(current)).toString() + roundedStr.substring(1, roundedStr.length);
}
return current + roundedStr;
}, roundedDecimalParts[0]);
var decimalPart = limitToScale(roundedDecimalParts[1] || '', Math.min(scale, afterDecimal.length), fixedDecimalScale);
var negation = hasNagation ? '-' : '';
var decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return "".concat(negation).concat(intPart).concat(decimalSeparator).concat(decimalPart);
}
/** set the caret positon in an input field **/
function setCaretPosition(el, caretPos) {
el.value = el.value; // ^ this is used to not only get 'focus', but
// to make sure we don't have it everything -selected-
// (it causes an issue in chrome, and having it doesn't hurt any other browser)
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
} // (el.selectionStart === 0 added for Firefox bug)
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
} // fail city, fortunately this never happens (as far as I've tested) :)
el.focus();
return false;
}
}
/**
Given previous value and newValue it returns the index
start - end to which values have changed.
This function makes assumption about only consecutive
characters are changed which is correct assumption for caret input.
*/
function findChangedIndex(prevValue, newValue) {
var i = 0,
j = 0;
var prevLength = prevValue.length;
var newLength = newValue.length;
while (prevValue[i] === newValue[i] && i < prevLength) {
i++;
} //check what has been changed from last
while (prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] && newLength - j > i && prevLength - j > i) {
j++;
}
return {
start: i,
end: prevLength - j
};
}
/*
Returns a number whose value is limited to the given range
*/
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function getCurrentCaretPosition(el) {
/*Max of selectionStart and selectionEnd is taken for the patch of pixel and other mobile device caret bug*/
return Math.max(el.selectionStart, el.selectionEnd);
}
function addInputMode(format) {
return format || typeof navigator !== 'undefined' && !(navigator.platform && /iPhone|iPod/.test(navigator.platform));
}