@devotp/react-ui
v1.0.0
Published
Headless React components for OTP verification. Provides UI only with zero API calls -- usable with any backend.
Readme
@devotp/react-ui
Headless React components for OTP verification. Provides UI only with zero API calls -- usable with any backend.
Installation
npm install @devotp/react-ui
# or
bun add @devotp/react-uiPeer Dependencies
react>= 18react-dom>= 18
Quick Start
import { DevOtp } from "@devotp/react-ui";
import type { RequestOtpResponse, ValidateOtpResponse, ResendOtpResponse } from "@devotp/react-ui";
function App() {
return (
<DevOtp
identifierType="both"
onRequestOtp={async (identifier, type) => {
const res = await fetch("/api/otp/send", {
method: "POST",
body: JSON.stringify({ identifier, type }),
});
return (await res.json()) as RequestOtpResponse;
}}
onValidateOtp={async (identifier, otp) => {
const res = await fetch("/api/otp/verify", {
method: "POST",
body: JSON.stringify({ identifier, otp }),
});
return (await res.json()) as ValidateOtpResponse;
}}
onResendOtp={async (identifier) => {
const res = await fetch("/api/otp/resend", {
method: "POST",
body: JSON.stringify({ identifier }),
});
return (await res.json()) as ResendOtpResponse;
}}
onSuccess={(data) => console.log("Verified!", data)}
/>
);
}Components
| Export | Description |
|--------|-------------|
| DevOtp | All-in-one compound component (identifier inputs + OTP modal) |
| DevOtpProvider | Context provider for building custom layouts |
| IdentifierStep | Email/phone input fields with verify buttons |
| OtpModal | OTP verification modal dialog |
| OtpInputBoxes | Individual OTP digit input boxes |
| CountrySelector | Country code dropdown for phone inputs |
Hooks
| Export | Description |
|--------|-------------|
| useDevOtp | Access context state and actions from any child component |
| useDevOtpContext | Same as useDevOtp (alias) |
Props (DevOtpProps)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| identifierType | "email" \| "phone" \| "both" | "both" | Which input(s) to render |
| otpLength | number | 6 | Number of OTP digit boxes |
| resendCooldown | number | 30 | Resend cooldown in seconds |
| onRequestOtp | (id, type) => Promise<RequestOtpResponse> | required | Send OTP handler |
| onValidateOtp | (id, otp) => Promise<ValidateOtpResponse> | required | Verify OTP handler |
| onResendOtp | (id) => Promise<ResendOtpResponse> | required | Resend OTP handler |
| onSuccess | (data: ValidateOtpResponse) => void | -- | Fires after all identifiers verified |
| onError | (error: Error) => void | -- | Error callback |
| texts | DevOtpTexts | -- | Override labels and button text |
| classNames | DevOtpClassNames | -- | CSS class overrides per slot |
| styles | DevOtpStyles | -- | Inline style overrides per slot |
| validate | DevOtpValidate \| false | built-in | Custom validators or false to disable |
| renderIdentifierInput | (props) => ReactNode | -- | Custom identifier input render prop |
| renderOtpInput | (props) => ReactNode | -- | Custom OTP input render prop |
| autoFocusOtp | boolean | true | Auto-focus first OTP box on modal open |
| showCountrySelector | boolean | false | Show country code dropdown |
| defaultCountry | string | -- | Default country (ISO 3166-1 alpha-2) |
| countryData | Record<string, CountryData> | built-in | Override country data |
| onCountryChange | (country: CountryData) => void | -- | Country selection callback |
Customization
Inline Styles
Pass a styles object with keys matching component slots (container, input, verifyButton, modalOverlay, otpInputBox, etc.).
CSS Classes
Pass a classNames object with the same slot keys to apply your own CSS classes.
Text Overrides
Pass a texts object to customize labels, placeholders, and button text.
Render Props
Use renderIdentifierInput and renderOtpInput for fully custom input components while keeping all state management.
Additional Exports
defaultStyles-- the built-in default style object- All shared types are re-exported from
@devotp/sharedfor convenience
