feat: update-layout & add uuid tool (#4)
Co-authored-by: typist <git@mail.typist.cc> Reviewed-on: #4
This commit is contained in:
@@ -18,11 +18,13 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.548.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss": "^4.1.16"
|
||||
"tailwindcss": "^4.1.16",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.36.0",
|
||||
|
||||
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -35,6 +35,9 @@ importers:
|
||||
lucide-react:
|
||||
specifier: ^0.548.0
|
||||
version: 0.548.0(react@19.2.0)
|
||||
nanoid:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
react:
|
||||
specifier: ^19.1.1
|
||||
version: 19.2.0
|
||||
@@ -50,6 +53,9 @@ importers:
|
||||
tailwindcss:
|
||||
specifier: ^4.1.16
|
||||
version: 4.1.16
|
||||
uuid:
|
||||
specifier: ^13.0.0
|
||||
version: 13.0.0
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: ^9.36.0
|
||||
@@ -1266,6 +1272,11 @@ packages:
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
nanoid@5.1.6:
|
||||
resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==}
|
||||
engines: {node: ^18 || >=20}
|
||||
hasBin: true
|
||||
|
||||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
@@ -1551,6 +1562,10 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
uuid@13.0.0:
|
||||
resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
|
||||
hasBin: true
|
||||
|
||||
which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -2683,6 +2698,8 @@ snapshots:
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
nanoid@5.1.6: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
node-releases@2.0.26: {}
|
||||
@@ -2912,6 +2929,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.2
|
||||
|
||||
uuid@13.0.0: {}
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar";
|
||||
import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar";
|
||||
import { tools } from "@/components/tool";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export const AppSidebar = () => (
|
||||
<Sidebar>
|
||||
<SidebarHeader>
|
||||
<SidebarHeader className="text-2xl font-bold flex justify-center items-center">
|
||||
Lite Kit
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
{
|
||||
tools.map((tool) => (
|
||||
<SidebarMenuItem key={tool.name}>
|
||||
<SidebarMenuButton>
|
||||
{tool.icon}
|
||||
{tool.name}
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))
|
||||
}
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>
|
||||
Tools
|
||||
</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
{
|
||||
tools.map((tool) => (
|
||||
<SidebarMenuItem key={tool.name}>
|
||||
<SidebarMenuButton asChild>
|
||||
<Link to={`/tool/${tool.path}`} title={tool.description}>
|
||||
{tool.icon}
|
||||
{tool.name}
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))
|
||||
}
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<a href="mailto:litek@mail.typist.cc">contact us</a>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
interface Tool {
|
||||
name: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
component: React.ReactNode;
|
||||
}
|
||||
import { Hash } from 'lucide-react'
|
||||
|
||||
export const tools: Tool[] = [];
|
||||
import type { Tool } from "./type";
|
||||
import { UUID } from './uuid'
|
||||
|
||||
export const tools: Tool[] = [
|
||||
{
|
||||
path: "uuid",
|
||||
name: "UUID Generator",
|
||||
description: "Generate a UUID",
|
||||
icon: <Hash />,
|
||||
component: <UUID />,
|
||||
}
|
||||
];
|
||||
9
src/components/tool/type.ts
Normal file
9
src/components/tool/type.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export interface Tool {
|
||||
path: string;
|
||||
name: string;
|
||||
icon: ReactNode;
|
||||
description: string;
|
||||
component: ReactNode;
|
||||
}
|
||||
22
src/components/tool/uuid.tsx
Normal file
22
src/components/tool/uuid.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { type FC } from "react";
|
||||
|
||||
import * as uuid from 'uuid'
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
export const UUID: FC = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="text-sm text-muted-foreground">Refresh the page to generate new UUID</span>
|
||||
<label>UUID Version 1</label>
|
||||
<span>{uuid.v1()}</span>
|
||||
<label>UUID Version 4</label>
|
||||
<span>{uuid.v4()}</span>
|
||||
<label>UUID Version 6</label>
|
||||
<span>{uuid.v6()}</span>
|
||||
<label>UUID Version 7</label>
|
||||
<span>{uuid.v7()}</span>
|
||||
<label>Nano ID</label>
|
||||
<span>{nanoid()}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,14 +1,20 @@
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
|
||||
import { Sidebar } from "@/components/ui/sidebar"
|
||||
import type { FC } from "react"
|
||||
import { Outlet } from "react-router-dom";
|
||||
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
|
||||
import { AppSidebar } from "@/components/sidebar";
|
||||
|
||||
export const Layout: FC = () => (
|
||||
<SidebarProvider>
|
||||
<Sidebar />
|
||||
<main>
|
||||
<SidebarTrigger />
|
||||
<Outlet />
|
||||
</main>
|
||||
<AppSidebar />
|
||||
<div className="p-4 flex flex-col w-full h-[100vh]">
|
||||
<nav className="flex items-center justify-between">
|
||||
<SidebarTrigger className="size-10" />
|
||||
<div role="actions" />
|
||||
</nav>
|
||||
<main className="flex-1 overflow-auto p-4">
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
);
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
RouterProvider,
|
||||
} from "react-router-dom";
|
||||
|
||||
import { Layout } from "./layout";
|
||||
import { tools } from "@/components/tool";
|
||||
import { Layout } from "./layout";
|
||||
|
||||
// 路由配置
|
||||
const router = createBrowserRouter([
|
||||
@@ -14,17 +14,17 @@ const router = createBrowserRouter([
|
||||
element: <Layout />,
|
||||
children: [
|
||||
{
|
||||
path: "tools",
|
||||
path: "tool",
|
||||
children: [
|
||||
...tools.map((tool) => (
|
||||
{
|
||||
path: tool.name,
|
||||
path: tool.path,
|
||||
element: tool.component,
|
||||
}
|
||||
)),
|
||||
{
|
||||
index: true,
|
||||
element: null,
|
||||
loader: () => redirect("/tool/uuid"),
|
||||
},
|
||||
]
|
||||
},
|
||||
@@ -32,15 +32,11 @@ const router = createBrowserRouter([
|
||||
},
|
||||
{
|
||||
index: true,
|
||||
loader: () => {
|
||||
return redirect("/tools");
|
||||
},
|
||||
loader: () => redirect("/tool"),
|
||||
},
|
||||
{
|
||||
path: "*",
|
||||
loader: () => {
|
||||
return redirect("/tools");
|
||||
},
|
||||
loader: () => redirect("/tool"),
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user