├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── examples └── index.html ├── main.js ├── package.json ├── password-strength-meter.js ├── style.css └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | public 4 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 4.2.2 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Abhijeet Mishra (https://github.com/abhijeetNmishra) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [React Password Strength Meter](https://github.com/abhijeetNmishra/react-password-strength-meter) 2 | React Component to display password strength meter with message and warning 3 | 4 | ## Dependencies 5 | This Component is built using [Dropbox zxcvbn password strength estimator library](https://github.com/dropbox/zxcvbn) 6 | 7 | ## Installation & Usage 8 | 9 | ``` 10 | npm install react-password-strength-meter --save 11 | ``` 12 | 13 | ## Password Strength Meter and values 14 | This component will 'strength' meter as prop value (type: object). 15 | 16 | ``` 17 | strength default value : 18 | strength : { 19 | 0: "Worst ☹", 20 | 1: "Bad ☹", 21 | 2: "Weak ☹", 22 | 3: "Good ☺", 23 | 4: "Strong ☻" 24 | } 25 | ``` 26 | 27 | ### Include the Component 28 | 29 | ``` 30 | var React = require('react'); 31 | var PasswordStrengthMeter = require('react-password-strength-meter'); 32 | 33 | class Component extends React.Component { 34 | constructor(props){ 35 | super(props); 36 | this.onChange = this.onChange.bind(this); 37 | } 38 | 39 | onChange(event){ 40 | 41 | } 42 | 43 | render() { 44 | return ; 45 | } 46 | } 47 | ``` 48 | 49 | ## License 50 | 51 | React Password Strength Meter is released under the MIT license. See [LICENSE](LICENSE) for details. 52 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react password strength meter 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from 'react-dom'; 3 | import PasswordStrengthMeter from './password-strength-meter'; 4 | 5 | require('./style.css'); 6 | 7 | render( 8 | ,document.getElementById('content') 9 | ) 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-password-strength-meter", 3 | "version": "1.0.5", 4 | "description": "react component to display password strength meter", 5 | "license": "MIT", 6 | "repository": "abhijeetNmishra/react-password-strength-meter", 7 | "main": "lib/index.js", 8 | "author": { 9 | "name": "Abhijeet Mishra", 10 | "email": "geminiabhijeet@gmail.com" 11 | }, 12 | "engines": { 13 | "node": "4.2.2" 14 | }, 15 | "scripts": { 16 | "build": "babel password-strength-meter.js --out-file lib/index.js", 17 | "prepublish": "npm run build" 18 | }, 19 | "files": [ 20 | "lib/index.js" 21 | ], 22 | "keywords": [ 23 | "react", 24 | "password meter", 25 | "react-component", 26 | "password strength checker", 27 | "zxcvbn" 28 | ], 29 | "dependencies": { 30 | "zxcvbn": "^4.2.0" 31 | }, 32 | "peerDependencies": { 33 | "react": "^0.14.3", 34 | "react-dom": "^0.14.3" 35 | }, 36 | "devDependencies": { 37 | "babel-core": "^6.2.1", 38 | "babel-loader": "^6.2.0", 39 | "babel-polyfill": "^6.2.0", 40 | "babel-runtime": "^6.2.0", 41 | "babel-plugin-transform-runtime": "^6.1.18", 42 | "babel-preset-es2015": "^6.1.18", 43 | "babel-preset-react": "^6.1.18", 44 | "css-loader": "^0.23.0", 45 | "style-loader": "^0.13.0", 46 | "webpack": "^1.12.9", 47 | "webpack-dev-server": "^1.14.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /password-strength-meter.js: -------------------------------------------------------------------------------- 1 | import React, {Component,PropTypes} from 'react'; 2 | import ReactDom from 'react-dom'; 3 | import zxcvbn from 'zxcvbn'; 4 | 5 | export default class PasswordStrengthMeter extends Component{ 6 | constructor(props){ 7 | super(props); 8 | this.handleInput = this.handleInput.bind(this); 9 | this.state = { 10 | resultScore: '', 11 | warning: '', 12 | suggestions:'' 13 | }; 14 | } 15 | 16 | handleInput(event){ 17 | event.preventDefault(); 18 | let { strength } = this.props; 19 | strength = (strength) ? strength : { 20 | 0: "Worst ☹", 21 | 1: "Bad ☹", 22 | 2: "Weak ☹", 23 | 3: "Good ☺", 24 | 4: "Strong ☻" 25 | } 26 | 27 | const password = ReactDom.findDOMNode(this.refs.password); 28 | const meter = ReactDom.findDOMNode(this.refs.passwordStrengthMeter); 29 | const text = ReactDom.findDOMNode(this.refs.passwordStrengthText); 30 | 31 | let val = password.value; 32 | let result = zxcvbn(val); 33 | 34 | // Update the password strength meter 35 | meter.value = result.score; 36 | 37 | // Update the text indicator 38 | if(val !== "") { 39 | this.setState({ 40 | resultScore:strength[result.score], 41 | warning:result.feedback.warning, 42 | suggestions:result.feedback.suggestions 43 | }); 44 | } 45 | else { 46 | this.setState({ 47 | resultScore:'', 48 | warning:'', 49 | suggestions:'' 50 | }) 51 | } 52 | 53 | if(typeof this.props.onChange === 'function'){ 54 | this.props.onChange(event); 55 | } 56 | } 57 | 58 | render(){ 59 | const { passwordText } = this.props; 60 | const passwordHeader = (passwordText) ? passwordText : 'Enter Password'; 61 | const {resultScore,warning,suggestions} = this.state; 62 | return( 63 |
64 | 65 | 66 | 67 | 68 |

69 | {resultScore && 70 | "Strength: "} 71 | {resultScore}{warning + " " + suggestions} 72 |

73 |
74 | ) 75 | } 76 | } 77 | 78 | PasswordStrengthMeter.propTypes = { 79 | passwordText: React.PropTypes.string, 80 | strength: React.PropTypes.object, 81 | onChange: React.PropTypes.func, 82 | } 83 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Signika:400,700|Courgette); 2 | 3 | #content section { 4 | margin: 0em auto 0; 5 | width: 100%; 6 | max-width: 800px; 7 | } 8 | 9 | #content input { 10 | display: block; 11 | margin: .5em auto 0em; 12 | padding: -0.5em 1em 0.5em 0.7em; 13 | width: 100%; 14 | border: none; 15 | background: #159957; 16 | color: white; 17 | font-size: 2em; 18 | line-height: 0; 19 | transition: all .5s linear; 20 | } 21 | 22 | input:hover, input:focus { 23 | outline: 0; 24 | transition: all .5s linear; 25 | box-shadow: inset 0px 0px 10px #ccc; 26 | } 27 | 28 | meter { 29 | /* Reset the default appearance */ 30 | -webkit-appearance: none; 31 | -moz-appearance: none; 32 | appearance: none; 33 | 34 | margin: 0 auto 1em; 35 | width: 100%; 36 | height: .5em; 37 | 38 | /* Applicable only to Firefox */ 39 | background: none; 40 | background-color: rgba(0,0,0,0.1); 41 | } 42 | 43 | meter::-webkit-meter-bar { 44 | background: none; 45 | background-color: rgba(0,0,0,0.1); 46 | } 47 | 48 | meter[value="1"]::-webkit-meter-optimum-value { background: red; } 49 | meter[value="2"]::-webkit-meter-optimum-value { background: yellow; } 50 | meter[value="3"]::-webkit-meter-optimum-value { background: orange; } 51 | meter[value="4"]::-webkit-meter-optimum-value { background: green; } 52 | 53 | meter[value="1"]::-moz-meter-bar { background: red; } 54 | meter[value="2"]::-moz-meter-bar { background: yellow; } 55 | meter[value="3"]::-moz-meter-bar { background: orange; } 56 | meter[value="4"]::-moz-meter-bar { background: green; } 57 | 58 | .feedback { 59 | color: #9ab; 60 | font-size: 90%; 61 | padding: 0 .25em; 62 | font-family: Courgette, cursive; 63 | margin-top: 1em; 64 | } 65 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | var nodeModulesPath = path.join(__dirname, 'node_modules'); 4 | 5 | module.exports = { 6 | entry: [ 7 | // Set up an ES6-ish environment 8 | // Add your application's scripts below 9 | './main', 10 | ], 11 | output: { 12 | filename: 'main.js', 13 | path: path.join(__dirname, 'public'), 14 | publicPath: '/public/' 15 | }, 16 | module: { 17 | loaders: [{ 18 | loader: "babel-loader", 19 | 20 | exclude: nodeModulesPath, 21 | 22 | // Only run `.js` and `.jsx` files through Babel 23 | test: /\.jsx?$/, 24 | 25 | // Options to configure babel with 26 | query: { 27 | plugins: [], 28 | presets: ['es2015', 'react'], 29 | } 30 | },{ test: /\.css$/, loader: "style-loader!css-loader" }] 31 | }, 32 | plugins: [ 33 | new webpack.optimize.UglifyJsPlugin({ 34 | compress: { 35 | warnings: false 36 | } 37 | }), 38 | new webpack.optimize.DedupePlugin() 39 | ] 40 | } 41 | --------------------------------------------------------------------------------