@solidjs/router 1.0.0-next.9 → 2.0.0-next.12

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
@@ -29,12 +29,14 @@ Explore the official [documentation](https://docs.solidjs.com/solid-router) for
29
29
  - [The Mental Model: Instance vs Hooks](#the-mental-model-instance-vs-hooks)
30
30
  - [Route Definitions](#route-definitions)
31
31
  - [Dynamic Routes](#dynamic-routes)
32
+ - [Typed Route Params](#typed-route-params)
32
33
  - [Match Filters](#match-filters)
33
34
  - [Optional Parameters](#optional-parameters)
34
35
  - [Wildcard Routes](#wildcard-routes)
35
36
  - [Multiple Paths](#multiple-paths)
36
37
  - [Nested Routes](#nested-routes)
37
38
  - [Lazy Route Subtrees](#lazy-route-subtrees)
39
+ - [File-System Routes](#file-system-routes)
38
40
  - [Typed Paths](#typed-paths)
39
41
  - [Links](#links)
40
42
  - [Preload Functions](#preload-functions)
@@ -94,6 +96,8 @@ export const adminRoutes = defineRoutes([
94
96
  export const Router = createRouter({ routes: [...appRoutes, ...adminRoutes] });
95
97
  ```
96
98
 
99
+ Its single-route sibling `defineRoute` also types `params` inside the route's own `component` and `preload` — see [Typed Route Params](#typed-route-params).
100
+
97
101
  Mount it by rendering the instance. The render-prop child is your root layout — it always stays mounted, receives the matched content as `props.children`, and is the ideal place for top-level navigation and context providers:
98
102
 
99
103
  ```tsx
@@ -188,6 +192,48 @@ As long as the URL fits the pattern, the `User` component shows, and `id` is ava
188
192
  </Show>
189
193
  ```
190
194
 
195
+ ### Typed Route Params
196
+
197
+ By default `params` is an open record — every key is `string | undefined`, even when the pattern guarantees it. Wrap a route in `defineRoute` and its `component` and `preload` are typed from the route's own `path`:
198
+
199
+ ```tsx
200
+ import { defineRoute } from "@solidjs/router";
201
+
202
+ const story = defineRoute({
203
+ path: "/stories/:id/:tab?",
204
+ preload: ({ params }) => getStory(params.id), // params.id: string
205
+ component: props => (
206
+ <Story
207
+ id={props.params.id} // string — the pattern guarantees it
208
+ tab={props.params.tab} // string | undefined — optional param
209
+ />
210
+ )
211
+ });
212
+ ```
213
+
214
+ `defineRoute` is an identity function at runtime — the route object drops into `routes` (or a parent's `children`) like any plain object, and `path`, `children`, `matchFilters`, and `search` still flow into `paths` and the typed hooks. Params inherited from parent routes stay accessible as `string | undefined`; nested `children` type their own params only if they use `defineRoute` themselves.
215
+
216
+ For components declared away from their route, `RouteProps` takes a path witness — the same `paths` node you navigate with (`import type` keeps the instance out of the runtime graph, so no cycle) — plus an optional data type:
217
+
218
+ ```tsx
219
+ import type { RouteComponent, RouteProps } from "@solidjs/router";
220
+ import type { Router } from "./app/router";
221
+
222
+ function Story(props: RouteProps<typeof Router.paths.stories, StoryData>) {
223
+ props.params.id; // string
224
+ }
225
+
226
+ // component-type form — props infer contextually
227
+ const Story: RouteComponent<typeof Router.paths.stories, StoryData> = props => (
228
+ <h1>{props.params.id}</h1>
229
+ );
230
+
231
+ // or, anywhere under the route:
232
+ const params = useParams(paths.stories); // typed from the tree
233
+ ```
234
+
235
+ When no instance is in scope at the definition site — most notably [file-system route files](#file-system-routes), where the pattern lives in the filename — the witness can be the pattern string itself: `RouteProps<"/stories/:id">`.
236
+
191
237
  ### Match Filters
192
238
 
193
239
  Each parameter can be validated with a `MatchFilter` — an enum array, a regex, or a predicate. If validation fails, the route doesn't match:
@@ -316,6 +362,37 @@ The import only fires when something needs the subtree — hovering a link into
316
362
 
317
363
  Resolution is cached per thunk and append-only: the tree never changes shape after a subtree lands, it just gets more specific. Keep thunks deterministic — `() => import(...)` — rather than switching tables on runtime state.
318
364
 
365
+ ### File-System Routes
366
+
367
+ The `@solidjs/router/fs` adapter turns a `file-routes` manifest into route definitions — the app imports the virtual module, the adapter maps it:
368
+
369
+ ```tsx
370
+ import { pageRoutes } from "virtual:file-routes";
371
+ import { fileRoutes } from "@solidjs/router/fs";
372
+
373
+ export const Router = createRouter({ routes: fileRoutes(pageRoutes) });
374
+ ```
375
+
376
+ Route files export their component as `default` and everything else as a `route` config export, which is spread into the definition. Inside a route file the pattern lives in the filename, so there's no `paths` node to witness with at the definition site — `defineFileRoute` takes the pattern string instead, types `preload`'s params from it, and validates `matchFilters` along the way. The config then doubles as the component's [`RouteProps`](#typed-route-params) witness, typing `params` from the pattern and `data` from the `preload`'s return type:
377
+
378
+ ```tsx
379
+ // routes/blog/[id].tsx
380
+ import { int } from "@solidjs/router";
381
+ import { defineFileRoute } from "@solidjs/router/fs";
382
+
383
+ export const route = defineFileRoute("/blog/:id", {
384
+ matchFilters: { id: int },
385
+ preload: ({ params }) => getPost(params.id) // params.id: string
386
+ });
387
+
388
+ export default function Post(props: RouteProps<typeof route>) {
389
+ props.params.id; // string
390
+ props.data; // ReturnType of the preload above
391
+ }
392
+ ```
393
+
394
+ The pattern string is a typing witness — at runtime the manifest's path (from the filename) is the source of truth. With the plugin's `types` option generating a literal declaration for the virtual module, the file paths flow into `paths` and the typed hooks like a hand-written tree — `paths.blog(42)` typechecks, filters and search schemas included, and `useParams(paths.blog)` works as usual anywhere under the route.
395
+
319
396
  ## Typed Paths
320
397
 
321
398
  `paths` is a proxy inferred from the route tree. Property access descends into static segments, calls bind params, and it mirrors URL anatomy — params, then a search object, then a hash string:
@@ -598,9 +675,11 @@ Retrieves a reactive, store-like object of the current route's path parameters.
598
675
 
599
676
  ```tsx
600
677
  const params = useParams(); // Params (strings)
601
- const params = useParams(paths.users); // { id: number } — typed via matchFilters
678
+ const params = useParams(paths.users); // { id: string } — typed from the tree
602
679
  ```
603
680
 
681
+ Inside a route's own `component`/`preload`, [`defineRoute`](#typed-route-params) types `props.params` without a witness.
682
+
604
683
  ### useNavigate
605
684
 
606
685
  Retrieves a method to navigate. Accepts a string or a typed path node, plus options:
@@ -641,11 +720,14 @@ return <div classList={{ "grey-out": isRouting() }}>...</div>;
641
720
 
642
721
  ### useMatch
643
722
 
644
- Tests a path *pattern you supply* against the current location; returns a memo of match information or `undefined`. It never consults the route tree — the pattern doesn't have to correspond to a defined route:
723
+ Tests a path *pattern you supply* against the current location; returns a memo of match information or `undefined`. It never consults the route tree — the pattern doesn't have to correspond to a defined route. The match's `params` are typed from the pattern, and a typed path node works too (a concrete URL — useful for "am I here" checks):
645
724
 
646
725
  ```tsx
647
726
  const match = useMatch(() => "/admin/*rest");
727
+ match()?.params.rest; // string
648
728
  return <Show when={match()}>...</Show>;
729
+
730
+ const here = useMatch(() => paths.users(2));
649
731
  ```
650
732
 
651
733
  ### useRouteMatches
@@ -654,7 +736,17 @@ Returns an accessor of the router's *resolved* matches for the current location
654
736
 
655
737
  ```tsx
656
738
  const matches = useRouteMatches();
657
- const breadcrumbs = createMemo(() => matches().map(m => m.route.info.breadcrumb));
739
+ const breadcrumbs = createMemo(() => matches().map(m => m.route.info?.breadcrumb));
740
+ ```
741
+
742
+ `info` is freeform by default; augment `RouteInfo` to type it app-wide — declared keys are checked at route definitions and typed on reads:
743
+
744
+ ```ts
745
+ declare module "@solidjs/router" {
746
+ interface RouteInfo {
747
+ breadcrumb?: string;
748
+ }
749
+ }
658
750
  ```
659
751
 
660
752
  ### usePreloadRoute
@@ -738,17 +830,18 @@ Router.match("/users/2/settings?tab=x");
738
830
 
739
831
  ## Server Integration
740
832
 
741
- Framework handler wiring lives in `@solidjs/router/server`. Both integrations accept the router instance directly — its routes, base, and preload are the single source of truth:
833
+ Framework handler wiring lives in `@solidjs/router/server`. The integration accepts the router instance directly — its routes, base, and preload are the single source of truth:
742
834
 
743
835
  ```tsx
744
- import { createFlightDataCollector, createNoJSHandler } from "@solidjs/router/server";
836
+ import { createFlightDataCollector } from "@solidjs/router/server";
745
837
  import { Router } from "./app/router";
746
838
 
747
839
  const collectFlightData = createFlightDataCollector(Router);
748
- const handleNoJS = createNoJSHandler();
749
840
  ```
750
841
 
751
- `createFlightDataCollector` produces the single-flight hook: after a mutation it reruns the route data the mutation invalidated for the page the client is on (or is redirected to), folding fresh data into the same response. `createNoJSHandler` implements the no-JS form convention: form posts without the client runtime redirect back with the outcome in a one-shot flash cookie that SSR reads into submission state. Both policies previously lived inside SolidStart; the router now owns them, so custom server setups get single-flight mutations and progressive enhancement without a framework.
842
+ `createFlightDataCollector` produces the single-flight hook: after a mutation it reruns the route data the mutation invalidated for the page the client is on (or is redirected to), folding fresh data into the same response. This policy previously lived inside SolidStart; the router now owns it, so custom server setups get single-flight mutations without a framework.
843
+
844
+ The no-JS form convention needs no wiring at all: the server function runtime answers form posts made without the client runtime by redirecting back with the outcome in a one-shot flash cookie, and the router's SSR reads it into submission state. To configure it (e.g. a base path), pass `createNoJSHandler(options)` from `@solidjs/web/server-functions/server` as the handler's `handleNoJS`.
752
845
 
753
846
  ## Migration from 0.x
754
847
 
@@ -1,9 +1,11 @@
1
1
  import { $TRACK, action as createSolidAction, createMemo, onCleanup, getOwner } from "solid-js";
2
- import { isResponseEnvelope, isServer } from "@solidjs/web";
3
- import { createServerReference, decodeResponse, subscribeFlightData } from "@solidjs/web/server-functions";
2
+ import { isResponseEnvelope, isServer, REVALIDATE_HEADER } from "@solidjs/web";
3
+ import { createServerReference, decodeResponsePayload, subscribeFlightData } from "@solidjs/web/server-functions";
4
+ // The explicit /server specifier is safe here: the only call site is
5
+ // server-guarded, so client builds tree-shake the codec away.
6
+ import { decodeFlashCookie } from "@solidjs/web/server-functions/server";
4
7
  import { provideFlashDecoder, provideFlightConsumer, useRouter } from "../routing.js";
5
8
  import { setRouterFormHandler } from "./events.js";
6
- import { decodeFlashCookie } from "./flash.js";
7
9
  import { mockBase, setFunctionName } from "../utils.js";
8
10
  import { cacheKeyOp, hashKey, revalidate, query } from "./query.js";
9
11
  const submitHooksSymbol = Symbol("routerActionSubmitHooks");
@@ -108,8 +110,12 @@ function installRouterIntegrations() {
108
110
  if (integrationsInstalled)
109
111
  return;
110
112
  integrationsInstalled = true;
111
- provideFlashDecoder(decodeFlashCookie);
112
- if (!isServer) {
113
+ if (isServer) {
114
+ // Server-only: initSubmissions only decodes during SSR, so client builds
115
+ // tree-shake the codec (which now lives behind the runtime's server entry).
116
+ provideFlashDecoder(decodeFlashCookie);
117
+ }
118
+ else {
113
119
  setRouterFormHandler(handleFormAction);
114
120
  provideFlightConsumer(setupFlightDataConsumer);
115
121
  }
@@ -179,14 +185,12 @@ function actionImpl(fn, options = {}) {
179
185
  finally {
180
186
  form && setFormBusy(form, -1);
181
187
  }
182
- if (!response)
183
- return undefined;
184
188
  let submission;
185
189
  submission = {
186
190
  input: variables,
187
191
  url,
188
- result: response.data,
189
- error: response.error,
192
+ result: response && response.data,
193
+ error: response && response.error,
190
194
  clear() {
191
195
  router.submissions[1](entries => entries.filter(entry => entry !== submission));
192
196
  },
@@ -195,12 +199,20 @@ function actionImpl(fn, options = {}) {
195
199
  return current[invokeSymbol].call({ r: router, f: form }, variables, current);
196
200
  }
197
201
  };
198
- router.submissions[1](entries => [...entries, submission]);
202
+ // Book-keeping is intentional: only outcomes worth showing or retrying
203
+ // (a result or an error) enter the submissions list, so the typical void
204
+ // mutation leaves nothing behind. Settled hooks still see every
205
+ // completion — void, metadata-only, and redirects included — one
206
+ // `onSettled` per invocation (#580).
207
+ response && router.submissions[1](entries => [...entries, submission]);
199
208
  for (const hook of settledHooks.values())
200
209
  hook(submission);
201
- if (response.error && !form)
202
- throw response.error;
203
- return response.data;
210
+ if (response) {
211
+ if (response.error && !form)
212
+ throw response.error;
213
+ return response.data;
214
+ }
215
+ return undefined;
204
216
  }
205
217
  const o = typeof options === "string" ? { name: options } : options;
206
218
  const name = o.name || (!isServer ? String(hashString(fn.toString())) : undefined);
@@ -299,11 +311,11 @@ export function setupFlightDataConsumer(router) {
299
311
  * the flight-data consumer and the action response path (which still sees
300
312
  * metadata-bearing responses when no flight data was collected).
301
313
  */
302
- async function applyResponseMetadata(metadata, navigate, flightData) {
314
+ function applyResponseMetadata(metadata, navigate, flightData) {
303
315
  let keys;
304
316
  if (metadata) {
305
- if (metadata.headers.has("X-Revalidate"))
306
- keys = metadata.headers.get("X-Revalidate").split(",");
317
+ if (metadata.headers.has(REVALIDATE_HEADER))
318
+ keys = metadata.headers.get(REVALIDATE_HEADER).split(",");
307
319
  if (metadata.headers.has("Location")) {
308
320
  const locationUrl = metadata.headers.get("Location") || "/";
309
321
  if (locationUrl.startsWith("http")) {
@@ -319,7 +331,7 @@ async function applyResponseMetadata(metadata, navigate, flightData) {
319
331
  // set cache
320
332
  flightData && Object.keys(flightData).forEach(k => query.set(k, flightData[k]));
321
333
  // trigger revalidation
322
- await revalidate(keys, false);
334
+ revalidate(keys, false);
323
335
  }
324
336
  async function handleResponse(response, error, navigate, metadataHandled) {
325
337
  let data;
@@ -336,14 +348,11 @@ async function handleResponse(response, error, navigate, metadataHandled) {
336
348
  // carry a codec-encoded body the router decodes itself. With the
337
349
  // flight-data consumer registered single-flight payloads never reach
338
350
  // this path, but a manually opted-in call (no consumer) still can —
339
- // unwrap the standardized { value, data } shape for it too.
351
+ // the runtime splits its own envelope shape.
340
352
  if (response.body) {
341
- data = await decodeResponse(response);
342
- if (response.headers.has("X-Single-Flight")) {
343
- const payload = data;
344
- data = payload.value;
345
- flightData = payload.data;
346
- }
353
+ const payload = await decodeResponsePayload(response);
354
+ data = payload.value;
355
+ flightData = payload.flightData;
347
356
  }
348
357
  }
349
358
  else if (error)
@@ -354,6 +363,6 @@ async function handleResponse(response, error, navigate, metadataHandled) {
354
363
  // function's unwrapped value. Do not treat that value as a second plain
355
364
  // action response and invalidate the freshly seeded query cache again.
356
365
  if (!metadataHandled || metadata || flightData)
357
- await applyResponseMetadata(metadata, navigate, flightData);
366
+ applyResponseMetadata(metadata, navigate, flightData);
358
367
  return data != null ? { data } : undefined;
359
368
  }
package/dist/fs.d.ts ADDED
@@ -0,0 +1,94 @@
1
+ import type { DefinedRouteFilters, RouteParams, RoutePreloadFunc, RoutePreloadFuncArgs, RouteInfo, RouteSectionComponent, StandardSchemaV1, TypedRouteConfig, ValidFilters } from "./types.js";
2
+ /**
3
+ * The type `defineFileRoute` hands back: `matchFilters` and `search` stay
4
+ * literal — and only present when provided precisely, which is what the
5
+ * `paths` machinery keys on once the manifest spreads this into the
6
+ * definition — while `preload` widens back to the plain contract. The
7
+ * pattern rides along as a phantom brand so `RouteProps<typeof route>`
8
+ * can type the file's component from the same witness.
9
+ */
10
+ export type FileRouteConfig<S extends string = string, T = unknown, F = undefined, Sch = undefined> = TypedRouteConfig<S> & ([F] extends [undefined] ? {} : DefinedRouteFilters<S> extends F ? {} : {
11
+ matchFilters: F;
12
+ }) & ([Sch] extends [undefined] ? {} : {
13
+ search: Sch;
14
+ }) & {
15
+ preload?: RoutePreloadFunc<T>;
16
+ info?: RouteInfo;
17
+ };
18
+ /**
19
+ * Identity helper for a route file's `route` export that types `preload`'s
20
+ * `args.params` from a pattern witness — the file's path pattern, which the
21
+ * manifest (not this string) still provides at runtime:
22
+ *
23
+ * ```ts
24
+ * // routes/blog/[id].tsx
25
+ * export const route = defineFileRoute("/blog/:id", {
26
+ * matchFilters: { id: int },
27
+ * preload: ({ params }) => getPost(params.id) // params.id: string
28
+ * });
29
+ *
30
+ * export default function Post(props: RouteProps<typeof route>) {} // params *and* data typed
31
+ * ```
32
+ *
33
+ * `matchFilters` are validated against the pattern's params, and their
34
+ * types (and any `search` schema) flow through the manifest into `paths`.
35
+ */
36
+ export declare function defineFileRoute<S extends string, T = unknown, const F = DefinedRouteFilters<S>, Sch extends StandardSchemaV1<any, any> | undefined = undefined>(path: S, config: {
37
+ matchFilters?: F & ValidFilters<F, S>;
38
+ preload?: (args: RoutePreloadFuncArgs<RouteParams<S>>) => T;
39
+ /** Standard Schema validator for this route's search params; its input type flows into the typed path proxy. */
40
+ search?: Sch;
41
+ info?: RouteInfo;
42
+ }): FileRouteConfig<S, T, F, Sch>;
43
+ /** A code-split module ref: delivered as a dynamic import. */
44
+ export interface FileRouteLazyRef<M = Record<string, unknown>> {
45
+ src: string;
46
+ import(): Promise<M>;
47
+ }
48
+ /** An eager module ref: its picked exports are imported statically. */
49
+ export interface FileRouteEagerRef<M = Record<string, unknown>> {
50
+ require(): M;
51
+ }
52
+ /** The shape of a nested route-manifest entry the adapter consumes. */
53
+ export interface FileRouteEntry {
54
+ path: string;
55
+ page?: boolean;
56
+ $component?: FileRouteLazyRef<any> | undefined;
57
+ $$route?: FileRouteEagerRef<any> | undefined;
58
+ children?: readonly FileRouteEntry[] | undefined;
59
+ }
60
+ type RouteConfigOf<E> = E extends {
61
+ $$route: {
62
+ require(): {
63
+ route: infer R;
64
+ };
65
+ };
66
+ } ? R : {};
67
+ /**
68
+ * One manifest entry as a route definition. `children` is a required key on
69
+ * purpose: an optional key infers as `C | undefined`, and that union
70
+ * distributes `RoutePaths` into an uncallable shape.
71
+ */
72
+ export type FileRouteFrom<E> = RouteConfigOf<E> & {
73
+ path: E extends {
74
+ path: infer P extends string;
75
+ } ? P : never;
76
+ component: E extends {
77
+ $component: object;
78
+ } ? RouteSectionComponent : undefined;
79
+ children: E extends {
80
+ children: infer C extends readonly FileRouteEntry[];
81
+ } ? FileRoutesFrom<C> : undefined;
82
+ };
83
+ export type FileRoutesFrom<T extends readonly FileRouteEntry[]> = {
84
+ [K in keyof T]: FileRouteFrom<T[K]>;
85
+ };
86
+ /**
87
+ * Converts the nested page entries of a file-system route manifest into
88
+ * route definitions: `$component` refs become code-split `lazy` components
89
+ * (their `src` doubles as the `moduleUrl` core resolves assets and islands
90
+ * against), and each entry's `route` config export is spread into its
91
+ * definition. Pass the result to `createRouter({ routes })`.
92
+ */
93
+ export declare function fileRoutes<const T extends readonly FileRouteEntry[]>(entries: T): FileRoutesFrom<T>;
94
+ export {};
package/dist/fs.js ADDED
@@ -0,0 +1,51 @@
1
+ import { lazy } from "solid-js";
2
+ /**
3
+ * Identity helper for a route file's `route` export that types `preload`'s
4
+ * `args.params` from a pattern witness — the file's path pattern, which the
5
+ * manifest (not this string) still provides at runtime:
6
+ *
7
+ * ```ts
8
+ * // routes/blog/[id].tsx
9
+ * export const route = defineFileRoute("/blog/:id", {
10
+ * matchFilters: { id: int },
11
+ * preload: ({ params }) => getPost(params.id) // params.id: string
12
+ * });
13
+ *
14
+ * export default function Post(props: RouteProps<typeof route>) {} // params *and* data typed
15
+ * ```
16
+ *
17
+ * `matchFilters` are validated against the pattern's params, and their
18
+ * types (and any `search` schema) flow through the manifest into `paths`.
19
+ */
20
+ export function defineFileRoute(path, config) {
21
+ return config;
22
+ }
23
+ /**
24
+ * Converts the nested page entries of a file-system route manifest into
25
+ * route definitions: `$component` refs become code-split `lazy` components
26
+ * (their `src` doubles as the `moduleUrl` core resolves assets and islands
27
+ * against), and each entry's `route` config export is spread into its
28
+ * definition. Pass the result to `createRouter({ routes })`.
29
+ */
30
+ export function fileRoutes(entries) {
31
+ const components = new Map();
32
+ const componentOf = (ref) => {
33
+ let component = components.get(ref.src);
34
+ if (!component) {
35
+ component = lazy(ref.import, ref.src);
36
+ components.set(ref.src, component);
37
+ }
38
+ return component;
39
+ };
40
+ const toRoute = (entry) => {
41
+ const config = (entry.$$route?.require().route ?? {});
42
+ return {
43
+ ...config,
44
+ path: entry.path,
45
+ component: entry.$component ? componentOf(entry.$component) : undefined,
46
+ info: { ...config.info, filesystem: true },
47
+ children: entry.children ? entry.children.map(toRoute) : undefined
48
+ };
49
+ };
50
+ return entries.map(toRoute);
51
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,22 @@
1
+ /**
2
+ * Arbitrary metadata attached to routes via `info`, surfaced through
3
+ * `useRouteMatches` and the instance's `match()`. Declared here — in the
4
+ * package entry — so apps can augment it for typed, discoverable metadata:
5
+ *
6
+ * ```ts
7
+ * declare module "@solidjs/router" {
8
+ * interface RouteInfo {
9
+ * breadcrumb?: string;
10
+ * }
11
+ * }
12
+ * ```
13
+ *
14
+ * Declared keys are type-checked at route definitions and typed on reads;
15
+ * undeclared keys remain freeform.
16
+ */
17
+ export interface RouteInfo {
18
+ [key: string]: any;
19
+ }
1
20
  export * from "./routers/index.js";
2
21
  export * from "./lifecycle.js";
3
22
  export { useHref, useIsRouting, useLinkState, useLocation, useMatch, useNavigate, usePreloadRoute, useParams, useResolvedPath, useRouteMatches, useSearchParams, RouterContextObj as RouterContext } from "./routing.js";
@@ -6,4 +25,4 @@ export { mergeSearchString as _mergeSearchString } from "./utils.js";
6
25
  export { int } from "./paths.js";
7
26
  export type { RoutePaths, PathParamsOf, PathEnd, TypedMatchFilter, DefaultSearchTypes } from "./paths.js";
8
27
  export * from "./data/index.js";
9
- export type { Location, LocationChange, SearchParams, MatchFilter, MatchFilters, NavigateOptions, Navigator, OutputMatch, Params, PathMatch, RouteSectionProps, RoutePreloadFunc, RoutePreloadFuncArgs, RouteDefinition, RouteDescription, RouteMatch, RouterIntegration, RouterUtils, SetParams, SetSearchParams, Submission, BeforeLeaveEventArgs, TypedPath, TypedSearchPath, StandardSchemaV1 } from "./types.js";
28
+ export type { Location, LocationChange, SearchParams, MatchFilter, MatchFilters, NavigateOptions, Navigator, OutputMatch, Params, PathMatch, RouteComponent, RouteParams, RouteProps, RouteSectionProps, RoutePreloadFunc, RoutePreloadFuncArgs, RouteDefinition, RouteDescription, RouteMatch, RouterIntegration, RouterUtils, SetParams, SetSearchParams, Submission, BeforeLeaveEventArgs, TypedPath, TypedSearchPath, StandardSchemaV1 } from "./types.js";