@real-router/preact 0.6.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 +45 -4
- package/dist/cjs/index.d.ts +224 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.mts +224 -1
- package/dist/esm/index.d.mts.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/RouterProvider.tsx +20 -1
- package/src/components/RouteView/RouteView.tsx +8 -3
- package/src/components/RouteView/components.tsx +7 -1
- package/src/components/RouteView/helpers.tsx +111 -28
- package/src/components/RouteView/index.ts +1 -0
- package/src/components/RouteView/types.ts +7 -0
- package/src/hooks/useRouteEnter.tsx +155 -0
- package/src/hooks/useRouteExit.tsx +159 -0
- package/src/index.ts +17 -0
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,18 +260,30 @@ 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
|
|
|
243
|
-
11 runnable examples — each is a standalone Vite app. Run: `cd examples/preact/basic && pnpm dev`
|
|
284
|
+
11 runnable examples — each is a standalone Vite app. Run: `cd examples/web/preact/basic && pnpm dev`
|
|
244
285
|
|
|
245
|
-
[basic](../../examples/preact/basic) · [nested-routes](../../examples/preact/nested-routes) · [auth-guards](../../examples/preact/auth-guards) · [data-loading](../../examples/preact/data-loading) · [lazy-loading](../../examples/preact/lazy-loading) · [async-guards](../../examples/preact/async-guards) · [hash-routing](../../examples/preact/hash-routing) · [persistent-params](../../examples/preact/persistent-params) · [error-handling](../../examples/preact/error-handling) · [dynamic-routes](../../examples/preact/dynamic-routes) · [combined](../../examples/preact/combined)
|
|
286
|
+
[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)
|
|
246
287
|
|
|
247
288
|
## Related Packages
|
|
248
289
|
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ interface MatchProps {
|
|
|
15
15
|
readonly fallback?: ComponentChildren;
|
|
16
16
|
readonly children: ComponentChildren;
|
|
17
17
|
}
|
|
18
|
+
interface SelfProps {
|
|
19
|
+
/** Fallback content while children are suspended. */
|
|
20
|
+
readonly fallback?: ComponentChildren;
|
|
21
|
+
/** Content to render when the active route name equals the parent RouteView's nodeName. */
|
|
22
|
+
readonly children: ComponentChildren;
|
|
23
|
+
}
|
|
18
24
|
interface NotFoundProps {
|
|
19
25
|
readonly children: ComponentChildren;
|
|
20
26
|
}
|
|
@@ -24,6 +30,10 @@ declare function Match(_props: MatchProps): null;
|
|
|
24
30
|
declare namespace Match {
|
|
25
31
|
var displayName: string;
|
|
26
32
|
}
|
|
33
|
+
declare function Self(_props: SelfProps): null;
|
|
34
|
+
declare namespace Self {
|
|
35
|
+
var displayName: string;
|
|
36
|
+
}
|
|
27
37
|
declare function NotFound(_props: NotFoundProps): null;
|
|
28
38
|
declare namespace NotFound {
|
|
29
39
|
var displayName: string;
|
|
@@ -39,6 +49,7 @@ declare namespace RouteViewRoot {
|
|
|
39
49
|
}
|
|
40
50
|
declare const RouteView: typeof RouteViewRoot & {
|
|
41
51
|
Match: typeof Match;
|
|
52
|
+
Self: typeof Self;
|
|
42
53
|
NotFound: typeof NotFound;
|
|
43
54
|
};
|
|
44
55
|
//#endregion
|
|
@@ -94,6 +105,217 @@ declare function useRouteNode(nodeName: string): RouteContext$1;
|
|
|
94
105
|
//#region src/hooks/useRouterTransition.d.ts
|
|
95
106
|
declare function useRouterTransition(): RouterTransitionSnapshot$1;
|
|
96
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
|
|
97
319
|
//#region ../../shared/dom-utils/scroll-restore.d.ts
|
|
98
320
|
type ScrollRestorationMode = "restore" | "top" | "manual";
|
|
99
321
|
interface ScrollRestorationOptions {
|
|
@@ -108,6 +330,7 @@ interface RouteProviderProps {
|
|
|
108
330
|
children: ComponentChildren;
|
|
109
331
|
announceNavigation?: boolean;
|
|
110
332
|
scrollRestoration?: ScrollRestorationOptions;
|
|
333
|
+
viewTransitions?: boolean;
|
|
111
334
|
}
|
|
112
335
|
declare const RouterProvider: FunctionComponent<RouteProviderProps>;
|
|
113
336
|
//#endregion
|
|
@@ -116,5 +339,5 @@ declare const RouteContext: _$preact.Context<RouteContext$1 | null>;
|
|
|
116
339
|
declare const RouterContext: _$preact.Context<Router<object> | null>;
|
|
117
340
|
declare const NavigatorContext: _$preact.Context<Navigator$1 | null>;
|
|
118
341
|
//#endregion
|
|
119
|
-
export { Link, type LinkProps, type Navigator, NavigatorContext, RouteContext, RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps, 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 };
|
|
120
343
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -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,aAAA;EAAA,SACN,QAAA,EAAU,iBAAA;AAAA;;;
|
|
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.NotFound`;function u(e,t,r){return t===``?!1:r?e===t:(0,n.startsWithSegment)(e,t)}function d(e,t){for(let n of(0,r.toChildArray)(e))(0,r.isValidElement)(n)&&(n.type===c||n.type===l?t.push(n):d(n.props.children,t))}function f(e,n,o){let s=null,c=!1,d=[];for(let t of e){if(t.type===l){s=t.props.children;continue}let{segment:e,exact:f=!1,fallback:p}=t.props,m=o?`${o}.${e}`:e;if(!c&&u(n,m,f)){c=!0;let e=t.props.children,n=p===void 0?e:(0,a.jsx)(i.Suspense,{fallback:p,children:e});d.push((0,a.jsx)(r.Fragment,{children:n},m))}}return!c&&n===t.UNKNOWN_ROUTE&&s!==null&&d.push((0,a.jsx)(r.Fragment,{children:s},`__route-view-not-found__`)),{rendered:d,activeMatchFound:c}}function p(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 m=(0,r.createContext)(null),h=(0,r.createContext)(null),g=(0,r.createContext)(null),_=()=>{let t=(0,e.useContext)(h);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function v(n){let r=_(),i=(0,e.useMemo)(()=>(0,o.createRouteNodeSource)(r,n),[r,n]),{route:a,previousRoute:s}=p(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 y({nodeName:t,children:n}){let{route:r}=v(t),i=(0,e.useMemo)(()=>{let e=[];return d(n,e),e},[n]);if(!r)return null;let{rendered:o}=f(i,r.name,t);return o.length>0?(0,a.jsx)(a.Fragment,{children:o}):null}y.displayName=`RouteView`;const b=Object.assign(y,{Match:c,NotFound:l}),x=Object.freeze({}),S=Object.freeze({}),C=`data-real-router-announcer`;function w(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=T(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),O(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=D(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),E()}}}function T(){let e=document.querySelector(`[${C}]`);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(C,``),document.body.prepend(t),t}function E(){document.querySelector(`[${C}]`)?.remove()}function D(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 O(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const k=`real-router:scroll`,A=Object.freeze({destroy:()=>{}});function j(e,t){if(globalThis.window===void 0)return A;let n=t?.mode??`restore`;if(n===`manual`)return A;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&&P(M(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(N()[M(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&P(M(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function M(e){return`${e.name}:${F(e.params)}`}function N(){try{let e=sessionStorage.getItem(k);return e?JSON.parse(e):{}}catch{return{}}}function P(e,t){try{let n=N();n[e]=t,sessionStorage.setItem(k,JSON.stringify(n))}catch{}}function F(e){return JSON.stringify(e,I)}function I(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 L(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function R(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 z(e){return e?e.match(/\S+/g)??[]:[]}function B(e,t,n){if(e&&t){let e=z(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=z(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 V(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 H(e,t,n=!1,r=!0){let i=(0,o.createActiveRouteSource)(_(),e,t,{strict:n,ignoreQueryParams:r});return p(i.subscribe,i.getSnapshot,i.getSnapshot)}function U(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&&V(e.routeParams,t.routeParams)&&V(e.routeOptions,t.routeOptions)}const W=(0,i.memo)(({routeName:t,routeParams:n=x,routeOptions:r=S,className:i,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:l,target:u,children:d,...f})=>{let p=_(),m=H(t,n,s,c),h=(0,e.useMemo)(()=>R(p,t,n),[p,t,n]),g=(0,e.useCallback)(e=>{l&&(l(e),e.defaultPrevented)||!L(e)||u===`_blank`||(e.preventDefault(),p.navigate(t,n,r).catch(()=>{}))},[l,u,p,t,n,r]),v=(0,e.useMemo)(()=>B(m,o,i),[m,o,i]);return(0,a.jsx)(`a`,{...f,href:h,className:v,onClick:g,children:d})},U);W.displayName=`Link`;function G({children:t,fallback:n,onError:i}){let s=(0,o.createDismissableError)(_()),c=p(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 K=()=>{let t=(0,e.useContext)(g);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},q=()=>(0,n.getRouteUtils)((0,s.getPluginApi)(_()).getTree()),J=()=>{let t=(0,e.useContext)(m);if(!t)throw Error(`useRoute must be used within a RouteProvider`);return t};function Y(){let e=(0,o.getTransitionSource)(_());return p(e.subscribe,e.getSnapshot,e.getSnapshot)}const X=({router:n,children:r,announceNavigation:i,scrollRestoration:s})=>{(0,e.useEffect)(()=>{if(!i)return;let e=w(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=j(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:_,previousRoute:v}=p(f.subscribe,f.getSnapshot,f.getSnapshot),y=(0,e.useMemo)(()=>({navigator:d,route:_,previousRoute:v}),[d,_,v]);return(0,a.jsx)(h.Provider,{value:n,children:(0,a.jsx)(g.Provider,{value:d,children:(0,a.jsx)(m.Provider,{value:y,children:r})})})};exports.Link=W,exports.NavigatorContext=g,exports.RouteContext=m,exports.RouteView=b,exports.RouterContext=h,exports.RouterErrorBoundary=G,exports.RouterProvider=X,exports.useNavigator=K,exports.useRoute=J,exports.useRouteNode=v,exports.useRouteUtils=q,exports.useRouter=_,exports.useRouterTransition=Y;
|
|
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
|