@tanstack/react-router 1.34.3 → 1.34.6

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.
Files changed (66) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +5 -8
  3. package/dist/cjs/RouterProvider.cjs.map +1 -1
  4. package/dist/cjs/RouterProvider.d.cts +3 -1
  5. package/dist/cjs/Transitioner.cjs +1 -0
  6. package/dist/cjs/Transitioner.cjs.map +1 -1
  7. package/dist/cjs/fileRoute.cjs.map +1 -1
  8. package/dist/cjs/fileRoute.d.cts +2 -2
  9. package/dist/cjs/route.cjs.map +1 -1
  10. package/dist/cjs/route.d.cts +11 -11
  11. package/dist/cjs/routeInfo.d.cts +6 -13
  12. package/dist/cjs/router.cjs +16 -8
  13. package/dist/cjs/router.cjs.map +1 -1
  14. package/dist/cjs/router.d.cts +8 -2
  15. package/dist/cjs/useLoaderData.cjs.map +1 -1
  16. package/dist/cjs/useLoaderData.d.cts +3 -2
  17. package/dist/cjs/useMatch.cjs.map +1 -1
  18. package/dist/cjs/useMatch.d.cts +3 -2
  19. package/dist/cjs/useParams.cjs.map +1 -1
  20. package/dist/cjs/useParams.d.cts +4 -3
  21. package/dist/cjs/useRouteContext.cjs.map +1 -1
  22. package/dist/cjs/useRouteContext.d.cts +5 -4
  23. package/dist/cjs/useSearch.cjs.map +1 -1
  24. package/dist/cjs/useSearch.d.cts +3 -2
  25. package/dist/cjs/utils.cjs.map +1 -1
  26. package/dist/cjs/utils.d.cts +12 -9
  27. package/dist/esm/Matches.d.ts +5 -8
  28. package/dist/esm/Matches.js.map +1 -1
  29. package/dist/esm/RouterProvider.d.ts +3 -1
  30. package/dist/esm/RouterProvider.js.map +1 -1
  31. package/dist/esm/Transitioner.js +1 -0
  32. package/dist/esm/Transitioner.js.map +1 -1
  33. package/dist/esm/fileRoute.d.ts +2 -2
  34. package/dist/esm/fileRoute.js.map +1 -1
  35. package/dist/esm/route.d.ts +11 -11
  36. package/dist/esm/route.js.map +1 -1
  37. package/dist/esm/routeInfo.d.ts +6 -13
  38. package/dist/esm/router.d.ts +8 -2
  39. package/dist/esm/router.js +16 -8
  40. package/dist/esm/router.js.map +1 -1
  41. package/dist/esm/useLoaderData.d.ts +3 -2
  42. package/dist/esm/useLoaderData.js.map +1 -1
  43. package/dist/esm/useMatch.d.ts +3 -2
  44. package/dist/esm/useMatch.js.map +1 -1
  45. package/dist/esm/useParams.d.ts +4 -3
  46. package/dist/esm/useParams.js.map +1 -1
  47. package/dist/esm/useRouteContext.d.ts +5 -4
  48. package/dist/esm/useRouteContext.js.map +1 -1
  49. package/dist/esm/useSearch.d.ts +3 -2
  50. package/dist/esm/useSearch.js.map +1 -1
  51. package/dist/esm/utils.d.ts +12 -9
  52. package/dist/esm/utils.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/Matches.tsx +21 -27
  55. package/src/RouterProvider.tsx +3 -1
  56. package/src/Transitioner.tsx +1 -6
  57. package/src/fileRoute.ts +1 -1
  58. package/src/route.ts +13 -17
  59. package/src/routeInfo.ts +17 -23
  60. package/src/router.ts +26 -12
  61. package/src/useLoaderData.tsx +18 -9
  62. package/src/useMatch.tsx +12 -7
  63. package/src/useParams.tsx +14 -10
  64. package/src/useRouteContext.ts +16 -6
  65. package/src/useSearch.tsx +15 -10
  66. package/src/utils.ts +40 -18
@@ -1,8 +1,9 @@
1
1
  import { AnyRoute } from './route.js';
2
2
  import { AllParams, RouteById, RouteIds } from './routeInfo.js';
3
3
  import { RegisteredRouter } from './router.js';
4
- import { Expand, StrictOrFrom } from './utils.js';
4
+ import { StrictOrFrom } from './utils.js';
5
5
 
6
- export declare function useParams<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TReturnIntersection extends boolean = false, TParams = TReturnIntersection extends false ? RouteById<TRouteTree, TFrom>['types']['allParams'] : Expand<Partial<AllParams<TRouteTree>>>, TSelected = TParams>(opts: StrictOrFrom<TFrom, TReturnIntersection> & {
6
+ export type UseParamsOptions<TFrom, TStrict extends boolean, TParams, TSelected> = StrictOrFrom<TFrom, TStrict> & {
7
7
  select?: (params: TParams) => TSelected;
8
- }): TSelected;
8
+ };
9
+ export declare function useParams<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TStrict extends boolean = true, TParams = TStrict extends false ? AllParams<TRouteTree> : RouteById<TRouteTree, TFrom>['types']['allParams'], TSelected = TParams>(opts: UseParamsOptions<TFrom, TStrict, TParams, TSelected>): TSelected;
@@ -1 +1 @@
1
- {"version":3,"file":"useParams.js","sources":["../../src/useParams.tsx"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { AnyRoute } from './route'\nimport type { AllParams, RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { Expand } from './utils'\nimport type { StrictOrFrom } from './utils'\n\nexport function useParams<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TReturnIntersection extends boolean = false,\n TParams = TReturnIntersection extends false\n ? RouteById<TRouteTree, TFrom>['types']['allParams']\n : Expand<Partial<AllParams<TRouteTree>>>,\n TSelected = TParams,\n>(\n opts: StrictOrFrom<TFrom, TReturnIntersection> & {\n select?: (params: TParams) => TSelected\n },\n): TSelected {\n return useMatch({\n ...opts,\n select: (match) => {\n return opts.select ? opts.select(match.params as TParams) : match.params\n },\n }) as TSelected\n}\n"],"names":[],"mappings":";AAOO,SAAS,UASd,MAGW;AACX,SAAO,SAAS;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,CAAC,UAAU;AACjB,aAAO,KAAK,SAAS,KAAK,OAAO,MAAM,MAAiB,IAAI,MAAM;AAAA,IACpE;AAAA,EAAA,CACD;AACH;"}
1
+ {"version":3,"file":"useParams.js","sources":["../../src/useParams.tsx"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { AnyRoute } from './route'\nimport type { AllParams, RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { StrictOrFrom } from './utils'\n\nexport type UseParamsOptions<\n TFrom,\n TStrict extends boolean,\n TParams,\n TSelected,\n> = StrictOrFrom<TFrom, TStrict> & {\n select?: (params: TParams) => TSelected\n}\n\nexport function useParams<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n TParams = TStrict extends false\n ? AllParams<TRouteTree>\n : RouteById<TRouteTree, TFrom>['types']['allParams'],\n TSelected = TParams,\n>(opts: UseParamsOptions<TFrom, TStrict, TParams, TSelected>): TSelected {\n return useMatch({\n ...opts,\n select: (match) => {\n return opts.select ? opts.select(match.params as TParams) : match.params\n },\n }) as TSelected\n}\n"],"names":[],"mappings":";AAeO,SAAS,UAQd,MAAuE;AACvE,SAAO,SAAS;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,CAAC,UAAU;AACjB,aAAO,KAAK,SAAS,KAAK,OAAO,MAAM,MAAiB,IAAI,MAAM;AAAA,IACpE;AAAA,EAAA,CACD;AACH;"}
@@ -1,8 +1,9 @@
1
1
  import { AnyRoute } from './route.js';
2
- import { RouteById, RouteIds } from './routeInfo.js';
2
+ import { AllContext, RouteById, RouteIds } from './routeInfo.js';
3
3
  import { RegisteredRouter } from './router.js';
4
- import { StrictOrFrom } from './utils.js';
4
+ import { Expand, StrictOrFrom } from './utils.js';
5
5
 
6
- export declare function useRouteContext<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TRouteContext = RouteById<TRouteTree, TFrom>['types']['allContext'], TSelected = TRouteContext>(opts: StrictOrFrom<TFrom> & {
6
+ export type UseRouteContextOptions<TFrom, TStrict extends boolean, TRouteContext, TSelected> = StrictOrFrom<TFrom, TStrict> & {
7
7
  select?: (search: TRouteContext) => TSelected;
8
- }): TSelected;
8
+ };
9
+ export declare function useRouteContext<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TStrict extends boolean = true, TRouteContext = TStrict extends false ? AllContext<TRouteTree> : Expand<RouteById<TRouteTree, TFrom>['types']['allContext']>, TSelected = TRouteContext>(opts: UseRouteContextOptions<TFrom, TStrict, TRouteContext, TSelected>): TSelected;
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteContext.js","sources":["../../src/useRouteContext.ts"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { MakeRouteMatch } from './Matches'\nimport type { AnyRoute } from './route'\nimport type { RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { StrictOrFrom } from './utils'\n\nexport function useRouteContext<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TRouteContext = RouteById<TRouteTree, TFrom>['types']['allContext'],\n TSelected = TRouteContext,\n>(\n opts: StrictOrFrom<TFrom> & {\n select?: (search: TRouteContext) => TSelected\n },\n): TSelected {\n return useMatch({\n ...(opts as any),\n select: (match: MakeRouteMatch<TRouteTree, TFrom>) =>\n opts.select ? opts.select(match.context) : match.context,\n })\n}\n"],"names":[],"mappings":";AAOO,SAAS,gBAMd,MAGW;AACX,SAAO,SAAS;AAAA,IACd,GAAI;AAAA,IACJ,QAAQ,CAAC,UACP,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,IAAI,MAAM;AAAA,EAAA,CACpD;AACH;"}
1
+ {"version":3,"file":"useRouteContext.js","sources":["../../src/useRouteContext.ts"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { MakeRouteMatch } from './Matches'\nimport type { AnyRoute } from './route'\nimport type { AllContext, RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { Expand, StrictOrFrom } from './utils'\n\nexport type UseRouteContextOptions<\n TFrom,\n TStrict extends boolean,\n TRouteContext,\n TSelected,\n> = StrictOrFrom<TFrom, TStrict> & {\n select?: (search: TRouteContext) => TSelected\n}\n\nexport function useRouteContext<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n TRouteContext = TStrict extends false\n ? AllContext<TRouteTree>\n : Expand<RouteById<TRouteTree, TFrom>['types']['allContext']>,\n TSelected = TRouteContext,\n>(\n opts: UseRouteContextOptions<TFrom, TStrict, TRouteContext, TSelected>,\n): TSelected {\n return useMatch({\n ...(opts as any),\n select: (match: MakeRouteMatch<TRouteTree, TFrom>) =>\n opts.select ? opts.select(match.context) : match.context,\n })\n}\n"],"names":[],"mappings":";AAgBO,SAAS,gBASd,MACW;AACX,SAAO,SAAS;AAAA,IACd,GAAI;AAAA,IACJ,QAAQ,CAAC,UACP,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,IAAI,MAAM;AAAA,EAAA,CACpD;AACH;"}
@@ -3,6 +3,7 @@ import { FullSearchSchema, RouteById, RouteIds } from './routeInfo.js';
3
3
  import { RegisteredRouter } from './router.js';
4
4
  import { StrictOrFrom } from './utils.js';
5
5
 
6
- export declare function useSearch<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TReturnIntersection extends boolean = false, TSearch = TReturnIntersection extends false ? Exclude<RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'], RootSearchSchema> : Partial<Omit<FullSearchSchema<TRouteTree>, keyof RootSearchSchema>>, TSelected = TSearch>(opts: StrictOrFrom<TFrom, TReturnIntersection> & {
6
+ export type UseSearchOptions<TFrom, TStrict extends boolean, TSearch, TSelected> = StrictOrFrom<TFrom, TStrict> & {
7
7
  select?: (search: TSearch) => TSelected;
8
- }): TSelected;
8
+ };
9
+ export declare function useSearch<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>, TStrict extends boolean = true, TSearch = TStrict extends false ? FullSearchSchema<TRouteTree> : Exclude<RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'], RootSearchSchema>, TSelected = TSearch>(opts: UseSearchOptions<TFrom, TStrict, TSearch, TSelected>): TSelected;
@@ -1 +1 @@
1
- {"version":3,"file":"useSearch.js","sources":["../../src/useSearch.tsx"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { AnyRoute, RootSearchSchema } from './route'\nimport type { FullSearchSchema, RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { MakeRouteMatch } from './Matches'\nimport type { StrictOrFrom } from './utils'\n\nexport function useSearch<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TReturnIntersection extends boolean = false,\n TSearch = TReturnIntersection extends false\n ? Exclude<\n RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'],\n RootSearchSchema\n >\n : Partial<Omit<FullSearchSchema<TRouteTree>, keyof RootSearchSchema>>,\n TSelected = TSearch,\n>(\n opts: StrictOrFrom<TFrom, TReturnIntersection> & {\n select?: (search: TSearch) => TSelected\n },\n): TSelected {\n return useMatch({\n ...opts,\n select: (match: MakeRouteMatch<TRouteTree, TFrom>) => {\n return opts.select ? opts.select(match.search) : match.search\n },\n })\n}\n"],"names":[],"mappings":";AAOO,SAAS,UAYd,MAGW;AACX,SAAO,SAAS;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,CAAC,UAA6C;AACpD,aAAO,KAAK,SAAS,KAAK,OAAO,MAAM,MAAM,IAAI,MAAM;AAAA,IACzD;AAAA,EAAA,CACD;AACH;"}
1
+ {"version":3,"file":"useSearch.js","sources":["../../src/useSearch.tsx"],"sourcesContent":["import { useMatch } from './useMatch'\nimport type { AnyRoute, RootSearchSchema } from './route'\nimport type { FullSearchSchema, RouteById, RouteIds } from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type { MakeRouteMatch } from './Matches'\nimport type { StrictOrFrom } from './utils'\n\nexport type UseSearchOptions<\n TFrom,\n TStrict extends boolean,\n TSearch,\n TSelected,\n> = StrictOrFrom<TFrom, TStrict> & {\n select?: (search: TSearch) => TSelected\n}\n\nexport function useSearch<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n TSearch = TStrict extends false\n ? FullSearchSchema<TRouteTree>\n : Exclude<\n RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'],\n RootSearchSchema\n >,\n TSelected = TSearch,\n>(opts: UseSearchOptions<TFrom, TStrict, TSearch, TSelected>): TSelected {\n return useMatch({\n ...opts,\n select: (match: MakeRouteMatch<TRouteTree, TFrom>) => {\n return opts.select ? opts.select(match.search) : match.search\n },\n })\n}\n"],"names":[],"mappings":";AAgBO,SAAS,UAWd,MAAuE;AACvE,SAAO,SAAS;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,CAAC,UAA6C;AACpD,aAAO,KAAK,SAAS,KAAK,OAAO,MAAM,MAAM,IAAI,MAAM;AAAA,IACzD;AAAA,EAAA,CACD;AACH;"}
@@ -21,8 +21,13 @@ export type Assign<TLeft, TRight> = keyof TLeft extends never ? TRight : keyof T
21
21
  export type Timeout = ReturnType<typeof setTimeout>;
22
22
  export type Updater<TPrevious, TResult = TPrevious> = TResult | ((prev?: TPrevious) => TResult);
23
23
  export type NonNullableUpdater<TPrevious, TResult = TPrevious> = TResult | ((prev: TPrevious) => TResult);
24
- type LastInUnion<T> = UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (x: infer L) => 0 ? L : never;
25
- export type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never] ? [] : [...UnionToTuple<Exclude<T, TLast>>, TLast];
24
+ export type MergeUnionObjects<TUnion> = TUnion extends MergeUnionPrimitive ? never : TUnion;
25
+ export type MergeUnionObject<TUnion> = MergeUnionObjects<TUnion> extends infer TObj ? {
26
+ [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any ? TKey extends keyof TObj ? TObj[TKey] : never : never;
27
+ } : never;
28
+ export type MergeUnionPrimitive = ReadonlyArray<any> | number | string | bigint | boolean | symbol;
29
+ export type MergeUnionPrimitives<TUnion> = TUnion extends MergeUnionPrimitive ? TUnion : TUnion extends object ? never : TUnion;
30
+ export type MergeUnion<TUnion> = MergeUnionPrimitives<TUnion> | MergeUnionObject<MergeUnionObjects<TUnion>>;
26
31
  export declare function last<T>(arr: Array<T>): T | undefined;
27
32
  export declare function functionalUpdate<TResult>(updater: Updater<TResult> | NonNullableUpdater<TResult>, previous: TResult): TResult;
28
33
  export declare function pick<TValue, TKey extends keyof TValue>(parent: TValue, keys: Array<TKey>): Pick<TValue, TKey>;
@@ -39,13 +44,12 @@ export declare function deepEqual(a: any, b: any, partial?: boolean): boolean;
39
44
  export declare function useStableCallback<T extends (...args: Array<any>) => any>(fn: T): T;
40
45
  export declare function shallow<T>(objA: T, objB: T): boolean;
41
46
  export type StringLiteral<T> = T extends string ? string extends T ? string : T : never;
42
- export type StrictOrFrom<TFrom, TReturnIntersection extends boolean = false> = {
43
- from: StringLiteral<TFrom> | TFrom;
44
- strict?: true;
45
- } | {
47
+ export type StrictOrFrom<TFrom, TStrict extends boolean = true> = TStrict extends false ? {
46
48
  from?: never;
47
- strict: false;
48
- experimental_returnIntersection?: TReturnIntersection;
49
+ strict: TStrict;
50
+ } : {
51
+ from: StringLiteral<TFrom> | TFrom;
52
+ strict?: TStrict;
49
53
  };
50
54
  export declare const useLayoutEffect: typeof React.useLayoutEffect;
51
55
  /**
@@ -65,4 +69,3 @@ export declare function createControlledPromise<T>(onResolve?: () => void): Cont
65
69
  * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3
66
70
  */
67
71
  export declare function usePrevious<T>(value: T): T | null;
68
- export {};
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\n// export type Expand<T> = T\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = Omit<\n TRight,\n keyof TLeft\n> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n}\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type Assign<TLeft, TRight> = keyof TLeft extends never\n ? TRight\n : keyof TRight extends never\n ? TLeft\n : Omit<TLeft, keyof TRight> & TRight\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\n// from https://github.com/type-challenges/type-challenges/issues/737\ntype LastInUnion<T> =\n UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (\n x: infer L,\n ) => 0\n ? L\n : never\nexport type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never]\n ? []\n : [...UnionToTuple<Exclude<T, TLast>>, TLast]\n\n//\n\nexport function last<T>(arr: Array<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\nexport function functionalUpdate<TResult>(\n updater: Updater<TResult> | NonNullableUpdater<TResult>,\n previous: TResult,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nexport function pick<TValue, TKey extends keyof TValue>(\n parent: TValue,\n keys: Array<TKey>,\n): Pick<TValue, TKey> {\n return keys.reduce((obj: any, key: TKey) => {\n obj[key] = parent[key]\n return obj\n }, {} as any)\n}\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T): T {\n if (prev === _next) {\n return prev\n }\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (array || (isPlainObject(prev) && isPlainObject(next))) {\n const prevItems = array ? prev : Object.keys(prev)\n const prevSize = prevItems.length\n const nextItems = array ? next : Object.keys(next)\n const nextSize = nextItems.length\n const copy: any = array ? [] : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : nextItems[i]\n if (\n ((!array && prevItems.includes(key)) || array) &&\n prev[key] === undefined &&\n next[key] === undefined\n ) {\n copy[key] = undefined\n equalItems++\n } else {\n copy[key] = replaceEqualDeep(prev[key], next[key])\n if (copy[key] === prev[key] && prev[key] !== undefined) {\n equalItems++\n }\n }\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n }\n\n return next\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\nexport function isPlainArray(value: unknown) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\n }\n\n return false\n}\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (const item of keysA) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, item) ||\n !Object.is(objA[item as keyof T], objB[item as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type StrictOrFrom<TFrom, TReturnIntersection extends boolean = false> =\n | {\n from: StringLiteral<TFrom> | TFrom\n strict?: true\n }\n | {\n from?: never\n strict: false\n experimental_returnIntersection?: TReturnIntersection\n }\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n *\n * @deprecated use `jsesc` instead\n */\nexport function escapeJSON(jsonString: string) {\n return jsonString\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n .replace(/'/g, \"\\\\'\") // Escape single quotes\n .replace(/\"/g, '\\\\\"') // Escape double quotes\n}\n\nexport function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\n// export type Expand<T> = T\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = Omit<\n TRight,\n keyof TLeft\n> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n}\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type Assign<TLeft, TRight> = keyof TLeft extends never\n ? TRight\n : keyof TRight extends never\n ? TLeft\n : Omit<TLeft, keyof TRight> & TRight\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\nexport type MergeUnionObjects<TUnion> = TUnion extends MergeUnionPrimitive\n ? never\n : TUnion\n\nexport type MergeUnionObject<TUnion> =\n MergeUnionObjects<TUnion> extends infer TObj\n ? {\n [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any\n ? TKey extends keyof TObj\n ? TObj[TKey]\n : never\n : never\n }\n : never\n\nexport type MergeUnionPrimitive =\n | ReadonlyArray<any>\n | number\n | string\n | bigint\n | boolean\n | symbol\n\nexport type MergeUnionPrimitives<TUnion> = TUnion extends MergeUnionPrimitive\n ? TUnion\n : TUnion extends object\n ? never\n : TUnion\n\nexport type MergeUnion<TUnion> =\n | MergeUnionPrimitives<TUnion>\n | MergeUnionObject<MergeUnionObjects<TUnion>>\n\nexport function last<T>(arr: Array<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\nexport function functionalUpdate<TResult>(\n updater: Updater<TResult> | NonNullableUpdater<TResult>,\n previous: TResult,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nexport function pick<TValue, TKey extends keyof TValue>(\n parent: TValue,\n keys: Array<TKey>,\n): Pick<TValue, TKey> {\n return keys.reduce((obj: any, key: TKey) => {\n obj[key] = parent[key]\n return obj\n }, {} as any)\n}\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T): T {\n if (prev === _next) {\n return prev\n }\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (array || (isPlainObject(prev) && isPlainObject(next))) {\n const prevItems = array ? prev : Object.keys(prev)\n const prevSize = prevItems.length\n const nextItems = array ? next : Object.keys(next)\n const nextSize = nextItems.length\n const copy: any = array ? [] : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : nextItems[i]\n if (\n ((!array && prevItems.includes(key)) || array) &&\n prev[key] === undefined &&\n next[key] === undefined\n ) {\n copy[key] = undefined\n equalItems++\n } else {\n copy[key] = replaceEqualDeep(prev[key], next[key])\n if (copy[key] === prev[key] && prev[key] !== undefined) {\n equalItems++\n }\n }\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n }\n\n return next\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\nexport function isPlainArray(value: unknown) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\n }\n\n return false\n}\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (const item of keysA) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, item) ||\n !Object.is(objA[item as keyof T], objB[item as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type StrictOrFrom<\n TFrom,\n TStrict extends boolean = true,\n> = TStrict extends false\n ? {\n from?: never\n strict: TStrict\n }\n : {\n from: StringLiteral<TFrom> | TFrom\n strict?: TStrict\n }\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n *\n * @deprecated use `jsesc` instead\n */\nexport function escapeJSON(jsonString: string) {\n return jsonString\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n .replace(/'/g, \"\\\\'\") // Escape single quotes\n .replace(/\"/g, '\\\\\"') // Escape double quotes\n}\n\nexport function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.34.3",
3
+ "version": "1.34.6",
4
4
  "description": "",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/Matches.tsx CHANGED
@@ -17,6 +17,8 @@ import {
17
17
  import { rootRouteId } from './root'
18
18
  import type { ResolveRelativePath, ToOptions } from './link'
19
19
  import type {
20
+ AllContext,
21
+ AllLoaderData,
20
22
  AllParams,
21
23
  FullSearchSchema,
22
24
  ParseRoute,
@@ -72,16 +74,20 @@ export interface RouteMatch<
72
74
  export type MakeRouteMatch<
73
75
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
74
76
  TRouteId = ParseRoute<TRouteTree>['id'],
75
- TReturnIntersection extends boolean = false,
77
+ TStrict extends boolean = true,
76
78
  TTypes extends AnyRoute['types'] = RouteById<TRouteTree, TRouteId>['types'],
77
- TAllParams = TReturnIntersection extends false
78
- ? TTypes['allParams']
79
- : Partial<AllParams<TRouteTree>>,
80
- TFullSearchSchema = TReturnIntersection extends false
81
- ? TTypes['fullSearchSchema']
82
- : Partial<FullSearchSchema<TRouteTree>>,
83
- TLoaderData = TTypes['loaderData'],
84
- TAllContext = TTypes['allContext'],
79
+ TAllParams = TStrict extends false
80
+ ? AllParams<TRouteTree>
81
+ : TTypes['allParams'],
82
+ TFullSearchSchema = TStrict extends false
83
+ ? FullSearchSchema<TRouteTree>
84
+ : TTypes['fullSearchSchema'],
85
+ TLoaderData = TStrict extends false
86
+ ? AllLoaderData<TRouteTree>
87
+ : TTypes['loaderData'],
88
+ TAllContext = TStrict extends false
89
+ ? AllContext<TRouteTree>
90
+ : TTypes['allContext'],
85
91
  TRouteContext = TTypes['routeContext'],
86
92
  TLoaderDeps = TTypes['loaderDeps'],
87
93
  > = RouteMatch<
@@ -549,13 +555,9 @@ export function MatchRoute<
549
555
  export function useMatches<
550
556
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
551
557
  TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
552
- TReturnIntersection extends boolean = false,
553
- TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
558
+ TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId>,
554
559
  T = Array<TRouteMatch>,
555
- >(opts?: {
556
- select?: (matches: Array<TRouteMatch>) => T
557
- experimental_returnIntersection?: TReturnIntersection
558
- }): T {
560
+ >(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {
559
561
  return useRouterState({
560
562
  select: (state) => {
561
563
  const matches = state.matches
@@ -569,13 +571,9 @@ export function useMatches<
569
571
  export function useParentMatches<
570
572
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
571
573
  TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
572
- TReturnIntersection extends boolean = false,
573
- TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
574
+ TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId>,
574
575
  T = Array<TRouteMatch>,
575
- >(opts?: {
576
- select?: (matches: Array<TRouteMatch>) => T
577
- experimental_returnIntersection?: TReturnIntersection
578
- }): T {
576
+ >(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {
579
577
  const contextMatchId = React.useContext(matchContext)
580
578
 
581
579
  return useMatches({
@@ -594,13 +592,9 @@ export function useParentMatches<
594
592
  export function useChildMatches<
595
593
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
596
594
  TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
597
- TReturnIntersection extends boolean = false,
598
- TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
595
+ TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId>,
599
596
  T = Array<TRouteMatch>,
600
- >(opts?: {
601
- select?: (matches: Array<TRouteMatch>) => T
602
- experimental_returnIntersection?: TReturnIntersection
603
- }): T {
597
+ >(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {
604
598
  const contextMatchId = React.useContext(matchContext)
605
599
 
606
600
  return useMatches({
@@ -40,7 +40,9 @@ export type NavigateFn = <
40
40
  TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,
41
41
  TMaskTo extends string = '',
42
42
  >(
43
- opts: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
43
+ opts: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {
44
+ __isRedirect?: boolean
45
+ },
44
46
  ) => Promise<void>
45
47
 
46
48
  export type BuildLocationFn<TRouteTree extends AnyRoute> = <
@@ -79,16 +79,11 @@ export function Transitioner() {
79
79
  const pathChanged = fromLocation.href !== toLocation.href
80
80
 
81
81
  router.emit({
82
- type: 'onLoad',
82
+ type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches
83
83
  fromLocation,
84
84
  toLocation,
85
85
  pathChanged,
86
86
  })
87
-
88
- // if (router.viewTransitionPromise) {
89
- // console.log('resolving view transition promise')
90
- // }
91
- // router.viewTransitionPromise?.resolve(true)
92
87
  }
93
88
  }, [previousIsLoading, router, routerState.isLoading])
94
89
 
package/src/fileRoute.ts CHANGED
@@ -94,7 +94,7 @@ export class FileRoute<
94
94
  TAllContext = ResolveAllContext<TParentRoute, TRouteContext>,
95
95
  TRouterContext = AnyContext,
96
96
  TLoaderDeps extends Record<string, any> = {},
97
- TLoaderDataReturn = unknown,
97
+ TLoaderDataReturn = {},
98
98
  TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
99
99
  TChildren = unknown,
100
100
  >(
package/src/route.ts CHANGED
@@ -71,10 +71,8 @@ export type RouteOptions<
71
71
  TRouterContext = AnyContext,
72
72
  TAllContext = AnyContext,
73
73
  TLoaderDeps extends Record<string, any> = {},
74
- TLoaderDataReturn = unknown,
75
- TLoaderData = [TLoaderDataReturn] extends [never]
76
- ? undefined
77
- : TLoaderDataReturn,
74
+ TLoaderDataReturn = {},
75
+ TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
78
76
  > = BaseRouteOptions<
79
77
  TParentRoute,
80
78
  TCustomId,
@@ -121,7 +119,7 @@ export type FileBaseRouteOptions<
121
119
  TRouterContext = AnyContext,
122
120
  TAllContext = AnyContext,
123
121
  TLoaderDeps extends Record<string, any> = {},
124
- TLoaderDataReturn = unknown,
122
+ TLoaderDataReturn = {},
125
123
  > = {
126
124
  validateSearch?: SearchSchemaValidator<TSearchSchemaInput, TSearchSchema>
127
125
  shouldReload?:
@@ -187,7 +185,7 @@ export type BaseRouteOptions<
187
185
  TRouterContext = AnyContext,
188
186
  TAllContext = AnyContext,
189
187
  TLoaderDeps extends Record<string, any> = {},
190
- TLoaderDataReturn = unknown,
188
+ TLoaderDataReturn = {},
191
189
  > = RoutePathOptions<TCustomId, TPath> &
192
190
  FileBaseRouteOptions<
193
191
  TParentRoute,
@@ -344,7 +342,7 @@ export type RouteLoaderFn<
344
342
  in out TLoaderDeps extends Record<string, any> = {},
345
343
  in out TAllContext = AnyContext,
346
344
  in out TRouteContext = AnyContext,
347
- TLoaderData = unknown,
345
+ TLoaderData = undefined,
348
346
  > = (
349
347
  match: LoaderFnContext<TAllParams, TLoaderDeps, TAllContext, TRouteContext>,
350
348
  ) => Promise<TLoaderData> | TLoaderData
@@ -629,7 +627,7 @@ export class Route<
629
627
  >,
630
628
  in out TRouterContext = AnyContext,
631
629
  in out TLoaderDeps extends Record<string, any> = {},
632
- TLoaderDataReturn = unknown,
630
+ TLoaderDataReturn = {},
633
631
  in out TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
634
632
  in out TChildren = unknown,
635
633
  > {
@@ -971,7 +969,7 @@ export function createRoute<
971
969
  >,
972
970
  TRouterContext = AnyContext,
973
971
  TLoaderDeps extends Record<string, any> = {},
974
- TLoaderDataReturn = unknown,
972
+ TLoaderDataReturn = {},
975
973
  TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
976
974
  TChildren = unknown,
977
975
  >(
@@ -1029,7 +1027,7 @@ export type RootRouteOptions<
1029
1027
  TRouteContext = ResolveRouteContext<TRouteContextReturn>,
1030
1028
  TRouterContext = {},
1031
1029
  TLoaderDeps extends Record<string, any> = {},
1032
- TLoaderDataReturn = unknown,
1030
+ TLoaderDataReturn = {},
1033
1031
  TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
1034
1032
  > = Omit<
1035
1033
  RouteOptions<
@@ -1069,10 +1067,8 @@ export function createRootRouteWithContext<TRouterContext extends {}>() {
1069
1067
  ? RouteContext
1070
1068
  : TRouteContextReturn,
1071
1069
  TLoaderDeps extends Record<string, any> = {},
1072
- TLoaderDataReturn = unknown,
1073
- TLoaderData = [TLoaderDataReturn] extends [never]
1074
- ? undefined
1075
- : TLoaderDataReturn,
1070
+ TLoaderDataReturn = {},
1071
+ TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
1076
1072
  >(
1077
1073
  options?: RootRouteOptions<
1078
1074
  TSearchSchemaInput,
@@ -1116,7 +1112,7 @@ export class RootRoute<
1116
1112
  in out TRouteContext = ResolveRouteContext<TRouteContextReturn>,
1117
1113
  in out TRouterContext = {},
1118
1114
  TLoaderDeps extends Record<string, any> = {},
1119
- TLoaderDataReturn = unknown,
1115
+ TLoaderDataReturn = {},
1120
1116
  in out TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
1121
1117
  > extends Route<
1122
1118
  any, // TParentRoute
@@ -1168,7 +1164,7 @@ export function createRootRoute<
1168
1164
  TRouteContext = ResolveRouteContext<TRouteContextReturn>,
1169
1165
  TRouterContext = {},
1170
1166
  TLoaderDeps extends Record<string, any> = {},
1171
- TLoaderDataReturn = unknown,
1167
+ TLoaderDataReturn = {},
1172
1168
  TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
1173
1169
  >(
1174
1170
  options?: Omit<
@@ -1326,7 +1322,7 @@ export class NotFoundRoute<
1326
1322
  >,
1327
1323
  TRouterContext = AnyContext,
1328
1324
  TLoaderDeps extends Record<string, any> = {},
1329
- TLoaderDataReturn = unknown,
1325
+ TLoaderDataReturn = {},
1330
1326
  TLoaderData = ResolveLoaderData<TLoaderDataReturn>,
1331
1327
  TChildren = unknown,
1332
1328
  > extends Route<
package/src/routeInfo.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { AnyRoute } from './route'
2
- import type { AnyRouter, Router, TrailingSlashOption } from './router'
3
- import type { UnionToIntersection, UnionToTuple } from './utils'
1
+ import type { AnyRoute, RootSearchSchema } from './route'
2
+ import type { AnyRouter, TrailingSlashOption } from './router'
3
+ import type { Expand, MergeUnion } from './utils'
4
4
 
5
5
  export type ParseRoute<TRouteTree, TAcc = TRouteTree> = TRouteTree extends {
6
6
  types: { children: infer TChildren }
@@ -114,26 +114,20 @@ export type RouteByToPath<TRouter extends AnyRouter, TTo> = Extract<
114
114
  AnyRoute
115
115
  >
116
116
 
117
- // eslint-disable-next-line @typescript-eslint/naming-convention
118
- type UnionizeCollisions<T, U> = {
119
- [P in keyof T & keyof U]: T[P] extends U[P] ? T[P] : T[P] | U[P]
120
- }
121
- // eslint-disable-next-line @typescript-eslint/naming-convention
122
- type Reducer<T, U, C = UnionizeCollisions<T, U>> = C &
123
- Omit<T, keyof C> &
124
- Omit<U, keyof C>
125
-
126
- type Reduce<TValue extends Array<any>, TResult = unknown> = TValue extends [
127
- infer First,
128
- ...infer Rest,
129
- ]
130
- ? Reduce<Rest, Reducer<TResult, First>>
131
- : TResult
132
-
133
- export type FullSearchSchema<TRouteTree extends AnyRoute> = Partial<
134
- Reduce<UnionToTuple<ParseRoute<TRouteTree>['types']['fullSearchSchema']>>
117
+ export type FullSearchSchema<TRouteTree extends AnyRoute> = Expand<
118
+ MergeUnion<
119
+ Exclude<ParseRoute<TRouteTree>['types']['searchSchema'], RootSearchSchema>
120
+ >
121
+ >
122
+
123
+ export type AllParams<TRouteTree extends AnyRoute> = Expand<
124
+ MergeUnion<ParseRoute<TRouteTree>['types']['params']>
125
+ >
126
+
127
+ export type AllContext<TRouteTree extends AnyRoute> = Expand<
128
+ MergeUnion<ParseRoute<TRouteTree>['types']['allContext']>
135
129
  >
136
130
 
137
- export type AllParams<TRouteTree extends AnyRoute> = UnionToIntersection<
138
- ParseRoute<TRouteTree>['types']['allParams']
131
+ export type AllLoaderData<TRouteTree extends AnyRoute> = Expand<
132
+ MergeUnion<ParseRoute<TRouteTree>['types']['loaderData']>
139
133
  >
package/src/router.ts CHANGED
@@ -7,7 +7,6 @@ import { defaultParseSearch, defaultStringifySearch } from './searchParams'
7
7
  import {
8
8
  createControlledPromise,
9
9
  deepEqual,
10
- escapeJSON,
11
10
  functionalUpdate,
12
11
  last,
13
12
  pick,
@@ -421,6 +420,12 @@ export const componentTypes = [
421
420
  ] as const
422
421
 
423
422
  export type RouterEvents = {
423
+ onBeforeNavigate: {
424
+ type: 'onBeforeNavigate'
425
+ fromLocation: ParsedLocation
426
+ toLocation: ParsedLocation
427
+ pathChanged: boolean
428
+ }
424
429
  onBeforeLoad: {
425
430
  type: 'onBeforeLoad'
426
431
  fromLocation: ParsedLocation
@@ -504,7 +509,7 @@ export class Router<
504
509
  'stringifySearch' | 'parseSearch' | 'context'
505
510
  >
506
511
  history!: RouterHistory
507
- latestLocation!: ParsedLocation
512
+ latestLocation!: ParsedLocation<FullSearchSchema<TRouteTree>>
508
513
  basepath!: string
509
514
  routeTree!: TRouteTree
510
515
  routesById!: RoutesById<TRouteTree>
@@ -765,7 +770,7 @@ export class Router<
765
770
  }
766
771
 
767
772
  parseLocation = (
768
- previousLocation?: ParsedLocation,
773
+ previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>,
769
774
  ): ParsedLocation<FullSearchSchema<TRouteTree>> => {
770
775
  const parse = ({
771
776
  pathname,
@@ -1374,7 +1379,7 @@ export class Router<
1374
1379
  })
1375
1380
  }
1376
1381
 
1377
- navigate: NavigateFn = ({ from, to, ...rest }) => {
1382
+ navigate: NavigateFn = ({ from, to, __isRedirect, ...rest }) => {
1378
1383
  // If this link simply reloads the current route,
1379
1384
  // make sure it has a new key so it will trigger a data refresh
1380
1385
 
@@ -1423,13 +1428,6 @@ export class Router<
1423
1428
  // Cancel any pending matches
1424
1429
  this.cancelMatches()
1425
1430
 
1426
- this.emit({
1427
- type: 'onBeforeLoad',
1428
- fromLocation: prevLocation,
1429
- toLocation: next,
1430
- pathChanged: pathDidChange,
1431
- })
1432
-
1433
1431
  let pendingMatches!: Array<AnyRouteMatch>
1434
1432
 
1435
1433
  this.__store.batch(() => {
@@ -1454,6 +1452,22 @@ export class Router<
1454
1452
  }))
1455
1453
  })
1456
1454
 
1455
+ if (!this.state.redirect) {
1456
+ this.emit({
1457
+ type: 'onBeforeNavigate',
1458
+ fromLocation: prevLocation,
1459
+ toLocation: next,
1460
+ pathChanged: pathDidChange,
1461
+ })
1462
+ }
1463
+
1464
+ this.emit({
1465
+ type: 'onBeforeLoad',
1466
+ fromLocation: prevLocation,
1467
+ toLocation: next,
1468
+ pathChanged: pathDidChange,
1469
+ })
1470
+
1457
1471
  await this.loadMatches({
1458
1472
  matches: pendingMatches,
1459
1473
  location: next,
@@ -1516,7 +1530,7 @@ export class Router<
1516
1530
  if (isResolvedRedirect(err)) {
1517
1531
  redirect = err
1518
1532
  if (!this.isServer) {
1519
- this.navigate({ ...err, replace: true })
1533
+ this.navigate({ ...err, replace: true, __isRedirect: true })
1520
1534
  this.load()
1521
1535
  }
1522
1536
  } else if (isNotFound(err)) {
@@ -5,25 +5,34 @@ import type { MakeRouteMatch } from './Matches'
5
5
  import type { RouteIds } from './routeInfo'
6
6
  import type { StrictOrFrom } from './utils'
7
7
 
8
+ export type UseLoaderDataOptions<
9
+ TFrom,
10
+ TStrict extends boolean,
11
+ TRouteMatch,
12
+ TSelected,
13
+ > = StrictOrFrom<TFrom, TStrict> & {
14
+ select?: (match: TRouteMatch) => TSelected
15
+ }
16
+
8
17
  export function useLoaderData<
9
18
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
10
19
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
11
- TRouteMatch extends MakeRouteMatch<TRouteTree, TFrom> = MakeRouteMatch<
20
+ TStrict extends boolean = true,
21
+ TRouteMatch extends MakeRouteMatch<
12
22
  TRouteTree,
13
- TFrom
14
- >,
23
+ TFrom,
24
+ TStrict
25
+ > = MakeRouteMatch<TRouteTree, TFrom, TStrict>,
15
26
  TSelected = Required<TRouteMatch>['loaderData'],
16
27
  >(
17
- opts: StrictOrFrom<TFrom> & {
18
- select?: (match: TRouteMatch) => TSelected
19
- },
28
+ opts: UseLoaderDataOptions<TFrom, TStrict, TRouteMatch, TSelected>,
20
29
  ): TSelected {
21
- return useMatch({
30
+ return useMatch<TRouteTree, TFrom, TStrict, TRouteMatch, TSelected>({
22
31
  ...opts,
23
32
  select: (s) => {
24
33
  return typeof opts.select === 'function'
25
34
  ? opts.select(s.loaderData as TRouteMatch)
26
- : s.loaderData
35
+ : (s.loaderData as TSelected)
27
36
  },
28
- }) as TSelected
37
+ })
29
38
  }