| /*! |
| * Bootstrap strength.js v6.0.0-alpha1 (https://getbootstrap.com/) |
| * Copyright 2011-2026 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| */ |
| import BaseComponent from "./base-component.js"; |
| import EventHandler from "./dom/event-handler.js"; |
| import SelectorEngine from "./dom/selector-engine.js"; |
| //#region js/src/strength.ts |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap strength.ts |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * Constants |
| */ |
| const NAME = "strength"; |
| const EVENT_KEY = `.bs.strength`; |
| const DATA_API_KEY = ".data-api"; |
| const EVENT_STRENGTH_CHANGE = `strengthChange${EVENT_KEY}`; |
| const SELECTOR_DATA_STRENGTH = "[data-bs-strength]"; |
| const STRENGTH_LEVELS = [ |
| "weak", |
| "fair", |
| "good", |
| "strong" |
| ]; |
| const Default = { |
| input: null, |
| minLength: 8, |
| messages: { |
| weak: "Weak", |
| fair: "Fair", |
| good: "Good", |
| strong: "Strong" |
| }, |
| weights: { |
| minLength: 1, |
| extraLength: 1, |
| lowercase: 1, |
| uppercase: 1, |
| numbers: 1, |
| special: 1, |
| multipleSpecial: 1, |
| longPassword: 1 |
| }, |
| thresholds: [ |
| 2, |
| 4, |
| 6 |
| ], |
| scorer: null |
| }; |
| const DefaultType = { |
| input: "(string|element|null)", |
| minLength: "number", |
| messages: "object", |
| weights: "object", |
| thresholds: "array", |
| scorer: "(function|null)" |
| }; |
| /** |
| * Class definition |
| */ |
| var Strength = class extends BaseComponent { |
| constructor(element, config) { |
| super(element, config); |
| this._input = this._getInput(); |
| this._segments = SelectorEngine.find(".strength-segment", this._element); |
| this._textElement = SelectorEngine.findOne(".strength-text", this._element.parentElement); |
| this._currentStrength = null; |
| if (this._input) { |
| this._addEventListeners(); |
| this._evaluate(); |
| } |
| } |
| static get Default() { |
| return Default; |
| } |
| static get DefaultType() { |
| return DefaultType; |
| } |
| static get NAME() { |
| return NAME; |
| } |
| getStrength() { |
| return this._currentStrength; |
| } |
| evaluate() { |
| this._evaluate(); |
| } |
| _getInput() { |
| if (this._config.input) return typeof this._config.input === "string" ? SelectorEngine.findOne(this._config.input) : this._config.input; |
| const parent = this._element.parentElement; |
| return SelectorEngine.findOne("input[type=\"password\"]", parent); |
| } |
| _addEventListeners() { |
| EventHandler.on(this._input, "input", () => this._evaluate()); |
| EventHandler.on(this._input, "change", () => this._evaluate()); |
| } |
| _evaluate() { |
| const password = this._input.value; |
| const score = this._calculateScore(password); |
| const strength = this._scoreToStrength(score); |
| if (strength !== this._currentStrength) { |
| this._currentStrength = strength; |
| this._updateUI(strength); |
| EventHandler.trigger(this._element, EVENT_STRENGTH_CHANGE, { |
| strength, |
| score, |
| password: password.length > 0 ? "***" : "" |
| }); |
| } |
| } |
| _calculateScore(password) { |
| if (!password) return 0; |
| if (typeof this._config.scorer === "function") return this._config.scorer(password); |
| const { weights } = this._config; |
| let score = 0; |
| if (password.length >= this._config.minLength) score += weights.minLength; |
| if (password.length >= this._config.minLength + 4) score += weights.extraLength; |
| if (/[a-z]/.test(password)) score += weights.lowercase; |
| if (/[A-Z]/.test(password)) score += weights.uppercase; |
| if (/\d/.test(password)) score += weights.numbers; |
| if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score += weights.special; |
| if (/[!@#$%^&*(),.?":{}|<>].*[!@#$%^&*(),.?":{}|<>]/.test(password)) score += weights.multipleSpecial; |
| if (password.length >= 16) score += weights.longPassword; |
| return score; |
| } |
| _scoreToStrength(score) { |
| if (score === 0) return null; |
| const [weak, fair, good] = this._config.thresholds; |
| if (score <= weak) return "weak"; |
| if (score <= fair) return "fair"; |
| if (score <= good) return "good"; |
| return "strong"; |
| } |
| _updateUI(strength) { |
| if (strength) this._element.dataset.bsStrength = strength; |
| else delete this._element.dataset.bsStrength; |
| const strengthIndex = strength ? STRENGTH_LEVELS.indexOf(strength) : -1; |
| for (const [index, segment] of this._segments.entries()) if (index <= strengthIndex) segment.classList.add("active"); |
| else segment.classList.remove("active"); |
| if (this._textElement) if (strength && this._config.messages[strength]) { |
| this._textElement.textContent = this._config.messages[strength]; |
| this._textElement.dataset.bsStrength = strength; |
| this._textElement.style.setProperty("--strength-color", `var(--${{ |
| weak: "danger", |
| fair: "warning", |
| good: "info", |
| strong: "success" |
| }[strength]}-text)`); |
| } else { |
| this._textElement.textContent = ""; |
| delete this._textElement.dataset.bsStrength; |
| } |
| } |
| }; |
| /** |
| * Data API implementation |
| */ |
| EventHandler.on(document, `DOMContentLoaded${EVENT_KEY}${DATA_API_KEY}`, () => { |
| for (const element of SelectorEngine.find(SELECTOR_DATA_STRENGTH)) Strength.getOrCreateInstance(element); |
| }); |
| //#endregion |
| export { Strength as default }; |
| |
| //# sourceMappingURL=strength.js.map |