beholdr / maska

Simple zero-dependency input mask for Vue, Svelte, Alpine.js and vanilla JS.
https://beholdr.github.io/maska/
MIT License
1.79k stars 71 forks source link

Trailing zeros #230

Closed mdoesburg closed 2 months ago

mdoesburg commented 3 months ago

Describe the bug

When typing a lot of numbers eventually only zeros are appended to the input. Maybe this is an issue related to rounding or integers/floats?

Steps to reproduce

  1. Go to: https://beholdr.github.io/maska/v3/#/
  2. Open the Number mode: money (UK) example
  3. Paste 22222222222222222 into the input
  4. See the following result: £22 222 222 222 222 224
  5. Paste 222222222222222222 into the input
  6. See the following result: £222 222 222 222 222 200
  7. Continue to type 2
  8. See more zeroes appended at the end

The Money, via hooks (pre v3 variant) example seems to work with the above input values, but it doesn't have all the nice built-in features that the new number mask brings to the table.

You can actually reproduce this issue with an example equivalent to the Money, via hooks (pre v3 variant) example, with one addition, a parseFloat call:

const maskOptions = reactive({
    mask: '0.99',
    tokens: {
        0: { pattern: /\d/, multiple: true },
        9: { pattern: /\d/, optional: true },
    },
    preProcess: (val: string) => val.replace(/[$,]/g, ''),
    postProcess: (val: string) => {
        if (!val) {
            return '';
        }

        const sub = 3 - (val.includes('.') ? val.length - val.indexOf('.') : 0);

        return new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'USD',
        })
            .format(parseFloat(val))
            .slice(0, sub ? -sub : undefined);
    },
});

With the parseFloat call in the above example you get the trailing zero issue, without is, it works, but TypeScript won't be too happy. I think it's safe to assume this issue is caused by the parseFloat calls in the number file: https://github.com/beholdr/maska/blob/master/src/number.ts

Reproduction link

rozsazoltan commented 3 months ago

The error is caused by exceeding the Number.MAX_SAFE_INTEGER limit, beyond which the resulting number becomes inaccurate.

Users have previously reported a similar issue to me on my a project. However, in many cases, it's impractical for them to input such large numbers. If we still wanted to treat it, I have implemented two solutions for this:

  1. Limit the maximum input value to prevent exceeding the safe limits.
  2. Alternatively, handle the result as a BigInt or BigFloat when it surpasses the limit.
beholdr commented 2 months ago

I've added info about maximum number in the docs