import { createContext, useContext, useEffect, useMemo, useState, type ReactNode, } from "react"; export type UhuruPanelRoute = { element: ReactNode; path: string; }; export type UhuruPanelRouteDefinition = UhuruPanelRoute; type PanelRouteContextValue = { activeRoute: UhuruPanelRoute | null; clear: () => void; navigate: (route: UhuruPanelRoute) => void; }; /** Return the complete browser location used by Uhuru's local panel router. */ export function getUhuruPanelLocation() { if (typeof window === "undefined") return ""; return `${window.location.pathname}${window.location.search}${window.location.hash}`; } /** * Match a route against the current browser location. Query/hash-aware routes * must match exactly; path-only routes continue to work when a consumer owns * unrelated query parameters. */ export function matchesUhuruPanelRoute(routePath: string, location = getUhuruPanelLocation()) { if (!location) return false; if (routePath === location) return true; const routeHasQueryOrHash = /[?#]/.test(routePath); if (routeHasQueryOrHash) return false; return location.split(/[?#]/, 1)[0] === routePath; } const PanelRouteContext = createContext(null); export function UhuruPanelRouteProvider({ children }: { children: ReactNode }) { const [activeRoute, setActiveRoute] = useState(null); useEffect(() => { function handlePopState() { setActiveRoute(null); } window.addEventListener("popstate", handlePopState); return () => window.removeEventListener("popstate", handlePopState); }, []); const value = useMemo( () => ({ activeRoute, clear: () => setActiveRoute(null), navigate: (route) => { if ( typeof window !== "undefined" && getUhuruPanelLocation() !== route.path ) { window.history.pushState({}, "", route.path); } setActiveRoute(route); }, }), [activeRoute], ); return {children}; } export function useUhuruPanelRoute() { return useContext(PanelRouteContext); }