UNPKG

capsule-ai-cli

Version:

The AI Model Orchestrator - Intelligent multi-model workflows with device-locked licensing

113 lines 6.7 kB
import React, { useState, useEffect } from 'react'; import { Box, Text } from 'ink'; import gradient from 'gradient-string'; export const StartupAnimation = ({ onComplete }) => { const [stage, setStage] = useState('particles'); const [frame, setFrame] = useState(0); const [typewriterText, setTypewriterText] = useState(''); const [showLogo, setShowLogo] = useState(false); const [logoOpacity, setLogoOpacity] = useState(0); const [taglineVisible, setTaglineVisible] = useState(false); const [loadingDots, setLoadingDots] = useState(''); const capsuleLetters = ['C', 'A', 'P', 'S', 'U', 'L', 'E']; const totalFrames = 80; const particles = ['✦', '✧', '✨', '⬢', '◆', '●', '○', '⬡']; useEffect(() => { const timer = setInterval(() => { setFrame(prev => { const next = prev + 1; if (next === 12) { setStage('typewriter'); } if (next >= 12 && next < 12 + capsuleLetters.length * 3) { const index = Math.floor((next - 12) / 3); setTypewriterText(capsuleLetters.slice(0, index + 1).join('')); } if (next === 30) { setStage('logo'); setShowLogo(true); } if (next >= 30 && next <= 40) { setLogoOpacity((next - 30) / 10); } if (next === 45) { setTaglineVisible(true); } if (next >= 50) { const dotCount = ((next - 50) % 4); setLoadingDots('.'.repeat(dotCount)); } if (next >= totalFrames) { clearInterval(timer); setTimeout(onComplete, 500); } return next; }); }, 50); return () => clearInterval(timer); }, [onComplete]); const renderParticles = () => { if (stage === 'particles' && frame < 12) { const particleElements = []; const centerX = 30; const centerY = 5; for (let i = 0; i < 12; i++) { const angle = (i / 12) * Math.PI * 2; const delay = i * 0.5; if (frame > delay) { const particle = particles[i % particles.length]; const progress = Math.min((frame - delay) / 8, 1); const radius = progress * 15; const x = Math.floor(centerX + Math.cos(angle) * radius); const y = Math.floor(centerY + Math.sin(angle) * radius * 0.5); const opacity = 1 - progress * 0.5; particleElements.push(React.createElement(Box, { key: i, position: "absolute", marginLeft: x, marginTop: y }, React.createElement(Text, { color: i % 3 === 0 ? 'cyan' : i % 3 === 1 ? 'magenta' : 'yellow', dimColor: opacity < 0.7 }, particle))); } } return particleElements; } return null; }; const logo = ` ██████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗ ███████╗ ██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║██║ ██╔════╝ ██║ ███████║██████╔╝███████╗██║ ██║██║ █████╗ ██║ ██╔══██║██╔═══╝ ╚════██║██║ ██║██║ ██╔══╝ ╚██████╗██║ ██║██║ ███████║╚██████╔╝███████╗███████╗ ╚═════╝╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚══════╝╚══════╝`; const animatedLogo = showLogo ? gradient(['#39ff14', '#00ff41', '#0fa']).multiline(logo) : ''; const tagline = "AI-Powered Software Engineering"; return (React.createElement(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", minHeight: 20 }, React.createElement(Box, { marginBottom: 2 }, React.createElement(Text, { dimColor: true, italic: true }, "Press any key to skip...")), stage === 'particles' && (React.createElement(Box, { position: "relative", width: 60, height: 12 }, renderParticles())), stage === 'typewriter' && typewriterText && (React.createElement(Box, null, React.createElement(Text, { bold: true }, typewriterText.split('').map((char, i) => (React.createElement(Text, { key: i, color: gradient(['#39ff14', '#00ff41', '#0fa']).multiline(char) }, char))), React.createElement(Text, { color: "gray" }, '_'.repeat(7 - typewriterText.length))))), showLogo && (React.createElement(Box, { flexDirection: "column", alignItems: "center" }, React.createElement(Text, { dimColor: logoOpacity < 0.7 }, animatedLogo))), taglineVisible && (React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: "cyan", bold: true }, gradient(['#0fa', '#39ff14']).multiline(tagline)))), frame >= 50 && (React.createElement(Box, { marginTop: 2 }, React.createElement(Text, { color: "gray" }, "Initializing AI systems", loadingDots))), frame >= 35 && frame < totalFrames - 5 && (React.createElement(Box, { marginTop: 2, flexDirection: "column", alignItems: "center" }, React.createElement(Box, null, React.createElement(Text, { color: "gray" }, "["), Array.from({ length: 36 }).map((_, i) => { const progress = (frame - 35) / (totalFrames - 40); const filled = i < Math.floor(progress * 36); const isHead = i === Math.floor(progress * 36) - 1; return (React.createElement(Text, { key: i, color: isHead ? 'yellow' : filled ? 'green' : 'gray' }, isHead ? '▶' : filled ? '=' : '-')); }), React.createElement(Text, { color: "gray" }, "]")), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: "gray", dimColor: true }, Math.floor(((frame - 35) / (totalFrames - 40)) * 100), "%")))))); }; //# sourceMappingURL=StartupAnimation.js.map