"use client"; import { Box, LinearProgress } from "@mui/material"; import { usePathname } from "next/navigation"; import { createContext, useCallback, useContext, useMemo, useState, type ReactNode, } from "react"; import { mapSkeletonForPath, MapRouteSkeleton, PageLoadingSkeleton, } from "./PageLoadingSkeleton"; type PendingNavigation = { id: string; pathname: string }; type NavigationFeedback = { pendingPath: string | null; reportPending: (id: string, pathname: string, pending: boolean) => void; }; const NavigationContext = createContext({ pendingPath: null, reportPending: () => {}, }); export const useNavigationFeedback = () => useContext(NavigationContext); export function NavigationFeedbackProvider({ children }: { children: ReactNode }) { const pathname = usePathname(); const [navigation, setNavigation] = useState(null); const reportPending = useCallback((id: string, target: string, pending: boolean) => { setNavigation((current) => { if (!pending) return current?.id === id ? null : current; return current?.id === id && current.pathname === target ? current : { id, pathname: target }; }); }, []); // History commits can precede a page's lazy component. Its loading.tsx and // dynamic fallback take over at that point, without an artificial delay. const pendingPath = navigation && navigation.pathname !== pathname ? navigation.pathname : null; const value = useMemo(() => ({ pendingPath, reportPending }), [pendingPath, reportPending]); return ( {children} ); } export function PageNavigationContent({ children }: { children: ReactNode }) { const pathname = usePathname(); const { pendingPath } = useNavigationFeedback(); const withinMap = Boolean(mapSkeletonForPath(pathname) && pendingPath && mapSkeletonForPath(pendingPath)); return ( {children} {pendingPath && ( <> {!withinMap && ( )} )} ); } export function MapNavigationContent({ children }: { children: ReactNode }) { const { pendingPath } = useNavigationFeedback(); return ( <> {children} {pendingPath && } ); }