preline
Version:
Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
329 lines (240 loc) • 10.9 kB
Markdown
# Input Number
Input Number - input idea for Shop systems or so.
[](https://www.npmjs.com/package/@preline/input-number) [](https://opensource.org/licenses/MIT) [](https://preline.co/plugins/input-number.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 Input Number component provides a numeric input field with increment and decrement buttons. It's ideal for quantity selectors, cart systems, or any interface requiring numeric input with step controls.
**Key Features:**
- Numeric input with step controls
- Increment/decrement buttons
- Min/max value constraints
- Custom step values
- Programmatic control via JavaScript API
- Event system for value tracking
- Disabled state support
## Installation
To get started, install Input Number plugin via npm, else you can skip this step if you are already using Preline UI as a package.
```bash
npm i @preline/input-number
```
### 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/input-number */
@source "../node_modules/@preline/input-number/*.js";
@import "./node_modules/@preline/input-number/variants.css";
@import "./node_modules/@preline/input-number/theme.css";
```
### JavaScript
Include the JavaScript that powers the interactive elements near the end of your `</body>` tag:
```html
<script src="./node_modules/@preline/input-number/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 HSInputNumber from "@preline/input-number/non-auto.mjs";
new HSInputNumber(document.querySelector("#input-number"));
</script>
```
### Via Bundler
When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.
`@preline/input-number` is the auto-init entry: it scans the DOM and initializes matching elements automatically.
```js
import "@preline/input-number";
```
`@preline/input-number/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 HSInputNumber from "@preline/input-number/non-auto";
HSInputNumber.autoInit();
// Or initialize a specific element manually
const el = document.querySelector("#input-number");
if (el) new HSInputNumber(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 an input number component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The component includes an input field and increment/decrement buttons.
```html
<div data-hs-input-number>
<input type="text" aria-roledescription="Number field" value="1" data-hs-input-number-input>
<button type="button" class="" tabindex="-1" aria-label="Decrease" data-hs-input-number-decrement>
Minus
</button>
<button type="button" class="" tabindex="-1" aria-label="Increase" data-hs-input-number-increment>
Add
</button>
</div>
```
**Structure Requirements:**
- `data-hs-input-number`: Required on the container element
- `data-hs-input-number-input`: Required on the input element
- `data-hs-input-number-increment`: Required on the increment button
- `data-hs-input-number-decrement`: Required on the decrement button
- Proper ARIA attributes (`aria-roledescription`, `aria-label`)
**Initial State:**
- Input field contains the initial value (e.g., `value="1"`)
- Buttons are enabled/disabled based on min/max constraints
## Configuration Options
### Data Options
Data options are specified in the `data-hs-input-number` attribute.
| Attribute | Target Element | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `data-hs-input-number` | Container | - | - | Activate an Input Number by specifying on an element. Should be added to the container. |
| `:min` | Inside `data-hs-input-number` | number \| `"-Infinity"` | `0` | Defines the minimum possible value. `-Infinity` allows you to enter negative values without restrictions. |
| `:max` | Inside `data-hs-input-number` | number \| null | `null` | Defines the maximum possible value. `null` means no maximum limit. |
| `:step` | Inside `data-hs-input-number` | number | `1` | Determines the step by which the value will increase or decrease when buttons are clicked. |
| `:forceBlankValue` | Inside `data-hs-input-number` | boolean | `false` | Whether the input value should be blank when the value isn't set. When `true`, empty input shows blank instead of default value. |
**Example:**
```html
<div data-hs-input-number='{
"min": 0,
"max": 100,
"step": 5,
"forceBlankValue": false
}'>
<!-- Input and buttons -->
</div>
```
### Required CSS Classes / Data Attributes
These data attributes define the structure and must be present for the input number to function.
| Data Attribute | Required On | Purpose |
| --- | --- | --- |
| `data-hs-input-number-input` | Input element | Identifies the numeric input field |
| `data-hs-input-number-increment` | Button element | Identifies the increment button |
| `data-hs-input-number-decrement` | Button element | Identifies the decrement button |
### Tailwind Modifiers
| Name | Description |
| --- | --- |
| `hs-input-number-disabled:*` | A modifier that allows you to set Tailwind classes when input's value is set to zero (or minimum value). |
## JavaScript API
The `HSInputNumber` object is available in the global `window` object after the plugin is loaded.
### Instance Methods
These methods are called on an input number instance.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| `destroy()` | None | `void` | Destroys the input number instance, removes all generated markup, classes, and event listeners. Use when removing input number from DOM. |
### Static Methods
These methods are called directly on the `HSInputNumber` class.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| `HSInputNumber.getInstance(target, isInstance)` | `target`: `HTMLElement \| string` (CSS selector)<br>`isInstance`: `boolean` (optional) | `HSInputNumber \| { id: number, element: HSInputNumber } \| null` | Returns the input number instance associated with the target. If `isInstance` is `true`, returns collection item object `{ id, element }` where `element` is the `HSInputNumber` instance. If `isInstance` is `false` or omitted, returns the `HSInputNumber` instance directly. Returns `null` if input number instance is not found. |
### Usage Examples
**Example 1: Destroying input number instance**
```javascript
const instance = HSInputNumber.getInstance('#hs-input-number', 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 input number instance
const instance = HSInputNumber.getInstance('#hs-input-number', true);
if (instance) {
const { element } = instance;
// Access instance properties
console.log('Current value:', element.inputValue);
console.log('Min value:', element.minInputValue);
console.log('Max value:', element.maxInputValue);
console.log('Step:', element.step);
// Clean up when removing from DOM
function removeInputNumber() {
element.destroy();
}
}
```
**Example 3: Destroying input number instance**
```javascript
const instance = HSInputNumber.getInstance('#hs-input-number', 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-input-number').remove();
});
}
```
## Events
Input number instances emit events that can be listened to for value tracking and custom behavior.
| Event Name | When Fired | Callback Parameter | Description |
| --- | --- | --- | --- |
| `on:change` | When input value was changed | `{ inputValue: number }` | Fires when the input value changes (via buttons or direct input). Returns an object with the `inputValue` containing the current numeric value. |
### Event Usage Example
```javascript
// Get input number instance
const instance = HSInputNumber.getInstance('#hs-input-number', true);
if (instance) {
const { element } = instance;
// Listen to change event
element.on('change', ({ inputValue }) => {
console.log('Input value changed:', inputValue);
// Perform actions after value changes
// e.g., update cart, calculate totals, validate
});
}
```
## Common Patterns
### Pattern 1: Quantity Selector
Create a quantity selector for shopping carts.
```html
<div data-hs-input-number='{
"min": 1,
"max": 99,
"step": 1
}'>
<input type="text" value="1" data-hs-input-number-input>
<button data-hs-input-number-decrement>-</button>
<button data-hs-input-number-increment>+</button>
</div>
```
### Pattern 2: Negative Values Allowed
Allow negative values by setting min to -Infinity.
```html
<div data-hs-input-number='{
"min": "-Infinity",
"max": null,
"step": 1
}'>
<!-- Input and buttons -->
</div>
```
### Pattern 3: Handling Value Changes
Track value changes with event listener.
```html
<div id="hs-input-number-first" data-hs-input-number>
<input type="text" value="1" data-hs-input-number-input>
<button data-hs-input-number-decrement>-</button>
<button data-hs-input-number-increment>+</button>
</div>
<script>
const instance = HSInputNumber.getInstance('#hs-input-number-first', true);
if (instance) {
const { element } = instance;
element.on('change', ({ inputValue }) => {
console.log('Quantity:', inputValue);
// Update cart or perform other actions
});
}
</script>
```
## License
Copyright (c) 2026 Preline Labs.
Licensed under the [MIT License](https://opensource.org/licenses/MIT).