@real-router/preact 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -68,6 +68,8 @@ function App() {
68
68
  | `useRouteNode(name)` | `{ navigator, route, previousRoute }` | Only when node activates/deactivates |
69
69
  | `useRouteUtils()` | `RouteUtils` | Never |
70
70
  | `useRouterTransition()` | `{ isTransitioning, isLeaveApproved, toRoute, fromRoute }` | On transition start/end |
71
+ | `useRouteExit(handler, options?)` | `void` — wraps `router.subscribeLeave` with abort + same-route guards | Never (stable subscription) |
72
+ | `useRouteEnter(handler, options?)` | `void` — fires on nav-driven mount via `useRoute()` snapshot | Never (handler stays current) |
71
73
 
72
74
  ```tsx
73
75
  // useRouteNode — re-renders only when "users.*" changes
@@ -97,6 +99,33 @@ function GlobalProgress() {
97
99
  if (!isTransitioning) return null;
98
100
  return <div className="progress-bar" />;
99
101
  }
102
+
103
+ // useRouteExit — exit animations, draft autosave, AbortSignal-aware cleanup
104
+ function FadeOut() {
105
+ const ref = useRef<HTMLDivElement>(null);
106
+ useRouteExit(async ({ signal }) => {
107
+ const el = ref.current;
108
+ if (!el) return;
109
+ el.classList.add("fade-out");
110
+ const cleanup = () => el.classList.remove("fade-out");
111
+ signal.addEventListener("abort", cleanup, { once: true });
112
+ el.getBoundingClientRect(); // style flush
113
+ await Promise.allSettled(el.getAnimations().map((a) => a.finished));
114
+ cleanup();
115
+ });
116
+ return <div ref={ref}>...</div>;
117
+ }
118
+
119
+ // useRouteEnter — page-enter analytics, focus management, entry animations
120
+ function PageEnterAnalytics() {
121
+ useRouteEnter(({ route, previousRoute }) => {
122
+ analytics.track("page_enter", {
123
+ route: route.name,
124
+ from: previousRoute.name,
125
+ });
126
+ });
127
+ return null;
128
+ }
100
129
  ```
101
130
 
102
131
  ## Components
@@ -231,12 +260,24 @@ Opt-in preservation of scroll position across navigations:
231
260
 
232
261
  Restores scroll on back/forward, scrolls to top (or `#hash`) on push. Three modes: `"restore"` (default), `"top"`, `"manual"`. Custom containers via `scrollContainer: () => HTMLElement | null`. Lifecycle tied to the provider — created on mount, destroyed on unmount. See [Scroll Restoration guide](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) for details.
233
262
 
263
+ ## View Transitions
264
+
265
+ Opt-in animated route transitions via the browser's [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API):
266
+
267
+ ```tsx
268
+ <RouterProvider router={router} viewTransitions>
269
+ {/* Your app */}
270
+ </RouterProvider>
271
+ ```
272
+
273
+ No-op on unsupported browsers (Firefox as of 2026-04, SSR). Customization is pure CSS via `::view-transition-*` pseudo-elements and `view-transition-name` for hero morphs. See [View Transitions guide](https://github.com/greydragon888/real-router/wiki/View-Transitions) for patterns.
274
+
234
275
  ## Documentation
235
276
 
236
277
  Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
237
278
 
238
- - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [Scroll Restoration](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration)
239
- - [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition)
279
+ - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [Scroll Restoration](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) · [View Transitions](https://github.com/greydragon888/real-router/wiki/View-Transitions)
280
+ - [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition) · [useRouteExit](https://github.com/greydragon888/real-router/wiki/useRouteExit) · [useRouteEnter](https://github.com/greydragon888/real-router/wiki/useRouteEnter)
240
281
 
241
282
  ## Examples
242
283
 
@@ -97,7 +97,9 @@ declare const useNavigator: () => Navigator$1;
97
97
  declare const useRouteUtils: () => RouteUtils;
98
98
  //#endregion
99
99
  //#region src/hooks/useRoute.d.ts
100
- declare const useRoute: <P extends Params = Params>() => RouteContext$1<P>;
100
+ declare const useRoute: <P extends Params = Params>() => Omit<RouteContext$1<P>, "route"> & {
101
+ route: State<P>;
102
+ };
101
103
  //#endregion
102
104
  //#region src/hooks/useRouteNode.d.ts
103
105
  declare function useRouteNode(nodeName: string): RouteContext$1;
@@ -105,6 +107,217 @@ declare function useRouteNode(nodeName: string): RouteContext$1;
105
107
  //#region src/hooks/useRouterTransition.d.ts
106
108
  declare function useRouterTransition(): RouterTransitionSnapshot$1;
107
109
  //#endregion
110
+ //#region src/hooks/useRouteExit.d.ts
111
+ interface RouteExitContext {
112
+ /** The route being left. */
113
+ route: State;
114
+ /** The route being navigated to. */
115
+ nextRoute: State;
116
+ /**
117
+ * AbortSignal that fires when this navigation is superseded by a later
118
+ * one (rapid clicks). Already filtered: when the handler runs,
119
+ * `signal.aborted` is guaranteed to be `false`. Use
120
+ * `signal.addEventListener("abort", cleanup, { once: true })` for
121
+ * cleanup that must run on cancellation.
122
+ */
123
+ signal: AbortSignal;
124
+ }
125
+ interface UseRouteExitOptions {
126
+ /**
127
+ * Skip the handler when `route.name === nextRoute.name`
128
+ * (sort/filter/query-only navigations on the same route). Default:
129
+ * `true`.
130
+ */
131
+ skipSameRoute?: boolean;
132
+ }
133
+ type RouteExitHandler = (context: RouteExitContext) => void | Promise<void>;
134
+ /**
135
+ * Subscribe to the router's leave-window with the universal guards baked
136
+ * in. Wraps `router.subscribeLeave` so consumers don't repeat the same
137
+ * boilerplate every time:
138
+ *
139
+ * - **Reentrant abort pre-check**: if `signal.aborted` is already `true`
140
+ * when the handler would run (rapid navigation superseded a slower
141
+ * one), the handler is skipped entirely. `signal.addEventListener(
142
+ * "abort", ...)` does not fire retroactively, so without this guard
143
+ * downstream cleanup would never trigger.
144
+ * - **Same-route skip**: by default, `route.name === nextRoute.name`
145
+ * short-circuits the handler — query-only navigations (sort, filter,
146
+ * pagination) skip the work. Opt out with `skipSameRoute: false`.
147
+ * - **Stable handler reference**: the handler can change identity on
148
+ * every render without causing resubscription — internal ref keeps
149
+ * the latest handler accessible to the long-lived subscription.
150
+ *
151
+ * Returns nothing — the subscription's lifecycle is bound to the
152
+ * component's mount.
153
+ *
154
+ * If the handler returns a Promise, the router blocks on it. If the
155
+ * Promise resolves, navigation proceeds. If it rejects, the router emits
156
+ * `TRANSITION_CANCELLED` (existing core behavior, no change here).
157
+ *
158
+ * @example Animation
159
+ * ```tsx
160
+ * const ref = useRef<HTMLDivElement>(null);
161
+ *
162
+ * useRouteExit(async ({ signal }) => {
163
+ * const el = ref.current;
164
+ * if (!el) return;
165
+ * el.classList.add("fade-out");
166
+ * const cleanup = () => el.classList.remove("fade-out");
167
+ * signal.addEventListener("abort", cleanup, { once: true });
168
+ * try {
169
+ * el.getBoundingClientRect(); // style flush
170
+ * await Promise.allSettled(el.getAnimations().map((a) => a.finished));
171
+ * } finally {
172
+ * cleanup();
173
+ * }
174
+ * });
175
+ * ```
176
+ *
177
+ * @example Auto-save form draft
178
+ * ```tsx
179
+ * useRouteExit(async ({ signal }) => {
180
+ * if (formState.dirty) await api.saveDraft(formState, { signal });
181
+ * });
182
+ * ```
183
+ *
184
+ * @example Cancel inflight requests
185
+ * ```tsx
186
+ * useRouteExit(() => {
187
+ * inflightController.abort();
188
+ * });
189
+ * ```
190
+ *
191
+ * @example Library-coordinated exit (motion / framer-motion)
192
+ * ```tsx
193
+ * const exitResolverRef = useRef<(() => void) | null>(null);
194
+ *
195
+ * useRouteExit(({ signal }) => {
196
+ * return new Promise<void>((resolve) => {
197
+ * exitResolverRef.current = resolve;
198
+ * signal.addEventListener("abort", () => resolve(), { once: true });
199
+ * });
200
+ * });
201
+ *
202
+ * const onExitComplete = () => exitResolverRef.current?.();
203
+ * // pass onExitComplete to <AnimatePresence>
204
+ * ```
205
+ *
206
+ * @example Reading rich transition metadata via `nextRoute.transition`
207
+ * ```tsx
208
+ * useRouteExit(({ route, nextRoute }) => {
209
+ * // nextRoute.transition: TransitionMeta — preview of the upcoming nav
210
+ * if (nextRoute.transition.segments.deactivated.includes("products")) {
211
+ * // leaving the products subtree entirely — flush product-related caches
212
+ * productCache.clear();
213
+ * }
214
+ * if (nextRoute.transition.redirected) {
215
+ * // skip animation when navigation arrived via redirect
216
+ * return;
217
+ * }
218
+ * });
219
+ * ```
220
+ */
221
+ declare function useRouteExit(handler: RouteExitHandler, options?: UseRouteExitOptions): void;
222
+ //#endregion
223
+ //#region src/hooks/useRouteEnter.d.ts
224
+ interface RouteEnterContext {
225
+ /** The route that was just activated. */
226
+ route: State;
227
+ /** The route that was active immediately before this navigation. */
228
+ previousRoute: State;
229
+ }
230
+ type RouteEnterHandler = (context: RouteEnterContext) => void;
231
+ interface UseRouteEnterOptions {
232
+ /**
233
+ * Skip the handler when `route.name === previousRoute.name`
234
+ * (sort/filter/query-only navigations on the same route). Default:
235
+ * `true`. Symmetric with `useRouteExit`'s same-name option.
236
+ */
237
+ skipSameRoute?: boolean;
238
+ }
239
+ /**
240
+ * Fire `handler` once when the component mounts as a result of a
241
+ * navigation. Mirror of `useRouteExit` for the entry side.
242
+ *
243
+ * What this hook covers that ad-hoc `useEffect` + `useRoute()` doesn't:
244
+ *
245
+ * - **Skip-initial**: handler is skipped when there is no
246
+ * `previousRoute` (i.e. first-load mount). Most consumers want to
247
+ * fire side effects only on real navigations, not on hydration.
248
+ * - **Same-route skip** (default): handler is skipped when
249
+ * `route.name === previousRoute.name`. Sort/filter/query-only
250
+ * navigations re-run the effect (because `route` reference changes
251
+ * in `useRoute`'s snapshot), but they are not "entries" in the
252
+ * animation / analytics sense — the component instance has stayed
253
+ * mounted throughout. Opt out with `skipSameRoute: false` when
254
+ * the handler legitimately needs to fire on every navigation
255
+ * (e.g. analytics tracking each query-param flip).
256
+ * - **Latest-handler ref**: the handler can change identity on every
257
+ * render without re-running the effect — the registered wrapper
258
+ * dispatches to whatever `handlerRef.current` points to.
259
+ * - **Mount-time `route` / `previousRoute` snapshot**: the handler
260
+ * receives the values that were live at the moment of mount, not
261
+ * the latest ones (which may have moved on if the user navigated
262
+ * again before the effect drained).
263
+ *
264
+ * Race-safety: `useRoute()` is wired through `useSyncExternalStore` from
265
+ * `@real-router/sources` (Preact polyfill: useState + useEffect, same
266
+ * post-commit semantics), so by the time the new component's effect
267
+ * runs, the snapshot is the post-commit one. This is the reason we can
268
+ * read mount-time context from `useRoute()` instead of subscribing to
269
+ * `router.subscribe` directly (which fires before Preact schedules a
270
+ * re-render — the well-known race in distributed components).
271
+ *
272
+ * Note: Preact does not expose a `StrictMode` equivalent, so the
273
+ * `lastHandledRouteRef` guard exists primarily for defensive symmetry
274
+ * with the React implementation. It is harmless in Preact.
275
+ *
276
+ * @example Direction-aware entry animation
277
+ * ```tsx
278
+ * useRouteEnter(({ route }) => {
279
+ * const direction = route.context.browser?.direction;
280
+ * ref.current?.classList.add(
281
+ * direction === "back" ? "slide-from-left" : "slide-from-right",
282
+ * );
283
+ * });
284
+ * ```
285
+ *
286
+ * @example Source-aware focus management
287
+ * ```tsx
288
+ * useRouteEnter(({ route }) => {
289
+ * if (route.context.browser?.source === "navigate") {
290
+ * headingRef.current?.focus();
291
+ * }
292
+ * });
293
+ * ```
294
+ *
295
+ * @example Analytics page-enter event (skip-initial built-in)
296
+ * ```tsx
297
+ * useRouteEnter(({ route, previousRoute }) => {
298
+ * analytics.track("page_enter", {
299
+ * route: route.name,
300
+ * from: previousRoute.name,
301
+ * });
302
+ * });
303
+ * ```
304
+ *
305
+ * @example Reading rich transition metadata via `route.transition`
306
+ * ```tsx
307
+ * useRouteEnter(({ route }) => {
308
+ * // route.transition: TransitionMeta — populated by core for every state
309
+ * if (route.transition.redirected) {
310
+ * showToast(`Redirected from ${route.transition.from}`);
311
+ * }
312
+ * if (route.transition.segments.activated.includes("products")) {
313
+ * // products subtree just became active (could be products or
314
+ * // products.detail). Useful for subtree-scoped side effects.
315
+ * }
316
+ * });
317
+ * ```
318
+ */
319
+ declare function useRouteEnter(handler: RouteEnterHandler, options?: UseRouteEnterOptions): void;
320
+ //#endregion
108
321
  //#region ../../shared/dom-utils/scroll-restore.d.ts
109
322
  type ScrollRestorationMode = "restore" | "top" | "manual";
110
323
  interface ScrollRestorationOptions {
@@ -119,6 +332,7 @@ interface RouteProviderProps {
119
332
  children: ComponentChildren;
120
333
  announceNavigation?: boolean;
121
334
  scrollRestoration?: ScrollRestorationOptions;
335
+ viewTransitions?: boolean;
122
336
  }
123
337
  declare const RouterProvider: FunctionComponent<RouteProviderProps>;
124
338
  //#endregion
@@ -127,5 +341,5 @@ declare const RouteContext: _$preact.Context<RouteContext$1 | null>;
127
341
  declare const RouterContext: _$preact.Context<Router<object> | null>;
128
342
  declare const NavigatorContext: _$preact.Context<Navigator$1 | null>;
129
343
  //#endregion
130
- export { Link, type LinkProps, type Navigator, NavigatorContext, RouteContext, RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps, type SelfProps as RouteViewSelfProps, RouterContext, RouterErrorBoundary, type RouterErrorBoundaryProps, RouterProvider, type RouterTransitionSnapshot, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
344
+ export { Link, type LinkProps, type Navigator, NavigatorContext, RouteContext, type RouteEnterContext, type RouteEnterHandler, type RouteExitContext, type RouteExitHandler, RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps, type SelfProps as RouteViewSelfProps, RouterContext, RouterErrorBoundary, type RouterErrorBoundaryProps, RouterProvider, type RouterTransitionSnapshot, type UseRouteEnterOptions, type UseRouteExitOptions, useNavigator, useRoute, useRouteEnter, useRouteExit, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
131
345
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/components.tsx","../../src/components/RouteView/RouteView.tsx","../../src/types.ts","../../src/components/Link.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useRouter.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRouterTransition.tsx","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.tsx","../../src/context.ts"],"mappings":";;;;;;;UAEiB,cAAA;EAAA,SACN,QAAA;EAAA,SACA,QAAA,EAAU,iBAAA;AAAA;AAAA,UAGJ,UAAA;EAAA,SACN,OAAA;EAAA,SACA,KAAA;EAAA,SACA,QAAA,GAAW,iBAAA;EAAA,SACX,QAAA,EAAU,iBAAA;AAAA;AAAA,UAGJ,SAAA;EAVN;EAAA,SAYA,QAAA,GAAW,iBAAA;EAZgB;EAAA,SAc3B,QAAA,EAAU,iBAAA;AAAA;AAAA,UAGJ,aAAA;EAAA,SACN,QAAA,EAAU,iBAAA;AAAA;;;iBCpBL,KAAA,CAAM,MAAA,EAAQ,UAAA;AAAA,kBAAd,KAAA;EAAA,IAAK,WAAA;AAAA;AAAA,iBAML,IAAA,CAAK,MAAA,EAAQ,SAAA;AAAA,kBAAb,IAAA;EAAA,IAAI,WAAA;AAAA;AAAA,iBAMJ,QAAA,CAAS,MAAA,EAAQ,aAAA;AAAA,kBAAjB,QAAA;EAAA,IAAQ,WAAA;AAAA;;;iBCLf,aAAA,CAAA;EACP,QAAA;EACA;AAAA,GACC,QAAA,CAAS,cAAA,IAAkB,KAAA;AAAA,kBAHrB,aAAA;EAAA,IAAa,WAAA;AAAA;AAAA,cAgCT,SAAA,SAAS,aAAA;;;;;;;UCjCL,UAAA,WAAqB,MAAA,GAAS,MAAA;EAC7C,KAAA,EAAO,KAAA,CAAM,CAAA;EACb,aAAA,GAAgB,KAAA;AAAA;AAAA,KAGN,cAAA,WAAuB,MAAA,GAAS,MAAA;EAC1C,SAAA,EAAW,WAAA;AAAA,IACT,UAAA,CAAW,CAAA;AAAA,UAEE,SAAA,WAAoB,MAAA,GAAS,MAAA,UAAgB,IAAA,CAC5D,GAAA,CAAI,cAAA,CAAe,iBAAA;EAGnB,SAAA;EACA,WAAA,GAAc,CAAA;EACd,YAAA,GAAe,iBAAA;EACf,SAAA;EACA,eAAA;EACA,YAAA;EACA,iBAAA;EACA,MAAA;AAAA;;;cCOW,IAAA,EAAM,iBAAA,CAAkB,SAAA;;;UCzBpB,wBAAA;EAAA,SACN,QAAA,EAAU,iBAAA;EAAA,SACV,QAAA,GACP,KAAA,EAAO,WAAA,EACP,UAAA,iBACG,iBAAA;EAAA,SACI,OAAA,IACP,KAAA,EAAO,WAAA,EACP,OAAA,EAAS,KAAA,SACT,SAAA,EAAW,KAAA;AAAA;AAAA,iBAIC,mBAAA,CAAA;EACd,QAAA;EACA,QAAA;EACA;AAAA,GACC,wBAAA,GAA2B,KAAA;;;cCrBjB,SAAA,QAAgB,MAAA;;;cCAhB,YAAA,QAAmB,WAAA;;;cCCnB,aAAA,QAAoB,UAAA;;;cCApB,QAAA,aAAsB,MAAA,GAAS,MAAA,OAAW,cAAA,CAAiB,CAAA;;;iBCExD,YAAA,CAAa,QAAA,WAAmB,cAAA;;;iBCFhC,mBAAA,CAAA,GAAuB,0BAAA;;;KCG3B,qBAAA;AAAA,UAEK,wBAAA;EACf,IAAA,GAAO,qBAAA;EACP,eAAA;EACA,eAAA,UAAyB,WAAA;AAAA;;;UCHV,kBAAA;EACf,MAAA,EAAQ,MAAA;EACR,QAAA,EAAU,iBAAA;EACV,kBAAA;EACA,iBAAA,GAAoB,wBAAA;AAAA;AAAA,cAGT,cAAA,EAAgB,iBAAA,CAAkB,kBAAA;;;cCdlC,YAAA,EAAY,QAAA,CAAA,OAAA,CAAA,cAAA;AAAA,cAEZ,aAAA,EAAa,QAAA,CAAA,OAAA,CAAA,MAAA;AAAA,cAEb,gBAAA,EAAgB,QAAA,CAAA,OAAA,CAAA,WAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/components.tsx","../../src/components/RouteView/RouteView.tsx","../../src/types.ts","../../src/components/Link.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useRouter.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRouterTransition.tsx","../../src/hooks/useRouteExit.tsx","../../src/hooks/useRouteEnter.tsx","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.tsx","../../src/context.ts"],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`preact/hooks`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`preact`),i=require(`preact/compat`),a=require(`preact/jsx-runtime`),o=require(`@real-router/sources`),s=require(`@real-router/core/api`);function c(e){return null}c.displayName=`RouteView.Match`;function l(e){return null}l.displayName=`RouteView.Self`;function u(e){return null}u.displayName=`RouteView.NotFound`;function d(e,t,r){return t===``?!1:r?e===t:(0,n.startsWithSegment)(e,t)}function f(e,t){for(let n of(0,r.toChildArray)(e))(0,r.isValidElement)(n)&&(n.type===c||n.type===l||n.type===u?t.push(n):f(n.props.children,t))}function p(e,t,n){return(0,a.jsx)(r.Fragment,{children:n===void 0?e:(0,a.jsx)(i.Suspense,{fallback:n,children:e})},t)}function m(e,t){return e.type===u?(t.notFoundChildren=e.props.children,!0):e.type===l?(t.selfFound||=(t.selfChildren=e.props.children,t.selfFallback=e.props.fallback,!0),!0):!1}function h(e,t,n,r){let{segment:i,exact:a=!1,fallback:o}=e.props,s=n?`${n}.${i}`:i;return!r&&d(t,s,a)?p(e.props.children,s,o):null}function g(e,n,i,o){if(o.selfFound&&n===i){e.push(p(o.selfChildren,`__route-view-self__`,o.selfFallback));return}n===t.UNKNOWN_ROUTE&&o.notFoundChildren!==null&&e.push((0,a.jsx)(r.Fragment,{children:o.notFoundChildren},`__route-view-not-found__`))}function _(e,t,n){let r={selfChildren:null,selfFallback:void 0,selfFound:!1,notFoundChildren:null},i=!1,a=[];for(let o of e){if(m(o,r))continue;let e=h(o,t,n,i);e!==null&&(i=!0,a.push(e))}return i||g(a,t,n,r),{rendered:a,activeMatchFound:i}}function v(t,n,r){let[i,a]=(0,e.useState)(n);return(0,e.useEffect)(()=>{let e=()=>{a(e=>{let t=n();return Object.is(e,t)?e:t})};return e(),t(e)},[t,n]),i}const y=(0,r.createContext)(null),b=(0,r.createContext)(null),x=(0,r.createContext)(null),S=()=>{let t=(0,e.useContext)(b);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function C(n){let r=S(),i=(0,e.useMemo)(()=>(0,o.createRouteNodeSource)(r,n),[r,n]),{route:a,previousRoute:s}=v(i.subscribe,i.getSnapshot,i.getSnapshot),c=(0,e.useMemo)(()=>(0,t.getNavigator)(r),[r]);return(0,e.useMemo)(()=>({navigator:c,route:a,previousRoute:s}),[c,a,s])}function w({nodeName:t,children:n}){let{route:r}=C(t),i=(0,e.useMemo)(()=>{let e=[];return f(n,e),e},[n]);if(!r)return null;let{rendered:o}=_(i,r.name,t);return o.length>0?(0,a.jsx)(a.Fragment,{children:o}):null}w.displayName=`RouteView`;const T=Object.assign(w,{Match:c,Self:l,NotFound:u}),E=Object.freeze({}),D=Object.freeze({}),O=`data-real-router-announcer`;function k(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=A(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),N(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=M(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),j()}}}function A(){let e=document.querySelector(`[${O}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(O,``),document.body.prepend(t),t}function j(){document.querySelector(`[${O}]`)?.remove()}function M(e,t,n,r){if(n)return n(e);let i=r?.textContent.trim()??``,a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function N(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const P=`real-router:scroll`,F=Object.freeze({destroy:()=>{}});function I(e,t){if(globalThis.window===void 0)return F;let n=t?.mode??`restore`;if(n===`manual`)return F;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let o=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},s=e=>{let t=i?.();t?t.scrollTop=e:globalThis.scrollTo(0,e)},c=()=>{let e=globalThis.location.hash;if(r&&e.length>1){let t;try{t=decodeURIComponent(e.slice(1))}catch{t=e.slice(1)}let n=document.getElementById(t);if(n){n.scrollIntoView();return}}s(0)},l=!1,u=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;t&&z(L(t),o()),requestAnimationFrame(()=>{if(!l){if(n===`top`||!r){c();return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){s(R()[L(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&z(L(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function L(e){return`${e.name}:${B(e.params)}`}function R(){try{let e=sessionStorage.getItem(P);return e?JSON.parse(e):{}}catch{return{}}}function z(e,t){try{let n=R();n[e]=t,sessionStorage.setItem(P,JSON.stringify(n))}catch{}}function B(e){return JSON.stringify(e,V)}function V(e,t){if(typeof t==`object`&&t&&!Array.isArray(t)){let e={},n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}function H(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function U(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function W(e){return e?e.match(/\S+/g)??[]:[]}function G(e,t,n){if(e&&t){let e=W(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=W(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function K(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.is(r[e],i[e]))return!1;return!0}function q(e,t,n=!1,r=!0){let i=(0,o.createActiveRouteSource)(S(),e,t,{strict:n,ignoreQueryParams:r});return v(i.subscribe,i.getSnapshot,i.getSnapshot)}function J(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&K(e.routeParams,t.routeParams)&&K(e.routeOptions,t.routeOptions)}const Y=(0,i.memo)(({routeName:t,routeParams:n=E,routeOptions:r=D,className:i,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:l,target:u,children:d,...f})=>{let p=S(),m=q(t,n,s,c),h=(0,e.useMemo)(()=>U(p,t,n),[p,t,n]),g=(0,e.useCallback)(e=>{l&&(l(e),e.defaultPrevented)||!H(e)||u===`_blank`||(e.preventDefault(),p.navigate(t,n,r).catch(()=>{}))},[l,u,p,t,n,r]),_=(0,e.useMemo)(()=>G(m,o,i),[m,o,i]);return(0,a.jsx)(`a`,{...f,href:h,className:_,onClick:g,children:d})},J);Y.displayName=`Link`;function X({children:t,fallback:n,onError:i}){let s=(0,o.createDismissableError)(S()),c=v(s.subscribe,s.getSnapshot,s.getSnapshot),l=(0,e.useRef)(i);return l.current=i,(0,e.useEffect)(()=>{c.error&&l.current?.(c.error,c.toRoute,c.fromRoute)},[c.version]),(0,a.jsxs)(r.Fragment,{children:[t,c.error?n(c.error,c.resetError):null]})}const Z=()=>{let t=(0,e.useContext)(x);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},Q=()=>(0,n.getRouteUtils)((0,s.getPluginApi)(S()).getTree()),$=()=>{let t=(0,e.useContext)(y);if(!t)throw Error(`useRoute must be used within a RouteProvider`);return t};function ee(){let e=(0,o.getTransitionSource)(S());return v(e.subscribe,e.getSnapshot,e.getSnapshot)}const te=({router:n,children:r,announceNavigation:i,scrollRestoration:s})=>{(0,e.useEffect)(()=>{if(!i)return;let e=k(n);return()=>{e.destroy()}},[i,n]);let c=s?.mode,l=s?.anchorScrolling,u=s!==void 0;(0,e.useEffect)(()=>{if(!u)return;let e=I(n,{mode:c,anchorScrolling:l,scrollContainer:s.scrollContainer});return()=>{e.destroy()}},[n,u,c,l]);let d=(0,e.useMemo)(()=>(0,t.getNavigator)(n),[n]),f=(0,e.useMemo)(()=>(0,o.createRouteSource)(n),[n]),{route:p,previousRoute:m}=v(f.subscribe,f.getSnapshot,f.getSnapshot),h=(0,e.useMemo)(()=>({navigator:d,route:p,previousRoute:m}),[d,p,m]);return(0,a.jsx)(b.Provider,{value:n,children:(0,a.jsx)(x.Provider,{value:d,children:(0,a.jsx)(y.Provider,{value:h,children:r})})})};exports.Link=Y,exports.NavigatorContext=x,exports.RouteContext=y,exports.RouteView=T,exports.RouterContext=b,exports.RouterErrorBoundary=X,exports.RouterProvider=te,exports.useNavigator=Z,exports.useRoute=$,exports.useRouteNode=C,exports.useRouteUtils=Q,exports.useRouter=S,exports.useRouterTransition=ee;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`preact/hooks`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`preact`),i=require(`preact/compat`),a=require(`preact/jsx-runtime`),o=require(`@real-router/sources`),s=require(`@real-router/core/api`);function c(e){return null}c.displayName=`RouteView.Match`;function l(e){return null}l.displayName=`RouteView.Self`;function u(e){return null}u.displayName=`RouteView.NotFound`;function d(e,t,r){return t===``?!1:r?e===t:(0,n.startsWithSegment)(e,t)}function f(e,t){for(let n of(0,r.toChildArray)(e))(0,r.isValidElement)(n)&&(n.type===c||n.type===l||n.type===u?t.push(n):f(n.props.children,t))}function p(e,t,n){return(0,a.jsx)(r.Fragment,{children:n===void 0?e:(0,a.jsx)(i.Suspense,{fallback:n,children:e})},t)}function m(e,t){return e.type===u?(t.notFoundChildren=e.props.children,!0):e.type===l?(t.selfFound||=(t.selfChildren=e.props.children,t.selfFallback=e.props.fallback,!0),!0):!1}function h(e,t,n,r){let{segment:i,exact:a=!1,fallback:o}=e.props,s=n?`${n}.${i}`:i;return!r&&d(t,s,a)?p(e.props.children,s,o):null}function g(e,n,i,o){if(o.selfFound&&n===i){e.push(p(o.selfChildren,`__route-view-self__`,o.selfFallback));return}n===t.UNKNOWN_ROUTE&&o.notFoundChildren!==null&&e.push((0,a.jsx)(r.Fragment,{children:o.notFoundChildren},`__route-view-not-found__`))}function _(e,t,n){let r={selfChildren:null,selfFallback:void 0,selfFound:!1,notFoundChildren:null},i=!1,a=[];for(let o of e){if(m(o,r))continue;let e=h(o,t,n,i);e!==null&&(i=!0,a.push(e))}return i||g(a,t,n,r),{rendered:a,activeMatchFound:i}}function v(t,n,r){let[i,a]=(0,e.useState)(n);return(0,e.useEffect)(()=>{let e=()=>{a(e=>{let t=n();return Object.is(e,t)?e:t})};return e(),t(e)},[t,n]),i}const y=(0,r.createContext)(null),b=(0,r.createContext)(null),x=(0,r.createContext)(null),S=()=>{let t=(0,e.useContext)(b);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function C(n){let r=S(),i=(0,e.useMemo)(()=>(0,o.createRouteNodeSource)(r,n),[r,n]),{route:a,previousRoute:s}=v(i.subscribe,i.getSnapshot,i.getSnapshot),c=(0,e.useMemo)(()=>(0,t.getNavigator)(r),[r]);return(0,e.useMemo)(()=>({navigator:c,route:a,previousRoute:s}),[c,a,s])}function w({nodeName:t,children:n}){let{route:r}=C(t),i=(0,e.useMemo)(()=>{let e=[];return f(n,e),e},[n]);if(!r)return null;let{rendered:o}=_(i,r.name,t);return o.length>0?(0,a.jsx)(a.Fragment,{children:o}):null}w.displayName=`RouteView`;const T=Object.assign(w,{Match:c,Self:l,NotFound:u}),E=Object.freeze({}),D=Object.freeze({}),O=`data-real-router-announcer`;function k(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=A(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),N(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=M(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),j()}}}function A(){let e=document.querySelector(`[${O}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(O,``),document.body.prepend(t),t}function j(){document.querySelector(`[${O}]`)?.remove()}function M(e,t,n,r){if(n)return n(e);let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function N(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const P=`real-router:scroll`,F=Object.freeze({destroy:()=>{}});function ee(e,t){if(globalThis.window===void 0)return F;let n=t?.mode??`restore`;if(n===`manual`)return F;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let o=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},s=e=>{let t=i?.();t?t.scrollTop=e:globalThis.scrollTo(0,e)},c=()=>{let e=globalThis.location.hash;if(r&&e.length>1){let t;try{t=decodeURIComponent(e.slice(1))}catch{t=e.slice(1)}let n=document.getElementById(t);if(n){n.scrollIntoView();return}}s(0)},l=!1,u=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;t&&R(I(t),o()),requestAnimationFrame(()=>{if(!l){if(n===`top`||!r){c();return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){s(L()[I(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&R(I(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function I(e){return`${e.name}:${z(e.params)}`}function L(){try{let e=sessionStorage.getItem(P);return e?JSON.parse(e):{}}catch{return{}}}function R(e,t){try{let n=L();n[e]=t,sessionStorage.setItem(P,JSON.stringify(n))}catch{}}function z(e){return JSON.stringify(e,B)}function B(e,t){if(typeof t==`object`&&t&&!Array.isArray(t)){let e={},n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const V=Object.freeze({destroy:()=>{}});function H(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return V;let t=null,n=null,r=!1,i=()=>{t?.(),t=null},a=e.subscribeLeave(({signal:e})=>{if(!e.aborted)return r=!1,i(),new Promise(a=>{let o=new Promise(e=>{t=e});e.addEventListener(`abort`,()=>{r||(i(),n?.skipTransition?.(),a())},{once:!0});try{n=document.startViewTransition(()=>(a(),o))}catch{i(),a()}})}),o=e.subscribe(()=>{let e=t;r=!0,t=null,e===null?n=null:setTimeout(()=>{e(),n=null},0)});return{destroy:()=>{a(),o(),n?.skipTransition?.(),n=null,i()}}}function U(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function W(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function G(e){return e?e.match(/\S+/g)??[]:[]}function K(e,t,n){if(e&&t){let e=G(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=G(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function q(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.is(r[e],i[e]))return!1;return!0}function J(e,t,n=!1,r=!0){let i=(0,o.createActiveRouteSource)(S(),e,t,{strict:n,ignoreQueryParams:r});return v(i.subscribe,i.getSnapshot,i.getSnapshot)}function Y(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&q(e.routeParams,t.routeParams)&&q(e.routeOptions,t.routeOptions)}const X=(0,i.memo)(({routeName:t,routeParams:n=E,routeOptions:r=D,className:i,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:l,target:u,children:d,...f})=>{let p=S(),m=J(t,n,s,c),h=(0,e.useMemo)(()=>W(p,t,n),[p,t,n]),g=(0,e.useCallback)(e=>{l&&(l(e),e.defaultPrevented)||!U(e)||u===`_blank`||(e.preventDefault(),p.navigate(t,n,r).catch(()=>{}))},[l,u,p,t,n,r]),_=(0,e.useMemo)(()=>K(m,o,i),[m,o,i]);return(0,a.jsx)(`a`,{...f,href:h,className:_,onClick:g,children:d})},Y);X.displayName=`Link`;function Z({children:t,fallback:n,onError:i}){let s=(0,o.createDismissableError)(S()),c=v(s.subscribe,s.getSnapshot,s.getSnapshot),l=(0,e.useRef)(i);return l.current=i,(0,e.useEffect)(()=>{c.error&&l.current?.(c.error,c.toRoute,c.fromRoute)},[c.version]),(0,a.jsxs)(r.Fragment,{children:[t,c.error?n(c.error,c.resetError):null]})}const Q=()=>{let t=(0,e.useContext)(x);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},te=()=>(0,n.getRouteUtils)((0,s.getPluginApi)(S()).getTree()),$=()=>{let t=(0,e.useContext)(y);if(!t)throw Error(`useRoute must be used within a RouterProvider`);if(!t.route)throw Error(`useRoute called with no active route. Did you forget to await router.start() before rendering, or is the router stopped/disposed?`);return t};function ne(){let e=(0,o.getTransitionSource)(S());return v(e.subscribe,e.getSnapshot,e.getSnapshot)}function re(t,n){let r=S(),i=(0,e.useRef)(t),a=n?.skipSameRoute??!0;(0,e.useLayoutEffect)(()=>{i.current=t}),(0,e.useEffect)(()=>r.subscribeLeave(({route:e,nextRoute:t,signal:n})=>{if(!(a&&e.name===t.name)&&!n.aborted)return i.current({route:e,nextRoute:t,signal:n})}),[r,a])}function ie(t,n){let{route:r,previousRoute:i}=$(),a=(0,e.useRef)(t),o=(0,e.useRef)(null),s=n?.skipSameRoute??!0;(0,e.useLayoutEffect)(()=>{a.current=t}),(0,e.useEffect)(()=>{r.transition.from&&(s&&r.transition.from===r.name||o.current===r||!i||(o.current=r,a.current({route:r,previousRoute:i})))},[r,i,s])}const ae=({router:n,children:r,announceNavigation:i,scrollRestoration:s,viewTransitions:c})=>{(0,e.useEffect)(()=>{if(!i)return;let e=k(n);return()=>{e.destroy()}},[i,n]);let l=s?.mode,u=s?.anchorScrolling,d=s!==void 0;(0,e.useEffect)(()=>{if(!d)return;let e=ee(n,{mode:l,anchorScrolling:u,scrollContainer:s.scrollContainer});return()=>{e.destroy()}},[n,d,l,u]),(0,e.useEffect)(()=>{if(!c)return;let e=H(n);return()=>{e.destroy()}},[n,c]);let f=(0,e.useMemo)(()=>(0,t.getNavigator)(n),[n]),p=(0,e.useMemo)(()=>(0,o.createRouteSource)(n),[n]),{route:m,previousRoute:h}=v(p.subscribe,p.getSnapshot,p.getSnapshot),g=(0,e.useMemo)(()=>({navigator:f,route:m,previousRoute:h}),[f,m,h]);return(0,a.jsx)(b.Provider,{value:n,children:(0,a.jsx)(x.Provider,{value:f,children:(0,a.jsx)(y.Provider,{value:g,children:r})})})};exports.Link=X,exports.NavigatorContext=x,exports.RouteContext=y,exports.RouteView=T,exports.RouterContext=b,exports.RouterErrorBoundary=Z,exports.RouterProvider=ae,exports.useNavigator=Q,exports.useRoute=$,exports.useRouteEnter=ie,exports.useRouteExit=re,exports.useRouteNode=C,exports.useRouteUtils=te,exports.useRouter=S,exports.useRouterTransition=ne;
2
2
  //# sourceMappingURL=index.js.map