From 651b490ea5f62a41734434478be276f3f04010a0 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Mon, 24 May 2021 13:35:44 +0100 Subject: [PATCH] Add tsx syntax to PwGen. --- src/elements/ReactForm.tsx | 1 - src/pages/PwGen.ts | 142 ---------------------------------- src/pages/PwGen.tsx | 153 +++++++++++++++++++++++++++++++++++++ src/scss/uikit.scss | 4 + 4 files changed, 157 insertions(+), 143 deletions(-) delete mode 100644 src/pages/PwGen.ts create mode 100644 src/pages/PwGen.tsx diff --git a/src/elements/ReactForm.tsx b/src/elements/ReactForm.tsx index d3b76b0..2248416 100644 --- a/src/elements/ReactForm.tsx +++ b/src/elements/ReactForm.tsx @@ -13,7 +13,6 @@ export class Form extends Component {
{ e.preventDefault(); - console.log(this.ref.current); this.props.onSubmit(new FormData(this.ref.current)); }} ref={this.ref} diff --git a/src/pages/PwGen.ts b/src/pages/PwGen.ts deleted file mode 100644 index e2f3858..0000000 --- a/src/pages/PwGen.ts +++ /dev/null @@ -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 { - 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 { - this.passwordBox = undefined; - this.passwordLengthTitle = undefined; - this.passwordLengthRange = undefined; - this.passwordAlphabet = undefined; - this.passwordForm = undefined; - } - - get name(): string { - return i18next.t("password_generator_title"); - } -} diff --git a/src/pages/PwGen.tsx b/src/pages/PwGen.tsx new file mode 100644 index 0000000..3f8cf74 --- /dev/null +++ b/src/pages/PwGen.tsx @@ -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 { + constructor() { + super(); + this.state = { + length: passwordOptionsDefault.length, + alphabet: passwordOptionsDefault.alphabet, + }; + } + passwordLengthSlider = createRef(); + alphabetSelector = createRef(); + + 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 ( + this.onSubmit()}> + +

{this.getPasswordLengthText(this.state.length)}

+
+ + { + this.updateLength(); + }} + /> + + + + + + + + + + + ); + } +} + +export class PwGenPage extends Page { + constructor() { + super(); + } + + async render(): Promise { + render(, this.router.pageContentElement); + } + + get name(): string { + return i18next.t("password_generator_title"); + } +} diff --git a/src/scss/uikit.scss b/src/scss/uikit.scss index 4a5cdd5..4d33885 100644 --- a/src/scss/uikit.scss +++ b/src/scss/uikit.scss @@ -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";