mirror of
https://github.com/ershisan99/DevToysWeb.git
synced 2025-12-16 20:49:23 +00:00
refactor: memoize configuration on export
This commit is contained in:
@@ -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} />;
|
||||||
|
|||||||
@@ -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} />;
|
||||||
|
|||||||
@@ -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} />;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user