├── src ├── vite-env.d.ts ├── components │ └── ui │ │ ├── use-toast.ts │ │ ├── aspect-ratio.tsx │ │ ├── skeleton.tsx │ │ ├── collapsible.tsx │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── input.tsx │ │ ├── separator.tsx │ │ ├── progress.tsx │ │ ├── toaster.tsx │ │ ├── sonner.tsx │ │ ├── checkbox.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── tooltip.tsx │ │ ├── badge.tsx │ │ ├── hover-card.tsx │ │ ├── popover.tsx │ │ ├── avatar.tsx │ │ ├── toggle.tsx │ │ ├── radio-group.tsx │ │ ├── alert.tsx │ │ ├── scroll-area.tsx │ │ ├── resizable.tsx │ │ ├── toggle-group.tsx │ │ ├── tabs.tsx │ │ ├── button.tsx │ │ ├── accordion.tsx │ │ ├── card.tsx │ │ ├── input-otp.tsx │ │ ├── calendar.tsx │ │ ├── breadcrumb.tsx │ │ ├── pagination.tsx │ │ ├── table.tsx │ │ ├── drawer.tsx │ │ ├── dialog.tsx │ │ ├── sheet.tsx │ │ ├── form.tsx │ │ ├── alert-dialog.tsx │ │ ├── toast.tsx │ │ ├── command.tsx │ │ ├── navigation-menu.tsx │ │ ├── select.tsx │ │ ├── carousel.tsx │ │ ├── context-menu.tsx │ │ ├── dropdown-menu.tsx │ │ ├── menubar.tsx │ │ └── multi-select.tsx ├── main.tsx ├── lib │ └── utils.ts ├── pages │ ├── Index.tsx │ └── NotFound.tsx ├── hooks │ ├── use-mobile.tsx │ └── use-toast.ts ├── App.css ├── App.tsx ├── index.css └── aliases.d.ts ├── bun.lockb ├── public ├── favicon.ico ├── robots.txt └── placeholder.svg ├── postcss.config.js ├── docker-compose.yml ├── types.ts ├── .dockerignore ├── metadata.json ├── bunfig.toml ├── .gitignore ├── install.json ├── components ├── Footer.tsx ├── icons │ ├── CheckIcon.tsx │ ├── BrknLogo.tsx │ ├── SearchIcon.tsx │ ├── ClipboardIcon.tsx │ ├── ImageIcon.tsx │ ├── JsonIcon.tsx │ ├── LightbulbIcon.tsx │ ├── FilmIcon.tsx │ ├── ClapperboardIcon.tsx │ ├── SparklesIcon.tsx │ └── BrainIcon.tsx ├── Header.tsx ├── Loader.tsx ├── IdeaCard.tsx └── PromptCard.tsx ├── index.tsx ├── pinokio.js ├── nginx.conf ├── components.json ├── tsconfig.node.json ├── tsconfig.json ├── Dockerfile ├── start.json ├── start-prod.json ├── tsconfig.app.json ├── vite.config.ts ├── eslint.config.js ├── INSTALL.md ├── index.html ├── tailwind.config.ts ├── package.json ├── start-ui.bat ├── LICENSE └── install-windows.bat /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUVoize/wan22-brkn-prompt-helper/HEAD/bun.lockb -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUVoize/wan22-brkn-prompt-helper/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/components/ui/use-toast.ts: -------------------------------------------------------------------------------- 1 | import { useToast, toast } from "../../hooks/use-toast"; 2 | 3 | export { useToast, toast }; 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | app: 4 | build: . 5 | ports: 6 | - "8080:80" 7 | restart: unless-stopped 8 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client' 2 | import App from './App.tsx' 3 | import './index.css' 4 | 5 | createRoot(document.getElementById("root")!).render(); 6 | -------------------------------------------------------------------------------- /src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" 2 | 3 | const AspectRatio = AspectRatioPrimitive.Root 4 | 5 | export { AspectRatio } 6 | -------------------------------------------------------------------------------- /types.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface VideoPrompt { 3 | title: string; 4 | prompt: string; 5 | } 6 | 7 | export interface Idea { 8 | title: string; 9 | description: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/Index.tsx: -------------------------------------------------------------------------------- 1 | // Import the main app component from the root directory 2 | import MainApp from '../../App'; 3 | 4 | const Index = () => { 5 | return ; 6 | }; 7 | 8 | export default Index; 9 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: Googlebot 2 | Allow: / 3 | 4 | User-agent: Bingbot 5 | Allow: / 6 | 7 | User-agent: Twitterbot 8 | Allow: / 9 | 10 | User-agent: facebookexternalhit 11 | Allow: / 12 | 13 | User-agent: * 14 | Allow: / 15 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Ignore files not needed in the Docker build context 2 | node_modules 3 | npm-debug.log 4 | .git 5 | .gitignore 6 | .vscode 7 | .DS_Store 8 | coverage 9 | .tmp 10 | dist 11 | 12 | # Local env or editor files 13 | *.local 14 | *.swp 15 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WAN 2.2 - BRKN AI Prompt Generator", 3 | "description": "An AI-powered tool by BRKN to generate detailed, creative video prompts. Kickstart your video creation process.", 4 | "requestFramePermissions": [], 5 | "prompt": "" 6 | } -------------------------------------------------------------------------------- /bunfig.toml: -------------------------------------------------------------------------------- 1 | [install] 2 | # Override problematic dependencies 3 | [install.scopes."@radix-ui"] 4 | # Map react-sheet to react-dialog since they're compatible 5 | "react-sheet" = "@radix-ui/react-dialog@^1.0.5" 6 | 7 | [install.scopes."lovable"] 8 | # Remove lovable-tagger dependency 9 | "tagger" = "@types/node@^20.4.0" -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "../../lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 2 | 3 | const Collapsible = CollapsiblePrimitive.Root 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 10 | -------------------------------------------------------------------------------- /install.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": [ 3 | { 4 | "method": "shell.run", 5 | "params": { 6 | "message": "npm ci || npm install" 7 | } 8 | }, 9 | { 10 | "method": "notify", 11 | "params": { 12 | "html": "Install complete

Click here to start the app!", 13 | "href": "./start.json" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Footer: React.FC = () => { 4 | return ( 5 |
6 |
7 |

A BRKN TRIBE Creation. Powered by the Gemini API.

8 |
9 |
10 | ); 11 | }; 12 | 13 | export default Footer; -------------------------------------------------------------------------------- /index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | 5 | const rootElement = document.getElementById('root'); 6 | if (!rootElement) { 7 | throw new Error("Could not find root element to mount to"); 8 | } 9 | 10 | const root = ReactDOM.createRoot(rootElement); 11 | root.render( 12 | 13 | 14 | 15 | ); -------------------------------------------------------------------------------- /pinokio.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | menu: [ 3 | { 4 | html: " Install", 5 | href: "install.json", 6 | }, 7 | { 8 | html: " Start (dev :8080)", 9 | href: "start.json", 10 | }, 11 | { 12 | html: " Start (prod)", 13 | href: "start-prod.json", 14 | }, 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /components/icons/CheckIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const CheckIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | ); 8 | 9 | export default CheckIcon; 10 | -------------------------------------------------------------------------------- /components/icons/BrknLogo.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // The previous base64 string was too large and crashed the application at runtime. 4 | // This is now a placeholder. Consider loading the logo from a file in the public directory. 5 | const BrknLogo: React.FC> = (props) => { 6 | // Returning null or a simple placeholder to avoid the crash. 7 | return null; 8 | }; 9 | 10 | export default BrknLogo; -------------------------------------------------------------------------------- /components/icons/SearchIcon.tsx: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | 4 | const SearchIcon: React.FC> = (props) => ( 5 | 6 | 7 | 8 | 9 | ); 10 | 11 | export default SearchIcon; 12 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name _; 4 | 5 | root /usr/share/nginx/html; 6 | index index.html; 7 | 8 | # SPA routing 9 | location / { 10 | try_files $uri /index.html; 11 | } 12 | 13 | # Static assets caching 14 | location /assets/ { 15 | try_files $uri =404; 16 | access_log off; 17 | expires 1y; 18 | } 19 | 20 | gzip on; 21 | gzip_types text/plain text/css application/json application/javascript application/octet-stream image/svg+xml; 22 | } 23 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/index.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /components/icons/ClipboardIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ClipboardIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | 8 | ); 9 | 10 | export default ClipboardIcon; 11 | -------------------------------------------------------------------------------- /components/icons/ImageIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ImageIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | ); 10 | 11 | export default ImageIcon; 12 | -------------------------------------------------------------------------------- /components/icons/JsonIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const JsonIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | 8 | ); 9 | 10 | export default JsonIcon; -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["ES2023"], 5 | "module": "ESNext", 6 | "skipLibCheck": true, 7 | 8 | /* Bundler mode */ 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "isolatedModules": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | 15 | /* Linting */ 16 | "strict": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noFallthroughCasesInSwitch": true 20 | }, 21 | "include": ["vite.config.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /components/icons/LightbulbIcon.tsx: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | 4 | const LightbulbIcon: React.FC> = (props) => ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | 12 | export default LightbulbIcon; 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "experimentalDecorators": true, 5 | "useDefineForClassFields": false, 6 | "module": "ESNext", 7 | "lib": [ 8 | "ES2022", 9 | "DOM", 10 | "DOM.Iterable" 11 | ], 12 | "skipLibCheck": true, 13 | "moduleResolution": "bundler", 14 | "isolatedModules": true, 15 | "moduleDetection": "force", 16 | "allowJs": true, 17 | "jsx": "react-jsx", 18 | "paths": { 19 | "@/*": [ 20 | "./*" 21 | ] 22 | }, 23 | "allowImportingTsExtensions": true, 24 | "noEmit": true 25 | } 26 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | # Build stage 4 | FROM node:20-alpine AS builder 5 | WORKDIR /app 6 | 7 | # Install dependencies 8 | COPY package*.json ./ 9 | RUN npm ci 10 | 11 | # Copy source and build 12 | COPY . . 13 | RUN npm run build 14 | 15 | # Runtime stage using Nginx to serve static files 16 | FROM nginx:alpine AS runner 17 | 18 | # Clear default content and copy build 19 | RUN rm -rf /usr/share/nginx/html/* 20 | COPY --from=builder /app/dist /usr/share/nginx/html 21 | 22 | # Nginx config for SPA routing and caching 23 | COPY nginx.conf /etc/nginx/conf.d/default.conf 24 | 25 | EXPOSE 80 26 | CMD ["nginx", "-g", "daemon off;"] 27 | -------------------------------------------------------------------------------- /src/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /components/icons/FilmIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const FilmIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | 16 | export default FilmIcon; 17 | -------------------------------------------------------------------------------- /start.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": [ 3 | { 4 | "method": "shell.start", 5 | "params": { 6 | "path": "." 7 | } 8 | }, 9 | { 10 | "method": "shell.enter", 11 | "params": { 12 | "message": "npm run dev -- --port 8080", 13 | "on": [ 14 | { 15 | "event": "/(http:\\S.+)/", 16 | "return": "{{event.matches[0][1]}}" 17 | } 18 | ] 19 | }, 20 | "notify": true 21 | }, 22 | { 23 | "method": "browser.open", 24 | "params": { 25 | "uri": "{{input}}", 26 | "target": "_blank" 27 | } 28 | }, 29 | { 30 | "method": "process.wait" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /start-prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": [ 3 | { 4 | "method": "shell.start", 5 | "params": { 6 | "path": "." 7 | } 8 | }, 9 | { 10 | "method": "shell.enter", 11 | "params": { 12 | "message": "npm run build && npm run preview", 13 | "on": [ 14 | { 15 | "event": "/(http:\\S.+)/", 16 | "return": "{{event.matches[0][1]}}" 17 | } 18 | ] 19 | }, 20 | "notify": true 21 | }, 22 | { 23 | "method": "browser.open", 24 | "params": { 25 | "uri": "{{input}}", 26 | "target": "_blank" 27 | } 28 | }, 29 | { 30 | "method": "process.wait" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Header: React.FC = () => { 4 | return ( 5 |
6 |
7 |
8 |

9 | WAN 2.2 10 |

11 |

12 | BRKN AI Prompt Generator 13 |

14 |
15 |
16 |
17 | ); 18 | }; 19 | 20 | export default Header; -------------------------------------------------------------------------------- /components/icons/ClapperboardIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ClapperboardIcon: React.FC> = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | 16 | export default ClapperboardIcon; 17 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": false, 19 | "noUnusedLocals": false, 20 | "noUnusedParameters": false, 21 | "noImplicitAny": false, 22 | "noFallthroughCasesInSwitch": false, 23 | 24 | "baseUrl": ".", 25 | "paths": { 26 | "@/*": ["./src/*"] 27 | } 28 | }, 29 | "include": ["src"] 30 | } 31 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { defineConfig, loadEnv } from 'vite'; 3 | import react from '@vitejs/plugin-react-swc'; 4 | import { componentTagger } from "lovable-tagger"; 5 | 6 | export default defineConfig(({ mode }) => { 7 | const env = loadEnv(mode, '.', ''); 8 | return { 9 | server: { 10 | host: "::", 11 | port: 8080, 12 | }, 13 | plugins: [ 14 | react(), 15 | mode === 'development' && componentTagger(), 16 | ].filter(Boolean), 17 | resolve: { 18 | alias: { 19 | "@": path.resolve(__dirname, "./src"), 20 | }, 21 | }, 22 | define: { 23 | 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY), 24 | 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY), 25 | }, 26 | }; 27 | }); -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "../../lib/utils" 6 | 7 | const labelVariants = cva( 8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 9 | ) 10 | 11 | const Label = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef & 14 | VariantProps 15 | >(({ className, ...props }, ref) => ( 16 | 21 | )) 22 | Label.displayName = LabelPrimitive.Root.displayName 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /src/pages/NotFound.tsx: -------------------------------------------------------------------------------- 1 | import { useLocation } from "react-router-dom"; 2 | import { useEffect } from "react"; 3 | 4 | const NotFound = () => { 5 | const location = useLocation(); 6 | 7 | useEffect(() => { 8 | console.error( 9 | "404 Error: User attempted to access non-existent route:", 10 | location.pathname 11 | ); 12 | }, [location.pathname]); 13 | 14 | return ( 15 |
16 |
17 |

404

18 |

Oops! Page not found

19 | 20 | Return to Home 21 | 22 |
23 |
24 | ); 25 | }; 26 | 27 | export default NotFound; 28 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "../../lib/utils" 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |