Initial commit
This commit is contained in:
13 files changed
+899
No files matched your search
+72
@@ -0,0 +1,72 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
body {
|
||||
@apply bg-black text-white text-center select-none p-4 min-h-screen flex items-center justify-center;
|
||||
|
||||
--col0: rgb(8, 8, 8);
|
||||
--col1: rgb(16, 16, 16);
|
||||
--col2: rgb(32, 32, 32);
|
||||
--col3: rgb(48, 48, 48);
|
||||
--col4: rgb(64, 64, 64);
|
||||
--col5: rgb(80, 80, 80);
|
||||
--col6: rgb(96, 96, 96);
|
||||
--col7: rgb(112, 112, 112);
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply mb-2;
|
||||
}
|
||||
|
||||
p {
|
||||
@apply mb-4;
|
||||
}
|
||||
|
||||
.form {
|
||||
@apply flex flex-col items-center gap-2 mb-4;
|
||||
}
|
||||
|
||||
.slider-section {
|
||||
@apply flex flex-col items-center w-full;
|
||||
}
|
||||
|
||||
#password-length {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
button {
|
||||
@apply bg-(--col1) hover:bg-(--col3) border border-(--col3) hover:border-(--col5) rounded-lg cursor-pointer transition-all;
|
||||
}
|
||||
|
||||
.preset-buttons,
|
||||
.char-selection-buttons {
|
||||
@apply flex gap-2 flex-wrap justify-center;
|
||||
}
|
||||
|
||||
.preset-btn,
|
||||
.char-selection-buttons button {
|
||||
@apply px-2 py-1;
|
||||
}
|
||||
|
||||
.char-selection-buttons button.char-selected {
|
||||
@apply bg-(--col3) hover:bg-(--col5) border-(--col5) hover:border-(--col7) -translate-y-0.5;
|
||||
}
|
||||
|
||||
.generate-btn {
|
||||
@apply px-4 py-2;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
@apply flex flex-col items-center justify-center mt-2;
|
||||
}
|
||||
|
||||
.password-display {
|
||||
@apply w-full mb-2 p-2 bg-(--col1) border border-(--col3) rounded-lg wrap-break-word text-sm max-h-48 overflow-y-auto select-text;
|
||||
}
|
||||
|
||||
.result-buttons {
|
||||
@apply flex flex-row gap-2.5 justify-center items-center;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
@apply px-4 py-2;
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
import './App.css'
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
|
||||
function App () {
|
||||
const [password, setPassword] = useState('')
|
||||
const [length, setLength] = useState(8)
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const [useUpper, setUseUpper] = useState<boolean>(true)
|
||||
const [useLower, setUseLower] = useState<boolean>(true)
|
||||
const [useNumbers, setUseNumbers] = useState<boolean>(true)
|
||||
const [useSymbols, setUseSymbols] = useState<boolean>(true)
|
||||
|
||||
const presets = [8, 16, 32, 64, 128]
|
||||
|
||||
const charsUpper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
const charsLower = 'abcdefghijklmnopqrstuvwxyz'
|
||||
const charsNumber = '0123456789'
|
||||
const charsSymbols = '!@#$%^&*'
|
||||
|
||||
const generatePassword = useCallback(() => {
|
||||
const chars =
|
||||
(useUpper ? charsUpper : '') +
|
||||
(useLower ? charsLower : '') +
|
||||
(useNumbers ? charsNumber : '') +
|
||||
(useSymbols ? charsSymbols : '')
|
||||
if (chars == '') return setPassword('')
|
||||
setPassword(
|
||||
Array.from(
|
||||
{ length },
|
||||
() => chars[Math.floor(Math.random() * chars.length)]
|
||||
).join('')
|
||||
)
|
||||
}, [length, useUpper, useLower, useNumbers, useSymbols])
|
||||
|
||||
const copyToClipboard = () => {
|
||||
if (password.trim().length == 0) return
|
||||
navigator.clipboard.writeText(password)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 1000)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => generatePassword(), 0)
|
||||
}, [generatePassword])
|
||||
|
||||
return (
|
||||
<main className='w-full max-w-200 mx-auto'>
|
||||
<p className='text-3xl font-bold'>Password Generator</p>
|
||||
<p>Select a length, or use the slider for a custom value.</p>
|
||||
|
||||
<form
|
||||
className='form'
|
||||
onSubmit={e => {
|
||||
e.preventDefault()
|
||||
generatePassword()
|
||||
}}
|
||||
>
|
||||
<div className='slider-section'>
|
||||
<label htmlFor='password-length'>Password Length: {length}</label>
|
||||
<input
|
||||
id='password-length'
|
||||
type='range'
|
||||
min='1'
|
||||
max='500'
|
||||
value={length}
|
||||
onChange={e => setLength(Number(e.target.value))}
|
||||
step='1'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='preset-buttons'>
|
||||
{presets.map(preset => (
|
||||
<button
|
||||
key={preset}
|
||||
type='button'
|
||||
className='preset-btn'
|
||||
onClick={() => setLength(preset)}
|
||||
>
|
||||
{preset}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</form>
|
||||
<p>Characters to use</p>
|
||||
<div className='char-selection-buttons'>
|
||||
<button
|
||||
type='button'
|
||||
className={useUpper ? 'char-selected' : ''}
|
||||
onClick={() => setUseUpper(!useUpper)}
|
||||
>
|
||||
Use uppercase
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
className={useLower ? 'char-selected' : ''}
|
||||
onClick={() => setUseLower(!useLower)}
|
||||
>
|
||||
Use lowercases
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
className={useNumbers ? 'char-selected' : ''}
|
||||
onClick={() => setUseNumbers(!useNumbers)}
|
||||
>
|
||||
Use numbers
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
className={useSymbols ? 'char-selected' : ''}
|
||||
onClick={() => setUseSymbols(!useSymbols)}
|
||||
>
|
||||
Use symbols
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className='result-section'>
|
||||
<p className='password-display'>
|
||||
{password.trim().length == 0 ? '(none)' : password}
|
||||
</p>
|
||||
<div className='result-buttons'>
|
||||
<button
|
||||
className='copy-btn'
|
||||
onClick={copyToClipboard}
|
||||
disabled={copied}
|
||||
>
|
||||
{copied ? 'Copied' : 'Copy'}
|
||||
</button>
|
||||
<button className='copy-btn' onClick={generatePassword}>
|
||||
Regenerate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
declare module '@fontsource/lexend'
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
)
|
||||
Reference in new issue
Block a user