github.com/resonatecoop/id@v1.1.0-43/frontend/src/components/password-meter/index.js (about) 1 const html = require('choo/html') 2 const Component = require('choo/component') 3 const zxcvbnAsync = require('zxcvbn-async') 4 5 // Password meter component class 6 class PasswordMeter extends Component { 7 /*** 8 * Create a password meter component 9 * @param {string} id - The password meter component id (unique) 10 * @param {number} state - The choo app state 11 * @param {function} emit - Emit event on choo app 12 */ 13 constructor (id, state, emit) { 14 super(id) 15 16 this.emit = emit 17 this.state = state 18 19 this.local = state.components[id] = {} 20 } 21 22 /*** 23 * Create password meter component element 24 * @param {Object} props - The password meter component props 25 * @param {String} props.password - The password 26 * @returns {HTMLElement} 27 */ 28 createElement (props) { 29 this.local.password = props.password 30 31 const score = this.getScore(this.local.password) 32 const meter = [0, 1, 2, 3, 4] // zxcvbn score meter 33 34 return html` 35 <div class="flex flex-column"> 36 <div class="flex"> 37 ${this.local.password 38 ? meter.map((n) => { 39 const colors = [ 40 'dark-red', 41 'red', 42 'orange', 43 'green', 44 'dark-green' 45 ] 46 const color = n <= score ? colors[score] : 'gray' 47 48 return html` 49 <div style="height:3px" class="flex-auto w-100 bg-${color}"></div> 50 ` 51 }) 52 : '' 53 } 54 </div> 55 </div> 56 ` 57 } 58 59 /*** 60 * @description Get zxcvbn score for password 61 * @param {String} password - The password 62 * @returns {Number} The zxcvbn score 63 */ 64 getScore (password) { 65 if (!password) return 0 66 67 const zxcvbn = zxcvbnAsync.load({ 68 sync: true, 69 libUrl: 'https://cdn.jsdelivr.net/npm/zxcvbn@4.4.2/dist/zxcvbn.js', 70 libIntegrity: 'sha256-9CxlH0BQastrZiSQ8zjdR6WVHTMSA5xKuP5QkEhPNRo=' 71 }) 72 const { score } = zxcvbn(this.local.password || '') 73 return score 74 } 75 76 /*** 77 * Password meter component on update event handler 78 * @param {Object} props - Password meter component props 79 * @returns {Boolean} Should update 80 */ 81 update (props) { 82 return props.password !== this.local.password 83 } 84 } 85 86 module.exports = PasswordMeter