mirror of
https://github.com/ershisan99/DevToysWeb.git
synced 2025-12-16 20:49:23 +00:00
144 lines
4.7 KiB
TypeScript
144 lines
4.7 KiB
TypeScript
"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 * as 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 title="Generate">
|
||
<div className="flex items-center gap-2">
|
||
<Button variant="secondary" onClick={onGenerateClick}>
|
||
Generate UUID(s)
|
||
</Button>
|
||
<span>×</span>
|
||
<Input className="w-24" type="number" value={generates} onChange={onGeneratesChange} />
|
||
</div>
|
||
</PageSection>
|
||
<PageSection className="-mt-3" title="UUID(s)" control={uuidsControl}>
|
||
<Textarea {...{ ref }} value={uuidsString} rows={10} readOnly />
|
||
</PageSection>
|
||
</PageRootSection>
|
||
);
|
||
}
|