/antd-input-otp

An OTP Input Component based on Ant Design Component Library for React.

Primary LanguageTypeScript

antd-input-otp 📱

A custom input component for OTP (One Time Password) based on Ant Design Input for React.

antd-input-otp

Demo 🧪

Prerequisite ⭐

Install 💻

npm

npm install antd-input-otp

yarn

yarn add antd-input-otp

How to use 🪴

Simply import like other antd's components as usual and call it. You can use it uncontrolled with Form from Ant Design Form or use it controlled with React useState.

Keep in mind this component will return undefined or array of string.

Uncontrolled

import { Button, Form } from 'antd';
import { InputOTP } from 'antd-input-otp'; // Don't forget to import this too!

const InputOTPPage = () => {
  const [form] = Form.useForm();

  const handleFinish = (values) => {
    // Your logic
  };

  return (
    <Form onFinish={handleFinish} form={form}>
      <Form.Item label="OTP" name="otp">
        <InputOTP autoSubmit={form} inputType="numeric" />
      </Form.Item>

      <Form.Item>
        <Button htmlType="submit">Submit</Button>
      </Form.Item>
    </Form>
  );
};

Controlled

import { useState } from 'react';
import { Button } from 'antd';
import { InputOTP } from 'antd-input-otp'; // Don't forget to import this too!

const InputOTPPage = () => {
  const [value, setValue] = useState([]); // Since the value will be array of string, the default value of state is empty array.

  const handleFinish = (otp) => {
    const payload = otp || value; // Since useState work asynchronously, we shall add the field value from the autoSubmit.
    // Your logic with state
  };

  return (
    <div>
      <InputOTP onChange={setValue} value={value} autoSubmit={handleFinish} />

      <Button onClick={() => handleFinish()}>Submit</Button>
    </div>
  );
};

Props 🥠

Keep in mind, the props will be extended to antd InputProps, which means properties that are not listed below can be seen on Ant Design Input.

Property Type Default Value Description
autoFocus boolean false Autofocus for the first field of OTP. If you want to make the second or third or even the last field autofocused, use `inputRef.
autoSubmit FormInstance | (value: string[]) => void | null null Autosubmit when the value is fully filled.
disabled boolean false
inputClassName string Classes for styling input field.
inputRef Mutable Reference Object (InputRef[], null[], null) null Reference for the input fields. Inside of the current should be array of InputRef from antd.
inputRegex RegExp or string when inputType set as custom.
Other than that is never
If you choose custom as inputType, inputRegex will be mandatory.

Wrote your validation with regex here.
inputStyle CSSProperties Inline style input field.
inputType all | alphabet | alphabet-numeric | alphabet-symbol | numeric | numeric-symbol | symbol | custom all custom validation will be requiring your own regex on inputType.

Selecting all as the value will invalidate the field and every field can be filled with anything.
length number 6 Determine the total of your fields.

Keep in mind the minimum value is 2 and the maximum value is 16. The length will stay on the limit if you fill it outside the limit.
isPreservedFocus boolean false Determine whether the input is still focused or not when every field is filled.
onChange (value: string[]) => void
placeholder string Placeholder for each field. When the value is only one character It will apply to all fields with the same value.

For example, if you put "x", all fields will have x as placeholder.

If you want to keep it unique for each field, you must input the characters with the length same as the field.

For example, if you have 6 fields and want to keep the placeholder unique to each field, the value should be "x_x_x_".
value string[] | null
wrapperClassName string Classes for styling input wrapper.
wrapperStyle CSSProperties Inline style input wrapper.

FAQ ❓

Q: (NEW) When I use autoSubmit on controlled field, why my value always late 1 step?

A: You see, React useState works asynchronously, so when autoSubmit is triggered, the setState is not running yet. The solution so far is by using the value from the argument of the functions. You can see this in the example above.

Q: (NEW) I am using Webpack / create-react-app, why I always get an error Failed to parse source map from...?

A: To be honest, I am not quite sure about this, but the solution for now is to add this line of code inside your .env file.

GENERATE_SOURCEMAP=false

Q: Can I paste the OTP to this component?

A: YES! But you should update it to v1.1.0 first. Keep in mind, the value that you copy should be suitable with your inputType, for example if you have 030212 in your clipboard, and your inputType is numeric, it will work. But it will be a different story when your value is A023@c!, it won't work.

Q: What will this component return?

A: This component will return an array of strings if erased or already filled, or undefined if this component remains untouched.

Q: Can I use it on Ant Design Form?

A: Ofcourse, the best part is you don't need to setup anything. Just write and go!

Q: Ant Design Form is not my cup of tea, can I use it with useState instead?

A: You bet! Use it like other input with onChange and value.

Q: So I'm using Ant Design Form and I want to add an error below it, but it's ugly. How to fix it?

A: Interesting, first of all, add a class on your InputOTP's Form.Item. then add text-align: center on .ant-form-item .ant-form-item-explain-error.

If you are using antd v5, be sure to wrap .ant-form-item with :where(), so it will become like this..

.your-classname:where(.ant-form-item) .ant-form-item-explain-error {
  text-align: center;
}

Having another question? Ask me on the github issue!