{"version":3,"file":"router.mjs","names":[],"sources":["../src/router/errors.ts","../src/router/components/error.tsx","../src/router/symbols.ts","../src/router/components/router.tsx","../src/router/components/link.tsx","../src/router/redirect.ts","../src/router/util.ts","../src/router/outlet.tsx","../src/router/route.tsx","../src/router/make-routes.tsx","../src/router/router.store.ts","../src/router/use-confirm-leave.ts","../src/router/use-navigation-block.ts"],"sourcesContent":["import type { MatchState } from \"./make-routes\";\n\nexport type RouterErrorType = \"NOT_FOUND\" | \"GUARD\" | \"LOAD\" | \"RENDER\" | \"REDIRECT\";\n\nexport interface RouterErrorOptions {\n  message?: string;\n  cause?: unknown;\n  path?: string;\n}\n\nconst defaultMessage = (type: RouterErrorType, path?: string): string => {\n  switch (type) {\n    case \"NOT_FOUND\":\n      return path ? `No route matches '${path}'.` : \"No matching route.\";\n    case \"GUARD\":\n      return \"A route guard rejected the navigation.\";\n    case \"LOAD\":\n      return \"A route loader or lazy component failed.\";\n    case \"RENDER\":\n      return \"A route component failed to render.\";\n    case \"REDIRECT\":\n      return path\n        ? `The redirect for '${path}' could not be resolved.`\n        : \"A redirect could not be resolved.\";\n  }\n};\n\n/**\n * The single error type surfaced to `[ERROR]` components. `type`\n * discriminates the failure source; when the router wraps an\n * application-level error (thrown by a guard or loader), the original\n * is preserved on the standard `cause` property.\n *\n * Guards and loaders may also throw `RouterError` directly — e.g.\n * `throw new RouterError(\"NOT_FOUND\")` from a loader when an entity\n * doesn't exist — and it passes through unwrapped.\n */\nexport class RouterError extends Error {\n  readonly type: RouterErrorType;\n  readonly path?: string;\n\n  /** @internal matched-prefix state captured when the matcher throws NOT_FOUND */\n  state?: MatchState;\n  /** @internal level index of the failing guard, for depth-aware bubbling */\n  depth?: number;\n\n  constructor(type: RouterErrorType, options?: RouterErrorOptions) {\n    super(options?.message ?? defaultMessage(type, options?.path), { cause: options?.cause });\n    this.name = \"RouterError\";\n    this.type = type;\n    this.path = options?.path;\n  }\n}\n\n/**\n * @internal Builds the `REDIRECT` error for a redirect that could not be\n * carried out — a `[REDIRECT]` function that threw, or navigation options\n * naming a path whose `:params` can't be filled.\n *\n * `from` carries whatever the `Redirect` knew about where it came from, so\n * the error route keeps the matched prefix's layout and wrappers and bubbles\n * to the same `[ERROR]` a failure at that level would have.\n */\nexport const redirectFailed = (\n  cause: unknown,\n  path: string | undefined,\n  from?: { state?: MatchState; depth?: number },\n): RouterError => {\n  const error = new RouterError(\"REDIRECT\", { cause, path });\n  error.state = from?.state;\n  error.depth = from?.depth;\n  return error;\n};\n","import React from \"react\";\nimport { RouterError } from \"../errors\";\nimport type { Route } from \"../route\";\nimport type { Component, ErrorProps } from \"../types\";\n\n/**\n * Rendered when an error occurs and no `[ERROR]` component is defined\n * on the matched prefix. Deliberately minimal and dependency-free —\n * define a root-level `[ERROR]` to replace it.\n */\nexport const DefaultErrorPage: Component = ({ error }: ErrorProps) => (\n  <div role=\"alert\">\n    <h1>{error.type === \"NOT_FOUND\" ? \"Page Not Found\" : \"Something Went Wrong\"}</h1>\n    <p>{error.message}</p>\n  </div>\n);\n\nexport interface RouteErrorBoundaryProps {\n  route: Route;\n  fallback: Component;\n  children?: React.ReactNode;\n}\n\ninterface RouteErrorBoundaryState {\n  error?: RouterError;\n  route?: Route;\n}\n\n/**\n * Catches render-time crashes in page and `[WRAPPER]` components and\n * renders the nearest `[ERROR]` component with `type: \"RENDER\"`. Mounted\n * inside the `[LAYOUT]` so the layout survives page crashes; crashes in\n * the layout itself (or in the fallback) propagate out of `<Router>` by\n * design — those are developer bugs that should stay loud.\n *\n * Deliberately NOT keyed by location: the boundary must be transparent\n * to reconciliation (a key would remount the entire subtree and re-fire\n * every effect on each navigation). Instead, a captured error is cleared\n * when a new Route object arrives.\n */\nexport class RouteErrorBoundary extends React.Component<\n  RouteErrorBoundaryProps,\n  RouteErrorBoundaryState\n> {\n  override state: RouteErrorBoundaryState = {};\n\n  static getDerivedStateFromError(cause: unknown): RouteErrorBoundaryState {\n    return { error: cause instanceof RouterError ? cause : new RouterError(\"RENDER\", { cause }) };\n  }\n\n  static getDerivedStateFromProps(\n    props: RouteErrorBoundaryProps,\n    state: RouteErrorBoundaryState,\n  ): Partial<RouteErrorBoundaryState> | null {\n    if (state.route === props.route) return null;\n    // a new Route object means a navigation occurred — clear any\n    // captured error so the boundary doesn't keep a stale fallback\n    return { route: props.route, error: undefined };\n  }\n\n  override render(): React.ReactNode {\n    if (!this.state.error) return this.props.children;\n\n    const Fallback = this.props.fallback;\n    return <Fallback route={this.props.route} error={this.state.error} />;\n  }\n}\n","export const CONTEXT: unique symbol = Symbol.for(\"MOBX_ROUTER_CONTEXT\");\nexport const LAYOUT: unique symbol = Symbol.for(\"MOBX_ROUTER_LAYOUT\");\nexport const WRAPPER: unique symbol = Symbol.for(\"MOBX_ROUTER_WRAPPER\");\nexport const LOAD: unique symbol = Symbol.for(\"MOBX_ROUTER_LOAD\");\nexport const GUARD: unique symbol = Symbol.for(\"MOBX_ROUTER_GUARD\");\nexport const PAGE: unique symbol = Symbol.for(\"MOBX_ROUTER_PAGE\");\nexport const ERROR: unique symbol = Symbol.for(\"MOBX_ROUTER_ERROR\");\nexport const LOADING: unique symbol = Symbol.for(\"MOBX_ROUTER_LOADING\");\nexport const SPLASH: unique symbol = Symbol.for(\"MOBX_ROUTER_SPLASH\");\nexport const REDIRECT: unique symbol = Symbol.for(\"MOBX_ROUTER_REDIRECT\");\n","import { observer } from \"mobx-react-lite\";\nimport { createContext, useContext } from \"react\";\nimport type { Route } from \"../route\";\nimport type { RouterStore } from \"../router.store\";\nimport { SPLASH } from \"../symbols\";\nimport type { Component, RouteLevel } from \"../types\";\nimport { DefaultErrorPage, RouteErrorBoundary } from \"./error\";\n\nexport const PassThrough: Component = ({ children }) => children;\n\n/** One rendered slot in the outlet chain: what fills it, and where it sits. */\nexport interface OutletSlot {\n  Component: Component | undefined;\n  level: RouteLevel | undefined;\n}\n\n// Plain (non-observer) renderer. State observation lives one level up\n// in `Router`, so the page component renders as a child of a plain\n// FunctionComponent — no memo wrapper in the parent chain to interact\n// with React Refresh's family-update propagation.\nexport const RouterOutlet: React.FC<{ route: Route; slots: OutletSlot[] }> = ({ route, slots }) => {\n  const [slot, ...remaining] = slots;\n  const C = slot?.Component;\n\n  if (!C) return null;\n\n  return (\n    <C route={route} level={slot.level}>\n      {remaining.length > 0 && <RouterOutlet route={route} slots={remaining} />}\n    </C>\n  );\n};\n\nexport const routerContext = createContext<RouterStore>(null as any);\nexport const useRouter = () => useContext(routerContext);\n\nexport interface RouterProps {\n  store: RouterStore;\n}\n\nexport const Router = observer(({ store }: RouterProps) => {\n  // On a warm navigation `activeRoute` holds the previous page on screen\n  // until the pending one has loaded. On a cold load there is nothing to\n  // preserve, so the pending route renders instead and its outlets surface\n  // their [LOADING] components while they resolve.\n  const route = store.activeRoute ?? store.pendingRoute;\n  if (!route) {\n    // Nothing has matched yet — the first navigation is still matching or\n    // running its guards. No route means no layout and no outlets, so\n    // [SPLASH] is the only thing that can be shown here.\n    const Splash = store.routesDef?.[SPLASH];\n    return Splash ? <Splash /> : null;\n  }\n\n  const Layout = route.layout ?? PassThrough;\n  // `Component` is a computed and must be read here, inside the observer\n  const slots = route.outlets.map((o) => ({ Component: o.Component, level: o.level }));\n  const outlet = <RouterOutlet route={route} slots={slots} />;\n\n  // Render crashes in pages/wrappers funnel to the nearest [ERROR]\n  // component; the layout survives. On synthetic error routes the\n  // boundary is omitted so a crashing [ERROR] component propagates\n  // out of <Router> — a developer bug that should stay loud. Layout\n  // crashes propagate for the same reason. The boundary is unkeyed on\n  // purpose — it resets itself when the route changes — so navigation\n  // reconciles by component type instead of remounting the subtree.\n  const fallback = route.levels.at(-1)?.errorComponent ?? DefaultErrorPage;\n\n  return (\n    <routerContext.Provider value={store}>\n      <Layout route={route}>\n        {route.error ? (\n          outlet\n        ) : (\n          <RouteErrorBoundary route={route} fallback={fallback}>\n            {outlet}\n          </RouteErrorBoundary>\n        )}\n      </Layout>\n    </routerContext.Provider>\n  );\n});\n","import { observer } from \"mobx-react-lite\";\nimport React, { useCallback } from \"react\";\nimport type {\n  DynamicRoutePath,\n  ExtractParams,\n  NavigateOptions,\n  RoutePath,\n  StaticRoutePath,\n} from \"../types\";\nimport { useRouter } from \"./router\";\n\n/**\n * The host element's own props, minus the ones the link claims for itself — everything that passes\n * straight through to whatever `C` renders as.\n *\n * Deliberately not called `LinkProps`: these are the *element's* props, not the link's. The link's\n * own are {@link LinkPropsBase}, which is built from these.\n */\ntype PassthroughProps<C extends React.ElementType> = Omit<\n  React.ComponentProps<C>,\n  | \"ref\"\n  | \"exact\"\n  | \"to\"\n  | \"params\"\n  | \"onClick\"\n  | \"asChild\"\n  | \"replace\"\n  | \"state\"\n  | \"search\"\n  | \"preserveSearch\"\n>;\n\nexport type LinkPropsBase<\n  C extends React.ElementType,\n  I extends React.ElementType = C,\n> = PassthroughProps<C> &\n  // `replace`, `state`, `search` and `preserveSearch` — everything\n  // `navigate()` takes beyond the destination itself, which `to` and\n  // `params` carry. Derived rather than restated so a new navigate option\n  // reaches links without a second edit.\n  Omit<NavigateOptions<string>, \"to\" | \"params\"> & {\n    exact?: boolean;\n    ref?: React.Ref<React.ComponentRef<I>>;\n    /**\n     * Runs before the link navigates, and can cancel it with\n     * `preventDefault()`. Declared here rather than inherited from `C` so the\n     * signature stays the same whatever element the link renders as.\n     */\n    onClick?: (event: React.MouseEvent<HTMLElement>) => void;\n  };\n\n// function overloading is much faster than leveraging conditional types\n// but once the typescript go compiler is released and performance is no\n// longer an issue, it might make sense to simplify this a bit so it can\n// be more easily consumed by users\nexport interface LinkComponent<C extends React.ElementType, I extends React.ElementType = C> {\n  <P extends StaticRoutePath>(\n    props: LinkPropsBase<C, I> & { to: P; params?: undefined },\n  ): React.ReactNode;\n  <P extends DynamicRoutePath>(\n    props: LinkPropsBase<C, I> & { to: P; params: ExtractParams<P> },\n  ): React.ReactNode;\n}\n\n// final thing to do is make sure refs still work in React 19\n\n// this smooths over some of the awkwardness when extending this component\nexport const makeLinkComponent = <C extends React.ElementType, I extends React.ElementType = C>(\n  C: C,\n  baseProps?: Partial<PassthroughProps<C>> & {\n    as?: I;\n    onClick?: (event: React.MouseEvent<HTMLElement>) => void;\n  },\n) => {\n  return observer(\n    ({ to, params, exact, replace, state, search, preserveSearch, children, ...props }: any) => {\n      const router = useRouter();\n      const mergedProps = { ...baseProps, ...props };\n\n      // the href carries `search`/`preserveSearch` too, so a cmd-click opens\n      // the URL a plain click would have navigated to rather than a bare\n      // pathname. `replace` and `state` have no equivalent — a new tab starts\n      // its own history — and are dropped from it.\n      if (props.role !== \"link\") {\n        mergedProps.href = router.resolveHref({\n          to,\n          params,\n          search,\n          preserveSearch,\n        } as NavigateOptions<RoutePath>);\n      }\n\n      if (router.doesPathMatch(to, exact)) {\n        mergedProps[\"aria-current\"] = \"page\";\n      }\n\n      const onClick = props.onClick ?? baseProps?.onClick;\n      const hasHref = mergedProps.href !== undefined;\n\n      mergedProps.onClick = useCallback(\n        (event: React.MouseEvent<HTMLElement>) => {\n          // a disabled link is inert: no navigation, no href, and no handler\n          // — the same as a native disabled control\n          if (props.disabled) {\n            event.preventDefault();\n            return;\n          }\n\n          // the caller's handler runs first and owns the decision: calling\n          // preventDefault() cancels the navigation, and the href with it,\n          // which is what a \"confirm before leaving\" handler wants\n          onClick?.(event);\n          if (event.defaultPrevented) return;\n\n          // Let the browser have the ones it does better: cmd/ctrl-click opens\n          // a new tab, shift a new window, alt downloads, middle-click a\n          // background tab. The href is already correct, so the only thing\n          // that broke these was cancelling the event. Only worth deferring to\n          // when there is an href to follow — a link rendered as a button (or\n          // with role=\"link\") has none, so a modifier-click there navigates in\n          // place rather than doing nothing at all.\n          if (hasHref && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {\n            return;\n          }\n\n          // `button` is 0 for a primary click and for a keyboard-activated\n          // one; a middle-click arrives as button 1 where it reaches click at\n          // all (most browsers route it to auxclick, which is left untouched)\n          if (hasHref && event.button !== 0) {\n            return;\n          }\n\n          event.preventDefault();\n          // a link click is fire-and-forget; the promise is for callers who\n          // want to sequence work after the navigation lands\n          void router.navigate({\n            to,\n            params,\n            replace,\n            state,\n            search,\n            preserveSearch,\n          } as NavigateOptions<RoutePath>);\n        },\n        [\n          router,\n          to,\n          params,\n          replace,\n          state,\n          search,\n          preserveSearch,\n          props.disabled,\n          onClick,\n          hasHref,\n        ],\n      );\n\n      return React.createElement(C, mergedProps, children);\n    },\n  ) as LinkComponent<C, I>;\n};\n\n//export const Link = makeLinkComponent('a');\n","import type { MatchState } from \"./make-routes\";\nimport type { NavigateOptions, RoutePath } from \"./types\";\n\nexport class Redirect<P extends RoutePath = RoutePath> {\n  /**\n   * @internal matched-prefix state, set when the matcher throws this for a\n   * `[REDIRECT]` leaf. Used to render the error route if the redirect fails.\n   */\n  state?: MatchState;\n  /** @internal level index of the guard that threw, for depth-aware bubbling */\n  depth?: number;\n\n  constructor(readonly options: NavigateOptions<P>) {}\n}\n\nexport const redirect = <P extends RoutePath>(options: NavigateOptions<P>): Redirect<P> =>\n  new Redirect(options);\n","import { PAGE, REDIRECT } from \"./symbols\";\nimport type { Component, LazyComponent, Leaf, Obj, Page, Redirector } from \"./types\";\n\n/**\n * Substitute a path pattern's `:params`. Throws when one has no value —\n * the right default for `navigate()` and `href`, where an unresolved path\n * is a bug rather than a state to render.\n *\n * Use {@link tryResolvePath} for a path you did not construct — resolving a\n * `level.pattern` against params that may not reach that deep, say.\n */\nexport const resolvePath = (to: string, params?: Obj): string => {\n  return to.replaceAll(/:[^/]*/g, (segment) => {\n    const value = params?.[segment.slice(1)];\n    if (!value)\n      throw new Error(`Unable to resolve route '${to}'. Parameter '${segment}' not specified.`);\n    return value;\n  });\n};\n\n/**\n * {@link resolvePath} without the throw: `undefined` when any `:param` has\n * no value. The idiom for \"link it if we can address it, otherwise render\n * it as plain text\".\n */\nexport const tryResolvePath = (to: string, params?: Obj): string | undefined => {\n  let resolved = true;\n  const path = to.replaceAll(/:[^/]*/g, (segment) => {\n    const value = params?.[segment.slice(1)];\n    if (!value) {\n      resolved = false;\n      return segment;\n    }\n    return value;\n  });\n  return resolved ? path : undefined;\n};\n\nexport const isComponent = (data: any): data is Component => {\n  if (!data) return false;\n  return (\n    typeof data === \"function\" ||\n    (typeof data === \"object\" && data[\"$$typeof\"] === Symbol.for(\"react.memo\"))\n  );\n};\n\nexport const isPage = (data: any): data is Page => {\n  if (typeof data !== \"object\") return false;\n  const symbols = Object.getOwnPropertySymbols(data);\n  return symbols.includes(PAGE);\n};\n\nexport const isRedirect = (data: any): data is Redirector => {\n  if (typeof data !== \"object\") return false;\n  const symbols = Object.getOwnPropertySymbols(data);\n  return symbols.includes(REDIRECT);\n};\n\nexport const isLeaf = (data: any): data is Leaf => {\n  return isComponent(data) || isPage(data) || isRedirect(data);\n};\n\nexport const isLazyComponent = (data: any): data is LazyComponent => {\n  return typeof data === \"function\" && data.toString().startsWith(\"() => import(\");\n};\n","import { makeAutoObservable, observable } from \"mobx\";\nimport { DefaultErrorPage } from \"./components/error\";\nimport { RouterError } from \"./errors\";\nimport { Redirect } from \"./redirect\";\nimport type { Route } from \"./route\";\nimport type { Component, LazyComponent, Loader, Obj, RouteLevel } from \"./types\";\nimport { isLazyComponent } from \"./util\";\n\nexport interface OutletConfig {\n  component?: Component | LazyComponent;\n  loader?: Loader;\n  errorComponent?: Component;\n  loadingComponent?: Component;\n  /**\n   * The matched level this outlet renders at. Passed to whatever component\n   * fills the slot — the outlet's own, or the `[LOADING]` / `[ERROR]` that\n   * stands in for it — alongside `route`.\n   */\n  level?: RouteLevel;\n}\n\nexport type RouteSegmentState = \"preloading\" | \"loading\" | \"error\" | \"ready\";\n\nexport interface LoadOptions {\n  /**\n   * Hold the `[LOADING]` component on screen for\n   * `LOADING_MIN_DURATION_MS` after the data arrives, so a just-shown\n   * indicator can't vanish a frame later. Only worth paying for when the\n   * indicator is actually rendered — i.e. a cold load. During a warm\n   * navigation the previous page is still on screen and the pending\n   * route's outlets aren't rendered at all, so holding would delay\n   * content to hide an indicator nobody saw.\n   */\n  hold?: boolean;\n}\n\n/**\n * How long an outlet stays `\"preloading\"` — rendering nothing — before\n * it shows its `[LOADING]` component. Loads that finish inside this\n * window never render an indicator at all.\n */\nexport const LOADING_DELAY_MS = 300;\n\n/**\n * Once the `[LOADING]` component is on screen, how long it is held there\n * even if the data has already arrived. Only applies to loads that\n * already exceeded `LOADING_DELAY_MS`, and exists solely to keep a\n * just-shown indicator from vanishing a frame later.\n */\nexport const LOADING_MIN_DURATION_MS = 300;\n\nexport const DefaultOutlet: Component = ({ children }) => children;\n\n/**\n * Rendered in a pending outlet's slot when no `[LOADING]` component is\n * defined at or above that level. Deliberately minimal — define a\n * root-level `[LOADING]` to replace it.\n */\nexport const DefaultLoadingPage: Component = () => <p>Loading...</p>;\n\nexport class Outlet {\n  state: RouteSegmentState = \"preloading\";\n  promise: Promise<unknown> | undefined;\n  data: unknown;\n  error: RouterError | undefined;\n\n  // Plain (non-observable) reference. The page component must reach\n  // React unmediated by MobX — once MobX deep-observes the holder,\n  // React Refresh can no longer swap the page identity via family\n  // lookup on the original function. This mirrors how Route holds\n  // `layout` as a plain field under makeObservable.\n  component: Component | undefined;\n\n  // Plain field for the same reason as `component`: it is read during\n  // render and never changes for the life of the outlet.\n  readonly level: RouteLevel | undefined;\n\n  // The pending and failed slots render without `children` on purpose:\n  // outlets in a chain resolve in parallel, so a descendant can already\n  // be \"ready\" while this slot waits or fails. Forwarding children would\n  // paint that descendant with incomplete (or missing) `route.data`.\n  get Component(): Component | undefined {\n    switch (this.state) {\n      case \"loading\": {\n        // render the nearest [LOADING] component in this outlet's slot\n        const LoadingComponent = this.config.loadingComponent ?? DefaultLoadingPage;\n        return ({ route, level }: Obj) => <LoadingComponent route={route} level={level} />;\n      }\n      case \"ready\":\n        return this.component ?? DefaultOutlet;\n      case \"error\": {\n        // render the nearest [ERROR] component in this outlet's slot,\n        // leaving the rest of the page intact\n        const ErrorComponent = this.config.errorComponent ?? DefaultErrorPage;\n        const error = this.error ?? new RouterError(\"LOAD\");\n        return ({ route, level }: Obj) => (\n          <ErrorComponent route={route} level={level} error={error} />\n        );\n      }\n      default:\n        return undefined;\n    }\n  }\n\n  constructor(readonly config: OutletConfig) {\n    if (!isLazyComponent(config.component)) {\n      this.component = config.component;\n    }\n    this.level = config.level;\n\n    makeAutoObservable<Outlet, \"component\" | \"config\" | \"level\">(this, {\n      promise: observable.ref,\n      data: observable.ref,\n      error: observable.ref,\n      component: false,\n      config: false,\n      level: false,\n    });\n  }\n\n  async load(route: Route, options?: LoadOptions): Promise<void> {\n    const promises: Promise<void>[] = [];\n\n    if (isLazyComponent(this.config.component) && !this.component) {\n      promises.push(this.loadComponent());\n    }\n\n    if (this.config.loader) {\n      promises.push(this.loadData(route));\n    }\n\n    if (!promises.length) {\n      this.setState(\"ready\");\n      return;\n    }\n\n    // wait to transition to loading to avoid\n    // screen flashes when the loader function\n    // executes quickly\n    const preloadingTimer = setTimeout(() => {\n      if (this.state === \"preloading\") {\n        this.setState(\"loading\");\n      }\n    }, LOADING_DELAY_MS);\n\n    this.promise = Promise.all(promises)\n      .then(() => {\n        clearTimeout(preloadingTimer);\n        if (options?.hold && this.state === \"loading\") {\n          // the [LOADING] component is on screen and the loader was slow\n          // enough to have shown it — keep it there briefly so it doesn't\n          // flash out the moment the data lands\n          setTimeout(() => {\n            this.setState(\"ready\");\n          }, LOADING_MIN_DURATION_MS);\n        } else {\n          this.setState(\"ready\");\n        }\n      })\n      .catch((e) => {\n        clearTimeout(preloadingTimer);\n        // a Redirect thrown by a loader is control flow, not a failure: it\n        // propagates so the router navigates. Leaving the slot in `loading`\n        // keeps the [LOADING] component on screen until the new route lands\n        // — marking it `error` here flashed the generic load-failure text,\n        // with no error recorded to explain it.\n        if (e instanceof Redirect) throw e;\n        this.setState(\"error\");\n        this.setError(e instanceof RouterError ? e : new RouterError(\"LOAD\", { cause: e }));\n      });\n\n    await this.promise;\n  }\n\n  setData(data: unknown) {\n    this.data = data;\n  }\n\n  setError(error: RouterError) {\n    this.error = error;\n  }\n\n  setState(state: RouteSegmentState) {\n    this.state = state;\n  }\n\n  private async loadData(route: Route): Promise<void> {\n    await this.config.loader?.(route).then((data) => this.setData(data));\n  }\n\n  private async loadComponent(): Promise<void> {\n    if (!isLazyComponent(this.config.component)) return;\n    const module = await this.config.component();\n    for (const exportName in module) {\n      if (exportName === \"default\" || exportName.endsWith(\"Page\")) {\n        this.component = module[exportName];\n        return;\n      }\n    }\n    throw new Error(\n      \"Lazy route component module did not export `default` or a `*Page` named export\",\n    );\n  }\n}\n","import { computed, makeObservable } from \"mobx\";\nimport { RouterError } from \"./errors\";\nimport type { LoadOptions, Outlet } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport type {\n  Component,\n  Guard,\n  GuardEntry,\n  MatchLevel,\n  Obj,\n  RouteContext,\n  RoutePath,\n} from \"./types\";\n\nexport interface RouteConfig {\n  path: string;\n  pattern?: RoutePath;\n  outlets: Outlet[];\n  guards: GuardEntry[];\n  levels: MatchLevel[];\n  context?: Obj;\n  layout?: Component;\n  params: Obj;\n  error?: RouterError;\n}\n\nexport class Route {\n  readonly path: string;\n  /**\n   * This route's pattern, e.g. `/org/:orgId/surveys` — `path` with its\n   * dynamic segments left unsubstituted. Ready to hand to `to=` or\n   * `router.navigate()` alongside `params`.\n   *\n   * Comparing patterns is how you ask \"which route is this\" without\n   * interpolating params into a path and matching strings. `RouteLevel.pattern`\n   * is the same idea per level; this is the whole route's.\n   *\n   * `undefined` only on a synthetic error route, which by definition has no\n   * matched pattern — nothing matched, or matching is what failed.\n   */\n  readonly pattern?: RoutePath;\n  readonly outlets: Outlet[];\n  readonly guards: Guard[];\n  readonly context: RouteContext;\n  readonly params: Obj;\n  readonly layout?: Component;\n  /** set on synthetic error routes; the error being rendered */\n  readonly error?: RouterError;\n  /** @internal */\n  readonly guardEntries: GuardEntry[];\n  /** @internal */\n  readonly levels: MatchLevel[];\n\n  get data(): Obj {\n    return Object.assign({}, ...this.outlets.map((o) => o.data));\n  }\n\n  /**\n   * `true` once a pending outlet has crossed the debounce threshold and\n   * its `[LOADING]` component is on screen. This is the signal to drive\n   * layout-level indicators (a top progress bar, a dimmed shell) — it\n   * stays `false` through the quiet window, so navigations that resolve\n   * quickly never flash an indicator.\n   */\n  get isLoading(): boolean {\n    return this.outlets.some((o) => o.state === \"loading\");\n  }\n\n  /**\n   * `true` whenever any outlet is still resolving, including the quiet\n   * window before `isLoading` flips. Use this to reason about whether\n   * navigation has settled (tests, effects) — not to render indicators.\n   */\n  get isPending(): boolean {\n    return this.outlets.some((o) => o.state === \"preloading\" || o.state === \"loading\");\n  }\n\n  constructor(def: RouteConfig) {\n    this.path = def.path;\n    this.pattern = def.pattern;\n    this.guardEntries = def.guards;\n    this.guards = def.guards.map((entry) => entry.guard);\n    this.levels = def.levels;\n    // The matcher assembles context by merging the `[CONTEXT]` objects down the matched chain, so\n    // what arrives here is a plain `Obj`. `MobxRouterContext` is the app's assertion about what\n    // those declarations add up to — a claim the library has no way to check — so this is the one\n    // place it is taken on trust.\n    this.context = (def.context ?? {}) as RouteContext;\n    this.outlets = def.outlets;\n    this.params = def.params;\n    this.layout = def.layout;\n    this.error = def.error;\n\n    makeObservable(this, {\n      data: computed,\n      isLoading: computed,\n      isPending: computed,\n    });\n  }\n\n  async guard(): Promise<void> {\n    for (const { guard, depth } of this.guardEntries) {\n      try {\n        await guard(this);\n      } catch (e) {\n        // depth rides along so a redirect that later fails to resolve\n        // bubbles to the same [ERROR] this guard's own failure would have\n        if (e instanceof Redirect) {\n          e.depth ??= depth;\n          throw e;\n        }\n        const error = e instanceof RouterError ? e : new RouterError(\"GUARD\", { cause: e });\n        error.depth ??= depth;\n        throw error;\n      }\n    }\n  }\n\n  async load(options?: LoadOptions): Promise<void> {\n    await Promise.all(this.outlets.map((outlet) => outlet.load(this, options)));\n  }\n}\n","import { DefaultErrorPage } from \"./components/error\";\nimport { redirectFailed, RouterError } from \"./errors\";\nimport { Outlet } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport { Route } from \"./route\";\nimport { CONTEXT, ERROR, GUARD, LAYOUT, LOAD, LOADING, PAGE, REDIRECT, WRAPPER } from \"./symbols\";\nimport type {\n  Component,\n  GuardEntry,\n  Leaf,\n  MatchLevel,\n  Obj,\n  RedirectOptions,\n  RedirectTarget,\n  RouteLevel,\n  RoutePath,\n  Routes,\n} from \"./types\";\nimport { isComponent, isLazyComponent, isLeaf, isPage, isRedirect, resolvePath } from \"./util\";\n\n// Declared locally rather than pulled from @types/node: this is a browser\n// build, and the reference exists only to be string-replaced by the consumer's\n// bundler. `declare` emits nothing, so the guard below still compiles down to\n// the literal comparison that dead-code elimination depends on.\ndeclare const process: { env: { NODE_ENV?: string } };\n\nconst pathToSegments = (path: string): string[] => {\n  return path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n};\n\nexport interface MatchState {\n  segments: string[];\n  patternSegments: string[];\n  context: Obj;\n  params: Obj;\n  outlets: (Outlet | undefined)[];\n  guards: GuardEntry[];\n  levels: MatchLevel[];\n  layout?: Component;\n  errorComponent?: Component;\n  loadingComponent?: Component;\n}\n\n/**\n * A level's pattern is the definition keys that led to it, dynamic segments\n * in their `:param` path spelling. No segments at all is the root, `/`.\n */\nconst toPattern = (patternSegments: string[]): RoutePath =>\n  `/${patternSegments.join(\"/\")}` as RoutePath;\n\n/** `$orgId` and `\":orgId\"` are the same segment; paths spell it `:orgId`. */\nconst toPatternSegment = (defKey: string): string =>\n  defKey.startsWith(\"$\") ? `:${defKey.slice(1)}` : defKey;\n\nconst isDynamicKey = (key: string): boolean => key.startsWith(\"$\") || key.startsWith(\":\");\n\n/**\n * A `_`-prefixed key is a **group**: its children are matched as if they were\n * siblings of the group's parent, while its `[WRAPPER]`, `[LOAD]`, `[GUARD]`,\n * `[CONTEXT]`, `[ERROR]` and `[LOADING]` apply only within it. The name after\n * the `_` is for humans.\n *\n * Two sigils, one rule each: `$param` contributes a dynamic segment, `_name`\n * contributes none. `_`-prefixed keys are reserved — they can never match a\n * literal URL segment.\n */\nconst isGroupKey = (key: string): boolean => key.startsWith(\"_\");\n\n/** @internal a resolved child, and the groups traversed to reach it */\ninterface Resolution {\n  def: Leaf | Routes;\n  defKey: string;\n  /** outermost first; each applies its config before the child is inspected */\n  groups: { key: string; def: Routes }[];\n}\n\n/**\n * Searches a node and then, in declaration order, its groups — recursively,\n * since groups may nest. `pick` chooses the candidate key at each node.\n */\nconst findChild = (\n  routeDef: Routes,\n  pick: (routeDef: Routes) => string | undefined,\n  groups: Resolution[\"groups\"] = [],\n): Resolution | undefined => {\n  const defKey = pick(routeDef);\n  const def = defKey === undefined ? undefined : routeDef[defKey];\n  if (defKey !== undefined && def !== undefined) return { def, defKey, groups };\n\n  for (const key of Object.keys(routeDef)) {\n    if (!isGroupKey(key)) continue;\n    const groupDef = routeDef[key];\n    // a group holding a leaf is rejected by makeRoutes; skip it rather than\n    // treating the leaf as a set of children\n    if (groupDef === undefined || isLeaf(groupDef)) continue;\n\n    const found = findChild(groupDef, pick, [...groups, { key, def: groupDef }]);\n    if (found) return found;\n  }\n\n  return undefined;\n};\n\n// `hasOwn` rather than a property read, so an inherited name (`constructor`,\n// `toString`) can't be mistaken for a route.\nconst pickKey = (key: string) => (routeDef: Routes) =>\n  Object.hasOwn(routeDef, key) ? key : undefined;\n\nconst pickDynamic = (routeDef: Routes): string | undefined =>\n  Object.keys(routeDef).find(isDynamicKey);\n\n/**\n * The child a URL segment addresses, looked up through groups.\n *\n * Precedence: the static key on the node, then static keys in its groups in\n * declaration order, then the dynamic (`$`/`:`) key on the node, then dynamic\n * keys in its groups. An `index` never falls back to a dynamic key — it\n * addresses the level itself.\n */\nconst resolveChild = (routeDef: Routes, key: string, isIndex: boolean): Resolution | undefined => {\n  // reserved: a group key is config, never a URL segment\n  if (!isIndex && isGroupKey(key)) return undefined;\n\n  const found = findChild(routeDef, pickKey(key));\n  return found ?? (isIndex ? undefined : findChild(routeDef, pickDynamic));\n};\n\n/** Whether this node addresses a page of its own, through groups included. */\nconst hasIndex = (routeDef: Routes): boolean => findChild(routeDef, pickKey(\"index\")) !== undefined;\n\nexport const makeRoute = (matchState: MatchState): Route => {\n  const outlets = matchState.outlets.filter((o) => o !== undefined);\n\n  return new Route({\n    ...matchState,\n    outlets,\n    path: matchState.segments.join(\"/\"),\n    pattern: toPattern(matchState.patternSegments),\n  });\n};\n\n/**\n * Builds the synthetic route rendered when navigation fails. Bubbles\n * from the failing level (`error.depth`, defaulting to the deepest\n * matched level) to the nearest `[ERROR]` component, preserving the\n * `[LAYOUT]` and `[WRAPPER]`s accumulated up to that level. Ancestor\n * `[LOAD]` loaders are intentionally not run — error routes never\n * fetch data.\n */\nexport const makeErrorRoute = (\n  error: RouterError,\n  pathname: string,\n  source?: { levels: MatchLevel[]; params: Obj; context: Obj },\n): Route => {\n  const levels = error.state?.levels ?? source?.levels ?? [];\n  const depth = Math.min(error.depth ?? levels.length - 1, levels.length - 1);\n  const matched = depth >= 0 ? levels[depth] : undefined;\n\n  const ErrorComponent = matched?.errorComponent ?? DefaultErrorPage;\n  const outlets = levels\n    .slice(0, depth + 1)\n    .flatMap((l) => (l.wrapper ? [new Outlet({ component: l.wrapper, level: l.level })] : []));\n  // no children — `[ERROR]` components never receive them, on the\n  // synthetic-route path or the in-slot one. `level` is whatever level\n  // failed; absent when nothing matched at all.\n  outlets.push(\n    new Outlet({\n      component: ({ route, level }: Obj) => (\n        <ErrorComponent route={route} level={level} error={error} />\n      ),\n      level: matched?.level,\n    }),\n  );\n\n  return new Route({\n    path: pathname.replace(/^\\/+/, \"\"),\n    outlets,\n    guards: [],\n    levels: [],\n    params: error.state?.params ?? source?.params ?? {},\n    context: error.state?.context ?? source?.context ?? {},\n    layout: matched?.layout,\n    error,\n  });\n};\n\n/** A bare path is the one-field spelling of the options object. */\nconst toRedirectOptions = (target: string | RedirectOptions): RedirectOptions =>\n  typeof target === \"string\" ? { to: target } : target;\n\n/**\n * Resolves a `[REDIRECT]` to the navigation it names.\n *\n * The function form is called with the route the redirect matched — the\n * whole point being that a redirect to a dynamic path can read\n * `route.params` itself. It may return either spelling: a path it has\n * already substituted, or options for the router to substitute. A throw from\n * it fails the navigation as a redirect rather than as a generic render\n * error, and carries the matched prefix along so the nearest `[ERROR]`\n * renders inside its layout and wrappers.\n */\nconst makeRedirect = (target: RedirectTarget, state: MatchState): Redirect => {\n  let options: RedirectOptions;\n\n  if (typeof target === \"function\") {\n    try {\n      options = toRedirectOptions(target(makeRoute(state)));\n    } catch (cause) {\n      throw redirectFailed(cause, `/${state.segments.join(\"/\")}`, { state });\n    }\n  } else {\n    options = toRedirectOptions(target);\n  }\n\n  const redirect = new Redirect(options as any);\n  redirect.state = state;\n  return redirect;\n};\n\nconst notFound = (state: MatchState, attemptedSegments: string[]): RouterError => {\n  const error = new RouterError(\"NOT_FOUND\", {\n    path: `/${attemptedSegments.filter((s) => s !== \"\").join(\"/\")}`,\n  });\n  error.state = state;\n  return error;\n};\n\n/**\n * Folds one definition node's config into the match state: `[LAYOUT]`,\n * `[ERROR]` and `[LOADING]` inheritance, the `[CONTEXT]` merge, the `[GUARD]`\n * push, the `[WRAPPER]`/`[LOAD]` outlets, and the level entry they render at.\n *\n * Groups go through this unchanged — it is what gives a group its own wrapper,\n * loader and error boundary. They differ only in the `level` handed in and in\n * contributing no segment.\n */\nconst applyLevel = (routeDef: Routes, level: RouteLevel, matchState?: MatchState): MatchState => {\n  const layout = routeDef[LAYOUT] ?? matchState?.layout;\n  const errorComponent = routeDef[ERROR] ?? matchState?.errorComponent;\n  const loadingComponent = routeDef[LOADING] ?? matchState?.loadingComponent;\n\n  return {\n    segments: [],\n    patternSegments: [],\n    params: {},\n    ...matchState,\n    layout,\n    errorComponent,\n    loadingComponent,\n    context: { ...matchState?.context, ...routeDef[CONTEXT] },\n    guards: [\n      ...(matchState?.guards ?? []),\n      ...(routeDef[GUARD] ? [{ guard: routeDef[GUARD], depth: level.index }] : []),\n    ],\n    outlets: [\n      ...(matchState?.outlets ?? []),\n      routeDef[WRAPPER]\n        ? new Outlet({ component: routeDef[WRAPPER], errorComponent, loadingComponent, level })\n        : undefined,\n      routeDef[LOAD]\n        ? new Outlet({ loader: routeDef[LOAD], errorComponent, loadingComponent, level })\n        : undefined,\n    ],\n    levels: [\n      ...(matchState?.levels ?? []),\n      { level, wrapper: routeDef[WRAPPER], layout, errorComponent },\n    ],\n  };\n};\n\nexport const matchRoute = (path: string, routeDef: Routes, matchState?: MatchState): Route => {\n  const patternSegments = matchState?.patternSegments ?? [];\n\n  // This level's own address. Only navigable when it has an `index` child —\n  // reachable through its groups, which contribute no segment — since a\n  // nesting level without one has no page of its own, and handing out a\n  // pattern for it would produce a path that 404s on navigation.\n  const level: RouteLevel = {\n    index: matchState?.levels.length ?? 0,\n    segment: patternSegments.at(-1) ?? \"\",\n    pattern: hasIndex(routeDef) ? toPattern(patternSegments) : undefined,\n  };\n\n  const [segment, ...remainingSegments] = pathToSegments(path);\n  const remainingPath = remainingSegments.join(\"/\");\n\n  // an empty segment addresses this level itself, which is what `index`\n  // names — so it consumes no segment of the path or the pattern\n  const isIndex = !segment;\n  const resolved = resolveChild(routeDef, isIndex ? \"index\" : segment, isIndex);\n\n  let state = applyLevel(routeDef, level, matchState);\n\n  if (!resolved) {\n    throw notFound(state, [...state.segments, segment ?? \"\", ...remainingSegments]);\n  }\n\n  // Each group traversed to reach the child applies its config at a level of\n  // its own. No segment, so its pattern is the parent's — and because this\n  // runs before the child is inspected, the group's [ERROR] and [LOADING]\n  // reach the child through `state`.\n  for (const group of resolved.groups) {\n    state = applyLevel(\n      group.def,\n      {\n        index: state.levels.length,\n        segment: group.key,\n        pattern: hasIndex(group.def) ? toPattern(state.patternSegments) : undefined,\n      },\n      state,\n    );\n  }\n\n  const { def: defAtSegment, defKey } = resolved;\n  const errorComponent = state.errorComponent;\n  const loadingComponent = state.loadingComponent;\n\n  if (isDynamicKey(defKey)) {\n    state.params[defKey.slice(1)] = segment;\n  }\n\n  if (!isIndex) {\n    state.segments.push(segment);\n    state.patternSegments.push(toPatternSegment(defKey));\n  }\n\n  // the level a leaf or [PAGE] renders at — one below the nesting level\n  // that contains it, and always navigable: it *is* a page\n  const leafLevel: RouteLevel = {\n    index: state.levels.length,\n    segment: isIndex ? \"index\" : toPatternSegment(defKey),\n    pattern: toPattern(state.patternSegments),\n  };\n\n  if (isLeaf(defAtSegment)) {\n    if (remainingPath) {\n      throw notFound(state, [...state.segments, ...remainingSegments]);\n    }\n\n    if (isRedirect(defAtSegment)) {\n      throw makeRedirect(defAtSegment[REDIRECT], state);\n    }\n\n    if (isComponent(defAtSegment) || isLazyComponent(defAtSegment)) {\n      state.outlets.push(\n        new Outlet({ component: defAtSegment, errorComponent, loadingComponent, level: leafLevel }),\n      );\n      return makeRoute(state);\n    }\n  }\n\n  // at this point we have a nested route or a [Page] definition\n\n  if (isPage(defAtSegment)) {\n    state.layout = defAtSegment[LAYOUT] ?? state.layout;\n    state.errorComponent = defAtSegment[ERROR] ?? state.errorComponent;\n    state.loadingComponent = defAtSegment[LOADING] ?? state.loadingComponent;\n    Object.assign(state.context, defAtSegment[CONTEXT]);\n    // the level a [PAGE] refines is the innermost one reached — the containing\n    // group's when it sits inside one, which is what keeps its [GUARD]'s depth\n    // and its [ERROR] on the same level\n    const pageDepth = state.levels.length - 1;\n    if (defAtSegment[GUARD]) {\n      state.guards.push({ guard: defAtSegment[GUARD], depth: pageDepth });\n    }\n    state.outlets.push(\n      new Outlet({\n        component: defAtSegment[PAGE],\n        loader: defAtSegment[LOAD],\n        errorComponent: state.errorComponent,\n        loadingComponent: state.loadingComponent,\n        level: leafLevel,\n      }),\n    );\n    // a [PAGE] refines the level it sits in rather than adding one of its\n    // own — that is what makes a page's [ERROR] catch its own [GUARD],\n    // which resolves through `levels[depth]`\n    const pageLevel = state.levels[pageDepth];\n    if (pageLevel) {\n      state.levels[pageDepth] = {\n        ...pageLevel,\n        layout: state.layout,\n        errorComponent: state.errorComponent,\n      };\n    }\n\n    return makeRoute(state);\n  }\n\n  // now we know we have a nested route\n  return matchRoute(remainingPath, defAtSegment, state);\n};\n\n/** @internal a leaf together with the path it answers to */\ninterface Addressable {\n  /** this leaf's own pattern, e.g. `/org/:orgId/overview` */\n  pattern: string;\n  /** dotted route-key trail, so validation errors can name the culprit */\n  at: string;\n  def: Leaf;\n}\n\n/**\n * Every path the tree can address, in `:param` pattern spelling. Mirrors how\n * `matchRoute` walks it: an `index` key addresses its parent's path and adds\n * no segment, a group adds none either, a leaf adds its own, and a nesting\n * level without an `index` is not addressable at all — so it is correctly\n * absent here.\n */\nconst collectAddressable = (\n  routeDef: Routes,\n  prefix: string[] = [],\n  trail: string[] = [],\n  out: Addressable[] = [],\n): Addressable[] => {\n  for (const key of Object.keys(routeDef)) {\n    const def = routeDef[key];\n    if (def === undefined) continue;\n    const keys = [...trail, key];\n\n    if (isGroupKey(key)) {\n      if (isLeaf(def)) {\n        throw new Error(\n          `Route group '${keys.join(\".\")}' holds a leaf. A group exists to apply ` +\n            \"config to its children and contributes no segment of its own, so a \" +\n            \"leaf there addresses nothing. Drop the `_` prefix to make it a route.\",\n        );\n      }\n      collectAddressable(def, prefix, keys, out);\n      continue;\n    }\n\n    const segments = key === \"index\" ? prefix : [...prefix, toPatternSegment(key)];\n    if (isLeaf(def)) {\n      out.push({ pattern: `/${segments.join(\"/\")}`, at: keys.join(\".\"), def });\n    } else {\n      collectAddressable(def, segments, keys, out);\n    }\n  }\n  return out;\n};\n\n/** Whether `path` addresses `pattern`, a `:param` segment matching anything. */\nconst matchesPattern = (path: string, pattern: string): boolean => {\n  const pathSegments = path.split(\"/\");\n  const patternSegments = pattern.split(\"/\");\n\n  return (\n    pathSegments.length === patternSegments.length &&\n    patternSegments.every((segment, i) =>\n      segment.startsWith(\":\") ? !!pathSegments[i] : segment === pathSegments[i],\n    )\n  );\n};\n\n/** The first `:param` in `to` that `params` has no value for. */\nconst unresolvedParam = (to: string, params?: Obj<string>): string | undefined =>\n  to.split(\"/\").find((segment) => segment.startsWith(\":\") && !params?.[segment.slice(1)]);\n\n/**\n * The leaf a concrete path lands on. Exact patterns win over dynamic ones, the\n * way `matchRoute` prefers a literal key over the level's `$param` key.\n */\nconst findAddressable = (path: string, entries: Addressable[]): Addressable | undefined =>\n  entries.find((entry) => entry.pattern === path) ??\n  entries.find((entry) => matchesPattern(path, entry.pattern));\n\n/**\n * Follows a redirect's static targets and returns the cycle it falls into, if\n * any — `[\"/a\", \"/b\", \"/a\"]` for a two-hop loop.\n *\n * Revisiting a pattern is always a real loop: a static target is the same\n * every time that leaf is matched, so a second visit resolves identically and\n * would keep doing so. A function target ends the walk instead of being\n * guessed at — where it goes depends on the route it matched.\n */\nconst findRedirectLoop = (start: Addressable, entries: Addressable[]): string[] | undefined => {\n  const chain: string[] = [];\n  let current: Addressable | undefined = start;\n\n  while (current && isRedirect(current.def)) {\n    const seen = chain.indexOf(current.pattern);\n    if (seen !== -1) return [...chain.slice(seen), current.pattern];\n    chain.push(current.pattern);\n\n    const target = current.def[REDIRECT];\n    if (typeof target === \"function\") return undefined;\n\n    const { to, params } = toRedirectOptions(target);\n    // an unresolvable or unaddressable target is reported on its own entry\n    if (unresolvedParam(to, params)) return undefined;\n    current = findAddressable(resolvePath(to, params), entries);\n  }\n\n  return undefined;\n};\n\n/**\n * Rejects two definitions answering the same path — which is what makes a\n * group's transparency safe. Because a group's children are matched as\n * siblings of its parent, a key present both on the parent and inside one of\n * its groups silently shadows: `matchRoute` takes the first by precedence and\n * the other is dead. Falls out of the collected patterns, so it also catches\n * two groups defining the same child, and colliding `index` keys.\n */\nconst validateCollisions = (entries: Addressable[]): void => {\n  const seen = new Map<string, string>();\n\n  for (const entry of entries) {\n    const first = seen.get(entry.pattern);\n    if (first !== undefined) {\n      throw new Error(\n        `'${first}' and '${entry.at}' both address '${entry.pattern}'. ` +\n          \"A route group's children are matched as siblings of its parent, so \" +\n          \"only one of them is ever reached.\",\n      );\n    }\n    seen.set(entry.pattern, entry.at);\n  }\n};\n\n/**\n * Rejects a `[REDIRECT]` that can never work: a target no route addresses, a\n * `:param` with nothing to fill it, or a chain that loops instead of landing.\n * Runs when the route tree is defined, so it throws on first import —\n * deterministic, and therefore impossible to ship past a single dev or CI run.\n * Without it these surface late and quietly: a mistyped target is a valid path\n * string, so the redirect happens and the *next* navigation 404s, one step\n * removed from the actual mistake.\n *\n * Function targets are skipped. What they return depends on the route they\n * matched, which does not exist yet.\n */\nconst validateRedirects = (entries: Addressable[]): void => {\n  for (const entry of entries) {\n    if (!isRedirect(entry.def)) continue;\n\n    const target = entry.def[REDIRECT];\n    if (typeof target === \"function\") continue;\n\n    const { to, params } = toRedirectOptions(target);\n    const unresolved = unresolvedParam(to, params);\n    if (unresolved) {\n      throw new Error(\n        `[REDIRECT] at '${entry.at}' targets '${to}', but '${unresolved}' has no value. ` +\n          \"Supply it in `params`, or use the function form to read it off the \" +\n          \"matched route: [REDIRECT]: (route) => ...\",\n      );\n    }\n\n    if (!findAddressable(resolvePath(to, params), entries)) {\n      throw new Error(\n        `[REDIRECT] at '${entry.at}' targets '${to}', which no route in this tree addresses.`,\n      );\n    }\n\n    const loop = findRedirectLoop(entry, entries);\n    if (loop) {\n      throw new Error(`[REDIRECT] at '${entry.at}' never lands — it loops: ${loop.join(\" → \")}.`);\n    }\n  }\n};\n\n// TODO: ideally this could resolve to something less than R,\n// but specific enough to infer all paths as a literal union.\n// As it stands, there are certain things we can't access reliably\n// without the compiler complaining about circular references\n// try \"as const satisfies\" approach which would allow us to\n// exchange a less specific version of MobxRoutesRoot for this\n//\n// The concrete rule that falls out of `R extends Routes`: **nothing\n// reachable from `Routes` may reference `RoutePath`** (or `StaticRoutePath`,\n// or anything else derived from `MobxRouter[\"routes\"]`). `RoutePath` comes\n// from the object being inferred here, so naming it inside the constraint\n// makes `typeof routes` depend on itself — TS7022, and the whole tree types\n// as `any` in any app that augments `MobxRouter`. Route *values* may of\n// course be typed against paths at their own call sites; the route\n// definition types may not. router.types.test.ts guards this.\nexport const makeRoutes =\n  () =>\n  <R extends Routes>(routes: R): R => {\n    // Development only. Every check here is deterministic — it depends on the\n    // route tree and nothing else — so anything it would catch has already\n    // thrown on the first dev or CI run. Production has nothing left to learn\n    // from it, and this way a consumer's bundler drops the whole validation\n    // half of this module: `collectAddressable` and everything it reaches are\n    // referenced from nowhere else.\n    //\n    // `process.env.NODE_ENV` is the form mobx uses, so a consumer already has\n    // it defined by necessity. Keep the comparison inline and literal — a\n    // hoisted `const isDev` would defeat the dead-code elimination.\n    if (process.env.NODE_ENV !== \"production\") {\n      const entries = collectAddressable(routes);\n      validateCollisions(entries);\n      validateRedirects(entries);\n    }\n\n    // todo: perform the rest of the validation here\n    // - no forward slashes in keys\n    // - at most one variable segment per level\n    // - only lowercase letters (except variables)\n    // - paths/variables cannot contain $ or : that aren't at the beginning\n    // - path variables must be unique across a path\n    return routes;\n  };\n","import {\n  Action,\n  createBrowserHistory,\n  type History,\n  type Location,\n  type Transition,\n} from \"history\";\nimport { action, computed, makeObservable, observable, reaction, runInAction, when } from \"mobx\";\nimport { flushSync } from \"react-dom\";\nimport { redirectFailed, RouterError } from \"./errors\";\nimport { makeErrorRoute, matchRoute } from \"./make-routes\";\nimport { LOADING_DELAY_MS } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport type { Route } from \"./route\";\nimport type {\n  BlockedNavigation,\n  Component,\n  MobxRouterConfig,\n  NavigateOptions,\n  NavigationBlocker,\n  Obj,\n  RoutePath,\n  RouteTarget,\n  Routes,\n} from \"./types\";\nimport { resolvePath } from \"./util\";\n\n/**\n * How many redirects one navigation may chain through before the router\n * calls it a loop. Every hop is a full match-and-guard cycle, so this is\n * also how long a looping app spins before it says so — kept well above any\n * plausible real chain (one or two hops) and well below \"the tab is stuck\".\n */\nconst MAX_REDIRECTS = 10;\n\n/** @internal one `block()` registration: when it applies, and what it decides. */\ninterface BlockerEntry {\n  when: () => boolean;\n  blocker: NavigationBlocker;\n}\n\nexport interface MobxRenderSegment {\n  segment: string;\n  component: Component;\n  props?: Obj;\n}\n\n/** Narrows a freshly matched route to the value `target` publishes. */\nconst toTarget = (route: Route, pathname: string): RouteTarget => ({\n  pathname,\n  pattern: route.pattern,\n  params: { ...route.params },\n  levels: route.levels.map((level) => level.level),\n});\n\n/**\n * Whether `path` addresses `segments`, a `:param` in `path` matching any\n * value. Shared by `doesPathMatch` and `doesTargetMatch` so the two can only\n * differ in which clock they read.\n */\nconst matchesSegments = (path: string, segments: string[], exact?: boolean): boolean => {\n  const parts = path.slice(1).split(\"/\");\n\n  return (\n    parts.every((part, i) => part === segments[i] || part.startsWith(\":\")) &&\n    segments.length >= parts.length &&\n    (!exact || parts.length === segments.length)\n  );\n};\n\nexport class RouterStore {\n  readonly history: History;\n  readonly viewTransitions: boolean;\n\n  routesDef?: Routes;\n\n  /**\n   * The current URL. Updates the **instant** a navigation starts, before\n   * guards and loaders run.\n   *\n   * `activeRoute` — and so `pathParams`, `activeSegments` and\n   * `doesPathMatch` — commits only once the navigation lands. The two\n   * therefore disagree for the whole duration of a navigation, and combining\n   * them silently mixes clocks: interpolating `pathParams` (old) into a test\n   * against `location.pathname` (new) is wrong for exactly as long as the\n   * navigation takes. Use {@link target} for a matched view of the\n   * destination that is available immediately.\n   */\n  location!: Location;\n\n  /**\n   * The route on screen. Commits after guards **and** loaders resolve, so it\n   * lags `location` for the duration of a navigation — see the note there.\n   */\n  activeRoute: Route | undefined;\n\n  /**\n   * The route being matched, guarded and loaded. Set for the duration of\n   * a navigation and cleared when it lands. `activeRoute` keeps rendering\n   * the previous page while this is set, so navigation never blanks the\n   * screen — see {@link isNavigating}.\n   *\n   * Assigned only once guards have resolved, because it gates rendering. For\n   * the destination as soon as it is *known*, use {@link target}.\n   */\n  pendingRoute: Route | undefined;\n\n  /** Backs {@link target}; written at match time, never cleared. */\n  private matchedTarget: RouteTarget | undefined;\n\n  /**\n   * Navigation-scoped state, tracked from the first line of a navigation\n   * rather than derived from `pendingRoute`, so both span the guard phase.\n   * See `beginNavigation`.\n   */\n  private navigating = false;\n  private navigationSlow = false;\n  private slowTimer: ReturnType<typeof setTimeout> | undefined;\n\n  /**\n   * Redirect hops taken since the last navigation landed. Reset on landing,\n   * so it measures one chain rather than session history.\n   */\n  private redirects = 0;\n\n  /**\n   * Registered navigation blockers, in registration order (a `Set` iterates\n   * by insertion). See {@link block}.\n   */\n  private readonly blockers = new Set<BlockerEntry>();\n\n  /**\n   * State of the single `history.block` blocker that covers pops — its\n   * disposer while armed, the one-shot listener that re-arms it after a\n   * transition has been let through, and whether a handler is currently\n   * deciding about one. See {@link syncHistoryBlocker}.\n   */\n  private unblockHistory: (() => void) | undefined;\n  private stopRearm: (() => void) | undefined;\n  private deciding = false;\n\n  get search(): URLSearchParams {\n    return new URLSearchParams(this.location?.search);\n  }\n\n  get query(): Record<string, string> {\n    return Object.fromEntries(this.search);\n  }\n\n  get pathParams(): Record<string, string> {\n    return { ...this.activeRoute?.params };\n  }\n\n  get activeSegments(): string[] {\n    return this.activeRoute?.path.split(\"/\") ?? [];\n  }\n\n  /**\n   * Where navigation is headed, as soon as the matcher knows — before guards\n   * and loaders, and so well before `activeRoute` swaps. When nothing is in\n   * flight this is the active route, so consumers never branch on navigation\n   * state: `target.pattern` answers \"which route is, or is about to be,\n   * on screen\".\n   *\n   * Compare `pattern`s rather than interpolating params into a path — that\n   * is the comparison that mixes the `location` and `activeRoute` clocks.\n   *\n   * ```tsx\n   * const active = tabs.find((tab) => tab.to === router.target?.pattern);\n   * ```\n   *\n   * Holds its previous value when a URL produces no match, rather than\n   * blanking: a `[REDIRECT]` leaf throws instead of matching, and clearing\n   * would flicker for exactly the one hop before the redirect's own match\n   * lands. The same applies to a `NOT_FOUND` or a rejected guard — the error\n   * route commits through `activeRoute`, and `target` keeps naming the last\n   * route that matched. So this is not \"the route on screen\": after a failed\n   * navigation the two differ until the next successful match.\n   *\n   * `undefined` only before the first successful match of the session.\n   */\n  get target(): RouteTarget | undefined {\n    return this.matchedTarget;\n  }\n\n  private get targetSegments(): string[] {\n    const pathname = this.target?.pathname;\n    return pathname === undefined ? [] : pathname.replace(/^\\//, \"\").split(\"/\");\n  }\n\n  /**\n   * `true` from the first moment of a navigation until it lands, guard\n   * phase included — the honest answer to \"is something in flight\".\n   *\n   * Undebounced: it flips for every navigation however fast, so an\n   * indicator rendered straight off it will flicker. Use it for logic, and\n   * {@link isSlowNavigation} or {@link isLoading} for pixels. For the\n   * narrower question \"is a route currently loading\", check `pendingRoute`,\n   * which is only assigned once guards have resolved.\n   */\n  get isNavigating(): boolean {\n    return this.navigating;\n  }\n\n  /**\n   * `true` whenever a loading indicator is warranted *anywhere*: a\n   * navigation has been in flight longer than `LOADING_DELAY_MS` (guards\n   * included), or a cold load's `[LOADING]` component is on screen\n   * (including through the minimum-duration hold). Debounced, so quick\n   * navigations never flip it.\n   *\n   * Use this for a layout progress bar that should stay visible alongside\n   * a cold load's `[LOADING]` skeleton. For a bar that yields to the\n   * skeleton instead, use {@link isSlowNavigation}.\n   */\n  get isLoading(): boolean {\n    // navigationSlow covers the whole in-flight window; activeRoute's own\n    // flag covers the cold-load hold, which outlives the navigation itself\n    return this.navigationSlow || !!this.pendingRoute?.isLoading || !!this.activeRoute?.isLoading;\n  }\n\n  /**\n   * `true` when a navigation has been slow enough to be worth showing\n   * *and* there is already a page on screen to show it over — the usual\n   * signal for a layout-level progress bar.\n   *\n   * Measured from the start of the navigation, so a slow `[GUARD]` counts\n   * toward it just as a slow `[LOAD]` does, and a navigation made slow by\n   * both phases together still trips it.\n   *\n   * Excludes the cold load, where the pending route's `[LOADING]`\n   * component is on screen instead, so a bar driven off this is mutually\n   * exclusive with `[LOADING]`. Use {@link isLoading} if you want both at\n   * once.\n   */\n  get isSlowNavigation(): boolean {\n    return this.navigationSlow && this.activeRoute !== undefined;\n  }\n\n  constructor(config?: MobxRouterConfig) {\n    makeObservable<\n      RouterStore,\n      \"navigating\" | \"navigationSlow\" | \"matchedTarget\" | \"targetSegments\"\n    >(this, {\n      location: observable.ref,\n      activeRoute: observable.ref,\n      pendingRoute: observable.ref,\n      matchedTarget: observable.ref,\n      navigating: observable,\n      navigationSlow: observable,\n\n      search: computed,\n      pathParams: computed,\n      activeSegments: computed,\n      target: computed,\n      targetSegments: computed,\n      isNavigating: computed,\n      isLoading: computed,\n      isSlowNavigation: computed,\n\n      setLocation: action,\n    });\n\n    this.history = config?.history ?? createBrowserHistory();\n    this.viewTransitions = config?.viewTransitions ?? true;\n  }\n\n  /**\n   * Wires the router to its history and starts the first navigation,\n   * resolving when that navigation lands — the same guarantee\n   * {@link navigate} gives, including any redirect the initial URL runs\n   * through. Await it to hand off from a boot screen, or to hold a test\n   * until there is a route to assert on; ignore it to let `[SPLASH]` and\n   * `[LOADING]` cover the wait, which is the usual case.\n   */\n  initialize(routesDef: Routes): Promise<void> {\n    this.routesDef = routesDef;\n    this.history.listen((data) => {\n      void this.setLocation(data.location);\n    });\n\n    void this.setLocation(this.history.location);\n\n    // `setLocation` has already claimed the navigation clock synchronously\n    // — it only awaits once matching is done — so there is no window here\n    // in which `settled()` could see an idle router and resolve early.\n    return this.settled();\n  }\n\n  /**\n   * Whether `path` matches the route **on screen**. Lags a navigation in\n   * flight, because it reads `activeSegments`; use {@link doesTargetMatch} for\n   * the destination. A `:param` segment in `path` matches any value.\n   */\n  doesPathMatch<P extends RoutePath>(path: P, exact?: boolean): boolean {\n    return matchesSegments(path, this.activeSegments, exact);\n  }\n\n  /**\n   * {@link doesPathMatch} against {@link target} instead of the active route,\n   * so it answers for the destination the moment a navigation starts.\n   *\n   * A separate method rather than an option on `doesPathMatch`: which clock a\n   * call site means is worth stating at the call site.\n   */\n  doesTargetMatch<P extends RoutePath>(path: P, exact?: boolean): boolean {\n    return matchesSegments(path, this.targetSegments, exact);\n  }\n\n  /**\n   * Navigates to `options`, resolving `true` once the navigation has\n   * **landed** — or `false` as soon as a {@link block}er declines it.\n   *\n   * Landing is the end of the whole chain, not this hop: guards, loaders,\n   * any redirect they throw, and the `activeRoute` swap (view transition\n   * included). Await it to run a side effect against the page that actually\n   * ended up on screen.\n   *\n   * ```ts\n   * await router.navigate({ to: \"/orders/:id\", params: { id } });\n   * announce(`Now viewing ${router.target?.pathname}`);\n   * ```\n   *\n   * Resolves rather than rejects when a navigation fails. A rejected guard,\n   * a `NOT_FOUND` or a throwing loader commits the `[ERROR]` route, which is\n   * a landing like any other — the caller's \"after navigation\" work usually\n   * still wants to run. Read `activeRoute.error`, or compare `target.pattern`\n   * against where you meant to go, when the distinction matters. A\n   * navigation skipped as redundant (already at that URL, no `state`)\n   * resolves immediately, and counts as landing.\n   *\n   * `false` means only that *this* call did not navigate. A blocker that\n   * saves and then lets the user leave is expected to return `true` and land\n   * normally; `false` is the \"stay here\" answer. See {@link block}.\n   *\n   * An unresolvable `to` — a `:param` left unfilled — still throws\n   * *synchronously*, because that is a caller bug rather than a navigation\n   * outcome, and because the redirect path below depends on catching it.\n   *\n   * A redirect loop resolves too. Guards that redirect to each other would\n   * otherwise chain forever and leave this promise pending for the life of\n   * the page — see {@link redirectLoop}, which cuts the chain and lands an\n   * `[ERROR]` route instead. A guard that calls `navigate()` in a cycle\n   * rather than throwing `redirect()` is *not* bounded: that is the app\n   * driving navigation through the same public API a link click uses, and\n   * the router cannot tell the two apart.\n   *\n   * What is awaited is \"nothing is in flight\" rather than this call\n   * specifically, so a navigation superseded by another resolves when *that*\n   * one lands. That is the only useful answer: once a redirect has replaced\n   * the destination there is no separate completion for the original hop,\n   * and a caller awaiting navigation wants the view it ends on.\n   *\n   * The router's state is committed when this resolves. React has re-rendered\n   * too wherever a view transition ran, since the swap is flushed inside it;\n   * without one the re-render is left on React's scheduler, so a test reading\n   * the DOM still needs its usual `act` / `waitFor`.\n   */\n  navigate<P extends RoutePath>(options: NavigateOptions<P>): Promise<boolean> {\n    // resolved up front so an unresolvable `to` still throws synchronously\n    // even with a blocker registered — deferring it past the handler's\n    // `await` would turn a caller bug into a rejected promise\n    const { pathname, search } = this.resolveLocation(options);\n\n    const blockers = this.activeBlockers(pathname);\n    if (!blockers.length) {\n      return this.navigateNow(options);\n    }\n\n    return this.consultBlockers(blockers, {\n      action: options.replace ? \"REPLACE\" : \"PUSH\",\n      pathname,\n      search: search ?? \"\",\n      href: `${pathname}${search ?? \"\"}`,\n    }).then((allowed) => (allowed ? this.navigateNow(options) : false));\n  }\n\n  /**\n   * {@link navigate} without consulting blockers — the navigation the router\n   * itself performs rather than one the user asked for.\n   *\n   * That is the `redirect()` path: a `[REDIRECT]` leaf or a redirect thrown\n   * by a guard is the app's own decision about where a URL leads, not the\n   * user leaving a page, so prompting for it would ask about a destination\n   * the user never chose.\n   *\n   * Deliberately not `async`: `_navigate` throws synchronously for an\n   * unresolvable path, and the redirect handler in `setLocation` catches it\n   * with a plain `try`/`catch`. An async method would turn that throw into\n   * a rejection and the [ERROR] route would never render.\n   */\n  private navigateNow<P extends RoutePath>(options: NavigateOptions<P>): Promise<boolean> {\n    // navigating to the current URL attaches no new information — skip\n    // the navigation (and its view transition) entirely so redundant\n    // navigations (e.g. clicking an already-active link) cause no churn\n    if (!options.state && this.isCurrentLocation(options)) {\n      return Promise.resolve(true);\n    }\n\n    // the view transition is started around the route swap in\n    // `applyRoute`, not here — see the note there\n    this._navigate(options);\n\n    return this.settled().then(() => true);\n  }\n\n  /**\n   * Resolves once no navigation is in flight.\n   *\n   * Reads the same flag `isNavigating` publishes, which spans a redirect\n   * chain unbroken: the follow-up navigation starts inside the previous\n   * one's `catch`, before its `finally` runs, so `beginNavigation` hands the\n   * clock straight over and the flag never dips between hops. The same holds\n   * for a guard that calls `navigate()` itself, and for the trailing-slash\n   * normalization in `setLocation`. That is what makes awaiting a navigation\n   * mean the destination rather than the first redirect.\n   */\n  private async settled(): Promise<void> {\n    await when(() => !this.navigating);\n  }\n\n  _navigate<P extends RoutePath>(options: NavigateOptions<P>): void {\n    const location = this.resolveLocation(options);\n\n    if (options.replace) {\n      this.history.replace(location, options.state);\n    } else {\n      this.history.push(location, options.state);\n    }\n  }\n\n  /**\n   * Registers a navigation blocker: `when` says whether the block is live,\n   * and `blocker` decides what to do about a navigation while it is.\n   * Returns the disposer.\n   *\n   * ```ts\n   * const dispose = router.block(\n   *   () => designer.dirty,\n   *   async () => {\n   *     const choice = await confirmLeave(); // the app's own dialog\n   *     if (choice === \"save\") await designer.save();\n   *     return choice !== \"stay\";\n   *   },\n   * );\n   * ```\n   *\n   * {@link useNavigationBlock} is this with the lifetime tied to a\n   * component, which is the usual way to reach it.\n   *\n   * Only `true` proceeds — see {@link NavigationBlocker}. The handler may be\n   * async, and `navigate()` stays pending until it settles, so a blocker\n   * that saves before allowing the navigation still resolves the caller's\n   * `await router.navigate(...)` once the destination lands.\n   *\n   * Covers every navigation that goes through {@link navigate} — `<Link>`\n   * clicks, programmatic navigation, `search`-only navigations to another\n   * path — the back and forward buttons, and closing or reloading the tab.\n   *\n   * **`when` must be derived from observables.** It is read at the moment a\n   * navigation is proposed, but it also *drives registration*: the pop and\n   * `beforeunload` halves of this depend on a `history.block` blocker being\n   * armed exactly while the predicate holds, and that is kept in step by a\n   * MobX reaction. A predicate reading something MobX cannot see — a ref, a\n   * DOM query, a plain field — still blocks in-app navigation correctly, and\n   * silently stops covering the back button.\n   *\n   * Does **not** cover:\n   * - **The `redirect()` path.** See {@link navigateNow}.\n   * - **A change that keeps the same pathname** — a query param, a history\n   *   state update, or navigating to the current URL. The route on screen\n   *   does not change, so there is nothing to leave; this is the same rule\n   *   `setLocation` applies when it declines to re-match, and it is what\n   *   keeps `setQueryParam` working while a block is live.\n   * - **Writes straight to `router.history`.** A push there is let through\n   *   rather than prompted about — see {@link onTransition}.\n   *\n   * There is no \"navigate anyway\" option, because the predicate is one: a\n   * \"discard and leave\" action resets what it guards and then navigates, by\n   * which point `when` is false.\n   *\n   * Registering more than one blocker is allowed. They are consulted in\n   * registration order and the first to decline ends it, so two dirty models\n   * prompt one after the other rather than both at once.\n   *\n   * What blocking a pop cannot do anything about: the URL moves and comes\n   * back, so the address bar can flicker — `router.location` does not, since\n   * a blocked pop never reaches the history listeners — and popping to an\n   * entry the history library did not create cannot be blocked and fails\n   * silently in production. A cancelled pop is also invisible to\n   * `navigate()`, which was never called for it.\n   */\n  block(when: () => boolean, blocker: NavigationBlocker): () => void {\n    const entry: BlockerEntry = { when, blocker };\n    this.blockers.add(entry);\n\n    // registration follows the predicate rather than the caller's lifetime:\n    // `history.block` installs a `beforeunload` handler that calls\n    // `preventDefault()` without ever consulting a blocker, so a\n    // registration outliving its predicate would prompt \"Leave site?\" on a\n    // clean form. That listener is also why the router keeps none of its\n    // own — armed while the predicate holds is exactly the behaviour wanted.\n    const stopReaction = reaction(\n      () => entry.when(),\n      () => this.syncHistoryBlocker(),\n      {\n        fireImmediately: true,\n      },\n    );\n\n    // idempotent, so StrictMode's mount/unmount/mount and a caller that\n    // disposes twice both land in the same place\n    return () => {\n      stopReaction();\n      this.blockers.delete(entry);\n      this.syncHistoryBlocker();\n    };\n  }\n\n  /**\n   * The blockers with a say in a navigation to `pathname`, in registration\n   * order. Empty is the common case and costs one `Set` size check.\n   */\n  private activeBlockers(pathname: string): NavigationBlocker[] {\n    // a same-pathname change leaves the route on screen — see `block`\n    if (!this.blockers.size || pathname === this.location?.pathname) return [];\n\n    return [...this.blockers].filter((entry) => entry.when()).map((entry) => entry.blocker);\n  }\n\n  /** Asks each blocker in turn, stopping at the first that says no. */\n  private async consultBlockers(\n    blockers: NavigationBlocker[],\n    navigation: BlockedNavigation,\n  ): Promise<boolean> {\n    for (const blocker of blockers) {\n      try {\n        if ((await blocker(navigation)) !== true) return false;\n      } catch (cause) {\n        // staying is the safe failure: a dialog that crashed cannot have\n        // told the user their work was about to be discarded\n        console.error(\"A navigation blocker threw; staying at the current route.\", cause);\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  /**\n   * Arms a single `history.block` blocker while any predicate holds, and\n   * disarms it when none does.\n   *\n   * One blocker rather than one per registration: `history.block` fans a\n   * transition out to *every* blocker and gives each its own `retry()`, so\n   * several would prompt at once and each retry would re-prompt the others.\n   * Multiplexing here is what makes {@link consultBlockers} the only place\n   * that decides.\n   *\n   * Called from the reaction in {@link block}, from disposal, and after a\n   * transition has been let through.\n   */\n  private syncHistoryBlocker(): void {\n    // a transition is on its way through; the re-arm in `passThrough` owns\n    // the decision until it lands\n    if (this.stopRearm) return;\n\n    const armed = [...this.blockers].some((entry) => entry.when());\n    if (armed === !!this.unblockHistory) return;\n\n    if (!armed) {\n      this.standDown();\n      return;\n    }\n\n    this.unblockHistory = this.history.block((transition) => this.onTransition(transition));\n  }\n\n  /**\n   * The one blocker history sees.\n   *\n   * `history.block` declines *every* transition while a blocker is\n   * registered and never reads what the blocker returned, so most of what\n   * arrives here has already been decided: a push {@link navigate} approved,\n   * a `redirect()`, `setQueryParam`, the trailing-slash normalization and a\n   * write straight to `router.history` all need nothing but a retry.\n   * Prompting for them would ask twice about one navigation, or ask about\n   * one the user never made.\n   *\n   * A pop is the one transition nothing else sees, and the only one this\n   * consults blockers about.\n   */\n  private onTransition(transition: Transition): void {\n    if (transition.action !== Action.Pop) {\n      this.passThrough(transition);\n      return;\n    }\n\n    // one decision at a time. The pop stays reverted, so the user is where\n    // they were and can press back again once they have answered.\n    if (this.deciding) return;\n\n    const { pathname, search } = transition.location;\n    const blockers = this.activeBlockers(pathname);\n    if (!blockers.length) {\n      this.passThrough(transition);\n      return;\n    }\n\n    // where the retry counts from: `retry()` is a `go()` by the delta the\n    // pop fired with, so anything that moves while the handler is deciding\n    // leaves that delta addressing an entry the user did not ask for\n    const from = this.history.location.key;\n    this.deciding = true;\n\n    void this.consultBlockers(blockers, {\n      action: \"POP\",\n      pathname,\n      search,\n      href: `${pathname}${search}`,\n    })\n      .then((allowed) => {\n        if (allowed && this.history.location.key === from) {\n          this.passThrough(transition);\n        }\n      })\n      .finally(() => {\n        this.deciding = false;\n      });\n  }\n\n  /**\n   * Lets a transition history has already declined through, and re-arms once\n   * it lands.\n   *\n   * Standing down first is not optional: `retry()` re-enters the blocker,\n   * and a pop's retry is a `go()` whose `popstate` arrives asynchronously —\n   * so the blocker has to stay down until the retried navigation lands. The\n   * one-shot listener is that \"until\", and re-arming through\n   * {@link syncHistoryBlocker} means a predicate that went false in the\n   * meantime leaves it down.\n   *\n   * If the retry never lands — a pop to an entry the history library did not\n   * create cannot be blocked, and fails silently in production — the blocker\n   * stays down, which is the same outcome as never having armed it.\n   */\n  private passThrough(transition: Transition): void {\n    this.standDown();\n\n    this.stopRearm = this.history.listen(() => {\n      this.standDown();\n      this.syncHistoryBlocker();\n    });\n\n    transition.retry();\n  }\n\n  private standDown(): void {\n    this.unblockHistory?.();\n    this.unblockHistory = undefined;\n    this.stopRearm?.();\n    this.stopRearm = undefined;\n  }\n\n  /**\n   * The URL a set of navigation options addresses, as a single string.\n   *\n   * This is what the link components put on `href`, so a cmd-click lands on\n   * exactly where a plain click would have navigated — `search` and\n   * `preserveSearch` included. Reads {@link search} when preserving, so it\n   * re-derives as the current query changes.\n   */\n  resolveHref<P extends RoutePath>(options: NavigateOptions<P>): string {\n    const { pathname, search } = this.resolveLocation(options);\n    return `${pathname}${search ?? \"\"}`;\n  }\n\n  private resolveLocation<P extends RoutePath>(\n    options: NavigateOptions<P>,\n  ): { pathname: string; search: string | undefined } {\n    const { to, search = {}, preserveSearch, params } = options;\n\n    const searchParams = search instanceof URLSearchParams ? search : new URLSearchParams(search);\n\n    if (preserveSearch) {\n      for (const [name, value] of this.search) {\n        if (!searchParams.has(name)) {\n          searchParams.set(name, value);\n        }\n      }\n    }\n\n    return {\n      pathname: resolvePath(to, params),\n      search: searchParams.size ? `?${searchParams.toString()}` : undefined,\n    };\n  }\n\n  private isCurrentLocation<P extends RoutePath>(options: NavigateOptions<P>): boolean {\n    if (!this.location) return false;\n\n    const target = this.resolveLocation(options);\n    return (\n      target.pathname === this.location.pathname && (target.search ?? \"\") === this.location.search\n    );\n  }\n\n  setQueryParam(param: string, value: string): void {\n    const params = new URLSearchParams(this.location.search);\n    params.set(param, value);\n    this.history.replace({ search: `?${params.toString()}` });\n  }\n\n  removeQueryParam(param: string): string | undefined {\n    const params = new URLSearchParams(this.location.search);\n    const value = params.get(param) ?? undefined;\n    if (value !== undefined) {\n      params.delete(param);\n      this.history.replace({ search: params.size ? `?${params.toString()}` : \"\" });\n    }\n    return value;\n  }\n\n  async setLocation(location: Location): Promise<void> {\n    if (!this.routesDef) return;\n\n    // TODO: this should not be the responsibility of mobx-router\n    // and should really be handled server-side\n    if (location.pathname !== \"/\" && location.pathname.endsWith(\"/\")) {\n      this.history.replace({ ...location, pathname: location.pathname.slice(0, -1) });\n      return;\n    }\n\n    // a same-pathname change (query params, history state) can't affect\n    // which route matches, its guards, or its loaders (none of which can\n    // observe search params) — update the observable location without\n    // rebuilding the route, so query-param changes don't refetch loaders\n    // or replace activeRoute. Also guards against restarting a match for\n    // a pathname that a still-pending navigation is already resolving.\n    if ((this.activeRoute || this.pendingRoute) && this.location?.pathname === location.pathname) {\n      this.location = location;\n      return;\n    }\n\n    this.location = location;\n\n    // a cold load has no previous page to preserve, so the pending route\n    // renders and its [LOADING] components are on screen — the only case\n    // where holding a just-shown indicator is worth delaying content for\n    const cold = !this.activeRoute;\n\n    // starts before guards, so both isNavigating and isSlowNavigation span\n    // the guard phase\n    const settle = this.beginNavigation();\n\n    let matchedRoute: Route | undefined;\n    try {\n      const matched = matchRoute(location.pathname, this.routesDef);\n      matchedRoute = matched;\n\n      // Published before guards run — the point of `target` is that the\n      // destination is known here and nothing else exposes it until the swap.\n      // No staleness check is needed: matching is synchronous and there is no\n      // await between assigning `this.location` above and this write, so\n      // concurrent navigations cannot interleave and the newest always wins.\n      runInAction(() => {\n        this.matchedTarget = toTarget(matched, location.pathname);\n      });\n\n      await matchedRoute.guard();\n\n      // navigating within a guard function\n      // is essentially a redirect\n      if (this.isStale(location)) {\n        return;\n      }\n\n      runInAction(() => {\n        this.pendingRoute = matchedRoute;\n      });\n\n      await matchedRoute.load({ hold: cold });\n\n      // another navigation started while this one was loading — it owns\n      // the swap now, and its own pendingRoute assignment has replaced ours\n      if (this.isStale(location)) {\n        return;\n      }\n\n      await this.applyRoute(() => {\n        this.activeRoute = matchedRoute;\n        this.pendingRoute = undefined;\n      });\n    } catch (e) {\n      let thrown: unknown = e;\n\n      if (thrown instanceof Redirect) {\n        const loop = this.redirectLoop(location.pathname);\n\n        if (loop) {\n          // carries the Redirect's own origin so the loop renders under the\n          // same [ERROR] a failure at that level would have, exactly as\n          // `redirectFailed` does for the unresolvable case\n          loop.state = thrown.state;\n          loop.depth = thrown.depth;\n          thrown = loop;\n        } else {\n          try {\n            // a redirect replaces by default. The URL that redirected renders\n            // nothing of its own, so leaving it in history traps Back: it\n            // resolves to the same redirect and throws the user forward again.\n            // An explicit `replace: false` on the redirect still wins.\n            // not awaited: the caller's own `settled()` already spans this\n            // hop, and awaiting here would hold this navigation's `finally`\n            // open behind a chain it no longer owns\n            void this.navigateNow({ ...thrown.options, replace: thrown.options.replace ?? true });\n            return;\n          } catch (cause) {\n            // a redirect that can't be carried out — most often a `to` whose\n            // `:params` weren't filled — is a routing failure like any other.\n            // Falling through renders it via [ERROR] instead of escaping as an\n            // unhandled rejection out of the history listener, where nothing\n            // would catch it and the screen would keep the previous page.\n            thrown = redirectFailed(cause, location.pathname, thrown);\n          }\n        }\n      }\n\n      // navigating within a guard before it threw — treat as a redirect\n      if (this.isStale(location)) {\n        return;\n      }\n\n      const error =\n        thrown instanceof RouterError\n          ? thrown\n          : new RouterError(\"RENDER\", { cause: thrown, path: location.pathname });\n      console.error(error);\n\n      const errorRoute = makeErrorRoute(error, location.pathname, matchedRoute);\n      await this.applyRoute(() => {\n        this.activeRoute = errorRoute;\n        this.pendingRoute = undefined;\n      });\n      await errorRoute.load();\n    } finally {\n      // covers every exit: the swap, an error route, a stale bail, and the\n      // redirect path — where the follow-up navigation has already claimed\n      // the clock, so this call is a no-op\n      settle();\n    }\n  }\n\n  /**\n   * Marks a navigation as in flight, starts its debounce clock, and returns\n   * the cleanup that ends both.\n   *\n   * Both are tracked here — before guards run — rather than derived from\n   * `pendingRoute`, which is only assigned once guards resolve. That is\n   * what lets `isNavigating` mean \"in flight\" and `isSlowNavigation`\n   * measure how long the user has actually been waiting. An outlet-level\n   * clock cannot do the latter: outlets only begin loading after guards, so\n   * a 250ms guard followed by a 250ms loader would show no indicator at all\n   * despite half a second of waiting.\n   */\n  private beginNavigation(): () => void {\n    // a newer navigation supersedes the previous clock, but deliberately\n    // does not reset `navigationSlow` — if an indicator is already on\n    // screen, a follow-up navigation should not blink it out and back in\n    clearTimeout(this.slowTimer);\n    runInAction(() => {\n      this.navigating = true;\n    });\n\n    const timer = setTimeout(() => {\n      if (this.slowTimer === timer) {\n        runInAction(() => {\n          this.navigationSlow = true;\n        });\n      }\n    }, LOADING_DELAY_MS);\n    this.slowTimer = timer;\n\n    return () => {\n      // a later navigation owns the clock now; leave its state alone\n      if (this.slowTimer !== timer) return;\n      clearTimeout(timer);\n      this.slowTimer = undefined;\n      // reaching here is the definition of a chain ending: a superseded hop\n      // returns above, so only the navigation that actually landed clears it\n      this.redirects = 0;\n      runInAction(() => {\n        this.navigating = false;\n        this.navigationSlow = false;\n      });\n    };\n  }\n\n  /**\n   * Counts a redirect hop away from `pathname`, and reports the chain as a\n   * loop once it has taken too many.\n   *\n   * `makeRoutes` rejects a static `[REDIRECT]` cycle at build time, but it\n   * gives up on the function form and cannot see a `redirect()` thrown from\n   * a guard or loader at all. Those only reveal themselves by running, and\n   * left alone they spin forever: every hop begins a fresh navigation before\n   * the previous one's `finally`, so the clock is handed on indefinitely,\n   * `isNavigating` never drops, and an awaited `navigate()` never settles —\n   * which would silently swallow everything after it in an `async` caller.\n   *\n   * Deliberately a count and not a cycle search. Tracking the pathnames\n   * visited would name the exact cycle in the message and catch a ping-pong\n   * on its second hop rather than its tenth, but it only helps a chain that\n   * repeats itself — one that keeps inventing pathnames still needs the\n   * count — so it buys a better message at the price of being the second\n   * way to answer a question that already has one.\n   *\n   * Either way the loop becomes a `RouterError` and ends the chain the way\n   * any other routing failure does: `[ERROR]` renders and the promise\n   * resolves, instead of a hung tab.\n   */\n  private redirectLoop(pathname: string): RouterError | undefined {\n    if (++this.redirects <= MAX_REDIRECTS) return undefined;\n\n    return new RouterError(\"REDIRECT\", {\n      message:\n        `Redirect loop: ${MAX_REDIRECTS} redirects without landing, still going at '${pathname}'. ` +\n        \"A guard, loader or [REDIRECT] is sending this navigation in a circle.\",\n      path: pathname,\n    });\n  }\n\n  /**\n   * Whether another navigation has taken over since this one started.\n   * Compared by pathname rather than `Location` identity: a query-param or\n   * history-state change during a pending navigation replaces `location`\n   * without re-matching, and must not cancel the navigation in flight.\n   */\n  private isStale(location: Location): boolean {\n    return this.location?.pathname !== location.pathname;\n  }\n\n  /**\n   * Commits a route swap, wrapped in a view transition where supported.\n   *\n   * The transition wraps **only** the swap. Wrapping the navigation as a\n   * whole would freeze the page on its old snapshot for the entire guard\n   * and load phase — a fetch's worth of unresponsive UI, with the loading\n   * indicator unable to animate.\n   *\n   * `flushSync` removes a race rather than fixing an outright bug. The\n   * browser captures the new snapshot at the first rendering opportunity\n   * after the update callback settles; a bare MobX mutation schedules the\n   * re-render on React's scheduler, which in practice usually lands\n   * inside that window but is not guaranteed to (concurrent rendering may\n   * yield). Flushing synchronously inside the callback makes the captured\n   * frame deterministic.\n   *\n   * What the earlier implementation got wrong was placement, not\n   * flushing: it wrapped `history.push`, so the callback returned before\n   * guards had even run and both snapshots caught the same page. Verified\n   * against real Chrome — that version animated exactly one frame.\n   */\n  private async applyRoute(swap: () => void): Promise<void> {\n    const apply = () => runInAction(swap);\n    const startViewTransition =\n      typeof document !== \"undefined\" ? document.startViewTransition?.bind(document) : undefined;\n\n    // A cold load has no previous page to animate away from, and its\n    // visible change happens when outlets resolve rather than at the swap.\n    if (!this.viewTransitions || !startViewTransition || !this.activeRoute) {\n      apply();\n      return;\n    }\n\n    const transition = startViewTransition(() => {\n      flushSync(apply);\n    });\n\n    // `ready` rejects whenever the browser skips the animation — a second\n    // navigation interrupting this one, a backgrounded tab, duplicate\n    // view-transition-names. Routine, and the DOM update still happens.\n    transition.ready.catch(() => {});\n\n    // Awaited so the swap has landed before the navigation resolves.\n    // Deliberately not `finished`: that waits out the animation, which\n    // would make every navigation report as long as its transition.\n    await transition.updateCallbackDone.catch(() => {});\n  }\n}\n","import { useEffect } from \"react\";\nimport { useRouter } from \"./components/router\";\nimport type { RouterStore } from \"./router.store\";\n\nconst DEFAULT_MESSAGE = \"Leave this page? Changes you have made may not be saved.\";\n\n/**\n * Native `confirm()` protection against leaving the page, however the user\n * leaves it — links, programmatic navigation, back and forward, and closing\n * or reloading the tab.\n *\n * The deliberately dumb counterpart to `RouterStore.block`: no predicate, no\n * dialog of your own, nothing to keep in step. It protects for as long as it\n * is registered, and returns the disposer.\n *\n * ```ts\n * const dispose = confirmLeave(router);\n * ```\n *\n * It *is* a `block`, so everything documented there applies unchanged. The\n * only thing this trades away is the dialog: the prompts are native chrome,\n * and both ignore `message` in some form — every browser ignores a custom\n * `beforeunload` string, and `confirm()` renders as the browser draws it.\n *\n * The always-true predicate means the browser's own reload prompt is live\n * for as long as this is registered, clean page included. That is the point\n * of the shortcut — there is no state for it to consult — but it is why\n * `useNavigationBlock` is the better default for a form.\n */\nexport const confirmLeave = (router: RouterStore, message = DEFAULT_MESSAGE): (() => void) =>\n  router.block(\n    () => true,\n    () => window.confirm(message),\n  );\n\n/**\n * {@link confirmLeave} for the lifetime of a component — basic unsaved-work\n * protection in one line, with no state to track and no dialog to write.\n *\n * ```tsx\n * useConfirmLeave(\"Discard your changes?\");\n * ```\n *\n * Reach for `useNavigationBlock` instead when the block should follow a\n * predicate or show the app's own dialog — back button included.\n */\nexport const useConfirmLeave = (message?: string): void => {\n  const router = useRouter();\n\n  useEffect(() => confirmLeave(router, message), [router, message]);\n};\n","import { useEffect, useRef } from \"react\";\nimport { useRouter } from \"./components/router\";\nimport type { NavigationBlocker } from \"./types\";\n\n/**\n * Blocks navigation away from this component while `when` returns `true`,\n * asking `blocker` what to do about each attempt.\n *\n * ```tsx\n * useNavigationBlock(\n *   () => designer.dirty,\n *   async () => {\n *     const choice = await confirmLeave(); // the app's own dialog\n *     if (choice === \"save\") await designer.save();\n *     return choice !== \"stay\";\n *   },\n * );\n * ```\n *\n * Only `true` proceeds — `false`, nothing at all, and a throw each keep the\n * user where they are. `RouterStore.block` documents exactly what is and is\n * not covered; the short version is every in-app navigation plus closing the\n * tab, but not the back button (see `useConfirmLeave` for that).\n *\n * Both arguments are read through a ref, so neither has to be stable:\n * passing inline closures re-registers nothing, and the registration lasts\n * the component's lifetime. Blocking follows `when`, not the mount, so a\n * clean form is as good as no blocker at all — including for the\n * `beforeunload` prompt.\n */\nexport const useNavigationBlock = (when: () => boolean, blocker: NavigationBlocker): void => {\n  const router = useRouter();\n\n  // written during render like `useStable` does: what the effect below reads\n  // is always the latest pair, so a dialog closure never goes stale\n  const latest = useRef({ when, blocker });\n  latest.current = { when, blocker };\n\n  useEffect(\n    () =>\n      router.block(\n        () => latest.current.when(),\n        (navigation) => latest.current.blocker(navigation),\n      ),\n    [router],\n  );\n};\n"],"mappings":"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"}