├── public ├── favicon.ico ├── manifest.json └── index.html ├── src ├── index.js ├── components │ ├── PasswordList.js │ ├── Password.js │ └── Settings.js ├── utility │ └── password-generator.js └── App.js ├── README.md ├── .gitignore └── package.json /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luizbatanero/password-generator-react/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import 'semantic-ui-css/semantic.min.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Password Generator 2 | :lock: Password generator built with React and SemanticUI 3 | 4 | ### [Live Demo](https://password-generator-react.netlify.com/) 5 | 6 | ## Running Locally 7 | 8 | ```sh 9 | npm install 10 | npm start 11 | ``` 12 | 13 | Runs the app in development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/components/PasswordList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Password from './Password'; 3 | import { Loader } from 'semantic-ui-react'; 4 | 5 | const PasswordList = ({ passwords, isLoading }) => { 6 | if (isLoading) { 7 | return ( 8 | 14 | ); 15 | } 16 | return ( 17 |
18 | {passwords.map((password) => ( 19 | 20 | ))} 21 |
22 | ); 23 | }; 24 | 25 | export default PasswordList; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password-generator-react", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.8.6", 7 | "react-copy-to-clipboard": "^5.0.1", 8 | "react-dom": "^16.8.6", 9 | "react-scripts": "3.0.1", 10 | "react-semantic-ui-range": "^0.7.0", 11 | "semantic-ui-css": "^2.4.1", 12 | "semantic-ui-react": "^0.87.1", 13 | "zxcvbn": "^4.4.2" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/utility/password-generator.js: -------------------------------------------------------------------------------- 1 | function getCharactersFromSettings({ 2 | lowerCase, 3 | upperCase, 4 | numbers, 5 | symbols, 6 | allowedSymbols 7 | }) { 8 | let characters = []; 9 | 10 | if (lowerCase) characters.push('abcdefghijklmnopqrstuvwxyz'); 11 | if (upperCase) characters.push('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); 12 | if (numbers) characters.push('0123456789'); 13 | if (symbols) characters.push(allowedSymbols); 14 | 15 | return characters.join(''); 16 | } 17 | 18 | function randomPassword(characters, { length, lowerCase, upperCase }) { 19 | let password = []; 20 | 21 | while (password.length < length) { 22 | const randomIndex = Math.floor(Math.random() * characters.length); 23 | password.push(characters[randomIndex]); 24 | } 25 | 26 | return password.join(''); 27 | } 28 | 29 | export const generatePasswords = settings => { 30 | const characters = getCharactersFromSettings(settings); 31 | 32 | let passwords = []; 33 | 34 | while (passwords.length < settings.amount) { 35 | passwords.push(randomPassword(characters, settings)); 36 | } 37 | 38 | return passwords; 39 | }; 40 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Settings from './components/Settings'; 3 | import PasswordList from './components/PasswordList'; 4 | import { generatePasswords } from './utility/password-generator'; 5 | import { Grid, Header } from 'semantic-ui-react'; 6 | 7 | class App extends React.Component { 8 | state = { 9 | passwords: [], 10 | isLoading: false 11 | }; 12 | 13 | handleGenerate = settings => { 14 | this.setState({ isLoading: true }, () => { 15 | setTimeout(() => { 16 | this.setState({ 17 | passwords: generatePasswords(settings), 18 | isLoading: false 19 | }); 20 | }, 300); 21 | }); 22 | }; 23 | 24 | render() { 25 | return ( 26 |
29 | 30 | 31 |
32 | Password Generator 33 |
34 | 35 | 39 |
40 |
41 |
42 | ); 43 | } 44 | } 45 | 46 | export default App; 47 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | Password Generator 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/components/Password.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Card, Button, Popup, Progress } from 'semantic-ui-react'; 3 | import { CopyToClipboard } from 'react-copy-to-clipboard'; 4 | import zxcvbn from 'zxcvbn'; 5 | 6 | const strengthColors = ['red', 'orange', 'yellow', 'olive', 'teal']; 7 | 8 | function charColor(char) { 9 | if (char.match(/\d/)) { 10 | return 'teal'; 11 | } else if (char.match(/[^a-zA-Z0-9]/)) { 12 | return 'brown'; 13 | } else { 14 | return 'black'; 15 | } 16 | } 17 | 18 | const Password = ({ password }) => { 19 | const [copied, setCopied] = useState(false); 20 | const passwordStrength = zxcvbn(password).score; 21 | 22 | return ( 23 | 24 | 25 | {password.split('').map((char, index) => ( 26 | 30 | {char} 31 | 32 | ))} 33 | setCopied(true)}> 40 | 143 | 144 | ); 145 | } 146 | } 147 | 148 | export default Settings; 149 | --------------------------------------------------------------------------------