Skip to content

Commit 6175dfb

Browse files
committed
fix(input-otp): move focus to last input when all are filled
1 parent 9aaeef2 commit 6175dfb

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

core/src/components/input-otp/input-otp.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,12 @@ export class InputOTP implements ComponentInterface {
266266
this.updateValue();
267267

268268
// Focus the next empty input after pasting
269+
// If all boxes are filled, focus the last input
269270
const nextEmptyIndex = pasteStart + validChars.length;
270271
if (nextEmptyIndex < length) {
271272
inputRefs[nextEmptyIndex]?.focus();
273+
} else {
274+
inputRefs[length - 1]?.focus();
272275
}
273276
}
274277

@@ -377,8 +380,21 @@ export class InputOTP implements ComponentInterface {
377380
}
378381

379382
render() {
380-
const { color, disabled, fill, hasFocus, inputId, inputRefs, inputValues, length, pattern, readonly, shape, size, type } =
381-
this;
383+
const {
384+
color,
385+
disabled,
386+
fill,
387+
hasFocus,
388+
inputId,
389+
inputRefs,
390+
inputValues,
391+
length,
392+
pattern,
393+
readonly,
394+
shape,
395+
size,
396+
type,
397+
} = this;
382398
const mode = getIonMode(this);
383399
const inputmode = this.getInputmode();
384400
const tabbableIndex = this.getTabbableIndex();

core/src/components/input-otp/test/basic/input-otp.e2e.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -220,18 +220,15 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
220220

221221
test.describe(title('input-otp: paste functionality'), () => {
222222
test('should paste text into the first and second input box when pasting 2 digits', async ({ page }) => {
223-
await page.setContent(
224-
`<ion-input-otp>Description</ion-input-otp>`,
225-
config
226-
);
223+
await page.setContent(`<ion-input-otp>Description</ion-input-otp>`, config);
227224

228225
const firstInput = page.locator('ion-input-otp input').first();
229226
await firstInput.focus();
230227
await firstInput.evaluate((input, value) => {
231228
const event = new ClipboardEvent('paste', {
232229
bubbles: true,
233230
cancelable: true,
234-
clipboardData: new DataTransfer()
231+
clipboardData: new DataTransfer(),
235232
});
236233
if (event.clipboardData) {
237234
event.clipboardData.setData('text', value);
@@ -244,21 +241,21 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
244241
await expect(inputBoxes.nth(1)).toHaveValue('2');
245242
await expect(inputBoxes.nth(2)).toHaveValue('');
246243
await expect(inputBoxes.nth(3)).toHaveValue('');
244+
245+
// Focus should be on the 3rd input box
246+
await expect(inputBoxes.nth(2)).toBeFocused();
247247
});
248248

249249
test('should paste text into all input boxes when pasting 4 digits', async ({ page }) => {
250-
await page.setContent(
251-
`<ion-input-otp>Description</ion-input-otp>`,
252-
config
253-
);
250+
await page.setContent(`<ion-input-otp>Description</ion-input-otp>`, config);
254251

255252
const firstInput = page.locator('ion-input-otp input').first();
256253
await firstInput.focus();
257254
await firstInput.evaluate((input, value) => {
258255
const event = new ClipboardEvent('paste', {
259256
bubbles: true,
260257
cancelable: true,
261-
clipboardData: new DataTransfer()
258+
clipboardData: new DataTransfer(),
262259
});
263260
if (event.clipboardData) {
264261
event.clipboardData.setData('text', value);
@@ -271,21 +268,23 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
271268
await expect(inputBoxes.nth(1)).toHaveValue('2');
272269
await expect(inputBoxes.nth(2)).toHaveValue('3');
273270
await expect(inputBoxes.nth(3)).toHaveValue('4');
271+
272+
// Focus should be on the 4th input box
273+
await expect(inputBoxes.nth(3)).toBeFocused();
274274
});
275275

276-
test('should paste text into the first and second input box when pasting 2 digits in the 3rd box', async ({ page }) => {
277-
await page.setContent(
278-
`<ion-input-otp>Description</ion-input-otp>`,
279-
config
280-
);
276+
test('should paste text into the first and second input box when pasting 2 digits in the 3rd box', async ({
277+
page,
278+
}) => {
279+
await page.setContent(`<ion-input-otp>Description</ion-input-otp>`, config);
281280

282281
const thirdInput = page.locator('ion-input-otp input').nth(2);
283282
await thirdInput.focus();
284283
await thirdInput.evaluate((input, value) => {
285284
const event = new ClipboardEvent('paste', {
286285
bubbles: true,
287286
cancelable: true,
288-
clipboardData: new DataTransfer()
287+
clipboardData: new DataTransfer(),
289288
});
290289
if (event.clipboardData) {
291290
event.clipboardData.setData('text', value);
@@ -300,11 +299,10 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
300299
await expect(inputBoxes.nth(3)).toHaveValue('');
301300
});
302301

303-
test('should paste text into the last two input boxes when pasting 2 digits after typing 2 digits', async ({ page }) => {
304-
await page.setContent(
305-
`<ion-input-otp>Description</ion-input-otp>`,
306-
config
307-
);
302+
test('should paste text into the last two input boxes when pasting 2 digits after typing 2 digits', async ({
303+
page,
304+
}) => {
305+
await page.setContent(`<ion-input-otp>Description</ion-input-otp>`, config);
308306

309307
const firstInput = page.locator('ion-input-otp input').first();
310308
await firstInput.focus();
@@ -315,7 +313,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
315313
const event = new ClipboardEvent('paste', {
316314
bubbles: true,
317315
cancelable: true,
318-
clipboardData: new DataTransfer()
316+
clipboardData: new DataTransfer(),
319317
});
320318
if (event.clipboardData) {
321319
event.clipboardData.setData('text', value);
@@ -331,10 +329,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
331329
});
332330

333331
test('should paste text into all input boxes when pasting 4 digits after typing 4 digits', async ({ page }) => {
334-
await page.setContent(
335-
`<ion-input-otp>Description</ion-input-otp>`,
336-
config
337-
);
332+
await page.setContent(`<ion-input-otp>Description</ion-input-otp>`, config);
338333

339334
const firstInput = page.locator('ion-input-otp input').first();
340335
await firstInput.focus();
@@ -345,7 +340,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
345340
const event = new ClipboardEvent('paste', {
346341
bubbles: true,
347342
cancelable: true,
348-
clipboardData: new DataTransfer()
343+
clipboardData: new DataTransfer(),
349344
});
350345
if (event.clipboardData) {
351346
event.clipboardData.setData('text', value);

0 commit comments

Comments
 (0)