// What Framework Router - TypeScript Definitions import { VNode, VNodeChild, Component, Signal, Computed } from './index.js'; // --- Route State --- export interface RouteState { /** Current full URL */ readonly url: string; /** Current pathname */ readonly path: string; /** Route parameters */ readonly params: Record; /** Query parameters */ readonly query: Record; /** URL hash */ readonly hash: string; /** Navigation in progress */ readonly isNavigating: boolean; /** Navigation error if any */ readonly error: Error | null; } export const route: RouteState; // --- Navigation --- export interface NavigateOptions { /** Replace current history entry */ replace?: boolean; /** History state object */ state?: any; /** Use View Transitions API */ transition?: boolean; } /** Navigate to a new URL */ export function navigate(to: string, options?: NavigateOptions): Promise; // --- Route Configuration --- export interface RouteConfig { /** URL path pattern */ path: string; /** Page component */ component: Component; /** Layout wrapper */ layout?: Component; /** Loading component */ loading?: Component<{}>; /** Error component */ error?: Component<{ error: Error; reset: () => void }>; /** Route middleware */ middleware?: RouteMiddleware[]; } export interface RouteComponentProps { params: Record; query: Record; route: RouteConfig; } export interface LayoutProps { params: Record; query: Record; children?: VNodeChild; } /** Middleware is synchronous: allow with true/void, block with false, or redirect with a path. Use asyncGuard for async checks. */ export type RouteMiddleware = (props: RouteComponentProps & { path: string }) => boolean | string | void; // --- Router Component --- export interface RouterProps { routes: RouteConfig[]; fallback?: Component<{}>; globalLayout?: Component<{ children?: VNodeChild }>; } export function Router(props: RouterProps): VNode; // --- File-Based Router --- export interface FileRouteConfig { path: string; component: Component; layout?: Component; mode?: 'static' | 'server' | 'client' | 'hybrid'; } export interface FileRouterProps { routes: FileRouteConfig[]; layout?: Component<{ children?: VNodeChild }>; fallback?: Component<{}>; error?: Component<{ error: Error; reset: () => void }>; } /** Router driven by what-compiler's generated route manifest (virtual:what-routes). */ export function FileRouter(props: FileRouterProps): VNode; // --- Link Component --- export interface LinkProps { href: string; class?: string; className?: string; replace?: boolean; prefetch?: boolean; activeClass?: string; exactActiveClass?: string; transition?: boolean; children?: VNodeChild; [key: string]: any; } export function Link(props: LinkProps): VNode; export function NavLink(props: LinkProps): VNode; // --- Route Helpers --- /** Define routes from object config */ export function defineRoutes(config: Record>): RouteConfig[]; /** Create nested routes with shared options */ export function nestedRoutes( basePath: string, children: RouteConfig[], options?: { layout?: Component; loading?: Component; error?: Component } ): RouteConfig[]; /** Group routes without affecting URLs */ export function routeGroup( name: string, routes: RouteConfig[], options?: { layout?: Component; middleware?: RouteMiddleware[] } ): RouteConfig[]; // --- Redirect --- export function Redirect(props: { to: string }): null; // --- Guards --- /** Create a route guard */ export function guard( check: (props: RouteComponentProps) => boolean, fallback: string | Component ):

(component: Component

) => Component

; /** Create an async route guard */ export function asyncGuard( check: (props: RouteComponentProps) => Promise, options?: { fallback?: string | Component; loading?: Component } ):

(component: Component

) => Component

; // --- Prefetch --- export function prefetch(href: string): void; // --- Scroll Restoration --- export function enableScrollRestoration(): void; // --- View Transitions --- export function viewTransitionName(name: string): { style: { viewTransitionName: string } }; export function setViewTransition(type: string): void; // --- useRoute Hook --- export interface UseRouteResult { path: Computed; params: Computed>; query: Computed>; hash: Computed; isNavigating: Computed; navigate: typeof navigate; prefetch: typeof prefetch; } export function useRoute(): UseRouteResult; // --- Route Accessors --- /** Current route params. Subscribes when read inside a tracking scope. */ export function useParams>(): T; /** * Query string of the last successfully matched route, parsed. Subscribes when * read inside a tracking scope. Only the Router's match branch writes it, so on * an unmatched (404) route this is the previous route's query, not the current * URL's. Same value and same caveat as `route.query`. */ export function useSearch>(): T; /** The navigate function, for symmetry with useParams/useSearch. */ export function useNavigate(): typeof navigate; /** Prefetch a route's assets. */ export function prefetchRoute(href: string): void; // --- Redirect Signal --- /** * Abort the current render and navigate. * * Throws a navigation signal. Two places catch it: route middleware, caught by * the Router's matching pass, and a component body, caught by the runtime where * it instantiates components. Anywhere else (an event handler, a promise * callback, a timer, or a reactive thunk such as `{() => cond() && redirect(to)}`) * nothing catches it and the signal surfaces as an uncaught error carrying * `ERR_REDIRECT_NOT_CAUGHT`; call `navigate(to)` there instead. In a thunk the * first render reports the error, but on a later re-run the navigation simply * does not happen and the stale DOM stays, so prefer `navigate(to)` there. * A `try/catch` around the call also swallows it, so rethrow anything whose * `name` is `RouterRedirect`. On the server the signal escapes `renderToString` * to its caller: read `.to` and emit a 302. */ export function redirect(to: string, options?: NavigateOptions): never; // --- Navigation Hooks --- /** * Run before every route navigation; return false to cancel. Returns an * unsubscribe. Not consulted for same-page hash navigation (`navigate('#x')` * scrolls, it does not change the route). Cancelling a back/forward navigation * restores the address bar by pushing the previous URL as a new history entry: * the entry the browser moved to is not recovered and its `history.state` is * not carried over. */ export function beforeNavigate(fn: (to: string, from: string) => boolean | Promise): () => void; /** Run after every committed navigation. Returns an unsubscribe. */ export function afterNavigate(fn: (to: string, from: string) => void): () => void; // --- Outlet --- export function Outlet(props: { children?: VNodeChild }): VNode; // --- Path Matching --- export interface CompiledPath { regex: RegExp; paramNames: string[]; catchAll: string | null; } /** Compile a path pattern (`/users/:id`, `/posts/*`, `/[slug]`) to a matcher. */ export function compilePath(path: string): CompiledPath; /** Match a pathname against routes, most specific first. */ export function matchRoute( path: string, routes: T[], ): { route: T; params: Record } | null; /** Parse a query string into a null-prototype object. */ export function parseQuery(search: string): Record; /** Reject javascript:, data:, vbscript: and protocol-relative URLs. */ export function isSafeUrl(url: string): boolean;