@tanstack/router-core 0.0.1-beta.161 → 0.0.1-beta.163

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.
@@ -14,7 +14,7 @@ import { Store } from '@tanstack/react-store';
14
14
 
15
15
  interface RouterHistory {
16
16
  location: RouterLocation;
17
- listen: (cb: () => void) => () => void;
17
+ subscribe: (cb: () => void) => () => void;
18
18
  push: (path: string, state?: any) => void;
19
19
  replace: (path: string, state?: any) => void;
20
20
  go: (index: number) => void;
@@ -114,8 +114,8 @@ type RouteByPath<TRouteTree extends AnyRoute, TPath> = Extract<ParseRoute<TRoute
114
114
  fullPath: TPath;
115
115
  }>;
116
116
  type RoutePaths<TRouteTree extends AnyRoute> = ParseRoute<TRouteTree>['fullPath'] | '/';
117
- type FullSearchSchema<TRouteTree extends AnyRoute> = MergeUnion<ParseRoute<TRouteTree>['__types']['fullSearchSchema']> & {};
118
- type AllParams<TRouteTree extends AnyRoute> = MergeUnion<ParseRoute<TRouteTree>['__types']['allParams']>;
117
+ type FullSearchSchema<TRouteTree extends AnyRoute> = MergeUnion<ParseRoute<TRouteTree>['types']['fullSearchSchema']> & {};
118
+ type AllParams<TRouteTree extends AnyRoute> = MergeUnion<ParseRoute<TRouteTree>['types']['allParams']>;
119
119
 
120
120
  declare global {
121
121
  interface Window {
@@ -156,7 +156,7 @@ interface RouteMatch<TRouteTree extends AnyRoute = AnyRoute, TRoute extends AnyR
156
156
  key?: string;
157
157
  routeId: string;
158
158
  pathname: string;
159
- params: TRoute['__types']['allParams'];
159
+ params: TRoute['types']['allParams'];
160
160
  status: 'pending' | 'success' | 'error';
161
161
  isFetching: boolean;
162
162
  invalid: boolean;
@@ -166,21 +166,21 @@ interface RouteMatch<TRouteTree extends AnyRoute = AnyRoute, TRoute extends AnyR
166
166
  updatedAt: number;
167
167
  invalidAt: number;
168
168
  preloadInvalidAt: number;
169
- loaderData: TRoute['__types']['loader'];
169
+ loaderData: TRoute['types']['loader'];
170
170
  loadPromise?: Promise<void>;
171
171
  __resolveLoadPromise?: () => void;
172
- routeContext: TRoute['__types']['routeContext'];
173
- context: TRoute['__types']['context'];
174
- routeSearch: TRoute['__types']['searchSchema'];
175
- search: FullSearchSchema<TRouteTree> & TRoute['__types']['fullSearchSchema'];
172
+ routeContext: TRoute['types']['routeContext'];
173
+ context: TRoute['types']['context'];
174
+ routeSearch: TRoute['types']['searchSchema'];
175
+ search: FullSearchSchema<TRouteTree> & TRoute['types']['fullSearchSchema'];
176
176
  fetchedAt: number;
177
177
  abortController: AbortController;
178
178
  }
179
179
  type AnyRouteMatch = RouteMatch<AnyRoute, AnyRoute>;
180
- type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext extends TRouteTree['__types']['routerContext'] ? {
181
- context?: TRouteTree['__types']['routerContext'];
180
+ type RouterContextOptions<TRouteTree extends AnyRoute> = AnyContext extends TRouteTree['types']['routerContext'] ? {
181
+ context?: TRouteTree['types']['routerContext'];
182
182
  } : {
183
- context: TRouteTree['__types']['routerContext'];
183
+ context: TRouteTree['types']['routerContext'];
184
184
  };
185
185
  interface RouterOptions<TRouteTree extends AnyRoute, TDehydrated extends Record<string, any>> {
186
186
  history?: RouterHistory;
@@ -201,8 +201,7 @@ interface RouterOptions<TRouteTree extends AnyRoute, TDehydrated extends Record<
201
201
  route: AnyRoute;
202
202
  router: AnyRouter;
203
203
  }) => void;
204
- onRouteChange?: () => void;
205
- context?: TRouteTree['__types']['routerContext'];
204
+ context?: TRouteTree['types']['routerContext'];
206
205
  Wrap?: React.ComponentType<{
207
206
  children: React.ReactNode;
208
207
  dehydratedState?: TDehydrated;
@@ -222,7 +221,7 @@ interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {
222
221
  resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>;
223
222
  lastUpdated: number;
224
223
  }
225
- type ListenerFn = () => void;
224
+ type ListenerFn<TEvent extends RouterEvent> = (event: TEvent) => void;
226
225
  interface BuildNextOptions {
227
226
  to?: string | number | null;
228
227
  params?: true | Updater<unknown>;
@@ -254,6 +253,25 @@ interface DehydratedRouter {
254
253
  }
255
254
  type RouterConstructorOptions<TRouteTree extends AnyRoute, TDehydrated extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TDehydrated>, 'context'> & RouterContextOptions<TRouteTree>;
256
255
  declare const componentTypes: readonly ["component", "errorComponent", "pendingComponent"];
256
+ type RouterEvents = {
257
+ onBeforeLoad: {
258
+ type: 'onBeforeLoad';
259
+ from: ParsedLocation;
260
+ to: ParsedLocation;
261
+ pathChanged: boolean;
262
+ };
263
+ onLoad: {
264
+ type: 'onLoad';
265
+ from: ParsedLocation;
266
+ to: ParsedLocation;
267
+ pathChanged: boolean;
268
+ };
269
+ };
270
+ type RouterEvent = RouterEvents[keyof RouterEvents];
271
+ type RouterListener<TRouterEvent extends RouterEvent> = {
272
+ eventType: TRouterEvent['type'];
273
+ fn: ListenerFn<TRouterEvent>;
274
+ };
257
275
  declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated extends Record<string, any> = Record<string, any>> {
258
276
  #private;
259
277
  types: {
@@ -273,6 +291,8 @@ declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated extends
273
291
  state: RouterState<TRouteTree>;
274
292
  dehydratedData?: TDehydrated;
275
293
  constructor(options: RouterConstructorOptions<TRouteTree, TDehydrated>);
294
+ subscribers: Set<RouterListener<RouterEvent>>;
295
+ subscribe: <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
276
296
  reset: () => void;
277
297
  mount: () => void;
278
298
  update: (opts?: RouterOptions<any, any>) => this;
@@ -303,7 +323,7 @@ declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated extends
303
323
  reload: () => Promise<void>;
304
324
  resolvePath: (from: string, path: string) => string;
305
325
  navigate: <TFrom extends RoutePaths<TRouteTree> = "/", TTo extends string = "">({ from, to, search, hash, replace, params, }: NavigateOptions<TRouteTree, TFrom, TTo>) => Promise<void>;
306
- matchRoute: <TFrom extends RoutePaths<TRouteTree> = "/", TTo extends string = "", TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>>(location: ToOptions<TRouteTree, TFrom, TTo, ResolveRelativePath<TFrom, NoInfer<TTo>>>, opts?: MatchRouteOptions) => false | RouteById<TRouteTree, TResolved>["__types"]["allParams"];
326
+ matchRoute: <TFrom extends RoutePaths<TRouteTree> = "/", TTo extends string = "", TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>>(location: ToOptions<TRouteTree, TFrom, TTo, ResolveRelativePath<TFrom, NoInfer<TTo>>>, opts?: MatchRouteOptions) => false | RouteById<TRouteTree, TResolved>["types"]["allParams"];
307
327
  buildLink: <TFrom extends RoutePaths<TRouteTree> = "/", TTo extends string = "">({ from, to, search, params, hash, target, replace, activeOptions, preload, preloadDelay: userPreloadDelay, disabled, state, }: LinkOptions<TRouteTree, TFrom, TTo>) => LinkInfo;
308
328
  dehydrate: () => DehydratedRouter;
309
329
  hydrate: (__do_not_use_server_ctx?: HydrationCtx) => Promise<void>;
@@ -374,7 +394,7 @@ type MetaOptions = keyof PickRequired<RouteMeta> extends never ? {
374
394
  type AnyRouteProps = RouteProps<any, any, any, any, any>;
375
395
  type ComponentPropsFromRoute<TRoute> = TRoute extends Route<infer TParentRoute, infer TPath, infer TFullPath, infer TCustomId, infer TId, infer TLoader, infer TSearchSchema, infer TFullSearchSchema, infer TParams, infer TAllParams, infer TParentContext, infer TAllParentContext, infer TRouteContext, infer TContext, infer TRouterContext, infer TChildren, infer TRouteTree> ? RouteProps<TLoader, TFullSearchSchema, TAllParams, TRouteContext, TContext> : never;
376
396
  type ComponentFromRoute<TRoute> = RegisteredRouteComponent<ComponentPropsFromRoute<TRoute>>;
377
- type RouteLoaderFromRoute<TRoute extends AnyRoute> = LoaderFn<TRoute['__types']['loader'], TRoute['__types']['searchSchema'], TRoute['__types']['fullSearchSchema'], TRoute['__types']['allParams'], TRoute['__types']['routeContext'], TRoute['__types']['context']>;
397
+ type RouteLoaderFromRoute<TRoute extends AnyRoute> = LoaderFn<TRoute['types']['loader'], TRoute['types']['searchSchema'], TRoute['types']['fullSearchSchema'], TRoute['types']['allParams'], TRoute['types']['routeContext'], TRoute['types']['context']>;
378
398
  type RouteProps<TLoader extends any = unknown, TFullSearchSchema extends AnySearchSchema = AnySearchSchema, TAllParams extends AnyPathParams = AnyPathParams, TRouteContext extends AnyContext = AnyContext, TContext extends AnyContext = AnyContext> = {
379
399
  useMatch: () => RouteMatch<any, any>;
380
400
  useLoader: () => UseLoaderResult<TLoader>;
@@ -437,10 +457,6 @@ type UpdatableRouteOptions<TLoader, TSearchSchema extends AnySearchSchema, TFull
437
457
  maxAge?: number;
438
458
  gcMaxAge?: number;
439
459
  beforeLoad?: (opts: LoaderContext<TSearchSchema, TFullSearchSchema, TAllParams, NoInfer<TRouteContext>, TContext>) => Promise<void> | void;
440
- onBeforeLoadError?: (err: any) => void;
441
- onValidateSearchError?: (err: any) => void;
442
- onParseParamsError?: (err: any) => void;
443
- onLoadError?: (err: any) => void;
444
460
  onError?: (err: any) => void;
445
461
  onLoaded?: (matchContext: {
446
462
  params: TAllParams;
@@ -491,11 +507,11 @@ type ResolveId<TParentRoute, TCustomId extends string, TPath extends string> = T
491
507
  } ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId> : RootRouteId;
492
508
  type InferFullSearchSchema<TRoute> = TRoute extends {
493
509
  isRoot: true;
494
- __types: {
510
+ types: {
495
511
  searchSchema: infer TSearchSchema;
496
512
  };
497
513
  } ? TSearchSchema : TRoute extends {
498
- __types: {
514
+ types: {
499
515
  fullSearchSchema: infer TFullSearchSchema;
500
516
  };
501
517
  } ? TFullSearchSchema : {};
@@ -531,8 +547,8 @@ type RouteConstraints = {
531
547
  TChildren: unknown;
532
548
  TRouteTree: AnyRoute;
533
549
  };
534
- declare class Route<TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, TPath extends RouteConstraints['TPath'] = '/', TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, TCustomId extends RouteConstraints['TCustomId'] = string, TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, TLoader = unknown, TSearchSchema extends RouteConstraints['TSearchSchema'] = {}, TFullSearchSchema extends RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends RouteConstraints['TParams'] = Record<ParsePathParams<TPath>, string>, TAllParams extends RouteConstraints['TAllParams'] = MergeParamsFromParent<TParentRoute['__types']['allParams'], TParams>, TParentContext extends RouteConstraints['TParentContext'] = TParentRoute['__types']['routeContext'], TAllParentContext extends RouteConstraints['TAllParentContext'] = TParentRoute['__types']['context'], TRouteContext extends RouteConstraints['TRouteContext'] = RouteContext, TAllContext extends RouteConstraints['TAllContext'] = MergeParamsFromParent<TParentRoute['__types']['context'], TRouteContext>, TRouterContext extends RouteConstraints['TRouterContext'] = AnyContext, TChildren extends RouteConstraints['TChildren'] = unknown, TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute> {
535
- __types: {
550
+ declare class Route<TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, TPath extends RouteConstraints['TPath'] = '/', TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, TCustomId extends RouteConstraints['TCustomId'] = string, TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, TLoader = unknown, TSearchSchema extends RouteConstraints['TSearchSchema'] = {}, TFullSearchSchema extends RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends RouteConstraints['TParams'] = Record<ParsePathParams<TPath>, string>, TAllParams extends RouteConstraints['TAllParams'] = MergeParamsFromParent<TParentRoute['types']['allParams'], TParams>, TParentContext extends RouteConstraints['TParentContext'] = TParentRoute['types']['routeContext'], TAllParentContext extends RouteConstraints['TAllParentContext'] = TParentRoute['types']['context'], TRouteContext extends RouteConstraints['TRouteContext'] = RouteContext, TAllContext extends RouteConstraints['TAllContext'] = MergeParamsFromParent<TParentRoute['types']['context'], TRouteContext>, TRouterContext extends RouteConstraints['TRouterContext'] = AnyContext, TChildren extends RouteConstraints['TChildren'] = unknown, TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute> {
551
+ types: {
536
552
  parentRoute: TParentRoute;
537
553
  path: TPath;
538
554
  to: TrimPathRight<TFullPath>;
@@ -593,12 +609,12 @@ type TrimLeft<T extends string, S extends string> = T extends `${S}${infer U}` ?
593
609
  type TrimRight<T extends string, S extends string> = T extends `${infer U}${S}` ? U : T;
594
610
  type Trim<T extends string, S extends string> = TrimLeft<TrimRight<T, S>, S>;
595
611
  type RemoveUnderScores<T extends string> = Replace<Replace<TrimRight<TrimLeft<T, '/_'>, '_'>, '_/', '/'>, '/_', '/'>;
596
- type ResolveFilePath<TParentRoute extends AnyRoute, TFilePath extends string> = TParentRoute['id'] extends RootRouteId ? TrimPathLeft<TFilePath> : Replace<TrimPathLeft<TFilePath>, TrimPathLeft<TParentRoute['__types']['customId']>, ''>;
612
+ type ResolveFilePath<TParentRoute extends AnyRoute, TFilePath extends string> = TParentRoute['id'] extends RootRouteId ? TrimPathLeft<TFilePath> : Replace<TrimPathLeft<TFilePath>, TrimPathLeft<TParentRoute['types']['customId']>, ''>;
597
613
  type FileRoutePath<TParentRoute extends AnyRoute, TFilePath extends string> = ResolveFilePath<TParentRoute, TFilePath> extends `_${infer _}` ? string : ResolveFilePath<TParentRoute, TFilePath>;
598
614
  declare class FileRoute<TFilePath extends keyof FileRoutesByPath, TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'], TId extends RouteConstraints['TId'] = TFilePath, TPath extends RouteConstraints['TPath'] = FileRoutePath<TParentRoute, TFilePath>, TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, RemoveUnderScores<TPath>>> {
599
615
  path: TFilePath;
600
616
  constructor(path: TFilePath);
601
- createRoute: <TLoader = unknown, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<string, any> = (TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> extends infer T ? T extends TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> ? T extends `$${infer L}` ? L : never : never : never) extends never ? AnyPathParams : Record<TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> extends infer T ? T extends TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> ? T extends `$${infer L}` ? L : never : never : never, string>, TAllParams extends Record<string, any> = IsAny<TParentRoute["__types"]["allParams"], TParams, TParentRoute["__types"]["allParams"] & TParams>, TParentContext extends AnyContext = TParentRoute["__types"]["routeContext"], TAllParentContext extends string = TParentRoute["__types"]["context"], TRouteContext extends RouteContext = RouteContext, TContext extends AnyContext = IsAny<TParentRoute["__types"]["context"], TRouteContext, TParentRoute["__types"]["context"] & TRouteContext>, TRouterContext extends AnyContext = AnyContext, TChildren extends unknown = unknown, TRouteTree extends AnyRoute = AnyRoute>(options: Omit<RouteOptions<TParentRoute, string, string, TLoader, InferFullSearchSchema<TParentRoute>, TSearchSchema, TFullSearchSchema, TParams, TAllParams, TParentContext, TAllParentContext, TRouteContext, TContext>, "id" | "path" | "getParentRoute"> & {
617
+ createRoute: <TLoader = unknown, TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<string, any> = (TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> extends infer T ? T extends TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> ? T extends `$${infer L}` ? L : never : never : never) extends never ? AnyPathParams : Record<TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> extends infer T ? T extends TrimLeft<TrimRight<Split<TPath, true>[number], "_">, "_"> ? T extends `$${infer L}` ? L : never : never : never, string>, TAllParams extends Record<string, any> = IsAny<TParentRoute["types"]["allParams"], TParams, TParentRoute["types"]["allParams"] & TParams>, TParentContext extends AnyContext = TParentRoute["types"]["routeContext"], TAllParentContext extends string = TParentRoute["types"]["context"], TRouteContext extends RouteContext = RouteContext, TContext extends AnyContext = IsAny<TParentRoute["types"]["context"], TRouteContext, TParentRoute["types"]["context"] & TRouteContext>, TRouterContext extends AnyContext = AnyContext, TChildren extends unknown = unknown, TRouteTree extends AnyRoute = AnyRoute>(options: Omit<RouteOptions<TParentRoute, string, string, TLoader, InferFullSearchSchema<TParentRoute>, TSearchSchema, TFullSearchSchema, TParams, TAllParams, TParentContext, TAllParentContext, TRouteContext, TContext>, "id" | "path" | "getParentRoute"> & {
602
618
  meta?: RouteMeta | undefined;
603
619
  } & {
604
620
  key?: false | GetKeyFn<TFullSearchSchema, TAllParams> | null | undefined;
@@ -615,10 +631,6 @@ declare class FileRoute<TFilePath extends keyof FileRoutesByPath, TParentRoute e
615
631
  maxAge?: number | undefined;
616
632
  gcMaxAge?: number | undefined;
617
633
  beforeLoad?: ((opts: LoaderContext<TSearchSchema, TFullSearchSchema, TAllParams, NoInfer<TRouteContext>, TContext>) => void | Promise<void>) | undefined;
618
- onBeforeLoadError?: ((err: any) => void) | undefined;
619
- onValidateSearchError?: ((err: any) => void) | undefined;
620
- onParseParamsError?: ((err: any) => void) | undefined;
621
- onLoadError?: ((err: any) => void) | undefined;
622
634
  onError?: ((err: any) => void) | undefined;
623
635
  onLoaded?: ((matchContext: {
624
636
  params: TAllParams;
@@ -677,7 +689,7 @@ type ToOptions<TRouteTree extends AnyRoute = AnyRoute, TFrom extends RoutePaths<
677
689
  state?: LocationState;
678
690
  from?: TFrom;
679
691
  } & CheckPath<TRouteTree, NoInfer<TResolvedTo>, {}> & SearchParamOptions<TRouteTree, TFrom, TResolvedTo> & PathParamOptions<TRouteTree, TFrom, TResolvedTo>;
680
- type SearchParamOptions<TRouteTree extends AnyRoute, TFrom, TTo, TFromSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & RouteByPath<TRouteTree, TFrom> extends never ? {} : RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']>, TToSchema = Partial<RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']> & Omit<RouteByPath<TRouteTree, TTo>['__types']['fullSearchSchema'], keyof PickRequired<RouteByPath<TRouteTree, TFrom>['__types']['fullSearchSchema']>>, TFromFullSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & TFromSchema>, TToFullSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
692
+ type SearchParamOptions<TRouteTree extends AnyRoute, TFrom, TTo, TFromSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & RouteByPath<TRouteTree, TFrom> extends never ? {} : RouteByPath<TRouteTree, TFrom>['types']['fullSearchSchema']>, TToSchema = Partial<RouteByPath<TRouteTree, TFrom>['types']['fullSearchSchema']> & Omit<RouteByPath<TRouteTree, TTo>['types']['fullSearchSchema'], keyof PickRequired<RouteByPath<TRouteTree, TFrom>['types']['fullSearchSchema']>>, TFromFullSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & TFromSchema>, TToFullSchema = UnionToIntersection<FullSearchSchema<TRouteTree> & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
681
693
  search?: true | SearchReducer<TFromFullSchema, TToFullSchema>;
682
694
  } : {
683
695
  search: SearchReducer<TFromFullSchema, TToFullSchema>;
@@ -685,7 +697,7 @@ type SearchParamOptions<TRouteTree extends AnyRoute, TFrom, TTo, TFromSchema = U
685
697
  type SearchReducer<TFrom, TTo> = {
686
698
  [TKey in keyof TTo]: TTo[TKey];
687
699
  } | ((current: TFrom) => TTo);
688
- type PathParamOptions<TRouteTree extends AnyRoute, TFrom, TTo, TFromSchema = UnionToIntersection<RouteByPath<TRouteTree, TFrom> extends never ? {} : RouteByPath<TRouteTree, TFrom>['__types']['allParams']>, TToSchema = Partial<RouteByPath<TRouteTree, TFrom>['__types']['allParams']> & Omit<RouteByPath<TRouteTree, TTo>['__types']['allParams'], keyof PickRequired<RouteByPath<TRouteTree, TFrom>['__types']['allParams']>>, TFromFullParams = UnionToIntersection<AllParams<TRouteTree> & TFromSchema>, TToFullParams = UnionToIntersection<AllParams<TRouteTree> & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
700
+ type PathParamOptions<TRouteTree extends AnyRoute, TFrom, TTo, TFromSchema = UnionToIntersection<RouteByPath<TRouteTree, TFrom> extends never ? {} : RouteByPath<TRouteTree, TFrom>['types']['allParams']>, TToSchema = Partial<RouteByPath<TRouteTree, TFrom>['types']['allParams']> & Omit<RouteByPath<TRouteTree, TTo>['types']['allParams'], keyof PickRequired<RouteByPath<TRouteTree, TFrom>['types']['allParams']>>, TFromFullParams = UnionToIntersection<AllParams<TRouteTree> & TFromSchema>, TToFullParams = UnionToIntersection<AllParams<TRouteTree> & TToSchema>> = keyof PickRequired<TToSchema> extends never ? {
689
701
  params?: ParamsReducer<TFromFullParams, TToFullParams>;
690
702
  } : {
691
703
  params: ParamsReducer<TFromFullParams, TToFullParams>;
@@ -743,4 +755,4 @@ declare const defaultStringifySearch: (search: Record<string, any>) => string;
743
755
  declare function parseSearchWith(parser: (str: string) => any): (searchStr: string) => AnySearchSchema;
744
756
  declare function stringifySearchWith(stringify: (search: any) => string, parser?: (str: string) => any): (search: Record<string, any>) => string;
745
757
 
746
- export { ActiveOptions, AllParams, AnyContext, AnyPathParams, AnyRedirect, AnyRootRoute, AnyRoute, AnyRouteMatch, AnyRouteProps, AnyRouter, AnySearchSchema, BaseRouteOptions, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, CleanPath, ComponentFromRoute, ComponentPropsFromRoute, DeepAwaited, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FileRoute, FileRoutePath, FileRoutesByPath, FromLocation, FullSearchSchema, GetKeyFn, HydrationCtx, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, Join, Last, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderFn, LocationState, MatchLocation, MatchRouteOptions, MergeParamsFromParent, MergeUnion, MetaOptions, NavigateOptions, NoInfer, ParamsFallback, ParentParams, ParseParamsFn, ParseParamsObj, ParseParamsOption, ParsePathParams, ParseRoute, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamError, PathParamMask, PathParamOptions, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, PreloadableObj, Redirect, Register, RegisterRouteComponent, RegisterRouteErrorComponent, RegisteredRouteComponent, RegisteredRouteErrorComponent, RegisteredRouter, RelativeToPathAutoComplete, RemoveUnderScores, ResolveFilePath, ResolveFullPath, ResolveFullSearchSchema, ResolveId, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteConstraints, RouteContext, RouteIds, RouteLoaderFromRoute, RouteMatch, RouteMeta, RouteOptions, RoutePathOptions, RoutePathOptionsIntersection, RoutePaths, RouteProps, Router, RouterConstructorOptions, RouterContext, RouterContextOptions, RouterHistory, RouterLocation, RouterOptions, RouterState, RoutesById, RoutesByPath, SearchFilter, SearchParamError, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, StreamedPromise, Timeout, ToIdOption, ToOptions, ToPathOption, Trim, TrimLeft, TrimPath, TrimPathLeft, TrimPathRight, TrimRight, UnionToIntersection, UnloaderFn, UpdatableRouteOptions, Updater, UseLoaderResult, UseLoaderResultPromise, ValueKeys, Values, cleanPath, componentTypes, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, isRedirect, joinPaths, last, lazyFn, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight };
758
+ export { ActiveOptions, AllParams, AnyContext, AnyPathParams, AnyRedirect, AnyRootRoute, AnyRoute, AnyRouteMatch, AnyRouteProps, AnyRouter, AnySearchSchema, BaseRouteOptions, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, CleanPath, ComponentFromRoute, ComponentPropsFromRoute, DeepAwaited, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FileRoute, FileRoutePath, FileRoutesByPath, FromLocation, FullSearchSchema, GetKeyFn, HydrationCtx, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, Join, Last, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderFn, LocationState, MatchLocation, MatchRouteOptions, MergeParamsFromParent, MergeUnion, MetaOptions, NavigateOptions, NoInfer, ParamsFallback, ParentParams, ParseParamsFn, ParseParamsObj, ParseParamsOption, ParsePathParams, ParseRoute, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamError, PathParamMask, PathParamOptions, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, PreloadableObj, Redirect, Register, RegisterRouteComponent, RegisterRouteErrorComponent, RegisteredRouteComponent, RegisteredRouteErrorComponent, RegisteredRouter, RelativeToPathAutoComplete, RemoveUnderScores, ResolveFilePath, ResolveFullPath, ResolveFullSearchSchema, ResolveId, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteConstraints, RouteContext, RouteIds, RouteLoaderFromRoute, RouteMatch, RouteMeta, RouteOptions, RoutePathOptions, RoutePathOptionsIntersection, RoutePaths, RouteProps, Router, RouterConstructorOptions, RouterContext, RouterContextOptions, RouterEvent, RouterEvents, RouterHistory, RouterListener, RouterLocation, RouterOptions, RouterState, RoutesById, RoutesByPath, SearchFilter, SearchParamError, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, StreamedPromise, Timeout, ToIdOption, ToOptions, ToPathOption, Trim, TrimLeft, TrimPath, TrimPathLeft, TrimPathRight, TrimRight, UnionToIntersection, UnloaderFn, UpdatableRouteOptions, Updater, UseLoaderResult, UseLoaderResultPromise, ValueKeys, Values, cleanPath, componentTypes, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, isRedirect, joinPaths, last, lazyFn, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight };
@@ -62,7 +62,7 @@
62
62
  function createHistory(opts) {
63
63
  let location = opts.getLocation();
64
64
  let unsub = () => {};
65
- let listeners = new Set();
65
+ let subscribers = new Set();
66
66
  let blockers = [];
67
67
  let queue = [];
68
68
  const tryFlush = () => {
@@ -76,7 +76,7 @@
76
76
  while (queue.length) {
77
77
  queue.shift()?.();
78
78
  }
79
- if (!opts.listener) {
79
+ if (!opts.subscriber) {
80
80
  onUpdate();
81
81
  }
82
82
  };
@@ -86,20 +86,20 @@
86
86
  };
87
87
  const onUpdate = () => {
88
88
  location = opts.getLocation();
89
- listeners.forEach(listener => listener());
89
+ subscribers.forEach(subscriber => subscriber());
90
90
  };
91
91
  return {
92
92
  get location() {
93
93
  return location;
94
94
  },
95
- listen: cb => {
96
- if (listeners.size === 0) {
97
- unsub = typeof opts.listener === 'function' ? opts.listener(onUpdate) : () => {};
95
+ subscribe: cb => {
96
+ if (subscribers.size === 0) {
97
+ unsub = typeof opts.subscriber === 'function' ? opts.subscriber(onUpdate) : () => {};
98
98
  }
99
- listeners.add(cb);
99
+ subscribers.add(cb);
100
100
  return () => {
101
- listeners.delete(cb);
102
- if (listeners.size === 0) {
101
+ subscribers.delete(cb);
102
+ if (subscribers.size === 0) {
103
103
  unsub();
104
104
  }
105
105
  };
@@ -152,7 +152,7 @@
152
152
  const getLocation = () => parseLocation(getHref(), history.state);
153
153
  return createHistory({
154
154
  getLocation,
155
- listener: onUpdate => {
155
+ subscriber: onUpdate => {
156
156
  window.addEventListener(pushStateEvent, onUpdate);
157
157
  window.addEventListener(popStateEvent, onUpdate);
158
158
  var pushState = window.history.pushState;
@@ -207,7 +207,7 @@
207
207
  const getLocation = () => parseLocation(entries[index], currentState);
208
208
  return createHistory({
209
209
  getLocation,
210
- listener: false,
210
+ subscriber: false,
211
211
  pushState: (path, state) => {
212
212
  currentState = {
213
213
  ...state,
@@ -848,6 +848,24 @@
848
848
  });
849
849
  }
850
850
  }
851
+ subscribers = new Set();
852
+ subscribe = (eventType, fn) => {
853
+ const listener = {
854
+ eventType,
855
+ fn
856
+ };
857
+ this.subscribers.add(listener);
858
+ return () => {
859
+ this.subscribers.delete(listener);
860
+ };
861
+ };
862
+ #emit = routerEvent => {
863
+ this.subscribers.forEach(listener => {
864
+ if (listener.eventType === routerEvent.type) {
865
+ listener.fn(routerEvent);
866
+ }
867
+ });
868
+ };
851
869
  reset = () => {
852
870
  this.__store.setState(s => Object.assign(s, getInitialRouterState()));
853
871
  };
@@ -878,7 +896,7 @@
878
896
  resolvedLocation: parsedLocation,
879
897
  location: parsedLocation
880
898
  }));
881
- this.#unsubHistory = this.history.listen(() => {
899
+ this.#unsubHistory = this.history.subscribe(() => {
882
900
  this.safeLoad({
883
901
  next: this.#parseLocation(this.state.location)
884
902
  });
@@ -920,6 +938,8 @@
920
938
  latestLoadPromise = Promise.resolve();
921
939
  load = async opts => {
922
940
  const promise = new Promise(async (resolve, reject) => {
941
+ const prevLocation = this.state.resolvedLocation;
942
+ const pathDidChange = !!(opts?.next && prevLocation.href !== opts.next.href);
923
943
  let latestPromise;
924
944
  const checkLatest = () => {
925
945
  return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
@@ -929,6 +949,12 @@
929
949
  // this.cancelMatches()
930
950
 
931
951
  let pendingMatches;
952
+ this.#emit({
953
+ type: 'onBeforeLoad',
954
+ from: prevLocation,
955
+ to: opts?.next ?? this.state.location,
956
+ pathChanged: pathDidChange
957
+ });
932
958
  this.__store.batch(() => {
933
959
  if (opts?.next) {
934
960
  // Ingest the new location
@@ -963,7 +989,6 @@
963
989
  if (latestPromise = checkLatest()) {
964
990
  return latestPromise;
965
991
  }
966
- const prevLocation = this.state.resolvedLocation;
967
992
  this.__store.setState(s => ({
968
993
  ...s,
969
994
  status: 'idle',
@@ -971,9 +996,12 @@
971
996
  matchIds: s.pendingMatchIds,
972
997
  pendingMatchIds: []
973
998
  }));
974
- if (prevLocation.href !== this.state.location.href) {
975
- this.options.onRouteChange?.();
976
- }
999
+ this.#emit({
1000
+ type: 'onLoad',
1001
+ from: prevLocation,
1002
+ to: this.state.location,
1003
+ pathChanged: pathDidChange
1004
+ });
977
1005
  resolve();
978
1006
  } catch (err) {
979
1007
  // Only apply the latest transition
@@ -1223,14 +1251,14 @@
1223
1251
  try {
1224
1252
  for (const [index, match] of resolvedMatches.entries()) {
1225
1253
  const route = this.getRoute(match.routeId);
1226
- const handleError = (err, handler) => {
1254
+ const handleError = (err, code) => {
1255
+ err.routerCode = code;
1227
1256
  firstBadMatchIndex = firstBadMatchIndex ?? index;
1228
- handler = handler || route.options.onError;
1229
1257
  if (isRedirect(err)) {
1230
1258
  throw err;
1231
1259
  }
1232
1260
  try {
1233
- handler?.(err);
1261
+ route.options.onError?.(err);
1234
1262
  } catch (errorHandlerErr) {
1235
1263
  err = errorHandlerErr;
1236
1264
  if (isRedirect(errorHandlerErr)) {
@@ -1245,10 +1273,10 @@
1245
1273
  }));
1246
1274
  };
1247
1275
  if (match.paramsError) {
1248
- handleError(match.paramsError, route.options.onParseParamsError);
1276
+ handleError(match.paramsError, 'PARSE_PARAMS');
1249
1277
  }
1250
1278
  if (match.searchError) {
1251
- handleError(match.searchError, route.options.onValidateSearchError);
1279
+ handleError(match.searchError, 'VALIDATE_SEARCH');
1252
1280
  }
1253
1281
  let didError = false;
1254
1282
  try {
@@ -1257,7 +1285,7 @@
1257
1285
  preload: !!opts?.preload
1258
1286
  });
1259
1287
  } catch (err) {
1260
- handleError(err, route.options.onBeforeLoadError);
1288
+ handleError(err, 'BEFORE_LOAD');
1261
1289
  didError = true;
1262
1290
  }
1263
1291
 
@@ -1315,28 +1343,18 @@
1315
1343
  const [_, loader] = await Promise.all([componentsPromise, loaderPromise]);
1316
1344
  if (latestPromise = checkLatest()) return await latestPromise;
1317
1345
  this.setRouteMatchData(match.id, () => loader, opts);
1318
- } catch (loaderError) {
1319
- let latestError = loaderError;
1346
+ } catch (error) {
1320
1347
  if (latestPromise = checkLatest()) return await latestPromise;
1321
- if (handleIfRedirect(loaderError)) return;
1322
- if (route.options.onLoadError) {
1323
- try {
1324
- route.options.onLoadError(loaderError);
1325
- } catch (onLoadError) {
1326
- latestError = onLoadError;
1327
- if (handleIfRedirect(onLoadError)) return;
1328
- }
1329
- }
1330
- if ((!route.options.onLoadError || latestError !== loaderError) && route.options.onError) {
1331
- try {
1332
- route.options.onError(latestError);
1333
- } catch (onErrorError) {
1334
- if (handleIfRedirect(onErrorError)) return;
1335
- }
1348
+ if (handleIfRedirect(error)) return;
1349
+ try {
1350
+ route.options.onError?.(error);
1351
+ } catch (onErrorError) {
1352
+ error = onErrorError;
1353
+ if (handleIfRedirect(onErrorError)) return;
1336
1354
  }
1337
1355
  this.setRouteMatch(match.id, s => ({
1338
1356
  ...s,
1339
- error: loaderError,
1357
+ error,
1340
1358
  status: 'error',
1341
1359
  isFetching: false,
1342
1360
  updatedAt: Date.now()