* fix(input-amount): returns Unparseable as a modelValue if a wrong value has been entered * fix(input-amount): do not break when a large amount has been entered * Update docs/components/input-amount/overview.md Co-authored-by: Thijs Louisse <thijs.louisse@ing.com> * Update packages/ui/components/input-amount/test/parsers.test.js Co-authored-by: Thijs Louisse <thijs.louisse@ing.com> --------- Co-authored-by: Thijs Louisse <thijs.louisse@ing.com>
56 lines
1.9 KiB
JavaScript
56 lines
1.9 KiB
JavaScript
import { parseNumber, getFractionDigits } from '@lion/ui/localize-no-side-effects.js';
|
|
|
|
/**
|
|
* @typedef {import('../../localize/types/LocalizeMixinTypes.js').FormatNumberOptions} FormatOptions
|
|
*/
|
|
|
|
/**
|
|
* Rounding problem can be avoided by using numbers represented in exponential notation
|
|
* @param {number} value to be rounded up
|
|
* @param {number | undefined} decimals amount of decimals to keep
|
|
* @return {number} new value with rounded up decimals
|
|
*/
|
|
function round(value, decimals) {
|
|
const numberContainsExponent = value?.toString().includes('e');
|
|
if (typeof decimals === 'undefined' || numberContainsExponent) {
|
|
return Number(value);
|
|
}
|
|
return Number(`${Math.round(Number(`${value}e${decimals}`))}e-${decimals}`);
|
|
}
|
|
|
|
/**
|
|
* Uses `parseNumber()` to parses a number string and returns the best possible javascript number.
|
|
* Rounds up the number with the correct amount of decimals according to the currency.
|
|
*
|
|
* @example
|
|
* parseAmount('1,234.56', {currency: 'EUR'}); => 1234.56
|
|
* parseAmount('1,234.56', {currency: 'JPY'}); => 1235
|
|
* parseAmount('1,234.56', {currency: 'JOD'}); => 1234.560
|
|
*
|
|
* @param {string} value Number to be parsed
|
|
* @param {FormatOptions} [givenOptions] Locale Options
|
|
*/
|
|
export function parseAmount(value, givenOptions) {
|
|
const unmatchedInput = value.match(/[^0-9,.\- ]/g);
|
|
// for the full paste behavior documentation:
|
|
// ./docs/components/input-amount/use-cases.md#paste-behavior
|
|
if (unmatchedInput && givenOptions?.mode !== 'pasted') {
|
|
return undefined;
|
|
}
|
|
|
|
const number = parseNumber(value, givenOptions);
|
|
|
|
if (typeof number !== 'number' || Number.isNaN(number)) {
|
|
return undefined;
|
|
}
|
|
|
|
/** @type {FormatOptions} */
|
|
const options = {
|
|
...givenOptions,
|
|
};
|
|
|
|
if (options.currency && typeof options.maximumFractionDigits === 'undefined') {
|
|
options.maximumFractionDigits = getFractionDigits(options.currency);
|
|
}
|
|
return round(number, options.maximumFractionDigits);
|
|
}
|