1
1
import * as React from 'react' ;
2
- import type {
2
+ import {
3
3
LayoutChangeEvent ,
4
4
NativeSyntheticEvent ,
5
5
TextInput ,
6
6
TextInputFocusEventData ,
7
7
TextInputProps ,
8
+ Platform ,
8
9
} from 'react-native' ;
9
10
10
11
import { FormContext , FormContextType } from './FormContext' ;
@@ -61,6 +62,9 @@ type FieldsBoolean<T> = {
61
62
type FieldsError < T > = {
62
63
[ key in keyof T ] ?: boolean | string | undefined ;
63
64
} ;
65
+ type FieldsLastCharacters < T > = {
66
+ [ key in keyof T ] ?: string | undefined ;
67
+ } ;
64
68
65
69
type ReferencerReturns = TextInputProps & { ref : React . Ref < TextInput > } ;
66
70
export type ReferencerType = (
@@ -86,6 +90,10 @@ export function indexer(): IndexerType {
86
90
} ;
87
91
}
88
92
93
+ function withoutLastCharacter ( s : string ) {
94
+ return s . substring ( 0 , s . length - 1 ) ;
95
+ }
96
+
89
97
export function useFormContext ( ) : FormContextType & {
90
98
formIndex : number ;
91
99
} {
@@ -248,6 +256,9 @@ export default function useFormState<T>(
248
256
const [ touched , sTouched ] = React . useState < FieldsBoolean < T > > ( { } ) ;
249
257
const [ errors , sErrors ] = React . useState < FieldsError < T > > ( { } ) ;
250
258
const [ values , setValues ] = React . useState < T > ( initialState ) ;
259
+ const [ lastCharacters , setLastCharacters ] = React . useState <
260
+ FieldsLastCharacters < T >
261
+ > ( { } ) ;
251
262
252
263
const valuesRef = useLatest ( values ) ;
253
264
const onChangeRef = useLatest ( options ?. onChange ) ;
@@ -272,11 +283,12 @@ export default function useFormState<T>(
272
283
v : T [ K ] ,
273
284
allV : T
274
285
) => {
275
- let err : boolean | string | undefined = undefined ;
286
+ let err : boolean | string | undefined ;
276
287
277
288
if ( h ) {
278
289
err = h . validate ?.( v , allV ) ;
279
290
if ( ! err ) {
291
+ // TODO: add locale support
280
292
if ( h ?. required === true && ! v ) {
281
293
err = `${ k } is required` ;
282
294
} else if ( h . minLength !== undefined && `${ v } ` . length < h . minLength ) {
@@ -375,13 +387,27 @@ export default function useFormState<T>(
375
387
...ctx . referencer ( k as any , ctx . formIndex ) ,
376
388
testID : k as string ,
377
389
onChangeText : referencedCallback ( `number.${ k } ` , ( n : string ) => {
378
- if ( n !== '' ) {
379
- changeValue ( k , Number ( n ) as any , h ) ;
390
+ const endsWithSeparator = n . endsWith ( ',' ) || n . endsWith ( '.' ) ;
391
+
392
+ if ( endsWithSeparator ) {
393
+ setLastCharacters ( ( prev ) => ( { ...prev , [ k ] : n [ n . length - 1 ] } ) ) ;
394
+ } else {
395
+ setLastCharacters ( ( prev ) => ( { ...prev , [ k ] : undefined } ) ) ;
396
+ }
397
+
398
+ if ( n === '' ) {
399
+ changeValue ( k , null as any , h ) ;
400
+ } else {
401
+ changeValue (
402
+ k ,
403
+ Number ( endsWithSeparator ? withoutLastCharacter ( n ) : n ) as any ,
404
+ h
405
+ ) ;
380
406
}
381
407
} ) ,
382
408
onBlur : blur ( k , h ) ,
383
409
onLayout : layout ( k , h ) ,
384
- value : `${ ( values ?. [ k ] || '' ) as string } ` ,
410
+ value : `${ ( values ?. [ k ] || '' ) as string } ${ lastCharacters [ k ] || '' } ` ,
385
411
} ) ;
386
412
387
413
const number = < K extends keyof T > (
@@ -477,7 +503,7 @@ export default function useFormState<T>(
477
503
autoCompleteType : 'username' ,
478
504
autoCapitalize : 'none' ,
479
505
autoCorrect : false ,
480
- selectTextOnFocus : true ,
506
+ selectTextOnFocus : Platform . OS !== 'web' ,
481
507
} ) ;
482
508
483
509
const password = < K extends keyof T > (
@@ -489,7 +515,7 @@ export default function useFormState<T>(
489
515
autoCompleteType : 'password' ,
490
516
secureTextEntry : true ,
491
517
autoCorrect : false ,
492
- selectTextOnFocus : true ,
518
+ selectTextOnFocus : Platform . OS !== 'web' ,
493
519
} ) ;
494
520
495
521
const email = < K extends keyof T > (
0 commit comments