"use client"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import Link from "next/link"; import Logo from "@/components/Logo"; import SearchDialog from "@/components/SearchDialog"; import LanguageSelector from "@/components/LanguageSelector"; import { LOCALES, getLocalizedHref } from "@/i18n/links"; import { usePathname } from "next/navigation"; import { useTheme } from "next-themes"; import { ArrowRight, BookA, BookOpen, Box, ChevronDown, Cpu, Library, Menu, Moon, Scale, Search, SlidersHorizontal, Sparkles, Sun, X, AlertTriangle, } from "lucide-react"; const MENUS = [ { id: "hardware", label: "Hardware", items: [ { href: "/series", label: "Séries ESP32", desc: "12 chips, pinagem e especificações", icon: Cpu }, { href: "/comparacao", label: "Comparador", desc: "Até quatro séries lado a lado", icon: Scale }, { href: "/catalogo", label: "Catálogo de placas", desc: "DevKits, pinos e onde comprar", icon: Box }, ], }, { id: "tools", label: "Ferramentas", items: [ { href: "/seletor", label: "Seletor inteligente", desc: "O chip certo para o seu projeto", icon: SlidersHorizontal }, { href: "/diagnostico", label: "Diagnóstico", desc: "Brownout, bootloop, WDT e mais", icon: AlertTriangle }, { href: "/componentes", label: "Component Registry", desc: "Drivers e manifests idf_component.yml", icon: Search }, ], }, { id: "library", label: "Biblioteca", items: [ { href: "/frameworks", label: "Frameworks e SDKs", desc: "ESP-IDF, Arduino, Rust e Matter", icon: BookOpen }, { href: "/glossario", label: "Glossário técnico", desc: "Os termos que aparecem nos datasheets", icon: BookA }, { href: "/sobre", label: "Sobre o projeto", desc: "Autoria, método e abertura", icon: Sparkles }, ], }, ]; const MOBILE_LINKS = [ { href: "/series", label: "Séries ESP32" }, { href: "/comparacao", label: "Comparador" }, { href: "/seletor", label: "Seletor inteligente" }, { href: "/diagnostico", label: "Diagnóstico" }, { href: "/frameworks", label: "Frameworks e SDKs" }, { href: "/componentes", label: "Component Registry" }, { href: "/glossario", label: "Glossário" }, { href: "/catalogo", label: "Catálogo de placas" }, { href: "/livro", label: "O livro" }, { href: "/sobre", label: "Sobre" }, ]; function isActivePath(pathname, href, currentLocale) { const localized = getLocalizedHref(`/${currentLocale}${href}`, currentLocale); if (href === "/" || localized === `/${currentLocale}/` || localized === `/${currentLocale}`) { return pathname === `/${currentLocale}` || pathname === `/${currentLocale}/`; } return pathname === localized || String(pathname).startsWith(`${localized}/`); } export default function Header() { const pathname = usePathname() || ""; const [mounted, setMounted] = useState(false); const [openMenu, setOpenMenu] = useState(null); const [drawerOpen, setDrawerOpen] = useState(false); const navRef = useRef(null); const closeRef = useRef(null); const menuButtonRef = useRef(null); const currentLocale = LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt"; const isPt = currentLocale === "pt"; const getLinkHref = (href) => getLocalizedHref(`/${currentLocale}${href}`, currentLocale); useEffect(() => setMounted(true), []); useEffect(() => { setOpenMenu(null); setDrawerOpen(false); }, [pathname]); useEffect(() => { function onPointerDown(event) { if (navRef.current && !navRef.current.contains(event.target)) setOpenMenu(null); } function onKeyDown(event) { if (event.key === "Escape") { setOpenMenu(null); setDrawerOpen(false); } } document.addEventListener("mousedown", onPointerDown); document.addEventListener("keydown", onKeyDown); return () => { document.removeEventListener("mousedown", onPointerDown); document.removeEventListener("keydown", onKeyDown); }; }, []); useEffect(() => { if (!drawerOpen) return; const previous = document.body.style.overflow; document.body.style.overflow = "hidden"; closeRef.current?.focus(); return () => { document.body.style.overflow = previous; menuButtonRef.current?.focus(); }; }, [drawerOpen]); const visibleMobileLinks = isPt ? MOBILE_LINKS : MOBILE_LINKS.filter((l) => l.href !== "/livro"); return (
ESPDocs
{mounted && createPortal( <>
setDrawerOpen(false)} aria-hidden="true" />

Navegação

Para onde ir

{isPt && (
setDrawerOpen(false)} className="group grid grid-cols-[3.25rem_1fr_auto] items-center gap-3 rounded-2xl bg-[#0b0d10] p-3 text-[#f4f6f8] ring-1 ring-white/10" > {/* eslint-disable-next-line @next/next/no-img-element */} Livro novo Microcontroladores ESP32 Conectividade, eficiência e desempenho
)}
setDrawerOpen(false)} className="btn btn-primary w-full">
, document.body )}
); } function ThemeToggle() { const { resolvedTheme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); if (!mounted) { return