refactor: make some states grouped

This commit is contained in:
rusconn
2023-06-01 15:28:32 +09:00
parent d935d0579f
commit c8f69a7eef
4 changed files with 101 additions and 80 deletions

View File

@@ -31,50 +31,52 @@ const two = " ";
const four = " ";
export default function Page() {
const [indentation, setIndentation] = useState(two);
const [json, setJson] = useState('{\n "foo": "bar"\n}');
const [yaml, setYaml] = useState("foo: bar");
const [form, setForm] = useState({
indentation: two,
json: '{\n "foo": "bar"\n}',
yaml: "foo: bar",
});
const setJsonReactively = useCallback(
(text: string) => {
const parsed = safeJsonParse(text);
const setJsonReactively = useCallback((text: string) => {
const parsed = safeJsonParse(text);
setJson(text);
setYaml(
O.isNone(parsed)
? ""
: YAML.stringify(parsed.value, { indent: indentation.length, simpleKeys: true })
);
},
[indentation.length]
);
setForm(prev => ({
...prev,
json: text,
yaml: O.isNone(parsed)
? ""
: YAML.stringify(parsed.value, { indent: prev.indentation.length, simpleKeys: true }),
}));
}, []);
const setYamlReactively = useCallback(
(text: string) => {
const parsed = safeYamlParse(text, (_, v) => v, { merge: true });
const setYamlReactively = useCallback((text: string) => {
const parsed = safeYamlParse(text, (_, v) => v, { merge: true });
setYaml(text);
setJson(O.isNone(parsed) ? "" : JSON.stringify(parsed.value, null, indentation));
},
[indentation]
);
setForm(prev => ({
...prev,
yaml: text,
json: O.isNone(parsed) ? "" : JSON.stringify(parsed.value, null, prev.indentation),
}));
}, []);
const clearBoth = useCallback(() => {
setJson("");
setYaml("");
setForm(prev => ({ ...prev, json: "", yaml: "" }));
}, []);
const onIndentationChange: SelectProps["onValueChange"] = value => {
setIndentation(value);
const parsed = safeJsonParse(form.json);
const parsed = safeJsonParse(json);
const jsonYaml = O.isNone(parsed)
? { json: "", yaml: "" }
: {
json: JSON.stringify(parsed.value, null, value),
yaml: YAML.stringify(parsed.value, { indent: value.length, simpleKeys: true }),
};
if (O.isNone(parsed)) {
clearBoth();
} else {
setJson(JSON.stringify(parsed.value, null, value));
setYaml(YAML.stringify(parsed.value, { indent: value.length, simpleKeys: true }));
}
setForm({
indentation: value,
...jsonYaml,
});
};
const onJsonChange: EditorProps["onChange"] = value => setJsonReactively(value ?? "");
@@ -87,12 +89,12 @@ export default function Page() {
icon={indentationIcon}
title="Indentation"
control={
<Select value={indentation} onValueChange={onIndentationChange}>
<Select value={form.indentation} onValueChange={onIndentationChange}>
<SelectTrigger
className="w-28"
aria-label="toggle open/close state of indentation selection"
>
<SelectValue placeholder={indentation} />
<SelectValue placeholder={form.indentation} />
</SelectTrigger>
<SelectContent>
<SelectItem value={two}>2 spaces</SelectItem>
@@ -137,8 +139,8 @@ export default function Page() {
[setYamlReactively]
);
const jsonCopyButton = <CopyButton text={json} />;
const yamlCopyButton = <CopyButton text={yaml} />;
const jsonCopyButton = <CopyButton text={form.json} />;
const yamlCopyButton = <CopyButton text={form.yaml} />;
const clearButton = useMemo(
() => <ClearButton onClick={clearBoth} iconOnly aria-label="clear json and yaml" />,
@@ -163,10 +165,10 @@ export default function Page() {
</PageSection>
<div className="flex flex-1 flex-col gap-x-4 gap-y-5 lg:flex-row">
<PageSection className="mt-0 min-h-[200px] flex-1" title="Json" control={jsonControl}>
<Editor language="json" value={json} onChange={onJsonChange} />
<Editor language="json" value={form.json} onChange={onJsonChange} />
</PageSection>
<PageSection className="mt-0 min-h-[200px] flex-1" title="Yaml" control={yamlControl}>
<Editor language="yaml" value={yaml} onChange={onYamlChange} />
<Editor language="yaml" value={form.yaml} onChange={onYamlChange} />
</PageSection>
</div>
</PageRootSection>

View File

@@ -14,29 +14,32 @@ import { PageRootSection } from "@/components/page-root-section";
import { PageSection } from "@/components/page-section";
export default function Page() {
const [decoded, setDecoded] = useState("😀😂🤣");
const [encoded, setEncoded] = useState("8J+YgPCfmILwn6Sj");
const [form, setForm] = useState({
decoded: "😀😂🤣",
encoded: "8J+YgPCfmILwn6Sj",
});
const setDecodedReactively = useCallback((text: string) => {
setDecoded(text);
setEncoded(encode(text));
setForm({
decoded: text,
encoded: encode(text),
});
}, []);
const setEncodedReactively = useCallback((text: string) => {
setEncoded(text);
const newDecoded = decode(text);
if (isValid(text) && !newDecoded.includes("<22>")) {
setDecoded(newDecoded);
} else {
setDecoded("");
}
setForm({
encoded: text,
decoded: isValid(text) && !newDecoded.includes("<22>") ? newDecoded : "",
});
}, []);
const clearBoth = useCallback(() => {
setDecoded("");
setEncoded("");
setForm({
decoded: "",
encoded: "",
});
}, []);
const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) =>
@@ -69,8 +72,8 @@ export default function Page() {
[setEncodedReactively]
);
const decodedCopyButton = useMemo(() => <CopyButton text={decoded} />, [decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={encoded} />, [encoded]);
const decodedCopyButton = useMemo(() => <CopyButton text={form.decoded} />, [form.decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={form.encoded} />, [form.encoded]);
const clearButton = useMemo(
() => <ClearButton onClick={clearBoth} iconOnly aria-label="clear decoded and encoded" />,
@@ -88,10 +91,10 @@ export default function Page() {
return (
<PageRootSection title={toolGroups.encodersDecoders.tools.base64.longTitle}>
<PageSection title="Decoded" control={decodedControl}>
<Textarea value={decoded} onChange={onDecodedChange} rows={10} />
<Textarea value={form.decoded} onChange={onDecodedChange} rows={10} />
</PageSection>
<PageSection title="Encoded" control={encodedControl}>
<Textarea value={encoded} onChange={onEncodedChange} rows={10} />
<Textarea value={form.encoded} onChange={onEncodedChange} rows={10} />
</PageSection>
</PageRootSection>
);

View File

@@ -14,22 +14,30 @@ import { PageRootSection } from "@/components/page-root-section";
import { PageSection } from "@/components/page-section";
export default function Page() {
const [decoded, setDecoded] = useState('> It\'s "HTML escaping".');
const [encoded, setEncoded] = useState("&gt; It&apos;s &quot;HTML escaping&quot;.");
const [form, setForm] = useState({
decoded: '> It\'s "HTML escaping".',
encoded: "&gt; It&apos;s &quot;HTML escaping&quot;.",
});
const setDecodedReactively = useCallback((text: string) => {
setDecoded(text);
setEncoded(encode(text));
setForm({
decoded: text,
encoded: encode(text),
});
}, []);
const setEncodedReactively = useCallback((text: string) => {
setEncoded(text);
setDecoded(decode(text));
setForm({
encoded: text,
decoded: decode(text),
});
}, []);
const clearBoth = useCallback(() => {
setDecoded("");
setEncoded("");
setForm({
decoded: "",
encoded: "",
});
}, []);
const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) =>
@@ -62,8 +70,8 @@ export default function Page() {
[setEncodedReactively]
);
const decodedCopyButton = useMemo(() => <CopyButton text={decoded} />, [decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={encoded} />, [encoded]);
const decodedCopyButton = useMemo(() => <CopyButton text={form.decoded} />, [form.decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={form.encoded} />, [form.encoded]);
const clearButton = useMemo(
() => <ClearButton onClick={clearBoth} iconOnly aria-label="clear decoded and encoded" />,
@@ -81,10 +89,10 @@ export default function Page() {
return (
<PageRootSection title={toolGroups.encodersDecoders.tools.html.longTitle}>
<PageSection title="Decoded" control={decodedControl}>
<Textarea value={decoded} onChange={onDecodedChange} rows={10} />
<Textarea value={form.decoded} onChange={onDecodedChange} rows={10} />
</PageSection>
<PageSection title="Encoded" control={encodedControl}>
<Textarea value={encoded} onChange={onEncodedChange} rows={10} />
<Textarea value={form.encoded} onChange={onEncodedChange} rows={10} />
</PageSection>
</PageRootSection>
);

View File

@@ -16,22 +16,30 @@ import { PageRootSection } from "@/components/page-root-section";
import { PageSection } from "@/components/page-section";
export default function Page() {
const [decoded, setDecoded] = useState('> It\'s "URL encoding"?');
const [encoded, setEncoded] = useState("%3E%20It's%20%22URL%20encoding%22%3F");
const [form, setForm] = useState({
decoded: '> It\'s "URL encoding"?',
encoded: "%3E%20It's%20%22URL%20encoding%22%3F",
});
const setDecodedReactively = useCallback((text: string) => {
setDecoded(text);
setEncoded(O.getOrElse(constant(""))(safeEncodeURIComponent(text)));
setForm({
decoded: text,
encoded: O.getOrElse(constant(""))(safeEncodeURIComponent(text)),
});
}, []);
const setEncodedReactively = useCallback((text: string) => {
setEncoded(text);
setDecoded(O.getOrElse(constant(""))(safeDecodeURIComponent(text)));
setForm({
encoded: text,
decoded: O.getOrElse(constant(""))(safeDecodeURIComponent(text)),
});
}, []);
const clearBoth = useCallback(() => {
setDecoded("");
setEncoded("");
setForm({
decoded: "",
encoded: "",
});
}, []);
const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) =>
@@ -64,8 +72,8 @@ export default function Page() {
[setEncodedReactively]
);
const decodedCopyButton = useMemo(() => <CopyButton text={decoded} />, [decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={encoded} />, [encoded]);
const decodedCopyButton = useMemo(() => <CopyButton text={form.decoded} />, [form.decoded]);
const encodedCopyButton = useMemo(() => <CopyButton text={form.encoded} />, [form.encoded]);
const clearButton = useMemo(
() => <ClearButton onClick={clearBoth} iconOnly aria-label="clear decoded and encoded" />,
@@ -83,10 +91,10 @@ export default function Page() {
return (
<PageRootSection title={toolGroups.encodersDecoders.tools.url.longTitle}>
<PageSection title="Decoded" control={decodedControl}>
<Textarea value={decoded} onChange={onDecodedChange} rows={10} />
<Textarea value={form.decoded} onChange={onDecodedChange} rows={10} />
</PageSection>
<PageSection title="Encoded" control={encodedControl}>
<Textarea value={encoded} onChange={onEncodedChange} rows={10} />
<Textarea value={form.encoded} onChange={onEncodedChange} rows={10} />
</PageSection>
</PageRootSection>
);