@@ -3,6 +3,7 @@ import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} fro
33import type { NativeSyntheticEvent , TextInputFocusEventData , TextInputKeyPressEventData } from 'react-native' ;
44import { StyleSheet , View } from 'react-native' ;
55import { Gesture , GestureDetector } from 'react-native-gesture-handler' ;
6+ import Animated , { useAnimatedStyle , useSharedValue , withDelay , withRepeat , withSequence , withTiming } from 'react-native-reanimated' ;
67import useNetwork from '@hooks/useNetwork' ;
78import useStyleUtils from '@hooks/useStyleUtils' ;
89import useThemeStyles from '@hooks/useThemeStyles' ;
@@ -381,6 +382,17 @@ function MagicCodeInput(
381382 // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
382383 } , [ lastPressedDigit , isDisableKeyboard ] ) ;
383384
385+ const cursorOpacity = useSharedValue ( 1 ) ;
386+
387+ useEffect ( ( ) => {
388+ cursorOpacity . set ( withRepeat ( withSequence ( withDelay ( 500 , withTiming ( 0 , { duration : 0 } ) ) , withDelay ( 500 , withTiming ( 1 , { duration : 0 } ) ) ) , - 1 , false ) ) ;
389+ // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
390+ } , [ ] ) ;
391+
392+ const animatedCursorStyle = useAnimatedStyle ( ( ) => ( {
393+ opacity : cursorOpacity . get ( ) ,
394+ } ) ) ;
395+
384396 return (
385397 < >
386398 < View style = { [ styles . magicCodeInputContainer ] } >
@@ -424,24 +436,40 @@ function MagicCodeInput(
424436 />
425437 </ View >
426438 </ GestureDetector >
427- { getInputPlaceholderSlots ( maxLength ) . map ( ( index ) => (
428- < View
429- key = { index }
430- style = { maxLength === CONST . MAGIC_CODE_LENGTH ? [ styles . w15 ] : [ styles . flex1 , index !== 0 && styles . ml3 ] }
431- >
439+ { getInputPlaceholderSlots ( maxLength ) . map ( ( index ) => {
440+ const char = decomposeString ( value , maxLength ) . at ( index ) ?. trim ( ) ?? '' ;
441+ const cursorMargin = char ? { marginLeft : 2 } : { } ;
442+ const isFocused = focusedIndex === index ;
443+
444+ return (
432445 < View
433- style = { [
434- styles . textInputContainer ,
435- StyleUtils . getHeightOfMagicCodeInput ( ) ,
436- hasError || errorText ? styles . borderColorDanger : { } ,
437- focusedIndex === index ? styles . borderColorFocus : { } ,
438- styles . pt0 ,
439- ] }
446+ key = { index }
447+ style = { maxLength === CONST . MAGIC_CODE_LENGTH ? [ styles . w15 ] : [ styles . flex1 , index !== 0 && styles . ml3 ] }
440448 >
441- < Text style = { [ styles . magicCodeInput , styles . textAlignCenter ] } > { decomposeString ( value , maxLength ) . at ( index ) ?? '' } </ Text >
449+ < View
450+ style = { [
451+ styles . textInputContainer ,
452+ StyleUtils . getHeightOfMagicCodeInput ( ) ,
453+ hasError || errorText ? styles . borderColorDanger : { } ,
454+ focusedIndex === index ? styles . borderColorFocus : { } ,
455+ styles . pt0 ,
456+ { position : 'relative' } ,
457+ ] }
458+ >
459+ < View style = { styles . magicCodeInputValueContainer } >
460+ < Text style = { [ styles . magicCodeInput , styles . textAlignCenter ] } > { char } </ Text >
461+ { isFocused && ! isDisableKeyboard && (
462+ < View style = { [ styles . magicCodeInputCursorContainer ] } >
463+ { ! ! char && < Text style = { [ styles . magicCodeInput , styles . textAlignCenter , styles . opacity0 ] } > { char } </ Text > }
464+ < Text style = { [ styles . magicCodeInput , { width : 1 } ] } > </ Text >
465+ < Animated . Text style = { [ styles . magicCodeInputCursor , animatedCursorStyle , cursorMargin ] } > │</ Animated . Text >
466+ </ View >
467+ ) }
468+ </ View >
469+ </ View >
442470 </ View >
443- </ View >
444- ) ) }
471+ ) ;
472+ } ) }
445473 </ View >
446474 { ! ! errorText && (
447475 < FormHelpMessage
0 commit comments