'use client'; import { useEffect, useRef, useState } from 'react'; import { usePathname } from 'next/navigation'; export function NavigationProgress() { const pathname = usePathname(); const [visible, setVisible] = useState(false); const [width, setWidth] = useState(0); const timer = useRef | null>(null); useEffect(() => { setVisible(false); setWidth(100); const hide = window.setTimeout(() => { setWidth(0); }, 180); if (timer.current) clearInterval(timer.current); return () => window.clearTimeout(hide); }, [pathname]); useEffect(() => { const onClick = (event: MouseEvent) => { if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; const anchor = (event.target as HTMLElement | null)?.closest('a'); if (!anchor) return; const href = anchor.getAttribute('href'); if (!href || href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) return; if (anchor.target === '_blank' || anchor.hasAttribute('download')) return; try { const url = new URL(href, window.location.origin); if (url.origin !== window.location.origin) return; if (url.pathname === window.location.pathname && url.search === window.location.search) return; } catch { return; } setVisible(true); setWidth(18); if (timer.current) clearInterval(timer.current); timer.current = setInterval(() => { setWidth((current) => (current >= 88 ? current : current + 6 + Math.random() * 8)); }, 180); }; document.addEventListener('click', onClick, true); return () => { document.removeEventListener('click', onClick, true); if (timer.current) clearInterval(timer.current); }; }, []); if (!visible && width === 0) return null; return (
); }