A highly customizable, framework-agnostic OTP input library with full RTL support, accessibility, i18n, timer, and Web Component.
Import in your project:
Then use global variable:
Choose your preferred way to integrate the library into your project.
000 to
trigger the error animation automatically.
Use theme: 'soft' in options or
data-theme="soft" on the container.
6 toast themes × 4 types (success / error / warning / info). Auto-dismiss with progress bar, pause on hover, RTL-aware, and accessible (ARIA live regions).
Your code is 123456
@yourdomain.com #123456
| Method | Description |
|---|---|
| getValue() | Returns current OTP value as western-digit string |
| setValue(value) | Programmatically set OTP value |
| clear() | Clear all inputs and re-focus first |
| focus(index) | Focus a specific digit by index |
| disable() | Disable all inputs |
| enable() | Re-enable inputs |
| setError(msg) | Trigger error animation + announce to screen reader |
| clearError() | Remove error state from all inputs |
| resetTimer(dur) | Reset and restart countdown |
| setDirection(dir) |
Dynamically switch 'ltr' /
'rtl'
|
| setLocale(locale) | Switch locale (updates numeral rendering) |
| on(event, fn) | Subscribe to events. Returns unsubscribe function. |
| destroy() | Destroy instance, clean up all DOM and listeners |
| Event | Payload | Description |
|---|---|---|
| change | string |
Fires on every keystroke with current value |
| complete | string |
All digits filled and validation passed |
| error | Error[] |
Validation failed |
| focus | { index, input } |
A digit gained focus |
| blur | { index, input } |
A digit lost focus |
| expire | — | Timer reached zero |
| resend | — | User clicked resend button |
| Option | Type | Default | Description |
|---|---|---|---|
| length | number | 6 | Number of OTP digits |
| type | string | 'numeric' | 'numeric' | 'alpha' | 'alphanumeric' | 'hex' | 'custom' |
| pattern | RegExp | null | Custom character pattern (when type='custom') |
| secure | boolean | false | Mask input values (type="password") |
| direction | string | 'auto' | 'ltr' | 'rtl' | 'auto' (reads from DOM) |
| locale | string | null | BCP 47 locale for number rendering + direction |
| nativeNumerals | boolean | false | Render locale-native digits (Arabic-Indic, etc.) |
| autoSubmit | boolean | false | Submit closest form on completion |
| haptic | boolean | true | Vibration API feedback on mobile |
| clipboardDetection | boolean | true | Suggest pasting if OTP-like text in clipboard |
| validate | function | null | (value) => errorMsg | null |
| animation.error | string | 'shake' | 'shake' | 'highlight' | 'both' | false |
| timer.enabled | boolean | false | Show countdown timer |
| timer.duration | number | 60 | Timer duration in seconds |
| resend.enabled | boolean | false | Show resend button after expiry |