@real-router/preact 0.7.0 → 0.8.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
 
@@ -105,6 +105,217 @@ declare function useRouteNode(nodeName: string): RouteContext$1;
105
105
  //#region src/hooks/useRouterTransition.d.ts
106
106
  declare function useRouterTransition(): RouterTransitionSnapshot$1;
107
107
  //#endregion
108
+ //#region src/hooks/useRouteExit.d.ts
109
+ interface RouteExitContext {
110
+ /** The route being left. */
111
+ route: State;
112
+ /** The route being navigated to. */
113
+ nextRoute: State;
114
+ /**
115
+ * AbortSignal that fires when this navigation is superseded by a later
116
+ * one (rapid clicks). Already filtered: when the handler runs,
117
+ * `signal.aborted` is guaranteed to be `false`. Use
118
+ * `signal.addEventListener("abort", cleanup, { once: true })` for
119
+ * cleanup that must run on cancellation.
120
+ */
121
+ signal: AbortSignal;
122
+ }
123
+ interface UseRouteExitOptions {
124
+ /**
125
+ * Skip the handler when `route.name === nextRoute.name`
126
+ * (sort/filter/query-only navigations on the same route). Default:
127
+ * `true`.
128
+ */
129
+ skipSameRoute?: boolean;
130
+ }
131
+ type RouteExitHandler = (context: RouteExitContext) => void | Promise<void>;
132
+ /**
133
+ * Subscribe to the router's leave-window with the universal guards baked
134
+ * in. Wraps `router.subscribeLeave` so consumers don't repeat the same
135
+ * boilerplate every time:
136
+ *
137
+ * - **Reentrant abort pre-check**: if `signal.aborted` is already `true`
138
+ * when the handler would run (rapid navigation superseded a slower
139
+ * one), the handler is skipped entirely. `signal.addEventListener(
140
+ * "abort", ...)` does not fire retroactively, so without this guard
141
+ * downstream cleanup would never trigger.
142
+ * - **Same-route skip**: by default, `route.name === nextRoute.name`
143
+ * short-circuits the handler — query-only navigations (sort, filter,
144
+ * pagination) skip the work. Opt out with `skipSameRoute: false`.
145
+ * - **Stable handler reference**: the handler can change identity on
146
+ * every render without causing resubscription — internal ref keeps
147
+ * the latest handler accessible to the long-lived subscription.
148
+ *
149
+ * Returns nothing — the subscription's lifecycle is bound to the
150
+ * component's mount.
151
+ *
152
+ * If the handler returns a Promise, the router blocks on it. If the
153
+ * Promise resolves, navigation proceeds. If it rejects, the router emits
154
+ * `TRANSITION_CANCELLED` (existing core behavior, no change here).
155
+ *
156
+ * @example Animation
157
+ * ```tsx
158
+ * const ref = useRef<HTMLDivElement>(null);
159
+ *
160
+ * useRouteExit(async ({ signal }) => {
161
+ * const el = ref.current;
162
+ * if (!el) return;
163
+ * el.classList.add("fade-out");
164
+ * const cleanup = () => el.classList.remove("fade-out");
165
+ * signal.addEventListener("abort", cleanup, { once: true });
166
+ * try {
167
+ * el.getBoundingClientRect(); // style flush
168
+ * await Promise.allSettled(el.getAnimations().map((a) => a.finished));
169
+ * } finally {
170
+ * cleanup();
171
+ * }
172
+ * });
173
+ * ```
174
+ *
175
+ * @example Auto-save form draft
176
+ * ```tsx
177
+ * useRouteExit(async ({ signal }) => {
178
+ * if (formState.dirty) await api.saveDraft(formState, { signal });
179
+ * });
180
+ * ```
181
+ *
182
+ * @example Cancel inflight requests
183
+ * ```tsx
184
+ * useRouteExit(() => {
185
+ * inflightController.abort();
186
+ * });
187
+ * ```
188
+ *
189
+ * @example Library-coordinated exit (motion / framer-motion)
190
+ * ```tsx
191
+ * const exitResolverRef = useRef<(() => void) | null>(null);
192
+ *
193
+ * useRouteExit(({ signal }) => {
194
+ * return new Promise<void>((resolve) => {
195
+ * exitResolverRef.current = resolve;
196
+ * signal.addEventListener("abort", () => resolve(), { once: true });
197
+ * });
198
+ * });
199
+ *
200
+ * const onExitComplete = () => exitResolverRef.current?.();
201
+ * // pass onExitComplete to <AnimatePresence>
202
+ * ```
203
+ *
204
+ * @example Reading rich transition metadata via `nextRoute.transition`
205
+ * ```tsx
206
+ * useRouteExit(({ route, nextRoute }) => {
207
+ * // nextRoute.transition: TransitionMeta — preview of the upcoming nav
208
+ * if (nextRoute.transition.segments.deactivated.includes("products")) {
209
+ * // leaving the products subtree entirely — flush product-related caches
210
+ * productCache.clear();
211
+ * }
212
+ * if (nextRoute.transition.redirected) {
213
+ * // skip animation when navigation arrived via redirect
214
+ * return;
215
+ * }
216
+ * });
217
+ * ```
218
+ */
219
+ declare function useRouteExit(handler: RouteExitHandler, options?: UseRouteExitOptions): void;
220
+ //#endregion
221
+ //#region src/hooks/useRouteEnter.d.ts
222
+ interface RouteEnterContext {
223
+ /** The route that was just activated. */
224
+ route: State;
225
+ /** The route that was active immediately before this navigation. */
226
+ previousRoute: State;
227
+ }
228
+ type RouteEnterHandler = (context: RouteEnterContext) => void;
229
+ interface UseRouteEnterOptions {
230
+ /**
231
+ * Skip the handler when `route.name === previousRoute.name`
232
+ * (sort/filter/query-only navigations on the same route). Default:
233
+ * `true`. Symmetric with `useRouteExit`'s same-name option.
234
+ */
235
+ skipSameRoute?: boolean;
236
+ }
237
+ /**
238
+ * Fire `handler` once when the component mounts as a result of a
239
+ * navigation. Mirror of `useRouteExit` for the entry side.
240
+ *
241
+ * What this hook covers that ad-hoc `useEffect` + `useRoute()` doesn't:
242
+ *
243
+ * - **Skip-initial**: handler is skipped when there is no
244
+ * `previousRoute` (i.e. first-load mount). Most consumers want to
245
+ * fire side effects only on real navigations, not on hydration.
246
+ * - **Same-route skip** (default): handler is skipped when
247
+ * `route.name === previousRoute.name`. Sort/filter/query-only
248
+ * navigations re-run the effect (because `route` reference changes
249
+ * in `useRoute`'s snapshot), but they are not "entries" in the
250
+ * animation / analytics sense — the component instance has stayed
251
+ * mounted throughout. Opt out with `skipSameRoute: false` when
252
+ * the handler legitimately needs to fire on every navigation
253
+ * (e.g. analytics tracking each query-param flip).
254
+ * - **Latest-handler ref**: the handler can change identity on every
255
+ * render without re-running the effect — the registered wrapper
256
+ * dispatches to whatever `handlerRef.current` points to.
257
+ * - **Mount-time `route` / `previousRoute` snapshot**: the handler
258
+ * receives the values that were live at the moment of mount, not
259
+ * the latest ones (which may have moved on if the user navigated
260
+ * again before the effect drained).
261
+ *
262
+ * Race-safety: `useRoute()` is wired through `useSyncExternalStore` from
263
+ * `@real-router/sources` (Preact polyfill: useState + useEffect, same
264
+ * post-commit semantics), so by the time the new component's effect
265
+ * runs, the snapshot is the post-commit one. This is the reason we can
266
+ * read mount-time context from `useRoute()` instead of subscribing to
267
+ * `router.subscribe` directly (which fires before Preact schedules a
268
+ * re-render — the well-known race in distributed components).
269
+ *
270
+ * Note: Preact does not expose a `StrictMode` equivalent, so the
271
+ * `lastHandledRouteRef` guard exists primarily for defensive symmetry
272
+ * with the React implementation. It is harmless in Preact.
273
+ *
274
+ * @example Direction-aware entry animation
275
+ * ```tsx
276
+ * useRouteEnter(({ route }) => {
277
+ * const direction = route.context.browser?.direction;
278
+ * ref.current?.classList.add(
279
+ * direction === "back" ? "slide-from-left" : "slide-from-right",
280
+ * );
281
+ * });
282
+ * ```
283
+ *
284
+ * @example Source-aware focus management
285
+ * ```tsx
286
+ * useRouteEnter(({ route }) => {
287
+ * if (route.context.browser?.source === "navigate") {
288
+ * headingRef.current?.focus();
289
+ * }
290
+ * });
291
+ * ```
292
+ *
293
+ * @example Analytics page-enter event (skip-initial built-in)
294
+ * ```tsx
295
+ * useRouteEnter(({ route, previousRoute }) => {
296
+ * analytics.track("page_enter", {
297
+ * route: route.name,
298
+ * from: previousRoute.name,
299
+ * });
300
+ * });
301
+ * ```
302
+ *
303
+ * @example Reading rich transition metadata via `route.transition`
304
+ * ```tsx
305
+ * useRouteEnter(({ route }) => {
306
+ * // route.transition: TransitionMeta — populated by core for every state
307
+ * if (route.transition.redirected) {
308
+ * showToast(`Redirected from ${route.transition.from}`);
309
+ * }
310
+ * if (route.transition.segments.activated.includes("products")) {
311
+ * // products subtree just became active (could be products or
312
+ * // products.detail). Useful for subtree-scoped side effects.
313
+ * }
314
+ * });
315
+ * ```
316
+ */
317
+ declare function useRouteEnter(handler: RouteEnterHandler, options?: UseRouteEnterOptions): void;
318
+ //#endregion
108
319
  //#region ../../shared/dom-utils/scroll-restore.d.ts
109
320
  type ScrollRestorationMode = "restore" | "top" | "manual";
110
321
  interface ScrollRestorationOptions {
@@ -119,6 +330,7 @@ interface RouteProviderProps {
119
330
  children: ComponentChildren;
120
331
  announceNavigation?: boolean;
121
332
  scrollRestoration?: ScrollRestorationOptions;
333
+ viewTransitions?: boolean;
122
334
  }
123
335
  declare const RouterProvider: FunctionComponent<RouteProviderProps>;
124
336
  //#endregion
@@ -127,5 +339,5 @@ declare const RouteContext: _$preact.Context<RouteContext$1 | null>;
127
339
  declare const RouterContext: _$preact.Context<Router<object> | null>;
128
340
  declare const NavigatorContext: _$preact.Context<Navigator$1 | null>;
129
341
  //#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 };
342
+ 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
343
  //# 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 RouteProvider`);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&&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