UNPKG

preline

Version:

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

242 lines (200 loc) 5.89 kB
/* * HSTogglePassword * @version: 3.0.1 * @author: Preline Labs Ltd. * @license: Licensed under MIT and Preline UI Fair Use License (https://preline.co/docs/license.html) * Copyright 2024 Preline Labs Ltd. */ import { isFormElement, dispatch } from '../../utils'; import { ITogglePasswordOptions, ITogglePassword, } from '../toggle-password/interfaces'; import HSBasePlugin from '../base-plugin'; import { ICollectionItem } from '../../interfaces'; class HSTogglePassword extends HSBasePlugin<ITogglePasswordOptions> implements ITogglePassword { private readonly target: | string | string[] | HTMLInputElement | HTMLInputElement[] | null; private isShown: boolean; private isMultiple: boolean; private eventType: string; private onElementActionListener: () => void; constructor(el: HTMLElement, options?: ITogglePasswordOptions) { super(el, options); const data = el.getAttribute('data-hs-toggle-password'); const dataOptions: ITogglePasswordOptions = data ? JSON.parse(data) : {}; const concatOptions = { ...dataOptions, ...options, }; const targets: HTMLInputElement[] = []; if (concatOptions?.target && typeof concatOptions?.target === 'string') { const ids = concatOptions?.target.split(','); ids.forEach((id) => { targets.push(document.querySelector(id) as HTMLInputElement); }); } else if ( concatOptions?.target && typeof concatOptions?.target === 'object' ) { (concatOptions.target as string[]).forEach((el) => targets.push(document.querySelector(el)), ); } else { (concatOptions.target as HTMLInputElement[]).forEach((el) => targets.push(el), ); } this.target = targets; this.isShown = this.el.hasAttribute('type') ? (this.el as HTMLInputElement).checked : false; this.eventType = isFormElement(this.el) ? 'change' : 'click'; this.isMultiple = this.target.length > 1 && !!this.el.closest('[data-hs-toggle-password-group]'); if (this.target) this.init(); } private elementAction() { if (this.isShown) { this.hide(); } else { this.show(); } this.fireEvent('toggle', this.target); dispatch('toggle.hs.toggle-select', this.el, this.target); } private init() { this.createCollection(window.$hsTogglePasswordCollection, this); if (!this.isShown) { this.hide(); } else { this.show(); } this.onElementActionListener = () => this.elementAction(); this.el.addEventListener(this.eventType, this.onElementActionListener); } private getMultipleToggles(): HSTogglePassword[] { const group = this.el.closest('[data-hs-toggle-password-group]'); const toggles = group.querySelectorAll('[data-hs-toggle-password]'); const togglesInCollection: HSTogglePassword[] = []; toggles.forEach((el: HTMLElement) => { togglesInCollection.push( HSTogglePassword.getInstance(el) as HSTogglePassword, ); }); return togglesInCollection; } // Public methods public show() { if (this.isMultiple) { const toggles = this.getMultipleToggles(); toggles.forEach((el: HSTogglePassword) => el ? (el.isShown = true) : false, ); this.el .closest('[data-hs-toggle-password-group]') .classList.add('active'); } else { this.isShown = true; this.el.classList.add('active'); } (this.target as HTMLInputElement[]).forEach((el) => { (el as HTMLInputElement).type = 'text'; }); } public hide() { if (this.isMultiple) { const toggles = this.getMultipleToggles(); toggles.forEach((el: HSTogglePassword) => el ? (el.isShown = false) : false, ); this.el .closest('[data-hs-toggle-password-group]') .classList.remove('active'); } else { this.isShown = false; this.el.classList.remove('active'); } (this.target as HTMLInputElement[]).forEach((el) => { (el as HTMLInputElement).type = 'password'; }); } public destroy() { // Remove classes if (this.isMultiple) { this.el .closest('[data-hs-toggle-password-group]') .classList.remove('active'); } else { this.el.classList.remove('active'); } // Remove attributes (this.target as HTMLInputElement[]).forEach((el) => { (el as HTMLInputElement).type = 'password'; }); // Remove listeners this.el.removeEventListener(this.eventType, this.onElementActionListener); this.isShown = false; window.$hsTogglePasswordCollection = window.$hsTogglePasswordCollection.filter( ({ element }) => element.el !== this.el, ); } // Static methods static getInstance(target: HTMLElement | string, isInstance?: boolean) { const elInCollection = window.$hsTogglePasswordCollection.find( (el) => el.element.el === (typeof target === 'string' ? document.querySelector(target) : target), ); return elInCollection ? isInstance ? elInCollection : elInCollection.element : null; } static autoInit() { if (!window.$hsTogglePasswordCollection) window.$hsTogglePasswordCollection = []; if (window.$hsTogglePasswordCollection) window.$hsTogglePasswordCollection = window.$hsTogglePasswordCollection.filter(({ element }) => document.contains(element.el), ); document .querySelectorAll( '[data-hs-toggle-password]:not(.--prevent-on-load-init)', ) .forEach((el: HTMLInputElement) => { if ( !window.$hsTogglePasswordCollection.find( (elC) => (elC?.element?.el as HTMLElement) === el, ) ) new HSTogglePassword(el); }); } } declare global { interface Window { HSTogglePassword: Function; $hsTogglePasswordCollection: ICollectionItem<HSTogglePassword>[]; } } window.addEventListener('load', () => { HSTogglePassword.autoInit(); // Uncomment for debug // console.log('Toggle password collection:', window.$hsTogglePasswordCollection); }); if (typeof window !== 'undefined') { window.HSTogglePassword = HSTogglePassword; } export default HSTogglePassword;