Skip to content

Commit

Permalink
Fix #506 and #519
Browse files Browse the repository at this point in the history
  • Loading branch information
s-yadav committed Apr 11, 2021
1 parent 26b5f46 commit 4417fe6
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 136 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"browser": true,
"es6": true
},
"extends": ["prettier"],
"plugins": [
"react", //on react based application
"import",
"import"
],
"ecmaFeatures": {
"arrowFunctions": true,
Expand Down
14 changes: 14 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"printWidth": 100,
"arrowParens": "always",
"singleQuote": true,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"bracketSpacing": true,
"jsxBracketSameLine": false,
"requirePragma": false,
"proseWrap": "preserve",
"trailingComma": "all"
}

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^8.1.0",
"eslint-loader": "^3.0.2",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-react": "^7.15.1",
Expand All @@ -69,6 +70,7 @@
"karma-spec-reporter": "^0.0.32",
"karma-webpack": "^4.0.2",
"material-ui": "^0.20.2",
"prettier": "^2.2.1",
"react": "^15.4.0 || ^16.0.0",
"react-dom": "^15.4.0 || ^16.0.0",
"react-router": "5",
Expand Down
3 changes: 2 additions & 1 deletion src/number_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
getCurrentCaretPosition,
addInputMode,
isNil,
toNumericString,
} from './utils';


Expand Down Expand Up @@ -542,7 +543,7 @@ class NumberFormat extends React.Component {
if (isNonNumericFalsy && !allowEmptyFormatting) return '';

if (typeof value === 'number') {
value = value.toString();
value = toNumericString(value);
isNumericString = true;
}

Expand Down
133 changes: 99 additions & 34 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
type FormatInputValueFunction = (inputValue: string) => string;

// basic noop function
export function noop(){}
export function returnTrue(){ return true; }
export function noop() {}
export function returnTrue() {
return true;
}

export function charIsNumber(char?: string) {
return !!(char || '').match(/\d/);
Expand All @@ -15,7 +17,7 @@ export function isNil(val: any) {
}

export function escapeRegExp(str: string) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}

export function getThousandsGroupRegex(thousandsGroupStyle: string) {
Expand All @@ -30,11 +32,18 @@ export function getThousandsGroupRegex(thousandsGroupStyle: string) {
}
}

export function applyThousandSeparator(str: string, thousandSeparator: string, thousandsGroupStyle: string) {
export function applyThousandSeparator(
str: string,
thousandSeparator: string,
thousandsGroupStyle: string,
) {
const thousandsGroupRegex = getThousandsGroupRegex(thousandsGroupStyle);
let 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);
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
Expand All @@ -51,34 +60,79 @@ export function splitDecimal(numStr: string, allowNegative: boolean = true) {
beforeDecimal,
afterDecimal,
hasNagation,
addNegation
}
addNegation,
};
}

export function fixLeadingZero(numStr?: string) {
if (!numStr) return numStr;
const isNegative = numStr[0] === '-';
if (isNegative) numStr = numStr.substring(1, numStr.length);
const parts = numStr.split('.');
const beforeDecimal = parts[0].replace(/^0+/,'') || '0';
const beforeDecimal = parts[0].replace(/^0+/, '') || '0';
const afterDecimal = parts[1] || '';

return `${isNegative ? '-': ''}${beforeDecimal}${afterDecimal ? `.${afterDecimal}` : ''}`;
return `${isNegative ? '-' : ''}${beforeDecimal}${afterDecimal ? `.${afterDecimal}` : ''}`;
}

/**
* limit decimal numbers to given scale
* Not used .fixedTo because that will break with big numbers
*/
export function limitToScale(numStr: string, scale: number, fixedDecimalScale: boolean) {
let str = ''
let str = '';
const filler = fixedDecimalScale ? '0' : '';
for (let i=0; i<=scale - 1; i++) {
for (let i = 0; i <= scale - 1; i++) {
str += numStr[i] || filler;
}
return str;
}

function repeat(str, count) {
return Array(count + 1).join(str)
}

export function toNumericString(num) {
num += ''; // typecast number to string

// store the sign and remove it from the number.
const sign = num[0] === '-' ? '-' : '';
if (sign) num = num.substring(1);

// split the number into cofficient and exponent
let [coefficient, exponent] = num.split(/[eE]/g);

// 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
*/
const decimalIndex = 1 + exponent;

const 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
Expand All @@ -88,36 +142,46 @@ export function roundToPrecision(numStr: string, scale: number, fixedDecimalScal
if (['', '-'].indexOf(numStr) !== -1) return numStr;

const shoudHaveDecimalSeparator = numStr.indexOf('.') !== -1 && scale;
const {beforeDecimal, afterDecimal, hasNagation} = splitDecimal(numStr);
const { beforeDecimal, afterDecimal, hasNagation } = splitDecimal(numStr);
const floatValue = parseFloat(`0.${afterDecimal || '0'}`);
const floatValueStr = afterDecimal.length <= scale ? floatValue.toString() : floatValue.toFixed(scale)
const floatValueStr =
afterDecimal.length <= scale ? toNumericString(floatValue) : floatValue.toFixed(scale);
const roundedDecimalParts = floatValueStr.split('.');
const intPart = beforeDecimal.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 = limitToScale(roundedDecimalParts[1] || '', Math.min(scale, afterDecimal.length), fixedDecimalScale);
const intPart = beforeDecimal
.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 = limitToScale(
roundedDecimalParts[1] || '',
Math.min(scale, afterDecimal.length),
fixedDecimalScale,
);
const negation = hasNagation ? '-' : '';
const decimalSeparator = shoudHaveDecimalSeparator ? '.' : '';
return `${negation}${intPart}${decimalSeparator}${decimalPart}`;
}


export function omit(obj: Object, keyMaps: Object) {
const filteredObj = {};
Object.keys(obj).forEach((key) => {
if (!keyMaps[key]) filteredObj[key] = obj[key]
if (!keyMaps[key]) filteredObj[key] = obj[key];
});
return filteredObj;
}

/** set the caret positon in an input field **/
export function setCaretPosition(el: HTMLInputElement, caretPos: number) {
el.value = el.value;
// ^ this is used to not only get "focus", but
// ^ 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) {
Expand Down Expand Up @@ -147,21 +211,22 @@ export function setCaretPosition(el: HTMLInputElement, caretPos: number) {
characters are changed which is correct assumption for caret input.
*/
export function findChangedIndex(prevValue: string, newValue: string) {
let i = 0, j = 0;
let i = 0,
j = 0;
const prevLength = prevValue.length;
const 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
prevValue[prevLength - 1 - j] === newValue[newLength - 1 - j] &&
newLength - j > i &&
prevLength - j > i
) {
j++;
}
j++;
}

return {start: i, end: prevLength - j};
return { start: i, end: prevLength - j };
}

/*
Expand All @@ -171,11 +236,11 @@ export function clamp(num: number, min: number, max: number) {
return Math.min(Math.max(num, min), max);
}

export function getCurrentCaretPosition(el: HTMLInputElement ) {
export function getCurrentCaretPosition(el: HTMLInputElement) {
/*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);
}

export function addInputMode(format: string | FormatInputValueFunction){
export function addInputMode(format: string | FormatInputValueFunction) {
return format || !(navigator.platform && /iPhone|iPod/.test(navigator.platform));
}
}
Loading

0 comments on commit 4417fe6

Please sign in to comment.