@real-router/preact 0.11.0 → 0.12.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.
Files changed (43) hide show
  1. package/README.md +139 -13
  2. package/dist/cjs/index.d.ts +20 -5
  3. package/dist/cjs/index.d.ts.map +1 -1
  4. package/dist/cjs/index.js +1 -1
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/ssr.d.ts +169 -0
  7. package/dist/cjs/ssr.d.ts.map +1 -0
  8. package/dist/cjs/ssr.js +2 -0
  9. package/dist/cjs/ssr.js.map +1 -0
  10. package/dist/cjs/useRoute-B3rj5MXo.js +2 -0
  11. package/dist/cjs/useRoute-B3rj5MXo.js.map +1 -0
  12. package/dist/esm/index.d.mts +20 -5
  13. package/dist/esm/index.d.mts.map +1 -1
  14. package/dist/esm/index.mjs +1 -1
  15. package/dist/esm/index.mjs.map +1 -1
  16. package/dist/esm/ssr.d.mts +169 -0
  17. package/dist/esm/ssr.d.mts.map +1 -0
  18. package/dist/esm/ssr.mjs +2 -0
  19. package/dist/esm/ssr.mjs.map +1 -0
  20. package/dist/esm/useRoute-BSPVVbLz.mjs +2 -0
  21. package/dist/esm/useRoute-BSPVVbLz.mjs.map +1 -0
  22. package/package.json +21 -4
  23. package/src/RouterProvider.tsx +15 -2
  24. package/src/components/Await.tsx +99 -0
  25. package/src/components/ClientOnly.tsx +25 -0
  26. package/src/components/HttpStatusCode.tsx +82 -0
  27. package/src/components/HttpStatusProvider.tsx +22 -0
  28. package/src/components/Link.tsx +53 -38
  29. package/src/components/RouteView/RouteView.tsx +12 -8
  30. package/src/components/RouteView/helpers.tsx +20 -19
  31. package/src/components/RouterErrorBoundary.tsx +28 -3
  32. package/src/components/ServerOnly.tsx +26 -0
  33. package/src/components/Streamed.tsx +24 -0
  34. package/src/context.ts +17 -0
  35. package/src/hooks/useDeferred.tsx +26 -0
  36. package/src/hooks/useIsActiveRoute.tsx +21 -13
  37. package/src/hooks/useNavigator.tsx +5 -12
  38. package/src/hooks/useRoute.tsx +7 -8
  39. package/src/hooks/useRouteNode.tsx +11 -7
  40. package/src/hooks/useRouter.tsx +5 -12
  41. package/src/ssr.ts +39 -0
  42. package/src/useSyncExternalStore.ts +20 -0
  43. package/src/utils/createHttpStatusSink.ts +27 -0
package/README.md CHANGED
@@ -10,9 +10,12 @@
10
10
  npm install @real-router/preact @real-router/core
11
11
  ```
12
12
 
13
- `@real-router/core` is the only hard dependency. Add `@real-router/browser-plugin`
14
- (or `hash-plugin` / `navigation-plugin` / `memory-plugin`) when you need History
15
- API integration the Quick Start below uses it.
13
+ `@real-router/core` is the entry-point dependency the API revolves around;
14
+ `@real-router/route-utils` and `@real-router/sources` are pulled in automatically
15
+ as transitive deps (used internally by `useRouteUtils` / hook subscriptions).
16
+ Add `@real-router/browser-plugin` (or `hash-plugin` / `navigation-plugin` /
17
+ `memory-plugin`) when you need History API integration — the Quick Start below
18
+ uses it.
16
19
 
17
20
  **Peer dependency:** `preact` >= 10.0.0
18
21
 
@@ -69,7 +72,7 @@ function App() {
69
72
  | `useRouteUtils()` | `RouteUtils` | Never |
70
73
  | `useRouterTransition()` | `{ isTransitioning, isLeaveApproved, toRoute, fromRoute }` | On transition start/end |
71
74
  | `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) |
75
+ | `useRouteEnter(handler, options?)` | `void` — fires on nav-driven mount via `useRoute()` snapshot | Every navigation (host component reads `useRoute()`); handler ref + subscription are stable across renders |
73
76
 
74
77
  ```tsx
75
78
  // useRouteNode — re-renders only when "users.*" changes
@@ -158,7 +161,7 @@ Tri-state: `undefined` preserves the current hash, `""` clears it, a value sets
158
161
 
159
162
  ### `<RouteView>`
160
163
 
161
- Declarative route matching. Renders the first matching `<RouteView.Match>` child.
164
+ Declarative route matching. Renders the first matching `<RouteView.Match>` child; falls back to `<RouteView.Self>` when the active route name equals `nodeName`, or `<RouteView.NotFound>` for `UNKNOWN_ROUTE`.
162
165
 
163
166
  ```tsx
164
167
  <RouteView nodeName="">
@@ -178,11 +181,44 @@ Declarative route matching. Renders the first matching `<RouteView.Match>` child
178
181
 
179
182
  #### `RouteView.Match` props
180
183
 
181
- | Prop | Type | Description |
182
- | ---------- | ------------------- | ----------------------------------------------------------------------------- |
183
- | `segment` | `string` | Route segment to match |
184
- | `exact` | `boolean` | When `true`, matches only the exact route (not descendants). Default: `false` |
185
- | `fallback` | `ComponentChildren` | Shown while children suspend. Wraps children in `<Suspense>` when provided. |
184
+ | Prop | Type | Required | Description |
185
+ | ---------- | ------------------- | -------- | ----------------------------------------------------------------------------- |
186
+ | `segment` | `string` | Yes | Route segment to match |
187
+ | `exact` | `boolean` | No | When `true`, matches only the exact route (not descendants). Default: `false` |
188
+ | `fallback` | `ComponentChildren` | No | Shown while children suspend. Wraps children in `<Suspense>` when provided. |
189
+ | `children` | `ComponentChildren` | Yes | Content to render when the active route matches `segment` |
190
+
191
+ #### `<RouteView.Self>` and `<RouteView.NotFound>`
192
+
193
+ Three fallback slots compose inside a `<RouteView nodeName="…">`:
194
+
195
+ | Element | Fires when | Props | Render position |
196
+ |--------------------------|---------------------------------------------------------|------------------------------------|---------------------------------|
197
+ | `<RouteView.Match>` | Active route segment matches `segment` (or descendant when `exact={false}`) | `segment` / `exact` / `fallback` / `children` | Inline at source position |
198
+ | `<RouteView.Self>` | Active route name **exactly equals** parent's `nodeName` | `fallback` / `children` | Appended after Match elements |
199
+ | `<RouteView.NotFound>` | Active route name is `UNKNOWN_ROUTE` AND no Match activated | `children` | Appended after Match elements |
200
+
201
+ Precedence:
202
+
203
+ 1. `<Match>` first-wins — duplicate segments short-circuit; subsequent `<Match>` with the same segment are not rendered.
204
+ 2. `<Self>` first-wins — only the first `<RouteView.Self>` contributes; subsequent ones are ignored.
205
+ 3. `<NotFound>` **last-wins** — when multiple `<RouteView.NotFound>` siblings are declared (unusual but legal), only the *last* one renders. Asymmetric with the other two slots; prefer a single `<NotFound>` per RouteView.
206
+ 4. An activating `<Match>` suppresses both `<Self>` and `<NotFound>`.
207
+ 5. When no `<Match>` activates: `<Self>` wins over `<NotFound>` if both would fire (occurs only when `nodeName === UNKNOWN_ROUTE`, narrow edge case).
208
+
209
+ ```tsx
210
+ <RouteView nodeName="users">
211
+ <RouteView.Self>
212
+ <UsersIndex /> {/* route name === "users" → renders */}
213
+ </RouteView.Self>
214
+ <RouteView.Match segment="profile">
215
+ <UserProfile /> {/* "users.profile" and descendants → renders */}
216
+ </RouteView.Match>
217
+ <RouteView.NotFound>
218
+ <NotFoundPage /> {/* UNKNOWN_ROUTE → renders */}
219
+ </RouteView.NotFound>
220
+ </RouteView>
221
+ ```
186
222
 
187
223
  #### Lazy loading with `fallback` (experimental)
188
224
 
@@ -212,6 +248,7 @@ import {
212
248
  RouteContext, // { navigator, route, previousRoute }
213
249
  type RouteViewProps,
214
250
  type RouteViewMatchProps,
251
+ type RouteViewSelfProps,
215
252
  type RouteViewNotFoundProps,
216
253
  } from "@real-router/preact";
217
254
  ```
@@ -245,6 +282,87 @@ import { RouterErrorBoundary } from "@real-router/preact";
245
282
 
246
283
  Auto-resets on next successful navigation. Works with both `<Link>` and imperative `router.navigate()`.
247
284
 
285
+ ## SSR-feature surface — `@real-router/preact/ssr`
286
+
287
+ All SSR-aware components, hooks, and utilities live at the `/ssr` subpath — mirror of `@real-router/react/ssr` (same exports, same API). Eight exports total: `<ClientOnly>`, `<ServerOnly>`, `<Streamed>`, `<Await>`, `<HttpStatusCode>`, `<HttpStatusProvider>`, `useDeferred`, `createHttpStatusSink`.
288
+
289
+ ### `<ClientOnly>` / `<ServerOnly>`
290
+
291
+ Paired SSR-aware boundaries. `<ClientOnly>` renders `fallback` on the server (and on the client first paint, to match SSR HTML), then swaps in `children` after mount. `<ServerOnly>` is the symmetric inverse.
292
+
293
+ ```tsx
294
+ import { ClientOnly, ServerOnly } from "@real-router/preact/ssr";
295
+
296
+ <ClientOnly fallback={<Skeleton />}>
297
+ <BrowserApiWidget />
298
+ </ClientOnly>
299
+
300
+ <ServerOnly>
301
+ <SeoMetaStrip />
302
+ </ServerOnly>;
303
+ ```
304
+
305
+ Implementation: `useState(false)` + `useEffect(() => setMounted(true), [])` from `preact/hooks`. End-to-end dogfooding lives in [`examples/web/preact/ssr-examples/ssr/`](../../examples/web/preact/ssr-examples/ssr/) (see `e2e/ssr-boundaries.spec.ts`).
306
+
307
+ ### `<Streamed>` / `<Await>` / `useDeferred`
308
+
309
+ Three pieces of the deferred-data pipeline (paired with [`@real-router/ssr-data-plugin`](https://www.npmjs.com/package/@real-router/ssr-data-plugin)'s `defer()` API). `<Streamed>` is a cross-adapter alias for Preact's `<Suspense>` (from `preact/compat`). `<Await<T> name="key">` reads the deferred promise the loader published under that key and hands the resolved value to a render-prop via Preact's Suspense-throwing convention. `useDeferred<T>(key)` returns the same promise for callers composing with a third-party Suspense-aware lib.
310
+
311
+ ```tsx
312
+ import { Streamed, Await, useDeferred } from "@real-router/preact/ssr";
313
+
314
+ <Streamed fallback={<Spinner />}>
315
+ <Await<Review[]> name="reviews">
316
+ {(reviews) => <ReviewList items={reviews} />}
317
+ </Await>
318
+ </Streamed>;
319
+ ```
320
+
321
+ End-to-end example: [`examples/web/preact/ssr-examples/ssr-streaming/`](../../examples/web/preact/ssr-examples/ssr-streaming/).
322
+
323
+ ### `<HttpStatusCode>` / `<HttpStatusProvider>` / `createHttpStatusSink`
324
+
325
+ Render-time HTTP status declaration for SSR responses. Mount `<HttpStatusCode code={N} />` inside a route component (typical use: a `<RouteView.NotFound>` glob page) — it writes `N` to the nearest `<HttpStatusProvider>`'s sink during render and returns `null`. After `renderToString`, read `sink.code` and pass it to your response.
326
+
327
+ ```tsx
328
+ // app.tsx
329
+ import { HttpStatusCode } from "@real-router/preact/ssr";
330
+
331
+ function NotFound() {
332
+ return (
333
+ <>
334
+ <HttpStatusCode code={404} />
335
+ <h1>Page not found</h1>
336
+ </>
337
+ );
338
+ }
339
+
340
+ // entry-server.tsx
341
+ import { renderToString } from "preact-render-to-string";
342
+ import {
343
+ HttpStatusProvider,
344
+ createHttpStatusSink,
345
+ } from "@real-router/preact/ssr";
346
+
347
+ const sink = createHttpStatusSink();
348
+ const html = renderToString(
349
+ <HttpStatusProvider sink={sink}>
350
+ <RouterProvider router={router}>
351
+ <App />
352
+ </RouterProvider>
353
+ </HttpStatusProvider>,
354
+ );
355
+ response.status(sink.code ?? 200).send(html);
356
+ ```
357
+
358
+ | Export | Kind | Purpose |
359
+ | ------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
360
+ | `<HttpStatusCode code={N}/>` | component | Writes `code` to the optional context sink during render. Last write wins across multiple instances. No-op without a provider. |
361
+ | `<HttpStatusProvider sink={…}>` | component | Supplies an `HttpStatusSink` to descendant `<HttpStatusCode />` via Preact context. |
362
+ | `createHttpStatusSink()` | utility | Returns a fresh `{ code: number \| undefined }` sink — construct one per request on the server, read `sink.code` after rendering. |
363
+
364
+ Loader-driven errors (`LoaderNotFound` → 404, `LoaderRedirect` → 30x) keep working as before; this component covers render-time decisions only.
365
+
248
366
  ## Accessibility
249
367
 
250
368
  Enable screen reader announcements for route changes:
@@ -267,7 +385,7 @@ Opt-in preservation of scroll position across navigations:
267
385
  </RouterProvider>
268
386
  ```
269
387
 
270
- Restores scroll on back/forward, scrolls to top (or `#hash`) on push. Three modes: `"restore"` (default), `"top"`, `"native"`. 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.
388
+ Restores scroll on back/forward, scrolls to top (or `#hash`) on push. Three modes: `"restore"` (default), `"top"`, `"native"`. Custom containers via `scrollContainer: () => HTMLElement | null`. Override the `sessionStorage` key via `storageKey` (default `"real-router:scroll"`) when isolating multiple routers on one origin. 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.
271
389
 
272
390
  ## View Transitions
273
391
 
@@ -290,9 +408,17 @@ Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
290
408
 
291
409
  ## Examples
292
410
 
293
- 11 runnable examples — each is a standalone Vite app. Run: `cd examples/web/preact/basic && pnpm dev`
411
+ 20 runnable examples — each is a standalone Vite app. Run: `cd examples/web/preact/basic && pnpm dev`
412
+
413
+ **Routing fundamentals:** [basic](../../examples/web/preact/basic) · [nested-routes](../../examples/web/preact/nested-routes) · [dynamic-routes](../../examples/web/preact/dynamic-routes) · [combined](../../examples/web/preact/combined)
414
+
415
+ **Data & guards:** [auth-guards](../../examples/web/preact/auth-guards) · [async-guards](../../examples/web/preact/async-guards) · [data-loading](../../examples/web/preact/data-loading) · [lazy-loading](../../examples/web/preact/lazy-loading) · [error-handling](../../examples/web/preact/error-handling)
416
+
417
+ **URL features:** [hash-routing](../../examples/web/preact/hash-routing) · [persistent-params](../../examples/web/preact/persistent-params) · [search-schema](../../examples/web/preact/search-schema)
418
+
419
+ **Animations:** [motion-animations](../../examples/web/preact/animation-examples/motion-animations) · [page-animations](../../examples/web/preact/animation-examples/page-animations) · [route-animations](../../examples/web/preact/animation-examples/route-animations) · [view-transitions](../../examples/web/preact/animation-examples/view-transitions)
294
420
 
295
- [basic](../../examples/web/preact/basic) · [nested-routes](../../examples/web/preact/nested-routes) · [auth-guards](../../examples/web/preact/auth-guards) · [data-loading](../../examples/web/preact/data-loading) · [lazy-loading](../../examples/web/preact/lazy-loading) · [async-guards](../../examples/web/preact/async-guards) · [hash-routing](../../examples/web/preact/hash-routing) · [persistent-params](../../examples/web/preact/persistent-params) · [error-handling](../../examples/web/preact/error-handling) · [dynamic-routes](../../examples/web/preact/dynamic-routes) · [combined](../../examples/web/preact/combined)
421
+ **SSR:** [ssg](../../examples/web/preact/ssr-examples/ssg) · [ssr](../../examples/web/preact/ssr-examples/ssr) · [ssr-mixed](../../examples/web/preact/ssr-examples/ssr-mixed) · [ssr-streaming](../../examples/web/preact/ssr-examples/ssr-streaming)
296
422
 
297
423
  ## Related Packages
298
424
 
@@ -1,5 +1,4 @@
1
- import * as _$preact from "preact";
2
- import { ComponentChildren, FunctionComponent, JSX, VNode } from "preact";
1
+ import { ComponentChildren, Context, FunctionComponent, JSX, VNode } from "preact";
3
2
  import { NavigationOptions, Navigator, Navigator as Navigator$1, Params, Router, RouterError, State } from "@real-router/core";
4
3
  import { RouteUtils } from "@real-router/route-utils";
5
4
  import { RouterTransitionSnapshot, RouterTransitionSnapshot as RouterTransitionSnapshot$1 } from "@real-router/sources";
@@ -91,6 +90,22 @@ interface RouterErrorBoundaryProps {
91
90
  readonly fallback: (error: RouterError, resetError: () => void) => ComponentChildren;
92
91
  readonly onError?: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
93
92
  }
93
+ /**
94
+ * Declarative navigation-error boundary.
95
+ *
96
+ * **Not** a Preact `componentDidCatch`-style ErrorBoundary — this component
97
+ * does NOT catch render-time exceptions from `children`. It is a compositional
98
+ * component that subscribes to `createDismissableError` from
99
+ * `@real-router/sources` and renders `fallback(error, resetError)` ALONGSIDE
100
+ * `children` (wrapped in a `<Fragment>`) when the router emits a navigation
101
+ * error (guard rejection, ROUTE_NOT_FOUND, etc.). The boundary auto-resets on
102
+ * the next successful navigation; `resetError()` lets the consumer dismiss
103
+ * the fallback imperatively.
104
+ *
105
+ * For real exception boundaries, wrap children in a Preact ErrorBoundary
106
+ * (e.g. `preact-iso/ErrorBoundary` or a custom `componentDidCatch` class) —
107
+ * the two can coexist.
108
+ */
94
109
  declare function RouterErrorBoundary({
95
110
  children,
96
111
  fallback,
@@ -368,9 +383,9 @@ interface RouteProviderProps {
368
383
  declare const RouterProvider: FunctionComponent<RouteProviderProps>;
369
384
  //#endregion
370
385
  //#region src/context.d.ts
371
- declare const RouteContext: _$preact.Context<RouteContext$1 | null>;
372
- declare const RouterContext: _$preact.Context<Router<object> | null>;
373
- declare const NavigatorContext: _$preact.Context<Navigator$1 | null>;
386
+ declare const RouteContext: Context<RouteContext$1 | null>;
387
+ declare const RouterContext: Context<Router<object> | null>;
388
+ declare const NavigatorContext: Context<Navigator$1 | null>;
374
389
  //#endregion
375
390
  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 };
376
391
  //# 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","../../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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"}
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),M(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=ee(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 ee(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 M(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const N=Object.freeze({destroy:()=>{}});function P(e,t){if(globalThis.window===void 0)return N;let n=t?.mode??`restore`;if(n===`native`)return N;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s=()=>{try{let e=sessionStorage.getItem(o);return e?JSON.parse(e):{}}catch{return{}}},c=(e,t)=>{try{let n=s();n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},l=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let u=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},d=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},f=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}d(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}d(0)},p=!1,m=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;t&&c(F(t),u()),requestAnimationFrame(()=>{if(!p){if(n===`top`||!r){f(e);return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){d(s()[F(e)]??0);return}f(e)}}})}),h=()=>{let t=e.getState();t&&c(F(t),u())};return globalThis.addEventListener(`pagehide`,h),{destroy:()=>{if(!p){p=!0,m(),globalThis.removeEventListener(`pagehide`,h);try{history.scrollRestoration=l}catch{}}}}}function F(e){return`${e.name}:${I(e.params)}`}function I(e){return JSON.stringify(e,L)}function L(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 R=Object.freeze({destroy:()=>{}});function z(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return R;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 B(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function V(e){return encodeURI(e).replaceAll(`#`,`%23`)}function H(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(e!==void 0)return e}let s=e.buildPath(t,n);return a?`${s}#${V(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function U(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&K(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}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,i){let a=(0,o.createActiveRouteSource)(S(),e,t,i===void 0?{strict:n,ignoreQueryParams:r}:{strict:n,ignoreQueryParams:r,hash:i});return v(a.subscribe,a.getSnapshot,a.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&&e.hash===t.hash&&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,hash:l,onClick:u,target:d,children:f,...p})=>{let m=S(),h=q(t,n,s,c,l),g=(0,e.useMemo)(()=>H(m,t,n,l===void 0?void 0:{hash:l}),[m,t,n,l]),_=(0,e.useCallback)(e=>{u&&(u(e),e.defaultPrevented)||!B(e)||d===`_blank`||(e.preventDefault(),U(m,t,n,l,r).catch(()=>{}))},[u,d,m,t,n,r,l]),v=(0,e.useMemo)(()=>G(h,o,i),[h,o,i]);return(0,a.jsx)(`a`,{...p,href:g,className:v,onClick:_,children:f})},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 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 te(){let e=(0,o.getTransitionSource)(S());return v(e.subscribe,e.getSnapshot,e.getSnapshot)}function ne(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 re(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 ie=({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?.behavior,f=s?.storageKey,p=s!==void 0;(0,e.useEffect)(()=>{if(!p)return;let e=P(n,{mode:l,anchorScrolling:u,behavior:d,storageKey:f,scrollContainer:s.scrollContainer});return()=>{e.destroy()}},[n,p,l,u,d,f]),(0,e.useEffect)(()=>{if(!c)return;let e=z(n);return()=>{e.destroy()}},[n,c]);let m=(0,e.useMemo)(()=>(0,t.getNavigator)(n),[n]),h=(0,e.useMemo)(()=>(0,o.createRouteSource)(n),[n]),{route:g,previousRoute:_}=v(h.subscribe,h.getSnapshot,h.getSnapshot),S=(0,e.useMemo)(()=>({navigator:m,route:g,previousRoute:_}),[m,g,_]);return(0,a.jsx)(b.Provider,{value:n,children:(0,a.jsx)(x.Provider,{value:m,children:(0,a.jsx)(y.Provider,{value:S,children:r})})})};exports.Link=Y,exports.NavigatorContext=x,exports.RouteContext=y,exports.RouteView=T,exports.RouterContext=b,exports.RouterErrorBoundary=X,exports.RouterProvider=ie,exports.useNavigator=Z,exports.useRoute=$,exports.useRouteEnter=re,exports.useRouteExit=ne,exports.useRouteNode=C,exports.useRouteUtils=Q,exports.useRouter=S,exports.useRouterTransition=te;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./useRoute-B3rj5MXo.js`);let t=require(`preact/hooks`),n=require(`@real-router/core`),r=require(`@real-router/route-utils`),i=require(`preact`),a=require(`preact/compat`),o=require(`preact/jsx-runtime`),s=require(`@real-router/sources`),c=require(`@real-router/core/api`);function l(e){return null}l.displayName=`RouteView.Match`;function u(e){return null}u.displayName=`RouteView.Self`;function d(e){return null}d.displayName=`RouteView.NotFound`;function f(e,t,n){return t===``?!1:n?e===t:(0,r.startsWithSegment)(e,t)}function p(e,t){for(let n of(0,i.toChildArray)(e))(0,i.isValidElement)(n)&&(n.type===l||n.type===u||n.type===d?t.push(n):p(n.props.children,t))}function m(e,t,n){return(0,o.jsx)(i.Fragment,{children:n===void 0?e:(0,o.jsx)(a.Suspense,{fallback:n,children:e})},t)}function h(e){return e.type===d||e.type===u}function g(e,t){if(e.type===d){t.notFoundChildren=e.props.children;return}t.selfFound||=(t.selfChildren=e.props.children,t.selfFallback=e.props.fallback,!0)}function _(e,t,n,r){let{segment:i,exact:a=!1,fallback:o,children:s}=e.props,c=n?`${n}.${i}`:i;return!r&&f(t,c,a)?m(s,c,o):null}function v(e,t,r,a){if(a.selfFound&&t===r){e.push(m(a.selfChildren,`__route-view-self__`,a.selfFallback));return}t===n.UNKNOWN_ROUTE&&a.notFoundChildren!==null&&e.push((0,o.jsx)(i.Fragment,{children:a.notFoundChildren},`__route-view-not-found__`))}function y(e,t,n){let r={selfChildren:null,selfFallback:void 0,selfFound:!1,notFoundChildren:null},i=!1,a=[];for(let o of e){if(h(o)){g(o,r);continue}let e=_(o,t,n,i);e!==null&&(i=!0,a.push(e))}return i||v(a,t,n,r),{rendered:a,activeMatchFound:i}}function b(e,n,r){let[i,a]=(0,t.useState)(n);return(0,t.useEffect)(()=>{let t=()=>{a(e=>{let t=n();return Object.is(e,t)?e:t})};return t(),e(t)},[e,n]),i}const x=e.a(e.n,`useNavigator`),S=e.a(e.i,`useRouter`);function C(e){let n=S(),r=x(),i=(0,s.createRouteNodeSource)(n,e),{route:a,previousRoute:o}=b(i.subscribe,i.getSnapshot,i.getSnapshot);return(0,t.useMemo)(()=>({navigator:r,route:a,previousRoute:o}),[r,a,o])}function w({nodeName:e,children:n}){let{route:r}=C(e),i=(0,t.useMemo)(()=>{let e=[];return p(n,e),e},[n]),a=r?.name,s=(0,t.useMemo)(()=>a===void 0?[]:y(i,a,e).rendered,[i,a,e]);return s.length>0?(0,o.jsx)(o.Fragment,{children:s}):null}w.displayName=`RouteView`;const T=Object.assign(w,{Match:l,Self:u,NotFound:d}),E=Object.freeze({}),D=Object.freeze({}),O=`data-real-router-announcer`,k=Object.freeze({destroy:()=>{}});function ee(e,t){if(typeof document>`u`)return k;let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=te(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),M(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=j(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),A()}}}function te(){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??document.documentElement).prepend(t),t}function A(){document.querySelector(`[${O}]`)?.remove()}function j(e,t,n,r){if(n)try{let t=n(e);if(t)return t}catch(e){console.error(`[real-router] getAnnouncementText threw; falling back to default resolution.`,e)}let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function M(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const N=Object.freeze({destroy:()=>{}});function P(e,t){if(globalThis.window===void 0)return N;let n=t?.mode??`restore`;if(n===`native`)return N;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s,c=()=>{if(s!==void 0)return s;try{let e=sessionStorage.getItem(o);s=e?JSON.parse(e):{}}catch{s={}}return s},l=(e,t)=>{try{let n=c();if(n[e]===t)return;n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},u=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let d=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},f=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},p=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}f(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}f(0)},m=!1,h=!1,g=e=>{try{return I(e)}catch{return h||(h=!0,console.error(`[real-router] scroll-restore: route "${e.name}" has params that cannot be canonicalized (e.g. BigInt or cyclic structure). Scroll position will not be captured or restored for this route.`)),null}},_=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;if(t){let e=g(t);e!==null&&l(e,d())}requestAnimationFrame(()=>{if(!m){if(n===`top`||!r){p(e);return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){let t=g(e);f(t===null?0:c()[t]??0);return}p(e)}}})}),v=()=>{let t=e.getState();if(t){let e=g(t);e!==null&&l(e,d())}};return globalThis.addEventListener(`pagehide`,v),{destroy:()=>{if(!m){m=!0,_(),globalThis.removeEventListener(`pagehide`,v);try{history.scrollRestoration=u}catch{}}}}}const F=new WeakMap;function I(e){let t=F.get(e);if(t!==void 0)return t;let n=`${e.name}:${L(e.params)}`;return F.set(e,n),n}function L(e){return JSON.stringify(e,R)}function R(e,t){if(typeof t==`function`)return`<fn>`;if(typeof t==`symbol`)return`<sym>`;if(typeof t==`object`&&t&&!Array.isArray(t)){let e=Object.create(null),n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const z=Object.freeze({destroy:()=>{}});function B(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return z;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 V(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}const H=/%[\dA-Fa-f]{2}/;function U(e){if(H.test(e))try{return encodeURI(decodeURIComponent(e)).replaceAll(`#`,`%23`)}catch{}return encodeURI(e).replaceAll(`#`,`%23`)}function W(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(typeof e==`string`&&e.length>0)return e}let s=e.buildPath(t,n);if(typeof s!=`string`||s.length===0){console.error(`[real-router] Route "${t}" yielded an empty path. The element will render without an href attribute.`);return}return a?`${s}#${U(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function G(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&X(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}const K=/\s/,q=/\S+/g;function J(e){return e?K.test(e)?e.match(q)??[]:[e]:[]}function Y(e,t,n){if(e&&t){let e=J(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=J(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 X(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.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],i[e]))return!1;return!0}function Z(e,n,r=!1,i=!0,a){let o=S(),c=(0,t.useMemo)(()=>a===void 0?{strict:r,ignoreQueryParams:i}:{strict:r,ignoreQueryParams:i,hash:a},[r,i,a]),l=(0,t.useMemo)(()=>(0,s.createActiveRouteSource)(o,e,n,c),[o,e,n,c]);return b(l.subscribe,l.getSnapshot,l.getSnapshot)}function ne(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&&e.hash===t.hash&&X(e.routeParams,t.routeParams)&&X(e.routeOptions,t.routeOptions)}const Q=(0,a.memo)(({routeName:e,routeParams:t=E,routeOptions:n=D,className:r,activeClassName:i=`active`,activeStrict:a=!1,ignoreQueryParams:s=!0,hash:c,onClick:l,target:u,children:d,...f})=>{let p=S(),m=Z(e,t,a,s,c),h=W(p,e,t,c===void 0?void 0:{hash:c}),g=r=>{l&&(l(r),r.defaultPrevented)||!V(r)||u===`_blank`||(r.preventDefault(),G(p,e,t,c,n).catch(()=>{}))},_=Y(m,i,r);return(0,o.jsx)(`a`,{...f,href:h,className:_,onClick:g,children:d})},ne);Q.displayName=`Link`;function re({children:e,fallback:n,onError:r}){let a=(0,s.createDismissableError)(S()),c=b(a.subscribe,a.getSnapshot,a.getSnapshot),l=(0,t.useRef)(r);return(0,t.useLayoutEffect)(()=>{l.current=r}),(0,t.useEffect)(()=>{c.error&&l.current?.(c.error,c.toRoute,c.fromRoute)},[c.version]),(0,o.jsxs)(i.Fragment,{children:[e,c.error?n(c.error,c.resetError):null]})}const $=()=>(0,r.getRouteUtils)((0,c.getPluginApi)(S()).getTree());function ie(){let e=(0,s.getTransitionSource)(S());return b(e.subscribe,e.getSnapshot,e.getSnapshot)}function ae(e,n){let r=S(),i=(0,t.useRef)(e),a=n?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{i.current=e}),(0,t.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 oe(n,r){let{route:i,previousRoute:a}=e.t(),o=(0,t.useRef)(n),s=(0,t.useRef)(null),c=r?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{o.current=n}),(0,t.useEffect)(()=>{i.transition.from&&(c&&i.transition.from===i.name||s.current===i||!a||(s.current=i,o.current({route:i,previousRoute:a})))},[i,a,c])}const se=({router:r,children:i,announceNavigation:a,scrollRestoration:c,viewTransitions:l})=>{(0,t.useEffect)(()=>{if(!a)return;let e=ee(r);return()=>{e.destroy()}},[a,r]);let u=c?.mode,d=c?.anchorScrolling,f=c?.behavior,p=c?.storageKey,m=c!==void 0;(0,t.useEffect)(()=>{if(!m)return;let e=P(r,{mode:u,anchorScrolling:d,behavior:f,storageKey:p,scrollContainer:c.scrollContainer});return()=>{e.destroy()}},[r,m,u,d,f,p]),(0,t.useEffect)(()=>{if(!l)return;let e=B(r);return()=>{e.destroy()}},[r,l]);let h=(0,n.getNavigator)(r),g=(0,t.useMemo)(()=>(0,s.createRouteSource)(r),[r]),{route:_,previousRoute:v}=b(g.subscribe,g.getSnapshot,g.getSnapshot),y=(0,t.useMemo)(()=>({navigator:h,route:_,previousRoute:v}),[h,_,v]);return(0,o.jsx)(e.i.Provider,{value:r,children:(0,o.jsx)(e.n.Provider,{value:h,children:(0,o.jsx)(e.r.Provider,{value:y,children:i})})})};exports.Link=Q,exports.NavigatorContext=e.n,exports.RouteContext=e.r,exports.RouteView=T,exports.RouterContext=e.i,exports.RouterErrorBoundary=re,exports.RouterProvider=se,exports.useNavigator=x,exports.useRoute=e.t,exports.useRouteEnter=oe,exports.useRouteExit=ae,exports.useRouteNode=C,exports.useRouteUtils=$,exports.useRouter=S,exports.useRouterTransition=ie;
2
2
  //# sourceMappingURL=index.js.map