mirror of
https://github.com/ershisan99/DevToysWeb.git
synced 2025-12-16 12:32:48 +00:00
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback, useMemo, useState } from "react";
|
|
|
|
import { toolGroups } from "@/config/tools";
|
|
import { noOp } from "@/lib/base";
|
|
import {
|
|
countBytes,
|
|
countCharacters,
|
|
countLines,
|
|
countWords,
|
|
modeTitle,
|
|
TextTransformMode,
|
|
textTransformModes,
|
|
transformText,
|
|
} from "@/lib/text";
|
|
import { Textarea, TextareaProps } from "@/components/ui/textarea";
|
|
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
|
import * as Button from "@/components/buttons";
|
|
import { ControlMenu } from "@/components/control-menu";
|
|
import { PageRootSection } from "@/components/page-root-section";
|
|
import { PageSection } from "@/components/page-section";
|
|
|
|
export default function Page() {
|
|
const [input, setInput] = useState("ConvertMe");
|
|
const [mode, setMode] = useState(TextTransformMode.original);
|
|
|
|
const output = transformText(input, mode);
|
|
|
|
const stats = useMemo(
|
|
() => ({
|
|
characters: countCharacters(input),
|
|
words: countWords(input),
|
|
lines: countLines(input),
|
|
bytes: countBytes(input),
|
|
}),
|
|
[input]
|
|
);
|
|
|
|
const clearInput = useCallback(() => setInput(""), []);
|
|
|
|
const onInputChange: TextareaProps["onChange"] = e => setInput(e.currentTarget.value);
|
|
const onModeChange = (value: string) => {
|
|
if (value && value in TextTransformMode) {
|
|
setMode(value as TextTransformMode);
|
|
}
|
|
};
|
|
|
|
const inputPasteButton = <Button.Paste onClipboardRead={setInput} />;
|
|
const inputFileButton = <Button.File onFileRead={setInput} iconOnly aria-label="load a file" />;
|
|
const inputClearButton = <Button.Clear onClick={clearInput} iconOnly aria-label="clear input" />;
|
|
|
|
const outputCopyButton = <Button.Copy text={output} />;
|
|
|
|
const inputControl = <ControlMenu list={[inputPasteButton, inputFileButton, inputClearButton]} />;
|
|
const outputControl = <ControlMenu list={[outputCopyButton]} />;
|
|
|
|
return (
|
|
<PageRootSection title={toolGroups.text.tools.inspector_and_case_converter.longTitle}>
|
|
<PageSection title="Convert">
|
|
<ToggleGroup className="flex-wrap" type="single" value={mode} onValueChange={onModeChange}>
|
|
{textTransformModes.map(m => (
|
|
<ToggleGroupItem key={m} value={m}>
|
|
{modeTitle[m]}
|
|
</ToggleGroupItem>
|
|
))}
|
|
</ToggleGroup>
|
|
</PageSection>
|
|
|
|
<div className="flex flex-1 flex-col gap-x-4 gap-y-5 lg:flex-row">
|
|
<PageSection className="min-h-[200px] flex-1" title="Input" control={inputControl}>
|
|
<Textarea value={input} onChange={onInputChange} rows={10} />
|
|
</PageSection>
|
|
<PageSection className="min-h-[200px] flex-1" title="Output" control={outputControl}>
|
|
<Textarea value={output} onChange={noOp} rows={10} readOnly />
|
|
</PageSection>
|
|
</div>
|
|
|
|
<PageSection className="min-h-[200px] flex-1" title="Information">
|
|
<div className="grid max-w-sm grid-cols-2 gap-x-4">
|
|
Characters: <span className="font-mono">{stats.characters}</span>
|
|
Words: <span className="font-mono">{stats.words}</span>
|
|
Lines: <span className="font-mono">{stats.lines}</span>
|
|
Bytes: <span className="font-mono">{stats.bytes}</span>
|
|
</div>
|
|
</PageSection>
|
|
</PageRootSection>
|
|
);
|
|
}
|