# Toggle Password

Show or hide password field.

[![npm](https://img.shields.io/badge/npm-v4.2.0-blue)](https://www.npmjs.com/package/@preline/toggle-password) [![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/toggle-password.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 Toggle Password component provides a button to toggle password visibility in input fields. It allows users to switch between showing and hiding password text, improving usability while maintaining security.

**Key Features:**
- Toggle password visibility
- Show/hide password text
- Support for multiple password fields
- Grouped toggle support
- Programmatic control via JavaScript API
- Event system for visibility tracking

## Installation

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

```bash
npm i @preline/toggle-password
```

### CSS

[`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS file into your Tailwind CSS file.

```css
@import "tailwindcss";

/* @preline/toggle-password */
@import "./node_modules/@preline/toggle-password/theme.css";
```

### JavaScript

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

```html
<script src="./node_modules/@preline/toggle-password/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 HSTogglePassword from "@preline/toggle-password/non-auto.mjs";

  new HSTogglePassword(document.querySelector("#toggle-password"));
</script>
```

### Via Bundler

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

`@preline/toggle-password` is the auto-init entry: it scans the DOM and initializes matching elements automatically.

```js
import "@preline/toggle-password";
```

`@preline/toggle-password/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 HSTogglePassword from "@preline/toggle-password/non-auto";

HSTogglePassword.autoInit();

// Or initialize a specific element manually
const el = document.querySelector("#toggle-password");
if (el) new HSTogglePassword(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 toggle password component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. Clicking the button toggles password visibility.

```html
<div class="relative">
  <input id="hs-toggle-password-first" type="password" name="password" class="py-3 px-4 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400" value="12345qwerty" required>
  <button type="button" data-hs-toggle-password='{
      "target": "#hs-toggle-password-first"
    }' class="absolute inset-y-0 end-0 flex items-center pointer-events-none z-10 p-3.5">
    <svg class="shrink-0 text-gray-400 size-4" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
      <path class="hs-password-active:hidden" d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/>
      <path class="hs-password-active:hidden" d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/>
      <path class="hs-password-active:hidden" d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12 .708-.708 12 12-.708.708z"/>
      <path class="hidden hs-password-active:block" d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
      <path class="hidden hs-password-active:block" d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
    </svg>
    <span class="hs-password-active:hidden">
      <svg class="shrink-0 text-gray-400 size-4" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
        <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"></path>
        <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"></path>
      </svg>
    </span>
  </button>
</div>
```

**Structure Requirements:**
- `data-hs-toggle-password`: Required on the toggle button, contains configuration options as JSON
- `:target`: Required, must be a valid CSS selector pointing to the password input field
- Password input field must exist in the DOM
- Toggle button can be positioned anywhere (commonly inside a relative container)

**Initial State:**
- Password input is hidden (type="password")
- Toggle button shows "show" icon

## Configuration Options

### Data Options

Data options are specified in the `data-hs-toggle-password` attribute as a JSON object.

| Option | Target Element | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `data-hs-toggle-password` | Toggle button | - | - | Activate a Toggle Password by specifying on an element. Should be added to the button (trigger). |
| `:target` | Inside `data-hs-toggle-password` | string (CSS selector) | - | Determines which element will change type on click. This must be a valid CSS selector pointing to the password input field. Required. |
| `:isShown` | Inside `data-hs-toggle-password` | boolean | `false` | Determines password visibility initially. When `true`, password is shown by default. |
| `:eventType` | Inside `data-hs-toggle-password` | `'change'` \| `'click'` | `'click'` | Determines event type. `click` for button clicks, `change` for checkbox/radio changes. |
| `data-hs-toggle-password-group` | Container element | - | - | This option allows you to group multiple toggle password elements together so that they can be toggled simultaneously. It should be added to the parent element of the toggle password elements. Should be added to the container. |

**Example:**
```html
<button data-hs-toggle-password='{
  "target": "#hs-password-input",
  "isShown": false,
  "eventType": "click"
}'>
  Toggle
</button>
```

### Tailwind Modifiers

| Name | Description |
| --- | --- |
| `hs-password-active:*` | A modifier that allows you to set Tailwind classes when the password was shown. |

## JavaScript API

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

### Instance Methods

These methods are called on a toggle password instance.

| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| `show()` | None | `void` | Toggle the field to type text (show password). Changes input type from `password` to `text`. |
| `hide()` | None | `void` | Toggle the field to type password (hide password). Changes input type from `text` to `password`. |
| `destroy()` | None | `void` | Destroys the toggle password instance, removes all generated markup, classes, and event listeners. Use when removing toggle password from DOM. |

### Static Methods

These methods are called directly on the `HSTogglePassword` class.

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

### Usage Examples

**Example 1: Showing password programmatically**
```javascript
// Get the toggle password instance
const instance = HSTogglePassword.getInstance('#hs-toggle-password', true);

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

  showBtn.addEventListener('click', () => {
    element.show();
  });
}
```

**Example 2: Hiding password programmatically**
```javascript
const instance = HSTogglePassword.getInstance('#hs-toggle-password', true);

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

  hideBtn.addEventListener('click', () => {
    element.hide();
  });
}
```

**Example 3: Getting instance and accessing properties**
```javascript
// Get the toggle password instance
const instance = HSTogglePassword.getInstance('#hs-toggle-password', true);

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

  // Access instance properties
  console.log('Is shown:', element.isShown);
  console.log('Target:', element.target);

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

**Example 4: Destroying toggle password instance**
```javascript
const instance = HSTogglePassword.getInstance('#hs-toggle-password', 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-toggle-password').remove();
  });
}
```

## Events

Toggle password instances emit events that can be listened to for visibility tracking and custom behavior.

| Event Name | When Fired | Callback Parameter | Description |
| --- | --- | --- | --- |
| `on:toggle` | When password was shown or hidden | `HTMLElement` (target input element) | Fires when password visibility changes. Returns the target password input element. |

### Event Usage Example

```javascript
// Get toggle password instance
const instance = HSTogglePassword.getInstance('#hs-toggle-password', true);

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

  // Listen to toggle event
  element.on('toggle', (target) => {
    console.log('Password visibility toggled:', target);
    // Perform actions after password visibility changes
    // e.g., track analytics, update UI
  });
}
```

## Common Patterns

### Pattern 1: Grouped Toggle

Group multiple password fields to toggle simultaneously.

```html
<div data-hs-toggle-password-group>
  <input type="password" id="password-1">
  <button data-hs-toggle-password='{"target": "#password-1"}'>Toggle</button>
  
  <input type="password" id="password-2">
  <button data-hs-toggle-password='{"target": "#password-2"}'>Toggle</button>
</div>
```

### Pattern 2: Initially Shown

Show password by default.

```html
<button data-hs-toggle-password='{
  "target": "#hs-password-input",
  "isShown": true
}'>
  Toggle
</button>
```

## License

Copyright (c) 2024 Htmlstream.

Licensed under the [MIT License](https://opensource.org/licenses/MIT).
