Skip to content

Commit

Permalink
Float-input, Don't disable normalization when the trailing zero is no…
Browse files Browse the repository at this point in the history
…t in the fractional part (#318)
  • Loading branch information
jonenst authored Nov 23, 2023
1 parent f4db432 commit 34d9fe6
Showing 1 changed file with 27 additions and 7 deletions.
34 changes: 27 additions & 7 deletions src/components/react-hook-form/numbers/float-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { isFloatNumber } from './utils';
// uses the same string representation as the intermediate text that the user
// typed. For example, if the user wants to input "625", they will write "6"
// and then "62" and then "625". The intermediate strings are numbers that have
// nothing in common with the desired number but their normalization is the
// nothing in common with the final number but their normalization is the
// same as what was typed by the user. With exponential notation, if the user
// wants to input "12.5e21", at the intermediate step of "12.5e2" their input
// is normalized to "1.25e3" and after adding the final "1" they get "12.5e31"
Expand All @@ -34,7 +34,6 @@ const normalizeFixed = (number) => {

const FloatInput = (props) => {
const inputTransform = (value) => {
// do we want to handle infinities here ?
if (typeof value == 'number' && !isNaN(value)) {
// if we have a parsed real number, normalize like we do after each
// keystroke in outputTransform for consistency. We get parsed
Expand All @@ -44,10 +43,11 @@ const FloatInput = (props) => {
} else {
// The user is editing, leave as is because we already did what we
// need to do in outputTransform after the previous keystroke.
// NOTE: To avoid "bad things", we clear the text on NaN, so we need to
// special case known inputs that would be rejected by isNaN but are accepted by
// our acceptValue because they are need as intermediate strings for the
// user to input useful numbers.
// NOTE: To avoid "bad things" we haven't predicted and be extra
// cautious, we clear the text on NaN, so we need to special case
// known inputs that would be rejected by isNaN but are accepted by
// our acceptValue because they are needed as intermediate strings
// for the user to input useful numbers.
// TODO can we remove the isNaN check and the special cases check?
if (['-', '.'].includes(value)) {
return value;
Expand All @@ -65,7 +65,27 @@ const FloatInput = (props) => {
}

const tmp = value?.replace(',', '.') || '';
if (tmp.endsWith('.') || tmp.endsWith('0')) {

// Can't show the normalization to the user when the fractional part
// ends with 0 because normalizing removes the trailing zeroes and prevents
// inputting the required intermediate strings (e.g "1." or "1.0" to input "1.02")
// So we return the user string instead. This has the downside that
// when the user finally writes a non 0 digit at the end, the normalization takes place
// and may startle the user when changing a lot of its input text.
// For example:
// - "1.00000000000000000000000000" and then press any non zero digit
// removes all the zeroes at once
// - "1." or "1.0" and then left arrow to move the cursor to the left and then inputting many digits
// disables all normalization, can write huge numbers that are not rounded like
// - 1231231231241231241231245123124234234123123124234.
// vs 1231231231241231300000000000000000000000000000000
// - 1.4312322342321323434534234235234
// vs 1.4312322342321324
// Note: this is a symmetric problem inputting many zeros
// to the left of a number to allow to input a final leading nonzero
// digit, but users never want to do that, unlike inputting trailing zeroes in the
// fractional part before inputing the final trailing non zero digit
if (tmp.endsWith('.') || (tmp.includes('.') && tmp.endsWith('0'))) {
return tmp;
}

Expand Down

0 comments on commit 34d9fe6

Please sign in to comment.