// Shared icons (Lucide-style SVG) and helper components const Icon = ({ name, size = 18, stroke = 2, className = '', style = {} }) => { const paths = { home: <>, file: <>, files: <>, users: <>, user: <>, chart: <>, sparkles: <>, settings: <>, search: <>, bell: <>, plus: <>, check: , checkCircle: <>, x: <>, chevronRight: , chevronLeft: , chevronDown: , arrowRight: <>, arrowLeft: <>, clock: <>, calendar: <>, lock: <>, mail: <>, eye: <>, brain: <>, wand: <>, upload: <>, download: <>, filter: , trash: <>, edit: <>, copy: <>, grip: <>, logout: <>, flag: <>, bookmark: , warn: <>, play: , send: <>, book: <>, trophy: <>, building: <>, mapPin: <>, layers: <>, shield: , maximize: <>, save: <>, refresh: <>, moreH: <>, palette: <>, zap: , globe: <>, trending: <>, }; return ( {paths[name] || null} ); }; const Logo = ({ size = 'md', variant = 'prof' }) => { const grad = variant === 'stud' ? 'linear-gradient(135deg, #8B7CF6, #7C3AED)' : variant === 'admin' ? 'linear-gradient(135deg, #6366F1, #8B5CF6)' : 'linear-gradient(135deg, #6ECFB5, #4DB8A0)'; const sizes = { sm: { box: 26, font: 12, text: 15 }, md: { box: 32, font: 15, text: 18 }, lg: { box: 40, font: 18, text: 22 } }; const sz = sizes[size]; return (
S
StudyHub
); }; // Avatar — colored circle with initials const Avatar = ({ name, size = 36, variant = 'prof' }) => { const initials = name.split(' ').map(n => n[0]).slice(0, 2).join('').toUpperCase(); const bgs = { prof: ['#6ECFB5', '#A78BFA', '#F5C842', '#E879A0', '#60A5FA'], stud: ['#8B7CF6', '#E879A0', '#F5C842'], admin: ['#6366F1', '#8B5CF6', '#F59E0B'], }; const palette = bgs[variant]; const colorIdx = name.charCodeAt(0) % palette.length; return (
{initials}
); }; // Sparkline SVG const Sparkline = ({ data, color = '#6ECFB5', width = 80, height = 24 }) => { const max = Math.max(...data); const min = Math.min(...data); const range = max - min || 1; const pts = data.map((v, i) => `${(i / (data.length - 1)) * width},${height - ((v - min) / range) * height}`).join(' '); return ( ); }; // Toast host const Toast = ({ message, visible, variant = 'prof' }) => { const colors = { prof: '#6ECFB5', stud: '#8B7CF6', admin: '#6366F1' }; if (!visible) return null; return (
{message}
); }; // Confetti const Confetti = () => { const colors = ['#8B7CF6', '#E879A0', '#F5C842', '#6ECFB5', '#60A5FA']; const pieces = Array.from({ length: 80 }, (_, i) => ({ left: Math.random() * 100, delay: Math.random() * 1.2, dur: 2 + Math.random() * 2, color: colors[i % colors.length], size: 6 + Math.random() * 8, })); return (
{pieces.map((p, i) => (
))}
); }; Object.assign(window, { Icon, Logo, Avatar, Sparkline, Toast, Confetti });