Initial commit
This commit is contained in:
commit
8d675c9799
96 files changed
+7244
No files matched your search
+139
@@ -0,0 +1,139 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Lexend', sans-serif;
|
||||
background-color: #1e1e1e;
|
||||
color: #e0e0e0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: #2a2a2a;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 10px;
|
||||
color: #b3b3ff;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 20px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.slider-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#password-length {
|
||||
width: 80vw;
|
||||
background: #333;
|
||||
border: 2px solid #444;
|
||||
border-radius: 5px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.preset-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preset-btn {
|
||||
padding: 10px 15px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
background-color: #6a4cfc;
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.preset-btn:hover {
|
||||
background-color: #7e61ff;
|
||||
}
|
||||
|
||||
.generate-btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 1.2rem;
|
||||
background-color: #6a4cfc;
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.generate-btn:hover {
|
||||
background-color: #7e61ff;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.password-display {
|
||||
font-size: 1.2rem;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 10px;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
width: 80vw;
|
||||
margin-bottom: 20px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.result-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 1rem;
|
||||
background-color: #6a4cfc;
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.copy-btn:hover {
|
||||
background-color: #7e61ff;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import '@fontsource/lexend';
|
||||
import "./App.css";
|
||||
|
||||
function App() {
|
||||
const [password, setPassword] = useState("");
|
||||
const [length, setLength] = useState(8);
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const presets = [6, 8, 12, 16, 24, 32, 50, 100, 200, 250];
|
||||
|
||||
useEffect(() => {
|
||||
generatePassword();
|
||||
}, [length]);
|
||||
|
||||
async function generatePassword() {
|
||||
setPassword(await invoke("generate_password", { length }));
|
||||
}
|
||||
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard.writeText(password);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="container">
|
||||
<h1>Password Generator</h1>
|
||||
<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="6"
|
||||
max="250"
|
||||
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>
|
||||
|
||||
{password && (
|
||||
<div className="result-section">
|
||||
<p className="password-display">{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;
|
||||
@@ -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>,
|
||||
);
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
Reference in new issue
Block a user