From 28a3b7fd9adf8d415ba496b0c045f19155069276 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Tue, 20 May 2025 17:42:24 -0700 Subject: [PATCH 01/27] gen by ai --- .gitignore | 1 + README.md | 50 ++ components.json | 21 + eslint.config.js | 28 + index.html | 13 + package.json | 79 +++ postcss.config.js | 6 + public/anomaly-detection.jpg | 26 + public/customer-360.jpg | 26 + public/fraud-prevention.jpg | 26 + public/log-analytics.jpg | 26 + public/stream-dashboard.jpg | 26 + public/supply-chain.jpg | 26 + public/vite.svg | 1 + src/App.css | 0 src/App.tsx | 83 +++ src/assets/react.svg | 1 + src/components/demos/DemoCard.tsx | 52 ++ src/components/demos/DemoDetail.tsx | 94 ++++ src/components/demos/DemoGrid.tsx | 46 ++ src/components/layout/Footer.tsx | 30 + src/components/layout/Header.tsx | 35 ++ src/components/ui/accordion.tsx | 55 ++ src/components/ui/alert-dialog.tsx | 139 +++++ src/components/ui/alert.tsx | 59 ++ src/components/ui/aspect-ratio.tsx | 5 + src/components/ui/avatar.tsx | 50 ++ src/components/ui/badge.tsx | 36 ++ src/components/ui/breadcrumb.tsx | 115 ++++ src/components/ui/button.tsx | 57 ++ src/components/ui/calendar.tsx | 74 +++ src/components/ui/card.tsx | 76 +++ src/components/ui/carousel.tsx | 260 +++++++++ src/components/ui/chart.tsx | 365 ++++++++++++ src/components/ui/checkbox.tsx | 28 + src/components/ui/collapsible.tsx | 11 + src/components/ui/command.tsx | 151 +++++ src/components/ui/context-menu.tsx | 198 +++++++ src/components/ui/dialog.tsx | 122 +++++ src/components/ui/drawer.tsx | 118 ++++ src/components/ui/dropdown-menu.tsx | 199 +++++++ src/components/ui/form.tsx | 178 ++++++ src/components/ui/hover-card.tsx | 29 + src/components/ui/input-otp.tsx | 69 +++ src/components/ui/input.tsx | 22 + src/components/ui/label.tsx | 24 + src/components/ui/menubar.tsx | 236 ++++++++ src/components/ui/navigation-menu.tsx | 128 +++++ src/components/ui/pagination.tsx | 117 ++++ src/components/ui/popover.tsx | 31 ++ src/components/ui/progress.tsx | 28 + src/components/ui/radio-group.tsx | 42 ++ src/components/ui/resizable.tsx | 45 ++ src/components/ui/scroll-area.tsx | 46 ++ src/components/ui/select.tsx | 159 ++++++ src/components/ui/separator.tsx | 29 + src/components/ui/sheet.tsx | 140 +++++ src/components/ui/sidebar.tsx | 761 ++++++++++++++++++++++++++ src/components/ui/skeleton.tsx | 15 + src/components/ui/slider.tsx | 26 + src/components/ui/sonner.tsx | 31 ++ src/components/ui/switch.tsx | 27 + src/components/ui/table.tsx | 120 ++++ src/components/ui/tabs.tsx | 53 ++ src/components/ui/textarea.tsx | 22 + src/components/ui/toast.tsx | 127 +++++ src/components/ui/toaster.tsx | 33 ++ src/components/ui/toggle-group.tsx | 59 ++ src/components/ui/toggle.tsx | 45 ++ src/components/ui/tooltip.tsx | 32 ++ src/data/demos.ts | 194 +++++++ src/hooks/use-mobile.tsx | 19 + src/hooks/use-toast.ts | 194 +++++++ src/index.css | 106 ++++ src/lib/utils.ts | 6 + src/main.tsx | 10 + src/vite-env.d.ts | 1 + tailwind.config.js | 94 ++++ tsconfig.app.json | 33 ++ tsconfig.json | 18 + tsconfig.node.json | 24 + vite.config.ts | 13 + 82 files changed, 6200 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 components.json create mode 100644 eslint.config.js create mode 100644 index.html create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 public/anomaly-detection.jpg create mode 100644 public/customer-360.jpg create mode 100644 public/fraud-prevention.jpg create mode 100644 public/log-analytics.jpg create mode 100644 public/stream-dashboard.jpg create mode 100644 public/supply-chain.jpg create mode 100644 public/vite.svg create mode 100644 src/App.css create mode 100644 src/App.tsx create mode 100644 src/assets/react.svg create mode 100644 src/components/demos/DemoCard.tsx create mode 100644 src/components/demos/DemoDetail.tsx create mode 100644 src/components/demos/DemoGrid.tsx create mode 100644 src/components/layout/Footer.tsx create mode 100644 src/components/layout/Header.tsx create mode 100644 src/components/ui/accordion.tsx create mode 100644 src/components/ui/alert-dialog.tsx create mode 100644 src/components/ui/alert.tsx create mode 100644 src/components/ui/aspect-ratio.tsx create mode 100644 src/components/ui/avatar.tsx create mode 100644 src/components/ui/badge.tsx create mode 100644 src/components/ui/breadcrumb.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/calendar.tsx create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/carousel.tsx create mode 100644 src/components/ui/chart.tsx create mode 100644 src/components/ui/checkbox.tsx create mode 100644 src/components/ui/collapsible.tsx create mode 100644 src/components/ui/command.tsx create mode 100644 src/components/ui/context-menu.tsx create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/drawer.tsx create mode 100644 src/components/ui/dropdown-menu.tsx create mode 100644 src/components/ui/form.tsx create mode 100644 src/components/ui/hover-card.tsx create mode 100644 src/components/ui/input-otp.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/label.tsx create mode 100644 src/components/ui/menubar.tsx create mode 100644 src/components/ui/navigation-menu.tsx create mode 100644 src/components/ui/pagination.tsx create mode 100644 src/components/ui/popover.tsx create mode 100644 src/components/ui/progress.tsx create mode 100644 src/components/ui/radio-group.tsx create mode 100644 src/components/ui/resizable.tsx create mode 100644 src/components/ui/scroll-area.tsx create mode 100644 src/components/ui/select.tsx create mode 100644 src/components/ui/separator.tsx create mode 100644 src/components/ui/sheet.tsx create mode 100644 src/components/ui/sidebar.tsx create mode 100644 src/components/ui/skeleton.tsx create mode 100644 src/components/ui/slider.tsx create mode 100644 src/components/ui/sonner.tsx create mode 100644 src/components/ui/switch.tsx create mode 100644 src/components/ui/table.tsx create mode 100644 src/components/ui/tabs.tsx create mode 100644 src/components/ui/textarea.tsx create mode 100644 src/components/ui/toast.tsx create mode 100644 src/components/ui/toaster.tsx create mode 100644 src/components/ui/toggle-group.tsx create mode 100644 src/components/ui/toggle.tsx create mode 100644 src/components/ui/tooltip.tsx create mode 100644 src/data/demos.ts create mode 100644 src/hooks/use-mobile.tsx create mode 100644 src/hooks/use-toast.ts create mode 100644 src/index.css create mode 100644 src/lib/utils.ts create mode 100644 src/main.tsx create mode 100644 src/vite-env.d.ts create mode 100644 tailwind.config.js create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..74872fd --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default tseslint.config({ + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` +- Optionally add `...tseslint.configs.stylisticTypeChecked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: + +```js +// eslint.config.js +import react from 'eslint-plugin-react' + +export default tseslint.config({ + // Set the react version + settings: { react: { version: '18.3' } }, + plugins: { + // Add the react plugin + react, + }, + rules: { + // other rules... + // Enable its recommended rules + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + }, +}) +``` diff --git a/components.json b/components.json new file mode 100644 index 0000000..78cd18f --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "zinc", + "cssVariables": false, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..092408a --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,28 @@ +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' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/index.html b/index.html new file mode 100644 index 0000000..63d3894 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + timeplus-demo-site + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..2b870c8 --- /dev/null +++ b/package.json @@ -0,0 +1,79 @@ +{ + "name": "react_repo", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@hookform/resolvers": "^3.10.0", + "@radix-ui/react-accordion": "^1.2.2", + "@radix-ui/react-alert-dialog": "^1.1.4", + "@radix-ui/react-aspect-ratio": "^1.1.1", + "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-checkbox": "^1.1.3", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-context-menu": "^2.2.4", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-dropdown-menu": "^2.1.4", + "@radix-ui/react-hover-card": "^1.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-menubar": "^1.1.4", + "@radix-ui/react-navigation-menu": "^1.2.3", + "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-progress": "^1.1.1", + "@radix-ui/react-radio-group": "^1.2.2", + "@radix-ui/react-scroll-area": "^1.2.2", + "@radix-ui/react-select": "^2.1.4", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slider": "^1.2.2", + "@radix-ui/react-slot": "^1.1.1", + "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.2", + "@radix-ui/react-toast": "^1.2.4", + "@radix-ui/react-toggle": "^1.1.1", + "@radix-ui/react-toggle-group": "^1.1.1", + "@radix-ui/react-tooltip": "^1.1.6", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "1.0.0", + "date-fns": "^4.1.0", + "embla-carousel-react": "^8.5.2", + "input-otp": "^1.4.2", + "lucide-react": "^0.364.0", + "next-themes": "^0.4.4", + "react": "^18.3.1", + "react-day-picker": "8.10.1", + "react-dom": "^18.3.1", + "react-hook-form": "^7.54.2", + "react-markdown": "^10.1.0", + "react-resizable-panels": "^2.1.7", + "recharts": "^2.12.4", + "sonner": "^1.7.2", + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "vaul": "^1.1.2", + "zod": "^3.24.1" + }, + "devDependencies": { + "@eslint/js": "^9.15.0", + "@types/node": "^22.10.7", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "10.4.20", + "eslint": "^9.15.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.12.0", + "postcss": "8.4.49", + "tailwindcss": "v3.4.16", + "typescript": "~5.6.2", + "typescript-eslint": "^8.15.0", + "vite": "^6.0.1" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/public/anomaly-detection.jpg b/public/anomaly-detection.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/anomaly-detection.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/customer-360.jpg b/public/customer-360.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/customer-360.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/fraud-prevention.jpg b/public/fraud-prevention.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/fraud-prevention.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/log-analytics.jpg b/public/log-analytics.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/log-analytics.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/stream-dashboard.jpg b/public/stream-dashboard.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/stream-dashboard.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/supply-chain.jpg b/public/supply-chain.jpg new file mode 100644 index 0000000..6cd9750 --- /dev/null +++ b/public/supply-chain.jpg @@ -0,0 +1,26 @@ + + + + + + Application Error + + + + + + \ No newline at end of file diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..e69de29 diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..2da1e01 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,83 @@ +import React, { useState } from 'react'; +import Header from './components/layout/Header'; +import Footer from './components/layout/Footer'; +import DemoGrid from './components/demos/DemoGrid'; +import DemoDetail from './components/demos/DemoDetail'; +import { demos } from './data/demos'; + +const App: React.FC = () => { + const [selectedDemoId, setSelectedDemoId] = useState(null); + const [searchQuery, setSearchQuery] = useState(''); + const [selectedCategory, setSelectedCategory] = useState(undefined); + + const selectedDemo = selectedDemoId ? demos.find(demo => demo.id === selectedDemoId) : null; + + // Get unique categories from demos + const categories = Array.from(new Set(demos.map(demo => demo.category))); + + const handleDemoClick = (id: string) => { + setSelectedDemoId(id); + window.scrollTo(0, 0); + }; + + const handleBackClick = () => { + setSelectedDemoId(null); + }; + + return ( +
+
+ +
+ {selectedDemo ? ( + + ) : ( + <> +
+

Timeplus Product Demos

+

+ Explore our interactive demos showcasing real-time data processing, analytics, and streaming solutions. +

+
+ +
+
+ setSearchQuery(e.target.value)} + /> +
+ +
+ +
+
+ + + + )} +
+ +
+
+ ); +}; + +export default App; diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/demos/DemoCard.tsx b/src/components/demos/DemoCard.tsx new file mode 100644 index 0000000..19b3fb0 --- /dev/null +++ b/src/components/demos/DemoCard.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { Demo } from '../../data/demos'; + +interface DemoCardProps { + demo: Demo; + onClick: (id: string) => void; +} + +const DemoCard: React.FC = ({ demo, onClick }) => { + return ( +
onClick(demo.id)} + > +
+ {`${demo.title} +
+ + {demo.category} + +
+
+ +
+

{demo.title}

+

{demo.subtitle}

+ +
+ {demo.keywords.slice(0, 3).map((keyword, index) => ( + + {keyword} + + ))} + {demo.keywords.length > 3 && ( + + +{demo.keywords.length - 3} more + + )} +
+
+
+ ); +}; + +export default DemoCard; diff --git a/src/components/demos/DemoDetail.tsx b/src/components/demos/DemoDetail.tsx new file mode 100644 index 0000000..49610e3 --- /dev/null +++ b/src/components/demos/DemoDetail.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import ReactMarkdown from 'react-markdown'; +import { Demo } from '../../data/demos'; + +interface DemoDetailProps { + demo: Demo; + onBack: () => void; +} + +const DemoDetail: React.FC = ({ demo, onBack }) => { + return ( +
+
+ {`${demo.title} +
+
+ + + {demo.category} + +

{demo.title}

+

{demo.subtitle}

+
+
+ +
+
+ {demo.keywords.map((keyword, index) => ( + + {keyword} + + ))} +
+ +
+

Problem Statement

+

{demo.problemStatement}

+
+ +
+

Context

+
+ + {demo.context} + +
+
+ +
+

Key Steps

+
    + {demo.steps.map((step, index) => ( +
  1. {step}
  2. + ))} +
+
+ +
+

Demo Links

+
+ {demo.demoLinks.map((link, index) => ( + +

{link.title}

+ {link.description && ( +

{link.description}

+ )} +
+ ))} +
+
+
+
+ ); +}; + +export default DemoDetail; diff --git a/src/components/demos/DemoGrid.tsx b/src/components/demos/DemoGrid.tsx new file mode 100644 index 0000000..88b57e8 --- /dev/null +++ b/src/components/demos/DemoGrid.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import DemoCard from './DemoCard'; +import { Demo } from '../../data/demos'; + +interface DemoGridProps { + demos: Demo[]; + onDemoClick: (id: string) => void; + selectedCategory?: string; + searchQuery?: string; +} + +const DemoGrid: React.FC = ({ + demos, + onDemoClick, + selectedCategory, + searchQuery +}) => { + // Filter demos based on category and search query + const filteredDemos = demos.filter(demo => { + const matchesCategory = !selectedCategory || demo.category === selectedCategory; + const matchesSearch = !searchQuery || + demo.title.toLowerCase().includes(searchQuery.toLowerCase()) || + demo.subtitle.toLowerCase().includes(searchQuery.toLowerCase()) || + demo.keywords.some(keyword => keyword.toLowerCase().includes(searchQuery.toLowerCase())); + + return matchesCategory && matchesSearch; + }); + + return ( +
+ {filteredDemos.length > 0 ? ( + filteredDemos.map((demo) => ( + + )) + ) : ( +
+

+ No demos found matching your criteria. Try adjusting your filters. +

+
+ )} +
+ ); +}; + +export default DemoGrid; diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx new file mode 100644 index 0000000..f219ea2 --- /dev/null +++ b/src/components/layout/Footer.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +const Footer: React.FC = () => { + return ( + + ); +}; + +export default Footer; diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx new file mode 100644 index 0000000..7aeaeee --- /dev/null +++ b/src/components/layout/Header.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +const Header: React.FC = () => { + return ( +
+
+
+
+
+ T+ +
+
+

Timeplus Demos

+
+ + +
+
+ ); +}; + +export default Header; diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx new file mode 100644 index 0000000..5f67b5c --- /dev/null +++ b/src/components/ui/accordion.tsx @@ -0,0 +1,55 @@ +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..4224e8a --- /dev/null +++ b/src/components/ui/alert-dialog.tsx @@ -0,0 +1,139 @@ +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" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx new file mode 100644 index 0000000..218f631 --- /dev/null +++ b/src/components/ui/alert.tsx @@ -0,0 +1,59 @@ +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 border-zinc-200 px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-zinc-950 [&>svg~*]:pl-7 dark:border-zinc-800 dark:[&>svg]:text-zinc-50", + { + variants: { + variant: { + default: "bg-white text-zinc-950 dark:bg-zinc-950 dark:text-zinc-50", + destructive: + "border-red-500/50 text-red-500 dark:border-red-500 [&>svg]:text-red-500 dark:border-red-900/50 dark:text-red-900 dark:dark:border-red-900 dark:[&>svg]:text-red-900", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/src/components/ui/aspect-ratio.tsx b/src/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..c4abbf3 --- /dev/null +++ b/src/components/ui/aspect-ratio.tsx @@ -0,0 +1,5 @@ +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..5e76ffe --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx new file mode 100644 index 0000000..120c5b5 --- /dev/null +++ b/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-md border border-zinc-200 px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-zinc-950 focus:ring-offset-2 dark:border-zinc-800 dark:focus:ring-zinc-300", + { + variants: { + variant: { + default: + "border-transparent bg-zinc-900 text-zinc-50 shadow hover:bg-zinc-900/80 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/80", + secondary: + "border-transparent bg-zinc-100 text-zinc-900 hover:bg-zinc-100/80 dark:bg-zinc-800 dark:text-zinc-50 dark:hover:bg-zinc-800/80", + destructive: + "border-transparent bg-red-500 text-zinc-50 shadow hover:bg-red-500/80 dark:bg-red-900 dark:text-zinc-50 dark:hover:bg-red-900/80", + outline: "text-zinc-950 dark:text-zinc-50", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/src/components/ui/breadcrumb.tsx b/src/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..a00c8e0 --- /dev/null +++ b/src/components/ui/breadcrumb.tsx @@ -0,0 +1,115 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Breadcrumb = React.forwardRef< + HTMLElement, + React.ComponentPropsWithoutRef<"nav"> & { + separator?: React.ReactNode + } +>(({ ...props }, ref) =>