import type { HistoryState, ParsedHistoryState } from '@tanstack/history' import type { AllParams, CatchAllPaths, CurrentPath, FullSearchSchema, FullSearchSchemaInput, ParentPath, RouteByPath, RouteByToPath, RoutePaths, RouteToPath, ToPath, } from './routeInfo' import type { AnyRouter, RegisteredRouter, ViewTransitionOptions, } from './router' import type { ConstrainLiteral, Expand, MakeDifferenceOptional, NoInfer, NonNullableUpdater, PickRequired, Updater, WithoutEmpty, } from './utils' import type { ParsedLocation } from './location' export type IsRequiredParams = Record extends TParams ? never : true export type ParsePathParams = T & `${string}$${string}` extends never ? TAcc : T extends `${string}$${infer TPossiblyParam}` ? TPossiblyParam extends '' ? TAcc : TPossiblyParam & `${string}/${string}` extends never ? TPossiblyParam | TAcc : TPossiblyParam extends `${infer TParam}/${infer TRest}` ? ParsePathParams : never : TAcc export type AddTrailingSlash = T extends `${string}/` ? T : `${T & string}/` export type RemoveTrailingSlashes = T & `${string}/` extends never ? T : T extends `${infer R}/` ? R : T export type AddLeadingSlash = T & `/${string}` extends never ? `/${T & string}` : T export type RemoveLeadingSlashes = T & `/${string}` extends never ? T : T extends `/${infer R}` ? R : T type JoinPath = TRight extends '' ? TLeft : TLeft extends '' ? TRight : `${RemoveTrailingSlashes}/${RemoveLeadingSlashes}` type RemoveLastSegment< T extends string, TAcc extends string = '', > = T extends `${infer TSegment}/${infer TRest}` ? TRest & `${string}/${string}` extends never ? TRest extends '' ? TAcc : `${TAcc}${TSegment}` : RemoveLastSegment : TAcc export type ResolveCurrentPath< TFrom extends string, TTo extends string, > = TTo extends '.' ? TFrom : TTo extends './' ? AddTrailingSlash : TTo & `./${string}` extends never ? never : TTo extends `./${infer TRest}` ? AddLeadingSlash> : never export type ResolveParentPath< TFrom extends string, TTo extends string, > = TTo extends '../' | '..' ? TFrom extends '' | '/' ? never : AddLeadingSlash> : TTo & `../${string}` extends never ? AddLeadingSlash> : TFrom extends '' | '/' ? never : TTo extends `../${infer ToRest}` ? ResolveParentPath, ToRest> : AddLeadingSlash> export type ResolveRelativePath = string extends TFrom ? TTo : string extends TTo ? TFrom : undefined extends TTo ? TFrom : TTo extends string ? TFrom extends string ? TTo extends `/${string}` ? TTo : TTo extends `..${string}` ? ResolveParentPath : TTo extends `.${string}` ? ResolveCurrentPath : AddLeadingSlash> : never : never export type FindDescendantToPaths< TRouter extends AnyRouter, TPrefix extends string, > = `${TPrefix}/${string}` & RouteToPath export type InferDescendantToPaths< TRouter extends AnyRouter, TPrefix extends string, TPaths = FindDescendantToPaths, > = TPaths extends `${TPrefix}/` ? never : TPaths extends `${TPrefix}/${infer TRest}` ? TRest : never export type RelativeToPath< TRouter extends AnyRouter, TTo extends string, TResolvedPath extends string, > = | (TResolvedPath & RouteToPath extends never ? never : ToPath) | `${RemoveTrailingSlashes}/${InferDescendantToPaths>}` export type RelativeToParentPath< TRouter extends AnyRouter, TFrom extends string, TTo extends string, TResolvedPath extends string = ResolveRelativePath, > = | RelativeToPath | (TTo extends `${string}..` | `${string}../` ? TResolvedPath extends '/' | '' ? never : FindDescendantToPaths< TRouter, RemoveTrailingSlashes > extends never ? never : `${RemoveTrailingSlashes}/${ParentPath}` : never) export type RelativeToCurrentPath< TRouter extends AnyRouter, TFrom extends string, TTo extends string, TResolvedPath extends string = ResolveRelativePath, > = RelativeToPath | CurrentPath export type AbsoluteToPath = | (string extends TFrom ? CurrentPath : TFrom extends `/` ? never : CurrentPath) | (string extends TFrom ? ParentPath : TFrom extends `/` ? never : ParentPath) | RouteToPath | (TFrom extends '/' ? never : string extends TFrom ? never : InferDescendantToPaths>) export type RelativeToPathAutoComplete< TRouter extends AnyRouter, TFrom extends string, TTo extends string, > = string extends TTo ? string : string extends TFrom ? AbsoluteToPath : TTo & `..${string}` extends never ? TTo & `.${string}` extends never ? AbsoluteToPath : RelativeToCurrentPath : RelativeToParentPath export type NavigateOptions< TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = '.', TMaskFrom extends string = TFrom, TMaskTo extends string = '.', > = ToOptions & NavigateOptionProps /** * The NavigateOptions type is used to describe the options that can be used when describing a navigation action in TanStack Router. * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType) */ export interface NavigateOptionProps { /** * If set to `true`, the router will scroll the element with an id matching the hash into view with default `ScrollIntoViewOptions`. * If set to `false`, the router will not scroll the element with an id matching the hash into view. * If set to `ScrollIntoViewOptions`, the router will scroll the element with an id matching the hash into view with the provided options. * @default true * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#hashscrollintoview) * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) */ hashScrollIntoView?: boolean | ScrollIntoViewOptions /** * `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one. * @default false * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#replace) */ replace?: boolean /** * Defaults to `true` so that the scroll position will be reset to 0,0 after the location is committed to the browser history. * If `false`, the scroll position will not be reset to 0,0 after the location is committed to history. * @default true * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#resetscroll) */ resetScroll?: boolean /** @deprecated All navigations now use startTransition under the hood */ startTransition?: boolean /** * If set to `true`, the router will wrap the resulting navigation in a `document.startViewTransition()` call. * If `ViewTransitionOptions`, route navigations will be called using `document.startViewTransition({update, types})` * where `types` will be the strings array passed with `ViewTransitionOptions["types"]`. * If the browser does not support viewTransition types, the navigation will fall back to normal `document.startTransition()`, same as if `true` was passed. * * If the browser does not support this api, this option will be ignored. * @default false * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#viewtransition) * @see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) * @see [Google](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-types) */ viewTransition?: boolean | ViewTransitionOptions /** * If `true`, navigation will ignore any blockers that might prevent it. * @default false * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#ignoreblocker) */ ignoreBlocker?: boolean /** * If `true`, navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation. * @default false * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#reloaddocument) */ reloadDocument?: boolean /** * This can be used instead of `to` to navigate to a fully built href, e.g. pointing to an external target. * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/NavigateOptionsType#href) */ href?: string } export type ToOptions< TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = '.', TMaskFrom extends string = TFrom, TMaskTo extends string = '.', > = ToSubOptions & MaskOptions export interface MaskOptions< in out TRouter extends AnyRouter, in out TMaskFrom extends string, in out TMaskTo extends string, > { _fromLocation?: ParsedLocation mask?: ToMaskOptions } export type ToMaskOptions< TRouter extends AnyRouter = RegisteredRouter, TMaskFrom extends string = string, TMaskTo extends string = '.', > = ToSubOptions & { unmaskOnReload?: boolean } export type ToSubOptions< TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = '.', > = ToSubOptionsProps & SearchParamOptions & PathParamOptions export interface RequiredToOptions< in out TRouter extends AnyRouter, in out TFrom extends string, in out TTo extends string | undefined, > { to: ToPathOption & {} } export interface OptionalToOptions< in out TRouter extends AnyRouter, in out TFrom extends string, in out TTo extends string | undefined, > { to?: ToPathOption & {} } export type MakeToRequired< TRouter extends AnyRouter, TFrom extends string, TTo extends string | undefined, > = string extends TFrom ? string extends TTo ? OptionalToOptions : TTo & CatchAllPaths extends never ? RequiredToOptions : OptionalToOptions : OptionalToOptions export type ToSubOptionsProps< TRouter extends AnyRouter = RegisteredRouter, TFrom extends RoutePaths | string = string, TTo extends string | undefined = '.', > = MakeToRequired & { hash?: true | Updater state?: true | NonNullableUpdater from?: FromPathOption & {} } export type ParamsReducerFn< in out TRouter extends AnyRouter, in out TParamVariant extends ParamVariant, in out TFrom, in out TTo, > = ( current: Expand>, ) => Expand> type ParamsReducer< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, TTo, > = | Expand> | (ParamsReducerFn & {}) type ParamVariant = 'PATH' | 'SEARCH' export type ResolveRoute< TRouter extends AnyRouter, TFrom, TTo, TPath = ResolveRelativePath, > = TPath extends string ? TFrom extends TPath ? RouteByPath : RouteByToPath : never type ResolveFromParamType = TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchema' type ResolveFromAllParams< TRouter extends AnyRouter, TParamVariant extends ParamVariant, > = TParamVariant extends 'PATH' ? AllParams : FullSearchSchema type ResolveFromParams< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, > = string extends TFrom ? ResolveFromAllParams : RouteByPath< TRouter['routeTree'], TFrom >['types'][ResolveFromParamType] type ResolveToParamType = TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchemaInput' type ResolveAllToParams< TRouter extends AnyRouter, TParamVariant extends ParamVariant, > = TParamVariant extends 'PATH' ? AllParams : FullSearchSchemaInput export type ResolveToParams< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, TTo, > = ResolveRelativePath extends infer TPath ? undefined extends TPath ? never : string extends TPath ? ResolveAllToParams : TPath extends CatchAllPaths ? ResolveAllToParams : ResolveRoute< TRouter, TFrom, TTo >['types'][ResolveToParamType] : never type ResolveRelativeToParams< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, TTo, TToParams = ResolveToParams, > = TParamVariant extends 'SEARCH' ? TToParams : string extends TFrom ? TToParams : MakeDifferenceOptional< ResolveFromParams, TToParams > export interface MakeOptionalSearchParams< in out TRouter extends AnyRouter, in out TFrom, in out TTo, > { search?: true | (ParamsReducer & {}) } export interface MakeOptionalPathParams< in out TRouter extends AnyRouter, in out TFrom, in out TTo, > { params?: true | (ParamsReducer & {}) } type MakeRequiredParamsReducer< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, TTo, > = | (string extends TFrom ? never : ResolveFromParams extends WithoutEmpty< PickRequired< ResolveRelativeToParams > > ? true : never) | (ParamsReducer & {}) export interface MakeRequiredPathParams< in out TRouter extends AnyRouter, in out TFrom, in out TTo, > { params: MakeRequiredParamsReducer & {} } export interface MakeRequiredSearchParams< in out TRouter extends AnyRouter, in out TFrom, in out TTo, > { search: MakeRequiredParamsReducer & {} } export type IsRequired< TRouter extends AnyRouter, TParamVariant extends ParamVariant, TFrom, TTo, > = ResolveRelativePath extends infer TPath ? undefined extends TPath ? never : TPath extends CatchAllPaths ? never : IsRequiredParams< ResolveRelativeToParams > : never export type SearchParamOptions = IsRequired extends never ? MakeOptionalSearchParams : MakeRequiredSearchParams export type PathParamOptions = IsRequired extends never ? MakeOptionalPathParams : MakeRequiredPathParams export type ToPathOption< TRouter extends AnyRouter = AnyRouter, TFrom extends string = string, TTo extends string | undefined = string, > = ConstrainLiteral< TTo, RelativeToPathAutoComplete< TRouter, NoInfer extends string ? NoInfer : '', NoInfer & string > > export type FromPathOption = ConstrainLiteral< TFrom, RoutePaths > /** * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/navigation#active-options) */ export interface ActiveOptions { /** * If true, the link will be active if the current route matches the `to` route path exactly (no children routes) * @default false */ exact?: boolean /** * If true, the link will only be active if the current URL hash matches the `hash` prop * @default false */ includeHash?: boolean /** * If true, the link will only be active if the current URL search params inclusively match the `search` prop * @default true */ includeSearch?: boolean /** * This modifies the `includeSearch` behavior. * If true, properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active. * @default false */ explicitUndefined?: boolean } export interface LinkOptionsProps { /** * The standard anchor tag target attribute */ target?: HTMLAnchorElement['target'] /** * Configurable options to determine if the link should be considered active or not * @default {exact:true,includeHash:true} */ activeOptions?: ActiveOptions /** * The preloading strategy for this link * - `false` - No preloading * - `'intent'` - Preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there. * - `'viewport'` - Preload the linked route when it enters the viewport */ preload?: false | 'intent' | 'viewport' | 'render' /** * When a preload strategy is set, this delays the preload by this many milliseconds. * If the user exits the link before this delay, the preload will be cancelled. */ preloadDelay?: number /** * Control whether the link should be disabled or not * If set to `true`, the link will be rendered without an `href` attribute * @default false */ disabled?: boolean } export type LinkOptions< TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = '.', TMaskFrom extends string = TFrom, TMaskTo extends string = '.', > = NavigateOptions & LinkOptionsProps export type LinkCurrentTargetElement = { preloadTimeout?: null | ReturnType } export const preloadWarning = 'Error preloading route! ☝️'