UNPKG

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
"use strict"; 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)); }