From 51a29e87a481a20f6072d460825a9f1deb009826 Mon Sep 17 00:00:00 2001 From: NVWA Bot Date: Wed, 17 Dec 2025 08:22:33 +0000 Subject: [PATCH] Init applications --- .gitignore | 43 + AGENTS.md | 6 + apps/wireframe-renderer-web/.gitignore | 25 + apps/wireframe-renderer-web/components.json | 21 + apps/wireframe-renderer-web/eslint.config.js | 23 + apps/wireframe-renderer-web/index.html | 13 + apps/wireframe-renderer-web/overview.md | 12 + apps/wireframe-renderer-web/package.json | 81 ++ apps/wireframe-renderer-web/src/App.tsx | 62 ++ .../src/components/auth-router.tsx | 70 ++ .../src/components/layout.tsx | 39 + .../src/components/ui/accordion.tsx | 64 ++ .../src/components/ui/alert-dialog.tsx | 155 ++++ .../src/components/ui/alert.tsx | 66 ++ .../src/components/ui/aspect-ratio.tsx | 11 + .../src/components/ui/avatar.tsx | 51 ++ .../src/components/ui/badge.tsx | 46 + .../src/components/ui/breadcrumb.tsx | 109 +++ .../src/components/ui/button.tsx | 59 ++ .../src/components/ui/calendar.tsx | 213 +++++ .../src/components/ui/card.tsx | 92 ++ .../src/components/ui/carousel.tsx | 239 +++++ .../src/components/ui/chart.tsx | 353 ++++++++ .../src/components/ui/checkbox.tsx | 32 + .../src/components/ui/collapsible.tsx | 31 + .../src/components/ui/command.tsx | 182 ++++ .../src/components/ui/context-menu.tsx | 252 ++++++ .../src/components/ui/dialog.tsx | 141 +++ .../src/components/ui/drawer.tsx | 135 +++ .../src/components/ui/dropdown-menu.tsx | 255 ++++++ .../src/components/ui/form.tsx | 167 ++++ .../src/components/ui/hover-card.tsx | 44 + .../src/components/ui/input-otp.tsx | 75 ++ .../src/components/ui/input.tsx | 21 + .../src/components/ui/label.tsx | 24 + .../src/components/ui/menubar.tsx | 274 ++++++ .../src/components/ui/navigation-menu.tsx | 168 ++++ .../src/components/ui/pagination.tsx | 127 +++ .../src/components/ui/popover.tsx | 48 + .../src/components/ui/progress.tsx | 29 + .../src/components/ui/radio-group.tsx | 45 + .../src/components/ui/resizable.tsx | 54 ++ .../src/components/ui/scroll-area.tsx | 58 ++ .../src/components/ui/select.tsx | 183 ++++ .../src/components/ui/separator.tsx | 28 + .../src/components/ui/sheet.tsx | 137 +++ .../src/components/ui/sidebar.tsx | 726 +++++++++++++++ .../src/components/ui/skeleton.tsx | 13 + .../src/components/ui/slider.tsx | 63 ++ .../src/components/ui/sonner.tsx | 23 + .../src/components/ui/switch.tsx | 31 + .../src/components/ui/table.tsx | 114 +++ .../src/components/ui/tabs.tsx | 66 ++ .../src/components/ui/textarea.tsx | 18 + .../src/components/ui/toggle-group.tsx | 71 ++ .../src/components/ui/toggle.tsx | 45 + .../src/components/ui/tooltip.tsx | 61 ++ .../src/custom/redirect-to-login.ts | 15 + .../src/hooks/use-auth.ts | 72 ++ .../src/hooks/use-mobile.ts | 19 + apps/wireframe-renderer-web/src/index.css | 185 ++++ apps/wireframe-renderer-web/src/index.tsx | 10 + apps/wireframe-renderer-web/src/lib/config.ts | 22 + apps/wireframe-renderer-web/src/lib/nvwa.ts | 16 + apps/wireframe-renderer-web/src/lib/utils.ts | 6 + .../src/pages/index.tsx | 11 + .../src/pages/user/login.tsx | 273 ++++++ .../src/pages/user/register.tsx | 216 +++++ .../src/static/react.svg | 1 + apps/wireframe-renderer-web/src/vite-env.d.ts | 12 + apps/wireframe-renderer-web/tsconfig.app.json | 34 + apps/wireframe-renderer-web/tsconfig.json | 19 + .../wireframe-renderer-web/tsconfig.node.json | 25 + apps/wireframe-renderer-web/vite.config.ts | 59 ++ database/common.ts | 7 + database/schema/auth.db.ts | 74 ++ database/schema/basic.db.ts | 14 + database/schema/project.db.ts | 38 + package.json | 13 + pnpm-lock.yaml | 836 ++++++++++++++++++ pnpm-workspace.yaml | 3 + 81 files changed, 7574 insertions(+) create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 apps/wireframe-renderer-web/.gitignore create mode 100644 apps/wireframe-renderer-web/components.json create mode 100644 apps/wireframe-renderer-web/eslint.config.js create mode 100644 apps/wireframe-renderer-web/index.html create mode 100644 apps/wireframe-renderer-web/overview.md create mode 100644 apps/wireframe-renderer-web/package.json create mode 100644 apps/wireframe-renderer-web/src/App.tsx create mode 100644 apps/wireframe-renderer-web/src/components/auth-router.tsx create mode 100644 apps/wireframe-renderer-web/src/components/layout.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/accordion.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/alert-dialog.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/alert.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/aspect-ratio.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/avatar.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/badge.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/breadcrumb.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/button.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/calendar.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/card.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/carousel.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/chart.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/checkbox.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/collapsible.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/command.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/context-menu.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/dialog.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/drawer.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/dropdown-menu.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/form.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/hover-card.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/input-otp.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/input.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/label.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/menubar.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/navigation-menu.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/pagination.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/popover.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/progress.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/radio-group.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/resizable.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/scroll-area.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/select.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/separator.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/sheet.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/sidebar.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/skeleton.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/slider.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/sonner.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/switch.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/table.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/tabs.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/textarea.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/toggle-group.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/toggle.tsx create mode 100644 apps/wireframe-renderer-web/src/components/ui/tooltip.tsx create mode 100644 apps/wireframe-renderer-web/src/custom/redirect-to-login.ts create mode 100644 apps/wireframe-renderer-web/src/hooks/use-auth.ts create mode 100644 apps/wireframe-renderer-web/src/hooks/use-mobile.ts create mode 100644 apps/wireframe-renderer-web/src/index.css create mode 100644 apps/wireframe-renderer-web/src/index.tsx create mode 100644 apps/wireframe-renderer-web/src/lib/config.ts create mode 100644 apps/wireframe-renderer-web/src/lib/nvwa.ts create mode 100644 apps/wireframe-renderer-web/src/lib/utils.ts create mode 100644 apps/wireframe-renderer-web/src/pages/index.tsx create mode 100644 apps/wireframe-renderer-web/src/pages/user/login.tsx create mode 100644 apps/wireframe-renderer-web/src/pages/user/register.tsx create mode 100644 apps/wireframe-renderer-web/src/static/react.svg create mode 100644 apps/wireframe-renderer-web/src/vite-env.d.ts create mode 100644 apps/wireframe-renderer-web/tsconfig.app.json create mode 100644 apps/wireframe-renderer-web/tsconfig.json create mode 100644 apps/wireframe-renderer-web/tsconfig.node.json create mode 100644 apps/wireframe-renderer-web/vite.config.ts create mode 100644 database/common.ts create mode 100644 database/schema/auth.db.ts create mode 100644 database/schema/basic.db.ts create mode 100644 database/schema/project.db.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8f6d1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# database migration config +database/drizzle.config.ts +database/package.json + +# dependencies +node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# production +apps/*/dist +apps/*/dist-nvwa + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +/src/generated/prisma diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..9faae13 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,6 @@ +# AI Wireframe Renderer + +This project creates a website where users can interactively draw wireframes (such as UI or interface sketches) on a canvas, input related text descriptions, and use AI technology to generate beautiful rendered images (e.g., high-definition webpage design screenshots or artistic renderings). The site supports uploading or editing sketches, as well as previewing and downloading the generated results. It aims to streamline the design process by bridging rough sketches to polished visuals through AI assistance. + +## Applications +- [wireframe-renderer-web] Wireframe Renderer Web (Desktop) diff --git a/apps/wireframe-renderer-web/.gitignore b/apps/wireframe-renderer-web/.gitignore new file mode 100644 index 0000000..2b87096 --- /dev/null +++ b/apps/wireframe-renderer-web/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-nvwa +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/apps/wireframe-renderer-web/components.json b/apps/wireframe-renderer-web/components.json new file mode 100644 index 0000000..ba0c18c --- /dev/null +++ b/apps/wireframe-renderer-web/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/index.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + } +} diff --git a/apps/wireframe-renderer-web/eslint.config.js b/apps/wireframe-renderer-web/eslint.config.js new file mode 100644 index 0000000..d94e7de --- /dev/null +++ b/apps/wireframe-renderer-web/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/apps/wireframe-renderer-web/index.html b/apps/wireframe-renderer-web/index.html new file mode 100644 index 0000000..f828b81 --- /dev/null +++ b/apps/wireframe-renderer-web/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/apps/wireframe-renderer-web/overview.md b/apps/wireframe-renderer-web/overview.md new file mode 100644 index 0000000..5ae7b58 --- /dev/null +++ b/apps/wireframe-renderer-web/overview.md @@ -0,0 +1,12 @@ +# Wireframe Renderer Web (wireframe-renderer-web) + +A desktop web application that provides an interactive canvas for drawing wireframes, inputting descriptions, generating AI-rendered images, uploading/editing sketches, and handling previews and downloads. + +**Design style:** Modern, intuitive, and user-friendly interface with a clean canvas layout, drag-and-drop functionality, and responsive design elements to enhance the creative workflow. + +## Capabilities +- Interactive Drawing: Allows users to draw wireframes freely on a canvas, including basic shapes, lines, and UI elements. +- Text Input and Description: Enables users to add and edit text descriptions associated with wireframes to guide AI generation. +- AI Image Generation: Utilizes AI to convert wireframes and descriptions into high-quality rendered images, such as webpage screenshots or artistic visuals. +- Upload and Edit: Supports uploading existing sketches or images and editing them on the canvas. +- Preview and Download: Provides real-time previews of generated images and options to download them in various formats. diff --git a/apps/wireframe-renderer-web/package.json b/apps/wireframe-renderer-web/package.json new file mode 100644 index 0000000..33f4894 --- /dev/null +++ b/apps/wireframe-renderer-web/package.json @@ -0,0 +1,81 @@ +{ + "name": "template-frontend-react", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "nvwa:build-h5": "rm -rf dist-nvwa && tsc -b && NVWA_BUILD_DEBUG=true NVWA_ENABLE_SOURCE_LOCATION=true vite build && cp -r dist/ dist-nvwa/", + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@hookform/resolvers": "^5.2.1", + "@nvwa-app/sdk-web": "^0.10.0", + "@radix-ui/react-accordion": "^1.2.12", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-aspect-ratio": "^1.1.7", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-context-menu": "^2.2.16", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-hover-card": "^1.1.15", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-menubar": "^1.1.16", + "@radix-ui/react-navigation-menu": "^1.2.14", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.6", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@tailwindcss/vite": "^4.1.12", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "date-fns": "^4.1.0", + "embla-carousel-react": "^8.6.0", + "input-otp": "^1.4.2", + "lucide-react": "^0.542.0", + "next-themes": "^0.4.6", + "react": "^19.1.1", + "react-day-picker": "^9.9.0", + "react-dom": "^19.1.1", + "react-router-dom": "^7.1.3", + "react-hook-form": "^7.62.0", + "react-resizable-panels": "^3.0.5", + "recharts": "2.15.4", + "sonner": "^2.0.7", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.12", + "vaul": "^1.1.2", + "zod": "^4.1.5" + }, + "devDependencies": { + "@eslint/js": "^9.33.0", + "@nvwa-app/vite-plugin": "^1.1.1", + "@types/node": "^24.3.0", + "@types/react": "^19.1.10", + "@types/react-dom": "^19.1.7", + "@vitejs/plugin-react-swc": "^4.0.0", + "eslint": "^9.33.0", + "vite-plugin-pages": "^0.32.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "tw-animate-css": "^1.3.7", + "typescript": "~5.8.3", + "typescript-eslint": "^8.39.1", + "vite": "^7.1.2" + } +} diff --git a/apps/wireframe-renderer-web/src/App.tsx b/apps/wireframe-renderer-web/src/App.tsx new file mode 100644 index 0000000..8a2e51d --- /dev/null +++ b/apps/wireframe-renderer-web/src/App.tsx @@ -0,0 +1,62 @@ +import { useEffect } from 'react' +import { BrowserRouter, useRoutes } from 'react-router-dom' +import type { RouteObject } from 'react-router-dom' +import { AuthRouter } from './components/auth-router' +import { Layout } from './components/layout' +import { setupIframeHoverInspector, setupIframeSourceLocationListener } from '@nvwa-app/sdk-web' +import LoginPage from './pages/user/login' +import RegisterPage from './pages/user/register' + +/** + * 应用路由配置 + * + * 配置三个主要路由: + * 1. /user/login - 登录页面(不需要 layout) + * 2. /user/register - 注册页面(不需要 layout) + * 3. /* - 通配符路由,匹配所有其他路径,使用 Layout 组件包裹 + * + * Layout 组件内部会根据 pathname 动态渲染对应的页面组件 + */ +const routes: RouteObject[] = [ + { + path: '/user/login', + element: , + }, + { + path: '/user/register', + element: , + }, + { + path: '/*', + element: ( + + + + ), + }, +] + +function Router() { + const element = useRoutes(routes) + return element +} + +function App() { + // 如果页面被嵌入 iframe,设置跨域通信监听器 + useEffect(() => { + const cleanup1 = setupIframeSourceLocationListener() + const cleanup2 = setupIframeHoverInspector() + return () => { + cleanup1?.() + cleanup2?.() + } + }, []) + + return ( + + + + ) +} + +export default App diff --git a/apps/wireframe-renderer-web/src/components/auth-router.tsx b/apps/wireframe-renderer-web/src/components/auth-router.tsx new file mode 100644 index 0000000..2baa0b4 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/auth-router.tsx @@ -0,0 +1,70 @@ +import { useEffect, useState, type ReactNode } from 'react' +import { auth } from '@/lib/nvwa' +import { AUTH_REQUIRED } from '@/lib/config' +import redirectToLogin from '@/custom/redirect-to-login' + +type AuthRouterProps = { + children: ReactNode +} + +/** + * 认证路由守卫组件 + * 根据 AUTH_REQUIRED 配置决定是否需要登录 + * + * 行为说明: + * - 当 AUTH_REQUIRED=true 时:检查登录状态,未登录则跳转到登录页 + * - 当 AUTH_REQUIRED=false 时:不检查登录,直接渲染子组件 + */ +export function AuthRouter({ children }: AuthRouterProps) { + const [isLoading, setIsLoading] = useState(true) + const [isAuthenticated, setIsAuthenticated] = useState(null) + + useEffect(() => { + checkAuth() + }, []) + + const checkAuth = async () => { + // 如果不需要认证,直接通过 + if (!AUTH_REQUIRED) { + setIsAuthenticated(true) + setIsLoading(false) + return + } + + // 需要认证时,检查登录状态 + try { + const currentUser = await auth.currentUser() + if (currentUser) { + setIsAuthenticated(true) + } else { + // 未登录,跳转到登录页 + redirectToLogin() + return + } + } catch (error) { + // 获取用户信息失败,跳转到登录页 + redirectToLogin() + return + } finally { + setIsLoading(false) + } + } + + // 加载中状态 + if (isLoading) { + return ( +
+
加载中...
+
+ ) + } + + // 如果需要认证但未登录,redirectToLogin 会处理跳转,这里返回 null + if (AUTH_REQUIRED && !isAuthenticated) { + return null + } + + // 已认证或不需要认证,渲染子组件 + return <>{children} +} + diff --git a/apps/wireframe-renderer-web/src/components/layout.tsx b/apps/wireframe-renderer-web/src/components/layout.tsx new file mode 100644 index 0000000..c90a505 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/layout.tsx @@ -0,0 +1,39 @@ +import { useRoutes } from 'react-router-dom' + +// vite-plugin-pages 会自动生成路由配置 +// @ts-expect-error - 动态导入,类型会在构建时生成 +import autoRoutes from "~react-pages" + +/** + * Layout 组件 + * + * 这个组件会包裹所有需要 layout 的页面(除了 /user/login 和 /user/register) + * 它使用 vite-plugin-pages 生成的路由配置来根据 pathname 动态渲染对应的页面组件 + * + * 用户可以在生成代码时自定义这个 Layout,添加侧边栏、导航栏等公共布局元素 + */ +const noLayoutRoutes = [ + '/user/login', + '/user/register', +] + +export function Layout() { + // 过滤掉登录和注册页面,因为它们不应该被 layout 包裹 + const layoutRoutes = autoRoutes.filter( + (route: any) => !noLayoutRoutes.includes(route.path) + ) + + // 使用 useRoutes 来渲染当前路径对应的组件 + const element = useRoutes(layoutRoutes) + + return ( +
+ {/* 这里可以添加侧边栏、导航栏等公共布局元素 */} + {/* 用户可以在生成代码时自定义这个 Layout */} + {element} +
+ ) +} + + + diff --git a/apps/wireframe-renderer-web/src/components/ui/accordion.tsx b/apps/wireframe-renderer-web/src/components/ui/accordion.tsx new file mode 100644 index 0000000..d21b65f --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/accordion.tsx @@ -0,0 +1,64 @@ +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDownIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Accordion({ + ...props +}: React.ComponentProps) { + return +} + +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + + ) +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + +
{children}
+
+ ) +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/apps/wireframe-renderer-web/src/components/ui/alert-dialog.tsx b/apps/wireframe-renderer-web/src/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..935eecf --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/alert-dialog.tsx @@ -0,0 +1,155 @@ +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +function AlertDialog({ + ...props +}: React.ComponentProps) { + return +} + +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + ) +} + +function AlertDialogHeader({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/apps/wireframe-renderer-web/src/components/ui/alert.tsx b/apps/wireframe-renderer-web/src/components/ui/alert.tsx new file mode 100644 index 0000000..1421354 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/alert.tsx @@ -0,0 +1,66 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", + { + variants: { + variant: { + default: "bg-card text-card-foreground", + destructive: + "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDescription({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Alert, AlertTitle, AlertDescription } diff --git a/apps/wireframe-renderer-web/src/components/ui/aspect-ratio.tsx b/apps/wireframe-renderer-web/src/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..3df3fd0 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/aspect-ratio.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +function AspectRatio({ + ...props +}: React.ComponentProps) { + return +} + +export { AspectRatio } diff --git a/apps/wireframe-renderer-web/src/components/ui/avatar.tsx b/apps/wireframe-renderer-web/src/components/ui/avatar.tsx new file mode 100644 index 0000000..b7224f0 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/avatar.tsx @@ -0,0 +1,51 @@ +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +function Avatar({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/apps/wireframe-renderer-web/src/components/ui/badge.tsx b/apps/wireframe-renderer-web/src/components/ui/badge.tsx new file mode 100644 index 0000000..0205413 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/badge.tsx @@ -0,0 +1,46 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + secondary: + "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + destructive: + "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Badge({ + className, + variant, + asChild = false, + ...props +}: React.ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : "span" + + return ( + + ) +} + +export { Badge, badgeVariants } diff --git a/apps/wireframe-renderer-web/src/components/ui/breadcrumb.tsx b/apps/wireframe-renderer-web/src/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..eb88f32 --- /dev/null +++ b/apps/wireframe-renderer-web/src/components/ui/breadcrumb.tsx @@ -0,0 +1,109 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return