@@ -612,7 +612,9 @@ const OneTimePasswordFieldInput = React.forwardRef<
612
612
const keyboardActionTimeoutRef = React . useRef < number | null > ( null ) ;
613
613
React . useEffect ( ( ) => {
614
614
return ( ) => {
615
- window . clearTimeout ( keyboardActionTimeoutRef . current ! ) ;
615
+ if ( keyboardActionTimeoutRef . current ) {
616
+ window . clearTimeout ( keyboardActionTimeoutRef . current ) ;
617
+ }
616
618
} ;
617
619
} , [ ] ) ;
618
620
@@ -664,11 +666,9 @@ const OneTimePasswordFieldInput = React.forwardRef<
664
666
// In this case the value will be cleared, but we don't want to
665
667
// set it directly because the user may want to prevent default
666
668
// behavior in the onChange handler. The userActionRef will
667
- // is set temporarily so the change handler can behave correctly
669
+ // be set temporarily so the change handler can behave correctly
668
670
// in response to the action.
669
- userActionRef . current = {
670
- type : 'cut' ,
671
- } ;
671
+ userActionRef . current = { type : 'cut' } ;
672
672
// Set a short timeout to clear the action tracker after the change
673
673
// handler has had time to complete.
674
674
keyboardActionTimeoutRef . current = window . setTimeout ( ( ) => {
@@ -684,7 +684,11 @@ const OneTimePasswordFieldInput = React.forwardRef<
684
684
// additional input. Handle this the same as if a user were
685
685
// pasting a value.
686
686
event . preventDefault ( ) ;
687
+ userActionRef . current = { type : 'paste' } ;
687
688
dispatch ( { type : 'PASTE' , value } ) ;
689
+ keyboardActionTimeoutRef . current = window . setTimeout ( ( ) => {
690
+ userActionRef . current = null ;
691
+ } , 10 ) ;
688
692
}
689
693
} ) }
690
694
onChange = { composeEventHandlers ( props . onChange , ( event ) => {
@@ -696,11 +700,16 @@ const OneTimePasswordFieldInput = React.forwardRef<
696
700
if ( action ) {
697
701
switch ( action . type ) {
698
702
case 'cut' :
699
- // TODO: do we want to assume the user wantt to clear the
703
+ // TODO: do we want to assume the user wants to clear the
700
704
// entire value here and copy the code to the clipboard instead
701
705
// of just the value of the given input?
702
706
dispatch ( { type : 'CLEAR_CHAR' , index, reason : 'Cut' } ) ;
703
707
return ;
708
+ case 'paste' :
709
+ // the PASTE handler will already set the value and focus the final
710
+ // input; we want to skip focusing the wrong element if the browser fires
711
+ // onChange for the first input. This sometimes happens during autocomplete.
712
+ return ;
704
713
case 'keydown' : {
705
714
if ( action . key === 'Char' ) {
706
715
// update resulting from a keydown event that set a value
@@ -718,6 +727,7 @@ const OneTimePasswordFieldInput = React.forwardRef<
718
727
return ;
719
728
}
720
729
default :
730
+ action satisfies never ;
721
731
return ;
722
732
}
723
733
}
@@ -929,7 +939,8 @@ type KeyboardActionDetails =
929
939
metaKey : boolean ;
930
940
ctrlKey : boolean ;
931
941
}
932
- | { type : 'cut' } ;
942
+ | { type : 'cut' }
943
+ | { type : 'paste' } ;
933
944
934
945
type UpdateAction =
935
946
| {
0 commit comments