Add tsx syntax to PwGen.
This commit is contained in:
parent
2c87ceb24c
commit
651b490ea5
|
@ -13,7 +13,6 @@ export class Form extends Component<FormProps, unknown> {
|
|||
<form
|
||||
onSubmit={(e: Event) => {
|
||||
e.preventDefault();
|
||||
console.log(this.ref.current);
|
||||
this.props.onSubmit(new FormData(this.ref.current));
|
||||
}}
|
||||
ref={this.ref}
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox";
|
||||
import { Form } from "../elements/Form";
|
||||
import { Margin } from "../elements/Margin";
|
||||
import { Option } from "../elements/Option";
|
||||
import { Page } from "../types/Page";
|
||||
import { makeElement } from "z-makeelement";
|
||||
import i18next from "i18next";
|
||||
|
||||
const passwordLengthMin = 1;
|
||||
const passwordLengthMax = 64;
|
||||
const passwordLengthDefault = 24;
|
||||
|
||||
function random() {
|
||||
if (
|
||||
typeof window.crypto?.getRandomValues === "function" &&
|
||||
typeof window.Uint32Array === "function"
|
||||
) {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295;
|
||||
}
|
||||
|
||||
return Math.random();
|
||||
}
|
||||
|
||||
const lowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
const upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const numbers = "1234567890";
|
||||
const special = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
|
||||
|
||||
const alphabets = {
|
||||
SECURE: lowerCase + upperCase + numbers + special,
|
||||
SMOL: lowerCase + numbers,
|
||||
HEX: "123456789ABCDEF",
|
||||
};
|
||||
|
||||
const passwordOptionsDefault = {
|
||||
length: passwordLengthDefault,
|
||||
alphabet: alphabets.SECURE,
|
||||
};
|
||||
|
||||
function genPassword(options = passwordOptionsDefault) {
|
||||
let pw = "";
|
||||
options = { ...passwordOptionsDefault, ...options };
|
||||
const pwArray = options.alphabet.split("");
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
pw = pw.concat(pwArray[Math.floor(random() * pwArray.length)]);
|
||||
}
|
||||
return pw;
|
||||
}
|
||||
|
||||
export class PwGenPage extends Page {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
passwordBox: CopyableInputBoxType;
|
||||
passwordLengthTitle: HTMLTitleElement;
|
||||
passwordLengthRange: HTMLInputElement;
|
||||
passwordAlphabet: HTMLSelectElement;
|
||||
passwordForm: HTMLFormElement;
|
||||
|
||||
async render(): Promise<void> {
|
||||
await this.router.setPageContent("");
|
||||
this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault));
|
||||
|
||||
this.passwordLengthTitle = makeElement({
|
||||
tag: "h4",
|
||||
text: this.getPasswordLengthText(),
|
||||
}) as HTMLTitleElement;
|
||||
|
||||
this.passwordLengthRange = makeElement({
|
||||
tag: "input",
|
||||
name: "length",
|
||||
class: ["uk-range", "uk-width-1-2"],
|
||||
attributes: {
|
||||
type: "range",
|
||||
value: passwordLengthDefault.toString(),
|
||||
max: passwordLengthMax.toString(),
|
||||
min: passwordLengthMin.toString(),
|
||||
},
|
||||
}) as HTMLInputElement;
|
||||
|
||||
this.passwordLengthRange.addEventListener("input", this.updatePassword.bind(this));
|
||||
|
||||
this.passwordAlphabet = makeElement({
|
||||
tag: "select",
|
||||
class: ["uk-select", "uk-width-1-2"],
|
||||
children: [
|
||||
Option("a-z a-Z 0-9 specials", alphabets.SECURE),
|
||||
Option("a-z 0-9", alphabets.SMOL),
|
||||
Option("A-F 1-9", alphabets.HEX),
|
||||
],
|
||||
}) as HTMLSelectElement;
|
||||
|
||||
this.passwordForm = Form(
|
||||
[
|
||||
this.passwordLengthTitle,
|
||||
Margin(this.passwordLengthRange),
|
||||
Margin(this.passwordAlphabet),
|
||||
Margin(this.passwordBox),
|
||||
Margin(
|
||||
makeElement({
|
||||
tag: "button",
|
||||
text: i18next.t("gen_password_btn"),
|
||||
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
|
||||
attributes: { type: "submit" },
|
||||
}),
|
||||
),
|
||||
],
|
||||
(_) => this.updatePassword(),
|
||||
);
|
||||
await this.router.setPageContent(this.passwordForm);
|
||||
}
|
||||
|
||||
getPasswordLengthText(): string {
|
||||
return i18next.t("password_length_title", {
|
||||
min: this?.passwordLengthRange?.value || 24,
|
||||
max: passwordLengthMax,
|
||||
});
|
||||
}
|
||||
|
||||
updatePassword(): void {
|
||||
this.passwordLengthTitle.innerText = this.getPasswordLengthText();
|
||||
this.passwordBox.setText(
|
||||
genPassword({
|
||||
length: this.passwordLengthRange.value as unknown as number,
|
||||
alphabet: this.passwordAlphabet.value,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async cleanup(): Promise<void> {
|
||||
this.passwordBox = undefined;
|
||||
this.passwordLengthTitle = undefined;
|
||||
this.passwordLengthRange = undefined;
|
||||
this.passwordAlphabet = undefined;
|
||||
this.passwordForm = undefined;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("password_generator_title");
|
||||
}
|
||||
}
|
153
src/pages/PwGen.tsx
Normal file
153
src/pages/PwGen.tsx
Normal file
|
@ -0,0 +1,153 @@
|
|||
import { Component, JSX, createRef, render } from "preact";
|
||||
import { CopyableInputBox } from "../elements/ReactCopyableInputBox";
|
||||
import { Form } from "../elements/ReactForm";
|
||||
import { Margin } from "../elements/ReactMargin";
|
||||
import { Page } from "../types/Page";
|
||||
import i18next from "i18next";
|
||||
|
||||
const passwordLengthMin = 1;
|
||||
const passwordLengthMax = 64;
|
||||
const passwordLengthDefault = 24;
|
||||
|
||||
function random() {
|
||||
if (
|
||||
typeof window.crypto?.getRandomValues === "function" &&
|
||||
typeof window.Uint32Array === "function"
|
||||
) {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295;
|
||||
}
|
||||
|
||||
return Math.random();
|
||||
}
|
||||
|
||||
const lowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
const upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const numbers = "1234567890";
|
||||
const special = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
|
||||
|
||||
const alphabets = {
|
||||
SECURE: lowerCase + upperCase + numbers + special,
|
||||
SMOL: lowerCase + numbers,
|
||||
HEX: "123456789ABCDEF",
|
||||
};
|
||||
|
||||
const passwordOptionsDefault = {
|
||||
length: passwordLengthDefault,
|
||||
alphabet: alphabets.SECURE,
|
||||
};
|
||||
|
||||
function genPassword(options = passwordOptionsDefault) {
|
||||
let pw = "";
|
||||
options = { ...passwordOptionsDefault, ...options };
|
||||
const pwArray = options.alphabet.split("");
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
pw = pw.concat(pwArray[Math.floor(random() * pwArray.length)]);
|
||||
}
|
||||
return pw;
|
||||
}
|
||||
|
||||
type PasswordGeneratorState = {
|
||||
length: number;
|
||||
alphabet: string;
|
||||
};
|
||||
|
||||
export class PasswordGenerator extends Component<unknown, PasswordGeneratorState> {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
length: passwordOptionsDefault.length,
|
||||
alphabet: passwordOptionsDefault.alphabet,
|
||||
};
|
||||
}
|
||||
passwordLengthSlider = createRef<HTMLInputElement>();
|
||||
alphabetSelector = createRef<HTMLSelectElement>();
|
||||
|
||||
getPasswordLengthText(length: number): string {
|
||||
return i18next.t("password_length_title", {
|
||||
min: length,
|
||||
max: passwordLengthMax,
|
||||
});
|
||||
}
|
||||
|
||||
updateAlphabet(): void {
|
||||
this.setState({
|
||||
alphabet: this.alphabetSelector.current.value,
|
||||
});
|
||||
}
|
||||
|
||||
updateLength(): void {
|
||||
this.setState({
|
||||
length: parseInt(this.passwordLengthSlider.current.value, 10),
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
this.updateLength();
|
||||
this.updateAlphabet();
|
||||
}
|
||||
|
||||
// createRef
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Form onSubmit={() => this.onSubmit()}>
|
||||
<Margin>
|
||||
<h4>{this.getPasswordLengthText(this.state.length)}</h4>
|
||||
</Margin>
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-range uk-width-1-2"
|
||||
name="length"
|
||||
type="range"
|
||||
value={this.state.length}
|
||||
max={passwordLengthMax.toString()}
|
||||
min={passwordLengthMin.toString()}
|
||||
ref={this.passwordLengthSlider}
|
||||
onInput={() => {
|
||||
this.updateLength();
|
||||
}}
|
||||
/>
|
||||
</Margin>
|
||||
<Margin>
|
||||
<select
|
||||
class="uk-select uk-width-1-2"
|
||||
ref={this.alphabetSelector}
|
||||
onInput={() => {
|
||||
this.updateAlphabet();
|
||||
}}
|
||||
>
|
||||
<option value={alphabets.SECURE}>a-z a-Z 0-9 specials</option>
|
||||
<option value={alphabets.SMOL}>a-z 0-9</option>
|
||||
<option value={alphabets.HEX}>A-F 1-9</option>
|
||||
</select>
|
||||
</Margin>
|
||||
|
||||
<CopyableInputBox
|
||||
text={genPassword({
|
||||
length: this.state.length,
|
||||
alphabet: this.state.alphabet,
|
||||
})}
|
||||
copyable
|
||||
/>
|
||||
<Margin>
|
||||
<button class="uk-button uk-button-primary uk-margin-bottom" type="submit">
|
||||
{i18next.t("gen_password_btn")}
|
||||
</button>
|
||||
</Margin>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class PwGenPage extends Page {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async render(): Promise<void> {
|
||||
render(<PasswordGenerator />, this.router.pageContentElement);
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("password_generator_title");
|
||||
}
|
||||
}
|
|
@ -17,10 +17,14 @@ $global-danger-background: #bf616a;
|
|||
|
||||
$button-primary-background: #5e81ac;
|
||||
$progress-bar-background: #5e81ac;
|
||||
|
||||
$form-radio-background: $global-secondary-background;
|
||||
|
||||
$form-select-option-color: $global-muted-color;
|
||||
|
||||
$form-range-track-background: $global-link-color;
|
||||
$form-range-track-focus-background: $global-link-hover-color;
|
||||
|
||||
// Keep these in same order as https://github.com/uikit/uikit/blob/develop/src/scss/components/_import.scss
|
||||
@import "uikit/src/scss/variables.scss";
|
||||
@import "uikit/src/scss/mixins.scss";
|
||||
|
|
Loading…
Reference in a new issue