npm.io
5.0.0 • Published yesterday

@preline/pin-input

Licence
Licensed under MIT and Preline UI Fair Use License
Version
5.0.0
Deps
0
Size
76 kB
Vulns
0
Weekly
0
Stars
6.4K

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) 2024 Htmlstream.

Licensed under the MIT License.

Keywords