Skip to content

Commit c91f5d8

Browse files
authored
Merge pull request #78 from mohiulislam/production
feat(OtpInput): add paste support and fix input bugs with wheel and arrow keys
2 parents b2ca8d6 + 858b3af commit c91f5d8

File tree

1 file changed

+39
-9
lines changed
  • src/Components/Overview/SidebarContent/Content/Inputs

1 file changed

+39
-9
lines changed

src/Components/Overview/SidebarContent/Content/Inputs/OtpInput.jsx

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useRef } from "react";
1+
import { useState, useRef } from "react";
22

33
// components
44
import OverviewFooter from "../../../../../Shared/OverviewFooter";
@@ -61,6 +61,21 @@ const OtpInput = () => {
6161
}
6262
};
6363

64+
const handleAutoNavigationPaste = (e, index) => {
65+
e.preventDefault();
66+
const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, length);
67+
const newOtp = [...autoNavigationInputs.current.map(input => input.value)];
68+
69+
for (let i = 0; i < pastedData.length && i < length; i++) {
70+
newOtp[i] = pastedData[i];
71+
autoNavigationInputs.current[i].value = pastedData[i];
72+
}
73+
onChange(newOtp.join(''));
74+
75+
const focusIndex = Math.min(pastedData.length, length - 1);
76+
autoNavigationInputs.current[focusIndex].focus();
77+
};
78+
6479
// for custom navigation
6580
const handleCustomNavigationInputChange = (e, index) => {
6681
const { value } = e.target;
@@ -83,7 +98,6 @@ const OtpInput = () => {
8398
}
8499
}
85100

86-
87101
return (
88102
<>
89103
<aside className="flex items-start justify-between gap-6 w-full 640px:pl-[2.5rem] px-6 640px:px-10">
@@ -105,7 +119,7 @@ const OtpInput = () => {
105119
ref={(el) => (autoNavigationInputs.current[index] = el)}
106120
className='p-3 text-center dark:bg-transparent dark:border-slate-700 dark:text-[#abc2d3] dark:placeholder:text-slate-500 border border-[#bcbcbc] rounded-md outline-none focus:border-primary'
107121
placeholder='0'
108-
max="1"
122+
onWheel={(e) => e.target.blur()}
109123
onChange={(e) => handleCustomNavigationInputChange(e, index)}
110124
type='number'
111125
/>
@@ -154,7 +168,7 @@ const OtpInput = () => {
154168
ref={(el) => (navigationInputs.current[index] = el)}
155169
className="p-3 text-center dark:bg-transparent dark:border-slate-700 dark:text-[#abc2d3] dark:placeholder:text-slate-500 border border-[#bcbcbc] rounded-md outline-none focus:border-[#3B9DF8]"
156170
placeholder="0"
157-
max="1"
171+
onWheel={(e) => e.target.blur()}
158172
onChange={(e) => handleInputChange(e, index)}
159173
type="number"
160174
/>
@@ -174,8 +188,7 @@ export default OtpInput;
174188
<ContentHeader text={"Keyboard navigation"} id={"keyboard_navigation"}/>
175189
</div>
176190

177-
<ComponentDescription text='OTP input field with keyboard navigation, enabling users to move between digits using arrow keys
178-
for quick and efficient entry.'/>
191+
<ComponentDescription text='OTP input field with keyboard navigation, enabling users to move between digits using arrow keys and paste numeric codes (extracting only numbers) for quick and efficient entry.'/>
179192

180193
<ToggleTab code={autoNavigationCode} setCode={setAutoNavigationCode} setPreview={setAutoNavigationPreview} preview={autoNavigationPreview}/>
181194

@@ -190,9 +203,10 @@ export default OtpInput;
190203
ref={(el) => (autoNavigationInputs.current[index] = el)}
191204
className='p-3 text-center dark:bg-transparent dark:border-slate-700 dark:text-[#abc2d3] dark:placeholder:text-slate-500 border border-[#bcbcbc] rounded-md outline-none focus:border-primary'
192205
placeholder='0'
193-
max="1"
206+
onWheel={(e) => e.target.blur()}
194207
onChange={(e) => handleAutoNavigationInputChange(e, index)}
195208
onKeyDown={(e) => handleAutoNavigationKeydown(e, index)}
209+
onPaste={(e) => handleAutoNavigationPaste(e, index)}
196210
type='number'
197211
/>
198212
))
@@ -236,6 +250,21 @@ const OtpInput = () => {
236250
}
237251
};
238252
253+
const handlePaste = (e, index) => {
254+
e.preventDefault();
255+
const pastedData = e.clipboardData.getData("text").replace(/[^0-9]/g, "").slice(0, length);
256+
const newOtp = [...navigationInputs.current.map(input => input.value)];
257+
258+
for (let i = 0; i < pastedData.length && i < length; i++) {
259+
newOtp[i] = pastedData[i];
260+
navigationInputs.current[i].value = pastedData[i];
261+
}
262+
onChange(newOtp.join(""));
263+
264+
const focusIndex = Math.min(pastedData.length, length - 1);
265+
navigationInputs.current[focusIndex].focus();
266+
};
267+
239268
const handleKeydown = (e, index) => {
240269
if (e.key === "Backspace" && !navigationInputs.current[index].value && index > 0) {
241270
navigationInputs.current[index - 1].focus()
@@ -251,9 +280,10 @@ const OtpInput = () => {
251280
ref={(el) => (navigationInputs.current[index] = el)}
252281
className="p-3 text-center dark:bg-transparent dark:border-slate-700 dark:text-[#abc2d3] dark:placeholder:text-slate-500 border border-[#bcbcbc] rounded-md outline-none focus:border-[#3B9DF8]"
253282
placeholder="0"
254-
max="1"
283+
onWheel={(e) => e.target.blur()}
255284
onChange={(e) => handleInputChange(e, index)}
256285
onKeyDown={(e) => handleKeydown(e, index)}
286+
onPaste={(e) => handlePaste(e, index)}
257287
type="number"
258288
/>
259289
))
@@ -282,4 +312,4 @@ export default OtpInput;
282312
);
283313
};
284314

285-
export default OtpInput;
315+
export default OtpInput;

0 commit comments

Comments
 (0)