@tanstack/react-router 1.88.0 → 1.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { StructuralSharingOption, ValidateSelected } from './structuralSharing.js';
2
2
  import { AnyRouter, RegisteredRouter } from './router.js';
3
- import { MakeRouteMatch } from './Matches.js';
3
+ import { MakeRouteMatch, MakeRouteMatchUnion } from './Matches.js';
4
4
  import { StrictOrFrom, ThrowOrOptional } from './utils.js';
5
5
  export interface UseMatchBaseOptions<TRouter extends AnyRouter, TFrom, TStrict extends boolean, TThrow, TSelected, TStructuralSharing extends boolean> {
6
6
  select?: (match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>) => ValidateSelected<TRouter, TSelected, TStructuralSharing>;
@@ -8,5 +8,7 @@ export interface UseMatchBaseOptions<TRouter extends AnyRouter, TFrom, TStrict e
8
8
  }
9
9
  export type UseMatchRoute<out TFrom> = <TRouter extends AnyRouter = RegisteredRouter, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts?: UseMatchBaseOptions<TRouter, TFrom, true, true, TSelected, TStructuralSharing> & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>) => UseMatchResult<TRouter, TFrom, true, TSelected>;
10
10
  export type UseMatchOptions<TRouter extends AnyRouter, TFrom extends string | undefined, TStrict extends boolean, TSelected, TThrow extends boolean, TStructuralSharing extends boolean> = StrictOrFrom<TRouter, TFrom, TStrict> & UseMatchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected, TStructuralSharing> & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>;
11
- export type UseMatchResult<TRouter extends AnyRouter, TFrom, TStrict extends boolean, TSelected> = unknown extends TSelected ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict> : TSelected;
12
- export declare function useMatch<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string | undefined = undefined, TStrict extends boolean = true, TThrow extends boolean = true, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts: UseMatchOptions<TRouter, TFrom, TStrict, TSelected, TThrow, TStructuralSharing>): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>;
11
+ export type UseMatchResult<TRouter extends AnyRouter, TFrom, TStrict extends boolean, TSelected> = unknown extends TSelected ? TStrict extends true ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict> : MakeRouteMatchUnion<TRouter> : TSelected;
12
+ type ThrowConstraint<TStrict extends boolean, TThrow extends boolean> = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow;
13
+ export declare function useMatch<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string | undefined = undefined, TStrict extends boolean = true, TThrow extends boolean = true, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts: UseMatchOptions<TRouter, TFrom, TStrict, TSelected, ThrowConstraint<TStrict, TThrow>, TStructuralSharing>): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>;
14
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useMatch.js","sources":["../../src/useMatch.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport { useRouterState } from './useRouterState'\nimport { dummyMatchContext, matchContext } from './matchContext'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { MakeRouteMatch } from './Matches'\nimport type { StrictOrFrom, ThrowOrOptional } from './utils'\n\nexport interface UseMatchBaseOptions<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TThrow,\n TSelected,\n TStructuralSharing extends boolean,\n> {\n select?: (\n match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n shouldThrow?: TThrow\n}\n\nexport type UseMatchRoute<out TFrom> = <\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchBaseOptions<\n TRouter,\n TFrom,\n true,\n true,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n) => UseMatchResult<TRouter, TFrom, true, TSelected>\n\nexport type UseMatchOptions<\n TRouter extends AnyRouter,\n TFrom extends string | undefined,\n TStrict extends boolean,\n TSelected,\n TThrow extends boolean,\n TStructuralSharing extends boolean,\n> = StrictOrFrom<TRouter, TFrom, TStrict> &\n UseMatchBaseOptions<\n TRouter,\n TFrom,\n TStrict,\n TThrow,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>\n\nexport type UseMatchResult<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TSelected,\n> = unknown extends TSelected\n ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>\n : TSelected\n\nexport function useMatch<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string | undefined = undefined,\n TStrict extends boolean = true,\n TThrow extends boolean = true,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts: UseMatchOptions<\n TRouter,\n TFrom,\n TStrict,\n TSelected,\n TThrow,\n TStructuralSharing\n >,\n): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {\n const nearestMatchId = React.useContext(\n opts.from ? dummyMatchContext : matchContext,\n )\n\n const matchSelection = useRouterState({\n select: (state: any) => {\n const match = state.matches.find((d: any) =>\n opts.from ? opts.from === d.routeId : d.id === nearestMatchId,\n )\n invariant(\n !((opts.shouldThrow ?? true) && !match),\n `Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n\n if (match === undefined) {\n return undefined\n }\n\n return opts.select ? opts.select(match) : match\n },\n structuralSharing: opts.structuralSharing,\n } as any)\n\n return matchSelection as any\n}\n"],"names":[],"mappings":";;;;AAqEO,SAAS,SAQd,MAQ6E;AAC7E,QAAM,iBAAiB,MAAM;AAAA,IAC3B,KAAK,OAAO,oBAAoB;AAAA,EAClC;AAEA,QAAM,iBAAiB,eAAe;AAAA,IACpC,QAAQ,CAAC,UAAe;AAChB,YAAA,QAAQ,MAAM,QAAQ;AAAA,QAAK,CAAC,MAChC,KAAK,OAAO,KAAK,SAAS,EAAE,UAAU,EAAE,OAAO;AAAA,MACjD;AACA;AAAA,QACE,GAAG,KAAK,eAAe,SAAS,CAAC;AAAA,QACjC,kBAAkB,KAAK,OAAO,yBAAyB,KAAK,IAAI,MAAM,kBAAkB;AAAA,MAC1F;AAEA,UAAI,UAAU,QAAW;AAChB,eAAA;AAAA,MAAA;AAGT,aAAO,KAAK,SAAS,KAAK,OAAO,KAAK,IAAI;AAAA,IAC5C;AAAA,IACA,mBAAmB,KAAK;AAAA,EAAA,CAClB;AAED,SAAA;AACT;"}
1
+ {"version":3,"file":"useMatch.js","sources":["../../src/useMatch.tsx"],"sourcesContent":["import * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport { useRouterState } from './useRouterState'\nimport { dummyMatchContext, matchContext } from './matchContext'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { MakeRouteMatch, MakeRouteMatchUnion } from './Matches'\nimport type { StrictOrFrom, ThrowOrOptional } from './utils'\n\nexport interface UseMatchBaseOptions<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TThrow,\n TSelected,\n TStructuralSharing extends boolean,\n> {\n select?: (\n match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n shouldThrow?: TThrow\n}\n\nexport type UseMatchRoute<out TFrom> = <\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchBaseOptions<\n TRouter,\n TFrom,\n true,\n true,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n) => UseMatchResult<TRouter, TFrom, true, TSelected>\n\nexport type UseMatchOptions<\n TRouter extends AnyRouter,\n TFrom extends string | undefined,\n TStrict extends boolean,\n TSelected,\n TThrow extends boolean,\n TStructuralSharing extends boolean,\n> = StrictOrFrom<TRouter, TFrom, TStrict> &\n UseMatchBaseOptions<\n TRouter,\n TFrom,\n TStrict,\n TThrow,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>\n\nexport type UseMatchResult<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TSelected,\n> = unknown extends TSelected\n ? TStrict extends true\n ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>\n : MakeRouteMatchUnion<TRouter>\n : TSelected\n\ntype ThrowConstraint<\n TStrict extends boolean,\n TThrow extends boolean,\n> = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow\n\nexport function useMatch<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string | undefined = undefined,\n TStrict extends boolean = true,\n TThrow extends boolean = true,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts: UseMatchOptions<\n TRouter,\n TFrom,\n TStrict,\n TSelected,\n ThrowConstraint<TStrict, TThrow>,\n TStructuralSharing\n >,\n): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {\n const nearestMatchId = React.useContext(\n opts.from ? dummyMatchContext : matchContext,\n )\n\n const matchSelection = useRouterState({\n select: (state: any) => {\n const match = state.matches.find((d: any) =>\n opts.from ? opts.from === d.routeId : d.id === nearestMatchId,\n )\n invariant(\n !((opts.shouldThrow ?? true) && !match),\n `Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n\n if (match === undefined) {\n return undefined\n }\n\n return opts.select ? opts.select(match) : match\n },\n structuralSharing: opts.structuralSharing,\n } as any)\n\n return matchSelection as any\n}\n"],"names":[],"mappings":";;;;AA4EO,SAAS,SAQd,MAQ6E;AAC7E,QAAM,iBAAiB,MAAM;AAAA,IAC3B,KAAK,OAAO,oBAAoB;AAAA,EAClC;AAEA,QAAM,iBAAiB,eAAe;AAAA,IACpC,QAAQ,CAAC,UAAe;AAChB,YAAA,QAAQ,MAAM,QAAQ;AAAA,QAAK,CAAC,MAChC,KAAK,OAAO,KAAK,SAAS,EAAE,UAAU,EAAE,OAAO;AAAA,MACjD;AACA;AAAA,QACE,GAAG,KAAK,eAAe,SAAS,CAAC;AAAA,QACjC,kBAAkB,KAAK,OAAO,yBAAyB,KAAK,IAAI,MAAM,kBAAkB;AAAA,MAC1F;AAEA,UAAI,UAAU,QAAW;AAChB,eAAA;AAAA,MAAA;AAGT,aAAO,KAAK,SAAS,KAAK,OAAO,KAAK,IAAI;AAAA,IAC5C;AAAA,IACA,mBAAmB,KAAK;AAAA,EAAA,CAClB;AAED,SAAA;AACT;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.88.0",
3
+ "version": "1.89.1",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -15,6 +15,7 @@ import type {
15
15
  export interface CommitLocationOptions {
16
16
  replace?: boolean
17
17
  resetScroll?: boolean
18
+ hashScrollIntoView?: boolean | ScrollIntoViewOptions
18
19
  viewTransition?: boolean | ViewTransitionOptions
19
20
  /**
20
21
  * @deprecated All navigations use React transitions under the hood now
@@ -143,10 +143,13 @@ export function Transitioner() {
143
143
  }))
144
144
 
145
145
  if (typeof document !== 'undefined' && (document as any).querySelector) {
146
- if (router.state.location.hash !== '') {
146
+ const hashScrollIntoViewOptions =
147
+ router.state.location.state.__hashScrollIntoViewOptions ?? true
148
+
149
+ if (hashScrollIntoViewOptions && router.state.location.hash !== '') {
147
150
  const el = document.getElementById(router.state.location.hash)
148
151
  if (el) {
149
- el.scrollIntoView()
152
+ el.scrollIntoView(hashScrollIntoViewOptions)
150
153
  }
151
154
  }
152
155
  }
package/src/history.ts CHANGED
@@ -4,5 +4,6 @@ declare module '@tanstack/history' {
4
4
  interface HistoryState {
5
5
  __tempLocation?: HistoryLocation
6
6
  __tempKey?: string
7
+ __hashScrollIntoViewOptions?: boolean | ScrollIntoViewOptions
7
8
  }
8
9
  }
package/src/link.tsx CHANGED
@@ -210,6 +210,10 @@ export type NavigateOptions<
210
210
  > = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & NavigateOptionProps
211
211
 
212
212
  export interface NavigateOptionProps {
213
+ // if set to `true`, the router will scroll the element with an id matching the hash into view with default ScrollIntoViewOptions.
214
+ // if set to `false`, the router will not scroll the element with an id matching the hash into view.
215
+ // if set to `ScrollIntoViewOptions`, the router will scroll the element with an id matching the hash into view with the provided options.
216
+ hashScrollIntoView?: boolean | ScrollIntoViewOptions
213
217
  // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
214
218
  replace?: boolean
215
219
  resetScroll?: boolean
@@ -609,6 +613,7 @@ export function useLinkProps<
609
613
  to,
610
614
  preload: userPreload,
611
615
  preloadDelay: userPreloadDelay,
616
+ hashScrollIntoView,
612
617
  replace,
613
618
  startTransition,
614
619
  resetScroll,
@@ -806,6 +811,7 @@ export function useLinkProps<
806
811
  ...options,
807
812
  replace,
808
813
  resetScroll,
814
+ hashScrollIntoView,
809
815
  startTransition,
810
816
  viewTransition,
811
817
  ignoreBlocker,
package/src/router.ts CHANGED
@@ -313,6 +313,14 @@ export interface RouterOptions<
313
313
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultviewtransition-property)
314
314
  */
315
315
  defaultViewTransition?: boolean | ViewTransitionOptions
316
+ /**
317
+ * The default `hashScrollIntoView` a route should use if no hashScrollIntoView is provided while navigating
318
+ *
319
+ * See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) for more information on `ScrollIntoViewOptions`.
320
+ *
321
+ * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaulthashscrollintoview-property)
322
+ */
323
+ defaultHashScrollIntoView?: boolean | ScrollIntoViewOptions
316
324
  /**
317
325
  * @default 'fuzzy'
318
326
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#notfoundmode-property)
@@ -1809,7 +1817,7 @@ export class Router<
1809
1817
  this.load()
1810
1818
  } else {
1811
1819
  // eslint-disable-next-line prefer-const
1812
- let { maskedLocation, ...nextHistory } = next
1820
+ let { maskedLocation, hashScrollIntoView, ...nextHistory } = next
1813
1821
 
1814
1822
  if (maskedLocation) {
1815
1823
  nextHistory = {
@@ -1839,6 +1847,9 @@ export class Router<
1839
1847
  }
1840
1848
  }
1841
1849
 
1850
+ nextHistory.state.__hashScrollIntoViewOptions =
1851
+ hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true
1852
+
1842
1853
  this.shouldViewTransition = viewTransition
1843
1854
 
1844
1855
  this.history[next.replace ? 'replace' : 'push'](
@@ -1860,6 +1871,7 @@ export class Router<
1860
1871
  buildAndCommitLocation = ({
1861
1872
  replace,
1862
1873
  resetScroll,
1874
+ hashScrollIntoView,
1863
1875
  viewTransition,
1864
1876
  ignoreBlocker,
1865
1877
  href,
@@ -1882,6 +1894,7 @@ export class Router<
1882
1894
  viewTransition,
1883
1895
  replace,
1884
1896
  resetScroll,
1897
+ hashScrollIntoView,
1885
1898
  ignoreBlocker,
1886
1899
  })
1887
1900
  }
package/src/useMatch.tsx CHANGED
@@ -7,7 +7,7 @@ import type {
7
7
  ValidateSelected,
8
8
  } from './structuralSharing'
9
9
  import type { AnyRouter, RegisteredRouter } from './router'
10
- import type { MakeRouteMatch } from './Matches'
10
+ import type { MakeRouteMatch, MakeRouteMatchUnion } from './Matches'
11
11
  import type { StrictOrFrom, ThrowOrOptional } from './utils'
12
12
 
13
13
  export interface UseMatchBaseOptions<
@@ -64,9 +64,16 @@ export type UseMatchResult<
64
64
  TStrict extends boolean,
65
65
  TSelected,
66
66
  > = unknown extends TSelected
67
- ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>
67
+ ? TStrict extends true
68
+ ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>
69
+ : MakeRouteMatchUnion<TRouter>
68
70
  : TSelected
69
71
 
72
+ type ThrowConstraint<
73
+ TStrict extends boolean,
74
+ TThrow extends boolean,
75
+ > = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow
76
+
70
77
  export function useMatch<
71
78
  TRouter extends AnyRouter = RegisteredRouter,
72
79
  TFrom extends string | undefined = undefined,
@@ -80,7 +87,7 @@ export function useMatch<
80
87
  TFrom,
81
88
  TStrict,
82
89
  TSelected,
83
- TThrow,
90
+ ThrowConstraint<TStrict, TThrow>,
84
91
  TStructuralSharing
85
92
  >,
86
93
  ): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {