@ilha/router 0.1.1

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 ADDED
@@ -0,0 +1,547 @@
1
+ # `@ilha/router`
2
+
3
+ A lightweight, isomorphic router for [Ilha](https://github.com/ilhajs/ilha) islands. Runs in the browser with full reactivity and on the server as a synchronous HTML string renderer. Pairs natively with [Nitro](https://nitro.build/) and includes a Vite plugin for file-system based routing.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @ilha/router
11
+ # or Bun
12
+ bun add @ilha/router
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ ### Client-side
20
+
21
+ ```ts
22
+ import { router } from "@ilha/router";
23
+ import { homePage, aboutPage, userPage, notFound } from "./pages";
24
+
25
+ router()
26
+ .route("/", homePage)
27
+ .route("/about", aboutPage)
28
+ .route("/user/:id", userPage)
29
+ .route("/**", notFound)
30
+ .mount("#app");
31
+ ```
32
+
33
+ ### Server-side (SSR)
34
+
35
+ ```ts
36
+ import { router } from "@ilha/router";
37
+ import { homePage, aboutPage, userPage, notFound } from "./pages";
38
+
39
+ export default defineEventHandler((event) => {
40
+ const html = router()
41
+ .route("/", homePage)
42
+ .route("/about", aboutPage)
43
+ .route("/user/:id", userPage)
44
+ .route("/**", notFound)
45
+ .render(event.node.req.url ?? "/");
46
+
47
+ return new Response(`<!doctype html><html><body>${html}</body></html>`, {
48
+ headers: { "content-type": "text/html" },
49
+ });
50
+ });
51
+ ```
52
+
53
+ ### SSR + Client Hydration (recommended)
54
+
55
+ ```ts
56
+ // routes/[...].ts — Nitro handler
57
+ import { pageRouter } from "ilha:pages";
58
+ import { registry } from "ilha:registry";
59
+
60
+ export default defineEventHandler(async (event) => {
61
+ const html = await pageRouter.renderHydratable(event.node.req.url ?? "/", registry);
62
+ return new Response(`<!doctype html><html><body>${html}</body></html>`, {
63
+ headers: { "content-type": "text/html" },
64
+ });
65
+ });
66
+ ```
67
+
68
+ ```ts
69
+ // src/client.ts — browser entry
70
+ import { pageRouter } from "ilha:pages";
71
+ import { registry } from "ilha:registry";
72
+
73
+ pageRouter.hydrate(registry);
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Core API
79
+
80
+ ### `router()`
81
+
82
+ Creates a new router instance and **resets the route registry**. Always call `router()` fresh — never share instances across server requests.
83
+
84
+ Returns a `RouterBuilder`.
85
+
86
+ ---
87
+
88
+ #### `.route(pattern, island)`
89
+
90
+ Registers a route. Patterns are matched in **declaration order** — first match wins. Uses [rou3](https://github.com/h3js/rou3) for matching, the same engine as Nitro.
91
+
92
+ | Pattern | Matches | `routeParams()` |
93
+ | --------------- | ------------------- | --------------------------------- |
94
+ | `/` | `/` | `{}` |
95
+ | `/about` | `/about` | `{}` |
96
+ | `/user/:id` | `/user/42` | `{ id: "42" }` |
97
+ | `/:org/:repo` | `/ilha/router` | `{ org: "ilha", repo: "router" }` |
98
+ | `/docs/**:slug` | `/docs/guide/intro` | `{ slug: "guide/intro" }` |
99
+ | `/**` | anything | `{}` |
100
+
101
+ > Static segments take priority over `:param` segments — `/user/me` will match before `/user/:id`.
102
+
103
+ Returns the same `RouterBuilder` for chaining.
104
+
105
+ ---
106
+
107
+ #### `.mount(target, options?)` — browser only
108
+
109
+ Mounts the router into a DOM element or CSS selector. Sets up `popstate` listening and intercepts internal `<a>` clicks automatically.
110
+
111
+ ```ts
112
+ const unmount = router().route("/", homePage).mount("#app");
113
+
114
+ // later:
115
+ unmount();
116
+ ```
117
+
118
+ **Options:**
119
+
120
+ | Option | Type | Default | Description |
121
+ | ---------- | ------------------------ | ----------- | ---------------------------------------------------------- |
122
+ | `hydrate` | `boolean` | `false` | Preserve SSR DOM on first mount (no destructive re-render) |
123
+ | `registry` | `Record<string, Island>` | `undefined` | Island registry for interactive hydration on navigation |
124
+
125
+ When `hydrate: true`, `.mount()` does **not** wipe existing SSR HTML. It instead mounts a hidden navigation handler that re-renders routes with hydration on subsequent navigations.
126
+
127
+ No-op with a console warning when called outside a browser environment.
128
+
129
+ ---
130
+
131
+ #### `.render(url)` — server / SSR
132
+
133
+ Resolves the given URL against the route registry and returns a synchronous HTML string. Accepts a path string, full URL string, or `URL` object. Populates all route signals identically to the browser. Percent-encoded params are decoded automatically.
134
+
135
+ ```ts
136
+ const html = router().route("/", homePage).route("/**", notFound).render("/");
137
+ // → '<div data-router-view><p>home</p></div>'
138
+ ```
139
+
140
+ Renders `<div data-router-empty></div>` when no route matches.
141
+
142
+ ---
143
+
144
+ #### `.renderHydratable(url, registry, options?)` — server / SSR
145
+
146
+ Async variant of `.render()` that outputs HTML with `data-ilha` hydration markers so the client can rehydrate without a full re-render.
147
+
148
+ ```ts
149
+ const html = await router().route("/", homePage).renderHydratable("/", registry);
150
+ // → '<div data-router-view><div data-ilha="home">…</div></div>'
151
+ ```
152
+
153
+ If the active island is not found in the registry, falls back to plain SSR and emits a `console.warn`.
154
+
155
+ **Options** extend `HydratableOptions` from `ilha`:
156
+
157
+ | Option | Type | Default | Description |
158
+ | ---------- | --------- | ------- | ----------------------------------------------------- |
159
+ | `snapshot` | `boolean` | `true` | Embed island state as `data-ilha-state` for hydration |
160
+
161
+ ---
162
+
163
+ #### `.prime()` — browser only
164
+
165
+ Primes route context signals from the current `window.location` **before** `ilha.mount()` runs. This prevents a signal mismatch that would destroy hydrated bindings.
166
+
167
+ Call this after all routes are registered and before mounting islands for interactivity:
168
+
169
+ ```ts
170
+ import { mount } from "ilha";
171
+ import { pageRouter } from "ilha:pages";
172
+ import { registry } from "ilha:registry";
173
+
174
+ pageRouter.prime(); // ← sync signals first
175
+ mount(registry, { root: … }); // ← then hydrate islands
176
+ pageRouter.mount("#app", { hydrate: true, registry });
177
+ ```
178
+
179
+ ---
180
+
181
+ #### `.hydrate(registry, options?)` — browser only
182
+
183
+ Convenience method that combines `.prime()`, `ilha.mount()`, and `.mount()` into a single call. Use this as the recommended client entry point.
184
+
185
+ ```ts
186
+ pageRouter.hydrate(registry);
187
+
188
+ // With options:
189
+ pageRouter.hydrate(registry, {
190
+ root: document.getElementById("root"), // defaults to document.body
191
+ target: "#app", // defaults to root
192
+ });
193
+ ```
194
+
195
+ Returns an `unmount` function that tears down all listeners and hydrated islands.
196
+
197
+ ---
198
+
199
+ ### `navigate(to, options?)`
200
+
201
+ Programmatically navigate to a path. Updates the URL, history stack, and all reactive signals. Duplicate navigations (same URL) are no-ops.
202
+
203
+ ```ts
204
+ import { navigate } from "@ilha/router";
205
+
206
+ navigate("/about");
207
+ navigate("/about", { replace: true }); // replaces instead of pushing
208
+ ```
209
+
210
+ No-op on the server.
211
+
212
+ ---
213
+
214
+ ### `prime()`
215
+
216
+ Standalone export of the same signal-priming function available as `.prime()` on the builder. Useful when managing the priming step separately from the router instance.
217
+
218
+ ```ts
219
+ import { prime } from "@ilha/router";
220
+
221
+ prime();
222
+ ```
223
+
224
+ ---
225
+
226
+ ### `useRoute()`
227
+
228
+ Returns reactive signal accessors for the current route state. Safe to call inside any island render function on both client and server.
229
+
230
+ ```ts
231
+ import { useRoute } from "@ilha/router";
232
+
233
+ const MyPage = ilha.render(() => {
234
+ const { path, params, search, hash } = useRoute();
235
+ return `<p>user id: ${params().id}</p>`;
236
+ });
237
+ ```
238
+
239
+ ---
240
+
241
+ ### `routePath` · `routeParams` · `routeSearch` · `routeHash`
242
+
243
+ The underlying context signals — use these outside of islands when you need direct signal access.
244
+
245
+ ```ts
246
+ import { routePath, routeParams, routeSearch, routeHash } from "@ilha/router";
247
+
248
+ routePath(); // → "/user/42"
249
+ routeParams(); // → { id: "42" }
250
+ routeSearch(); // → "?tab=docs"
251
+ routeHash(); // → "#section"
252
+ ```
253
+
254
+ ---
255
+
256
+ ### `isActive(pattern)`
257
+
258
+ Returns `true` if the current path matches the given registered pattern. Uses O(1) reverse island lookup internally.
259
+
260
+ ```ts
261
+ import { isActive } from "@ilha/router";
262
+
263
+ isActive("/about"); // → true / false
264
+ isActive("/user/:id"); // → true when on any /user/* path
265
+ ```
266
+
267
+ ---
268
+
269
+ ### `enableLinkInterception(root?)`
270
+
271
+ Attaches a delegated click listener to `root` (defaults to `document`) that intercepts `<a>` clicks and routes them client-side. Called automatically by `.mount()`.
272
+
273
+ Skips links that are external, `target="_blank"`, anchor-only (`#hash`), or modified (`Ctrl`/`Meta`/`Shift`). Also skips events already handled (`e.defaultPrevented`).
274
+
275
+ Returns a cleanup function.
276
+
277
+ ```ts
278
+ const stop = enableLinkInterception(myContainer);
279
+ stop(); // remove listener
280
+ ```
281
+
282
+ No-op on the server.
283
+
284
+ ---
285
+
286
+ ### `RouterView`
287
+
288
+ The outlet island rendered by `.mount()` and `.render()`. Wraps the active island in `<div data-router-view>`, or renders `<div data-router-empty></div>` when no route matches.
289
+
290
+ ```ts
291
+ import { RouterView } from "@ilha/router";
292
+
293
+ RouterView.toString(); // SSR
294
+ RouterView.mount(el); // client
295
+ ```
296
+
297
+ ---
298
+
299
+ ### `RouterLink`
300
+
301
+ A declarative link island that calls `navigate()` on click.
302
+
303
+ ```ts
304
+ import { RouterLink } from "@ilha/router";
305
+
306
+ RouterLink.toString({ href: "/about", label: "About" });
307
+ // → '<a data-link href="/about">About</a>'
308
+ ```
309
+
310
+ ---
311
+
312
+ ### `wrapLayout(layout, page)`
313
+
314
+ Wraps a page island with a layout handler. Used internally by the Vite plugin codegen — also available for manual composition.
315
+
316
+ ```ts
317
+ import { wrapLayout } from "@ilha/router";
318
+
319
+ const wrapped = wrapLayout(myLayout, myPage);
320
+ ```
321
+
322
+ ---
323
+
324
+ ### `wrapError(handler, page)`
325
+
326
+ Wraps a page island with an error boundary. If the page throws during SSR (`.toString()`), the `handler` receives the error and current route snapshot and returns a fallback island. Also intercepts errors during `.mount()` for client-side resilience.
327
+
328
+ ```ts
329
+ import { wrapError } from "@ilha/router";
330
+
331
+ const safe = wrapError(myErrorHandler, myPage);
332
+ ```
333
+
334
+ The nearest (innermost) `wrapError` boundary catches first. If the inner handler re-throws, the next outer boundary takes over.
335
+
336
+ ---
337
+
338
+ ## TypeScript Types
339
+
340
+ ```ts
341
+ interface RouteSnapshot {
342
+ path: string;
343
+ params: Record<string, string>;
344
+ search: string;
345
+ hash: string;
346
+ }
347
+
348
+ interface AppError {
349
+ message: string;
350
+ status?: number;
351
+ stack?: string;
352
+ }
353
+
354
+ type LayoutHandler = (children: Island) => Island;
355
+ type ErrorHandler = (error: AppError, route: RouteSnapshot) => Island;
356
+
357
+ interface NavigateOptions {
358
+ replace?: boolean;
359
+ }
360
+
361
+ interface MountOptions {
362
+ hydrate?: boolean;
363
+ registry?: Record<string, Island>;
364
+ }
365
+
366
+ interface HydrateOptions {
367
+ root?: Element;
368
+ target?: string | Element;
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## File-system Routing
375
+
376
+ `@ilha/router` includes a Vite plugin that scans `src/pages/`, resolves layout and error boundary chains, and generates a ready-to-use router — no manual route registration needed.
377
+
378
+ ### Setup
379
+
380
+ ```ts
381
+ // vite.config.ts
382
+ import { pages } from "@ilha/router/vite";
383
+
384
+ export default defineConfig({
385
+ plugins: [pages()],
386
+ });
387
+ ```
388
+
389
+ Add `.ilha/` (or your custom `generated` path) to `.gitignore`.
390
+
391
+ ### Directory structure
392
+
393
+ ```
394
+ src/pages/
395
+ +layout.ts ← root layout (wraps all pages)
396
+ +error.ts ← root error boundary
397
+ index.ts → /
398
+ about.ts → /about
399
+ user/
400
+ +layout.ts ← nested layout (wraps user/* only)
401
+ +error.ts ← nested error boundary
402
+ [id].ts → /user/:id
403
+ [id]/
404
+ settings.ts → /user/:id/settings
405
+ [...slug].ts → /**:slug
406
+ ```
407
+
408
+ ### Filename → pattern mapping
409
+
410
+ | File | Pattern |
411
+ | ----------------- | ------------- |
412
+ | `index.ts` | `/` |
413
+ | `about.ts` | `/about` |
414
+ | `[id].ts` | `/:id` |
415
+ | `user/[id].ts` | `/user/:id` |
416
+ | `[org]/[repo].ts` | `/:org/:repo` |
417
+ | `[...slug].ts` | `/**:slug` |
418
+
419
+ `.test.ts`, `.spec.ts`, and `.d.ts` files are automatically excluded.
420
+
421
+ ### Route sorting
422
+
423
+ Routes are sorted automatically by specificity — no need to order files manually:
424
+
425
+ 1. **Static** paths (`/about`) — highest priority
426
+ 2. **Parameterised** paths (`/user/:id`)
427
+ 3. **Wildcard** paths (`/**:slug`) — lowest priority
428
+
429
+ Within the same tier, longer segment counts and alphabetical order act as tiebreakers for determinism.
430
+
431
+ ### Layouts
432
+
433
+ A `+layout.ts` wraps every page in its directory and all subdirectories. Layouts compose **inside-out** — the nearest layout is innermost, the root layout is outermost.
434
+
435
+ ```ts
436
+ // src/pages/+layout.ts
437
+ import { html } from "ilha";
438
+ import type { LayoutHandler } from "@ilha/router/vite";
439
+
440
+ export default ((children) =>
441
+ ilha.render(
442
+ () => html`
443
+ <nav>
444
+ <a href="/">Home</a>
445
+ <a href="/about">About</a>
446
+ </nav>
447
+ <main>${children}</main>
448
+ `,
449
+ )) satisfies LayoutHandler;
450
+ ```
451
+
452
+ ### Error boundaries
453
+
454
+ A `+error.ts` catches any error thrown during rendering of pages in its directory and all subdirectories. The nearest boundary wins. If an inner boundary re-throws, the next outer boundary takes over. Receives the error and the current route snapshot.
455
+
456
+ ```ts
457
+ // src/pages/+error.ts
458
+ import type { ErrorHandler } from "@ilha/router/vite";
459
+
460
+ export default ((error, route) =>
461
+ ilha.render(
462
+ () => `
463
+ <div class="error">
464
+ <h1>${error.status ?? 500}</h1>
465
+ <p>${error.message}</p>
466
+ <p>Path: ${route.path}</p>
467
+ </div>
468
+ `,
469
+ )) satisfies ErrorHandler;
470
+ ```
471
+
472
+ ### Virtual modules
473
+
474
+ The plugin exposes two virtual modules:
475
+
476
+ | Module | Export | Description |
477
+ | --------------- | ------------ | -------------------------------------------- |
478
+ | `ilha:pages` | `pageRouter` | A `RouterBuilder` with all routes registered |
479
+ | `ilha:registry` | `registry` | `Record<string, Island>` for hydration |
480
+
481
+ ```ts
482
+ // routes/[...].ts — Nitro catch-all handler
483
+ import { pageRouter } from "ilha:pages";
484
+ import { registry } from "ilha:registry";
485
+
486
+ export default defineEventHandler(async (event) => {
487
+ const html = await pageRouter.renderHydratable(event.node.req.url ?? "/", registry);
488
+ return new Response(`<!doctype html><html><body>${html}</body></html>`, {
489
+ headers: { "content-type": "text/html" },
490
+ });
491
+ });
492
+ ```
493
+
494
+ ```ts
495
+ // src/client.ts — browser entry
496
+ import { pageRouter } from "ilha:pages";
497
+ import { registry } from "ilha:registry";
498
+
499
+ pageRouter.hydrate(registry);
500
+ ```
501
+
502
+ ### Plugin options
503
+
504
+ ```ts
505
+ pages({
506
+ dir: "src/pages", // pages directory (default: "src/pages")
507
+ generated: ".ilha/routes.ts", // generated file output (default: ".ilha/routes.ts")
508
+ });
509
+ ```
510
+
511
+ The plugin regenerates the routes file only when content actually changes — avoiding unnecessary HMR invalidations. Structural changes (file add/remove, `+layout.ts`/`+error.ts` edits) trigger full HMR. Regular page content edits are handled by Vite's normal module HMR.
512
+
513
+ ---
514
+
515
+ ## SSR + Hydration
516
+
517
+ The same route config runs on both sides. Signals (`routePath`, `routeParams`, etc.) are populated identically by `.render()`/`.renderHydratable()` on the server and `.mount()`/`.hydrate()` on the client.
518
+
519
+ ```ts
520
+ // server: resolves URL → hydratable HTML string
521
+ await pageRouter.renderHydratable("/user/42", registry);
522
+ routeParams(); // → { id: "42" }
523
+
524
+ // client: hydrates SSR DOM, sets up navigation
525
+ pageRouter.hydrate(registry);
526
+ navigate("/user/99");
527
+ routeParams(); // → { id: "99" }
528
+ ```
529
+
530
+ ### Full SSR → hydration flow
531
+
532
+ ```
533
+ server client
534
+ ────────────────────────────── ──────────────────────────────────────────────
535
+ renderHydratable(url, registry) pageRouter.prime() ← sync signals first
536
+ → data-ilha="…" markers mount(registry, { root }) ← hydrate islands
537
+ → data-ilha-state snapshot pageRouter.mount(target, ← setup navigation
538
+ { hydrate: true, registry })
539
+ ```
540
+
541
+ Or use the one-liner: `pageRouter.hydrate(registry)`.
542
+
543
+ ---
544
+
545
+ ## License
546
+
547
+ MIT
@@ -0,0 +1,125 @@
1
+ import { HydratableOptions, Island } from "ilha";
2
+
3
+ //#region src/index.d.ts
4
+ interface RouteRecord {
5
+ pattern: string;
6
+ island: Island<any, any>;
7
+ }
8
+ interface RouteSnapshot {
9
+ path: string;
10
+ params: Record<string, string>;
11
+ search: string;
12
+ hash: string;
13
+ }
14
+ interface AppError {
15
+ message: string;
16
+ status?: number;
17
+ stack?: string;
18
+ }
19
+ type LayoutHandler = (children: Island<any, any>) => Island<any, any>;
20
+ type ErrorHandler = (error: AppError, route: RouteSnapshot) => Island<any, any>;
21
+ declare function wrapLayout(layout: LayoutHandler, page: Island<any, any>): Island<any, any>;
22
+ declare function wrapError(handler: ErrorHandler, page: Island<any, any>): Island<any, any>;
23
+ interface NavigateOptions {
24
+ replace?: boolean;
25
+ }
26
+ interface HydratableRenderOptions extends Partial<Omit<HydratableOptions, "name">> {}
27
+ interface HydrateOptions {
28
+ root?: Element;
29
+ target?: string | Element;
30
+ }
31
+ interface MountOptions {
32
+ hydrate?: boolean;
33
+ registry?: Record<string, Island<any, any>>;
34
+ }
35
+ interface RouterBuilder {
36
+ route(pattern: string, island: Island<any, any>): RouterBuilder;
37
+ prime(): void;
38
+ mount(target: string | Element, options?: MountOptions): () => void;
39
+ render(url: string | URL): string;
40
+ renderHydratable(url: string | URL, registry: Record<string, Island<any, any>>, options?: HydratableRenderOptions): Promise<string>;
41
+ /**
42
+ * Hydrate the application - combines prime(), mount(), and router.mount() into one call.
43
+ * @param registry - The island registry from ilha:registry
44
+ * @param options - Optional root element (defaults to document.body) and router target (defaults to root)
45
+ * @returns Cleanup function
46
+ */
47
+ hydrate(registry: Record<string, Island<any, any>>, options?: HydrateOptions): () => void;
48
+ }
49
+ declare const routePath: {
50
+ (): string;
51
+ (value: string): void;
52
+ };
53
+ declare const routeParams: {
54
+ (): Record<string, string>;
55
+ (value: Record<string, string>): void;
56
+ };
57
+ declare const routeSearch: {
58
+ (): string;
59
+ (value: string): void;
60
+ };
61
+ declare const routeHash: {
62
+ (): string;
63
+ (value: string): void;
64
+ };
65
+ declare function useRoute(): {
66
+ path: {
67
+ (): string;
68
+ (value: string): void;
69
+ };
70
+ params: {
71
+ (): Record<string, string>;
72
+ (value: Record<string, string>): void;
73
+ };
74
+ search: {
75
+ (): string;
76
+ (value: string): void;
77
+ };
78
+ hash: {
79
+ (): string;
80
+ (value: string): void;
81
+ };
82
+ };
83
+ /**
84
+ * Prime route context signals from the current `location` so that islands
85
+ * hydrated by `ilha.mount()` see the correct route values on their first
86
+ * render — preventing a mismatch morph that would destroy hydrated bindings.
87
+ *
88
+ * Call this **before** `ilha.mount()` and **after** all routes have been
89
+ * registered (i.e. after the `router().route(…).route(…)` chain).
90
+ *
91
+ * ```ts
92
+ * import { mount } from "ilha";
93
+ * import { pageRouter } from "ilha:pages";
94
+ * import { registry } from "ilha:registry";
95
+ *
96
+ * pageRouter.prime(); // ← sync signals first
97
+ * mount(registry, { root: … }); // ← then hydrate islands
98
+ * pageRouter.mount("#app", { hydrate: true });
99
+ * ```
100
+ */
101
+ declare function prime(): void;
102
+ declare function navigate(to: string, opts?: NavigateOptions): void;
103
+ declare function enableLinkInterception(root?: Element | Document): () => void;
104
+ declare const RouterView: Island<Record<string, unknown>, Record<string, never>>;
105
+ declare const RouterLink: Island<Record<string, unknown>, {
106
+ [x: string]: never;
107
+ href: string;
108
+ } & Record<"label", string>>;
109
+ declare function isActive(pattern: string): boolean;
110
+ declare function router(): RouterBuilder;
111
+ declare const _default: {
112
+ router: typeof router;
113
+ navigate: typeof navigate;
114
+ useRoute: typeof useRoute;
115
+ isActive: typeof isActive;
116
+ enableLinkInterception: typeof enableLinkInterception;
117
+ prime: typeof prime;
118
+ RouterView: Island<Record<string, unknown>, Record<string, never>>;
119
+ RouterLink: Island<Record<string, unknown>, {
120
+ [x: string]: never;
121
+ href: string;
122
+ } & Record<"label", string>>;
123
+ };
124
+ //#endregion
125
+ export { AppError, ErrorHandler, HydratableRenderOptions, HydrateOptions, LayoutHandler, MountOptions, NavigateOptions, RouteRecord, RouteSnapshot, RouterBuilder, RouterLink, RouterView, _default as default, enableLinkInterception, isActive, navigate, prime, routeHash, routeParams, routePath, routeSearch, router, useRoute, wrapError, wrapLayout };