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

@preline/pin-input

v4.2.0

Published

Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.

Readme

PIN Input

A PIN Input plugin that allows to fill in data for inputs.

npm License: MIT Demo

Contents

Overview

The PIN Input component provides a multi-field input interface for entering PIN codes, verification codes, or similar numeric/alphanumeric sequences. It automatically moves focus between fields and supports paste operations.

Key Features:

  • Multiple input fields for PIN entry
  • Automatic focus management
  • Paste support for bulk entry
  • Character validation via regex
  • Programmatic control via JavaScript API
  • Event system for completion tracking
  • Accessibility support

Installation

To get started, install PIN Input plugin via npm, else you can skip this step if you are already using Preline UI as a package.

npm i @preline/pin-input

CSS

Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.

@import "tailwindcss";

/* @preline/pin-input */
@source "../node_modules/@preline/pin-input/*.js";
@import "./node_modules/@preline/pin-input/variants.css";
@import "./node_modules/@preline/pin-input/theme.css";

JavaScript

Include the JavaScript that powers the interactive elements near the end of your </body> tag:

<script src="./node_modules/@preline/pin-input/index.js"></script>

Manual Initialization

Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.

<script type="module">
  import HSPinInput from "@preline/pin-input/non-auto.mjs";

  new HSPinInput(document.querySelector("#pin-input"));
</script>

Via Bundler

When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.

@preline/pin-input is the auto-init entry: it scans the DOM and initializes matching elements automatically.

import "@preline/pin-input";

@preline/pin-input/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.

import HSPinInput from "@preline/pin-input/non-auto";

HSPinInput.autoInit();

// Or initialize a specific element manually
const el = document.querySelector("#pin-input");
if (el) new HSPinInput(el);

TypeScript

This package ships with TypeScript type definitions. No additional @types/ package is needed.

Basic usage

The following example demonstrates the minimal HTML structure required for a PIN input component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The component consists of multiple input fields that automatically advance focus.

<div data-hs-pin-input>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
</div>

Structure Requirements:

  • data-hs-pin-input: Required on the container element
  • data-hs-pin-input-item: Required on each input field
  • All input fields should be direct children of the container

Initial State:

  • Input fields are empty by default
  • Focus starts on the first input field (if autofocus class is used)

Configuration Options

Data Options

Data options are specified in the data-hs-pin-input attribute.

| Attribute | Target Element | Type | Default | Description | | --- | --- | --- | --- | --- | | data-hs-pin-input | Container | - | - | Activate a Pin Input by specifying on an element. Should be added to the container. | | :availableCharsRE | Inside data-hs-pin-input | RegExp (string) | "^[a-zA-Z0-9]+$" | Regular expression string for available characters. Only characters matching this regex will be accepted. | | data-hs-pin-input-item | Input element | - | - | Determines which element inside the initialized container will be responsible for entering data. Should be added to the input. |

Example:

<div data-hs-pin-input='{
  "availableCharsRE": "^[0-9]+$"
}'>
  <!-- Input fields -->
</div>

CSS Classes (Modifiers)

CSS class modifiers use Tailwind-style syntax with -- prefix to control PIN input behavior.

| Class | Required On | Purpose | | --- | --- | --- | | autofocus | One of the input fields | If one of the fields has this class, it will be focused when the page loads. |

Tailwind Modifiers

| Name | Description | | --- | --- | | hs-pin-input-active:* | The class is added to the input when the PIN has been set up (all fields are filled). |

JavaScript API

The HSPinInput object is available in the global window object after the plugin is loaded.

Instance Methods

These methods are called on a PIN input instance.

| Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | destroy() | None | void | Destroys the PIN input instance, removes all generated markup, classes, and event listeners. Use when removing PIN input from DOM. |

Static Methods

These methods are called directly on the HSPinInput class.

| Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | HSPinInput.getInstance(target, isInstance) | target: HTMLElement \| string (CSS selector)isInstance: boolean (optional) | HSPinInput \| { id: string \| number, element: HSPinInput } \| null | Returns the PIN input instance associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSPinInput instance. If isInstance is false or omitted, returns the HSPinInput instance directly. Returns null if PIN input instance is not found. |

Usage Examples

Example 1: Destroying PIN input instance

const instance = HSPinInput.getInstance('#hs-pin-input', true);

if (instance) {
  const { element } = instance;
  const destroyBtn = document.querySelector('#hs-destroy-btn');

  destroyBtn.addEventListener('click', () => {
    element.destroy();
  });
}

Example 2: Getting instance and accessing properties

// Get the PIN input instance
const instance = HSPinInput.getInstance('#hs-pin-input', true);

if (instance) {
  const { element } = instance;

  // Access instance properties
  console.log('Current value:', element.currentValue);
  console.log('Items:', element.items);

  // Clean up when removing from DOM
  function removePinInput() {
    element.destroy();
  }
}

Example 3: Destroying PIN input instance

const instance = HSPinInput.getInstance('#hs-pin-input', true);

if (instance) {
  const { element } = instance;
  const removeBtn = document.querySelector('#hs-remove-btn');

  removeBtn.addEventListener('click', () => {
    // Clean up before removing from DOM
    element.destroy();
    // Now safe to remove the element
    document.querySelector('#hs-pin-input').remove();
  });
}

Events

PIN input instances emit events that can be listened to for completion tracking and custom behavior.

| Event Name | When Fired | Callback Parameter | Description | | --- | --- | --- | --- | | on:completed | When the PIN has been set up (all fields filled) | { currentValue: string } | Fires when all input fields have been filled. Returns an object with the currentValue containing the complete PIN string. |

Event Usage Example

// Get PIN input instance
const instance = HSPinInput.getInstance('#hs-pin-input', true);

if (instance) {
  const { element } = instance;

  // Listen to completed event
  element.on('completed', ({ currentValue }) => {
    console.log('PIN completed:', currentValue);
    // Perform actions after PIN is completed
    // e.g., validate PIN, submit form, proceed to next step
  });
}

Common Patterns

Pattern 1: Numeric PIN Only

Restrict input to numbers only.

<div data-hs-pin-input='{
  "availableCharsRE": "^[0-9]+$"
}'>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
</div>

Pattern 2: Auto-focus First Field

Automatically focus the first field on page load.

<div data-hs-pin-input>
  <input type="text" data-hs-pin-input-item class="autofocus">
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
</div>

Pattern 3: Handling Completion

Handle PIN completion with event listener.

<div id="hs-pin-input-first" data-hs-pin-input>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
  <input type="text" data-hs-pin-input-item>
</div>

<script>
  const instance = HSPinInput.getInstance('#hs-pin-input-first', true);
  
  if (instance) {
    const { element } = instance;

    element.on('completed', ({ currentValue }) => {
      console.log('PIN entered:', currentValue);
      // Validate or submit the PIN
    });
  }
</script>

License

Copyright (c) 2026 Preline Labs.

Licensed under the MIT License.