refactor: memoize configuration on export

This commit is contained in:
rusconn
2023-06-24 14:35:28 +09:00
parent 822a8db8f9
commit f8bceb7a4c
6 changed files with 129 additions and 147 deletions

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useState } from "react";
import { toolGroups } from "@/config/tools"; import { toolGroups } from "@/config/tools";
import * as baselib from "@/lib/base"; import * as baselib from "@/lib/base";
@@ -58,25 +58,21 @@ export default function Page() {
const onOctChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetOct(value); const onOctChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetOct(value);
const onBinChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetBin(value); const onBinChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetBin(value);
const formatNumberConfig = useMemo( const formatNumberConfig = (
() => ( <Configuration
<Configuration icon={<icons.CaseSensitive size={24} />}
icon={<icons.CaseSensitive size={24} />} title="Format number"
title="Format number" control={
control={ <LabeledSwitch
<LabeledSwitch id="format-number-switch"
id="format-number-switch" label={format ? "On" : "Off"}
label={format ? "On" : "Off"} checked={format}
checked={format} onCheckedChange={setFormat}
onCheckedChange={setFormat} aria-label="toggle whether to format numbers"
aria-label="toggle whether to format numbers" />
/> }
} />
/>
),
[format]
); );
const decPasteButton = <PasteButton onClipboardRead={trySetDec} />; const decPasteButton = <PasteButton onClipboardRead={trySetDec} />;
const hexPasteButton = <PasteButton onClipboardRead={trySetHex} />; const hexPasteButton = <PasteButton onClipboardRead={trySetHex} />;
const octPasteButton = <PasteButton onClipboardRead={trySetOct} />; const octPasteButton = <PasteButton onClipboardRead={trySetOct} />;

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useState } from "react";
import { toolGroups } from "@/config/tools"; import { toolGroups } from "@/config/tools";
import { safeJsonParse } from "@/lib/json"; import { safeJsonParse } from "@/lib/json";
@@ -41,30 +41,27 @@ export default function Page() {
const onJsonChange: EditorProps["onChange"] = value => setInput(value ?? ""); const onJsonChange: EditorProps["onChange"] = value => setInput(value ?? "");
const indentationConfig = useMemo( const indentationConfig = (
() => ( <Configuration
<Configuration icon={<icons.Space size={24} className="-translate-y-1.5" />}
icon={<icons.Space size={24} className="-translate-y-1.5" />} title="Indentation"
title="Indentation" control={
control={ <Select value={indentation} onValueChange={setIndentation}>
<Select value={indentation} onValueChange={setIndentation}> <SelectTrigger
<SelectTrigger className="w-28"
className="w-28" aria-label="toggle open/close state of indentation selection"
aria-label="toggle open/close state of indentation selection" >
> <SelectValue placeholder={indentation} />
<SelectValue placeholder={indentation} /> </SelectTrigger>
</SelectTrigger> <SelectContent>
<SelectContent> <SelectItem value={indentations.two}>2 spaces</SelectItem>
<SelectItem value={indentations.two}>2 spaces</SelectItem> <SelectItem value={indentations.four}>4 spaces</SelectItem>
<SelectItem value={indentations.four}>4 spaces</SelectItem> <SelectItem value={indentations.tab}>1 tab</SelectItem>
<SelectItem value={indentations.tab}>1 tab</SelectItem> <SelectItem value={indentations.zero}>minified</SelectItem>
<SelectItem value={indentations.zero}>minified</SelectItem> </SelectContent>
</SelectContent> </Select>
</Select> }
} />
/>
),
[indentation]
); );
const inputPasteButton = <PasteButton onClipboardRead={setInput} />; const inputPasteButton = <PasteButton onClipboardRead={setInput} />;

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useState } from "react";
import createHash from "create-hash"; import createHash from "create-hash";
import { toolGroups } from "@/config/tools"; import { toolGroups } from "@/config/tools";
@@ -37,23 +37,20 @@ export default function Page() {
const onInputChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => const onInputChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) =>
setInput(value); setInput(value);
const uppercaseConfig = useMemo( const uppercaseConfig = (
() => ( <Configuration
<Configuration icon={<icons.CaseSensitive size={24} />}
icon={<icons.CaseSensitive size={24} />} title="Uppercase"
title="Uppercase" control={
control={ <LabeledSwitch
<LabeledSwitch id="uppercase-switch"
id="uppercase-switch" label={uppercase ? "On" : "Off"}
label={uppercase ? "On" : "Off"} checked={uppercase}
checked={uppercase} onCheckedChange={setUppercase}
onCheckedChange={setUppercase} aria-label="toggle whether to generate in uppercase"
aria-label="toggle whether to generate in uppercase" />
/> }
} />
/>
),
[uppercase]
); );
const inputPasteButton = <PasteButton onClipboardRead={setInput} />; const inputPasteButton = <PasteButton onClipboardRead={setInput} />;

View File

@@ -48,11 +48,11 @@ export default function Page() {
const clearUuids = useCallback(() => setUuids([]), []); const clearUuids = useCallback(() => setUuids([]), []);
const onUuidVersionChange: SelectProps["onValueChange"] = value => { const onUuidVersionChange: NonNullable<SelectProps["onValueChange"]> = useCallback(value => {
if (uuidVersions.is(value)) { if (uuidVersions.is(value)) {
setUuidVersion(value); setUuidVersion(value);
} }
}; }, []);
const onGeneratesChange: InputProps["onChange"] = ({ currentTarget: { value } }) => { const onGeneratesChange: InputProps["onChange"] = ({ currentTarget: { value } }) => {
const newGenerates = Number(value); const newGenerates = Number(value);
@@ -67,67 +67,58 @@ export default function Page() {
setUuids([...uuids, ...newUuids]); setUuids([...uuids, ...newUuids]);
}; };
const hyphensConfig = useMemo( const hyphensConfig = (
() => ( <Configuration
<Configuration icon={<icons.Minus size={24} />}
icon={<icons.Minus size={24} />} title="Hyphens"
title="Hyphens" control={
control={ <LabeledSwitch
<LabeledSwitch id="hyphens-switch"
id="hyphens-switch" label={hyphens ? "On" : "Off"}
label={hyphens ? "On" : "Off"} checked={hyphens}
checked={hyphens} onCheckedChange={setHyphens}
onCheckedChange={setHyphens} aria-label="toggle whether to add hyphens"
aria-label="toggle whether to add hyphens" />
/> }
} />
/>
),
[hyphens]
); );
const uppercaseConfig = useMemo( const uppercaseConfig = (
() => ( <Configuration
<Configuration icon={<icons.CaseSensitive size={24} />}
icon={<icons.CaseSensitive size={24} />} title="Uppercase"
title="Uppercase" control={
control={ <LabeledSwitch
<LabeledSwitch id="uppercase-switch"
id="uppercase-switch" label={uppercase ? "On" : "Off"}
label={uppercase ? "On" : "Off"} checked={uppercase}
checked={uppercase} onCheckedChange={setUppercase}
onCheckedChange={setUppercase} aria-label="toggle whether to generate in uppercase"
aria-label="toggle whether to generate in uppercase" />
/> }
} />
/>
),
[uppercase]
); );
const uuidVersionConfig = useMemo( const uuidVersionConfig = (
() => ( <Configuration
<Configuration icon={<icons.Settings2 size={24} />}
icon={<icons.Settings2 size={24} />} title="UUID version"
title="UUID version" description="Choose the version of UUID to generate"
description="Choose the version of UUID to generate" control={
control={ <Select value={uuidVersion} onValueChange={onUuidVersionChange}>
<Select value={uuidVersion} onValueChange={onUuidVersionChange}> <SelectTrigger
<SelectTrigger className="w-28"
className="w-28" aria-label="toggle open/close state of uuid version selection"
aria-label="toggle open/close state of uuid version selection" >
> <SelectValue placeholder={uuidVersion} />
<SelectValue placeholder={uuidVersion} /> </SelectTrigger>
</SelectTrigger> <SelectContent>
<SelectContent> <SelectItem value={versions.v1}>1</SelectItem>
<SelectItem value={versions.v1}>1</SelectItem> <SelectItem value={versions.v4}>4 (GUID)</SelectItem>
<SelectItem value={versions.v4}>4 (GUID)</SelectItem> </SelectContent>
</SelectContent> </Select>
</Select> }
} />
/>
),
[uuidVersion]
); );
const generatesInput = useMemo( const generatesInput = useMemo(

View File

@@ -1,6 +1,5 @@
"use client"; "use client";
import { useMemo } from "react";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import { singleTools } from "@/config/tools"; import { singleTools } from "@/config/tools";
@@ -20,30 +19,27 @@ import { PageSection } from "@/components/page-section";
export default function Page() { export default function Page() {
const { theme = "system", setTheme } = useTheme(); const { theme = "system", setTheme } = useTheme();
const appThemeConfig = useMemo( const appThemeConfig = (
() => ( <Configuration
<Configuration icon={<icons.Paintbrush size={24} />}
icon={<icons.Paintbrush size={24} />} title="App theme"
title="App theme" description="Select which app theme to display"
description="Select which app theme to display" control={
control={ <Select value={theme} onValueChange={setTheme}>
<Select value={theme} onValueChange={setTheme}> <SelectTrigger
<SelectTrigger className="w-28"
className="w-28" aria-label="toggle open/close state of app theme selection"
aria-label="toggle open/close state of app theme selection" >
> <SelectValue placeholder={theme} />
<SelectValue placeholder={theme} /> </SelectTrigger>
</SelectTrigger> <SelectContent>
<SelectContent> <SelectItem value="light">Light</SelectItem>
<SelectItem value="light">Light</SelectItem> <SelectItem value="dark">Dark</SelectItem>
<SelectItem value="dark">Dark</SelectItem> <SelectItem value="system">System</SelectItem>
<SelectItem value="system">System</SelectItem> </SelectContent>
</SelectContent> </Select>
</Select> }
} />
/>
),
[setTheme, theme]
); );
return ( return (

View File

@@ -1,3 +1,6 @@
import { memo } from "react";
import equal from "react-fast-compare";
type Props = { type Props = {
icon: React.ReactNode; icon: React.ReactNode;
title: string; title: string;
@@ -5,7 +8,7 @@ type Props = {
control: React.ReactNode; control: React.ReactNode;
}; };
export function Configuration({ icon, title, description, control }: Props) { function RawConfiguration({ icon, title, description, control }: Props) {
return ( return (
<div className="flex h-16 items-center gap-6 rounded border bg-configuration px-4"> <div className="flex h-16 items-center gap-6 rounded border bg-configuration px-4">
{icon} {icon}
@@ -21,3 +24,5 @@ export function Configuration({ icon, title, description, control }: Props) {
</div> </div>
); );
} }
export const Configuration = memo(RawConfiguration, equal);