Files
DevToysWeb/app/generators/hash/page.tsx
rusconn f1c3bd2971 renewal
recreate project by using https://github.com/shadcn/next-template

App:
- support dark mode
- add toggle theme button
- add clear search button
- add search button
- add current page indicator
- add tool group pages
- add settings tool
- add 1 tab format option to Json format tool
- add paste button to some tools
- add file button to some tools
- add copy button to some tools
- add clear button to some tools
- change favicon
- change search hit rate
- change each page title
- change icons from Material Icons to Lucide
- change sidebar scroll area
- change editor from Ace to Monaco
- change parsable separators of number base converter
- change default value of format option of number base converter
- change default values of some tool forms
- change some styles
- remove disabled tools
- remove real-time search
- fix uri encoding tool

Dev:
- MUI + Emotion -> Radix UI + Tailwind CSS
- Next.js 12 Pages -> Next.js 13 App Router
- React 17 -> React 18
- many other packages upgraded
- use useState instead of recoil
- use Next.js typedRoutes instead of pathpida
- clean npm scripts
- format import statements by Prettier
- no component separations between container and presenter
- effective component memoizations
- add vscode settings
- many refactors
2023-05-28 23:56:43 +09:00

130 lines
4.4 KiB
TypeScript

"use client";
import { useCallback, useMemo, useState } from "react";
import createHash from "create-hash";
import { toolGroups } from "@/config/tools";
import { Input } from "@/components/ui/input";
import { Textarea, TextareaProps } from "@/components/ui/textarea";
import { ClearButton } from "@/components/buttons/clear";
import { CopyButton } from "@/components/buttons/copy";
import { FileButton } from "@/components/buttons/file";
import { PasteButton } from "@/components/buttons/paste";
import { Configuration } from "@/components/configuration";
import { Configurations } from "@/components/configurations";
import { ControlMenu } from "@/components/control-menu";
import { icons } from "@/components/icons";
import { LabeledSwitch } from "@/components/labeled-switch";
import { PageRootSection } from "@/components/page-root-section";
import { PageSection } from "@/components/page-section";
export default function Page() {
const [uppercase, setUppercase] = useState(false);
const [input, setInput] = useState("Hello there !");
const newMd5 = createHash("md5").update(input).digest("hex");
const newSha1 = createHash("sha1").update(input).digest("hex");
const newSha256 = createHash("sha256").update(input).digest("hex");
const newSha512 = createHash("sha512").update(input).digest("hex");
const md5 = uppercase ? newMd5.toUpperCase() : newMd5;
const sha1 = uppercase ? newSha1.toUpperCase() : newSha1;
const sha256 = uppercase ? newSha256.toUpperCase() : newSha256;
const sha512 = uppercase ? newSha512.toUpperCase() : newSha512;
const clearInput = useCallback(() => setInput(""), []);
const onInputChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) =>
setInput(value);
const uppercaseIcon = useMemo(() => <icons.CaseSensitive size={24} />, []);
const uppercaseConfig = useMemo(
() => (
<Configuration
icon={uppercaseIcon}
title="Uppercase"
control={
<LabeledSwitch
id="uppercase-switch"
label={uppercase ? "On" : "Off"}
checked={uppercase}
onCheckedChange={setUppercase}
aria-label="toggle whether to generate in uppercase"
/>
}
/>
),
[uppercase, uppercaseIcon]
);
const inputPasteButton = useMemo(() => <PasteButton onClipboardRead={setInput} />, []);
const inputFileButton = useMemo(
() => <FileButton onFileRead={setInput} iconOnly aria-label="load a file" />,
[]
);
const inputClearButton = useMemo(
() => <ClearButton onClick={clearInput} iconOnly aria-label="clear input" />,
[clearInput]
);
const inputControl = <ControlMenu list={[inputPasteButton, inputFileButton, inputClearButton]} />;
const md5CopyButton = useMemo(
() => <CopyButton text={md5} iconOnly aria-label="copy generated md5" />,
[md5]
);
const sha1CopyButton = useMemo(
() => <CopyButton text={sha1} iconOnly aria-label="copy generated sha1" />,
[sha1]
);
const sha256CopyButton = useMemo(
() => <CopyButton text={sha256} iconOnly aria-label="copy generated sha256" />,
[sha256]
);
const sha512CopyButton = useMemo(
() => <CopyButton text={sha512} iconOnly aria-label="copy generated sha512" />,
[sha512]
);
return (
<PageRootSection title={toolGroups.generators.tools.hash.longTitle}>
<PageSection title="Configuration">
<Configurations list={[uppercaseConfig]} />
</PageSection>
<PageSection className="my-4" title="Input" control={inputControl}>
<Textarea value={input} onChange={onInputChange} rows={5} />
</PageSection>
<PageSection title="MD5">
<div className="flex gap-2">
<Input className="flex-1" value={md5} readOnly />
<ControlMenu list={[md5CopyButton]} />
</div>
</PageSection>
<PageSection title="SHA1">
<div className="flex gap-2">
<Input className="flex-1" value={sha1} readOnly />
<ControlMenu list={[sha1CopyButton]} />
</div>
</PageSection>
<PageSection title="SHA256">
<div className="flex gap-2">
<Input className="flex-1" value={sha256} readOnly />
<ControlMenu list={[sha256CopyButton]} />
</div>
</PageSection>
<PageSection title="SHA512">
<div className="flex gap-2">
<Input className="flex-1" value={sha512} readOnly />
<ControlMenu list={[sha512CopyButton]} />
</div>
</PageSection>
</PageRootSection>
);
}