Initial commit gov-llm-v2

This commit is contained in:
2026-02-04 00:04:31 +05:00
commit 07c4f48601
43 changed files with 7640 additions and 0 deletions

92
components/Timeline.tsx Executable file
View File

@@ -0,0 +1,92 @@
import React, { useState, useEffect, useRef } from 'react';
const sections = [
{ id: 'hero', label: 'Старт' },
{ id: 'infra', label: 'ЦОД' },
{ id: 'science', label: 'Наука' },
{ id: 'social', label: 'Социум' },
{ id: 'leadership', label: 'Рейтинг' },
{ id: 'metrics', label: 'Цифры' },
{ id: 'scaling', label: 'Масштаб' },
{ id: 'team', label: 'Команда' },
];
const Timeline: React.FC = () => {
const [activeId, setActiveId] = useState<string>('hero');
const observerRef = useRef<IntersectionObserver | null>(null);
const visibilities = useRef<Map<string, number>>(new Map());
useEffect(() => {
const handleIntersection = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
// Calculate approximate visible height in pixels
// This creates a fair comparison between scrolling (tall) sections and snapping (short) sections
const visibleHeight = entry.intersectionRect.height;
visibilities.current.set(entry.target.id, visibleHeight);
});
let maxVisibleHeight = 0;
let maxId = '';
// The active section is the one occupying the most vertical space in the viewport
for (const [id, height] of visibilities.current.entries()) {
if (height > maxVisibleHeight) {
maxVisibleHeight = height;
maxId = id;
}
}
if (maxId && maxVisibleHeight > 0) {
setActiveId(maxId);
}
};
const options = {
root: null, // viewport
rootMargin: '0px',
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),
};
observerRef.current = new IntersectionObserver(handleIntersection, options);
// Observe all sections
sections.forEach(({ id }) => {
const element = document.getElementById(id);
if (element) observerRef.current?.observe(element);
});
return () => observerRef.current?.disconnect();
}, []);
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>, id: string) => {
e.preventDefault();
const element = document.getElementById(id);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
};
return (
<div className="fixed right-8 top-1/2 -translate-y-1/2 z-[60] hidden md:flex flex-col gap-3 mix-blend-difference items-end">
{sections.map((item) => {
const isActive = activeId === item.id;
return (
<a
key={item.id}
href={`#${item.id}`}
onClick={(e) => handleClick(e, item.id)}
className="group flex flex-row-reverse items-center justify-end gap-3"
>
<div className={`w-1.5 h-1.5 transition-all duration-300 ${isActive ? 'bg-[#ff4b4b] scale-150' : 'bg-white/30 group-hover:bg-white'}`} />
<span className={`text-[10px] font-mono transition-all duration-300 uppercase tracking-widest text-white ${isActive ? 'opacity-100' : 'opacity-0 translate-x-2 group-hover:opacity-50 group-hover:translate-x-0'}`}>
{item.label}
</span>
</a>
);
})}
</div>
);
};
export default Timeline;