11import type { ForwardedRef , KeyboardEvent } from 'react' ;
22import React , { forwardRef , useEffect , useImperativeHandle , useRef , useState } from 'react' ;
3- import type { NativeSyntheticEvent , TextInputFocusEventData , TextInputKeyPressEventData } from 'react-native' ;
3+ import type { NativeSyntheticEvent , TextInput as RNTextInput , TextInputFocusEventData , TextInputKeyPressEventData } from 'react-native' ;
44import { StyleSheet , View } from 'react-native' ;
55import { Gesture , GestureDetector } from 'react-native-gesture-handler' ;
66import Animated , { useAnimatedStyle , useSharedValue , withDelay , withRepeat , withSequence , withTiming } from 'react-native-reanimated' ;
@@ -17,6 +17,44 @@ import type {BaseTextInputRef} from './TextInput/BaseTextInput/types';
1717
1818const TEXT_INPUT_EMPTY_STATE = '' ;
1919
20+ /**
21+ * Trims whitespace from pasted magic codes
22+ */
23+ const useMagicCodePaste = ( inputRef : React . RefObject < BaseTextInputRef | null > , onChangeText : ( value : string ) => void ) => {
24+ useEffect ( ( ) => {
25+ if ( typeof document === 'undefined' ) {
26+ return ;
27+ }
28+
29+ const handlePaste = ( event : ClipboardEvent ) => {
30+ if ( ! inputRef . current ) {
31+ return ;
32+ }
33+
34+ const isFocused = ( inputRef . current as RNTextInput ) ?. isFocused ?.( ) ?? false ;
35+ if ( ! isFocused ) {
36+ return ;
37+ }
38+
39+ event . preventDefault ( ) ;
40+
41+ const plainText = event . clipboardData ?. getData ( 'text/plain' ) ;
42+ if ( plainText ) {
43+ const trimmedText = plainText . trim ( ) ;
44+ if ( trimmedText && isNumeric ( trimmedText ) ) {
45+ onChangeText ( trimmedText ) ;
46+ }
47+ }
48+ } ;
49+
50+ document . addEventListener ( 'paste' , handlePaste , true ) ;
51+
52+ return ( ) => {
53+ document . removeEventListener ( 'paste' , handlePaste , true ) ;
54+ } ;
55+ } , [ inputRef , onChangeText ] ) ;
56+ } ;
57+
2058type AutoCompleteVariant = 'sms-otp' | 'one-time-code' | 'off' ;
2159
2260type MagicCodeInputProps = {
@@ -122,6 +160,8 @@ function MagicCodeInput(
122160 const lastValue = useRef < string | number > ( TEXT_INPUT_EMPTY_STATE ) ;
123161 const valueRef = useRef ( value ) ;
124162
163+ useMagicCodePaste ( inputRef , onChangeTextProp ) ;
164+
125165 useEffect ( ( ) => {
126166 lastValue . current = input . length ;
127167 } , [ input ] ) ;
0 commit comments