From cf8ed0df25e8d1a6dfd76fb906bc76bfac5e4928 Mon Sep 17 00:00:00 2001 From: LCSOGthb <185141600+LCSOGthb@users.noreply.github.com> Date: Mon, 31 Aug 2026 03:12:57 +0800 Subject: [PATCH 1/3] Add more feature to the website Signed-off-by: LCSOGthb <185141600+LCSOGthb@users.noreply.github.com> --- artifacts/personal-tool-console/index.html | 12 +- artifacts/personal-tool-console/src/App.tsx | 19 +- .../src/components/layout/app-shell.tsx | 13 + .../src/components/layout/command-palette.tsx | 113 + .../src/components/layout/site-footer.tsx | 34 + .../src/components/layout/site-header.tsx | 44 + .../components/layout/tool-page-layout.tsx | 112 + .../src/components/tools/base64.tsx | 53 + .../components/tools/bitmap/bitmap-tools.tsx | 233 + .../src/components/tools/calculator.tsx | 111 + .../src/components/tools/code-to-image.tsx | 100 + .../src/components/tools/coding-tools.tsx | 274 + .../components/tools/color/color-tools.tsx | 308 + .../components/tools/crypto/crypto-tools.tsx | 355 + .../components/tools/css/css-generators.tsx | 453 ++ .../components/tools/currency-converter.tsx | 85 + .../src/components/tools/dns-lookup.tsx | 132 + .../src/components/tools/hash.tsx | 66 + .../components/tools/image/image-tools.tsx | 628 ++ .../src/components/tools/json-formatter.tsx | 96 + .../src/components/tools/json-tree-viewer.tsx | 128 + .../components/tools/linux/linux-tools.tsx | 426 ++ .../src/components/tools/misc/misc-tools.tsx | 402 ++ .../components/tools/password-generator.tsx | 71 + .../src/components/tools/qr-generator.tsx | 134 + .../src/components/tools/rn-shadow.tsx | 65 + .../src/components/tools/set/set-tools.tsx | 131 + .../components/tools/shared/coming-soon.tsx | 29 + .../src/components/tools/shared/fields.tsx | 110 + .../components/tools/social/social-tools.tsx | 964 +++ .../src/components/tools/speed-test.tsx | 79 + .../components/tools/text/text-tool-page.tsx | 116 + .../src/components/tools/timestamp.tsx | 77 + .../src/components/tools/unit-converter.tsx | 70 + .../src/components/tools/url-encoder.tsx | 47 + .../src/components/tools/utf8/utf8-tools.tsx | 243 + .../src/components/tools/uuid-generator.tsx | 66 + .../src/components/tools/xml/xml-tools.tsx | 132 + .../src/hooks/use-page-title.ts | 9 + .../personal-tool-console/src/lib/copy.ts | 3 + .../personal-tool-console/src/lib/format.ts | 10 + .../src/lib/registry/core-tools.ts | 148 + .../src/lib/registry/css-tools.ts | 74 + .../src/lib/registry/dev-tools.ts | 195 + .../src/lib/registry/lazy.ts | 7 + .../src/lib/registry/media-tools.ts | 162 + .../src/lib/registry/text.ts | 77 + .../personal-tool-console/src/lib/storage.ts | 38 + .../src/lib/tool-registry.ts | 130 + .../src/lib/tools/base64.ts | 11 + .../src/lib/tools/bitmap/index.ts | 33 + .../src/lib/tools/calculator.ts | 11 + .../src/lib/tools/coding.ts | 233 + .../src/lib/tools/color.ts | 152 + .../src/lib/tools/crypto.ts | 143 + .../src/lib/tools/css-gen.ts | 126 + .../src/lib/tools/currency-converter.ts | 18 + .../src/lib/tools/dns.ts | 24 + .../src/lib/tools/hash.ts | 18 + .../src/lib/tools/linux.ts | 316 + .../src/lib/tools/misc.ts | 165 + .../src/lib/tools/password.ts | 24 + .../src/lib/tools/set/index.ts | 31 + .../src/lib/tools/speed-test.ts | 112 + .../src/lib/tools/text/existing.ts | 95 + .../src/lib/tools/text/helpers.ts | 265 + .../src/lib/tools/text/index.ts | 18 + .../src/lib/tools/text/part1.ts | 1159 ++++ .../src/lib/tools/text/part2.ts | 1799 +++++ .../src/lib/tools/text/types.ts | 25 + .../src/lib/tools/timestamp.ts | 39 + .../src/lib/tools/unit-converter.ts | 45 + .../src/lib/tools/utf8.ts | 127 + .../src/lib/tools/xml.ts | 158 + .../src/pages/catalog.tsx | 193 + .../src/pages/console.tsx | 1205 ++++ .../src/pages/not-found.tsx | 45 +- .../src/pages/tool-page.tsx | 75 + pnpm-lock.yaml | 6039 +++++++---------- 79 files changed, 16329 insertions(+), 3759 deletions(-) create mode 100644 artifacts/personal-tool-console/src/components/layout/app-shell.tsx create mode 100644 artifacts/personal-tool-console/src/components/layout/command-palette.tsx create mode 100644 artifacts/personal-tool-console/src/components/layout/site-footer.tsx create mode 100644 artifacts/personal-tool-console/src/components/layout/site-header.tsx create mode 100644 artifacts/personal-tool-console/src/components/layout/tool-page-layout.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/base64.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/bitmap/bitmap-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/calculator.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/code-to-image.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/coding-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/color/color-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/crypto/crypto-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/css/css-generators.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/currency-converter.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/dns-lookup.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/hash.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/image/image-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/json-formatter.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/json-tree-viewer.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/linux/linux-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/misc/misc-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/password-generator.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/qr-generator.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/rn-shadow.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/set/set-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/shared/coming-soon.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/shared/fields.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/social/social-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/speed-test.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/text/text-tool-page.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/timestamp.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/unit-converter.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/url-encoder.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/utf8/utf8-tools.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/uuid-generator.tsx create mode 100644 artifacts/personal-tool-console/src/components/tools/xml/xml-tools.tsx create mode 100644 artifacts/personal-tool-console/src/hooks/use-page-title.ts create mode 100644 artifacts/personal-tool-console/src/lib/copy.ts create mode 100644 artifacts/personal-tool-console/src/lib/format.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/core-tools.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/css-tools.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/dev-tools.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/lazy.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/media-tools.ts create mode 100644 artifacts/personal-tool-console/src/lib/registry/text.ts create mode 100644 artifacts/personal-tool-console/src/lib/storage.ts create mode 100644 artifacts/personal-tool-console/src/lib/tool-registry.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/base64.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/bitmap/index.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/calculator.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/coding.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/color.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/crypto.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/css-gen.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/currency-converter.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/dns.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/hash.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/linux.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/misc.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/password.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/set/index.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/speed-test.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/existing.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/helpers.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/index.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/part1.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/part2.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/text/types.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/timestamp.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/unit-converter.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/utf8.ts create mode 100644 artifacts/personal-tool-console/src/lib/tools/xml.ts create mode 100644 artifacts/personal-tool-console/src/pages/catalog.tsx create mode 100644 artifacts/personal-tool-console/src/pages/console.tsx create mode 100644 artifacts/personal-tool-console/src/pages/tool-page.tsx diff --git a/artifacts/personal-tool-console/index.html b/artifacts/personal-tool-console/index.html index 5d4bce9..850b8a2 100644 --- a/artifacts/personal-tool-console/index.html +++ b/artifacts/personal-tool-console/index.html @@ -3,15 +3,15 @@ - Personal Tool Console - + Toolbox — Tools for text, code, media & math + - - + + - - + + diff --git a/artifacts/personal-tool-console/src/App.tsx b/artifacts/personal-tool-console/src/App.tsx index a3baeaa..20b7300 100644 --- a/artifacts/personal-tool-console/src/App.tsx +++ b/artifacts/personal-tool-console/src/App.tsx @@ -2,16 +2,27 @@ import { Switch, Route, Router as WouterRouter } from "wouter"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Toaster } from "@/components/ui/toaster"; import { TooltipProvider } from "@/components/ui/tooltip"; +import { AppShell } from "@/components/layout/app-shell"; +import Catalog from "@/pages/catalog"; +import Console from "@/pages/console"; +import ToolPage from "@/pages/tool-page"; import NotFound from "@/pages/not-found"; -import Home from "@/pages/home"; const queryClient = new QueryClient(); function Router() { return ( - - + {() => } + {() => } + + {({ slug }) => ( + + + + )} + + {() => } ); } @@ -29,4 +40,4 @@ function App() { ); } -export default App; +export default App; \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/layout/app-shell.tsx b/artifacts/personal-tool-console/src/components/layout/app-shell.tsx new file mode 100644 index 0000000..17bc18f --- /dev/null +++ b/artifacts/personal-tool-console/src/components/layout/app-shell.tsx @@ -0,0 +1,13 @@ +import type { ReactNode } from "react"; +import { SiteHeader } from "@/components/layout/site-header"; +import { SiteFooter } from "@/components/layout/site-footer"; + +export function AppShell({ children }: { children: ReactNode }) { + return ( +
+ +
{children}
+ +
+ ); +} \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/layout/command-palette.tsx b/artifacts/personal-tool-console/src/components/layout/command-palette.tsx new file mode 100644 index 0000000..c132c04 --- /dev/null +++ b/artifacts/personal-tool-console/src/components/layout/command-palette.tsx @@ -0,0 +1,113 @@ +import { useEffect, useMemo, useState } from "react"; +import { useLocation } from "wouter"; +import { Search, TerminalSquare } from "lucide-react"; +import { + CommandDialog, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command"; +import { Kbd } from "@/components/ui/kbd"; +import { searchTools, getRecentTools } from "@/lib/tool-registry"; +import type { ToolDefinition } from "@/lib/tool-registry"; + +export function CommandPalette() { + const [open, setOpen] = useState(false); + const [value, setValue] = useState(""); + const [, navigate] = useLocation(); + + useEffect(() => { + const onKey = (e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { + e.preventDefault(); + setOpen((o) => !o); + } + }; + window.addEventListener("keydown", onKey); + return () => window.removeEventListener("keydown", onKey); + }, []); + + const results = useMemo(() => (value.trim() ? searchTools(value, 10) : []), [value]); + const recents = useMemo(() => (value.trim() ? [] : getRecentTools().slice(0, 5)), [value, open]); + + const run = (url: string) => { + setOpen(false); + setValue(""); + const base = import.meta.env.BASE_URL.replace(/\/$/, ""); + navigate(base + url); + }; + + const ToolRow = ({ tool }: { tool: ToolDefinition }) => { + const Icon = tool.icon; + return ( + run(`/tools/${tool.slug}`)} + > + + {tool.name} + {tool.status === "coming-soon" && ( + Soon + )} + + ); + }; + + return ( + <> +
+ + +
+ + + + + No tools found for “{value}”. + {value.trim() ? ( + + {results.map((tool) => ( + + ))} + + ) : ( + <> + run("/console")}> + + Open command console + + {recents.length > 0 && ( + <> + + + {recents.map((tool) => ( + + ))} + + + )} + + )} + + + + ); +} \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/layout/site-footer.tsx b/artifacts/personal-tool-console/src/components/layout/site-footer.tsx new file mode 100644 index 0000000..a2d1343 --- /dev/null +++ b/artifacts/personal-tool-console/src/components/layout/site-footer.tsx @@ -0,0 +1,34 @@ +import { Link } from "wouter"; +import { Wrench } from "lucide-react"; +import { SITE_NAME } from "@/hooks/use-page-title"; + +export function SiteFooter() { + return ( + + ); +} \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/layout/site-header.tsx b/artifacts/personal-tool-console/src/components/layout/site-header.tsx new file mode 100644 index 0000000..35a3ca3 --- /dev/null +++ b/artifacts/personal-tool-console/src/components/layout/site-header.tsx @@ -0,0 +1,44 @@ +import { Link, useLocation } from "wouter"; +import { Wrench } from "lucide-react"; +import { CommandPalette } from "@/components/layout/command-palette"; +import { SITE_NAME } from "@/hooks/use-page-title"; +import { cn } from "@/lib/utils"; + +const NAV = [ + { href: "/", label: "Catalog" }, + { href: "/console", label: "Console" }, +]; + +export function SiteHeader() { + const [path] = useLocation(); + return ( +
+
+ + + + + {SITE_NAME} + + + +
+
+ ); +} \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/layout/tool-page-layout.tsx b/artifacts/personal-tool-console/src/components/layout/tool-page-layout.tsx new file mode 100644 index 0000000..53865c2 --- /dev/null +++ b/artifacts/personal-tool-console/src/components/layout/tool-page-layout.tsx @@ -0,0 +1,112 @@ +import type { ReactNode } from "react"; +import { Link } from "wouter"; +import { ChevronRight } from "lucide-react"; +import type { ToolDefinition, ToolCategoryMeta } from "@/lib/tool-registry"; +import { Badge } from "@/components/ui/badge"; +import { SquareTerminal, type LucideIcon } from "lucide-react"; + +function RelatedCard({ tool }: { tool: ToolDefinition }) { + const Icon = tool.icon; + return ( + +
+ + + +
+

{tool.name}

+

{tool.description}

+
+
+ + ); +} + +export function ToolPageLayout({ + tool, + category, + related, + onCopyCommand, + children, +}: { + tool: ToolDefinition; + category: ToolCategoryMeta; + related: ToolDefinition[]; + onCopyCommand?: () => void; + children: ReactNode; +}) { + const CatIcon = category.icon as LucideIcon; + return ( +
+ + +
+
+ + + +
+
+

{tool.name}

+ {tool.status === "coming-soon" && ( + + Coming soon + + )} +
+

{tool.description}

+ {tool.commands && tool.commands.length > 0 && ( +
+ Console: + {tool.commands.slice(0, 3).map((c) => ( + + ))} +
+ )} +
+
+
+ + {children} + + {related.length > 0 && ( +
+

+ + More in {category.label} +

+
+ {related.map((t) => ( + + ))} +
+
+ )} +
+ ); +} \ No newline at end of file diff --git a/artifacts/personal-tool-console/src/components/tools/base64.tsx b/artifacts/personal-tool-console/src/components/tools/base64.tsx new file mode 100644 index 0000000..766d86c --- /dev/null +++ b/artifacts/personal-tool-console/src/components/tools/base64.tsx @@ -0,0 +1,53 @@ +import { useState } from "react"; +import type { ToolPageProps } from "@/lib/tool-registry"; +import { base64Encode, base64Decode } from "@/lib/tools/base64"; +import { Field, TextArea, SelectInput, OutBox, Chip } from "@/components/tools/shared/fields"; + +export default function Base64({ tool }: ToolPageProps) { + const [mode, setMode] = useState("Encode"); + const [input, setInput] = useState(""); + const [error, setError] = useState(null); + + const transform = () => { + if (!input) return ""; + try { + setError(null); + return mode === "Encode" ? base64Encode(input) : base64Decode(input); + } catch (e) { + setError((e as Error).message); + return ""; + } + }; + + const output = transform(); + + return ( +
+
+ { setMode(e.target.value); setError(null); }} options={["Encode", "Decode"]} className="w-36" /> + {tool.slug} +
+ +
+ +