Files
DevToysWeb/app/generators/uuid/page.tsx
2024-03-29 20:47:21 +09:00

149 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useCallback, useState } from "react";
import { range } from "fp-ts/NonEmptyArray";
import { toolGroups } from "@/config/tools";
import { uuid } from "@/lib/uuid";
import { useAutoScroll } from "@/hooks/useAutoScroll";
import { Button } from "@/components/ui/button";
import { Input, InputProps } from "@/components/ui/input";
import * as Select from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { Clear } from "@/components/buttons/clear";
import { Copy } from "@/components/buttons/copy";
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";
const versions = {
v1: "1",
v4: "4",
} as const;
type UuidVersion = (typeof versions)[keyof typeof versions];
function isUuidVersion(s: string): s is UuidVersion {
return Object.values(versions).includes(s as UuidVersion);
}
export default function Page() {
const [hyphens, setHyphens] = useState(true);
const [uppercase, setUppercase] = useState(false);
const [uuidVersion, setUuidVersion] = useState<UuidVersion>("4");
const [generates, setGenerates] = useState(1);
const [uuids, setUuids] = useState<string[]>([]);
const ref = useAutoScroll<HTMLTextAreaElement>([uuids]);
const uuidsString = uuids.join("\n");
const clearUuids = useCallback(() => setUuids([]), []);
const onUuidVersionChange: NonNullable<Select.Props["onValueChange"]> = useCallback(value => {
if (isUuidVersion(value)) {
setUuidVersion(value);
}
}, []);
const onGeneratesChange: NonNullable<InputProps["onChange"]> = useCallback(e => {
const newGenerates = Number(e.currentTarget.value);
if (newGenerates >= 1 && newGenerates <= 1000) {
setGenerates(newGenerates);
}
}, []);
const onGenerateClick = () => {
const newUuids = range(1, generates).map(_ => uuid(uuidVersion, hyphens, uppercase));
setUuids([...uuids, ...newUuids]);
};
const hyphensConfig = (
<Configuration
icon={<icons.Minus size={24} />}
title="Hyphens"
control={
<LabeledSwitch
id="hyphens-switch"
label={hyphens ? "On" : "Off"}
checked={hyphens}
onCheckedChange={setHyphens}
aria-label="toggle whether to add hyphens"
/>
}
/>
);
const uppercaseConfig = (
<Configuration
icon={<icons.CaseSensitive size={24} />}
title="Uppercase"
control={
<LabeledSwitch
id="uppercase-switch"
label={uppercase ? "On" : "Off"}
checked={uppercase}
onCheckedChange={setUppercase}
aria-label="toggle whether to generate in uppercase"
/>
}
/>
);
const uuidVersionConfig = (
<Configuration
icon={<icons.Settings2 size={24} />}
title="UUID version"
description="Choose the version of UUID to generate"
control={
<Select.Root value={uuidVersion} onValueChange={onUuidVersionChange}>
<Select.Trigger
className="w-28"
aria-label="toggle open/close state of uuid version selection"
>
<Select.Value placeholder={uuidVersion} />
</Select.Trigger>
<Select.Content>
<Select.Item value={versions.v1}>1</Select.Item>
<Select.Item value={versions.v4}>4 (GUID)</Select.Item>
</Select.Content>
</Select.Root>
}
/>
);
const uuidsCopyButton = <Copy text={uuidsString} />;
const uuidsClearButton = <Clear onClick={clearUuids} iconOnly aria-label="clear uuids" />;
const uuidsControl = <ControlMenu list={[uuidsCopyButton, uuidsClearButton]} />;
return (
<PageRootSection title={toolGroups.generators.tools.uuid.longTitle}>
<PageSection title="Configuration">
<Configurations list={[hyphensConfig, uppercaseConfig, uuidVersionConfig]} />
</PageSection>
<PageSection className="mt-6" title="Generate">
<div className="flex items-center gap-2">
<Button variant="secondary" onClick={onGenerateClick}>
Generate UUID(s)
</Button>
<span>×</span>
<Input
className="w-24 font-sans"
type="number"
value={generates}
onChange={onGeneratesChange}
/>
</div>
</PageSection>
<PageSection title="UUID(s)" control={uuidsControl}>
<Textarea {...{ ref }} value={uuidsString} rows={10} readOnly />
</PageSection>
</PageRootSection>
);
}