James McCool commited on
Commit
b967c2c
·
1 Parent(s): 68b07dd

Initial commit from LLM generated shadcn table logic

Browse files
package-lock.json ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "react-template",
3
+ "version": "0.1.0",
4
+ "lockfileVersion": 1,
5
+ "requires": true,
6
+ "dependencies": {
7
+ "@radix-ui/react-compose-refs": {
8
+ "version": "1.1.2",
9
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
10
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="
11
+ },
12
+ "@radix-ui/react-slot": {
13
+ "version": "1.2.3",
14
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
15
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
16
+ "requires": {
17
+ "@radix-ui/react-compose-refs": "1.1.2"
18
+ }
19
+ },
20
+ "autoprefixer": {
21
+ "version": "10.4.21",
22
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
23
+ "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
24
+ "dev": true,
25
+ "requires": {
26
+ "browserslist": "^4.24.4",
27
+ "caniuse-lite": "^1.0.30001702",
28
+ "fraction.js": "^4.3.7",
29
+ "normalize-range": "^0.1.2",
30
+ "picocolors": "^1.1.1",
31
+ "postcss-value-parser": "^4.2.0"
32
+ }
33
+ },
34
+ "browserslist": {
35
+ "version": "4.25.2",
36
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz",
37
+ "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==",
38
+ "dev": true,
39
+ "requires": {
40
+ "caniuse-lite": "^1.0.30001733",
41
+ "electron-to-chromium": "^1.5.199",
42
+ "node-releases": "^2.0.19",
43
+ "update-browserslist-db": "^1.1.3"
44
+ }
45
+ },
46
+ "caniuse-lite": {
47
+ "version": "1.0.30001734",
48
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz",
49
+ "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==",
50
+ "dev": true
51
+ },
52
+ "class-variance-authority": {
53
+ "version": "0.7.1",
54
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
55
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
56
+ "requires": {
57
+ "clsx": "^2.1.1"
58
+ }
59
+ },
60
+ "clsx": {
61
+ "version": "2.1.1",
62
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
63
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
64
+ },
65
+ "electron-to-chromium": {
66
+ "version": "1.5.200",
67
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz",
68
+ "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==",
69
+ "dev": true
70
+ },
71
+ "escalade": {
72
+ "version": "3.2.0",
73
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
74
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
75
+ "dev": true
76
+ },
77
+ "fraction.js": {
78
+ "version": "4.3.7",
79
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
80
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
81
+ "dev": true
82
+ },
83
+ "lucide-react": {
84
+ "version": "0.539.0",
85
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz",
86
+ "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg=="
87
+ },
88
+ "nanoid": {
89
+ "version": "3.3.11",
90
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
91
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
92
+ "dev": true
93
+ },
94
+ "node-releases": {
95
+ "version": "2.0.19",
96
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
97
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
98
+ "dev": true
99
+ },
100
+ "normalize-range": {
101
+ "version": "0.1.2",
102
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
103
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
104
+ "dev": true
105
+ },
106
+ "picocolors": {
107
+ "version": "1.1.1",
108
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
109
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
110
+ "dev": true
111
+ },
112
+ "postcss": {
113
+ "version": "8.5.6",
114
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
115
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
116
+ "dev": true,
117
+ "requires": {
118
+ "nanoid": "^3.3.11",
119
+ "picocolors": "^1.1.1",
120
+ "source-map-js": "^1.2.1"
121
+ }
122
+ },
123
+ "postcss-value-parser": {
124
+ "version": "4.2.0",
125
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
126
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
127
+ "dev": true
128
+ },
129
+ "source-map-js": {
130
+ "version": "1.2.1",
131
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
132
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
133
+ "dev": true
134
+ },
135
+ "tailwind-merge": {
136
+ "version": "3.3.1",
137
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
138
+ "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="
139
+ },
140
+ "tailwindcss": {
141
+ "version": "4.1.11",
142
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
143
+ "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
144
+ "dev": true
145
+ },
146
+ "tailwindcss-animate": {
147
+ "version": "1.0.7",
148
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
149
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="
150
+ },
151
+ "update-browserslist-db": {
152
+ "version": "1.1.3",
153
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
154
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
155
+ "dev": true,
156
+ "requires": {
157
+ "escalade": "^3.2.0",
158
+ "picocolors": "^1.1.1"
159
+ }
160
+ }
161
+ }
162
+ }
package.json CHANGED
@@ -3,13 +3,19 @@
3
  "version": "0.1.0",
4
  "private": true,
5
  "dependencies": {
 
6
  "@testing-library/dom": "^10.4.0",
7
  "@testing-library/jest-dom": "^6.6.3",
8
  "@testing-library/react": "^16.3.0",
9
  "@testing-library/user-event": "^13.5.0",
 
 
 
10
  "react": "^19.1.0",
11
  "react-dom": "^19.1.0",
12
  "react-scripts": "5.0.1",
 
 
13
  "web-vitals": "^2.1.4"
14
  },
15
  "scripts": {
@@ -35,5 +41,10 @@
35
  "last 1 firefox version",
36
  "last 1 safari version"
37
  ]
 
 
 
 
 
38
  }
39
  }
 
3
  "version": "0.1.0",
4
  "private": true,
5
  "dependencies": {
6
+ "@radix-ui/react-slot": "^1.2.3",
7
  "@testing-library/dom": "^10.4.0",
8
  "@testing-library/jest-dom": "^6.6.3",
9
  "@testing-library/react": "^16.3.0",
10
  "@testing-library/user-event": "^13.5.0",
11
+ "class-variance-authority": "^0.7.1",
12
+ "clsx": "^2.1.1",
13
+ "lucide-react": "^0.539.0",
14
  "react": "^19.1.0",
15
  "react-dom": "^19.1.0",
16
  "react-scripts": "5.0.1",
17
+ "tailwind-merge": "^3.3.1",
18
+ "tailwindcss-animate": "^1.0.7",
19
  "web-vitals": "^2.1.4"
20
  },
21
  "scripts": {
 
41
  "last 1 firefox version",
42
  "last 1 safari version"
43
  ]
44
+ },
45
+ "devDependencies": {
46
+ "autoprefixer": "^10.4.21",
47
+ "postcss": "^8.5.6",
48
+ "tailwindcss": "^4.1.11"
49
  }
50
  }
postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
src/App.js CHANGED
@@ -1,23 +1,24 @@
1
- import logo from './logo.svg';
2
  import './App.css';
 
3
 
4
  function App() {
5
  return (
6
- <div className="App">
7
- <header className="App-header">
8
- <img src={logo} className="App-logo" alt="logo" />
9
- <p>
10
- Edit <code>src/App.js</code> and save to reload.
11
- </p>
12
- <a
13
- className="App-link"
14
- href="https://reactjs.org"
15
- target="_blank"
16
- rel="noopener noreferrer"
17
- >
18
- Learn React
19
- </a>
20
  </header>
 
 
 
 
21
  </div>
22
  );
23
  }
 
1
+ import React from 'react';
2
  import './App.css';
3
+ import DataTable from './components/DataTable';
4
 
5
  function App() {
6
  return (
7
+ <div className="min-h-screen bg-background">
8
+ <header className="border-b bg-card">
9
+ <div className="container mx-auto px-6 py-4">
10
+ <h1 className="text-3xl font-bold text-foreground">
11
+ MongoDB Data Viewer
12
+ </h1>
13
+ <p className="text-muted-foreground mt-2">
14
+ A React app with shadcn/ui styling to display MongoDB data
15
+ </p>
16
+ </div>
 
 
 
 
17
  </header>
18
+
19
+ <main className="container mx-auto py-8">
20
+ <DataTable />
21
+ </main>
22
  </div>
23
  );
24
  }
src/components/DataTable.jsx ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Table, TableHeader, TableBody, TableHead, TableRow, TableCell, TableCaption } from './ui/table';
3
+ import { Button } from './ui/button';
4
+
5
+ const DataTable = () => {
6
+ const [data, setData] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [error, setError] = useState(null);
9
+
10
+ // Mock data for demonstration - replace with actual MongoDB data
11
+ const mockData = [
12
+ { id: 1, name: 'John Doe', email: '[email protected]', role: 'Developer' },
13
+ { id: 2, name: 'Jane Smith', email: '[email protected]', role: 'Designer' },
14
+ { id: 3, name: 'Bob Johnson', email: '[email protected]', role: 'Manager' },
15
+ { id: 4, name: 'Alice Brown', email: '[email protected]', role: 'Developer' },
16
+ { id: 5, name: 'Charlie Wilson', email: '[email protected]', role: 'Designer' },
17
+ ];
18
+
19
+ useEffect(() => {
20
+ // Simulate loading data
21
+ setTimeout(() => {
22
+ setData(mockData);
23
+ setLoading(false);
24
+ }, 1000);
25
+ }, []);
26
+
27
+ const fetchFromMongoDB = async () => {
28
+ try {
29
+ setLoading(true);
30
+ // Replace this with your actual MongoDB connection logic
31
+ // const response = await fetch('/api/data');
32
+ // const result = await response.json();
33
+ // setData(result);
34
+
35
+ // For now, using mock data
36
+ setData(mockData);
37
+ } catch (err) {
38
+ setError('Failed to fetch data');
39
+ } finally {
40
+ setLoading(false);
41
+ }
42
+ };
43
+
44
+ if (loading) {
45
+ return (
46
+ <div className="flex items-center justify-center p-8">
47
+ <div className="text-lg text-muted-foreground">Loading...</div>
48
+ </div>
49
+ );
50
+ }
51
+
52
+ if (error) {
53
+ return (
54
+ <div className="flex items-center justify-center p-8">
55
+ <div className="text-red-500">{error}</div>
56
+ </div>
57
+ );
58
+ }
59
+
60
+ return (
61
+ <div className="w-full max-w-4xl mx-auto p-6">
62
+ <div className="flex justify-between items-center mb-6">
63
+ <h2 className="text-2xl font-bold text-foreground">User Data</h2>
64
+ <Button onClick={fetchFromMongoDB}>
65
+ Refresh Data
66
+ </Button>
67
+ </div>
68
+
69
+ <div className="border rounded-lg bg-card">
70
+ <Table>
71
+ <TableCaption>A list of users from the database.</TableCaption>
72
+ <TableHeader>
73
+ <TableRow>
74
+ <TableHead>ID</TableHead>
75
+ <TableHead>Name</TableHead>
76
+ <TableHead>Email</TableHead>
77
+ <TableHead>Role</TableHead>
78
+ </TableRow>
79
+ </TableHeader>
80
+ <TableBody>
81
+ {data.map((user) => (
82
+ <TableRow key={user.id}>
83
+ <TableCell className="font-medium">{user.id}</TableCell>
84
+ <TableCell>{user.name}</TableCell>
85
+ <TableCell>{user.email}</TableCell>
86
+ <TableCell>{user.role}</TableCell>
87
+ </TableRow>
88
+ ))}
89
+ </TableBody>
90
+ </Table>
91
+ </div>
92
+ </div>
93
+ );
94
+ };
95
+
96
+ export default DataTable;
src/components/ui/button.jsx ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { cn } from "../../lib/utils"
4
+
5
+ const buttonVariants = cn(
6
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
7
+ "bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2",
8
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
9
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
10
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
11
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
12
+ "hover:bg-accent hover:text-accent-foreground",
13
+ "h-9 w-9 p-0",
14
+ "h-11 w-11"
15
+ )
16
+
17
+ const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
18
+ const Comp = asChild ? Slot : "button"
19
+ return (
20
+ <Comp
21
+ className={cn(buttonVariants, className)}
22
+ ref={ref}
23
+ {...props}
24
+ />
25
+ )
26
+ })
27
+ Button.displayName = "Button"
28
+
29
+ export { Button }
src/components/ui/table.jsx ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+ import { cn } from "../../lib/utils"
3
+
4
+ const Table = React.forwardRef(({ className, ...props }, ref) => (
5
+ <div className="relative w-full overflow-auto">
6
+ <table
7
+ ref={ref}
8
+ className={cn("w-full caption-bottom text-sm", className)}
9
+ {...props}
10
+ />
11
+ </div>
12
+ ))
13
+ Table.displayName = "Table"
14
+
15
+ const TableHeader = React.forwardRef(({ className, ...props }, ref) => (
16
+ <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
17
+ ))
18
+ TableHeader.displayName = "TableHeader"
19
+
20
+ const TableBody = React.forwardRef(({ className, ...props }, ref) => (
21
+ <tbody
22
+ ref={ref}
23
+ className={cn("[&_tr:last-child]:border-0", className)}
24
+ {...props}
25
+ />
26
+ ))
27
+ TableBody.displayName = "TableBody"
28
+
29
+ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (
30
+ <tfoot
31
+ ref={ref}
32
+ className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
33
+ {...props}
34
+ />
35
+ ))
36
+ TableFooter.displayName = "TableFooter"
37
+
38
+ const TableRow = React.forwardRef(({ className, ...props }, ref) => (
39
+ <tr
40
+ ref={ref}
41
+ className={cn(
42
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ ))
48
+ TableRow.displayName = "TableRow"
49
+
50
+ const TableHead = React.forwardRef(({ className, ...props }, ref) => (
51
+ <th
52
+ ref={ref}
53
+ className={cn(
54
+ "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
55
+ className
56
+ )}
57
+ {...props}
58
+ />
59
+ ))
60
+ TableHead.displayName = "TableHead"
61
+
62
+ const TableCell = React.forwardRef(({ className, ...props }, ref) => (
63
+ <td
64
+ ref={ref}
65
+ className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
66
+ {...props}
67
+ />
68
+ ))
69
+ TableCell.displayName = "TableCell"
70
+
71
+ const TableCaption = React.forwardRef(({ className, ...props }, ref) => (
72
+ <caption
73
+ ref={ref}
74
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
75
+ {...props}
76
+ />
77
+ ))
78
+ TableCaption.displayName = "TableCaption"
79
+
80
+ export {
81
+ Table,
82
+ TableHeader,
83
+ TableBody,
84
+ TableFooter,
85
+ TableHead,
86
+ TableRow,
87
+ TableCell,
88
+ TableCaption,
89
+ }
src/index.css CHANGED
@@ -1,13 +1,59 @@
1
- body {
2
- margin: 0;
3
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
- sans-serif;
6
- -webkit-font-smoothing: antialiased;
7
- -moz-osx-font-smoothing: grayscale;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  }
9
 
10
- code {
11
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12
- monospace;
 
 
 
 
13
  }
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 222.2 84% 4.9%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 222.2 84% 4.9%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 222.2 84% 4.9%;
13
+ --primary: 222.2 47.4% 11.2%;
14
+ --primary-foreground: 210 40% 98%;
15
+ --secondary: 210 40% 96%;
16
+ --secondary-foreground: 222.2 47.4% 11.2%;
17
+ --muted: 210 40% 96%;
18
+ --muted-foreground: 215.4 16.3% 46.9%;
19
+ --accent: 210 40% 96%;
20
+ --accent-foreground: 222.2 47.4% 11.2%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 210 40% 98%;
23
+ --border: 214.3 31.8% 91.4%;
24
+ --input: 214.3 31.8% 91.4%;
25
+ --ring: 222.2 84% 4.9%;
26
+ --radius: 0.5rem;
27
+ }
28
+
29
+ .dark {
30
+ --background: 222.2 84% 4.9%;
31
+ --foreground: 210 40% 98%;
32
+ --card: 222.2 84% 4.9%;
33
+ --card-foreground: 210 40% 98%;
34
+ --popover: 222.2 84% 4.9%;
35
+ --popover-foreground: 210 40% 98%;
36
+ --primary: 210 40% 98%;
37
+ --primary-foreground: 222.2 47.4% 11.2%;
38
+ --secondary: 217.2 32.6% 17.5%;
39
+ --secondary-foreground: 210 40% 98%;
40
+ --muted: 217.2 32.6% 17.5%;
41
+ --muted-foreground: 215 20.2% 65.1%;
42
+ --accent: 217.2 32.6% 17.5%;
43
+ --accent-foreground: 210 40% 98%;
44
+ --destructive: 0 62.8% 30.6%;
45
+ --destructive-foreground: 210 40% 98%;
46
+ --border: 217.2 32.6% 17.5%;
47
+ --input: 217.2 32.6% 17.5%;
48
+ --ring: 212.7 26.8% 83.9%;
49
+ }
50
  }
51
 
52
+ @layer base {
53
+ * {
54
+ @apply border-border;
55
+ }
56
+ body {
57
+ @apply bg-background text-foreground;
58
+ }
59
  }
src/lib/utils.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import { clsx } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs) {
5
+ return twMerge(clsx(inputs))
6
+ }
tailwind.config.js ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ darkMode: ["class"],
4
+ content: [
5
+ './pages/**/*.{js,jsx}',
6
+ './components/**/*.{js,jsx}',
7
+ './app/**/*.{js,jsx}',
8
+ './src/**/*.{js,jsx}',
9
+ ],
10
+ prefix: "",
11
+ theme: {
12
+ container: {
13
+ center: true,
14
+ padding: "2rem",
15
+ screens: {
16
+ "2xl": "1400px",
17
+ },
18
+ },
19
+ extend: {
20
+ colors: {
21
+ border: "hsl(var(--border))",
22
+ input: "hsl(var(--input))",
23
+ ring: "hsl(var(--ring))",
24
+ background: "hsl(var(--background))",
25
+ foreground: "hsl(var(--foreground))",
26
+ primary: {
27
+ DEFAULT: "hsl(var(--primary))",
28
+ foreground: "hsl(var(--primary-foreground))",
29
+ },
30
+ secondary: {
31
+ DEFAULT: "hsl(var(--secondary))",
32
+ foreground: "hsl(var(--secondary-foreground))",
33
+ },
34
+ destructive: {
35
+ DEFAULT: "hsl(var(--destructive))",
36
+ foreground: "hsl(var(--destructive-foreground))",
37
+ },
38
+ muted: {
39
+ DEFAULT: "hsl(var(--muted))",
40
+ foreground: "hsl(var(--muted-foreground))",
41
+ },
42
+ accent: {
43
+ DEFAULT: "hsl(var(--accent))",
44
+ foreground: "hsl(var(--accent-foreground))",
45
+ },
46
+ popover: {
47
+ DEFAULT: "hsl(var(--popover))",
48
+ foreground: "hsl(var(--popover-foreground))",
49
+ },
50
+ card: {
51
+ DEFAULT: "hsl(var(--card))",
52
+ foreground: "hsl(var(--card-foreground))",
53
+ },
54
+ },
55
+ borderRadius: {
56
+ lg: "var(--radius)",
57
+ md: "calc(var(--radius) - 2px)",
58
+ sm: "calc(var(--radius) - 4px)",
59
+ },
60
+ keyframes: {
61
+ "accordion-down": {
62
+ from: { height: "0" },
63
+ to: { height: "var(--radix-accordion-content-height)" },
64
+ },
65
+ "accordion-up": {
66
+ from: { height: "var(--radix-accordion-content-height)" },
67
+ to: { height: "0" },
68
+ },
69
+ },
70
+ animation: {
71
+ "accordion-down": "accordion-down 0.2s ease-out",
72
+ "accordion-up": "accordion-up 0.2s ease-out",
73
+ },
74
+ },
75
+ },
76
+ plugins: [require("tailwindcss-animate")],
77
+ }