ifixkart-admin/components/layouts/NavigationProgress.tsx

62 lines
2.2 KiB
TypeScript

'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<ReturnType<typeof setInterval> | 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 (
<div className="fixed top-0 left-0 right-0 z-[80] h-[2px] pointer-events-none">
<div
className="h-full bg-primary transition-[width] duration-200 ease-out"
style={{ width: `${width}%` }}
/>
</div>
);
}