diff --git a/example/src/index.js b/example/src/index.js index 17e7402c..3ffbff36 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -21,6 +21,7 @@ class App extends React.Component { return (
+

Prefix and thousand separator : Format currency as text

diff --git a/src/numeric_format.tsx b/src/numeric_format.tsx index 9a4cd7de..47cd7e7a 100644 --- a/src/numeric_format.tsx +++ b/src/numeric_format.tsx @@ -136,24 +136,56 @@ export function removeFormatting( value = value.substring(0, start) + separator + value.substring(start + 1, value.length); } - let hasNegation = false; + const stripNegation = (value: string, start: number, end: number) => { + /** + * if prefix starts with - the number hast to have two - at the start + * if suffix starts with - and the value length is same as suffix length, then the - sign is from the suffix + * In other cases, if the value starts with - then it is a negation + */ + let hasNegation = false; + let hasDoubleNegation = false; + if (prefix.startsWith('-')) hasNegation = !value.startsWith('--'); + else if (value.startsWith('--')) { + hasNegation = false; + hasDoubleNegation = true; + } else if (suffix.startsWith('-') && value.length === suffix.length) hasNegation = false; + else if (value[0] === '-') hasNegation = true; + + let charsToRemove = hasNegation ? 1 : 0; + if (hasDoubleNegation) charsToRemove = 2; + + // remove negation/double negation from start to simplify prefix logic as negation comes before prefix + if (charsToRemove) { + value = value.substring(charsToRemove); + + // account for the removal of the negation for start and end index + start -= charsToRemove; + end -= charsToRemove; + } - /** - * if prefix starts with - the number hast to have two - at the start - * if suffix starts with - and the value length is same as suffix length, then the - sign is from the suffix - * In other cases, if the value starts with - then it is a negation - */ - if (prefix.startsWith('-')) hasNegation = value.startsWith('--'); - else if (suffix.startsWith('-') && value.length === suffix.length) hasNegation = false; - else if (value[0] === '-') hasNegation = true; + return { value, start, end, hasNegation }; + }; - // remove negation from start to simplify prefix logic as negation comes before prefix - if (hasNegation) { - value = value.substring(1); + const toMetadata = stripNegation(value, start, end); + const { hasNegation } = toMetadata; + ({ value, start, end } = toMetadata); - // account for the removal of the negation for start and end index - start -= 1; - end -= 1; + const { + start: fromStart, + end: fromEnd, + value: lastValue, + } = stripNegation(changeMeta.lastValue, from.start, from.end); + + // if only prefix and suffix part is updated reset the value to last value + // if the changed range is from suffix in the updated value, and the the suffix starts with the same characters, allow the change + const updatedSuffixPart = value.substring(start, end); + if ( + value.length && + lastValue.length && + (fromStart > lastValue.length - suffix.length || fromEnd < prefix.length) && + !(updatedSuffixPart && suffix.startsWith(updatedSuffixPart)) + ) { + value = lastValue; } /** @@ -167,7 +199,7 @@ export function removeFormatting( else if (start < prefix.length) startIndex = start; value = value.substring(startIndex); - // account for deleted prefix for end index + // account for deleted prefix for end end -= startIndex; /** @@ -180,6 +212,9 @@ export function removeFormatting( const suffixStartIndex = value.length - suffix.length; if (value.endsWith(suffix)) endIndex = suffixStartIndex; + // if the suffix is removed from the end + else if (end > suffixStartIndex) endIndex = end; + // if the suffix is removed from start else if (end > value.length - suffix.length) endIndex = end; value = value.substring(0, endIndex); diff --git a/test/library/input_numeric_format.spec.js b/test/library/input_numeric_format.spec.js index f86a2aad..dee31f87 100644 --- a/test/library/input_numeric_format.spec.js +++ b/test/library/input_numeric_format.spec.js @@ -685,6 +685,36 @@ describe('Test NumberFormat as input with numeric format options', () => { expect(wrapper.find('input').prop('value')).toEqual('0.00000001'); }); + describe('should handle if only partial prefix or suffix is removed using double click select and the remove. #694', () => { + it('while changing suffix', () => { + const wrapper = mount(); + + simulateKeyInput(wrapper.find('input'), '2', 9, 12); + expect(wrapper.find('input').prop('value')).toEqual('100-1000 USD'); + }); + + it('while changing prefix', () => { + const wrapper = mount(); + + simulateKeyInput(wrapper.find('input'), '2', 0, 2); + expect(wrapper.find('input').prop('value')).toEqual('100-1000 USD'); + }); + + it('while deleting suffix', () => { + const wrapper = mount(); + + simulateKeyInput(wrapper.find('input'), 'Backspace', 9, 12); + expect(wrapper.find('input').prop('value')).toEqual('100-1000 USD'); + }); + + fit('while deleting prefix', () => { + const wrapper = mount(); + + simulateKeyInput(wrapper.find('input'), 'Backspace', 0, 3); + expect(wrapper.find('input').prop('value')).toEqual('100-1000 USD'); + }); + }); + describe('Test thousand group style', () => { it('should format on english style thousand grouping', () => { const wrapper = mount();