@@ -9,6 +9,7 @@ export type OTPInputProps = Exclude<
9
9
> & {
10
10
render ?: ( props : { value : string ; status : 'cursor' | 'selected' | 'none' ; index : number } ) => React . ReactNode ;
11
11
length ?: number ;
12
+ autoSubmit ?: boolean ;
12
13
} ;
13
14
14
15
type SelectionRange = readonly [ start : number , end : number ] ;
@@ -44,7 +45,7 @@ export const OTPInput = React.forwardRef<HTMLInputElement, OTPInputProps>(functi
44
45
*/
45
46
const OTPInputSegmented = React . forwardRef < HTMLInputElement , Required < Pick < OTPInputProps , 'render' > > & OTPInputProps > (
46
47
function OTPInput ( props , ref ) {
47
- const { className, render, length = OTP_LENGTH_DEFAULT , ...rest } = props ;
48
+ const { className, render, length = OTP_LENGTH_DEFAULT , autoSubmit = false , ...rest } = props ;
48
49
49
50
const innerRef = React . useRef < HTMLInputElement > ( null ) ;
50
51
const [ selectionRange , setSelectionRange ] = React . useState < SelectionRange > ( props . autoFocus ? ZERO : OUTSIDE ) ;
@@ -60,6 +61,13 @@ const OTPInputSegmented = React.forwardRef<HTMLInputElement, Required<Pick<OTPIn
60
61
setSelectionRange ( cur => selectionRangeUpdater ( cur , innerRef ) ) ;
61
62
} , [ props . value ] ) ;
62
63
64
+ // Fire the requestSubmit callback when the input has the required length and autoSubmit is enabled
65
+ React . useEffect ( ( ) => {
66
+ if ( String ( props . value ) . length === length && autoSubmit ) {
67
+ innerRef . current ?. form ?. requestSubmit ( ) ;
68
+ }
69
+ } , [ props . value , length , autoSubmit ] ) ;
70
+
63
71
return (
64
72
< div
65
73
style = {
@@ -86,16 +94,7 @@ const OTPInputSegmented = React.forwardRef<HTMLInputElement, Required<Pick<OTPIn
86
94
setSelectionRange ( cur => selectionRangeUpdater ( cur , innerRef ) ) ;
87
95
rest ?. onSelect ?.( event ) ;
88
96
} }
89
- style = { {
90
- display : 'block' ,
91
- cursor : 'default' ,
92
- background : 'none' ,
93
- outline : 'none' ,
94
- appearance : 'none' ,
95
- color : 'transparent' ,
96
- position : 'absolute' ,
97
- inset : 0 ,
98
- } }
97
+ style = { inputStyle }
99
98
/>
100
99
< div
101
100
className = { className }
@@ -106,7 +105,7 @@ const OTPInputSegmented = React.forwardRef<HTMLInputElement, Required<Pick<OTPIn
106
105
} }
107
106
>
108
107
{ Array . from ( { length } ) . map ( ( _ , i ) => (
109
- < React . Fragment key = { i } >
108
+ < React . Fragment key = { `otp-segment- ${ i } ` } >
110
109
{ render ( {
111
110
value : String ( props . value ) [ i ] || '' ,
112
111
status :
@@ -152,3 +151,14 @@ function selectionRangeUpdater(cur: SelectionRange, inputRef: React.RefObject<HT
152
151
153
152
return updated ;
154
153
}
154
+
155
+ const inputStyle = {
156
+ display : 'block' ,
157
+ cursor : 'default' ,
158
+ background : 'none' ,
159
+ outline : 'none' ,
160
+ appearance : 'none' ,
161
+ color : 'transparent' ,
162
+ position : 'absolute' ,
163
+ inset : 0 ,
164
+ } satisfies React . CSSProperties ;
0 commit comments