'use client' import Link from 'next/link' import { usePathname, useRouter } from 'next/navigation' import { useEffect, useId, useRef, useState } from 'react' import { accessApi, type WalletAccessSession } from '@/services/api/access' const navItemBase = 'rounded-xl px-3 py-2 text-[15px] font-medium transition-all duration-150' const navLink = `${navItemBase} text-gray-700 dark:text-gray-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-gray-700/70 dark:hover:text-primary-300` const navLinkActive = `${navItemBase} bg-primary-50 text-primary-700 shadow-sm ring-1 ring-primary-100 dark:bg-primary-500/10 dark:text-primary-300 dark:ring-primary-500/20` function NavDropdown({ label, icon, active, children, }: { label: string icon: React.ReactNode active?: boolean children: React.ReactNode }) { const [open, setOpen] = useState(false) const wrapperRef = useRef(null) const menuId = useId() useEffect(() => { if (!open) return const handlePointerDown = (event: MouseEvent | TouchEvent) => { const target = event.target as Node | null if (!target || !wrapperRef.current?.contains(target)) { setOpen(false) } } const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { setOpen(false) } } document.addEventListener('mousedown', handlePointerDown) document.addEventListener('touchstart', handlePointerDown) document.addEventListener('keydown', handleKeyDown) return () => { document.removeEventListener('mousedown', handlePointerDown) document.removeEventListener('touchstart', handlePointerDown) document.removeEventListener('keydown', handleKeyDown) } }, [open]) return (
setOpen(true)} onMouseLeave={() => setOpen(false)} onBlurCapture={(event) => { const nextTarget = event.relatedTarget as Node | null if (nextTarget && wrapperRef.current?.contains(nextTarget)) { return } setOpen(false) }} > {open && ( )}
) } function DropdownItem({ href, icon, children, external, }: { href: string icon?: React.ReactNode children: React.ReactNode external?: boolean }) { const className = 'flex items-center gap-2 px-4 py-2.5 text-gray-700 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:text-gray-300 dark:hover:bg-gray-700 dark:hover:text-primary-400' if (external) { return (
  • {icon} {children}
  • ) } return (
  • {icon} {children}
  • ) } export default function Navbar() { const router = useRouter() const pathname = usePathname() ?? '' const [mobileMenuOpen, setMobileMenuOpen] = useState(false) const [exploreOpen, setExploreOpen] = useState(false) const [dataOpen, setDataOpen] = useState(false) const [operationsOpen, setOperationsOpen] = useState(false) const [walletSession, setWalletSession] = useState(null) const [connectingWallet, setConnectingWallet] = useState(false) const isExploreActive = pathname === '/' || pathname.startsWith('/blocks') || pathname.startsWith('/transactions') || pathname.startsWith('/addresses') const isDataActive = pathname.startsWith('/tokens') || pathname.startsWith('/pools') || pathname.startsWith('/analytics') || pathname.startsWith('/watchlist') const isOperationsActive = pathname.startsWith('/bridge') || pathname.startsWith('/routes') || pathname.startsWith('/liquidity') || pathname.startsWith('/operations') || pathname.startsWith('/operator') || pathname.startsWith('/system') || pathname.startsWith('/weth') const isDocsActive = pathname.startsWith('/docs') const isAccessActive = pathname.startsWith('/access') useEffect(() => { const syncWalletSession = () => { setWalletSession(accessApi.getStoredWalletSession()) } syncWalletSession() window.addEventListener('storage', syncWalletSession) window.addEventListener('explorer-access-session-changed', syncWalletSession) return () => { window.removeEventListener('storage', syncWalletSession) window.removeEventListener('explorer-access-session-changed', syncWalletSession) } }, []) const handleAccessClick = async () => { if (walletSession) { router.push('/access') setMobileMenuOpen(false) return } try { setConnectingWallet(true) await accessApi.connectWalletSession() router.push('/access') setMobileMenuOpen(false) } catch (error) { console.error('Wallet connect failed', error) router.push('/access') setMobileMenuOpen(false) } finally { setConnectingWallet(false) } } const toggleMobileMenu = () => { setMobileMenuOpen((open) => { const nextOpen = !open if (!nextOpen) { setExploreOpen(false) setDataOpen(false) setOperationsOpen(false) } return nextOpen }) } return ( ) }