UNPKG

preline

Version:

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

314 lines (225 loc) 10 kB
# PIN Input A PIN Input plugin that allows to fill in data for inputs. [![npm](https://img.shields.io/badge/npm-v4.2.0-blue)](https://www.npmjs.com/package/@preline/pin-input) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Demo](https://img.shields.io/badge/demo-online-brightgreen)](https://preline.co/plugins/pin-input.html) ## Contents - [Overview](#overview) - [Installation](#installation) - [Basic usage](#basic-usage) - [Configuration Options](#configuration-options) - [JavaScript API](#javascript-api) - [Events](#events) - [Common Patterns](#common-patterns) - [License](#license) ## 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. ```bash npm i @preline/pin-input ``` ### CSS Use [`@source`](https://tailwindcss.com/docs/functions-and-directives#source-directive) to register the plugin's JavaScript path for Tailwind CSS scanning, then [`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS files into your Tailwind CSS file. ```css @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: ```html <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. ```html <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. ```js 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. ```js 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. ```html <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:** ```html <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)<br>`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** ```javascript 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** ```javascript // 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** ```javascript 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 ```javascript // 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. ```html <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. ```html <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. ```html <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](https://opensource.org/licenses/MIT).