From 0a713c39cc3af8c93266793cc549fef432ed3bc1 Mon Sep 17 00:00:00 2001 From: Drex <90635055+Drex72@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:35:29 +0100 Subject: [PATCH] Password generator (#677) * completed the generator * completed password generator * resolved issues --- .../src/examples/password-generator.tsx | 238 ++++++++++++++++++ packages/kitchen-sink/src/style.css | 104 ++++++++ pnpm-lock.yaml | 2 +- 3 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 packages/kitchen-sink/src/examples/password-generator.tsx diff --git a/packages/kitchen-sink/src/examples/password-generator.tsx b/packages/kitchen-sink/src/examples/password-generator.tsx new file mode 100644 index 0000000000..259822ff22 --- /dev/null +++ b/packages/kitchen-sink/src/examples/password-generator.tsx @@ -0,0 +1,238 @@ +import { useState, useEffect, useRef } from 'react'; +import { block } from 'million/react'; +import { BsClipboardCheck } from 'react-icons/bs'; +import { FiRefreshCcw } from 'react-icons/fi'; + +const PasswordGenerator = block(() => { + const { + copyPasswordToClipboard, + password, + passwordInputRef, + setPassword, + generatePassword, + } = useGeneratePassword(); + return ( +
+

Password Generator

+ +

+ Create strong and secure passwords to keep your account safe online. +

+ +
+ {/* Password Generator Output */} +
+ + + + + +
+ + +
+ + {/* Options */} + +
+
+ + { + setPassword({ + ...password, + length: parseInt(e.target.value), + }); + }} + /> +
+ +
+
+ + +
+ +
+ + setPassword({ ...password, numbers: !password.numbers }) + } + className="password_generator_customizable_options__checkbox" + /> + +
+ +
+ + setPassword({ ...password, symbols: !password.symbols }) + } + className="password_generator_customizable_options__checkbox" + /> + +
+
+
+
+ ); +}); + +export default PasswordGenerator; + +const Tooltip = ({ text, children, show }: IToolTipProps) => { + return ( +
+
{children}
+

+ {text} +

+
+ ); +}; + +type IPasswordType = 'password' | 'pin'; + +interface IPasswordState { + value: string; + password_type: IPasswordType; + length: number; + isCopied: boolean; + numbers?: boolean; + symbols?: boolean; +} + +interface IToolTipProps { + children: JSX.Element; + text: string; + show: boolean; +} + +interface IGeneratePassword { + includeNumbers: boolean; + includeSymbols: boolean; + passwordLength: number; + password_type: IPasswordType; +} + +const useGeneratePassword = () => { + const passwordInputRef = useRef(null); + + const [password, setPassword] = useState({ + value: '', + password_type: 'password', + length: 3, + isCopied: false, + numbers: false, + symbols: false, + }); + + const copyPasswordToClipboard = () => { + if (passwordInputRef.current) { + passwordInputRef.current.select(); + document.execCommand('copy'); + + // Deselect the text + window.getSelection()?.removeAllRanges(); + + setPassword({ ...password, isCopied: true }); + + setTimeout(() => { + setPassword({ ...password, isCopied: false }); + }, 3000); + } + }; + + const generatePassword = () => { + const lowercaseChars = 'abcdefghijklmnopqrstuvwxyz'; + const uppercaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const numberChars = '0123456789'; + const symbolChars = '!@#$%^&*()_+{}[]|:;"<>,.?/~'; + + let charset = ''; + + if (password.password_type === 'password') { + charset += lowercaseChars + uppercaseChars; + + if (password.numbers) { + charset += numberChars; + } + + if (password.symbols) { + charset += symbolChars; + } + } + + if (password.password_type === 'pin') { + charset += numberChars; + } + + let generatedValue = ''; + + for (let i = 0; i < password.length; i++) { + const randomIndex = Math.floor(Math.random() * charset.length); + generatedValue += charset[randomIndex]; + } + + setPassword({ ...password, value: generatedValue }); + }; + + useEffect(() => { + generatePassword(); + }, [ + password.length, + password.numbers, + password.password_type, + password.symbols, + ]); + + return { + passwordInputRef, + password, + setPassword, + copyPasswordToClipboard, + generatePassword, + }; +}; diff --git a/packages/kitchen-sink/src/style.css b/packages/kitchen-sink/src/style.css index 21eed2e273..3a8f735648 100644 --- a/packages/kitchen-sink/src/style.css +++ b/packages/kitchen-sink/src/style.css @@ -222,3 +222,107 @@ input[type='range'] { } } } + +/********** PASSWORD GENERATOR **********/ +.password_generator { + width: 80%; + margin: 2em auto; +} + +.password_generator_top_section { + display: flex; + gap: 1.5em; +} + +.password_generator_output_container { + display: flex; + border-radius: 10px; + background: #353535; + border: 1px solid #dddddd; + align-items: center; + padding-right: 20px; + flex: 5; +} + +.password_generator_output_container input { + padding: 14px; + width: 100%; + outline: none; + line-height: 30px; + caret-color: #1c1c1c; + background-color: transparent; + font-size: 16px; + border-radius: 10px; + transition: all 0.3s ease-in; + color: #fff; + font-weight: 600; + font-size: 1.5rem; +} + +.password_generator_output_container .right-icon { + font-size: 25px; + cursor: pointer; + border: none; +} + +.password_generator_refresh_password { + flex: 0.5; +} + +.password_generator_tooltip-container { + position: relative; +} + +.password_generator_tooltip-text { + background-color: #333; + color: #fff; + text-align: center; + border-radius: 4px; + padding: 6px; + position: absolute; + z-index: 1; + bottom: 50%; + left: 90%; + font-size: 12px; + opacity: 0; + transition: all 200ms ease-in-out; +} + +.password_generator_tooltip-text.visible { + opacity: 1; +} + +.password_generator_customizable_options { +} + +.password_generator_customizable_options__length { + display: flex; + align-items: center; +} + +.password_generator_customizable_options__checkbox { + position: relative; + /* border: 1px solid themed("primary"); */ + border-radius: 4px; + background: none; + cursor: pointer; + line-height: 0; + margin: 0 0.6em 0 0; + outline: 0; + padding: 0 !important; + vertical-align: text-top; + height: 18px; + width: 18px; + opacity: 0.5; + transition: all 200ms ease-in-out; + + &:hover { + opacity: 1; + } + + &:checked { + /* background-color: themed("primary"); */ + opacity: 1; + border: none; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3ba176c47..2d710c2ac2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11235,4 +11235,4 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false + dev: false \ No newline at end of file