Spaces:
Running
Running
Pulastya B commited on
Commit Β·
259c45d
1
Parent(s): c0e18bf
Added Sign in and Sign Up page
Browse files- FRRONTEEEND/App.tsx +20 -5
- FRRONTEEEND/components/AuthPage.tsx +750 -202
- FRRONTEEEND/components/ui/button.tsx +55 -0
- FRRONTEEEND/components/ui/card.tsx +78 -0
- FRRONTEEEND/components/ui/checkbox.tsx +29 -0
- FRRONTEEEND/components/ui/input.tsx +24 -0
- FRRONTEEEND/components/ui/label.tsx +25 -0
- FRRONTEEEND/components/ui/radio-group.tsx +43 -0
- FRRONTEEEND/components/ui/select.tsx +159 -0
- FRRONTEEEND/components/ui/textarea.tsx +23 -0
- FRRONTEEEND/index.html +55 -0
- FRRONTEEEND/lib/AuthContext.tsx +15 -3
- FRRONTEEEND/lib/supabase.ts +6 -1
- FRRONTEEEND/package-lock.json +919 -0
- FRRONTEEEND/package.json +7 -0
- idx.html +1281 -0
FRRONTEEEND/App.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
|
| 2 |
-
import React, { useState
|
| 3 |
import { HeroGeometric } from './components/HeroGeometric';
|
| 4 |
import ProblemSolution from './components/ProblemSolution';
|
| 5 |
import KeyCapabilities from './components/KeyCapabilities';
|
|
@@ -11,12 +11,12 @@ import { Logo } from './components/Logo';
|
|
| 11 |
import { ChatInterface } from './components/ChatInterface';
|
| 12 |
import { AuthPage } from './components/AuthPage';
|
| 13 |
import { AuthProvider, useAuth } from './lib/AuthContext';
|
| 14 |
-
import { User, LogOut } from 'lucide-react';
|
| 15 |
|
| 16 |
// Inner app component that uses auth context
|
| 17 |
const AppContent: React.FC = () => {
|
| 18 |
const [view, setView] = useState<'landing' | 'chat' | 'auth'>('landing');
|
| 19 |
-
const { user, isAuthenticated, loading, signOut } = useAuth();
|
| 20 |
const [showUserMenu, setShowUserMenu] = useState(false);
|
| 21 |
|
| 22 |
// Handle launch console - redirect to auth if not logged in
|
|
@@ -25,6 +25,21 @@ const AppContent: React.FC = () => {
|
|
| 25 |
setView('chat');
|
| 26 |
};
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
// Show auth page
|
| 29 |
if (view === 'auth') {
|
| 30 |
return (
|
|
@@ -51,7 +66,7 @@ const AppContent: React.FC = () => {
|
|
| 51 |
</div>
|
| 52 |
|
| 53 |
<div className="flex items-center gap-3">
|
| 54 |
-
{/* User menu */}
|
| 55 |
{isAuthenticated ? (
|
| 56 |
<div className="relative">
|
| 57 |
<button
|
|
@@ -130,4 +145,4 @@ const App: React.FC = () => {
|
|
| 130 |
);
|
| 131 |
};
|
| 132 |
|
| 133 |
-
export default App;
|
|
|
|
| 1 |
|
| 2 |
+
import React, { useState } from 'react';
|
| 3 |
import { HeroGeometric } from './components/HeroGeometric';
|
| 4 |
import ProblemSolution from './components/ProblemSolution';
|
| 5 |
import KeyCapabilities from './components/KeyCapabilities';
|
|
|
|
| 11 |
import { ChatInterface } from './components/ChatInterface';
|
| 12 |
import { AuthPage } from './components/AuthPage';
|
| 13 |
import { AuthProvider, useAuth } from './lib/AuthContext';
|
| 14 |
+
import { User, LogOut, Loader2 } from 'lucide-react';
|
| 15 |
|
| 16 |
// Inner app component that uses auth context
|
| 17 |
const AppContent: React.FC = () => {
|
| 18 |
const [view, setView] = useState<'landing' | 'chat' | 'auth'>('landing');
|
| 19 |
+
const { user, isAuthenticated, loading, signOut, isConfigured } = useAuth();
|
| 20 |
const [showUserMenu, setShowUserMenu] = useState(false);
|
| 21 |
|
| 22 |
// Handle launch console - redirect to auth if not logged in
|
|
|
|
| 25 |
setView('chat');
|
| 26 |
};
|
| 27 |
|
| 28 |
+
// Show loading state only briefly
|
| 29 |
+
if (loading) {
|
| 30 |
+
return (
|
| 31 |
+
<div className="min-h-screen bg-[#030303] flex items-center justify-center">
|
| 32 |
+
<div className="flex flex-col items-center gap-4">
|
| 33 |
+
<Logo className="w-16 h-16 animate-pulse" />
|
| 34 |
+
<div className="flex items-center gap-2 text-white/50">
|
| 35 |
+
<Loader2 className="w-4 h-4 animate-spin" />
|
| 36 |
+
<span>Loading...</span>
|
| 37 |
+
</div>
|
| 38 |
+
</div>
|
| 39 |
+
</div>
|
| 40 |
+
);
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
// Show auth page
|
| 44 |
if (view === 'auth') {
|
| 45 |
return (
|
|
|
|
| 66 |
</div>
|
| 67 |
|
| 68 |
<div className="flex items-center gap-3">
|
| 69 |
+
{/* User menu - only show if Supabase is configured */}
|
| 70 |
{isAuthenticated ? (
|
| 71 |
<div className="relative">
|
| 72 |
<button
|
|
|
|
| 145 |
);
|
| 146 |
};
|
| 147 |
|
| 148 |
+
export default App;
|
FRRONTEEEND/components/AuthPage.tsx
CHANGED
|
@@ -1,8 +1,61 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
import
|
| 4 |
-
import {
|
| 5 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
interface AuthPageProps {
|
| 8 |
onSuccess?: () => void;
|
|
@@ -12,43 +65,90 @@ interface AuthPageProps {
|
|
| 12 |
export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
|
| 13 |
const { signIn, signUp, signInWithGoogle, signInWithGithub } = useAuth();
|
| 14 |
const [mode, setMode] = useState<'signin' | 'signup'>('signin');
|
| 15 |
-
const [
|
| 16 |
-
const [
|
| 17 |
-
const [
|
| 18 |
const [error, setError] = useState<string | null>(null);
|
| 19 |
const [success, setSuccess] = useState<string | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
e.preventDefault();
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
setError(null);
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
try {
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
setError(error.message);
|
| 32 |
-
} else {
|
| 33 |
-
setSuccess('Check your email to confirm your account!');
|
| 34 |
-
}
|
| 35 |
} else {
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
setError(error.message);
|
| 39 |
-
} else {
|
| 40 |
onSuccess?.();
|
| 41 |
-
}
|
| 42 |
}
|
| 43 |
} catch (err: any) {
|
| 44 |
setError(err.message || 'An error occurred');
|
| 45 |
} finally {
|
| 46 |
-
|
| 47 |
}
|
| 48 |
};
|
| 49 |
|
| 50 |
const handleOAuthSignIn = async (provider: 'google' | 'github') => {
|
| 51 |
-
|
| 52 |
setError(null);
|
| 53 |
|
| 54 |
try {
|
|
@@ -59,204 +159,652 @@ export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
|
|
| 59 |
} catch (err: any) {
|
| 60 |
setError(err.message || 'An error occurred');
|
| 61 |
} finally {
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
}
|
| 64 |
};
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
return (
|
| 67 |
-
<div className="min-h-screen bg-[#
|
| 68 |
-
{/* Background gradient */}
|
| 69 |
<div className="absolute inset-0 overflow-hidden">
|
| 70 |
<div className="absolute -top-40 -right-40 w-80 h-80 bg-indigo-500/10 rounded-full blur-3xl" />
|
| 71 |
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-purple-500/10 rounded-full blur-3xl" />
|
| 72 |
</div>
|
| 73 |
|
| 74 |
-
<
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
className="w-full flex items-center justify-center gap-3 px-4 py-3 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl transition-all text-white font-medium disabled:opacity-50"
|
| 104 |
-
>
|
| 105 |
-
<svg className="w-5 h-5" viewBox="0 0 24 24">
|
| 106 |
-
<path
|
| 107 |
-
fill="currentColor"
|
| 108 |
-
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
| 109 |
-
/>
|
| 110 |
-
<path
|
| 111 |
-
fill="currentColor"
|
| 112 |
-
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
| 113 |
-
/>
|
| 114 |
-
<path
|
| 115 |
-
fill="currentColor"
|
| 116 |
-
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
| 117 |
-
/>
|
| 118 |
-
<path
|
| 119 |
-
fill="currentColor"
|
| 120 |
-
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
| 121 |
/>
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
</div>
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
<span className="px-4 bg-[#0a0a0a] text-white/40">or continue with email</span>
|
| 143 |
-
</div>
|
| 144 |
</div>
|
|
|
|
| 145 |
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
<div>
|
| 149 |
-
<
|
| 150 |
-
<div className="relative">
|
| 151 |
-
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-white/30" />
|
| 152 |
-
<input
|
| 153 |
-
type="email"
|
| 154 |
-
value={email}
|
| 155 |
-
onChange={(e) => setEmail(e.target.value)}
|
| 156 |
-
placeholder="you@example.com"
|
| 157 |
-
required
|
| 158 |
-
className="w-full pl-11 pr-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/30 focus:outline-none focus:border-indigo-500/50 focus:ring-1 focus:ring-indigo-500/50 transition-all"
|
| 159 |
-
/>
|
| 160 |
-
</div>
|
| 161 |
-
</div>
|
| 162 |
-
|
| 163 |
-
<div>
|
| 164 |
-
<label className="block text-sm font-medium text-white/70 mb-2">Password</label>
|
| 165 |
-
<div className="relative">
|
| 166 |
-
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-white/30" />
|
| 167 |
-
<input
|
| 168 |
-
type="password"
|
| 169 |
-
value={password}
|
| 170 |
-
onChange={(e) => setPassword(e.target.value)}
|
| 171 |
-
placeholder="β’β’β’β’β’β’β’β’"
|
| 172 |
-
required
|
| 173 |
-
minLength={6}
|
| 174 |
-
className="w-full pl-11 pr-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/30 focus:outline-none focus:border-indigo-500/50 focus:ring-1 focus:ring-indigo-500/50 transition-all"
|
| 175 |
-
/>
|
| 176 |
-
</div>
|
| 177 |
-
</div>
|
| 178 |
-
|
| 179 |
-
{/* Error Message */}
|
| 180 |
-
<AnimatePresence>
|
| 181 |
-
{error && (
|
| 182 |
<motion.div
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
|
|
|
| 187 |
>
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
</motion.div>
|
| 206 |
-
|
| 207 |
-
</AnimatePresence>
|
| 208 |
-
|
| 209 |
-
{/* Submit Button */}
|
| 210 |
-
<button
|
| 211 |
-
type="submit"
|
| 212 |
-
disabled={loading}
|
| 213 |
-
className="w-full py-3 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 text-white font-medium rounded-xl transition-all disabled:opacity-50 flex items-center justify-center gap-2"
|
| 214 |
-
>
|
| 215 |
-
{loading ? (
|
| 216 |
-
<Loader2 className="w-5 h-5 animate-spin" />
|
| 217 |
-
) : mode === 'signin' ? (
|
| 218 |
-
'Sign In'
|
| 219 |
-
) : (
|
| 220 |
-
'Create Account'
|
| 221 |
-
)}
|
| 222 |
-
</button>
|
| 223 |
-
</form>
|
| 224 |
-
|
| 225 |
-
{/* Toggle Mode */}
|
| 226 |
-
<div className="mt-6 text-center">
|
| 227 |
-
<p className="text-white/50 text-sm">
|
| 228 |
-
{mode === 'signin' ? "Don't have an account? " : 'Already have an account? '}
|
| 229 |
-
<button
|
| 230 |
-
onClick={() => {
|
| 231 |
-
setMode(mode === 'signin' ? 'signup' : 'signin');
|
| 232 |
-
setError(null);
|
| 233 |
-
setSuccess(null);
|
| 234 |
-
}}
|
| 235 |
-
className="text-indigo-400 hover:text-indigo-300 font-medium"
|
| 236 |
-
>
|
| 237 |
-
{mode === 'signin' ? 'Sign Up' : 'Sign In'}
|
| 238 |
-
</button>
|
| 239 |
-
</p>
|
| 240 |
-
</div>
|
| 241 |
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
</div>
|
| 252 |
-
|
| 253 |
-
</div>
|
| 254 |
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
</div>
|
| 261 |
);
|
| 262 |
};
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client";
|
| 2 |
+
|
| 3 |
+
import React, { useState } from "react";
|
| 4 |
+
import { motion, AnimatePresence } from "framer-motion";
|
| 5 |
+
import { ChevronLeft, ChevronRight, Check, Loader2, Eye, EyeOff, Github, Mail, Lock, User, Target, Briefcase } from "lucide-react";
|
| 6 |
+
import { Button } from "./ui/button";
|
| 7 |
+
import {
|
| 8 |
+
Card,
|
| 9 |
+
CardContent,
|
| 10 |
+
CardDescription,
|
| 11 |
+
CardFooter,
|
| 12 |
+
CardHeader,
|
| 13 |
+
CardTitle,
|
| 14 |
+
} from "./ui/card";
|
| 15 |
+
import { Input } from "./ui/input";
|
| 16 |
+
import { Label } from "./ui/label";
|
| 17 |
+
import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
|
| 18 |
+
import { Textarea } from "./ui/textarea";
|
| 19 |
+
import {
|
| 20 |
+
Select,
|
| 21 |
+
SelectContent,
|
| 22 |
+
SelectItem,
|
| 23 |
+
SelectTrigger,
|
| 24 |
+
SelectValue,
|
| 25 |
+
} from "./ui/select";
|
| 26 |
+
import { cn } from "../lib/utils";
|
| 27 |
+
import { useAuth } from "../lib/AuthContext";
|
| 28 |
+
import { Logo } from "./Logo";
|
| 29 |
+
|
| 30 |
+
const steps = [
|
| 31 |
+
{ id: "personal", title: "Personal Info" },
|
| 32 |
+
{ id: "goals", title: "Data Science Goals" },
|
| 33 |
+
{ id: "professional", title: "Professional" },
|
| 34 |
+
];
|
| 35 |
+
|
| 36 |
+
interface FormData {
|
| 37 |
+
name: string;
|
| 38 |
+
email: string;
|
| 39 |
+
password: string;
|
| 40 |
+
confirmPassword: string;
|
| 41 |
+
primaryGoal: string;
|
| 42 |
+
targetOutcome: string;
|
| 43 |
+
dataTypes: string[];
|
| 44 |
+
profession: string;
|
| 45 |
+
experience: string;
|
| 46 |
+
industry: string;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
const fadeInUp = {
|
| 50 |
+
hidden: { opacity: 0, y: 20 },
|
| 51 |
+
visible: { opacity: 1, y: 0, transition: { duration: 0.3 } },
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
const contentVariants = {
|
| 55 |
+
hidden: { opacity: 0, x: 50 },
|
| 56 |
+
visible: { opacity: 1, x: 0, transition: { duration: 0.3 } },
|
| 57 |
+
exit: { opacity: 0, x: -50, transition: { duration: 0.2 } },
|
| 58 |
+
};
|
| 59 |
|
| 60 |
interface AuthPageProps {
|
| 61 |
onSuccess?: () => void;
|
|
|
|
| 65 |
export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
|
| 66 |
const { signIn, signUp, signInWithGoogle, signInWithGithub } = useAuth();
|
| 67 |
const [mode, setMode] = useState<'signin' | 'signup'>('signin');
|
| 68 |
+
const [currentStep, setCurrentStep] = useState(0);
|
| 69 |
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
| 70 |
+
const [showPassword, setShowPassword] = useState(false);
|
| 71 |
const [error, setError] = useState<string | null>(null);
|
| 72 |
const [success, setSuccess] = useState<string | null>(null);
|
| 73 |
+
|
| 74 |
+
const [formData, setFormData] = useState<FormData>({
|
| 75 |
+
name: "",
|
| 76 |
+
email: "",
|
| 77 |
+
password: "",
|
| 78 |
+
confirmPassword: "",
|
| 79 |
+
primaryGoal: "",
|
| 80 |
+
targetOutcome: "",
|
| 81 |
+
dataTypes: [],
|
| 82 |
+
profession: "",
|
| 83 |
+
experience: "",
|
| 84 |
+
industry: "",
|
| 85 |
+
});
|
| 86 |
+
|
| 87 |
+
const updateFormData = (field: keyof FormData, value: string) => {
|
| 88 |
+
setFormData((prev) => ({ ...prev, [field]: value }));
|
| 89 |
+
setError(null);
|
| 90 |
+
};
|
| 91 |
|
| 92 |
+
const nextStep = () => {
|
| 93 |
+
if (currentStep < steps.length - 1) {
|
| 94 |
+
setCurrentStep((prev) => prev + 1);
|
| 95 |
+
}
|
| 96 |
+
};
|
| 97 |
+
|
| 98 |
+
const prevStep = () => {
|
| 99 |
+
if (currentStep > 0) {
|
| 100 |
+
setCurrentStep((prev) => prev - 1);
|
| 101 |
+
}
|
| 102 |
+
};
|
| 103 |
+
|
| 104 |
+
const handleSignIn = async (e: React.FormEvent) => {
|
| 105 |
e.preventDefault();
|
| 106 |
+
setIsSubmitting(true);
|
| 107 |
+
setError(null);
|
| 108 |
+
|
| 109 |
+
try {
|
| 110 |
+
const { error } = await signIn(formData.email, formData.password);
|
| 111 |
+
if (error) {
|
| 112 |
+
setError(error.message);
|
| 113 |
+
} else {
|
| 114 |
+
onSuccess?.();
|
| 115 |
+
}
|
| 116 |
+
} catch (err: any) {
|
| 117 |
+
setError(err.message || 'An error occurred');
|
| 118 |
+
} finally {
|
| 119 |
+
setIsSubmitting(false);
|
| 120 |
+
}
|
| 121 |
+
};
|
| 122 |
+
|
| 123 |
+
const handleSignUp = async () => {
|
| 124 |
+
setIsSubmitting(true);
|
| 125 |
setError(null);
|
| 126 |
+
|
| 127 |
+
if (formData.password !== formData.confirmPassword) {
|
| 128 |
+
setError("Passwords don't match");
|
| 129 |
+
setIsSubmitting(false);
|
| 130 |
+
return;
|
| 131 |
+
}
|
| 132 |
|
| 133 |
try {
|
| 134 |
+
const { error } = await signUp(formData.email, formData.password);
|
| 135 |
+
if (error) {
|
| 136 |
+
setError(error.message);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
} else {
|
| 138 |
+
setSuccess('Account created! Check your email to confirm your account.');
|
| 139 |
+
setTimeout(() => {
|
|
|
|
|
|
|
| 140 |
onSuccess?.();
|
| 141 |
+
}, 2000);
|
| 142 |
}
|
| 143 |
} catch (err: any) {
|
| 144 |
setError(err.message || 'An error occurred');
|
| 145 |
} finally {
|
| 146 |
+
setIsSubmitting(false);
|
| 147 |
}
|
| 148 |
};
|
| 149 |
|
| 150 |
const handleOAuthSignIn = async (provider: 'google' | 'github') => {
|
| 151 |
+
setIsSubmitting(true);
|
| 152 |
setError(null);
|
| 153 |
|
| 154 |
try {
|
|
|
|
| 159 |
} catch (err: any) {
|
| 160 |
setError(err.message || 'An error occurred');
|
| 161 |
} finally {
|
| 162 |
+
setIsSubmitting(false);
|
| 163 |
+
}
|
| 164 |
+
};
|
| 165 |
+
|
| 166 |
+
const isStepValid = () => {
|
| 167 |
+
switch (currentStep) {
|
| 168 |
+
case 0:
|
| 169 |
+
return formData.name.trim() !== "" && formData.email.trim() !== "" &&
|
| 170 |
+
formData.password.length >= 6 && formData.password === formData.confirmPassword;
|
| 171 |
+
case 1:
|
| 172 |
+
return formData.primaryGoal !== "";
|
| 173 |
+
case 2:
|
| 174 |
+
return formData.profession.trim() !== "" && formData.industry !== "";
|
| 175 |
+
default:
|
| 176 |
+
return true;
|
| 177 |
}
|
| 178 |
};
|
| 179 |
|
| 180 |
+
// Sign In Form
|
| 181 |
+
if (mode === 'signin') {
|
| 182 |
+
return (
|
| 183 |
+
<div className="min-h-screen bg-[#030303] flex items-center justify-center p-4">
|
| 184 |
+
<div className="absolute inset-0 overflow-hidden">
|
| 185 |
+
<div className="absolute -top-40 -right-40 w-80 h-80 bg-indigo-500/10 rounded-full blur-3xl" />
|
| 186 |
+
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-purple-500/10 rounded-full blur-3xl" />
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<motion.div
|
| 190 |
+
initial={{ opacity: 0, y: 20 }}
|
| 191 |
+
animate={{ opacity: 1, y: 0 }}
|
| 192 |
+
className="relative w-full max-w-md"
|
| 193 |
+
>
|
| 194 |
+
<Card className="border-white/10 bg-white/[0.03] backdrop-blur-xl shadow-2xl pb-0">
|
| 195 |
+
<CardHeader className="space-y-1 text-center mb-2 mt-4">
|
| 196 |
+
<div className="flex justify-center mb-2">
|
| 197 |
+
<Logo className="w-12 h-12" />
|
| 198 |
+
</div>
|
| 199 |
+
<div>
|
| 200 |
+
<h2 className="text-2xl font-semibold text-white">Sign in to Data Science Agent</h2>
|
| 201 |
+
<p className="text-white/50 text-sm mt-1">
|
| 202 |
+
Welcome back! Please enter your details.
|
| 203 |
+
</p>
|
| 204 |
+
</div>
|
| 205 |
+
</CardHeader>
|
| 206 |
+
<CardContent className="space-y-4 px-8">
|
| 207 |
+
<div className="space-y-3">
|
| 208 |
+
<Button
|
| 209 |
+
type="button"
|
| 210 |
+
variant="outline"
|
| 211 |
+
onClick={() => handleOAuthSignIn('google')}
|
| 212 |
+
disabled={isSubmitting}
|
| 213 |
+
className="w-full bg-white/5 hover:bg-white/10 border-white/10 text-white h-11"
|
| 214 |
+
>
|
| 215 |
+
<svg className="w-5 h-5 mr-2" viewBox="0 0 24 24">
|
| 216 |
+
<path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
|
| 217 |
+
<path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
|
| 218 |
+
<path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
|
| 219 |
+
<path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
|
| 220 |
+
</svg>
|
| 221 |
+
Continue with Google
|
| 222 |
+
</Button>
|
| 223 |
+
|
| 224 |
+
<Button
|
| 225 |
+
type="button"
|
| 226 |
+
variant="outline"
|
| 227 |
+
onClick={() => handleOAuthSignIn('github')}
|
| 228 |
+
disabled={isSubmitting}
|
| 229 |
+
className="w-full bg-white/5 hover:bg-white/10 border-white/10 text-white h-11"
|
| 230 |
+
>
|
| 231 |
+
<Github className="w-5 h-5 mr-2" />
|
| 232 |
+
Continue with GitHub
|
| 233 |
+
</Button>
|
| 234 |
+
</div>
|
| 235 |
+
|
| 236 |
+
<div className="relative my-6">
|
| 237 |
+
<div className="absolute inset-0 flex items-center">
|
| 238 |
+
<div className="w-full border-t border-white/10"></div>
|
| 239 |
+
</div>
|
| 240 |
+
<div className="relative flex justify-center text-sm">
|
| 241 |
+
<span className="px-4 bg-[#030303] text-white/40">or continue with email</span>
|
| 242 |
+
</div>
|
| 243 |
+
</div>
|
| 244 |
+
|
| 245 |
+
<form onSubmit={handleSignIn} className="space-y-4">
|
| 246 |
+
<div className="space-y-2">
|
| 247 |
+
<Label htmlFor="email" className="text-white/70">Email address</Label>
|
| 248 |
+
<div className="relative">
|
| 249 |
+
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 250 |
+
<Input
|
| 251 |
+
id="email"
|
| 252 |
+
type="email"
|
| 253 |
+
placeholder="you@example.com"
|
| 254 |
+
value={formData.email}
|
| 255 |
+
onChange={(e) => updateFormData("email", e.target.value)}
|
| 256 |
+
className="pl-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 257 |
+
/>
|
| 258 |
+
</div>
|
| 259 |
+
</div>
|
| 260 |
+
|
| 261 |
+
<div className="space-y-2">
|
| 262 |
+
<Label htmlFor="password" className="text-white/70">Password</Label>
|
| 263 |
+
<div className="relative">
|
| 264 |
+
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 265 |
+
<Input
|
| 266 |
+
id="password"
|
| 267 |
+
type={showPassword ? "text" : "password"}
|
| 268 |
+
placeholder="β’β’β’β’β’β’β’β’"
|
| 269 |
+
value={formData.password}
|
| 270 |
+
onChange={(e) => updateFormData("password", e.target.value)}
|
| 271 |
+
className="pl-10 pr-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 272 |
+
/>
|
| 273 |
+
<button
|
| 274 |
+
type="button"
|
| 275 |
+
onClick={() => setShowPassword(!showPassword)}
|
| 276 |
+
className="absolute right-3 top-1/2 -translate-y-1/2 text-white/30 hover:text-white/50"
|
| 277 |
+
>
|
| 278 |
+
{showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
|
| 279 |
+
</button>
|
| 280 |
+
</div>
|
| 281 |
+
</div>
|
| 282 |
+
|
| 283 |
+
<AnimatePresence>
|
| 284 |
+
{error && (
|
| 285 |
+
<motion.div
|
| 286 |
+
initial={{ opacity: 0, y: -10 }}
|
| 287 |
+
animate={{ opacity: 1, y: 0 }}
|
| 288 |
+
exit={{ opacity: 0 }}
|
| 289 |
+
className="p-3 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400 text-sm"
|
| 290 |
+
>
|
| 291 |
+
{error}
|
| 292 |
+
</motion.div>
|
| 293 |
+
)}
|
| 294 |
+
</AnimatePresence>
|
| 295 |
+
|
| 296 |
+
<Button
|
| 297 |
+
type="submit"
|
| 298 |
+
disabled={isSubmitting || !formData.email || !formData.password}
|
| 299 |
+
className="w-full bg-indigo-600 hover:bg-indigo-700 text-white h-11"
|
| 300 |
+
>
|
| 301 |
+
{isSubmitting ? (
|
| 302 |
+
<>
|
| 303 |
+
<Loader2 className="w-4 h-4 mr-2 animate-spin" /> Signing in...
|
| 304 |
+
</>
|
| 305 |
+
) : (
|
| 306 |
+
"Sign In"
|
| 307 |
+
)}
|
| 308 |
+
</Button>
|
| 309 |
+
</form>
|
| 310 |
+
|
| 311 |
+
<Button
|
| 312 |
+
type="button"
|
| 313 |
+
variant="ghost"
|
| 314 |
+
onClick={onSkip}
|
| 315 |
+
className="w-full text-white/50 hover:text-white hover:bg-white/5"
|
| 316 |
+
>
|
| 317 |
+
Continue as Guest
|
| 318 |
+
</Button>
|
| 319 |
+
</CardContent>
|
| 320 |
+
<CardFooter className="flex justify-center border-t border-white/10 py-4">
|
| 321 |
+
<p className="text-center text-sm text-white/50">
|
| 322 |
+
New to Data Science Agent?{" "}
|
| 323 |
+
<button
|
| 324 |
+
onClick={() => {
|
| 325 |
+
setMode('signup');
|
| 326 |
+
setError(null);
|
| 327 |
+
setCurrentStep(0);
|
| 328 |
+
}}
|
| 329 |
+
className="text-indigo-400 hover:text-indigo-300 hover:underline"
|
| 330 |
+
>
|
| 331 |
+
Sign up
|
| 332 |
+
</button>
|
| 333 |
+
</p>
|
| 334 |
+
</CardFooter>
|
| 335 |
+
</Card>
|
| 336 |
+
</motion.div>
|
| 337 |
+
</div>
|
| 338 |
+
);
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
// Sign Up Multi-Step Form
|
| 342 |
return (
|
| 343 |
+
<div className="min-h-screen bg-[#030303] flex items-center justify-center p-4">
|
|
|
|
| 344 |
<div className="absolute inset-0 overflow-hidden">
|
| 345 |
<div className="absolute -top-40 -right-40 w-80 h-80 bg-indigo-500/10 rounded-full blur-3xl" />
|
| 346 |
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-purple-500/10 rounded-full blur-3xl" />
|
| 347 |
</div>
|
| 348 |
|
| 349 |
+
<div className="relative w-full max-w-lg py-8">
|
| 350 |
+
<motion.div
|
| 351 |
+
className="mb-8"
|
| 352 |
+
initial={{ opacity: 0, y: -20 }}
|
| 353 |
+
animate={{ opacity: 1, y: 0 }}
|
| 354 |
+
transition={{ duration: 0.5 }}
|
| 355 |
+
>
|
| 356 |
+
<div className="flex justify-between mb-2">
|
| 357 |
+
{steps.map((step, index) => (
|
| 358 |
+
<motion.div
|
| 359 |
+
key={index}
|
| 360 |
+
className="flex flex-col items-center"
|
| 361 |
+
whileHover={{ scale: 1.1 }}
|
| 362 |
+
>
|
| 363 |
+
<motion.div
|
| 364 |
+
className={cn(
|
| 365 |
+
"w-4 h-4 rounded-full cursor-pointer transition-colors duration-300",
|
| 366 |
+
index < currentStep
|
| 367 |
+
? "bg-indigo-500"
|
| 368 |
+
: index === currentStep
|
| 369 |
+
? "bg-indigo-500 ring-4 ring-indigo-500/20"
|
| 370 |
+
: "bg-white/20",
|
| 371 |
+
)}
|
| 372 |
+
onClick={() => {
|
| 373 |
+
if (index <= currentStep) {
|
| 374 |
+
setCurrentStep(index);
|
| 375 |
+
}
|
| 376 |
+
}}
|
| 377 |
+
whileTap={{ scale: 0.95 }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
/>
|
| 379 |
+
<motion.span
|
| 380 |
+
className={cn(
|
| 381 |
+
"text-xs mt-1.5 hidden sm:block",
|
| 382 |
+
index === currentStep
|
| 383 |
+
? "text-indigo-400 font-medium"
|
| 384 |
+
: "text-white/40",
|
| 385 |
+
)}
|
| 386 |
+
>
|
| 387 |
+
{step.title}
|
| 388 |
+
</motion.span>
|
| 389 |
+
</motion.div>
|
| 390 |
+
))}
|
| 391 |
</div>
|
| 392 |
+
<div className="w-full bg-white/10 h-1.5 rounded-full overflow-hidden mt-2">
|
| 393 |
+
<motion.div
|
| 394 |
+
className="h-full bg-indigo-500"
|
| 395 |
+
initial={{ width: 0 }}
|
| 396 |
+
animate={{ width: `${(currentStep / (steps.length - 1)) * 100}%` }}
|
| 397 |
+
transition={{ duration: 0.3 }}
|
| 398 |
+
/>
|
|
|
|
|
|
|
| 399 |
</div>
|
| 400 |
+
</motion.div>
|
| 401 |
|
| 402 |
+
<motion.div
|
| 403 |
+
initial={{ opacity: 0, y: 20 }}
|
| 404 |
+
animate={{ opacity: 1, y: 0 }}
|
| 405 |
+
transition={{ duration: 0.5, delay: 0.2 }}
|
| 406 |
+
>
|
| 407 |
+
<Card className="border-white/10 bg-white/[0.03] backdrop-blur-xl shadow-2xl overflow-hidden">
|
| 408 |
<div>
|
| 409 |
+
<AnimatePresence mode="wait">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 410 |
<motion.div
|
| 411 |
+
key={currentStep}
|
| 412 |
+
initial="hidden"
|
| 413 |
+
animate="visible"
|
| 414 |
+
exit="exit"
|
| 415 |
+
variants={contentVariants}
|
| 416 |
>
|
| 417 |
+
{currentStep === 0 && (
|
| 418 |
+
<>
|
| 419 |
+
<CardHeader>
|
| 420 |
+
<div className="flex justify-center mb-2">
|
| 421 |
+
<Logo className="w-10 h-10" />
|
| 422 |
+
</div>
|
| 423 |
+
<CardTitle className="text-white text-center">Create your account</CardTitle>
|
| 424 |
+
<CardDescription className="text-white/50 text-center">
|
| 425 |
+
Let's start with some basic information
|
| 426 |
+
</CardDescription>
|
| 427 |
+
</CardHeader>
|
| 428 |
+
<CardContent className="space-y-4">
|
| 429 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 430 |
+
<Label htmlFor="name" className="text-white/70">Full Name</Label>
|
| 431 |
+
<div className="relative">
|
| 432 |
+
<User className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 433 |
+
<Input
|
| 434 |
+
id="name"
|
| 435 |
+
placeholder="John Doe"
|
| 436 |
+
value={formData.name}
|
| 437 |
+
onChange={(e) => updateFormData("name", e.target.value)}
|
| 438 |
+
className="pl-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 439 |
+
/>
|
| 440 |
+
</div>
|
| 441 |
+
</motion.div>
|
| 442 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 443 |
+
<Label htmlFor="signup-email" className="text-white/70">Email Address</Label>
|
| 444 |
+
<div className="relative">
|
| 445 |
+
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 446 |
+
<Input
|
| 447 |
+
id="signup-email"
|
| 448 |
+
type="email"
|
| 449 |
+
placeholder="john@example.com"
|
| 450 |
+
value={formData.email}
|
| 451 |
+
onChange={(e) => updateFormData("email", e.target.value)}
|
| 452 |
+
className="pl-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 453 |
+
/>
|
| 454 |
+
</div>
|
| 455 |
+
</motion.div>
|
| 456 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 457 |
+
<Label htmlFor="signup-password" className="text-white/70">Password</Label>
|
| 458 |
+
<div className="relative">
|
| 459 |
+
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 460 |
+
<Input
|
| 461 |
+
id="signup-password"
|
| 462 |
+
type={showPassword ? "text" : "password"}
|
| 463 |
+
placeholder="β’β’β’β’β’β’β’β’"
|
| 464 |
+
value={formData.password}
|
| 465 |
+
onChange={(e) => updateFormData("password", e.target.value)}
|
| 466 |
+
className="pl-10 pr-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 467 |
+
/>
|
| 468 |
+
<button
|
| 469 |
+
type="button"
|
| 470 |
+
onClick={() => setShowPassword(!showPassword)}
|
| 471 |
+
className="absolute right-3 top-1/2 -translate-y-1/2 text-white/30 hover:text-white/50"
|
| 472 |
+
>
|
| 473 |
+
{showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
|
| 474 |
+
</button>
|
| 475 |
+
</div>
|
| 476 |
+
<p className="text-xs text-white/40">Minimum 6 characters</p>
|
| 477 |
+
</motion.div>
|
| 478 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 479 |
+
<Label htmlFor="confirm-password" className="text-white/70">Confirm Password</Label>
|
| 480 |
+
<div className="relative">
|
| 481 |
+
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-white/30" />
|
| 482 |
+
<Input
|
| 483 |
+
id="confirm-password"
|
| 484 |
+
type={showPassword ? "text" : "password"}
|
| 485 |
+
placeholder="β’β’β’β’β’β’β’β’"
|
| 486 |
+
value={formData.confirmPassword}
|
| 487 |
+
onChange={(e) => updateFormData("confirmPassword", e.target.value)}
|
| 488 |
+
className={cn(
|
| 489 |
+
"pl-10 bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50",
|
| 490 |
+
formData.confirmPassword && formData.password !== formData.confirmPassword && "border-red-500/50"
|
| 491 |
+
)}
|
| 492 |
+
/>
|
| 493 |
+
</div>
|
| 494 |
+
{formData.confirmPassword && formData.password !== formData.confirmPassword && (
|
| 495 |
+
<p className="text-xs text-red-400">Passwords don't match</p>
|
| 496 |
+
)}
|
| 497 |
+
</motion.div>
|
| 498 |
|
| 499 |
+
<div className="relative my-4">
|
| 500 |
+
<div className="absolute inset-0 flex items-center">
|
| 501 |
+
<div className="w-full border-t border-white/10"></div>
|
| 502 |
+
</div>
|
| 503 |
+
<div className="relative flex justify-center text-sm">
|
| 504 |
+
<span className="px-4 bg-[#0a0a0a] text-white/40">or sign up with</span>
|
| 505 |
+
</div>
|
| 506 |
+
</div>
|
| 507 |
+
|
| 508 |
+
<div className="flex gap-3">
|
| 509 |
+
<Button
|
| 510 |
+
type="button"
|
| 511 |
+
variant="outline"
|
| 512 |
+
onClick={() => handleOAuthSignIn('google')}
|
| 513 |
+
disabled={isSubmitting}
|
| 514 |
+
className="flex-1 bg-white/5 hover:bg-white/10 border-white/10 text-white"
|
| 515 |
+
>
|
| 516 |
+
<svg className="w-4 h-4 mr-2" viewBox="0 0 24 24">
|
| 517 |
+
<path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
|
| 518 |
+
<path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
|
| 519 |
+
<path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
|
| 520 |
+
<path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
|
| 521 |
+
</svg>
|
| 522 |
+
Google
|
| 523 |
+
</Button>
|
| 524 |
+
<Button
|
| 525 |
+
type="button"
|
| 526 |
+
variant="outline"
|
| 527 |
+
onClick={() => handleOAuthSignIn('github')}
|
| 528 |
+
disabled={isSubmitting}
|
| 529 |
+
className="flex-1 bg-white/5 hover:bg-white/10 border-white/10 text-white"
|
| 530 |
+
>
|
| 531 |
+
<Github className="w-4 h-4 mr-2" />
|
| 532 |
+
GitHub
|
| 533 |
+
</Button>
|
| 534 |
+
</div>
|
| 535 |
+
</CardContent>
|
| 536 |
+
</>
|
| 537 |
+
)}
|
| 538 |
+
|
| 539 |
+
{currentStep === 1 && (
|
| 540 |
+
<>
|
| 541 |
+
<CardHeader>
|
| 542 |
+
<div className="flex justify-center mb-2">
|
| 543 |
+
<div className="w-12 h-12 bg-indigo-500/10 rounded-full flex items-center justify-center">
|
| 544 |
+
<Target className="w-6 h-6 text-indigo-400" />
|
| 545 |
+
</div>
|
| 546 |
+
</div>
|
| 547 |
+
<CardTitle className="text-white text-center">Data Science Goals</CardTitle>
|
| 548 |
+
<CardDescription className="text-white/50 text-center">
|
| 549 |
+
What are you trying to achieve with data science?
|
| 550 |
+
</CardDescription>
|
| 551 |
+
</CardHeader>
|
| 552 |
+
<CardContent className="space-y-4">
|
| 553 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 554 |
+
<Label className="text-white/70">What's your primary goal?</Label>
|
| 555 |
+
<RadioGroup
|
| 556 |
+
value={formData.primaryGoal}
|
| 557 |
+
onValueChange={(value) => updateFormData("primaryGoal", value)}
|
| 558 |
+
className="space-y-2"
|
| 559 |
+
>
|
| 560 |
+
{[
|
| 561 |
+
{ value: "explore-data", label: "Explore and understand my data", icon: "π" },
|
| 562 |
+
{ value: "build-models", label: "Build predictive models", icon: "π€" },
|
| 563 |
+
{ value: "automate-analysis", label: "Automate data analysis workflows", icon: "β‘" },
|
| 564 |
+
{ value: "visualize", label: "Create data visualizations", icon: "π" },
|
| 565 |
+
{ value: "learn", label: "Learn data science concepts", icon: "π" },
|
| 566 |
+
].map((goal, index) => (
|
| 567 |
+
<motion.div
|
| 568 |
+
key={goal.value}
|
| 569 |
+
className={cn(
|
| 570 |
+
"flex items-center space-x-3 rounded-lg border p-3 cursor-pointer transition-colors",
|
| 571 |
+
formData.primaryGoal === goal.value
|
| 572 |
+
? "border-indigo-500/50 bg-indigo-500/10"
|
| 573 |
+
: "border-white/10 bg-white/5 hover:bg-white/10"
|
| 574 |
+
)}
|
| 575 |
+
whileHover={{ scale: 1.02 }}
|
| 576 |
+
whileTap={{ scale: 0.98 }}
|
| 577 |
+
onClick={() => updateFormData("primaryGoal", goal.value)}
|
| 578 |
+
initial={{ opacity: 0, x: -10 }}
|
| 579 |
+
animate={{
|
| 580 |
+
opacity: 1,
|
| 581 |
+
x: 0,
|
| 582 |
+
transition: { delay: 0.1 * index, duration: 0.3 },
|
| 583 |
+
}}
|
| 584 |
+
>
|
| 585 |
+
<RadioGroupItem value={goal.value} id={`goal-${index}`} className="border-white/30" />
|
| 586 |
+
<span className="text-lg">{goal.icon}</span>
|
| 587 |
+
<Label htmlFor={`goal-${index}`} className="cursor-pointer w-full text-white/80">
|
| 588 |
+
{goal.label}
|
| 589 |
+
</Label>
|
| 590 |
+
</motion.div>
|
| 591 |
+
))}
|
| 592 |
+
</RadioGroup>
|
| 593 |
+
</motion.div>
|
| 594 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 595 |
+
<Label htmlFor="targetOutcome" className="text-white/70">
|
| 596 |
+
What outcome are you hoping to achieve?
|
| 597 |
+
</Label>
|
| 598 |
+
<Textarea
|
| 599 |
+
id="targetOutcome"
|
| 600 |
+
placeholder="E.g., Predict customer churn, automate reporting, understand trends..."
|
| 601 |
+
value={formData.targetOutcome}
|
| 602 |
+
onChange={(e) => updateFormData("targetOutcome", e.target.value)}
|
| 603 |
+
className="min-h-[80px] bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 604 |
+
/>
|
| 605 |
+
</motion.div>
|
| 606 |
+
</CardContent>
|
| 607 |
+
</>
|
| 608 |
+
)}
|
| 609 |
+
|
| 610 |
+
{currentStep === 2 && (
|
| 611 |
+
<>
|
| 612 |
+
<CardHeader>
|
| 613 |
+
<div className="flex justify-center mb-2">
|
| 614 |
+
<div className="w-12 h-12 bg-indigo-500/10 rounded-full flex items-center justify-center">
|
| 615 |
+
<Briefcase className="w-6 h-6 text-indigo-400" />
|
| 616 |
+
</div>
|
| 617 |
+
</div>
|
| 618 |
+
<CardTitle className="text-white text-center">Professional Background</CardTitle>
|
| 619 |
+
<CardDescription className="text-white/50 text-center">
|
| 620 |
+
Tell us about your professional experience
|
| 621 |
+
</CardDescription>
|
| 622 |
+
</CardHeader>
|
| 623 |
+
<CardContent className="space-y-4">
|
| 624 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 625 |
+
<Label htmlFor="profession" className="text-white/70">What's your profession?</Label>
|
| 626 |
+
<Input
|
| 627 |
+
id="profession"
|
| 628 |
+
placeholder="e.g. Data Analyst, Business Manager, Researcher"
|
| 629 |
+
value={formData.profession}
|
| 630 |
+
onChange={(e) => updateFormData("profession", e.target.value)}
|
| 631 |
+
className="bg-white/5 border-white/10 text-white placeholder:text-white/30 focus:border-indigo-500/50"
|
| 632 |
+
/>
|
| 633 |
+
</motion.div>
|
| 634 |
+
|
| 635 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 636 |
+
<Label htmlFor="industry" className="text-white/70">What industry do you work in?</Label>
|
| 637 |
+
<Select
|
| 638 |
+
value={formData.industry}
|
| 639 |
+
onValueChange={(value) => updateFormData("industry", value)}
|
| 640 |
+
>
|
| 641 |
+
<SelectTrigger
|
| 642 |
+
id="industry"
|
| 643 |
+
className="bg-white/5 border-white/10 text-white focus:border-indigo-500/50"
|
| 644 |
+
>
|
| 645 |
+
<SelectValue placeholder="Select an industry" />
|
| 646 |
+
</SelectTrigger>
|
| 647 |
+
<SelectContent className="bg-[#1a1a1a] border-white/10">
|
| 648 |
+
<SelectItem value="technology" className="text-white hover:bg-white/10">Technology</SelectItem>
|
| 649 |
+
<SelectItem value="finance" className="text-white hover:bg-white/10">Finance & Banking</SelectItem>
|
| 650 |
+
<SelectItem value="healthcare" className="text-white hover:bg-white/10">Healthcare</SelectItem>
|
| 651 |
+
<SelectItem value="education" className="text-white hover:bg-white/10">Education</SelectItem>
|
| 652 |
+
<SelectItem value="retail" className="text-white hover:bg-white/10">Retail & E-commerce</SelectItem>
|
| 653 |
+
<SelectItem value="manufacturing" className="text-white hover:bg-white/10">Manufacturing</SelectItem>
|
| 654 |
+
<SelectItem value="consulting" className="text-white hover:bg-white/10">Consulting</SelectItem>
|
| 655 |
+
<SelectItem value="research" className="text-white hover:bg-white/10">Research & Academia</SelectItem>
|
| 656 |
+
<SelectItem value="marketing" className="text-white hover:bg-white/10">Marketing & Advertising</SelectItem>
|
| 657 |
+
<SelectItem value="other" className="text-white hover:bg-white/10">Other</SelectItem>
|
| 658 |
+
</SelectContent>
|
| 659 |
+
</Select>
|
| 660 |
+
</motion.div>
|
| 661 |
+
|
| 662 |
+
<motion.div variants={fadeInUp} className="space-y-2">
|
| 663 |
+
<Label className="text-white/70">Experience with data science</Label>
|
| 664 |
+
<RadioGroup
|
| 665 |
+
value={formData.experience}
|
| 666 |
+
onValueChange={(value) => updateFormData("experience", value)}
|
| 667 |
+
className="space-y-2"
|
| 668 |
+
>
|
| 669 |
+
{[
|
| 670 |
+
{ value: "beginner", label: "Beginner - Just getting started" },
|
| 671 |
+
{ value: "intermediate", label: "Intermediate - Some experience" },
|
| 672 |
+
{ value: "advanced", label: "Advanced - Experienced practitioner" },
|
| 673 |
+
{ value: "expert", label: "Expert - Professional data scientist" },
|
| 674 |
+
].map((level, index) => (
|
| 675 |
+
<motion.div
|
| 676 |
+
key={level.value}
|
| 677 |
+
className={cn(
|
| 678 |
+
"flex items-center space-x-3 rounded-lg border p-3 cursor-pointer transition-colors",
|
| 679 |
+
formData.experience === level.value
|
| 680 |
+
? "border-indigo-500/50 bg-indigo-500/10"
|
| 681 |
+
: "border-white/10 bg-white/5 hover:bg-white/10"
|
| 682 |
+
)}
|
| 683 |
+
whileHover={{ scale: 1.02 }}
|
| 684 |
+
whileTap={{ scale: 0.98 }}
|
| 685 |
+
onClick={() => updateFormData("experience", level.value)}
|
| 686 |
+
initial={{ opacity: 0, y: 10 }}
|
| 687 |
+
animate={{
|
| 688 |
+
opacity: 1,
|
| 689 |
+
y: 0,
|
| 690 |
+
transition: { delay: 0.1 * index, duration: 0.3 },
|
| 691 |
+
}}
|
| 692 |
+
>
|
| 693 |
+
<RadioGroupItem value={level.value} id={`exp-${index}`} className="border-white/30" />
|
| 694 |
+
<Label htmlFor={`exp-${index}`} className="cursor-pointer w-full text-white/80">
|
| 695 |
+
{level.label}
|
| 696 |
+
</Label>
|
| 697 |
+
</motion.div>
|
| 698 |
+
))}
|
| 699 |
+
</RadioGroup>
|
| 700 |
+
</motion.div>
|
| 701 |
+
|
| 702 |
+
<AnimatePresence>
|
| 703 |
+
{error && (
|
| 704 |
+
<motion.div
|
| 705 |
+
initial={{ opacity: 0, y: -10 }}
|
| 706 |
+
animate={{ opacity: 1, y: 0 }}
|
| 707 |
+
exit={{ opacity: 0 }}
|
| 708 |
+
className="p-3 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400 text-sm"
|
| 709 |
+
>
|
| 710 |
+
{error}
|
| 711 |
+
</motion.div>
|
| 712 |
+
)}
|
| 713 |
+
{success && (
|
| 714 |
+
<motion.div
|
| 715 |
+
initial={{ opacity: 0, y: -10 }}
|
| 716 |
+
animate={{ opacity: 1, y: 0 }}
|
| 717 |
+
exit={{ opacity: 0 }}
|
| 718 |
+
className="p-3 bg-green-500/10 border border-green-500/20 rounded-lg text-green-400 text-sm"
|
| 719 |
+
>
|
| 720 |
+
{success}
|
| 721 |
+
</motion.div>
|
| 722 |
+
)}
|
| 723 |
+
</AnimatePresence>
|
| 724 |
+
</CardContent>
|
| 725 |
+
</>
|
| 726 |
+
)}
|
| 727 |
</motion.div>
|
| 728 |
+
</AnimatePresence>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 729 |
|
| 730 |
+
<CardFooter className="flex justify-between pt-6 pb-4">
|
| 731 |
+
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
| 732 |
+
{currentStep === 0 ? (
|
| 733 |
+
<Button
|
| 734 |
+
type="button"
|
| 735 |
+
variant="outline"
|
| 736 |
+
onClick={() => {
|
| 737 |
+
setMode('signin');
|
| 738 |
+
setError(null);
|
| 739 |
+
}}
|
| 740 |
+
className="flex items-center gap-1 bg-white/5 hover:bg-white/10 border-white/10 text-white rounded-xl"
|
| 741 |
+
>
|
| 742 |
+
<ChevronLeft className="h-4 w-4" /> Sign In
|
| 743 |
+
</Button>
|
| 744 |
+
) : (
|
| 745 |
+
<Button
|
| 746 |
+
type="button"
|
| 747 |
+
variant="outline"
|
| 748 |
+
onClick={prevStep}
|
| 749 |
+
className="flex items-center gap-1 bg-white/5 hover:bg-white/10 border-white/10 text-white rounded-xl"
|
| 750 |
+
>
|
| 751 |
+
<ChevronLeft className="h-4 w-4" /> Back
|
| 752 |
+
</Button>
|
| 753 |
+
)}
|
| 754 |
+
</motion.div>
|
| 755 |
+
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
| 756 |
+
<Button
|
| 757 |
+
type="button"
|
| 758 |
+
onClick={currentStep === steps.length - 1 ? handleSignUp : nextStep}
|
| 759 |
+
disabled={!isStepValid() || isSubmitting}
|
| 760 |
+
className="flex items-center gap-1 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl"
|
| 761 |
+
>
|
| 762 |
+
{isSubmitting ? (
|
| 763 |
+
<>
|
| 764 |
+
<Loader2 className="h-4 w-4 animate-spin" /> Creating...
|
| 765 |
+
</>
|
| 766 |
+
) : (
|
| 767 |
+
<>
|
| 768 |
+
{currentStep === steps.length - 1 ? "Create Account" : "Next"}
|
| 769 |
+
{currentStep === steps.length - 1 ? (
|
| 770 |
+
<Check className="h-4 w-4" />
|
| 771 |
+
) : (
|
| 772 |
+
<ChevronRight className="h-4 w-4" />
|
| 773 |
+
)}
|
| 774 |
+
</>
|
| 775 |
+
)}
|
| 776 |
+
</Button>
|
| 777 |
+
</motion.div>
|
| 778 |
+
</CardFooter>
|
| 779 |
</div>
|
| 780 |
+
</Card>
|
| 781 |
+
</motion.div>
|
| 782 |
|
| 783 |
+
<motion.div
|
| 784 |
+
className="mt-4 text-center"
|
| 785 |
+
initial={{ opacity: 0 }}
|
| 786 |
+
animate={{ opacity: 1 }}
|
| 787 |
+
transition={{ duration: 0.5, delay: 0.4 }}
|
| 788 |
+
>
|
| 789 |
+
<button
|
| 790 |
+
onClick={onSkip}
|
| 791 |
+
className="text-sm text-white/40 hover:text-white/60 transition-colors"
|
| 792 |
+
>
|
| 793 |
+
Skip for now and continue as guest
|
| 794 |
+
</button>
|
| 795 |
+
</motion.div>
|
| 796 |
+
|
| 797 |
+
<motion.div
|
| 798 |
+
className="mt-4 text-center text-sm text-white/40"
|
| 799 |
+
initial={{ opacity: 0 }}
|
| 800 |
+
animate={{ opacity: 1 }}
|
| 801 |
+
transition={{ duration: 0.5, delay: 0.4 }}
|
| 802 |
+
>
|
| 803 |
+
Step {currentStep + 1} of {steps.length}: {steps[currentStep].title}
|
| 804 |
+
</motion.div>
|
| 805 |
+
</div>
|
| 806 |
</div>
|
| 807 |
);
|
| 808 |
};
|
| 809 |
+
|
| 810 |
+
export default AuthPage;
|
FRRONTEEEND/components/ui/button.tsx
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { Slot } from "@radix-ui/react-slot"
|
| 3 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 4 |
+
import { cn } from "../../lib/utils"
|
| 5 |
+
|
| 6 |
+
const buttonVariants = cva(
|
| 7 |
+
"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",
|
| 8 |
+
{
|
| 9 |
+
variants: {
|
| 10 |
+
variant: {
|
| 11 |
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
| 12 |
+
destructive:
|
| 13 |
+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
| 14 |
+
outline:
|
| 15 |
+
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
| 16 |
+
secondary:
|
| 17 |
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
| 18 |
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
| 19 |
+
link: "text-primary underline-offset-4 hover:underline",
|
| 20 |
+
},
|
| 21 |
+
size: {
|
| 22 |
+
default: "h-10 px-4 py-2",
|
| 23 |
+
sm: "h-9 rounded-md px-3",
|
| 24 |
+
lg: "h-11 rounded-md px-8",
|
| 25 |
+
icon: "h-10 w-10",
|
| 26 |
+
},
|
| 27 |
+
},
|
| 28 |
+
defaultVariants: {
|
| 29 |
+
variant: "default",
|
| 30 |
+
size: "default",
|
| 31 |
+
},
|
| 32 |
+
},
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
export interface ButtonProps
|
| 36 |
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
| 37 |
+
VariantProps<typeof buttonVariants> {
|
| 38 |
+
asChild?: boolean
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
| 42 |
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
| 43 |
+
const Comp = asChild ? Slot : "button"
|
| 44 |
+
return (
|
| 45 |
+
<Comp
|
| 46 |
+
className={cn(buttonVariants({ variant, size, className }))}
|
| 47 |
+
ref={ref}
|
| 48 |
+
{...props}
|
| 49 |
+
/>
|
| 50 |
+
)
|
| 51 |
+
},
|
| 52 |
+
)
|
| 53 |
+
Button.displayName = "Button"
|
| 54 |
+
|
| 55 |
+
export { Button, buttonVariants }
|
FRRONTEEEND/components/ui/card.tsx
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { cn } from "../../lib/utils"
|
| 3 |
+
|
| 4 |
+
const Card = React.forwardRef<
|
| 5 |
+
HTMLDivElement,
|
| 6 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 7 |
+
>(({ className, ...props }, ref) => (
|
| 8 |
+
<div
|
| 9 |
+
ref={ref}
|
| 10 |
+
className={cn(
|
| 11 |
+
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
| 12 |
+
className,
|
| 13 |
+
)}
|
| 14 |
+
{...props}
|
| 15 |
+
/>
|
| 16 |
+
))
|
| 17 |
+
Card.displayName = "Card"
|
| 18 |
+
|
| 19 |
+
const CardHeader = React.forwardRef<
|
| 20 |
+
HTMLDivElement,
|
| 21 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 22 |
+
>(({ className, ...props }, ref) => (
|
| 23 |
+
<div
|
| 24 |
+
ref={ref}
|
| 25 |
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
| 26 |
+
{...props}
|
| 27 |
+
/>
|
| 28 |
+
))
|
| 29 |
+
CardHeader.displayName = "CardHeader"
|
| 30 |
+
|
| 31 |
+
const CardTitle = React.forwardRef<
|
| 32 |
+
HTMLParagraphElement,
|
| 33 |
+
React.HTMLAttributes<HTMLHeadingElement>
|
| 34 |
+
>(({ className, ...props }, ref) => (
|
| 35 |
+
<h3
|
| 36 |
+
ref={ref}
|
| 37 |
+
className={cn(
|
| 38 |
+
"text-2xl font-semibold leading-none tracking-tight",
|
| 39 |
+
className,
|
| 40 |
+
)}
|
| 41 |
+
{...props}
|
| 42 |
+
/>
|
| 43 |
+
))
|
| 44 |
+
CardTitle.displayName = "CardTitle"
|
| 45 |
+
|
| 46 |
+
const CardDescription = React.forwardRef<
|
| 47 |
+
HTMLParagraphElement,
|
| 48 |
+
React.HTMLAttributes<HTMLParagraphElement>
|
| 49 |
+
>(({ className, ...props }, ref) => (
|
| 50 |
+
<p
|
| 51 |
+
ref={ref}
|
| 52 |
+
className={cn("text-sm text-muted-foreground", className)}
|
| 53 |
+
{...props}
|
| 54 |
+
/>
|
| 55 |
+
))
|
| 56 |
+
CardDescription.displayName = "CardDescription"
|
| 57 |
+
|
| 58 |
+
const CardContent = React.forwardRef<
|
| 59 |
+
HTMLDivElement,
|
| 60 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 61 |
+
>(({ className, ...props }, ref) => (
|
| 62 |
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
| 63 |
+
))
|
| 64 |
+
CardContent.displayName = "CardContent"
|
| 65 |
+
|
| 66 |
+
const CardFooter = React.forwardRef<
|
| 67 |
+
HTMLDivElement,
|
| 68 |
+
React.HTMLAttributes<HTMLDivElement>
|
| 69 |
+
>(({ className, ...props }, ref) => (
|
| 70 |
+
<div
|
| 71 |
+
ref={ref}
|
| 72 |
+
className={cn("flex items-center p-6 pt-0", className)}
|
| 73 |
+
{...props}
|
| 74 |
+
/>
|
| 75 |
+
))
|
| 76 |
+
CardFooter.displayName = "CardFooter"
|
| 77 |
+
|
| 78 |
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
FRRONTEEEND/components/ui/checkbox.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
| 5 |
+
import { Check } from "lucide-react"
|
| 6 |
+
import { cn } from "../../lib/utils"
|
| 7 |
+
|
| 8 |
+
const Checkbox = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
| 11 |
+
>(({ className, ...props }, ref) => (
|
| 12 |
+
<CheckboxPrimitive.Root
|
| 13 |
+
ref={ref}
|
| 14 |
+
className={cn(
|
| 15 |
+
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
| 16 |
+
className,
|
| 17 |
+
)}
|
| 18 |
+
{...props}
|
| 19 |
+
>
|
| 20 |
+
<CheckboxPrimitive.Indicator
|
| 21 |
+
className={cn("flex items-center justify-center text-current")}
|
| 22 |
+
>
|
| 23 |
+
<Check className="h-4 w-4" />
|
| 24 |
+
</CheckboxPrimitive.Indicator>
|
| 25 |
+
</CheckboxPrimitive.Root>
|
| 26 |
+
))
|
| 27 |
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
| 28 |
+
|
| 29 |
+
export { Checkbox }
|
FRRONTEEEND/components/ui/input.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { cn } from "../../lib/utils"
|
| 3 |
+
|
| 4 |
+
export interface InputProps
|
| 5 |
+
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
| 6 |
+
|
| 7 |
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
| 8 |
+
({ className, type, ...props }, ref) => {
|
| 9 |
+
return (
|
| 10 |
+
<input
|
| 11 |
+
type={type}
|
| 12 |
+
className={cn(
|
| 13 |
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
| 14 |
+
className
|
| 15 |
+
)}
|
| 16 |
+
ref={ref}
|
| 17 |
+
{...props}
|
| 18 |
+
/>
|
| 19 |
+
)
|
| 20 |
+
}
|
| 21 |
+
)
|
| 22 |
+
Input.displayName = "Input"
|
| 23 |
+
|
| 24 |
+
export { Input }
|
FRRONTEEEND/components/ui/label.tsx
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
| 5 |
+
import { cva, type VariantProps } from "class-variance-authority"
|
| 6 |
+
import { cn } from "../../lib/utils"
|
| 7 |
+
|
| 8 |
+
const labelVariants = cva(
|
| 9 |
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
const Label = React.forwardRef<
|
| 13 |
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
| 14 |
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
| 15 |
+
VariantProps<typeof labelVariants>
|
| 16 |
+
>(({ className, ...props }, ref) => (
|
| 17 |
+
<LabelPrimitive.Root
|
| 18 |
+
ref={ref}
|
| 19 |
+
className={cn(labelVariants(), className)}
|
| 20 |
+
{...props}
|
| 21 |
+
/>
|
| 22 |
+
))
|
| 23 |
+
Label.displayName = LabelPrimitive.Root.displayName
|
| 24 |
+
|
| 25 |
+
export { Label }
|
FRRONTEEEND/components/ui/radio-group.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
| 5 |
+
import { Circle } from "lucide-react"
|
| 6 |
+
import { cn } from "../../lib/utils"
|
| 7 |
+
|
| 8 |
+
const RadioGroup = React.forwardRef<
|
| 9 |
+
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
| 10 |
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
| 11 |
+
>(({ className, ...props }, ref) => {
|
| 12 |
+
return (
|
| 13 |
+
<RadioGroupPrimitive.Root
|
| 14 |
+
className={cn("grid gap-2", className)}
|
| 15 |
+
{...props}
|
| 16 |
+
ref={ref}
|
| 17 |
+
/>
|
| 18 |
+
)
|
| 19 |
+
})
|
| 20 |
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
|
| 21 |
+
|
| 22 |
+
const RadioGroupItem = React.forwardRef<
|
| 23 |
+
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
| 24 |
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
|
| 25 |
+
>(({ className, ...props }, ref) => {
|
| 26 |
+
return (
|
| 27 |
+
<RadioGroupPrimitive.Item
|
| 28 |
+
ref={ref}
|
| 29 |
+
className={cn(
|
| 30 |
+
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
| 31 |
+
className,
|
| 32 |
+
)}
|
| 33 |
+
{...props}
|
| 34 |
+
>
|
| 35 |
+
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
| 36 |
+
<Circle className="h-2.5 w-2.5 fill-current text-current" />
|
| 37 |
+
</RadioGroupPrimitive.Indicator>
|
| 38 |
+
</RadioGroupPrimitive.Item>
|
| 39 |
+
)
|
| 40 |
+
})
|
| 41 |
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
|
| 42 |
+
|
| 43 |
+
export { RadioGroup, RadioGroupItem }
|
FRRONTEEEND/components/ui/select.tsx
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
|
| 3 |
+
import * as React from "react"
|
| 4 |
+
import * as SelectPrimitive from "@radix-ui/react-select"
|
| 5 |
+
import { Check, ChevronDown, ChevronUp } from "lucide-react"
|
| 6 |
+
import { cn } from "../../lib/utils"
|
| 7 |
+
|
| 8 |
+
const Select = SelectPrimitive.Root
|
| 9 |
+
|
| 10 |
+
const SelectGroup = SelectPrimitive.Group
|
| 11 |
+
|
| 12 |
+
const SelectValue = SelectPrimitive.Value
|
| 13 |
+
|
| 14 |
+
const SelectTrigger = React.forwardRef<
|
| 15 |
+
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
| 16 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
| 17 |
+
>(({ className, children, ...props }, ref) => (
|
| 18 |
+
<SelectPrimitive.Trigger
|
| 19 |
+
ref={ref}
|
| 20 |
+
className={cn(
|
| 21 |
+
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
| 22 |
+
className,
|
| 23 |
+
)}
|
| 24 |
+
{...props}
|
| 25 |
+
>
|
| 26 |
+
{children}
|
| 27 |
+
<SelectPrimitive.Icon asChild>
|
| 28 |
+
<ChevronDown className="h-4 w-4 opacity-50" />
|
| 29 |
+
</SelectPrimitive.Icon>
|
| 30 |
+
</SelectPrimitive.Trigger>
|
| 31 |
+
))
|
| 32 |
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
| 33 |
+
|
| 34 |
+
const SelectScrollUpButton = React.forwardRef<
|
| 35 |
+
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
| 36 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
| 37 |
+
>(({ className, ...props }, ref) => (
|
| 38 |
+
<SelectPrimitive.ScrollUpButton
|
| 39 |
+
ref={ref}
|
| 40 |
+
className={cn(
|
| 41 |
+
"flex cursor-default items-center justify-center py-1",
|
| 42 |
+
className,
|
| 43 |
+
)}
|
| 44 |
+
{...props}
|
| 45 |
+
>
|
| 46 |
+
<ChevronUp className="h-4 w-4" />
|
| 47 |
+
</SelectPrimitive.ScrollUpButton>
|
| 48 |
+
))
|
| 49 |
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
|
| 50 |
+
|
| 51 |
+
const SelectScrollDownButton = React.forwardRef<
|
| 52 |
+
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
| 53 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
| 54 |
+
>(({ className, ...props }, ref) => (
|
| 55 |
+
<SelectPrimitive.ScrollDownButton
|
| 56 |
+
ref={ref}
|
| 57 |
+
className={cn(
|
| 58 |
+
"flex cursor-default items-center justify-center py-1",
|
| 59 |
+
className,
|
| 60 |
+
)}
|
| 61 |
+
{...props}
|
| 62 |
+
>
|
| 63 |
+
<ChevronDown className="h-4 w-4" />
|
| 64 |
+
</SelectPrimitive.ScrollDownButton>
|
| 65 |
+
))
|
| 66 |
+
SelectScrollDownButton.displayName =
|
| 67 |
+
SelectPrimitive.ScrollDownButton.displayName
|
| 68 |
+
|
| 69 |
+
const SelectContent = React.forwardRef<
|
| 70 |
+
React.ElementRef<typeof SelectPrimitive.Content>,
|
| 71 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
| 72 |
+
>(({ className, children, position = "popper", ...props }, ref) => (
|
| 73 |
+
<SelectPrimitive.Portal>
|
| 74 |
+
<SelectPrimitive.Content
|
| 75 |
+
ref={ref}
|
| 76 |
+
className={cn(
|
| 77 |
+
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
| 78 |
+
position === "popper" &&
|
| 79 |
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
| 80 |
+
className,
|
| 81 |
+
)}
|
| 82 |
+
position={position}
|
| 83 |
+
{...props}
|
| 84 |
+
>
|
| 85 |
+
<SelectScrollUpButton />
|
| 86 |
+
<SelectPrimitive.Viewport
|
| 87 |
+
className={cn(
|
| 88 |
+
"p-1",
|
| 89 |
+
position === "popper" &&
|
| 90 |
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
| 91 |
+
)}
|
| 92 |
+
>
|
| 93 |
+
{children}
|
| 94 |
+
</SelectPrimitive.Viewport>
|
| 95 |
+
<SelectScrollDownButton />
|
| 96 |
+
</SelectPrimitive.Content>
|
| 97 |
+
</SelectPrimitive.Portal>
|
| 98 |
+
))
|
| 99 |
+
SelectContent.displayName = SelectPrimitive.Content.displayName
|
| 100 |
+
|
| 101 |
+
const SelectLabel = React.forwardRef<
|
| 102 |
+
React.ElementRef<typeof SelectPrimitive.Label>,
|
| 103 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
| 104 |
+
>(({ className, ...props }, ref) => (
|
| 105 |
+
<SelectPrimitive.Label
|
| 106 |
+
ref={ref}
|
| 107 |
+
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
|
| 108 |
+
{...props}
|
| 109 |
+
/>
|
| 110 |
+
))
|
| 111 |
+
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
| 112 |
+
|
| 113 |
+
const SelectItem = React.forwardRef<
|
| 114 |
+
React.ElementRef<typeof SelectPrimitive.Item>,
|
| 115 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
| 116 |
+
>(({ className, children, ...props }, ref) => (
|
| 117 |
+
<SelectPrimitive.Item
|
| 118 |
+
ref={ref}
|
| 119 |
+
className={cn(
|
| 120 |
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
| 121 |
+
className,
|
| 122 |
+
)}
|
| 123 |
+
{...props}
|
| 124 |
+
>
|
| 125 |
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
| 126 |
+
<SelectPrimitive.ItemIndicator>
|
| 127 |
+
<Check className="h-4 w-4" />
|
| 128 |
+
</SelectPrimitive.ItemIndicator>
|
| 129 |
+
</span>
|
| 130 |
+
|
| 131 |
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
| 132 |
+
</SelectPrimitive.Item>
|
| 133 |
+
))
|
| 134 |
+
SelectItem.displayName = SelectPrimitive.Item.displayName
|
| 135 |
+
|
| 136 |
+
const SelectSeparator = React.forwardRef<
|
| 137 |
+
React.ElementRef<typeof SelectPrimitive.Separator>,
|
| 138 |
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
| 139 |
+
>(({ className, ...props }, ref) => (
|
| 140 |
+
<SelectPrimitive.Separator
|
| 141 |
+
ref={ref}
|
| 142 |
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
| 143 |
+
{...props}
|
| 144 |
+
/>
|
| 145 |
+
))
|
| 146 |
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
| 147 |
+
|
| 148 |
+
export {
|
| 149 |
+
Select,
|
| 150 |
+
SelectGroup,
|
| 151 |
+
SelectValue,
|
| 152 |
+
SelectTrigger,
|
| 153 |
+
SelectContent,
|
| 154 |
+
SelectLabel,
|
| 155 |
+
SelectItem,
|
| 156 |
+
SelectSeparator,
|
| 157 |
+
SelectScrollUpButton,
|
| 158 |
+
SelectScrollDownButton,
|
| 159 |
+
}
|
FRRONTEEEND/components/ui/textarea.tsx
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as React from "react"
|
| 2 |
+
import { cn } from "../../lib/utils"
|
| 3 |
+
|
| 4 |
+
export interface TextareaProps
|
| 5 |
+
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
| 6 |
+
|
| 7 |
+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
| 8 |
+
({ className, ...props }, ref) => {
|
| 9 |
+
return (
|
| 10 |
+
<textarea
|
| 11 |
+
className={cn(
|
| 12 |
+
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
| 13 |
+
className
|
| 14 |
+
)}
|
| 15 |
+
ref={ref}
|
| 16 |
+
{...props}
|
| 17 |
+
/>
|
| 18 |
+
)
|
| 19 |
+
}
|
| 20 |
+
)
|
| 21 |
+
Textarea.displayName = "Textarea"
|
| 22 |
+
|
| 23 |
+
export { Textarea }
|
FRRONTEEEND/index.html
CHANGED
|
@@ -23,6 +23,29 @@
|
|
| 23 |
}
|
| 24 |
</script>
|
| 25 |
<style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
body {
|
| 27 |
margin: 0;
|
| 28 |
background-color: #030303;
|
|
@@ -35,6 +58,38 @@
|
|
| 35 |
background-color: rgba(99, 102, 241, 0.3);
|
| 36 |
color: white;
|
| 37 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
</style>
|
| 39 |
<script type="importmap">
|
| 40 |
{
|
|
|
|
| 23 |
}
|
| 24 |
</script>
|
| 25 |
<style>
|
| 26 |
+
:root {
|
| 27 |
+
--background: 0 0% 1%;
|
| 28 |
+
--foreground: 0 0% 98%;
|
| 29 |
+
--card: 0 0% 3%;
|
| 30 |
+
--card-foreground: 0 0% 98%;
|
| 31 |
+
--popover: 0 0% 6%;
|
| 32 |
+
--popover-foreground: 0 0% 98%;
|
| 33 |
+
--primary: 239 84% 67%;
|
| 34 |
+
--primary-foreground: 0 0% 100%;
|
| 35 |
+
--secondary: 0 0% 10%;
|
| 36 |
+
--secondary-foreground: 0 0% 98%;
|
| 37 |
+
--muted: 0 0% 15%;
|
| 38 |
+
--muted-foreground: 0 0% 64%;
|
| 39 |
+
--accent: 0 0% 15%;
|
| 40 |
+
--accent-foreground: 0 0% 98%;
|
| 41 |
+
--destructive: 0 62.8% 30.6%;
|
| 42 |
+
--destructive-foreground: 0 0% 98%;
|
| 43 |
+
--border: 0 0% 14.9%;
|
| 44 |
+
--input: 0 0% 14.9%;
|
| 45 |
+
--ring: 239 84% 67%;
|
| 46 |
+
--radius: 0.75rem;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
body {
|
| 50 |
margin: 0;
|
| 51 |
background-color: #030303;
|
|
|
|
| 58 |
background-color: rgba(99, 102, 241, 0.3);
|
| 59 |
color: white;
|
| 60 |
}
|
| 61 |
+
|
| 62 |
+
/* Shadcn color utilities */
|
| 63 |
+
.bg-background { background-color: hsl(var(--background)); }
|
| 64 |
+
.bg-card { background-color: hsl(var(--card)); }
|
| 65 |
+
.bg-popover { background-color: hsl(var(--popover)); }
|
| 66 |
+
.bg-primary { background-color: hsl(var(--primary)); }
|
| 67 |
+
.bg-secondary { background-color: hsl(var(--secondary)); }
|
| 68 |
+
.bg-muted { background-color: hsl(var(--muted)); }
|
| 69 |
+
.bg-accent { background-color: hsl(var(--accent)); }
|
| 70 |
+
.bg-destructive { background-color: hsl(var(--destructive)); }
|
| 71 |
+
|
| 72 |
+
.text-foreground { color: hsl(var(--foreground)); }
|
| 73 |
+
.text-card-foreground { color: hsl(var(--card-foreground)); }
|
| 74 |
+
.text-popover-foreground { color: hsl(var(--popover-foreground)); }
|
| 75 |
+
.text-primary { color: hsl(var(--primary)); }
|
| 76 |
+
.text-primary-foreground { color: hsl(var(--primary-foreground)); }
|
| 77 |
+
.text-secondary-foreground { color: hsl(var(--secondary-foreground)); }
|
| 78 |
+
.text-muted-foreground { color: hsl(var(--muted-foreground)); }
|
| 79 |
+
.text-accent-foreground { color: hsl(var(--accent-foreground)); }
|
| 80 |
+
.text-destructive { color: hsl(var(--destructive)); }
|
| 81 |
+
.text-destructive-foreground { color: hsl(var(--destructive-foreground)); }
|
| 82 |
+
|
| 83 |
+
.border-border { border-color: hsl(var(--border)); }
|
| 84 |
+
.border-input { border-color: hsl(var(--input)); }
|
| 85 |
+
.border-primary { border-color: hsl(var(--primary)); }
|
| 86 |
+
|
| 87 |
+
.ring-ring { --tw-ring-color: hsl(var(--ring)); }
|
| 88 |
+
.ring-offset-background { --tw-ring-offset-color: hsl(var(--background)); }
|
| 89 |
+
|
| 90 |
+
/* Focus ring styles */
|
| 91 |
+
.focus-visible\\:ring-ring:focus-visible { --tw-ring-color: hsl(var(--ring)); }
|
| 92 |
+
.focus-visible\\:ring-offset-2:focus-visible { --tw-ring-offset-width: 2px; }
|
| 93 |
</style>
|
| 94 |
<script type="importmap">
|
| 95 |
{
|
FRRONTEEEND/lib/AuthContext.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import React, { createContext, useContext, useEffect, useState } from 'react';
|
| 2 |
import { User, Session, AuthChangeEvent } from '@supabase/supabase-js';
|
| 3 |
-
import { supabase, startUserSession, endUserSession } from './supabase';
|
| 4 |
|
| 5 |
interface AuthContextType {
|
| 6 |
user: User | null;
|
|
@@ -13,6 +13,7 @@ interface AuthContextType {
|
|
| 13 |
signInWithGithub: () => Promise<{ error: any }>;
|
| 14 |
signOut: () => Promise<void>;
|
| 15 |
isAuthenticated: boolean;
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
@@ -22,8 +23,15 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|
| 22 |
const [session, setSession] = useState<Session | null>(null);
|
| 23 |
const [dbSessionId, setDbSessionId] = useState<string | null>(null);
|
| 24 |
const [loading, setLoading] = useState(true);
|
|
|
|
| 25 |
|
| 26 |
useEffect(() => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
// Get initial session
|
| 28 |
supabase.auth.getSession().then(({ data: { session } }) => {
|
| 29 |
setSession(session);
|
|
@@ -38,6 +46,9 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|
| 38 |
}
|
| 39 |
});
|
| 40 |
}
|
|
|
|
|
|
|
|
|
|
| 41 |
});
|
| 42 |
|
| 43 |
// Listen for auth changes
|
|
@@ -71,7 +82,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|
| 71 |
endUserSession(dbSessionId);
|
| 72 |
}
|
| 73 |
};
|
| 74 |
-
}, []);
|
| 75 |
|
| 76 |
const signIn = async (email: string, password: string) => {
|
| 77 |
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
@@ -123,7 +134,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|
| 123 |
signInWithGoogle,
|
| 124 |
signInWithGithub,
|
| 125 |
signOut,
|
| 126 |
-
isAuthenticated: !!user
|
|
|
|
| 127 |
}}
|
| 128 |
>
|
| 129 |
{children}
|
|
|
|
| 1 |
import React, { createContext, useContext, useEffect, useState } from 'react';
|
| 2 |
import { User, Session, AuthChangeEvent } from '@supabase/supabase-js';
|
| 3 |
+
import { supabase, startUserSession, endUserSession, isSupabaseConfigured } from './supabase';
|
| 4 |
|
| 5 |
interface AuthContextType {
|
| 6 |
user: User | null;
|
|
|
|
| 13 |
signInWithGithub: () => Promise<{ error: any }>;
|
| 14 |
signOut: () => Promise<void>;
|
| 15 |
isAuthenticated: boolean;
|
| 16 |
+
isConfigured: boolean;
|
| 17 |
}
|
| 18 |
|
| 19 |
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
| 23 |
const [session, setSession] = useState<Session | null>(null);
|
| 24 |
const [dbSessionId, setDbSessionId] = useState<string | null>(null);
|
| 25 |
const [loading, setLoading] = useState(true);
|
| 26 |
+
const configured = isSupabaseConfigured();
|
| 27 |
|
| 28 |
useEffect(() => {
|
| 29 |
+
// If Supabase is not configured, skip auth initialization
|
| 30 |
+
if (!configured) {
|
| 31 |
+
setLoading(false);
|
| 32 |
+
return;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
// Get initial session
|
| 36 |
supabase.auth.getSession().then(({ data: { session } }) => {
|
| 37 |
setSession(session);
|
|
|
|
| 46 |
}
|
| 47 |
});
|
| 48 |
}
|
| 49 |
+
}).catch((err) => {
|
| 50 |
+
console.error('Failed to get session:', err);
|
| 51 |
+
setLoading(false);
|
| 52 |
});
|
| 53 |
|
| 54 |
// Listen for auth changes
|
|
|
|
| 82 |
endUserSession(dbSessionId);
|
| 83 |
}
|
| 84 |
};
|
| 85 |
+
}, [configured]);
|
| 86 |
|
| 87 |
const signIn = async (email: string, password: string) => {
|
| 88 |
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
|
|
| 134 |
signInWithGoogle,
|
| 135 |
signInWithGithub,
|
| 136 |
signOut,
|
| 137 |
+
isAuthenticated: !!user,
|
| 138 |
+
isConfigured: configured
|
| 139 |
}}
|
| 140 |
>
|
| 141 |
{children}
|
FRRONTEEEND/lib/supabase.ts
CHANGED
|
@@ -4,8 +4,13 @@ import { createClient } from '@supabase/supabase-js';
|
|
| 4 |
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL || '';
|
| 5 |
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
// Create Supabase client
|
| 8 |
-
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
|
| 9 |
|
| 10 |
// Types for our analytics
|
| 11 |
export interface UsageAnalytics {
|
|
|
|
| 4 |
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL || '';
|
| 5 |
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
|
| 6 |
|
| 7 |
+
// Check if Supabase is configured
|
| 8 |
+
export const isSupabaseConfigured = () => {
|
| 9 |
+
return !!(supabaseUrl && supabaseAnonKey && supabaseUrl.includes('supabase'));
|
| 10 |
+
};
|
| 11 |
+
|
| 12 |
// Create Supabase client
|
| 13 |
+
export const supabase = createClient(supabaseUrl || 'https://placeholder.supabase.co', supabaseAnonKey || 'placeholder');
|
| 14 |
|
| 15 |
// Types for our analytics
|
| 16 |
export interface UsageAnalytics {
|
FRRONTEEEND/package-lock.json
CHANGED
|
@@ -8,13 +8,20 @@
|
|
| 8 |
"name": "data-science-agent",
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"@supabase/supabase-js": "^2.93.3",
|
|
|
|
| 12 |
"clsx": "^2.1.1",
|
| 13 |
"framer-motion": "^12.23.26",
|
| 14 |
"lucide-react": "^0.562.0",
|
| 15 |
"react": "^19.2.3",
|
| 16 |
"react-dom": "^19.2.3",
|
| 17 |
"react-markdown": "^9.0.1",
|
|
|
|
| 18 |
"tailwind-merge": "^3.4.0"
|
| 19 |
},
|
| 20 |
"devDependencies": {
|
|
@@ -749,6 +756,44 @@
|
|
| 749 |
"node": ">=18"
|
| 750 |
}
|
| 751 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 752 |
"node_modules/@jridgewell/gen-mapping": {
|
| 753 |
"version": "0.3.13",
|
| 754 |
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
|
@@ -799,6 +844,719 @@
|
|
| 799 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
| 800 |
}
|
| 801 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 802 |
"node_modules/@rolldown/pluginutils": {
|
| 803 |
"version": "1.0.0-beta.53",
|
| 804 |
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
|
|
@@ -1354,6 +2112,18 @@
|
|
| 1354 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
| 1355 |
}
|
| 1356 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1357 |
"node_modules/bail": {
|
| 1358 |
"version": "2.0.2",
|
| 1359 |
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
|
@@ -1480,6 +2250,18 @@
|
|
| 1480 |
"url": "https://github.com/sponsors/wooorm"
|
| 1481 |
}
|
| 1482 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1483 |
"node_modules/clsx": {
|
| 1484 |
"version": "2.1.1",
|
| 1485 |
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
|
@@ -1551,6 +2333,12 @@
|
|
| 1551 |
"node": ">=6"
|
| 1552 |
}
|
| 1553 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1554 |
"node_modules/devlop": {
|
| 1555 |
"version": "1.1.0",
|
| 1556 |
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
|
@@ -1709,6 +2497,15 @@
|
|
| 1709 |
"node": ">=6.9.0"
|
| 1710 |
}
|
| 1711 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1712 |
"node_modules/hast-util-to-jsx-runtime": {
|
| 1713 |
"version": "2.3.6",
|
| 1714 |
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
|
@@ -2679,6 +3476,75 @@
|
|
| 2679 |
"node": ">=0.10.0"
|
| 2680 |
}
|
| 2681 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2682 |
"node_modules/remark-parse": {
|
| 2683 |
"version": "11.0.0",
|
| 2684 |
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
|
|
@@ -2770,6 +3636,16 @@
|
|
| 2770 |
"semver": "bin/semver.js"
|
| 2771 |
}
|
| 2772 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2773 |
"node_modules/source-map-js": {
|
| 2774 |
"version": "1.2.1",
|
| 2775 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
@@ -3013,6 +3889,49 @@
|
|
| 3013 |
"browserslist": ">= 4.21.0"
|
| 3014 |
}
|
| 3015 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3016 |
"node_modules/vfile": {
|
| 3017 |
"version": "6.0.3",
|
| 3018 |
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
|
|
|
| 8 |
"name": "data-science-agent",
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
+
"@radix-ui/react-checkbox": "^1.3.3",
|
| 12 |
+
"@radix-ui/react-label": "^2.1.8",
|
| 13 |
+
"@radix-ui/react-radio-group": "^1.3.8",
|
| 14 |
+
"@radix-ui/react-select": "^2.2.6",
|
| 15 |
+
"@radix-ui/react-slot": "^1.2.4",
|
| 16 |
"@supabase/supabase-js": "^2.93.3",
|
| 17 |
+
"class-variance-authority": "^0.7.1",
|
| 18 |
"clsx": "^2.1.1",
|
| 19 |
"framer-motion": "^12.23.26",
|
| 20 |
"lucide-react": "^0.562.0",
|
| 21 |
"react": "^19.2.3",
|
| 22 |
"react-dom": "^19.2.3",
|
| 23 |
"react-markdown": "^9.0.1",
|
| 24 |
+
"sonner": "^2.0.7",
|
| 25 |
"tailwind-merge": "^3.4.0"
|
| 26 |
},
|
| 27 |
"devDependencies": {
|
|
|
|
| 756 |
"node": ">=18"
|
| 757 |
}
|
| 758 |
},
|
| 759 |
+
"node_modules/@floating-ui/core": {
|
| 760 |
+
"version": "1.7.4",
|
| 761 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
|
| 762 |
+
"integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
|
| 763 |
+
"license": "MIT",
|
| 764 |
+
"dependencies": {
|
| 765 |
+
"@floating-ui/utils": "^0.2.10"
|
| 766 |
+
}
|
| 767 |
+
},
|
| 768 |
+
"node_modules/@floating-ui/dom": {
|
| 769 |
+
"version": "1.7.5",
|
| 770 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz",
|
| 771 |
+
"integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
|
| 772 |
+
"license": "MIT",
|
| 773 |
+
"dependencies": {
|
| 774 |
+
"@floating-ui/core": "^1.7.4",
|
| 775 |
+
"@floating-ui/utils": "^0.2.10"
|
| 776 |
+
}
|
| 777 |
+
},
|
| 778 |
+
"node_modules/@floating-ui/react-dom": {
|
| 779 |
+
"version": "2.1.7",
|
| 780 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz",
|
| 781 |
+
"integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==",
|
| 782 |
+
"license": "MIT",
|
| 783 |
+
"dependencies": {
|
| 784 |
+
"@floating-ui/dom": "^1.7.5"
|
| 785 |
+
},
|
| 786 |
+
"peerDependencies": {
|
| 787 |
+
"react": ">=16.8.0",
|
| 788 |
+
"react-dom": ">=16.8.0"
|
| 789 |
+
}
|
| 790 |
+
},
|
| 791 |
+
"node_modules/@floating-ui/utils": {
|
| 792 |
+
"version": "0.2.10",
|
| 793 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
|
| 794 |
+
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
|
| 795 |
+
"license": "MIT"
|
| 796 |
+
},
|
| 797 |
"node_modules/@jridgewell/gen-mapping": {
|
| 798 |
"version": "0.3.13",
|
| 799 |
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
|
|
|
| 844 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
| 845 |
}
|
| 846 |
},
|
| 847 |
+
"node_modules/@radix-ui/number": {
|
| 848 |
+
"version": "1.1.1",
|
| 849 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
|
| 850 |
+
"integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
|
| 851 |
+
"license": "MIT"
|
| 852 |
+
},
|
| 853 |
+
"node_modules/@radix-ui/primitive": {
|
| 854 |
+
"version": "1.1.3",
|
| 855 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
|
| 856 |
+
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
|
| 857 |
+
"license": "MIT"
|
| 858 |
+
},
|
| 859 |
+
"node_modules/@radix-ui/react-arrow": {
|
| 860 |
+
"version": "1.1.7",
|
| 861 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
|
| 862 |
+
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
|
| 863 |
+
"license": "MIT",
|
| 864 |
+
"dependencies": {
|
| 865 |
+
"@radix-ui/react-primitive": "2.1.3"
|
| 866 |
+
},
|
| 867 |
+
"peerDependencies": {
|
| 868 |
+
"@types/react": "*",
|
| 869 |
+
"@types/react-dom": "*",
|
| 870 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 871 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 872 |
+
},
|
| 873 |
+
"peerDependenciesMeta": {
|
| 874 |
+
"@types/react": {
|
| 875 |
+
"optional": true
|
| 876 |
+
},
|
| 877 |
+
"@types/react-dom": {
|
| 878 |
+
"optional": true
|
| 879 |
+
}
|
| 880 |
+
}
|
| 881 |
+
},
|
| 882 |
+
"node_modules/@radix-ui/react-checkbox": {
|
| 883 |
+
"version": "1.3.3",
|
| 884 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
|
| 885 |
+
"integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
|
| 886 |
+
"license": "MIT",
|
| 887 |
+
"dependencies": {
|
| 888 |
+
"@radix-ui/primitive": "1.1.3",
|
| 889 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 890 |
+
"@radix-ui/react-context": "1.1.2",
|
| 891 |
+
"@radix-ui/react-presence": "1.1.5",
|
| 892 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 893 |
+
"@radix-ui/react-use-controllable-state": "1.2.2",
|
| 894 |
+
"@radix-ui/react-use-previous": "1.1.1",
|
| 895 |
+
"@radix-ui/react-use-size": "1.1.1"
|
| 896 |
+
},
|
| 897 |
+
"peerDependencies": {
|
| 898 |
+
"@types/react": "*",
|
| 899 |
+
"@types/react-dom": "*",
|
| 900 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 901 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 902 |
+
},
|
| 903 |
+
"peerDependenciesMeta": {
|
| 904 |
+
"@types/react": {
|
| 905 |
+
"optional": true
|
| 906 |
+
},
|
| 907 |
+
"@types/react-dom": {
|
| 908 |
+
"optional": true
|
| 909 |
+
}
|
| 910 |
+
}
|
| 911 |
+
},
|
| 912 |
+
"node_modules/@radix-ui/react-collection": {
|
| 913 |
+
"version": "1.1.7",
|
| 914 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
|
| 915 |
+
"integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
|
| 916 |
+
"license": "MIT",
|
| 917 |
+
"dependencies": {
|
| 918 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 919 |
+
"@radix-ui/react-context": "1.1.2",
|
| 920 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 921 |
+
"@radix-ui/react-slot": "1.2.3"
|
| 922 |
+
},
|
| 923 |
+
"peerDependencies": {
|
| 924 |
+
"@types/react": "*",
|
| 925 |
+
"@types/react-dom": "*",
|
| 926 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 927 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 928 |
+
},
|
| 929 |
+
"peerDependenciesMeta": {
|
| 930 |
+
"@types/react": {
|
| 931 |
+
"optional": true
|
| 932 |
+
},
|
| 933 |
+
"@types/react-dom": {
|
| 934 |
+
"optional": true
|
| 935 |
+
}
|
| 936 |
+
}
|
| 937 |
+
},
|
| 938 |
+
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
|
| 939 |
+
"version": "1.2.3",
|
| 940 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
| 941 |
+
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
|
| 942 |
+
"license": "MIT",
|
| 943 |
+
"dependencies": {
|
| 944 |
+
"@radix-ui/react-compose-refs": "1.1.2"
|
| 945 |
+
},
|
| 946 |
+
"peerDependencies": {
|
| 947 |
+
"@types/react": "*",
|
| 948 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 949 |
+
},
|
| 950 |
+
"peerDependenciesMeta": {
|
| 951 |
+
"@types/react": {
|
| 952 |
+
"optional": true
|
| 953 |
+
}
|
| 954 |
+
}
|
| 955 |
+
},
|
| 956 |
+
"node_modules/@radix-ui/react-compose-refs": {
|
| 957 |
+
"version": "1.1.2",
|
| 958 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
| 959 |
+
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
|
| 960 |
+
"license": "MIT",
|
| 961 |
+
"peerDependencies": {
|
| 962 |
+
"@types/react": "*",
|
| 963 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 964 |
+
},
|
| 965 |
+
"peerDependenciesMeta": {
|
| 966 |
+
"@types/react": {
|
| 967 |
+
"optional": true
|
| 968 |
+
}
|
| 969 |
+
}
|
| 970 |
+
},
|
| 971 |
+
"node_modules/@radix-ui/react-context": {
|
| 972 |
+
"version": "1.1.2",
|
| 973 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
|
| 974 |
+
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
|
| 975 |
+
"license": "MIT",
|
| 976 |
+
"peerDependencies": {
|
| 977 |
+
"@types/react": "*",
|
| 978 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 979 |
+
},
|
| 980 |
+
"peerDependenciesMeta": {
|
| 981 |
+
"@types/react": {
|
| 982 |
+
"optional": true
|
| 983 |
+
}
|
| 984 |
+
}
|
| 985 |
+
},
|
| 986 |
+
"node_modules/@radix-ui/react-direction": {
|
| 987 |
+
"version": "1.1.1",
|
| 988 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
|
| 989 |
+
"integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
|
| 990 |
+
"license": "MIT",
|
| 991 |
+
"peerDependencies": {
|
| 992 |
+
"@types/react": "*",
|
| 993 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 994 |
+
},
|
| 995 |
+
"peerDependenciesMeta": {
|
| 996 |
+
"@types/react": {
|
| 997 |
+
"optional": true
|
| 998 |
+
}
|
| 999 |
+
}
|
| 1000 |
+
},
|
| 1001 |
+
"node_modules/@radix-ui/react-dismissable-layer": {
|
| 1002 |
+
"version": "1.1.11",
|
| 1003 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
|
| 1004 |
+
"integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
|
| 1005 |
+
"license": "MIT",
|
| 1006 |
+
"dependencies": {
|
| 1007 |
+
"@radix-ui/primitive": "1.1.3",
|
| 1008 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1009 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1010 |
+
"@radix-ui/react-use-callback-ref": "1.1.1",
|
| 1011 |
+
"@radix-ui/react-use-escape-keydown": "1.1.1"
|
| 1012 |
+
},
|
| 1013 |
+
"peerDependencies": {
|
| 1014 |
+
"@types/react": "*",
|
| 1015 |
+
"@types/react-dom": "*",
|
| 1016 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1017 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1018 |
+
},
|
| 1019 |
+
"peerDependenciesMeta": {
|
| 1020 |
+
"@types/react": {
|
| 1021 |
+
"optional": true
|
| 1022 |
+
},
|
| 1023 |
+
"@types/react-dom": {
|
| 1024 |
+
"optional": true
|
| 1025 |
+
}
|
| 1026 |
+
}
|
| 1027 |
+
},
|
| 1028 |
+
"node_modules/@radix-ui/react-focus-guards": {
|
| 1029 |
+
"version": "1.1.3",
|
| 1030 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
|
| 1031 |
+
"integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
|
| 1032 |
+
"license": "MIT",
|
| 1033 |
+
"peerDependencies": {
|
| 1034 |
+
"@types/react": "*",
|
| 1035 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1036 |
+
},
|
| 1037 |
+
"peerDependenciesMeta": {
|
| 1038 |
+
"@types/react": {
|
| 1039 |
+
"optional": true
|
| 1040 |
+
}
|
| 1041 |
+
}
|
| 1042 |
+
},
|
| 1043 |
+
"node_modules/@radix-ui/react-focus-scope": {
|
| 1044 |
+
"version": "1.1.7",
|
| 1045 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
|
| 1046 |
+
"integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
|
| 1047 |
+
"license": "MIT",
|
| 1048 |
+
"dependencies": {
|
| 1049 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1050 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1051 |
+
"@radix-ui/react-use-callback-ref": "1.1.1"
|
| 1052 |
+
},
|
| 1053 |
+
"peerDependencies": {
|
| 1054 |
+
"@types/react": "*",
|
| 1055 |
+
"@types/react-dom": "*",
|
| 1056 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1057 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1058 |
+
},
|
| 1059 |
+
"peerDependenciesMeta": {
|
| 1060 |
+
"@types/react": {
|
| 1061 |
+
"optional": true
|
| 1062 |
+
},
|
| 1063 |
+
"@types/react-dom": {
|
| 1064 |
+
"optional": true
|
| 1065 |
+
}
|
| 1066 |
+
}
|
| 1067 |
+
},
|
| 1068 |
+
"node_modules/@radix-ui/react-id": {
|
| 1069 |
+
"version": "1.1.1",
|
| 1070 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
| 1071 |
+
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
|
| 1072 |
+
"license": "MIT",
|
| 1073 |
+
"dependencies": {
|
| 1074 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1075 |
+
},
|
| 1076 |
+
"peerDependencies": {
|
| 1077 |
+
"@types/react": "*",
|
| 1078 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1079 |
+
},
|
| 1080 |
+
"peerDependenciesMeta": {
|
| 1081 |
+
"@types/react": {
|
| 1082 |
+
"optional": true
|
| 1083 |
+
}
|
| 1084 |
+
}
|
| 1085 |
+
},
|
| 1086 |
+
"node_modules/@radix-ui/react-label": {
|
| 1087 |
+
"version": "2.1.8",
|
| 1088 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
|
| 1089 |
+
"integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
|
| 1090 |
+
"license": "MIT",
|
| 1091 |
+
"dependencies": {
|
| 1092 |
+
"@radix-ui/react-primitive": "2.1.4"
|
| 1093 |
+
},
|
| 1094 |
+
"peerDependencies": {
|
| 1095 |
+
"@types/react": "*",
|
| 1096 |
+
"@types/react-dom": "*",
|
| 1097 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1098 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1099 |
+
},
|
| 1100 |
+
"peerDependenciesMeta": {
|
| 1101 |
+
"@types/react": {
|
| 1102 |
+
"optional": true
|
| 1103 |
+
},
|
| 1104 |
+
"@types/react-dom": {
|
| 1105 |
+
"optional": true
|
| 1106 |
+
}
|
| 1107 |
+
}
|
| 1108 |
+
},
|
| 1109 |
+
"node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
|
| 1110 |
+
"version": "2.1.4",
|
| 1111 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
|
| 1112 |
+
"integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
|
| 1113 |
+
"license": "MIT",
|
| 1114 |
+
"dependencies": {
|
| 1115 |
+
"@radix-ui/react-slot": "1.2.4"
|
| 1116 |
+
},
|
| 1117 |
+
"peerDependencies": {
|
| 1118 |
+
"@types/react": "*",
|
| 1119 |
+
"@types/react-dom": "*",
|
| 1120 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1121 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1122 |
+
},
|
| 1123 |
+
"peerDependenciesMeta": {
|
| 1124 |
+
"@types/react": {
|
| 1125 |
+
"optional": true
|
| 1126 |
+
},
|
| 1127 |
+
"@types/react-dom": {
|
| 1128 |
+
"optional": true
|
| 1129 |
+
}
|
| 1130 |
+
}
|
| 1131 |
+
},
|
| 1132 |
+
"node_modules/@radix-ui/react-popper": {
|
| 1133 |
+
"version": "1.2.8",
|
| 1134 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
|
| 1135 |
+
"integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
|
| 1136 |
+
"license": "MIT",
|
| 1137 |
+
"dependencies": {
|
| 1138 |
+
"@floating-ui/react-dom": "^2.0.0",
|
| 1139 |
+
"@radix-ui/react-arrow": "1.1.7",
|
| 1140 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1141 |
+
"@radix-ui/react-context": "1.1.2",
|
| 1142 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1143 |
+
"@radix-ui/react-use-callback-ref": "1.1.1",
|
| 1144 |
+
"@radix-ui/react-use-layout-effect": "1.1.1",
|
| 1145 |
+
"@radix-ui/react-use-rect": "1.1.1",
|
| 1146 |
+
"@radix-ui/react-use-size": "1.1.1",
|
| 1147 |
+
"@radix-ui/rect": "1.1.1"
|
| 1148 |
+
},
|
| 1149 |
+
"peerDependencies": {
|
| 1150 |
+
"@types/react": "*",
|
| 1151 |
+
"@types/react-dom": "*",
|
| 1152 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1153 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1154 |
+
},
|
| 1155 |
+
"peerDependenciesMeta": {
|
| 1156 |
+
"@types/react": {
|
| 1157 |
+
"optional": true
|
| 1158 |
+
},
|
| 1159 |
+
"@types/react-dom": {
|
| 1160 |
+
"optional": true
|
| 1161 |
+
}
|
| 1162 |
+
}
|
| 1163 |
+
},
|
| 1164 |
+
"node_modules/@radix-ui/react-portal": {
|
| 1165 |
+
"version": "1.1.9",
|
| 1166 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
| 1167 |
+
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
|
| 1168 |
+
"license": "MIT",
|
| 1169 |
+
"dependencies": {
|
| 1170 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1171 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1172 |
+
},
|
| 1173 |
+
"peerDependencies": {
|
| 1174 |
+
"@types/react": "*",
|
| 1175 |
+
"@types/react-dom": "*",
|
| 1176 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1177 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1178 |
+
},
|
| 1179 |
+
"peerDependenciesMeta": {
|
| 1180 |
+
"@types/react": {
|
| 1181 |
+
"optional": true
|
| 1182 |
+
},
|
| 1183 |
+
"@types/react-dom": {
|
| 1184 |
+
"optional": true
|
| 1185 |
+
}
|
| 1186 |
+
}
|
| 1187 |
+
},
|
| 1188 |
+
"node_modules/@radix-ui/react-presence": {
|
| 1189 |
+
"version": "1.1.5",
|
| 1190 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
|
| 1191 |
+
"integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
|
| 1192 |
+
"license": "MIT",
|
| 1193 |
+
"dependencies": {
|
| 1194 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1195 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1196 |
+
},
|
| 1197 |
+
"peerDependencies": {
|
| 1198 |
+
"@types/react": "*",
|
| 1199 |
+
"@types/react-dom": "*",
|
| 1200 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1201 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1202 |
+
},
|
| 1203 |
+
"peerDependenciesMeta": {
|
| 1204 |
+
"@types/react": {
|
| 1205 |
+
"optional": true
|
| 1206 |
+
},
|
| 1207 |
+
"@types/react-dom": {
|
| 1208 |
+
"optional": true
|
| 1209 |
+
}
|
| 1210 |
+
}
|
| 1211 |
+
},
|
| 1212 |
+
"node_modules/@radix-ui/react-primitive": {
|
| 1213 |
+
"version": "2.1.3",
|
| 1214 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
| 1215 |
+
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
| 1216 |
+
"license": "MIT",
|
| 1217 |
+
"dependencies": {
|
| 1218 |
+
"@radix-ui/react-slot": "1.2.3"
|
| 1219 |
+
},
|
| 1220 |
+
"peerDependencies": {
|
| 1221 |
+
"@types/react": "*",
|
| 1222 |
+
"@types/react-dom": "*",
|
| 1223 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1224 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1225 |
+
},
|
| 1226 |
+
"peerDependenciesMeta": {
|
| 1227 |
+
"@types/react": {
|
| 1228 |
+
"optional": true
|
| 1229 |
+
},
|
| 1230 |
+
"@types/react-dom": {
|
| 1231 |
+
"optional": true
|
| 1232 |
+
}
|
| 1233 |
+
}
|
| 1234 |
+
},
|
| 1235 |
+
"node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
|
| 1236 |
+
"version": "1.2.3",
|
| 1237 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
| 1238 |
+
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
|
| 1239 |
+
"license": "MIT",
|
| 1240 |
+
"dependencies": {
|
| 1241 |
+
"@radix-ui/react-compose-refs": "1.1.2"
|
| 1242 |
+
},
|
| 1243 |
+
"peerDependencies": {
|
| 1244 |
+
"@types/react": "*",
|
| 1245 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1246 |
+
},
|
| 1247 |
+
"peerDependenciesMeta": {
|
| 1248 |
+
"@types/react": {
|
| 1249 |
+
"optional": true
|
| 1250 |
+
}
|
| 1251 |
+
}
|
| 1252 |
+
},
|
| 1253 |
+
"node_modules/@radix-ui/react-radio-group": {
|
| 1254 |
+
"version": "1.3.8",
|
| 1255 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz",
|
| 1256 |
+
"integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==",
|
| 1257 |
+
"license": "MIT",
|
| 1258 |
+
"dependencies": {
|
| 1259 |
+
"@radix-ui/primitive": "1.1.3",
|
| 1260 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1261 |
+
"@radix-ui/react-context": "1.1.2",
|
| 1262 |
+
"@radix-ui/react-direction": "1.1.1",
|
| 1263 |
+
"@radix-ui/react-presence": "1.1.5",
|
| 1264 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1265 |
+
"@radix-ui/react-roving-focus": "1.1.11",
|
| 1266 |
+
"@radix-ui/react-use-controllable-state": "1.2.2",
|
| 1267 |
+
"@radix-ui/react-use-previous": "1.1.1",
|
| 1268 |
+
"@radix-ui/react-use-size": "1.1.1"
|
| 1269 |
+
},
|
| 1270 |
+
"peerDependencies": {
|
| 1271 |
+
"@types/react": "*",
|
| 1272 |
+
"@types/react-dom": "*",
|
| 1273 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1274 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1275 |
+
},
|
| 1276 |
+
"peerDependenciesMeta": {
|
| 1277 |
+
"@types/react": {
|
| 1278 |
+
"optional": true
|
| 1279 |
+
},
|
| 1280 |
+
"@types/react-dom": {
|
| 1281 |
+
"optional": true
|
| 1282 |
+
}
|
| 1283 |
+
}
|
| 1284 |
+
},
|
| 1285 |
+
"node_modules/@radix-ui/react-roving-focus": {
|
| 1286 |
+
"version": "1.1.11",
|
| 1287 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
|
| 1288 |
+
"integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
|
| 1289 |
+
"license": "MIT",
|
| 1290 |
+
"dependencies": {
|
| 1291 |
+
"@radix-ui/primitive": "1.1.3",
|
| 1292 |
+
"@radix-ui/react-collection": "1.1.7",
|
| 1293 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1294 |
+
"@radix-ui/react-context": "1.1.2",
|
| 1295 |
+
"@radix-ui/react-direction": "1.1.1",
|
| 1296 |
+
"@radix-ui/react-id": "1.1.1",
|
| 1297 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1298 |
+
"@radix-ui/react-use-callback-ref": "1.1.1",
|
| 1299 |
+
"@radix-ui/react-use-controllable-state": "1.2.2"
|
| 1300 |
+
},
|
| 1301 |
+
"peerDependencies": {
|
| 1302 |
+
"@types/react": "*",
|
| 1303 |
+
"@types/react-dom": "*",
|
| 1304 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1305 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1306 |
+
},
|
| 1307 |
+
"peerDependenciesMeta": {
|
| 1308 |
+
"@types/react": {
|
| 1309 |
+
"optional": true
|
| 1310 |
+
},
|
| 1311 |
+
"@types/react-dom": {
|
| 1312 |
+
"optional": true
|
| 1313 |
+
}
|
| 1314 |
+
}
|
| 1315 |
+
},
|
| 1316 |
+
"node_modules/@radix-ui/react-select": {
|
| 1317 |
+
"version": "2.2.6",
|
| 1318 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
|
| 1319 |
+
"integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
|
| 1320 |
+
"license": "MIT",
|
| 1321 |
+
"dependencies": {
|
| 1322 |
+
"@radix-ui/number": "1.1.1",
|
| 1323 |
+
"@radix-ui/primitive": "1.1.3",
|
| 1324 |
+
"@radix-ui/react-collection": "1.1.7",
|
| 1325 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 1326 |
+
"@radix-ui/react-context": "1.1.2",
|
| 1327 |
+
"@radix-ui/react-direction": "1.1.1",
|
| 1328 |
+
"@radix-ui/react-dismissable-layer": "1.1.11",
|
| 1329 |
+
"@radix-ui/react-focus-guards": "1.1.3",
|
| 1330 |
+
"@radix-ui/react-focus-scope": "1.1.7",
|
| 1331 |
+
"@radix-ui/react-id": "1.1.1",
|
| 1332 |
+
"@radix-ui/react-popper": "1.2.8",
|
| 1333 |
+
"@radix-ui/react-portal": "1.1.9",
|
| 1334 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 1335 |
+
"@radix-ui/react-slot": "1.2.3",
|
| 1336 |
+
"@radix-ui/react-use-callback-ref": "1.1.1",
|
| 1337 |
+
"@radix-ui/react-use-controllable-state": "1.2.2",
|
| 1338 |
+
"@radix-ui/react-use-layout-effect": "1.1.1",
|
| 1339 |
+
"@radix-ui/react-use-previous": "1.1.1",
|
| 1340 |
+
"@radix-ui/react-visually-hidden": "1.2.3",
|
| 1341 |
+
"aria-hidden": "^1.2.4",
|
| 1342 |
+
"react-remove-scroll": "^2.6.3"
|
| 1343 |
+
},
|
| 1344 |
+
"peerDependencies": {
|
| 1345 |
+
"@types/react": "*",
|
| 1346 |
+
"@types/react-dom": "*",
|
| 1347 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1348 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1349 |
+
},
|
| 1350 |
+
"peerDependenciesMeta": {
|
| 1351 |
+
"@types/react": {
|
| 1352 |
+
"optional": true
|
| 1353 |
+
},
|
| 1354 |
+
"@types/react-dom": {
|
| 1355 |
+
"optional": true
|
| 1356 |
+
}
|
| 1357 |
+
}
|
| 1358 |
+
},
|
| 1359 |
+
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
|
| 1360 |
+
"version": "1.2.3",
|
| 1361 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
| 1362 |
+
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
|
| 1363 |
+
"license": "MIT",
|
| 1364 |
+
"dependencies": {
|
| 1365 |
+
"@radix-ui/react-compose-refs": "1.1.2"
|
| 1366 |
+
},
|
| 1367 |
+
"peerDependencies": {
|
| 1368 |
+
"@types/react": "*",
|
| 1369 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1370 |
+
},
|
| 1371 |
+
"peerDependenciesMeta": {
|
| 1372 |
+
"@types/react": {
|
| 1373 |
+
"optional": true
|
| 1374 |
+
}
|
| 1375 |
+
}
|
| 1376 |
+
},
|
| 1377 |
+
"node_modules/@radix-ui/react-slot": {
|
| 1378 |
+
"version": "1.2.4",
|
| 1379 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
|
| 1380 |
+
"integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
|
| 1381 |
+
"license": "MIT",
|
| 1382 |
+
"dependencies": {
|
| 1383 |
+
"@radix-ui/react-compose-refs": "1.1.2"
|
| 1384 |
+
},
|
| 1385 |
+
"peerDependencies": {
|
| 1386 |
+
"@types/react": "*",
|
| 1387 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1388 |
+
},
|
| 1389 |
+
"peerDependenciesMeta": {
|
| 1390 |
+
"@types/react": {
|
| 1391 |
+
"optional": true
|
| 1392 |
+
}
|
| 1393 |
+
}
|
| 1394 |
+
},
|
| 1395 |
+
"node_modules/@radix-ui/react-use-callback-ref": {
|
| 1396 |
+
"version": "1.1.1",
|
| 1397 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
| 1398 |
+
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
|
| 1399 |
+
"license": "MIT",
|
| 1400 |
+
"peerDependencies": {
|
| 1401 |
+
"@types/react": "*",
|
| 1402 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1403 |
+
},
|
| 1404 |
+
"peerDependenciesMeta": {
|
| 1405 |
+
"@types/react": {
|
| 1406 |
+
"optional": true
|
| 1407 |
+
}
|
| 1408 |
+
}
|
| 1409 |
+
},
|
| 1410 |
+
"node_modules/@radix-ui/react-use-controllable-state": {
|
| 1411 |
+
"version": "1.2.2",
|
| 1412 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
|
| 1413 |
+
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
|
| 1414 |
+
"license": "MIT",
|
| 1415 |
+
"dependencies": {
|
| 1416 |
+
"@radix-ui/react-use-effect-event": "0.0.2",
|
| 1417 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1418 |
+
},
|
| 1419 |
+
"peerDependencies": {
|
| 1420 |
+
"@types/react": "*",
|
| 1421 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1422 |
+
},
|
| 1423 |
+
"peerDependenciesMeta": {
|
| 1424 |
+
"@types/react": {
|
| 1425 |
+
"optional": true
|
| 1426 |
+
}
|
| 1427 |
+
}
|
| 1428 |
+
},
|
| 1429 |
+
"node_modules/@radix-ui/react-use-effect-event": {
|
| 1430 |
+
"version": "0.0.2",
|
| 1431 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
|
| 1432 |
+
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
|
| 1433 |
+
"license": "MIT",
|
| 1434 |
+
"dependencies": {
|
| 1435 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1436 |
+
},
|
| 1437 |
+
"peerDependencies": {
|
| 1438 |
+
"@types/react": "*",
|
| 1439 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1440 |
+
},
|
| 1441 |
+
"peerDependenciesMeta": {
|
| 1442 |
+
"@types/react": {
|
| 1443 |
+
"optional": true
|
| 1444 |
+
}
|
| 1445 |
+
}
|
| 1446 |
+
},
|
| 1447 |
+
"node_modules/@radix-ui/react-use-escape-keydown": {
|
| 1448 |
+
"version": "1.1.1",
|
| 1449 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
|
| 1450 |
+
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
|
| 1451 |
+
"license": "MIT",
|
| 1452 |
+
"dependencies": {
|
| 1453 |
+
"@radix-ui/react-use-callback-ref": "1.1.1"
|
| 1454 |
+
},
|
| 1455 |
+
"peerDependencies": {
|
| 1456 |
+
"@types/react": "*",
|
| 1457 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1458 |
+
},
|
| 1459 |
+
"peerDependenciesMeta": {
|
| 1460 |
+
"@types/react": {
|
| 1461 |
+
"optional": true
|
| 1462 |
+
}
|
| 1463 |
+
}
|
| 1464 |
+
},
|
| 1465 |
+
"node_modules/@radix-ui/react-use-layout-effect": {
|
| 1466 |
+
"version": "1.1.1",
|
| 1467 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
| 1468 |
+
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
| 1469 |
+
"license": "MIT",
|
| 1470 |
+
"peerDependencies": {
|
| 1471 |
+
"@types/react": "*",
|
| 1472 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1473 |
+
},
|
| 1474 |
+
"peerDependenciesMeta": {
|
| 1475 |
+
"@types/react": {
|
| 1476 |
+
"optional": true
|
| 1477 |
+
}
|
| 1478 |
+
}
|
| 1479 |
+
},
|
| 1480 |
+
"node_modules/@radix-ui/react-use-previous": {
|
| 1481 |
+
"version": "1.1.1",
|
| 1482 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
|
| 1483 |
+
"integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
|
| 1484 |
+
"license": "MIT",
|
| 1485 |
+
"peerDependencies": {
|
| 1486 |
+
"@types/react": "*",
|
| 1487 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1488 |
+
},
|
| 1489 |
+
"peerDependenciesMeta": {
|
| 1490 |
+
"@types/react": {
|
| 1491 |
+
"optional": true
|
| 1492 |
+
}
|
| 1493 |
+
}
|
| 1494 |
+
},
|
| 1495 |
+
"node_modules/@radix-ui/react-use-rect": {
|
| 1496 |
+
"version": "1.1.1",
|
| 1497 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
|
| 1498 |
+
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
|
| 1499 |
+
"license": "MIT",
|
| 1500 |
+
"dependencies": {
|
| 1501 |
+
"@radix-ui/rect": "1.1.1"
|
| 1502 |
+
},
|
| 1503 |
+
"peerDependencies": {
|
| 1504 |
+
"@types/react": "*",
|
| 1505 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1506 |
+
},
|
| 1507 |
+
"peerDependenciesMeta": {
|
| 1508 |
+
"@types/react": {
|
| 1509 |
+
"optional": true
|
| 1510 |
+
}
|
| 1511 |
+
}
|
| 1512 |
+
},
|
| 1513 |
+
"node_modules/@radix-ui/react-use-size": {
|
| 1514 |
+
"version": "1.1.1",
|
| 1515 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
|
| 1516 |
+
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
|
| 1517 |
+
"license": "MIT",
|
| 1518 |
+
"dependencies": {
|
| 1519 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 1520 |
+
},
|
| 1521 |
+
"peerDependencies": {
|
| 1522 |
+
"@types/react": "*",
|
| 1523 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1524 |
+
},
|
| 1525 |
+
"peerDependenciesMeta": {
|
| 1526 |
+
"@types/react": {
|
| 1527 |
+
"optional": true
|
| 1528 |
+
}
|
| 1529 |
+
}
|
| 1530 |
+
},
|
| 1531 |
+
"node_modules/@radix-ui/react-visually-hidden": {
|
| 1532 |
+
"version": "1.2.3",
|
| 1533 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
|
| 1534 |
+
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
|
| 1535 |
+
"license": "MIT",
|
| 1536 |
+
"dependencies": {
|
| 1537 |
+
"@radix-ui/react-primitive": "2.1.3"
|
| 1538 |
+
},
|
| 1539 |
+
"peerDependencies": {
|
| 1540 |
+
"@types/react": "*",
|
| 1541 |
+
"@types/react-dom": "*",
|
| 1542 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 1543 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 1544 |
+
},
|
| 1545 |
+
"peerDependenciesMeta": {
|
| 1546 |
+
"@types/react": {
|
| 1547 |
+
"optional": true
|
| 1548 |
+
},
|
| 1549 |
+
"@types/react-dom": {
|
| 1550 |
+
"optional": true
|
| 1551 |
+
}
|
| 1552 |
+
}
|
| 1553 |
+
},
|
| 1554 |
+
"node_modules/@radix-ui/rect": {
|
| 1555 |
+
"version": "1.1.1",
|
| 1556 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
|
| 1557 |
+
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
|
| 1558 |
+
"license": "MIT"
|
| 1559 |
+
},
|
| 1560 |
"node_modules/@rolldown/pluginutils": {
|
| 1561 |
"version": "1.0.0-beta.53",
|
| 1562 |
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
|
|
|
|
| 2112 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
| 2113 |
}
|
| 2114 |
},
|
| 2115 |
+
"node_modules/aria-hidden": {
|
| 2116 |
+
"version": "1.2.6",
|
| 2117 |
+
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
|
| 2118 |
+
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
|
| 2119 |
+
"license": "MIT",
|
| 2120 |
+
"dependencies": {
|
| 2121 |
+
"tslib": "^2.0.0"
|
| 2122 |
+
},
|
| 2123 |
+
"engines": {
|
| 2124 |
+
"node": ">=10"
|
| 2125 |
+
}
|
| 2126 |
+
},
|
| 2127 |
"node_modules/bail": {
|
| 2128 |
"version": "2.0.2",
|
| 2129 |
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
|
|
|
| 2250 |
"url": "https://github.com/sponsors/wooorm"
|
| 2251 |
}
|
| 2252 |
},
|
| 2253 |
+
"node_modules/class-variance-authority": {
|
| 2254 |
+
"version": "0.7.1",
|
| 2255 |
+
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
|
| 2256 |
+
"integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
|
| 2257 |
+
"license": "Apache-2.0",
|
| 2258 |
+
"dependencies": {
|
| 2259 |
+
"clsx": "^2.1.1"
|
| 2260 |
+
},
|
| 2261 |
+
"funding": {
|
| 2262 |
+
"url": "https://polar.sh/cva"
|
| 2263 |
+
}
|
| 2264 |
+
},
|
| 2265 |
"node_modules/clsx": {
|
| 2266 |
"version": "2.1.1",
|
| 2267 |
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
|
|
|
| 2333 |
"node": ">=6"
|
| 2334 |
}
|
| 2335 |
},
|
| 2336 |
+
"node_modules/detect-node-es": {
|
| 2337 |
+
"version": "1.1.0",
|
| 2338 |
+
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
| 2339 |
+
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
|
| 2340 |
+
"license": "MIT"
|
| 2341 |
+
},
|
| 2342 |
"node_modules/devlop": {
|
| 2343 |
"version": "1.1.0",
|
| 2344 |
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
|
|
|
| 2497 |
"node": ">=6.9.0"
|
| 2498 |
}
|
| 2499 |
},
|
| 2500 |
+
"node_modules/get-nonce": {
|
| 2501 |
+
"version": "1.0.1",
|
| 2502 |
+
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
|
| 2503 |
+
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
|
| 2504 |
+
"license": "MIT",
|
| 2505 |
+
"engines": {
|
| 2506 |
+
"node": ">=6"
|
| 2507 |
+
}
|
| 2508 |
+
},
|
| 2509 |
"node_modules/hast-util-to-jsx-runtime": {
|
| 2510 |
"version": "2.3.6",
|
| 2511 |
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
|
|
|
| 3476 |
"node": ">=0.10.0"
|
| 3477 |
}
|
| 3478 |
},
|
| 3479 |
+
"node_modules/react-remove-scroll": {
|
| 3480 |
+
"version": "2.7.2",
|
| 3481 |
+
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
|
| 3482 |
+
"integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
|
| 3483 |
+
"license": "MIT",
|
| 3484 |
+
"dependencies": {
|
| 3485 |
+
"react-remove-scroll-bar": "^2.3.7",
|
| 3486 |
+
"react-style-singleton": "^2.2.3",
|
| 3487 |
+
"tslib": "^2.1.0",
|
| 3488 |
+
"use-callback-ref": "^1.3.3",
|
| 3489 |
+
"use-sidecar": "^1.1.3"
|
| 3490 |
+
},
|
| 3491 |
+
"engines": {
|
| 3492 |
+
"node": ">=10"
|
| 3493 |
+
},
|
| 3494 |
+
"peerDependencies": {
|
| 3495 |
+
"@types/react": "*",
|
| 3496 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
| 3497 |
+
},
|
| 3498 |
+
"peerDependenciesMeta": {
|
| 3499 |
+
"@types/react": {
|
| 3500 |
+
"optional": true
|
| 3501 |
+
}
|
| 3502 |
+
}
|
| 3503 |
+
},
|
| 3504 |
+
"node_modules/react-remove-scroll-bar": {
|
| 3505 |
+
"version": "2.3.8",
|
| 3506 |
+
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
|
| 3507 |
+
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
|
| 3508 |
+
"license": "MIT",
|
| 3509 |
+
"dependencies": {
|
| 3510 |
+
"react-style-singleton": "^2.2.2",
|
| 3511 |
+
"tslib": "^2.0.0"
|
| 3512 |
+
},
|
| 3513 |
+
"engines": {
|
| 3514 |
+
"node": ">=10"
|
| 3515 |
+
},
|
| 3516 |
+
"peerDependencies": {
|
| 3517 |
+
"@types/react": "*",
|
| 3518 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 3519 |
+
},
|
| 3520 |
+
"peerDependenciesMeta": {
|
| 3521 |
+
"@types/react": {
|
| 3522 |
+
"optional": true
|
| 3523 |
+
}
|
| 3524 |
+
}
|
| 3525 |
+
},
|
| 3526 |
+
"node_modules/react-style-singleton": {
|
| 3527 |
+
"version": "2.2.3",
|
| 3528 |
+
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
| 3529 |
+
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
|
| 3530 |
+
"license": "MIT",
|
| 3531 |
+
"dependencies": {
|
| 3532 |
+
"get-nonce": "^1.0.0",
|
| 3533 |
+
"tslib": "^2.0.0"
|
| 3534 |
+
},
|
| 3535 |
+
"engines": {
|
| 3536 |
+
"node": ">=10"
|
| 3537 |
+
},
|
| 3538 |
+
"peerDependencies": {
|
| 3539 |
+
"@types/react": "*",
|
| 3540 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
| 3541 |
+
},
|
| 3542 |
+
"peerDependenciesMeta": {
|
| 3543 |
+
"@types/react": {
|
| 3544 |
+
"optional": true
|
| 3545 |
+
}
|
| 3546 |
+
}
|
| 3547 |
+
},
|
| 3548 |
"node_modules/remark-parse": {
|
| 3549 |
"version": "11.0.0",
|
| 3550 |
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
|
|
|
|
| 3636 |
"semver": "bin/semver.js"
|
| 3637 |
}
|
| 3638 |
},
|
| 3639 |
+
"node_modules/sonner": {
|
| 3640 |
+
"version": "2.0.7",
|
| 3641 |
+
"resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz",
|
| 3642 |
+
"integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==",
|
| 3643 |
+
"license": "MIT",
|
| 3644 |
+
"peerDependencies": {
|
| 3645 |
+
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
|
| 3646 |
+
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
| 3647 |
+
}
|
| 3648 |
+
},
|
| 3649 |
"node_modules/source-map-js": {
|
| 3650 |
"version": "1.2.1",
|
| 3651 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
|
|
| 3889 |
"browserslist": ">= 4.21.0"
|
| 3890 |
}
|
| 3891 |
},
|
| 3892 |
+
"node_modules/use-callback-ref": {
|
| 3893 |
+
"version": "1.3.3",
|
| 3894 |
+
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
|
| 3895 |
+
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
|
| 3896 |
+
"license": "MIT",
|
| 3897 |
+
"dependencies": {
|
| 3898 |
+
"tslib": "^2.0.0"
|
| 3899 |
+
},
|
| 3900 |
+
"engines": {
|
| 3901 |
+
"node": ">=10"
|
| 3902 |
+
},
|
| 3903 |
+
"peerDependencies": {
|
| 3904 |
+
"@types/react": "*",
|
| 3905 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
| 3906 |
+
},
|
| 3907 |
+
"peerDependenciesMeta": {
|
| 3908 |
+
"@types/react": {
|
| 3909 |
+
"optional": true
|
| 3910 |
+
}
|
| 3911 |
+
}
|
| 3912 |
+
},
|
| 3913 |
+
"node_modules/use-sidecar": {
|
| 3914 |
+
"version": "1.1.3",
|
| 3915 |
+
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
|
| 3916 |
+
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
|
| 3917 |
+
"license": "MIT",
|
| 3918 |
+
"dependencies": {
|
| 3919 |
+
"detect-node-es": "^1.1.0",
|
| 3920 |
+
"tslib": "^2.0.0"
|
| 3921 |
+
},
|
| 3922 |
+
"engines": {
|
| 3923 |
+
"node": ">=10"
|
| 3924 |
+
},
|
| 3925 |
+
"peerDependencies": {
|
| 3926 |
+
"@types/react": "*",
|
| 3927 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
| 3928 |
+
},
|
| 3929 |
+
"peerDependenciesMeta": {
|
| 3930 |
+
"@types/react": {
|
| 3931 |
+
"optional": true
|
| 3932 |
+
}
|
| 3933 |
+
}
|
| 3934 |
+
},
|
| 3935 |
"node_modules/vfile": {
|
| 3936 |
"version": "6.0.3",
|
| 3937 |
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
FRRONTEEEND/package.json
CHANGED
|
@@ -9,13 +9,20 @@
|
|
| 9 |
"preview": "vite preview"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
"@supabase/supabase-js": "^2.93.3",
|
|
|
|
| 13 |
"clsx": "^2.1.1",
|
| 14 |
"framer-motion": "^12.23.26",
|
| 15 |
"lucide-react": "^0.562.0",
|
| 16 |
"react": "^19.2.3",
|
| 17 |
"react-dom": "^19.2.3",
|
| 18 |
"react-markdown": "^9.0.1",
|
|
|
|
| 19 |
"tailwind-merge": "^3.4.0"
|
| 20 |
},
|
| 21 |
"devDependencies": {
|
|
|
|
| 9 |
"preview": "vite preview"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
+
"@radix-ui/react-checkbox": "^1.3.3",
|
| 13 |
+
"@radix-ui/react-label": "^2.1.8",
|
| 14 |
+
"@radix-ui/react-radio-group": "^1.3.8",
|
| 15 |
+
"@radix-ui/react-select": "^2.2.6",
|
| 16 |
+
"@radix-ui/react-slot": "^1.2.4",
|
| 17 |
"@supabase/supabase-js": "^2.93.3",
|
| 18 |
+
"class-variance-authority": "^0.7.1",
|
| 19 |
"clsx": "^2.1.1",
|
| 20 |
"framer-motion": "^12.23.26",
|
| 21 |
"lucide-react": "^0.562.0",
|
| 22 |
"react": "^19.2.3",
|
| 23 |
"react-dom": "^19.2.3",
|
| 24 |
"react-markdown": "^9.0.1",
|
| 25 |
+
"sonner": "^2.0.7",
|
| 26 |
"tailwind-merge": "^3.4.0"
|
| 27 |
},
|
| 28 |
"devDependencies": {
|
idx.html
ADDED
|
@@ -0,0 +1,1281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Cute Lamp Login - Ultimate Edition</title>
|
| 7 |
+
<style>
|
| 8 |
+
* {
|
| 9 |
+
margin: 0;
|
| 10 |
+
padding: 0;
|
| 11 |
+
box-sizing: border-box;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
body {
|
| 15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 16 |
+
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
|
| 17 |
+
min-height: 100vh;
|
| 18 |
+
display: flex;
|
| 19 |
+
flex-direction: column;
|
| 20 |
+
align-items: center;
|
| 21 |
+
justify-content: center;
|
| 22 |
+
overflow-x: hidden;
|
| 23 |
+
position: relative;
|
| 24 |
+
padding: 20px;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
/* Enhanced Animated background particles */
|
| 28 |
+
.particles {
|
| 29 |
+
position: fixed;
|
| 30 |
+
width: 100%;
|
| 31 |
+
height: 100%;
|
| 32 |
+
overflow: hidden;
|
| 33 |
+
z-index: 0;
|
| 34 |
+
top: 0;
|
| 35 |
+
left: 0;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.particle {
|
| 39 |
+
position: absolute;
|
| 40 |
+
width: 4px;
|
| 41 |
+
height: 4px;
|
| 42 |
+
background: radial-gradient(circle, #ffa500, transparent);
|
| 43 |
+
border-radius: 50%;
|
| 44 |
+
animation: float 15s infinite ease-in-out;
|
| 45 |
+
box-shadow: 0 0 10px #ffa500;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
@keyframes float {
|
| 49 |
+
0% { transform: translate(0, 100vh) scale(0); opacity: 0; }
|
| 50 |
+
10% { opacity: 1; }
|
| 51 |
+
90% { opacity: 1; }
|
| 52 |
+
100% { transform: translate(var(--tx), -100vh) scale(1); opacity: 0; }
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
/* Sparkles */
|
| 56 |
+
.sparkle {
|
| 57 |
+
position: absolute;
|
| 58 |
+
width: 3px;
|
| 59 |
+
height: 3px;
|
| 60 |
+
background: #fff;
|
| 61 |
+
border-radius: 50%;
|
| 62 |
+
animation: sparkle 3s infinite;
|
| 63 |
+
box-shadow: 0 0 8px #fff;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
@keyframes sparkle {
|
| 67 |
+
0%, 100% { opacity: 0; transform: scale(0); }
|
| 68 |
+
50% { opacity: 1; transform: scale(1.5); }
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
.title {
|
| 72 |
+
font-size: 52px;
|
| 73 |
+
font-weight: 700;
|
| 74 |
+
background: linear-gradient(90deg, #ffa500, #ff6b35, #ffa500);
|
| 75 |
+
background-size: 200% auto;
|
| 76 |
+
-webkit-background-clip: text;
|
| 77 |
+
-webkit-text-fill-color: transparent;
|
| 78 |
+
background-clip: text;
|
| 79 |
+
margin-bottom: 50px;
|
| 80 |
+
text-align: center;
|
| 81 |
+
z-index: 2;
|
| 82 |
+
text-shadow: 0 0 30px rgba(255, 165, 0, 0.5);
|
| 83 |
+
animation: gradientMove 3s linear infinite, fadeInDown 1s ease;
|
| 84 |
+
letter-spacing: 2px;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
@keyframes gradientMove {
|
| 88 |
+
0% { background-position: 0% center; }
|
| 89 |
+
100% { background-position: 200% center; }
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
@keyframes fadeInDown {
|
| 93 |
+
from {
|
| 94 |
+
opacity: 0;
|
| 95 |
+
transform: translateY(-50px);
|
| 96 |
+
}
|
| 97 |
+
to {
|
| 98 |
+
opacity: 1;
|
| 99 |
+
transform: translateY(0);
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.container {
|
| 104 |
+
display: flex;
|
| 105 |
+
align-items: center;
|
| 106 |
+
justify-content: center;
|
| 107 |
+
gap: 80px;
|
| 108 |
+
background: rgba(30, 40, 60, 0.5);
|
| 109 |
+
padding: 70px;
|
| 110 |
+
border-radius: 30px;
|
| 111 |
+
border: 2px solid rgba(255, 255, 255, 0.1);
|
| 112 |
+
backdrop-filter: blur(20px);
|
| 113 |
+
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6), inset 0 0 40px rgba(255, 165, 0, 0.05);
|
| 114 |
+
z-index: 2;
|
| 115 |
+
animation: fadeIn 1.2s ease 0.3s backwards;
|
| 116 |
+
position: relative;
|
| 117 |
+
max-width: 1200px;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
@keyframes fadeIn {
|
| 121 |
+
from {
|
| 122 |
+
opacity: 0;
|
| 123 |
+
transform: scale(0.8) rotateX(10deg);
|
| 124 |
+
}
|
| 125 |
+
to {
|
| 126 |
+
opacity: 1;
|
| 127 |
+
transform: scale(1) rotateX(0);
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
/* Enhanced Lamp Section */
|
| 132 |
+
.lamp-section {
|
| 133 |
+
position: relative;
|
| 134 |
+
display: flex;
|
| 135 |
+
align-items: center;
|
| 136 |
+
justify-content: center;
|
| 137 |
+
width: 300px;
|
| 138 |
+
height: 400px;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
.lamp-container {
|
| 142 |
+
position: relative;
|
| 143 |
+
cursor: pointer;
|
| 144 |
+
transition: transform 0.3s ease;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
.lamp-container:hover {
|
| 148 |
+
transform: scale(1.05);
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
.lamp {
|
| 152 |
+
position: relative;
|
| 153 |
+
width: 200px;
|
| 154 |
+
height: 320px;
|
| 155 |
+
display: flex;
|
| 156 |
+
align-items: flex-end;
|
| 157 |
+
justify-content: center;
|
| 158 |
+
animation: lampFloat 4s ease-in-out infinite;
|
| 159 |
+
filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
@keyframes lampFloat {
|
| 163 |
+
0%, 100% { transform: translateY(0) rotate(0deg); }
|
| 164 |
+
25% { transform: translateY(-12px) rotate(-2deg); }
|
| 165 |
+
75% { transform: translateY(-8px) rotate(2deg); }
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
/* Electric Cord */
|
| 169 |
+
.cord {
|
| 170 |
+
position: absolute;
|
| 171 |
+
width: 4px;
|
| 172 |
+
height: 80px;
|
| 173 |
+
background: linear-gradient(180deg, #555, #333);
|
| 174 |
+
top: -80px;
|
| 175 |
+
left: 50%;
|
| 176 |
+
transform: translateX(-50%);
|
| 177 |
+
border-radius: 2px;
|
| 178 |
+
animation: cordSwing 4s ease-in-out infinite;
|
| 179 |
+
transform-origin: top center;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
@keyframes cordSwing {
|
| 183 |
+
0%, 100% { transform: translateX(-50%) rotate(0deg); }
|
| 184 |
+
25% { transform: translateX(-50%) rotate(-3deg); }
|
| 185 |
+
75% { transform: translateX(-50%) rotate(3deg); }
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
.cord-plug {
|
| 189 |
+
position: absolute;
|
| 190 |
+
top: -10px;
|
| 191 |
+
left: 50%;
|
| 192 |
+
transform: translateX(-50%);
|
| 193 |
+
width: 12px;
|
| 194 |
+
height: 12px;
|
| 195 |
+
background: #444;
|
| 196 |
+
border-radius: 50%;
|
| 197 |
+
box-shadow: 0 2px 5px rgba(0,0,0,0.5);
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
.lamp-stand {
|
| 201 |
+
width: 10px;
|
| 202 |
+
height: 160px;
|
| 203 |
+
background: linear-gradient(180deg, #e8e8e8, #fff, #e8e8e8);
|
| 204 |
+
border-radius: 5px;
|
| 205 |
+
position: absolute;
|
| 206 |
+
bottom: 0;
|
| 207 |
+
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4), inset 0 0 10px rgba(255, 255, 255, 0.5);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
.lamp-base {
|
| 211 |
+
width: 80px;
|
| 212 |
+
height: 25px;
|
| 213 |
+
background: linear-gradient(180deg, #d0d0d0, #f8f8f8, #d0d0d0);
|
| 214 |
+
border-radius: 15px;
|
| 215 |
+
position: absolute;
|
| 216 |
+
bottom: 0;
|
| 217 |
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5), inset 0 -3px 10px rgba(0, 0, 0, 0.2);
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
.lamp-shade {
|
| 221 |
+
width: 140px;
|
| 222 |
+
height: 110px;
|
| 223 |
+
background: linear-gradient(180deg, #95d4a8, #a8d5ba, #8bc9a8);
|
| 224 |
+
clip-path: polygon(22% 0%, 78% 0%, 100% 100%, 0% 100%);
|
| 225 |
+
position: absolute;
|
| 226 |
+
top: 40px;
|
| 227 |
+
border-radius: 10px 10px 0 0;
|
| 228 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4), inset 0 -15px 40px rgba(255, 255, 255, 0.4);
|
| 229 |
+
animation: shadeGlow 3s ease-in-out infinite;
|
| 230 |
+
transition: all 0.3s ease;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
.lamp-shade.happy {
|
| 234 |
+
filter: brightness(1.2);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
.lamp-shade.sad {
|
| 238 |
+
filter: brightness(0.8);
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
@keyframes shadeGlow {
|
| 242 |
+
0%, 100% {
|
| 243 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4), inset 0 -15px 40px rgba(255, 255, 255, 0.4);
|
| 244 |
+
filter: brightness(1);
|
| 245 |
+
}
|
| 246 |
+
50% {
|
| 247 |
+
box-shadow: 0 10px 40px rgba(168, 213, 186, 0.7), inset 0 -15px 50px rgba(255, 255, 255, 0.6);
|
| 248 |
+
filter: brightness(1.15);
|
| 249 |
+
}
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/* Enhanced Lamp Face with expressions */
|
| 253 |
+
.lamp-face {
|
| 254 |
+
position: absolute;
|
| 255 |
+
top: 75px;
|
| 256 |
+
width: 140px;
|
| 257 |
+
height: 90px;
|
| 258 |
+
z-index: 2;
|
| 259 |
+
transition: all 0.3s ease;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
.lamp-eye {
|
| 263 |
+
width: 14px;
|
| 264 |
+
height: 20px;
|
| 265 |
+
background: #2d3436;
|
| 266 |
+
border-radius: 50%;
|
| 267 |
+
position: absolute;
|
| 268 |
+
top: 20px;
|
| 269 |
+
transition: all 0.3s ease;
|
| 270 |
+
animation: blink 5s infinite;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
.lamp-eye.left {
|
| 274 |
+
left: 35px;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
.lamp-eye.right {
|
| 278 |
+
right: 35px;
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
.lamp-eye::before {
|
| 282 |
+
content: '';
|
| 283 |
+
position: absolute;
|
| 284 |
+
width: 5px;
|
| 285 |
+
height: 5px;
|
| 286 |
+
background: #fff;
|
| 287 |
+
border-radius: 50%;
|
| 288 |
+
top: 4px;
|
| 289 |
+
left: 3px;
|
| 290 |
+
animation: eyeShine 3s infinite;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
@keyframes eyeShine {
|
| 294 |
+
0%, 100% { opacity: 0.8; }
|
| 295 |
+
50% { opacity: 1; }
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
@keyframes blink {
|
| 299 |
+
0%, 46%, 50%, 100% { height: 20px; }
|
| 300 |
+
48% { height: 2px; }
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
/* Lamp Tongue (when light is on) */
|
| 304 |
+
.lamp-tongue {
|
| 305 |
+
position: absolute;
|
| 306 |
+
width: 20px;
|
| 307 |
+
height: 25px;
|
| 308 |
+
background: #ff6b6b;
|
| 309 |
+
border-radius: 0 0 10px 10px;
|
| 310 |
+
bottom: 15px;
|
| 311 |
+
left: 50%;
|
| 312 |
+
transform: translateX(-50%) scaleY(0);
|
| 313 |
+
transform-origin: top;
|
| 314 |
+
opacity: 0;
|
| 315 |
+
transition: all 0.3s ease;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
.lamp-tongue.show {
|
| 319 |
+
transform: translateX(-50%) scaleY(1);
|
| 320 |
+
opacity: 1;
|
| 321 |
+
animation: tongueWiggle 0.5s ease-in-out;
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
@keyframes tongueWiggle {
|
| 325 |
+
0%, 100% { transform: translateX(-50%) scaleY(1) rotate(0deg); }
|
| 326 |
+
25% { transform: translateX(-50%) scaleY(1) rotate(-5deg); }
|
| 327 |
+
75% { transform: translateX(-50%) scaleY(1) rotate(5deg); }
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
.lamp-mouth {
|
| 331 |
+
width: 35px;
|
| 332 |
+
height: 18px;
|
| 333 |
+
border: 3px solid #e74c3c;
|
| 334 |
+
border-top: none;
|
| 335 |
+
border-radius: 0 0 35px 35px;
|
| 336 |
+
position: absolute;
|
| 337 |
+
top: 48px;
|
| 338 |
+
left: 50%;
|
| 339 |
+
transform: translateX(-50%);
|
| 340 |
+
transition: all 0.3s ease;
|
| 341 |
+
animation: smile 4s ease-in-out infinite;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
.lamp-mouth.sad {
|
| 345 |
+
border-radius: 35px 35px 0 0;
|
| 346 |
+
border-top: 3px solid #e74c3c;
|
| 347 |
+
border-bottom: none;
|
| 348 |
+
top: 55px;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
@keyframes smile {
|
| 352 |
+
0%, 100% { width: 35px; }
|
| 353 |
+
50% { width: 40px; }
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
.lamp-blush {
|
| 357 |
+
width: 22px;
|
| 358 |
+
height: 14px;
|
| 359 |
+
background: rgba(231, 76, 60, 0.5);
|
| 360 |
+
border-radius: 50%;
|
| 361 |
+
position: absolute;
|
| 362 |
+
top: 40px;
|
| 363 |
+
animation: blushPulse 3s ease-in-out infinite;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
@keyframes blushPulse {
|
| 367 |
+
0%, 100% { opacity: 0.5; }
|
| 368 |
+
50% { opacity: 0.8; }
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
.lamp-blush.left {
|
| 372 |
+
left: 15px;
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
.lamp-blush.right {
|
| 376 |
+
right: 15px;
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
/* Enhanced Light glow effect */
|
| 380 |
+
.lamp-glow {
|
| 381 |
+
position: absolute;
|
| 382 |
+
bottom: -50px;
|
| 383 |
+
left: 50%;
|
| 384 |
+
transform: translateX(-50%);
|
| 385 |
+
width: 280px;
|
| 386 |
+
height: 280px;
|
| 387 |
+
background: radial-gradient(circle, rgba(255, 243, 176, 0.6) 0%, rgba(255, 220, 100, 0.3) 40%, transparent 70%);
|
| 388 |
+
border-radius: 50%;
|
| 389 |
+
animation: glowPulse 3s ease-in-out infinite;
|
| 390 |
+
pointer-events: none;
|
| 391 |
+
filter: blur(20px);
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
@keyframes glowPulse {
|
| 395 |
+
0%, 100% {
|
| 396 |
+
opacity: 0.7;
|
| 397 |
+
transform: translateX(-50%) scale(1);
|
| 398 |
+
}
|
| 399 |
+
50% {
|
| 400 |
+
opacity: 1;
|
| 401 |
+
transform: translateX(-50%) scale(1.15);
|
| 402 |
+
}
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
/* Enhanced Login Form */
|
| 406 |
+
.login-box {
|
| 407 |
+
background: linear-gradient(135deg, rgba(40, 50, 70, 0.8), rgba(30, 40, 60, 0.9));
|
| 408 |
+
padding: 50px 55px;
|
| 409 |
+
border-radius: 25px;
|
| 410 |
+
border: 2px solid rgba(76, 209, 55, 0.6);
|
| 411 |
+
box-shadow: 0 0 50px rgba(76, 209, 55, 0.4), inset 0 0 30px rgba(0, 0, 0, 0.3);
|
| 412 |
+
width: 420px;
|
| 413 |
+
backdrop-filter: blur(15px);
|
| 414 |
+
position: relative;
|
| 415 |
+
overflow: hidden;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
.login-box::before {
|
| 419 |
+
content: '';
|
| 420 |
+
position: absolute;
|
| 421 |
+
top: -50%;
|
| 422 |
+
left: -50%;
|
| 423 |
+
width: 200%;
|
| 424 |
+
height: 200%;
|
| 425 |
+
background: linear-gradient(45deg, transparent, rgba(76, 209, 55, 0.1), transparent);
|
| 426 |
+
animation: shimmer 3s infinite;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
@keyframes shimmer {
|
| 430 |
+
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
|
| 431 |
+
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
.login-box > * {
|
| 435 |
+
position: relative;
|
| 436 |
+
z-index: 1;
|
| 437 |
+
}
|
| 438 |
+
|
| 439 |
+
.login-box h2 {
|
| 440 |
+
text-align: center;
|
| 441 |
+
color: #fff;
|
| 442 |
+
font-size: 36px;
|
| 443 |
+
margin-bottom: 35px;
|
| 444 |
+
font-weight: 700;
|
| 445 |
+
text-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
|
| 446 |
+
animation: textGlow 2s ease-in-out infinite;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
@keyframes textGlow {
|
| 450 |
+
0%, 100% { text-shadow: 0 4px 10px rgba(0, 0, 0, 0.5); }
|
| 451 |
+
50% { text-shadow: 0 4px 20px rgba(76, 209, 55, 0.5); }
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
.input-group {
|
| 455 |
+
margin-bottom: 28px;
|
| 456 |
+
position: relative;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.input-group label {
|
| 460 |
+
display: block;
|
| 461 |
+
color: #b8c5d8;
|
| 462 |
+
font-size: 14px;
|
| 463 |
+
margin-bottom: 10px;
|
| 464 |
+
font-weight: 600;
|
| 465 |
+
letter-spacing: 0.5px;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
.input-wrapper {
|
| 469 |
+
position: relative;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
.input-group input {
|
| 473 |
+
width: 100%;
|
| 474 |
+
padding: 16px 50px 16px 20px;
|
| 475 |
+
background: rgba(20, 30, 50, 0.7);
|
| 476 |
+
border: 2px solid rgba(255, 255, 255, 0.1);
|
| 477 |
+
border-radius: 12px;
|
| 478 |
+
color: #fff;
|
| 479 |
+
font-size: 15px;
|
| 480 |
+
outline: none;
|
| 481 |
+
transition: all 0.4s ease;
|
| 482 |
+
font-family: inherit;
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
.input-group input::placeholder {
|
| 486 |
+
color: #6c7a89;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.input-group input:focus {
|
| 490 |
+
border-color: #4cd137;
|
| 491 |
+
box-shadow: 0 0 20px rgba(76, 209, 55, 0.4), inset 0 0 10px rgba(76, 209, 55, 0.1);
|
| 492 |
+
background: rgba(20, 30, 50, 0.9);
|
| 493 |
+
transform: translateY(-2px);
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
.input-group input.error {
|
| 497 |
+
border-color: #e74c3c;
|
| 498 |
+
animation: shake 0.5s;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
@keyframes shake {
|
| 502 |
+
0%, 100% { transform: translateX(0); }
|
| 503 |
+
25% { transform: translateX(-10px); }
|
| 504 |
+
75% { transform: translateX(10px); }
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
/* Password Toggle Eye */
|
| 508 |
+
.toggle-password {
|
| 509 |
+
position: absolute;
|
| 510 |
+
right: 15px;
|
| 511 |
+
top: 50%;
|
| 512 |
+
transform: translateY(-50%);
|
| 513 |
+
cursor: pointer;
|
| 514 |
+
color: #6c7a89;
|
| 515 |
+
font-size: 20px;
|
| 516 |
+
transition: color 0.3s ease;
|
| 517 |
+
user-select: none;
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
.toggle-password:hover {
|
| 521 |
+
color: #4cd137;
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
/* Social Login Buttons */
|
| 525 |
+
.social-login {
|
| 526 |
+
display: flex;
|
| 527 |
+
gap: 12px;
|
| 528 |
+
margin-bottom: 25px;
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
.social-btn {
|
| 532 |
+
flex: 1;
|
| 533 |
+
padding: 12px;
|
| 534 |
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
| 535 |
+
background: rgba(30, 40, 60, 0.6);
|
| 536 |
+
border-radius: 10px;
|
| 537 |
+
color: #fff;
|
| 538 |
+
cursor: pointer;
|
| 539 |
+
transition: all 0.3s ease;
|
| 540 |
+
display: flex;
|
| 541 |
+
align-items: center;
|
| 542 |
+
justify-content: center;
|
| 543 |
+
gap: 8px;
|
| 544 |
+
font-size: 14px;
|
| 545 |
+
font-weight: 600;
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
.social-btn:hover {
|
| 549 |
+
transform: translateY(-3px);
|
| 550 |
+
border-color: #4cd137;
|
| 551 |
+
box-shadow: 0 5px 15px rgba(76, 209, 55, 0.3);
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
.divider {
|
| 555 |
+
text-align: center;
|
| 556 |
+
margin: 25px 0;
|
| 557 |
+
color: #6c7a89;
|
| 558 |
+
position: relative;
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
.divider::before,
|
| 562 |
+
.divider::after {
|
| 563 |
+
content: '';
|
| 564 |
+
position: absolute;
|
| 565 |
+
top: 50%;
|
| 566 |
+
width: 40%;
|
| 567 |
+
height: 1px;
|
| 568 |
+
background: rgba(255, 255, 255, 0.1);
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
.divider::before {
|
| 572 |
+
left: 0;
|
| 573 |
+
}
|
| 574 |
+
|
| 575 |
+
.divider::after {
|
| 576 |
+
right: 0;
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
.login-btn {
|
| 580 |
+
width: 100%;
|
| 581 |
+
padding: 17px;
|
| 582 |
+
background: linear-gradient(135deg, #4cd137, #44bd32, #3da82a);
|
| 583 |
+
background-size: 200% auto;
|
| 584 |
+
border: none;
|
| 585 |
+
border-radius: 12px;
|
| 586 |
+
color: #fff;
|
| 587 |
+
font-size: 18px;
|
| 588 |
+
font-weight: 700;
|
| 589 |
+
cursor: pointer;
|
| 590 |
+
transition: all 0.4s ease;
|
| 591 |
+
box-shadow: 0 6px 25px rgba(76, 209, 55, 0.5);
|
| 592 |
+
margin-top: 12px;
|
| 593 |
+
position: relative;
|
| 594 |
+
overflow: hidden;
|
| 595 |
+
letter-spacing: 1px;
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
.login-btn::before {
|
| 599 |
+
content: '';
|
| 600 |
+
position: absolute;
|
| 601 |
+
top: 0;
|
| 602 |
+
left: -100%;
|
| 603 |
+
width: 100%;
|
| 604 |
+
height: 100%;
|
| 605 |
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
| 606 |
+
transition: left 0.5s;
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
.login-btn:hover::before {
|
| 610 |
+
left: 100%;
|
| 611 |
+
}
|
| 612 |
+
|
| 613 |
+
.login-btn:hover {
|
| 614 |
+
transform: translateY(-4px);
|
| 615 |
+
box-shadow: 0 10px 30px rgba(76, 209, 55, 0.7);
|
| 616 |
+
background-position: right center;
|
| 617 |
+
}
|
| 618 |
+
|
| 619 |
+
.login-btn:active {
|
| 620 |
+
transform: translateY(-2px);
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
.login-btn.loading {
|
| 624 |
+
pointer-events: none;
|
| 625 |
+
opacity: 0.8;
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
.login-btn.loading::after {
|
| 629 |
+
content: '';
|
| 630 |
+
position: absolute;
|
| 631 |
+
width: 20px;
|
| 632 |
+
height: 20px;
|
| 633 |
+
border: 3px solid rgba(255, 255, 255, 0.3);
|
| 634 |
+
border-top-color: #fff;
|
| 635 |
+
border-radius: 50%;
|
| 636 |
+
animation: spin 0.8s linear infinite;
|
| 637 |
+
top: 50%;
|
| 638 |
+
left: 50%;
|
| 639 |
+
transform: translate(-50%, -50%);
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
@keyframes spin {
|
| 643 |
+
to { transform: translate(-50%, -50%) rotate(360deg); }
|
| 644 |
+
}
|
| 645 |
+
|
| 646 |
+
.forgot-password {
|
| 647 |
+
text-align: center;
|
| 648 |
+
margin-top: 22px;
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
.forgot-password a {
|
| 652 |
+
color: #7c8a9e;
|
| 653 |
+
text-decoration: none;
|
| 654 |
+
font-size: 14px;
|
| 655 |
+
transition: all 0.3s ease;
|
| 656 |
+
position: relative;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
.forgot-password a::after {
|
| 660 |
+
content: '';
|
| 661 |
+
position: absolute;
|
| 662 |
+
bottom: -2px;
|
| 663 |
+
left: 0;
|
| 664 |
+
width: 0;
|
| 665 |
+
height: 2px;
|
| 666 |
+
background: #4cd137;
|
| 667 |
+
transition: width 0.3s ease;
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
.forgot-password a:hover {
|
| 671 |
+
color: #4cd137;
|
| 672 |
+
}
|
| 673 |
+
|
| 674 |
+
.forgot-password a:hover::after {
|
| 675 |
+
width: 100%;
|
| 676 |
+
}
|
| 677 |
+
|
| 678 |
+
/* Toast Notification */
|
| 679 |
+
.toast {
|
| 680 |
+
position: fixed;
|
| 681 |
+
top: 30px;
|
| 682 |
+
right: 30px;
|
| 683 |
+
background: linear-gradient(135deg, rgba(76, 209, 55, 0.95), rgba(68, 189, 50, 0.95));
|
| 684 |
+
color: #fff;
|
| 685 |
+
padding: 18px 28px;
|
| 686 |
+
border-radius: 12px;
|
| 687 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
| 688 |
+
z-index: 1000;
|
| 689 |
+
transform: translateX(400px);
|
| 690 |
+
opacity: 0;
|
| 691 |
+
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
| 692 |
+
display: flex;
|
| 693 |
+
align-items: center;
|
| 694 |
+
gap: 12px;
|
| 695 |
+
font-weight: 600;
|
| 696 |
+
backdrop-filter: blur(10px);
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
.toast.show {
|
| 700 |
+
transform: translateX(0);
|
| 701 |
+
opacity: 1;
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
.toast.error {
|
| 705 |
+
background: linear-gradient(135deg, rgba(231, 76, 60, 0.95), rgba(192, 57, 43, 0.95));
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
.toast-icon {
|
| 709 |
+
font-size: 24px;
|
| 710 |
+
}
|
| 711 |
+
|
| 712 |
+
/* Code Display Section */
|
| 713 |
+
.code-section {
|
| 714 |
+
margin-top: 60px;
|
| 715 |
+
width: 100%;
|
| 716 |
+
max-width: 1200px;
|
| 717 |
+
z-index: 2;
|
| 718 |
+
animation: fadeIn 1.5s ease 1s backwards;
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
.code-header {
|
| 722 |
+
text-align: center;
|
| 723 |
+
margin-bottom: 30px;
|
| 724 |
+
}
|
| 725 |
+
|
| 726 |
+
.code-header h3 {
|
| 727 |
+
font-size: 28px;
|
| 728 |
+
color: #ffa500;
|
| 729 |
+
margin-bottom: 10px;
|
| 730 |
+
text-shadow: 0 0 20px rgba(255, 165, 0, 0.5);
|
| 731 |
+
}
|
| 732 |
+
|
| 733 |
+
.code-header p {
|
| 734 |
+
color: #b0b8c8;
|
| 735 |
+
font-size: 16px;
|
| 736 |
+
}
|
| 737 |
+
|
| 738 |
+
.code-display {
|
| 739 |
+
display: grid;
|
| 740 |
+
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
|
| 741 |
+
gap: 25px;
|
| 742 |
+
padding: 0 20px;
|
| 743 |
+
}
|
| 744 |
+
|
| 745 |
+
.code-block {
|
| 746 |
+
background: rgba(20, 25, 35, 0.9);
|
| 747 |
+
border: 1px solid rgba(76, 209, 55, 0.3);
|
| 748 |
+
border-radius: 15px;
|
| 749 |
+
padding: 25px;
|
| 750 |
+
position: relative;
|
| 751 |
+
overflow: hidden;
|
| 752 |
+
backdrop-filter: blur(10px);
|
| 753 |
+
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
|
| 754 |
+
transition: all 0.3s ease;
|
| 755 |
+
}
|
| 756 |
+
|
| 757 |
+
.code-block:hover {
|
| 758 |
+
transform: translateY(-5px);
|
| 759 |
+
box-shadow: 0 12px 35px rgba(76, 209, 55, 0.3);
|
| 760 |
+
border-color: #4cd137;
|
| 761 |
+
}
|
| 762 |
+
|
| 763 |
+
.code-block::before {
|
| 764 |
+
content: 'style.css';
|
| 765 |
+
position: absolute;
|
| 766 |
+
top: 0;
|
| 767 |
+
left: 0;
|
| 768 |
+
background: rgba(76, 209, 55, 0.2);
|
| 769 |
+
padding: 6px 15px;
|
| 770 |
+
font-size: 12px;
|
| 771 |
+
color: #4cd137;
|
| 772 |
+
border-radius: 0 0 10px 0;
|
| 773 |
+
font-family: 'Courier New', monospace;
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
.code-block pre {
|
| 777 |
+
margin-top: 30px;
|
| 778 |
+
color: #a8b2d1;
|
| 779 |
+
font-family: 'Courier New', monospace;
|
| 780 |
+
font-size: 13px;
|
| 781 |
+
line-height: 1.6;
|
| 782 |
+
overflow-x: auto;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
.code-block pre code {
|
| 786 |
+
display: block;
|
| 787 |
+
}
|
| 788 |
+
|
| 789 |
+
.keyword { color: #c792ea; }
|
| 790 |
+
.property { color: #82aaff; }
|
| 791 |
+
.value { color: #c3e88d; }
|
| 792 |
+
.important { color: #ff6b6b; }
|
| 793 |
+
.comment { color: #676e95; font-style: italic; }
|
| 794 |
+
|
| 795 |
+
/* Responsive */
|
| 796 |
+
@media (max-width: 1200px) {
|
| 797 |
+
.container {
|
| 798 |
+
gap: 50px;
|
| 799 |
+
padding: 50px 40px;
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
+
.code-display {
|
| 803 |
+
grid-template-columns: 1fr;
|
| 804 |
+
}
|
| 805 |
+
}
|
| 806 |
+
|
| 807 |
+
@media (max-width: 1024px) {
|
| 808 |
+
.container {
|
| 809 |
+
flex-direction: column;
|
| 810 |
+
gap: 40px;
|
| 811 |
+
padding: 40px 30px;
|
| 812 |
+
}
|
| 813 |
+
|
| 814 |
+
.title {
|
| 815 |
+
font-size: 42px;
|
| 816 |
+
}
|
| 817 |
+
|
| 818 |
+
.lamp-section {
|
| 819 |
+
width: 250px;
|
| 820 |
+
height: 350px;
|
| 821 |
+
}
|
| 822 |
+
}
|
| 823 |
+
|
| 824 |
+
@media (max-width: 600px) {
|
| 825 |
+
.title {
|
| 826 |
+
font-size: 32px;
|
| 827 |
+
margin-bottom: 30px;
|
| 828 |
+
}
|
| 829 |
+
|
| 830 |
+
.container {
|
| 831 |
+
padding: 30px 20px;
|
| 832 |
+
margin: 20px;
|
| 833 |
+
}
|
| 834 |
+
|
| 835 |
+
.login-box {
|
| 836 |
+
width: 100%;
|
| 837 |
+
padding: 35px 25px;
|
| 838 |
+
}
|
| 839 |
+
|
| 840 |
+
.lamp {
|
| 841 |
+
transform: scale(0.75);
|
| 842 |
+
}
|
| 843 |
+
|
| 844 |
+
.social-login {
|
| 845 |
+
flex-direction: column;
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
.code-display {
|
| 849 |
+
padding: 0;
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
.code-block {
|
| 853 |
+
padding: 20px 15px;
|
| 854 |
+
}
|
| 855 |
+
|
| 856 |
+
.code-block pre {
|
| 857 |
+
font-size: 11px;
|
| 858 |
+
}
|
| 859 |
+
}
|
| 860 |
+
</style>
|
| 861 |
+
</head>
|
| 862 |
+
<body>
|
| 863 |
+
<!-- Animated particles -->
|
| 864 |
+
<div class="particles" id="particles"></div>
|
| 865 |
+
|
| 866 |
+
<!-- Title -->
|
| 867 |
+
<h1 class="title">β¨ Cute Lamp Login β¨</h1>
|
| 868 |
+
|
| 869 |
+
<!-- Main Container -->
|
| 870 |
+
<div class="container">
|
| 871 |
+
<!-- Enhanced Lamp Section -->
|
| 872 |
+
<div class="lamp-section">
|
| 873 |
+
<div class="lamp-glow"></div>
|
| 874 |
+
<div class="lamp-container" id="lampContainer">
|
| 875 |
+
<div class="lamp" id="lamp">
|
| 876 |
+
<div class="cord">
|
| 877 |
+
<div class="cord-plug"></div>
|
| 878 |
+
</div>
|
| 879 |
+
<div class="lamp-shade" id="lampShade"></div>
|
| 880 |
+
<div class="lamp-face" id="lampFace">
|
| 881 |
+
<div class="lamp-eye left" id="leftEye"></div>
|
| 882 |
+
<div class="lamp-eye right" id="rightEye"></div>
|
| 883 |
+
<div class="lamp-mouth" id="lampMouth"></div>
|
| 884 |
+
<div class="lamp-tongue" id="lampTongue"></div>
|
| 885 |
+
<div class="lamp-blush left"></div>
|
| 886 |
+
<div class="lamp-blush right"></div>
|
| 887 |
+
</div>
|
| 888 |
+
<div class="lamp-stand"></div>
|
| 889 |
+
<div class="lamp-base"></div>
|
| 890 |
+
</div>
|
| 891 |
+
</div>
|
| 892 |
+
</div>
|
| 893 |
+
|
| 894 |
+
<!-- Enhanced Login Form -->
|
| 895 |
+
<div class="login-box">
|
| 896 |
+
<h2>Welcome Back</h2>
|
| 897 |
+
|
| 898 |
+
<!-- Social Login -->
|
| 899 |
+
<div class="social-login">
|
| 900 |
+
<button class="social-btn" onclick="socialLogin('Google')">
|
| 901 |
+
<span>π</span>
|
| 902 |
+
<span>Google</span>
|
| 903 |
+
</button>
|
| 904 |
+
<button class="social-btn" onclick="socialLogin('GitHub')">
|
| 905 |
+
<span>π»</span>
|
| 906 |
+
<span>GitHub</span>
|
| 907 |
+
</button>
|
| 908 |
+
</div>
|
| 909 |
+
|
| 910 |
+
<div class="divider">OR</div>
|
| 911 |
+
|
| 912 |
+
<form id="loginForm" onsubmit="handleLogin(event)">
|
| 913 |
+
<div class="input-group">
|
| 914 |
+
<label for="username">Username</label>
|
| 915 |
+
<div class="input-wrapper">
|
| 916 |
+
<input type="text" id="username" placeholder="Enter your username" required>
|
| 917 |
+
</div>
|
| 918 |
+
</div>
|
| 919 |
+
<div class="input-group">
|
| 920 |
+
<label for="password">Password</label>
|
| 921 |
+
<div class="input-wrapper">
|
| 922 |
+
<input type="password" id="password" placeholder="Enter your password" required>
|
| 923 |
+
<span class="toggle-password" id="togglePassword" onclick="togglePassword()">ποΈ</span>
|
| 924 |
+
</div>
|
| 925 |
+
</div>
|
| 926 |
+
<button type="submit" class="login-btn" id="loginBtn">Login</button>
|
| 927 |
+
</form>
|
| 928 |
+
<div class="forgot-password">
|
| 929 |
+
<a href="#" onclick="forgotPassword(); return false;">Forgot Password?</a>
|
| 930 |
+
</div>
|
| 931 |
+
</div>
|
| 932 |
+
</div>
|
| 933 |
+
|
| 934 |
+
<!-- Code Display Section -->
|
| 935 |
+
<div class="code-section">
|
| 936 |
+
<div class="code-header">
|
| 937 |
+
<h3>π» Comment "cute" for code</h3>
|
| 938 |
+
<p>Here's a peek at the magic behind this adorable login page</p>
|
| 939 |
+
</div>
|
| 940 |
+
<div class="code-display">
|
| 941 |
+
<div class="code-block">
|
| 942 |
+
<pre><code><span class="keyword">.lamp</span> {
|
| 943 |
+
<span class="property">display</span>: <span class="value">flex</span>;
|
| 944 |
+
<span class="property">height</span>: <span class="value">320px</span>;
|
| 945 |
+
<span class="property">overflow</span>: <span class="value">visible</span> <span class="important">!important</span>;
|
| 946 |
+
}
|
| 947 |
+
|
| 948 |
+
<span class="keyword">.cord</span> {
|
| 949 |
+
<span class="property">stroke</span>: <span class="value">var(--cord)</span>;
|
| 950 |
+
}
|
| 951 |
+
|
| 952 |
+
<span class="keyword">.cord--nip</span> {
|
| 953 |
+
<span class="property">display</span>: <span class="value">none</span>;
|
| 954 |
+
}
|
| 955 |
+
|
| 956 |
+
<span class="keyword">.lamp__tongue</span> {
|
| 957 |
+
<span class="property">fill</span>: <span class="value">var(--tongue)</span>;
|
| 958 |
+
}</code></pre>
|
| 959 |
+
</div>
|
| 960 |
+
|
| 961 |
+
<div class="code-block">
|
| 962 |
+
<pre><code><span class="keyword">.login-btn:active</span> {
|
| 963 |
+
<span class="property">transform</span>: <span class="value">translateY(0px)</span>;
|
| 964 |
+
}
|
| 965 |
+
|
| 966 |
+
<span class="keyword">.form-footer</span> {
|
| 967 |
+
<span class="property">margin-top</span>: <span class="value">1.5rem</span>;
|
| 968 |
+
<span class="property">text-align</span>: <span class="value">center</span>;
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
<span class="keyword">.forgot-link</span> {
|
| 972 |
+
<span class="property">color</span>: <span class="value">#888</span>;
|
| 973 |
+
<span class="property">font-size</span>: <span class="value">0.9rem</span>;
|
| 974 |
+
<span class="property">text-decoration</span>: <span class="value">none</span>;
|
| 975 |
+
<span class="property">transition</span>: <span class="value">all 0.3s ease</span>;
|
| 976 |
+
}</code></pre>
|
| 977 |
+
</div>
|
| 978 |
+
</div>
|
| 979 |
+
</div>
|
| 980 |
+
|
| 981 |
+
<!-- Toast Notification -->
|
| 982 |
+
<div class="toast" id="toast">
|
| 983 |
+
<span class="toast-icon" id="toastIcon">β¨</span>
|
| 984 |
+
<span id="toastMessage">Welcome!</span>
|
| 985 |
+
</div>
|
| 986 |
+
|
| 987 |
+
<script>
|
| 988 |
+
// Enhanced Particle System
|
| 989 |
+
const particlesContainer = document.getElementById('particles');
|
| 990 |
+
|
| 991 |
+
function createParticles() {
|
| 992 |
+
for (let i = 0; i < 40; i++) {
|
| 993 |
+
const particle = document.createElement('div');
|
| 994 |
+
particle.className = 'particle';
|
| 995 |
+
particle.style.left = Math.random() * 100 + '%';
|
| 996 |
+
particle.style.setProperty('--tx', (Math.random() - 0.5) * 200 + 'px');
|
| 997 |
+
particle.style.animationDelay = Math.random() * 15 + 's';
|
| 998 |
+
particle.style.animationDuration = (10 + Math.random() * 10) + 's';
|
| 999 |
+
particlesContainer.appendChild(particle);
|
| 1000 |
+
}
|
| 1001 |
+
|
| 1002 |
+
// Add sparkles
|
| 1003 |
+
for (let i = 0; i < 20; i++) {
|
| 1004 |
+
const sparkle = document.createElement('div');
|
| 1005 |
+
sparkle.className = 'sparkle';
|
| 1006 |
+
sparkle.style.left = Math.random() * 100 + '%';
|
| 1007 |
+
sparkle.style.top = Math.random() * 100 + '%';
|
| 1008 |
+
sparkle.style.animationDelay = Math.random() * 3 + 's';
|
| 1009 |
+
particlesContainer.appendChild(sparkle);
|
| 1010 |
+
}
|
| 1011 |
+
}
|
| 1012 |
+
|
| 1013 |
+
createParticles();
|
| 1014 |
+
|
| 1015 |
+
// Lamp Elements
|
| 1016 |
+
const lamp = document.getElementById('lamp');
|
| 1017 |
+
const lampShade = document.getElementById('lampShade');
|
| 1018 |
+
const lampFace = document.getElementById('lampFace');
|
| 1019 |
+
const lampMouth = document.getElementById('lampMouth');
|
| 1020 |
+
const lampTongue = document.getElementById('lampTongue');
|
| 1021 |
+
const leftEye = document.getElementById('leftEye');
|
| 1022 |
+
const rightEye = document.getElementById('rightEye');
|
| 1023 |
+
const lampContainer = document.getElementById('lampContainer');
|
| 1024 |
+
|
| 1025 |
+
// Form Elements
|
| 1026 |
+
const loginForm = document.getElementById('loginForm');
|
| 1027 |
+
const usernameInput = document.getElementById('username');
|
| 1028 |
+
const passwordInput = document.getElementById('password');
|
| 1029 |
+
const loginBtn = document.getElementById('loginBtn');
|
| 1030 |
+
const toast = document.getElementById('toast');
|
| 1031 |
+
const toastIcon = document.getElementById('toastIcon');
|
| 1032 |
+
const toastMessage = document.getElementById('toastMessage');
|
| 1033 |
+
|
| 1034 |
+
// Lamp Expressions
|
| 1035 |
+
function setLampExpression(expression) {
|
| 1036 |
+
lampShade.classList.remove('happy', 'sad');
|
| 1037 |
+
lampMouth.classList.remove('sad');
|
| 1038 |
+
lampTongue.classList.remove('show');
|
| 1039 |
+
|
| 1040 |
+
switch(expression) {
|
| 1041 |
+
case 'happy':
|
| 1042 |
+
lampShade.classList.add('happy');
|
| 1043 |
+
lampTongue.classList.add('show');
|
| 1044 |
+
leftEye.style.background = '#4cd137';
|
| 1045 |
+
rightEye.style.background = '#4cd137';
|
| 1046 |
+
break;
|
| 1047 |
+
case 'sad':
|
| 1048 |
+
lampShade.classList.add('sad');
|
| 1049 |
+
lampMouth.classList.add('sad');
|
| 1050 |
+
leftEye.style.background = '#3498db';
|
| 1051 |
+
rightEye.style.background = '#3498db';
|
| 1052 |
+
break;
|
| 1053 |
+
case 'neutral':
|
| 1054 |
+
leftEye.style.background = '#2d3436';
|
| 1055 |
+
rightEye.style.background = '#2d3436';
|
| 1056 |
+
break;
|
| 1057 |
+
}
|
| 1058 |
+
}
|
| 1059 |
+
|
| 1060 |
+
// Eye following cursor
|
| 1061 |
+
let isFollowingCursor = true;
|
| 1062 |
+
|
| 1063 |
+
document.addEventListener('mousemove', (e) => {
|
| 1064 |
+
if (!isFollowingCursor) return;
|
| 1065 |
+
|
| 1066 |
+
const lampRect = lamp.getBoundingClientRect();
|
| 1067 |
+
const lampCenterX = lampRect.left + lampRect.width / 2;
|
| 1068 |
+
const lampCenterY = lampRect.top + lampRect.height / 2;
|
| 1069 |
+
|
| 1070 |
+
const angle = Math.atan2(e.clientY - lampCenterY, e.clientX - lampCenterX);
|
| 1071 |
+
const distance = Math.min(3, Math.hypot(e.clientX - lampCenterX, e.clientY - lampCenterY) / 100);
|
| 1072 |
+
|
| 1073 |
+
const moveX = Math.cos(angle) * distance;
|
| 1074 |
+
const moveY = Math.sin(angle) * distance;
|
| 1075 |
+
|
| 1076 |
+
leftEye.style.transform = `translate(${moveX}px, ${moveY}px)`;
|
| 1077 |
+
rightEye.style.transform = `translate(${moveX}px, ${moveY}px)`;
|
| 1078 |
+
});
|
| 1079 |
+
|
| 1080 |
+
// Input Focus Effects
|
| 1081 |
+
const inputs = [usernameInput, passwordInput];
|
| 1082 |
+
|
| 1083 |
+
inputs.forEach(input => {
|
| 1084 |
+
input.addEventListener('focus', () => {
|
| 1085 |
+
setLampExpression('happy');
|
| 1086 |
+
isFollowingCursor = false;
|
| 1087 |
+
});
|
| 1088 |
+
|
| 1089 |
+
input.addEventListener('blur', () => {
|
| 1090 |
+
if (!usernameInput.value && !passwordInput.value) {
|
| 1091 |
+
setLampExpression('neutral');
|
| 1092 |
+
isFollowingCursor = true;
|
| 1093 |
+
}
|
| 1094 |
+
});
|
| 1095 |
+
|
| 1096 |
+
input.addEventListener('input', () => {
|
| 1097 |
+
if (input.classList.contains('error')) {
|
| 1098 |
+
input.classList.remove('error');
|
| 1099 |
+
setLampExpression('happy');
|
| 1100 |
+
}
|
| 1101 |
+
});
|
| 1102 |
+
});
|
| 1103 |
+
|
| 1104 |
+
// Toast Notification Function
|
| 1105 |
+
function showToast(message, type = 'success') {
|
| 1106 |
+
toast.className = 'toast';
|
| 1107 |
+
if (type === 'error') {
|
| 1108 |
+
toast.classList.add('error');
|
| 1109 |
+
toastIcon.textContent = 'β';
|
| 1110 |
+
} else {
|
| 1111 |
+
toastIcon.textContent = 'β¨';
|
| 1112 |
+
}
|
| 1113 |
+
|
| 1114 |
+
toastMessage.textContent = message;
|
| 1115 |
+
|
| 1116 |
+
setTimeout(() => {
|
| 1117 |
+
toast.classList.add('show');
|
| 1118 |
+
}, 100);
|
| 1119 |
+
|
| 1120 |
+
setTimeout(() => {
|
| 1121 |
+
toast.classList.remove('show');
|
| 1122 |
+
}, 3000);
|
| 1123 |
+
}
|
| 1124 |
+
|
| 1125 |
+
// Password Toggle
|
| 1126 |
+
function togglePassword() {
|
| 1127 |
+
const type = passwordInput.type === 'password' ? 'text' : 'password';
|
| 1128 |
+
passwordInput.type = type;
|
| 1129 |
+
document.getElementById('togglePassword').textContent = type === 'password' ? 'ποΈ' : 'π';
|
| 1130 |
+
}
|
| 1131 |
+
|
| 1132 |
+
// Form Validation
|
| 1133 |
+
function validateForm() {
|
| 1134 |
+
let isValid = true;
|
| 1135 |
+
|
| 1136 |
+
if (usernameInput.value.trim().length < 3) {
|
| 1137 |
+
usernameInput.classList.add('error');
|
| 1138 |
+
isValid = false;
|
| 1139 |
+
}
|
| 1140 |
+
|
| 1141 |
+
if (passwordInput.value.trim().length < 6) {
|
| 1142 |
+
passwordInput.classList.add('error');
|
| 1143 |
+
isValid = false;
|
| 1144 |
+
}
|
| 1145 |
+
|
| 1146 |
+
if (!isValid) {
|
| 1147 |
+
setLampExpression('sad');
|
| 1148 |
+
showToast('Please check your credentials! π’', 'error');
|
| 1149 |
+
}
|
| 1150 |
+
|
| 1151 |
+
return isValid;
|
| 1152 |
+
}
|
| 1153 |
+
|
| 1154 |
+
// Handle Login
|
| 1155 |
+
function handleLogin(e) {
|
| 1156 |
+
e.preventDefault();
|
| 1157 |
+
|
| 1158 |
+
if (!validateForm()) {
|
| 1159 |
+
return;
|
| 1160 |
+
}
|
| 1161 |
+
|
| 1162 |
+
// Show loading state
|
| 1163 |
+
loginBtn.classList.add('loading');
|
| 1164 |
+
loginBtn.textContent = '';
|
| 1165 |
+
setLampExpression('happy');
|
| 1166 |
+
|
| 1167 |
+
// Simulate API call
|
| 1168 |
+
setTimeout(() => {
|
| 1169 |
+
loginBtn.classList.remove('loading');
|
| 1170 |
+
loginBtn.textContent = 'Login';
|
| 1171 |
+
|
| 1172 |
+
const username = usernameInput.value;
|
| 1173 |
+
showToast(`Welcome back, ${username}! π`, 'success');
|
| 1174 |
+
|
| 1175 |
+
// Reset form after success
|
| 1176 |
+
setTimeout(() => {
|
| 1177 |
+
loginForm.reset();
|
| 1178 |
+
setLampExpression('neutral');
|
| 1179 |
+
isFollowingCursor = true;
|
| 1180 |
+
}, 2000);
|
| 1181 |
+
}, 2000);
|
| 1182 |
+
}
|
| 1183 |
+
|
| 1184 |
+
// Social Login
|
| 1185 |
+
function socialLogin(platform) {
|
| 1186 |
+
setLampExpression('happy');
|
| 1187 |
+
showToast(`Logging in with ${platform}... π`, 'success');
|
| 1188 |
+
|
| 1189 |
+
setTimeout(() => {
|
| 1190 |
+
showToast(`${platform} login successful! π`, 'success');
|
| 1191 |
+
}, 1500);
|
| 1192 |
+
}
|
| 1193 |
+
|
| 1194 |
+
// Forgot Password
|
| 1195 |
+
function forgotPassword() {
|
| 1196 |
+
setLampExpression('sad');
|
| 1197 |
+
showToast('Password reset link sent to your email! π§', 'success');
|
| 1198 |
+
|
| 1199 |
+
setTimeout(() => {
|
| 1200 |
+
setLampExpression('neutral');
|
| 1201 |
+
}, 2000);
|
| 1202 |
+
}
|
| 1203 |
+
|
| 1204 |
+
// Lamp Click Interaction
|
| 1205 |
+
lampContainer.addEventListener('click', () => {
|
| 1206 |
+
setLampExpression('happy');
|
| 1207 |
+
lampContainer.style.transform = 'scale(1.1)';
|
| 1208 |
+
|
| 1209 |
+
setTimeout(() => {
|
| 1210 |
+
lampContainer.style.transform = 'scale(1)';
|
| 1211 |
+
}, 300);
|
| 1212 |
+
|
| 1213 |
+
setTimeout(() => {
|
| 1214 |
+
if (!usernameInput.value && !passwordInput.value) {
|
| 1215 |
+
setLampExpression('neutral');
|
| 1216 |
+
}
|
| 1217 |
+
}, 2000);
|
| 1218 |
+
});
|
| 1219 |
+
|
| 1220 |
+
// Welcome Animation
|
| 1221 |
+
window.addEventListener('load', () => {
|
| 1222 |
+
setTimeout(() => {
|
| 1223 |
+
showToast('Hello! Ready to login? π', 'success');
|
| 1224 |
+
}, 1000);
|
| 1225 |
+
});
|
| 1226 |
+
|
| 1227 |
+
// Easter Egg: Konami Code
|
| 1228 |
+
let konamiCode = [];
|
| 1229 |
+
const konamiSequence = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a'];
|
| 1230 |
+
|
| 1231 |
+
document.addEventListener('keydown', (e) => {
|
| 1232 |
+
konamiCode.push(e.key);
|
| 1233 |
+
konamiCode = konamiCode.slice(-10);
|
| 1234 |
+
|
| 1235 |
+
if (konamiCode.join(',') === konamiSequence.join(',')) {
|
| 1236 |
+
lampShade.style.background = 'linear-gradient(180deg, #ff6b9d, #c44569)';
|
| 1237 |
+
showToast('π Rainbow Lamp Mode Activated! π', 'success');
|
| 1238 |
+
|
| 1239 |
+
let hue = 0;
|
| 1240 |
+
const rainbowInterval = setInterval(() => {
|
| 1241 |
+
lampShade.style.background = `hsl(${hue}, 70%, 60%)`;
|
| 1242 |
+
hue = (hue + 5) % 360;
|
| 1243 |
+
}, 100);
|
| 1244 |
+
|
| 1245 |
+
setTimeout(() => {
|
| 1246 |
+
clearInterval(rainbowInterval);
|
| 1247 |
+
lampShade.style.background = '';
|
| 1248 |
+
showToast('Back to normal! β¨', 'success');
|
| 1249 |
+
}, 5000);
|
| 1250 |
+
}
|
| 1251 |
+
});
|
| 1252 |
+
|
| 1253 |
+
// Keyboard shortcuts
|
| 1254 |
+
document.addEventListener('keydown', (e) => {
|
| 1255 |
+
// Ctrl/Cmd + Enter to submit
|
| 1256 |
+
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
| 1257 |
+
if (usernameInput.value || passwordInput.value) {
|
| 1258 |
+
loginForm.dispatchEvent(new Event('submit'));
|
| 1259 |
+
}
|
| 1260 |
+
}
|
| 1261 |
+
});
|
| 1262 |
+
|
| 1263 |
+
// Auto-focus username on load
|
| 1264 |
+
window.addEventListener('load', () => {
|
| 1265 |
+
setTimeout(() => {
|
| 1266 |
+
usernameInput.focus();
|
| 1267 |
+
}, 500);
|
| 1268 |
+
});
|
| 1269 |
+
|
| 1270 |
+
// Add accessibility: ESC to clear form
|
| 1271 |
+
document.addEventListener('keydown', (e) => {
|
| 1272 |
+
if (e.key === 'Escape') {
|
| 1273 |
+
loginForm.reset();
|
| 1274 |
+
setLampExpression('neutral');
|
| 1275 |
+
isFollowingCursor = true;
|
| 1276 |
+
showToast('Form cleared! π§Ή', 'success');
|
| 1277 |
+
}
|
| 1278 |
+
});
|
| 1279 |
+
</script>
|
| 1280 |
+
</body>
|
| 1281 |
+
</html>
|