https://github.com/tsvetan-ganev/otp-input
Angular component for entering one time password codes.
https://github.com/tsvetan-ganev/otp-input
angular component mfa otp
Last synced: about 1 month ago
JSON representation
Angular component for entering one time password codes.
- Host: GitHub
- URL: https://github.com/tsvetan-ganev/otp-input
- Owner: tsvetan-ganev
- License: mit
- Created: 2024-11-19T15:43:24.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2024-11-22T14:34:42.000Z (5 months ago)
- Last Synced: 2025-01-24T07:44:57.556Z (3 months ago)
- Topics: angular, component, mfa, otp
- Language: TypeScript
- Homepage: https://ng-otp-input.vercel.app/
- Size: 208 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 🚧 UNDER DEVELOPMENT 🚧
# @parabolabs/otp-input
Angular component for entering one time passwords built with modern Angular features (signals, zoneless change detection, new control flow syntax).
[Storybook Demo](https://ng-otp-input.vercel.app/)
## Features
- accessibility out of the box
- zero dependencies
- high performance (`ChangeDetectionStrategy.OnPush` + signals)
- customizability
- handles paste event
- support for the Forms API (implements `ControlValueAccessor`)
- core functionality is covered by unit tests## Installation
```bash
npm i @parabolabs/otp-input
```## How to use
The following diagram displays the logical structure of the component:
```mermaid
flowchart TD
A[otp-input] --> B1[group 1]
A --> B2[group 2]
A --> BN[group N]
B1 --> C1[cell]
B1 --> C2[cell]
B1 --> C3[cell]
B2 --> D1[cell]
B2 --> D2[cell]
B2 --> D3[cell]
BN --> E1[cell]
BN --> E2[cell]
BN --> E3[cell]
```Customizations are possible via CSS custom properties and custom `ng-template`s the cells.
You can provide any of the following to change the default styling (if not using a custom template):
```text
// group
--otp-input-group-gap// cell
--otp-input-cell-font-family
--otp-input-cell-font-size
--otp-input-cell-color
--otp-input-cell-width
--otp-input-cell-height
--otp-input-cell-border-width
--otp-input-cell-border-color
--otp-input-cell-outer-border-radius
--otp-input-cell-inner-border-radius
--otp-input-cell-padding
--otp-input-cell-focus-outline-color
--otp-input-cell-focus-outline-width
--otp-input-cell-background// caret
--otp-input-caret-width
--otp-input-caret-height
--otp-input-caret-color
--otp-input-caret-animation-duration
```> [!TIP]
> You should use as many of these to make the component match your project's styling preferences.### Single Input Group
```ts
import {
OtpInputComponent,
OtpInputGroupComponent
} from '@parabolabs/otp-input';@Component({
selector: 'my-component',
standalone: true,
imports: [
OtpInputComponent,
OtpInputGroupComponent,
...
],
...
})
``````html
```
### Multiple Input Groups
```html
```
### Custom pattern
You can use one of the patterns provided by the library (`OTP_INPUT_DIGIT_REGEXP` - default and `OTP_INPUT_ALPHANUMERIC_REGEXP`) or provide your own.
> [!TIP]
> By default on mobile devices the keyboard will only display digits. If you provide your own regex, make sure to also set the `inputMode` to `'text'`.```html
```
### Custom Input Cell Template
You can provide your own custom `ng-template` that will be rendered for each input cell.
> [!NOTE]
> This is the most powerful and probably most useful feature of this library - you can make the input cells match your project's UI/UX design.> [!WARNING]
> Too keep the component accessible, do not use an `input` (or interactive HTML elements) in the cell's content - all the needed events are already handled by the underlying `input` element inside `prbl-otp-input`.You can even provide your own caret element, use the built-in one `` or not show a caret at all.
```ts
import {
OtpInputComponent,
OtpInputGroupComponent
} from '@parabolabs/otp-input';@Component({
selector: 'my-component',
standalone: true,
imports: [
OtpInputComponent,
OtpInputGroupComponent,
OtpInputCaret,
...
],
...
})
``````html
{{ symbol }}
```
The template receives the following context:
```ts
export interface OtpInputTemplateRefContext {
index: number;
isSelected: boolean;
symbol: string | undefined;
}
```## Built-in behavior
- The first empty cell is focused or if all values are filled - the last cell.
- Focus moves to the next empty cell after a value was entered.
- When focus is on the last cell, pressing a key will update its value.
- When focus is on a cell with value, pressing delete will delete the value and keep focus in the cell.
- By default only digits are allowed to be entered. Can be changed via the `pattern` input (see examples).
- You can use the arrow keys to move backwards and forwards inside the cells - however, the rightmost allowed cell is always the first empty one.
- You can delete/replace a filled cell's value at any position (using the arrow keys).
- Pasting replaces everything that's already been entered by the user.
- Pasting only triggers if all the characters in the pasted text pass the `pattern` validation.
- Entering characters in arbitrary order (e.g. fill them from right to left) is intentionally not supported.
- `FormControl` value is either the full code or an empty string.## Component API
### `prbl-otp-input`
| Input | Type | Required | Default | Description |
|---------------|------------------|:--------:|----------------------:|---------------------------------------------------------------|
| `codeLength` | `number` | ✔️ | | The length of the OTP code |
| `pattern` | `RegExp` | ✖️ | `/^[0-9]$/` | Regex which validates each entered symbol |
| `label` | `string` | ✖️ | `undefined` | `aria-label` for the input |
| `id` | `string` | ✖️ | `crypto.randomUUID()` | `id` for the input |
| `inputMode` | `string` | ✖️ | `numeric` | Sets the `inputMode` for the underlying `input` element |
| `disabled` | `boolean` | ✖️ | `false` | Whether the input is disabled |
| `codeEntered` | `output` | ✖️ | | Called when the user fills in all the characters of the code |### `prbl-otp-input-group`
| Input | Type | Required | Default | Description |
|------------------|---------------|:--------:|------------:|-----------------------------------------------------|
| `cells` | `number` | ️️️️️✔️ | | How many character cells should be rendered. |
| `cellStartIndex` | `number` | ✖️ | `0` | The starting index for the first cell in the group. |
| `cellTemplate` | `TemplateRef` | ✖️ | `undefined` | `` instance which will be rendered for each cell |