1
0
Fork 0

Add tsx syntax to PwGen.

This commit is contained in:
Kitteh 2021-05-24 13:35:44 +01:00
parent 2c87ceb24c
commit 651b490ea5
4 changed files with 157 additions and 143 deletions

View file

@ -13,7 +13,6 @@ export class Form extends Component<FormProps, unknown> {
<form <form
onSubmit={(e: Event) => { onSubmit={(e: Event) => {
e.preventDefault(); e.preventDefault();
console.log(this.ref.current);
this.props.onSubmit(new FormData(this.ref.current)); this.props.onSubmit(new FormData(this.ref.current));
}} }}
ref={this.ref} ref={this.ref}

View file

@ -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
View 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");
}
}

View file

@ -17,10 +17,14 @@ $global-danger-background: #bf616a;
$button-primary-background: #5e81ac; $button-primary-background: #5e81ac;
$progress-bar-background: #5e81ac; $progress-bar-background: #5e81ac;
$form-radio-background: $global-secondary-background; $form-radio-background: $global-secondary-background;
$form-select-option-color: $global-muted-color; $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 // 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/variables.scss";
@import "uikit/src/scss/mixins.scss"; @import "uikit/src/scss/mixins.scss";