From b0a61fbd5bf95e4d949ddf181fea903387597f27 Mon Sep 17 00:00:00 2001 From: Cu Thanh Cam Date: Sun, 5 Jul 2026 17:58:23 +0700 Subject: [PATCH 1/6] Polish crypto tool ordering and output --- src/core/registry/tool.registry.ts | 22 +++++------ .../PasswordGeneratorPage.tsx | 38 ++++++++++++++++--- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/core/registry/tool.registry.ts b/src/core/registry/tool.registry.ts index 2aef213..996e3e4 100644 --- a/src/core/registry/tool.registry.ts +++ b/src/core/registry/tool.registry.ts @@ -107,6 +107,17 @@ export const toolRegistry: ToolDefinition[] = [ route: "/tools/url-encoder", status: "available", }, + { + id: "jwt-secret", + name: "JWT Secret Generator", + category: "Crypto", + description: "Generate secure HS256, HS384, and HS512 JWT secrets locally.", + keywords: ["jwt", "secret", "hs256", "hs512", "hmac"], + icon: ShieldCheck, + persist: false, + route: "/tools/jwt-secret", + status: "available", + }, { id: "hash-generator", name: "Hash Generator", @@ -129,17 +140,6 @@ export const toolRegistry: ToolDefinition[] = [ route: "/tools/password-generator", status: "available", }, - { - id: "jwt-secret", - name: "JWT Secret Generator", - category: "Crypto", - description: "Generate secure HS256, HS384, and HS512 JWT secrets locally.", - keywords: ["jwt", "secret", "hs256", "hs512", "hmac"], - icon: ShieldCheck, - persist: false, - route: "/tools/jwt-secret", - status: "available", - }, { id: "uuid", name: "UUID Generator", diff --git a/src/features/password-generator/PasswordGeneratorPage.tsx b/src/features/password-generator/PasswordGeneratorPage.tsx index df3ee19..9b490f9 100644 --- a/src/features/password-generator/PasswordGeneratorPage.tsx +++ b/src/features/password-generator/PasswordGeneratorPage.tsx @@ -8,6 +8,8 @@ import { RefreshCw, SlidersHorizontal, TextCursorInput, + Eye, + EyeOff, } from "lucide-react"; import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; @@ -410,17 +412,33 @@ function SecretOutput({ onCopy: () => void; result: GeneratedSecret; }): JSX.Element { + const [visible, setVisible] = useState(false); + return (
-
+

- {result.value} + {visible ? result.value : maskSecret(result.value)}

- +
+ + +
@@ -432,6 +450,14 @@ function SecretOutput({ ); } +function maskSecret(secret: string): string { + if (secret.length <= 12) { + return "*".repeat(secret.length); + } + + return `${secret.slice(0, 6)}${"*".repeat(Math.max(12, secret.length - 12))}${secret.slice(-6)}`; +} + function Metric({ label, value }: { label: string; value: string }): JSX.Element { return (
From 5604013079277db8475ba2a5080743fc4d79182a Mon Sep 17 00:00:00 2001 From: Cu Thanh Cam Date: Sun, 5 Jul 2026 17:58:29 +0700 Subject: [PATCH 2/6] Enhance UUID generator tool --- src/features/uuid/UuidPage.tsx | 334 +++++++++++++++++++++---- src/features/uuid/uuid.service.test.ts | 19 +- src/features/uuid/uuid.service.ts | 107 +++++++- 3 files changed, 408 insertions(+), 52 deletions(-) diff --git a/src/features/uuid/UuidPage.tsx b/src/features/uuid/UuidPage.tsx index 06f176e..9b5092b 100644 --- a/src/features/uuid/UuidPage.tsx +++ b/src/features/uuid/UuidPage.tsx @@ -1,65 +1,303 @@ import type { JSX } from "react"; -import { useState } from "react"; -import { Copy, RefreshCw } from "lucide-react"; +import { useMemo, useState } from "react"; +import { CheckCircle2, Copy, Download, Fingerprint, RefreshCw } from "lucide-react"; +import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; -import { ResultRow } from "@/shared/components/ToolSurface"; -import { createUuidBatch } from "./uuid.service"; +import { Tooltip } from "@/shared/ui/tooltip"; +import { PaneHeader, ToolSurface, ToolToolbar } from "@/shared/components/ToolSurface"; +import { + createUuidBatch, + validateUuid, + type UuidFormat, + type UuidVersion, +} from "./uuid.service"; export function UuidPage(): JSX.Element { - const [count, setCount] = useState(5); - const [values, setValues] = useState(() => createUuidBatch(5)); + const [version, setVersion] = useState("v4"); + const [format, setFormat] = useState("standard"); + const [count, setCount] = useState(10); + const [seed, setSeed] = useState(0); + const [validationInput, setValidationInput] = useState(""); + const values = useMemo(() => { + void seed; - function generate(): void { - setValues(createUuidBatch(count)); + return createUuidBatch({ count, format, version }); + }, [count, format, seed, version]); + const validation = useMemo(() => validateUuid(validationInput), [validationInput]); + + async function copy(value: string): Promise { + await navigator.clipboard.writeText(value); } async function copyAll(): Promise { - await navigator.clipboard.writeText(values.join("\n")); + await copy(values.join("\n")); + } + + function download(): void { + const blob = new Blob([values.join("\n")], { type: "text/plain;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const anchor = document.createElement("a"); + + anchor.href = url; + anchor.download = "forge-uuids.txt"; + anchor.click(); + URL.revokeObjectURL(url); } return ( -
-
-
-

- UUID Generator -

-

- Utilities -

+ + + setVersion("v4")} + /> + setVersion("v7")} + /> + setVersion("nil")} + /> +
+ +
+ } + right={ + <> + + + + + + + + } + /> + +
+
+ +
+
+

+ Batch size +

+
+ {[1, 10, 25, 100].map((value) => ( + setCount(value)} + value={value === 1 ? "Single" : "Bulk"} + /> + ))} +
+ +
+ +
+

+ Validate UUID +

+