version 1 with webshell and docs

This commit is contained in:
2026-01-22 15:52:08 -06:00
commit 612118ac48
13 changed files with 2212 additions and 0 deletions

89
src/main.ts Normal file
View File

@@ -0,0 +1,89 @@
import './style.css';
// Matrix rain effect
const canvas = document.getElementById('matrix') as HTMLCanvasElement;
const ctx = canvas.getContext('2d')!;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?/~`';
const fontSize = 14;
const columns = canvas.width / fontSize;
const drops: number[] = Array(Math.floor(columns)).fill(1);
let mouseX = canvas.width / 2;
let mouseY = canvas.height / 2;
function draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = `${fontSize}px monospace`;
for (let i = 0; i < drops.length; i++) {
const x = i * fontSize;
const y = drops[i] * fontSize;
const dist = Math.sqrt((x - mouseX) ** 2 + (y - mouseY) ** 2);
const text = chars[Math.floor(Math.random() * chars.length)];
// Only show characters near cursor
const alpha = Math.max(0, 1 - dist / 250);
if (alpha > 0.1) {
const color = dist < 120 ? '#a6e3a1' : dist < 200 ? '#89b4fa' : '#6c7086';
ctx.fillStyle = color + Math.floor(alpha * 255).toString(16).padStart(2, '0');
ctx.fillText(text, x, y);
}
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
drops[i]++;
}
}
setInterval(draw, 33);
window.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
// Copy functionality
const commandBox = document.getElementById('commandBox') as HTMLDivElement;
const copyBtn = document.getElementById('copyBtn') as HTMLButtonElement;
const tooltip = document.getElementById('tooltip') as HTMLDivElement;
const COMMAND = 'ssh portfolio@keshavanand.net';
async function copyToClipboard() {
try {
await navigator.clipboard.writeText(COMMAND);
copyBtn.classList.add('copied');
tooltip.classList.add('show');
setTimeout(() => {
copyBtn.classList.remove('copied');
tooltip.classList.remove('show');
}, 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
}
copyBtn.addEventListener('click', (e) => {
e.stopPropagation();
copyToClipboard();
});
commandBox.addEventListener('click', (e) => {
if (!(e.target as HTMLElement).closest('.copy-btn')) copyToClipboard();
});
// Fade in docs link after 2 seconds
setTimeout(() => {
document.getElementById('docsLink')?.classList.add('show');
}, 2000);