npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mavenoutline/otp-input-mui

v1.0.0

Published

Accessible OTP / PIN input component for React/Next.js using MUI, with resend timer, paste handling, a11y, and edge cases covered.

Readme

@mavenoutline/otp-input-mui

Accessible, production-ready OTP / PIN input for React & Next.js built with MUI.
Supports paste, auto-advance, backspace, resend with timer, SSR safety, a11y, IME, and mobile one-time-code autofill.

Features

  • MUI-themed inputs (variant, size, color, error, helperText support).
  • Controlled & uncontrolled usage.
  • Paste full OTP (handles spaces, hyphens, unicode digits).
  • Auto focus next / previous on type & backspace.
  • Masked display (e.g., •) with optional reveal on focus.
  • Mobile & iOS SMS autofill (autoComplete="one-time-code").
  • Resend button with customizable timer, formatting, and callbacks.
  • onComplete fires when all slots are filled.
  • RTL-aware and accessible (labels, descriptions, roles).
  • Imperative API via ref: focus, blur, clear, setValue.
  • Fully typed, tree-shakeable, ESM & CJS builds via tsup.

Install

npm i @mavenoutline/otp-input-mui
# peer deps
npm i @mui/material @emotion/react @emotion/styled

Quick start

import { OtpInput } from "@mavenoutline/otp-input-mui";

export default function Example() {
  const [code, setCode] = useState("");
  return (
    <OtpInput
      length={6}
      value={code}
      onChange={setCode}
      onComplete={(otp) => console.log("complete:", otp)}
      label="Enter verification code"
      resend={{
        seconds: 30,
        onResend: () => console.log("Resend clicked"),
      }}
      variant="outlined"
      size="medium"
      error={false}
      helperText="We sent it via SMS"
    />
  );
}

Props

type OtpInputProps = {
  length?: number; // default 6
  value?: string;              // controlled
  defaultValue?: string;       // uncontrolled
  onChange?: (value: string) => void;
  onComplete?: (value: string) => void;
  onInvalidChar?: (char: string) => void;

  // Input behavior
  type?: "number" | "text"; // default "number"
  inputMode?: React.HTMLAttributes<HTMLInputElement>["inputMode"];
  allowedChars?: RegExp; // default: digits when type="number", otherwise /./
  mask?: string | false; // e.g., "•" to mask, false to show raw characters
  revealOnFocus?: boolean; // default: false

  // MUI
  variant?: "outlined" | "filled" | "standard";
  size?: "small" | "medium";
  color?: "primary" | "secondary" | "error" | "info" | "success" | "warning";
  error?: boolean;
  disabled?: boolean;
  fullWidth?: boolean;
  label?: React.ReactNode;
  helperText?: React.ReactNode;
  TextFieldProps?: Partial<import("@mui/material").TextFieldProps>;

  // Layout
  gap?: number | string;      // spacing between cells
  renderSeparator?: React.ReactNode; // element between cells (e.g., <Box sx={{mx:1}}>-</Box>)

  // Resend
  resend?: {
    seconds?: number; // default 30
    autoStart?: boolean; // default true
    onResend?: () => void | Promise<void>;
    format?: (remaining: number) => string; // default mm:ss
    label?: React.ReactNode; // "Resend"
    disabled?: boolean;
    maxAttempts?: number; // default Infinity
    attemptsStorageKey?: string; // to persist attempts across reloads
  };

  // A11y
  id?: string;
  name?: string;
  "aria-describedby"?: string;

  // Imperative API
  ref?: React.Ref<OtpInputRef>;
};

export type OtpInputRef = {
  focus: (index?: number) => void;
  blur: () => void;
  clear: () => void;
  setValue: (value: string) => void;
  getValue: () => string;
};

Resend timer text

The timer format can be customized:

resend={{ seconds: 45, format: (s) => `Time remaining: ${s}s` }}

Paste handling

Users can paste the entire code (e.g., 123 456 or 123-456). Non-allowed characters are ignored.

Next.js (SSR) notes

  • Component is SSR-safe. Focus logic and window usage are guarded.
  • For App Router (app/), include "use client" at the top of your page or component file where you render <OtpInput />.

Theming

Uses your MUI theme. Customize via sx or theme overrides using the class name MuiOtpInput-root and MuiOtpInput-cell.

License

MIT © mavenoutline