import { warnOnce } from '../core/app-dom.js'; const rules = { min: (value, min) => value.length >= min, upper: (value) => /[A-Z]/.test(value), lower: (value) => /[a-z]/.test(value), number: (value) => /\d/.test(value), symbol: (value) => /[^a-zA-Z0-9]/.test(value), email: (value, _min, email) => { if (!email) {return true;} return !value.toLowerCase().includes(email.toLowerCase()); }, match: (_value, _min, _email, confirm) => { if (!confirm) {return false;} return true; } }; export function initPasswordHints() { const containers = document.querySelectorAll('[data-password-hints]'); if (!containers.length) {return;} containers.forEach((container) => { if (!(container instanceof HTMLElement)) {return;} if (container.dataset.passwordHintsBound === '1') {return;} const passwordSelector = container.dataset.passwordInput; const confirmSelector = container.dataset.confirmInput; const emailSelector = container.dataset.emailInput; const passwordInput = passwordSelector ? document.querySelector(passwordSelector) : null; const confirmInput = confirmSelector ? document.querySelector(confirmSelector) : null; const emailInput = emailSelector ? document.querySelector(emailSelector) : null; if (passwordSelector && !passwordInput) { warnOnce('UI_EL_MISSING', `Missing password input: ${passwordSelector}`, { module: 'password-hints' }); } if (confirmSelector && !confirmInput) { warnOnce('UI_EL_MISSING', `Missing confirm input: ${confirmSelector}`, { module: 'password-hints' }); } if (emailSelector && !emailInput) { warnOnce('UI_EL_MISSING', `Missing email input: ${emailSelector}`, { module: 'password-hints' }); } const minLength = Number.parseInt(container.dataset.minLength || '12', 10); const items = container.querySelectorAll('[data-rule]'); const setState = (item, state) => { item.classList.remove('is-valid', 'is-invalid'); if (state === 'valid') {item.classList.add('is-valid');} if (state === 'invalid') {item.classList.add('is-invalid');} }; const evaluate = () => { const password = passwordInput?.value ?? ''; const confirm = confirmInput?.value ?? ''; const email = emailInput?.value ?? ''; const hasValue = password.length > 0 || confirm.length > 0; items.forEach((item) => { const rule = item.dataset.rule; if (!rule) {return;} if (!hasValue) { setState(item, 'neutral'); return; } if (rule === 'match') { if (password === '' || confirm === '') { setState(item, 'neutral'); return; } setState(item, password === confirm ? 'valid' : 'invalid'); return; } const check = rules[rule]; if (!check) {return;} const ok = check(password, minLength, email, confirm); setState(item, ok ? 'valid' : 'invalid'); }); }; if (passwordInput) {passwordInput.addEventListener('input', evaluate);} if (confirmInput) {confirmInput.addEventListener('input', evaluate);} if (emailInput) {emailInput.addEventListener('input', evaluate);} evaluate(); container.dataset.passwordHintsBound = '1'; }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initPasswordHints); } else { initPasswordHints(); }