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",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.548.0",
|
"lucide-react": "^0.548.0",
|
||||||
|
"nanoid": "^5.1.6",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-router-dom": "^7.9.4",
|
"react-router-dom": "^7.9.4",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tailwindcss": "^4.1.16"
|
"tailwindcss": "^4.1.16",
|
||||||
|
"uuid": "^13.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
|
|||||||
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -35,6 +35,9 @@ importers:
|
|||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.548.0
|
specifier: ^0.548.0
|
||||||
version: 0.548.0(react@19.2.0)
|
version: 0.548.0(react@19.2.0)
|
||||||
|
nanoid:
|
||||||
|
specifier: ^5.1.6
|
||||||
|
version: 5.1.6
|
||||||
react:
|
react:
|
||||||
specifier: ^19.1.1
|
specifier: ^19.1.1
|
||||||
version: 19.2.0
|
version: 19.2.0
|
||||||
@@ -50,6 +53,9 @@ importers:
|
|||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.1.16
|
specifier: ^4.1.16
|
||||||
version: 4.1.16
|
version: 4.1.16
|
||||||
|
uuid:
|
||||||
|
specifier: ^13.0.0
|
||||||
|
version: 13.0.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.36.0
|
specifier: ^9.36.0
|
||||||
@@ -1266,6 +1272,11 @@ packages:
|
|||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
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:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
@@ -1551,6 +1562,10 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
uuid@13.0.0:
|
||||||
|
resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -2683,6 +2698,8 @@ snapshots:
|
|||||||
|
|
||||||
nanoid@3.3.11: {}
|
nanoid@3.3.11: {}
|
||||||
|
|
||||||
|
nanoid@5.1.6: {}
|
||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
node-releases@2.0.26: {}
|
node-releases@2.0.26: {}
|
||||||
@@ -2912,6 +2929,8 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.2
|
'@types/react': 19.2.2
|
||||||
|
|
||||||
|
uuid@13.0.0: {}
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
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 { tools } from "@/components/tool";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
export const AppSidebar = () => (
|
export const AppSidebar = () => (
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
<SidebarHeader>
|
<SidebarHeader className="text-2xl font-bold flex justify-center items-center">
|
||||||
Lite Kit
|
Lite Kit
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
{
|
<SidebarGroup>
|
||||||
tools.map((tool) => (
|
<SidebarGroupLabel>
|
||||||
<SidebarMenuItem key={tool.name}>
|
Tools
|
||||||
<SidebarMenuButton>
|
</SidebarGroupLabel>
|
||||||
{tool.icon}
|
<SidebarGroupContent>
|
||||||
{tool.name}
|
{
|
||||||
</SidebarMenuButton>
|
tools.map((tool) => (
|
||||||
</SidebarMenuItem>
|
<SidebarMenuItem key={tool.name}>
|
||||||
))
|
<SidebarMenuButton asChild>
|
||||||
}
|
<Link to={`/tool/${tool.path}`} title={tool.description}>
|
||||||
|
{tool.icon}
|
||||||
|
{tool.name}
|
||||||
|
</Link>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarFooter>
|
<SidebarFooter>
|
||||||
<a href="mailto:litek@mail.typist.cc">contact us</a>
|
<a href="mailto:litek@mail.typist.cc">contact us</a>
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
interface Tool {
|
import { Hash } from 'lucide-react'
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
icon: React.ReactNode;
|
|
||||||
component: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 type { FC } from "react"
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
|
|
||||||
|
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
|
||||||
|
import { AppSidebar } from "@/components/sidebar";
|
||||||
|
|
||||||
export const Layout: FC = () => (
|
export const Layout: FC = () => (
|
||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<Sidebar />
|
<AppSidebar />
|
||||||
<main>
|
<div className="p-4 flex flex-col w-full h-[100vh]">
|
||||||
<SidebarTrigger />
|
<nav className="flex items-center justify-between">
|
||||||
<Outlet />
|
<SidebarTrigger className="size-10" />
|
||||||
</main>
|
<div role="actions" />
|
||||||
|
</nav>
|
||||||
|
<main className="flex-1 overflow-auto p-4">
|
||||||
|
<Outlet />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
);
|
);
|
||||||
@@ -4,8 +4,8 @@ import {
|
|||||||
RouterProvider,
|
RouterProvider,
|
||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
|
|
||||||
import { Layout } from "./layout";
|
|
||||||
import { tools } from "@/components/tool";
|
import { tools } from "@/components/tool";
|
||||||
|
import { Layout } from "./layout";
|
||||||
|
|
||||||
// 路由配置
|
// 路由配置
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
@@ -14,17 +14,17 @@ const router = createBrowserRouter([
|
|||||||
element: <Layout />,
|
element: <Layout />,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "tools",
|
path: "tool",
|
||||||
children: [
|
children: [
|
||||||
...tools.map((tool) => (
|
...tools.map((tool) => (
|
||||||
{
|
{
|
||||||
path: tool.name,
|
path: tool.path,
|
||||||
element: tool.component,
|
element: tool.component,
|
||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
{
|
{
|
||||||
index: true,
|
index: true,
|
||||||
element: null,
|
loader: () => redirect("/tool/uuid"),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -32,15 +32,11 @@ const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: true,
|
index: true,
|
||||||
loader: () => {
|
loader: () => redirect("/tool"),
|
||||||
return redirect("/tools");
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "*",
|
path: "*",
|
||||||
loader: () => {
|
loader: () => redirect("/tool"),
|
||||||
return redirect("/tools");
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user