UNPKG

remix-utils-rt

Version:

This package contains simple utility functions to use with [React Router](https://reactrouter.com/home).

69 lines 2.8 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import * as React from "react"; import { PrefetchPageLinks, useNavigate } from "react-router"; const context = React.createContext(false); export function isLinkEvent(event) { if (!(event.target instanceof HTMLElement)) return; let a = event.target.closest("a"); if (a?.hasAttribute("href") && a.host === window.location.host) return a; return; } export function useDelegatedAnchors(nodeRef) { let navigate = useNavigate(); let hasParentPrefetch = React.useContext(context); React.useEffect(() => { // if you call useDelegatedAnchors as a children of a PrefetchPageAnchors // then do nothing if (hasParentPrefetch) return; let node = nodeRef.current; node?.addEventListener("click", handleClick); return () => node?.removeEventListener("click", handleClick); function handleClick(event) { if (!node) return; let anchor = isLinkEvent(event); if (!anchor) return; if (event.button !== 0) return; if (anchor.target && anchor.target !== "_self") return; if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) { return; } if (anchor.hasAttribute("download")) return; let { pathname, search, hash } = anchor; navigate({ pathname, search, hash }); event.preventDefault(); } }, [hasParentPrefetch, navigate, nodeRef]); } export function PrefetchPageAnchors({ children, }) { let nodeRef = React.useRef(null); let [page, setPage] = React.useState(null); let hasParentPrefetch = React.useContext(context); // prefetch is useless without delegated anchors, so we enable it useDelegatedAnchors(nodeRef); React.useEffect(() => { if (hasParentPrefetch) return; let node = nodeRef.current; node?.addEventListener("mouseenter", handleMouseEnter, true); return () => node?.removeEventListener("mouseenter", handleMouseEnter); function handleMouseEnter(event) { if (!nodeRef.current) return; let anchor = isLinkEvent(event); if (!anchor) return; let { pathname, search } = anchor; setPage(pathname + search); } }, [hasParentPrefetch]); return (_jsxs("div", { ref: nodeRef, style: { display: "contents" }, children: [_jsx(context.Provider, { value: true, children: children }), page && !hasParentPrefetch && _jsx(PrefetchPageLinks, { page: page })] })); } //# sourceMappingURL=use-delegated-anchors.js.map