thanks bolt.new
This commit is contained in:
parent
9a408a48f9
commit
698ca17323
18 changed files with 4621 additions and 0 deletions
3
.bolt/config.json
Normal file
3
.bolt/config.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"template": "bolt-vite-react-ts"
|
||||
}
|
8
.bolt/prompt
Normal file
8
.bolt/prompt
Normal file
|
@ -0,0 +1,8 @@
|
|||
For all designs I ask you to make, have them be beautiful, not cookie cutter. Make webpages that are fully featured and worthy for production.
|
||||
|
||||
By default, this template supports JSX syntax with Tailwind CSS classes, React hooks, and Lucide React for icons. Do not install other packages for UI themes, icons, etc unless absolutely necessary or I request them.
|
||||
|
||||
Use icons from lucide-react for logos.
|
||||
|
||||
Use stock photos from unsplash where appropriate, only valid URLs you know exist. Do not download the images, only link to them in image tags.
|
||||
|
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
28
eslint.config.js
Normal file
28
eslint.config.js
Normal file
|
@ -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 },
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
13
index.html
Normal file
13
index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23E06B6C' stroke='%23E06B6C' stroke-width='0' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21.47 4.35l.708-.708a1 1 0 0 0-.708-.708l-.708.708a1 1 0 0 0 .708.708zm.867 13.04a4.98 4.98 0 0 1-1.414 3.536l-1.829-1.829a4.92 4.92 0 0 1-3.364 1.364l-2.121 2.121a4.98 4.98 0 0 1-3.536 1.414 4.98 4.98 0 0 1-3.536-1.414l2.121-2.121a4.92 4.92 0 0 1-1.364-3.364l-1.829-1.829a4.98 4.98 0 0 1-1.414-3.536 4.98 4.98 0 0 1 1.414-3.536l2.121 2.121a4.92 4.92 0 0 1 3.364-1.364l1.829-1.829a4.98 4.98 0 0 1 3.536-1.414 4.98 4.98 0 0 1 3.536 1.414l-2.121 2.121a4.92 4.92 0 0 1 1.364 3.364l1.829 1.829a4.98 4.98 0 0 1 1.414 3.536z'/%3E%3C/svg%3E" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Proxmox Dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
4096
package-lock.json
generated
Normal file
4096
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
34
package.json
Normal file
34
package.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "vite-react-typescript-starter",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.344.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"framer-motion": "^11.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.9.1",
|
||||
"@types/react": "^18.3.5",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"autoprefixer": "^10.4.18",
|
||||
"eslint": "^9.9.1",
|
||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.11",
|
||||
"globals": "^15.9.0",
|
||||
"postcss": "^8.4.35",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.3.0",
|
||||
"vite": "^5.4.2"
|
||||
}
|
||||
}
|
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
324
src/App.tsx
Normal file
324
src/App.tsx
Normal file
|
@ -0,0 +1,324 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Plus, ExternalLink, Trash2, Activity } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
// Custom Proxmox Logo SVG component
|
||||
const ProxmoxLogo = ({ className }: { className?: string }) => (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
className={className}
|
||||
fill="#E06B6C"
|
||||
stroke="#E06B6C"
|
||||
strokeWidth="0"
|
||||
>
|
||||
<path d="M21.47 4.35l.708-.708a1 1 0 0 0-.708-.708l-.708.708a1 1 0 0 0 .708.708zm.867 13.04a4.98 4.98 0 0 1-1.414 3.536l-1.829-1.829a4.92 4.92 0 0 1-3.364 1.364l-2.121 2.121a4.98 4.98 0 0 1-3.536 1.414 4.98 4.98 0 0 1-3.536-1.414l2.121-2.121a4.92 4.92 0 0 1-1.364-3.364l-1.829-1.829a4.98 4.98 0 0 1-1.414-3.536 4.98 4.98 0 0 1 1.414-3.536l2.121 2.121a4.92 4.92 0 0 1 3.364-1.364l1.829-1.829a4.98 4.98 0 0 1 3.536-1.414 4.98 4.98 0 0 1 3.536 1.414l-2.121 2.121a4.92 4.92 0 0 1 1.364 3.364l1.829 1.829a4.98 4.98 0 0 1 1.414 3.536z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
interface ServerSpecs {
|
||||
cpu: string;
|
||||
ram: string;
|
||||
gpu: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface ProxmoxServer {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
status: 'online' | 'offline' | 'checking';
|
||||
specs: ServerSpecs;
|
||||
lastPing?: number;
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [servers, setServers] = useState<ProxmoxServer[]>([]);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [newServer, setNewServer] = useState({
|
||||
name: '',
|
||||
url: '',
|
||||
specs: {
|
||||
cpu: '',
|
||||
ram: '',
|
||||
gpu: '',
|
||||
type: ''
|
||||
}
|
||||
});
|
||||
|
||||
const pingServer = async (server: ProxmoxServer) => {
|
||||
setServers(current =>
|
||||
current.map(s =>
|
||||
s.id === server.id ? { ...s, status: 'checking' } : s
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
const response = await fetch(server.url, { mode: 'no-cors' });
|
||||
const endTime = Date.now();
|
||||
|
||||
setServers(current =>
|
||||
current.map(s =>
|
||||
s.id === server.id
|
||||
? { ...s, status: 'online', lastPing: endTime - startTime }
|
||||
: s
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
setServers(current =>
|
||||
current.map(s =>
|
||||
s.id === server.id ? { ...s, status: 'offline' } : s
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const addServer = () => {
|
||||
if (newServer.name && newServer.url) {
|
||||
const server: ProxmoxServer = {
|
||||
id: Date.now().toString(),
|
||||
name: newServer.name,
|
||||
url: newServer.url,
|
||||
status: 'checking',
|
||||
specs: newServer.specs
|
||||
};
|
||||
|
||||
setServers([...servers, server]);
|
||||
setNewServer({
|
||||
name: '',
|
||||
url: '',
|
||||
specs: { cpu: '', ram: '', gpu: '', type: '' }
|
||||
});
|
||||
setIsModalOpen(false);
|
||||
pingServer(server);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteServer = (id: string) => {
|
||||
setServers(servers.filter(server => server.id !== id));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
servers.forEach(server => pingServer(server));
|
||||
}, 30000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [servers]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 text-gray-100">
|
||||
{/* Header */}
|
||||
<header className="bg-gray-800 shadow-lg">
|
||||
<div className="container mx-auto px-6 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-3">
|
||||
<ProxmoxLogo className="h-8 w-8" />
|
||||
<h1 className="text-2xl font-bold">Proxmox Dashboard</h1>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="flex items-center space-x-2 bg-[#E06B6C] hover:bg-[#c85657] px-4 py-2 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
<Plus className="h-5 w-5" />
|
||||
<span>Add Server</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="container mx-auto px-6 py-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<AnimatePresence>
|
||||
{servers.map(server => (
|
||||
<motion.div
|
||||
key={server.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
className="relative group"
|
||||
>
|
||||
<div className="bg-gray-800 rounded-lg shadow-lg overflow-hidden hover:ring-2 hover:ring-[#E06B6C] transition-all duration-200">
|
||||
<div className="p-6">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold mb-2">{server.name}</h2>
|
||||
<p className="text-gray-400 text-sm">{server.url}</p>
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
onClick={() => pingServer(server)}
|
||||
className="p-2 hover:bg-gray-700 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
<Activity className={`h-5 w-5 ${
|
||||
server.status === 'checking' ? 'animate-pulse text-yellow-400' :
|
||||
server.status === 'online' ? 'text-[#E06B6C]' : 'text-red-400'
|
||||
}`} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => window.open(server.url, '_blank')}
|
||||
className="p-2 hover:bg-gray-700 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
<ExternalLink className="h-5 w-5 text-[#E06B6C]" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => deleteServer(server.id)}
|
||||
className="p-2 hover:bg-gray-700 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
<Trash2 className="h-5 w-5 text-red-400" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex items-center space-x-2">
|
||||
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
|
||||
server.status === 'checking' ? 'bg-yellow-100 text-yellow-800' :
|
||||
server.status === 'online' ? 'bg-[#fde8e8] text-[#E06B6C]' : 'bg-red-100 text-red-800'
|
||||
}`}>
|
||||
{server.status}
|
||||
</span>
|
||||
{server.lastPing && server.status === 'online' && (
|
||||
<span className="text-xs text-gray-400">
|
||||
{server.lastPing}ms
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Specs Tooltip */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="absolute invisible group-hover:visible -top-2 left-1/2 -translate-x-1/2 -translate-y-full
|
||||
bg-gray-700 rounded-lg shadow-lg p-4 w-64 z-10 transform origin-bottom"
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm"><span className="font-semibold">CPU:</span> {server.specs.cpu}</p>
|
||||
<p className="text-sm"><span className="font-semibold">RAM:</span> {server.specs.ram}</p>
|
||||
<p className="text-sm"><span className="font-semibold">GPU:</span> {server.specs.gpu}</p>
|
||||
<p className="text-sm"><span className="font-semibold">Type:</span> {server.specs.type}</p>
|
||||
</div>
|
||||
<div className="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2
|
||||
border-8 border-transparent border-t-gray-700" />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Empty State */}
|
||||
{servers.length === 0 && (
|
||||
<div className="text-center py-16">
|
||||
<ProxmoxLogo className="h-16 w-16 mx-auto text-gray-600 mb-4" />
|
||||
<h3 className="text-xl font-medium text-gray-400">No servers added yet</h3>
|
||||
<p className="text-gray-500 mt-2">Click the Add Server button to get started</p>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
|
||||
{/* Add Server Modal */}
|
||||
{isModalOpen && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="bg-gray-800 rounded-lg p-6 w-full max-w-md"
|
||||
>
|
||||
<h2 className="text-xl font-bold mb-4">Add New Server</h2>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Server Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.name}
|
||||
onChange={(e) => setNewServer({ ...newServer, name: e.target.value })}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="My Proxmox Server"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Server URL</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.url}
|
||||
onChange={(e) => setNewServer({ ...newServer, url: e.target.value })}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="https://proxmox.example.com:8006"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">CPU</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.specs.cpu}
|
||||
onChange={(e) => setNewServer({
|
||||
...newServer,
|
||||
specs: { ...newServer.specs, cpu: e.target.value }
|
||||
})}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="Intel Xeon E5-2680 v4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">RAM</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.specs.ram}
|
||||
onChange={(e) => setNewServer({
|
||||
...newServer,
|
||||
specs: { ...newServer.specs, ram: e.target.value }
|
||||
})}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="64GB DDR4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">GPU</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.specs.gpu}
|
||||
onChange={(e) => setNewServer({
|
||||
...newServer,
|
||||
specs: { ...newServer.specs, gpu: e.target.value }
|
||||
})}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="NVIDIA RTX 3080"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Server Type</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newServer.specs.type}
|
||||
onChange={(e) => setNewServer({
|
||||
...newServer,
|
||||
specs: { ...newServer.specs, type: e.target.value }
|
||||
})}
|
||||
className="w-full bg-gray-700 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-[#E06B6C]"
|
||||
placeholder="Dell R730"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex space-x-3 mt-6">
|
||||
<button
|
||||
onClick={addServer}
|
||||
className="flex-1 bg-[#E06B6C] hover:bg-[#c85657] px-4 py-2 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
Add Server
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(false)}
|
||||
className="flex-1 bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg transition-colors duration-200"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
3
src/index.css
Normal file
3
src/index.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
10
src/main.tsx
Normal file
10
src/main.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
import './index.css';
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
);
|
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
8
tailwind.config.js
Normal file
8
tailwind.config.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
24
tsconfig.app.json
Normal file
24
tsconfig.app.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
22
tsconfig.node.json
Normal file
22
tsconfig.node.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
10
vite.config.ts
Normal file
10
vite.config.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
optimizeDeps: {
|
||||
exclude: ['lucide-react'],
|
||||
},
|
||||
});
|
Loading…
Reference in a new issue