"use client"; import Link from "next/link"; import * as navigation from "next/navigation"; import { type ComponentProps, useState } from "react"; type LinkHref = ComponentProps["href"]; /** * O caminho da página aberta. Sem `usePathname` (testes que trocam next/navigation por um dublê só com * `notFound`, por exemplo) vale `null`: sem caminho conhecido, nada muda no pré-carregamento. */ const usePathname: () => string | null = navigation.usePathname ?? (() => null); /** Link para um ponto da home: `/#contact` ou `/?tipo=site#contact`. */ function isHomeAnchor(href: LinkHref) { if (typeof href === "string") return /^\/(\?[^#]*)?#/.test(href); return href.pathname === "/" && Boolean(href.hash); } /** * Link interno que só pré-carrega a rota quando a pessoa chega nele (mouse, teclado ou toque). * O padrão do Link pré-carrega todo link visível ao abrir a página, e o cabeçalho e a faixa de clientes * somavam 15 pedidos disputando a rede na abertura. Com `prefetch={false}` o App Router não pré-carrega nem no hover. * Padrão da documentação do Next: node_modules/next/dist/docs/01-app/02-guides/prefetching.md. * * Fora da home, um link para um ponto dela (`/#contact`) não pré-carrega nem no hover: o pré-carregamento puxaria * a home inteira, com o CSS da vitrine, para quem só passou o mouse (e o navegador avisava "preloaded but not * used"). Na própria home o link leva à página em que a pessoa já está, e o pré-carregamento segue o padrão. O * caminho vem de `usePathname`, e não de uma leitura única no hover: o cabeçalho e o rodapé não remontam entre as * páginas, e um link ativado na home não pode continuar pré-carregando depois que a pessoa sair dela. */ export default function HoverPrefetchLink({ onMouseEnter, onFocus, onTouchStart, ...props }: Omit, "prefetch">) { const pathname = usePathname(); const [active, setActive] = useState(false); const homeAnchorFromElsewhere = pathname !== null && pathname !== "/" && isHomeAnchor(props.href); return ( { setActive(true); onMouseEnter?.(event); }} onFocus={(event) => { setActive(true); onFocus?.(event); }} onTouchStart={(event) => { setActive(true); onTouchStart?.(event); }} /> ); }