@tanstack/react-router 0.0.1-beta.214 → 0.0.1-beta.216
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/Matches.js +14 -4
- package/build/cjs/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +94 -68
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/fileRoute.js.map +1 -1
- package/build/cjs/index.js +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/route.js +6 -0
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +114 -73
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +265 -265
- package/build/types/Matches.d.ts +4 -1
- package/build/types/RouterProvider.d.ts +2 -1
- package/build/types/fileRoute.d.ts +3 -3
- package/build/types/route.d.ts +30 -21
- package/build/types/router.d.ts +1 -1
- package/build/umd/index.development.js +114 -72
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +31 -9
- package/src/RouterProvider.tsx +115 -82
- package/src/fileRoute.ts +10 -2
- package/src/route.ts +69 -20
- package/src/router.ts +1 -1
package/build/cjs/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sources":["../../src/route.ts"],"sourcesContent":["import { HistoryLocation } from '@tanstack/history'\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport { useMatch } from './Matches'\nimport { AnyRouteMatch } from './RouterProvider'\nimport { NavigateOptions, ParsePathParams, ToSubOptions } from './link'\nimport { ParsedLocation } from './location'\nimport { joinPaths, trimPath } from './path'\nimport { RoutePaths } from './routeInfo'\nimport { AnyRouter } from './router'\nimport { useParams } from './useParams'\nimport { useSearch } from './useSearch'\nimport {\n Assign,\n Expand,\n IsAny,\n NoInfer,\n PickRequired,\n UnionToIntersection,\n} from './utils'\nimport { BuildLocationFn, NavigateFn } from './RouterProvider'\n\nexport const rootRouteId = '__root__' as const\nexport type RootRouteId = typeof rootRouteId\nexport type AnyPathParams = {}\n\nexport type AnySearchSchema = {}\n\nexport type AnyContext = {}\n\nexport interface RouteContext {}\n\nexport interface RouteMeta {}\n\nexport type PreloadableObj = { preload?: () => Promise<void> }\n\nexport type RoutePathOptions<TCustomId, TPath> =\n | {\n path: TPath\n }\n | {\n id: TCustomId\n }\n\nexport type RoutePathOptionsIntersection<TCustomId, TPath> =\n UnionToIntersection<RoutePathOptions<TCustomId, TPath>>\n\nexport type MetaOptions = keyof PickRequired<RouteMeta> extends never\n ? {\n meta?: RouteMeta\n }\n : {\n meta: RouteMeta\n }\n\nexport type RouteOptions<\n TParentRoute extends AnyRoute = AnyRoute,\n TCustomId extends string = string,\n TPath extends string = string,\n TSearchSchema extends Record<string, any> = {},\n TFullSearchSchema extends Record<string, any> = TSearchSchema,\n TParams extends AnyPathParams = AnyPathParams,\n TAllParams extends AnyPathParams = TParams,\n TRouteContext extends RouteContext = RouteContext,\n TAllContext extends Record<string, any> = AnyContext,\n> = BaseRouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext\n> &\n NoInfer<UpdatableRouteOptions<TFullSearchSchema, TAllParams, TAllContext>>\n\nexport type ParamsFallback<\n TPath extends string,\n TParams,\n> = unknown extends TParams ? Record<ParsePathParams<TPath>, string> : TParams\n\ntype Prefix<T extends string, U extends string> = U extends `${T}${infer _}`\n ? U\n : never\n\nexport type BaseRouteOptions<\n TParentRoute extends AnyRoute = AnyRoute,\n TCustomId extends string = string,\n TPath extends string = string,\n TSearchSchema extends Record<string, any> = {},\n TFullSearchSchema extends Record<string, any> = TSearchSchema,\n TParams extends AnyPathParams = {},\n TAllParams = ParamsFallback<TPath, TParams>,\n TRouteContext extends RouteContext = RouteContext,\n TAllContext extends Record<string, any> = AnyContext,\n> = RoutePathOptions<TCustomId, TPath> & {\n getParentRoute: () => TParentRoute\n validateSearch?: SearchSchemaValidator<TSearchSchema>\n} & (keyof PickRequired<RouteContext> extends never\n ? // This async function is called before a route is loaded.\n // If an error is thrown here, the route's loader will not be called.\n // If thrown during a navigation, the navigation will be cancelled and the error will be passed to the `onError` function.\n // If thrown during a preload event, the error will be logged to the console.\n {\n beforeLoad?: BeforeLoadFn<\n TFullSearchSchema,\n TParentRoute,\n TAllParams,\n TRouteContext\n >\n }\n : {\n beforeLoad: BeforeLoadFn<\n TFullSearchSchema,\n TParentRoute,\n TAllParams,\n TRouteContext\n >\n }) & {\n load?: RouteLoadFn<\n TAllParams,\n TFullSearchSchema,\n NoInfer<TAllContext>,\n NoInfer<TRouteContext>\n >\n } & (\n | {\n // Both or none\n parseParams?: (\n rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,\n ) => TParams extends Record<ParsePathParams<TPath>, any>\n ? TParams\n : 'parseParams must return an object'\n stringifyParams?: (\n params: NoInfer<ParamsFallback<TPath, TParams>>,\n ) => Record<ParsePathParams<TPath>, string>\n }\n | {\n stringifyParams?: never\n parseParams?: never\n }\n )\n\ntype BeforeLoadFn<\n TFullSearchSchema extends Record<string, any>,\n TParentRoute extends AnyRoute,\n TAllParams,\n TRouteContext,\n> = (opts: {\n search: TFullSearchSchema\n abortController: AbortController\n preload: boolean\n params: TAllParams\n context: TParentRoute['types']['allContext']\n location: ParsedLocation\n navigate: NavigateFn<AnyRoute>\n buildLocation: BuildLocationFn<AnyRoute>\n}) => Promise<TRouteContext> | TRouteContext | void\n\nexport type UpdatableRouteOptions<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends AnyContext,\n> = MetaOptions & {\n // test?: (args: TAllContext) => void\n // If true, this route will be matched as case-sensitive\n caseSensitive?: boolean\n // If true, this route will be forcefully wrapped in a suspense boundary\n wrapInSuspense?: boolean\n // The content to be rendered when the route is matched. If no component is provided, defaults to `<Outlet />`\n component?: RouteComponent<TFullSearchSchema, TAllParams, TAllContext>\n // The content to be rendered when the route encounters an error\n errorComponent?: ErrorRouteComponent<\n TFullSearchSchema,\n TAllParams,\n {}\n // TAllContext // TODO: I have no idea why this breaks the universe,\n // so we'll come back to it later.\n > //\n // If supported by your framework, the content to be rendered as the fallback content until the route is ready to render\n pendingComponent?: PendingRouteComponent<\n TFullSearchSchema,\n TAllParams,\n TAllContext\n >\n // Filter functions that can manipulate search params *before* they are passed to links and navigate\n // calls that match this route.\n preSearchFilters?: SearchFilter<TFullSearchSchema>[]\n // Filter functions that can manipulate search params *after* they are passed to links and navigate\n // calls that match this route.\n postSearchFilters?: SearchFilter<TFullSearchSchema>[]\n onError?: (err: any) => void\n // These functions are called as route matches are loaded, stick around and leave the active\n // matches\n onEnter?: (match: AnyRouteMatch) => void\n onTransition?: (match: AnyRouteMatch) => void\n onLeave?: (match: AnyRouteMatch) => void\n // Set this to true or false to specifically set whether or not this route should be preloaded. If unset, will\n // default to router.options.reloadOnWindowFocus\n reloadOnWindowFocus?: boolean\n}\n\nexport type ParseParamsOption<TPath extends string, TParams> = ParseParamsFn<\n TPath,\n TParams\n>\n\nexport type ParseParamsFn<TPath extends string, TParams> = (\n rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,\n) => TParams extends Record<ParsePathParams<TPath>, any>\n ? TParams\n : 'parseParams must return an object'\n\nexport type ParseParamsObj<TPath extends string, TParams> = {\n parse?: ParseParamsFn<TPath, TParams>\n}\n\n// The parse type here allows a zod schema to be passed directly to the validator\nexport type SearchSchemaValidator<TReturn> =\n | SearchSchemaValidatorObj<TReturn>\n | SearchSchemaValidatorFn<TReturn>\n\nexport type SearchSchemaValidatorObj<TReturn> = {\n parse?: SearchSchemaValidatorFn<TReturn>\n}\n\nexport type SearchSchemaValidatorFn<TReturn> = (\n searchObj: Record<string, unknown>,\n) => TReturn\n\nexport type DefinedPathParamWarning =\n 'Path params cannot be redefined by child routes!'\n\nexport type ParentParams<TParentParams> = AnyPathParams extends TParentParams\n ? {}\n : {\n [Key in keyof TParentParams]?: DefinedPathParamWarning\n }\n\nexport type RouteLoadFn<\n TAllParams = {},\n TFullSearchSchema extends Record<string, any> = {},\n TAllContext extends Record<string, any> = AnyContext,\n TRouteContext extends Record<string, any> = AnyContext,\n> = (\n match: LoadFnContext<\n TAllParams,\n TFullSearchSchema,\n TAllContext,\n TRouteContext\n > & {\n parentMatchPromise?: Promise<void>\n },\n) => any\n\nexport interface LoadFnContext<\n TAllParams = {},\n TFullSearchSchema extends Record<string, any> = {},\n TAllContext extends Record<string, any> = AnyContext,\n TRouteContext extends Record<string, any> = AnyContext,\n> {\n abortController: AbortController\n preload: boolean\n params: TAllParams\n search: TFullSearchSchema\n context: Expand<Assign<TAllContext, TRouteContext>>\n location: ParsedLocation<TFullSearchSchema>\n navigate: (opts: NavigateOptions<AnyRoute>) => Promise<void>\n}\n\nexport type SearchFilter<T, U = T> = (prev: T) => U\n\nexport type ResolveId<\n TParentRoute,\n TCustomId extends string,\n TPath extends string,\n> = TParentRoute extends { id: infer TParentId extends string }\n ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId>\n : RootRouteId\n\nexport type InferFullSearchSchema<TRoute> = TRoute extends {\n types: {\n fullSearchSchema: infer TFullSearchSchema\n }\n}\n ? TFullSearchSchema\n : {}\n\nexport type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = Expand<\n Assign<InferFullSearchSchema<TParentRoute>, TSearchSchema>\n>\n\nexport interface AnyRoute\n extends Route<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > {}\n\nexport type MergeFromFromParent<T, U> = IsAny<T, U, T & U>\n\nexport type StreamedPromise<T> = {\n promise: Promise<T>\n status: 'resolved' | 'pending'\n data: T\n resolve: (value: T) => void\n}\n\nexport type ResolveAllParams<\n TParentRoute extends AnyRoute,\n TParams extends AnyPathParams,\n> = Record<never, string> extends TParentRoute['types']['allParams']\n ? TParams\n : Expand<\n UnionToIntersection<TParentRoute['types']['allParams'] & TParams> & {}\n >\n\nexport type RouteConstraints = {\n TParentRoute: AnyRoute\n TPath: string\n TFullPath: string\n TCustomId: string\n TId: string\n TSearchSchema: AnySearchSchema\n TFullSearchSchema: AnySearchSchema\n TParams: Record<string, any>\n TAllParams: Record<string, any>\n TParentContext: AnyContext\n TRouteContext: RouteContext\n TAllContext: AnyContext\n TRouterContext: AnyContext\n TChildren: unknown\n TRouteTree: AnyRoute\n}\n\nexport class Route<\n TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,\n TPath extends RouteConstraints['TPath'] = '/',\n TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<\n TParentRoute,\n TPath\n >,\n TCustomId extends RouteConstraints['TCustomId'] = string,\n TId extends RouteConstraints['TId'] = ResolveId<\n TParentRoute,\n TCustomId,\n TPath\n >,\n TSearchSchema extends RouteConstraints['TSearchSchema'] = {},\n TFullSearchSchema extends RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<\n TParentRoute,\n TSearchSchema\n >,\n TParams extends RouteConstraints['TParams'] = Expand<\n Record<ParsePathParams<TPath>, string>\n >,\n TAllParams extends RouteConstraints['TAllParams'] = ResolveAllParams<\n TParentRoute,\n TParams\n >,\n TRouteContext extends RouteConstraints['TRouteContext'] = RouteContext,\n TAllContext extends Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n > = Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >,\n TRouterContext extends RouteConstraints['TRouterContext'] = AnyContext,\n TChildren extends RouteConstraints['TChildren'] = unknown,\n TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute,\n> {\n isRoot: TParentRoute extends Route<any> ? true : false\n options: RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext\n >\n\n test!: Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >\n\n // Set up in this.init()\n parentRoute!: TParentRoute\n id!: TId\n // customId!: TCustomId\n path!: TPath\n fullPath!: TFullPath\n to!: TrimPathRight<TFullPath>\n\n // Optional\n children?: TChildren\n originalIndex?: number\n router?: AnyRouter\n rank!: number\n\n constructor(\n options: RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext\n >,\n ) {\n this.options = (options as any) || {}\n this.isRoot = !options?.getParentRoute as any\n Route.__onInit(this)\n }\n\n types!: {\n parentRoute: TParentRoute\n path: TPath\n to: TrimPathRight<TFullPath>\n fullPath: TFullPath\n customId: TCustomId\n id: TId\n searchSchema: TSearchSchema\n fullSearchSchema: TFullSearchSchema\n params: TParams\n allParams: TAllParams\n routeContext: TRouteContext\n allContext: TAllContext\n children: TChildren\n routeTree: TRouteTree\n routerContext: TRouterContext\n }\n\n init = (opts: { originalIndex: number }) => {\n this.originalIndex = opts.originalIndex\n\n const options = this.options as RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext\n > &\n RoutePathOptionsIntersection<TCustomId, TPath>\n\n const isRoot = !options?.path && !options?.id\n\n this.parentRoute = this.options?.getParentRoute?.()\n\n if (isRoot) {\n this.path = rootRouteId as TPath\n } else {\n invariant(\n this.parentRoute,\n `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,\n )\n }\n\n let path: undefined | string = isRoot ? rootRouteId : options.path\n\n // If the path is anything other than an index path, trim it up\n if (path && path !== '/') {\n path = trimPath(path)\n }\n\n const customId = options?.id || path\n\n // Strip the parentId prefix from the first level of children\n let id = isRoot\n ? rootRouteId\n : joinPaths([\n (this.parentRoute.id as any) === rootRouteId\n ? ''\n : this.parentRoute.id,\n customId,\n ])\n\n if (path === rootRouteId) {\n path = '/'\n }\n\n if (id !== rootRouteId) {\n id = joinPaths(['/', id])\n }\n\n const fullPath =\n id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path])\n\n this.path = path as TPath\n this.id = id as TId\n // this.customId = customId as TCustomId\n this.fullPath = fullPath as TFullPath\n this.to = fullPath as TrimPathRight<TFullPath>\n }\n\n addChildren = <TNewChildren extends AnyRoute[]>(\n children: TNewChildren,\n ): Route<\n TParentRoute,\n TPath,\n TFullPath,\n TCustomId,\n TId,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TRouterContext,\n TNewChildren,\n TRouteTree\n > => {\n this.children = children as any\n return this as any\n }\n\n update = (\n options: UpdatableRouteOptions<\n TFullSearchSchema,\n TAllParams,\n Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >\n >,\n ) => {\n Object.assign(this.options, options)\n return this\n }\n\n static __onInit = (route: any) => {\n // This is a dummy static method that should get\n // replaced by a framework specific implementation if necessary\n }\n\n useMatch = <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }): TSelected => {\n return useMatch({ ...opts, from: this.id }) as any\n }\n useRouteContext = <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }): TSelected => {\n return useMatch({\n ...opts,\n from: this.id,\n select: (d: any) => (opts?.select ? opts.select(d.context) : d.context),\n } as any)\n }\n useSearch = <TSelected = TFullSearchSchema>(opts?: {\n select?: (search: TFullSearchSchema) => TSelected\n }): TSelected => {\n return useSearch({ ...opts, from: this.id } as any)\n }\n useParams = <TSelected = TAllParams>(opts?: {\n select?: (search: TAllParams) => TSelected\n }): TSelected => {\n return useParams({ ...opts, from: this.id } as any)\n }\n}\n\nexport type AnyRootRoute = RootRoute<any, any, any>\n\nexport function rootRouteWithContext<TRouterContext extends {}>() {\n return <\n TSearchSchema extends Record<string, any> = {},\n TRouteContext extends RouteContext = RouteContext,\n >(\n options?: Omit<\n RouteOptions<\n AnyRoute, // TParentRoute\n RootRouteId, // TCustomId\n '', // TPath\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Assign<TRouterContext, TRouteContext> // TAllContext\n >,\n | 'path'\n | 'id'\n | 'getParentRoute'\n | 'caseSensitive'\n | 'parseParams'\n | 'stringifyParams'\n >,\n ): RootRoute<TSearchSchema, TRouteContext, TRouterContext> => {\n return new RootRoute(options) as any\n }\n}\n\nexport class RootRoute<\n TSearchSchema extends Record<string, any> = {},\n TRouteContext extends RouteContext = RouteContext,\n TRouterContext extends {} = {},\n> extends Route<\n any, // TParentRoute\n '/', // TPath\n '/', // TFullPath\n string, // TCustomId\n RootRouteId, // TId\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Expand<Assign<TRouterContext, TRouteContext>>, // TAllContext\n TRouterContext, // TRouterContext\n any, // TChildren\n any // TRouteTree\n> {\n constructor(\n options?: Omit<\n RouteOptions<\n AnyRoute, // TParentRoute\n RootRouteId, // TCustomId\n '', // TPath\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Assign<TRouterContext, TRouteContext> // TAllContext\n >,\n | 'path'\n | 'id'\n | 'getParentRoute'\n | 'caseSensitive'\n | 'parseParams'\n | 'stringifyParams'\n >,\n ) {\n super(options as any)\n }\n}\n\nexport type ResolveFullPath<\n TParentRoute extends AnyRoute,\n TPath extends string,\n TPrefixed = RoutePrefix<TParentRoute['fullPath'], TPath>,\n> = TPrefixed extends RootRouteId ? '/' : TPrefixed\n\ntype RoutePrefix<\n TPrefix extends string,\n TPath extends string,\n> = string extends TPath\n ? RootRouteId\n : TPath extends string\n ? TPrefix extends RootRouteId\n ? TPath extends '/'\n ? '/'\n : `/${TrimPath<TPath>}`\n : `${TPrefix}/${TPath}` extends '/'\n ? '/'\n : `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TPath>}`>}`\n : never\n\nexport type TrimPath<T extends string> = '' extends T\n ? ''\n : TrimPathRight<TrimPathLeft<T>>\n\nexport type TrimPathLeft<T extends string> =\n T extends `${RootRouteId}/${infer U}`\n ? TrimPathLeft<U>\n : T extends `/${infer U}`\n ? TrimPathLeft<U>\n : T\nexport type TrimPathRight<T extends string> = T extends '/'\n ? '/'\n : T extends `${infer U}/`\n ? TrimPathRight<U>\n : T\n\nexport type RouteMask<TRouteTree extends AnyRoute> = {\n routeTree: TRouteTree\n from: RoutePaths<TRouteTree>\n to?: any\n params?: any\n search?: any\n hash?: any\n state?: any\n unmaskOnReload?: boolean\n}\n\nexport function createRouteMask<\n TRouteTree extends AnyRoute,\n TFrom extends RoutePaths<TRouteTree>,\n TTo extends string,\n>(\n opts: {\n routeTree: TRouteTree\n } & ToSubOptions<TRouteTree, TFrom, TTo>,\n): RouteMask<TRouteTree> {\n return opts as any\n}\n\nexport type RouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n> = {\n useMatch: <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }) => TSelected\n useRouteContext: <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }) => TSelected\n useSearch: <TSelected = TFullSearchSchema>(opts?: {\n select?: (search: TFullSearchSchema) => TSelected\n }) => TSelected\n useParams: <TSelected = TAllParams>(opts?: {\n select?: (search: TAllParams) => TSelected\n }) => TSelected\n}\n\nexport type ErrorRouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n> = {\n error: unknown\n info: { componentStack: string }\n} & RouteProps<TFullSearchSchema, TAllParams, TAllContext>\n\nexport type PendingRouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n> = RouteProps<TFullSearchSchema, TAllParams, TAllContext>\n//\n\nexport type ReactNode = any\n\nexport type SyncRouteComponent<TProps> =\n | ((props: TProps) => ReactNode)\n | React.LazyExoticComponent<(props: TProps) => ReactNode>\n\nexport type AsyncRouteComponent<TProps> = SyncRouteComponent<TProps> & {\n preload?: () => Promise<void>\n}\n\nexport type RouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n> = AsyncRouteComponent<RouteProps<TFullSearchSchema, TAllParams, TAllContext>>\n\nexport type ErrorRouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n> = AsyncRouteComponent<\n ErrorRouteProps<TFullSearchSchema, TAllParams, TAllContext>\n>\n\nexport type PendingRouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n> = AsyncRouteComponent<\n PendingRouteProps<TFullSearchSchema, TAllParams, TAllContext>\n>\n\nexport type AnyRouteComponent = RouteComponent<any, any, any>\n"],"names":["rootRouteId","Route","constructor","options","isRoot","getParentRoute","__onInit","init","opts","originalIndex","path","id","parentRoute","invariant","trimPath","customId","joinPaths","fullPath","to","addChildren","children","update","Object","assign","route","useMatch","from","useRouteContext","select","d","context","useSearch","useParams","rootRouteWithContext","RootRoute","createRouteMask"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"route.js","sources":["../../src/route.ts"],"sourcesContent":["import { HistoryLocation } from '@tanstack/history'\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport { useLoaderData, useMatch } from './Matches'\nimport { AnyRouteMatch } from './RouterProvider'\nimport { NavigateOptions, ParsePathParams, ToSubOptions } from './link'\nimport { ParsedLocation } from './location'\nimport { joinPaths, trimPath } from './path'\nimport { RoutePaths } from './routeInfo'\nimport { AnyRouter } from './router'\nimport { useParams } from './useParams'\nimport { useSearch } from './useSearch'\nimport {\n Assign,\n Expand,\n IsAny,\n NoInfer,\n PickRequired,\n UnionToIntersection,\n} from './utils'\nimport { BuildLocationFn, NavigateFn } from './RouterProvider'\n\nexport const rootRouteId = '__root__' as const\nexport type RootRouteId = typeof rootRouteId\nexport type AnyPathParams = {}\n\nexport type AnySearchSchema = {}\n\nexport type AnyContext = {}\n\nexport interface RouteContext {}\n\nexport interface RouteMeta {}\n\nexport type PreloadableObj = { preload?: () => Promise<void> }\n\nexport type RoutePathOptions<TCustomId, TPath> =\n | {\n path: TPath\n }\n | {\n id: TCustomId\n }\n\nexport type RoutePathOptionsIntersection<TCustomId, TPath> =\n UnionToIntersection<RoutePathOptions<TCustomId, TPath>>\n\nexport type MetaOptions = keyof PickRequired<RouteMeta> extends never\n ? {\n meta?: RouteMeta\n }\n : {\n meta: RouteMeta\n }\n\nexport type RouteOptions<\n TParentRoute extends AnyRoute = AnyRoute,\n TCustomId extends string = string,\n TPath extends string = string,\n TSearchSchema extends Record<string, any> = {},\n TFullSearchSchema extends Record<string, any> = TSearchSchema,\n TParams extends AnyPathParams = AnyPathParams,\n TAllParams extends AnyPathParams = TParams,\n TRouteContext extends RouteContext = RouteContext,\n TAllContext extends Record<string, any> = AnyContext,\n TLoaderData extends any = unknown,\n> = BaseRouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TLoaderData\n> &\n NoInfer<\n UpdatableRouteOptions<\n TFullSearchSchema,\n TAllParams,\n TAllContext,\n TLoaderData\n >\n >\n\nexport type ParamsFallback<\n TPath extends string,\n TParams,\n> = unknown extends TParams ? Record<ParsePathParams<TPath>, string> : TParams\n\ntype Prefix<T extends string, U extends string> = U extends `${T}${infer _}`\n ? U\n : never\n\nexport type BaseRouteOptions<\n TParentRoute extends AnyRoute = AnyRoute,\n TCustomId extends string = string,\n TPath extends string = string,\n TSearchSchema extends Record<string, any> = {},\n TFullSearchSchema extends Record<string, any> = TSearchSchema,\n TParams extends AnyPathParams = {},\n TAllParams = ParamsFallback<TPath, TParams>,\n TRouteContext extends RouteContext = RouteContext,\n TAllContext extends Record<string, any> = AnyContext,\n TLoaderData extends any = unknown,\n> = RoutePathOptions<TCustomId, TPath> & {\n getParentRoute: () => TParentRoute\n validateSearch?: SearchSchemaValidator<TSearchSchema>\n shouldReload?: (\n match: LoaderFnContext<\n TAllParams,\n TFullSearchSchema,\n TAllContext,\n TRouteContext\n >,\n ) => any\n} & (keyof PickRequired<RouteContext> extends never\n ? // This async function is called before a route is loaded.\n // If an error is thrown here, the route's loader will not be called.\n // If thrown during a navigation, the navigation will be cancelled and the error will be passed to the `onError` function.\n // If thrown during a preload event, the error will be logged to the console.\n {\n beforeLoad?: BeforeLoadFn<\n TFullSearchSchema,\n TParentRoute,\n TAllParams,\n TRouteContext\n >\n }\n : {\n beforeLoad: BeforeLoadFn<\n TFullSearchSchema,\n TParentRoute,\n TAllParams,\n TRouteContext\n >\n }) & {\n loader?: RouteLoadFn<\n TAllParams,\n TFullSearchSchema,\n NoInfer<TAllContext>,\n NoInfer<TRouteContext>,\n TLoaderData\n >\n } & (\n | {\n // Both or none\n parseParams?: (\n rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,\n ) => TParams extends Record<ParsePathParams<TPath>, any>\n ? TParams\n : 'parseParams must return an object'\n stringifyParams?: (\n params: NoInfer<ParamsFallback<TPath, TParams>>,\n ) => Record<ParsePathParams<TPath>, string>\n }\n | {\n stringifyParams?: never\n parseParams?: never\n }\n )\n\ntype BeforeLoadFn<\n TFullSearchSchema extends Record<string, any>,\n TParentRoute extends AnyRoute,\n TAllParams,\n TRouteContext,\n> = (opts: {\n search: TFullSearchSchema\n abortController: AbortController\n preload: boolean\n params: TAllParams\n context: TParentRoute['types']['allContext']\n location: ParsedLocation\n navigate: NavigateFn<AnyRoute>\n buildLocation: BuildLocationFn<AnyRoute>\n}) => Promise<TRouteContext> | TRouteContext | void\n\nexport type UpdatableRouteOptions<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends AnyContext,\n TLoaderData extends any = unknown,\n> = MetaOptions & {\n // test?: (args: TAllContext) => void\n // If true, this route will be matched as case-sensitive\n caseSensitive?: boolean\n // If true, this route will be forcefully wrapped in a suspense boundary\n wrapInSuspense?: boolean\n // The content to be rendered when the route is matched. If no component is provided, defaults to `<Outlet />`\n component?: RouteComponent<\n TFullSearchSchema,\n TAllParams,\n TAllContext,\n TLoaderData\n >\n // The content to be rendered when the route encounters an error\n errorComponent?: ErrorRouteComponent<\n TFullSearchSchema,\n TAllParams,\n {}\n // TAllContext // TODO: I have no idea why this breaks the universe,\n // so we'll come back to it later.\n > //\n // If supported by your framework, the content to be rendered as the fallback content until the route is ready to render\n pendingComponent?: PendingRouteComponent<\n TFullSearchSchema,\n TAllParams,\n TAllContext\n >\n // Filter functions that can manipulate search params *before* they are passed to links and navigate\n // calls that match this route.\n preSearchFilters?: SearchFilter<TFullSearchSchema>[]\n // Filter functions that can manipulate search params *after* they are passed to links and navigate\n // calls that match this route.\n postSearchFilters?: SearchFilter<TFullSearchSchema>[]\n onError?: (err: any) => void\n // These functions are called as route matches are loaded, stick around and leave the active\n // matches\n onEnter?: (match: AnyRouteMatch) => void\n onTransition?: (match: AnyRouteMatch) => void\n onLeave?: (match: AnyRouteMatch) => void\n // Set this to true or false to specifically set whether or not this route should be preloaded. If unset, will\n // default to router.options.reloadOnWindowFocus\n reloadOnWindowFocus?: boolean\n}\n\nexport type ParseParamsOption<TPath extends string, TParams> = ParseParamsFn<\n TPath,\n TParams\n>\n\nexport type ParseParamsFn<TPath extends string, TParams> = (\n rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,\n) => TParams extends Record<ParsePathParams<TPath>, any>\n ? TParams\n : 'parseParams must return an object'\n\nexport type ParseParamsObj<TPath extends string, TParams> = {\n parse?: ParseParamsFn<TPath, TParams>\n}\n\n// The parse type here allows a zod schema to be passed directly to the validator\nexport type SearchSchemaValidator<TReturn> =\n | SearchSchemaValidatorObj<TReturn>\n | SearchSchemaValidatorFn<TReturn>\n\nexport type SearchSchemaValidatorObj<TReturn> = {\n parse?: SearchSchemaValidatorFn<TReturn>\n}\n\nexport type SearchSchemaValidatorFn<TReturn> = (\n searchObj: Record<string, unknown>,\n) => TReturn\n\nexport type DefinedPathParamWarning =\n 'Path params cannot be redefined by child routes!'\n\nexport type ParentParams<TParentParams> = AnyPathParams extends TParentParams\n ? {}\n : {\n [Key in keyof TParentParams]?: DefinedPathParamWarning\n }\n\nexport type RouteLoadFn<\n TAllParams = {},\n TFullSearchSchema extends Record<string, any> = {},\n TAllContext extends Record<string, any> = AnyContext,\n TRouteContext extends Record<string, any> = AnyContext,\n TLoaderData extends any = unknown,\n> = (\n match: LoaderFnContext<\n TAllParams,\n TFullSearchSchema,\n TAllContext,\n TRouteContext\n >,\n) => Promise<TLoaderData> | TLoaderData\n\nexport interface LoaderFnContext<\n TAllParams = {},\n TFullSearchSchema extends Record<string, any> = {},\n TAllContext extends Record<string, any> = AnyContext,\n TRouteContext extends Record<string, any> = AnyContext,\n> {\n abortController: AbortController\n preload: boolean\n params: TAllParams\n search: TFullSearchSchema\n context: Expand<Assign<TAllContext, TRouteContext>>\n location: ParsedLocation<TFullSearchSchema>\n navigate: (opts: NavigateOptions<AnyRoute>) => Promise<void>\n parentMatchPromise?: Promise<void>\n cause: 'enter' | 'stay'\n}\n\nexport type SearchFilter<T, U = T> = (prev: T) => U\n\nexport type ResolveId<\n TParentRoute,\n TCustomId extends string,\n TPath extends string,\n> = TParentRoute extends { id: infer TParentId extends string }\n ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId>\n : RootRouteId\n\nexport type InferFullSearchSchema<TRoute> = TRoute extends {\n types: {\n fullSearchSchema: infer TFullSearchSchema\n }\n}\n ? TFullSearchSchema\n : {}\n\nexport type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = Expand<\n Assign<InferFullSearchSchema<TParentRoute>, TSearchSchema>\n>\n\nexport interface AnyRoute\n extends Route<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > {}\n\nexport type MergeFromFromParent<T, U> = IsAny<T, U, T & U>\n\nexport type StreamedPromise<T> = {\n promise: Promise<T>\n status: 'resolved' | 'pending'\n data: T\n resolve: (value: T) => void\n}\n\nexport type ResolveAllParams<\n TParentRoute extends AnyRoute,\n TParams extends AnyPathParams,\n> = Record<never, string> extends TParentRoute['types']['allParams']\n ? TParams\n : Expand<\n UnionToIntersection<TParentRoute['types']['allParams'] & TParams> & {}\n >\n\nexport type RouteConstraints = {\n TParentRoute: AnyRoute\n TPath: string\n TFullPath: string\n TCustomId: string\n TId: string\n TSearchSchema: AnySearchSchema\n TFullSearchSchema: AnySearchSchema\n TParams: Record<string, any>\n TAllParams: Record<string, any>\n TParentContext: AnyContext\n TRouteContext: RouteContext\n TAllContext: AnyContext\n TRouterContext: AnyContext\n TChildren: unknown\n TRouteTree: AnyRoute\n}\n\nexport class Route<\n TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,\n TPath extends RouteConstraints['TPath'] = '/',\n TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<\n TParentRoute,\n TPath\n >,\n TCustomId extends RouteConstraints['TCustomId'] = string,\n TId extends RouteConstraints['TId'] = ResolveId<\n TParentRoute,\n TCustomId,\n TPath\n >,\n TSearchSchema extends RouteConstraints['TSearchSchema'] = {},\n TFullSearchSchema extends RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<\n TParentRoute,\n TSearchSchema\n >,\n TParams extends RouteConstraints['TParams'] = Expand<\n Record<ParsePathParams<TPath>, string>\n >,\n TAllParams extends RouteConstraints['TAllParams'] = ResolveAllParams<\n TParentRoute,\n TParams\n >,\n TRouteContext extends RouteConstraints['TRouteContext'] = RouteContext,\n TAllContext extends Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n > = Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >,\n TRouterContext extends RouteConstraints['TRouterContext'] = AnyContext,\n TLoaderData extends any = unknown,\n TChildren extends RouteConstraints['TChildren'] = unknown,\n TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute,\n> {\n isRoot: TParentRoute extends Route<any> ? true : false\n options: RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TLoaderData\n >\n\n test!: Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >\n\n // Set up in this.init()\n parentRoute!: TParentRoute\n id!: TId\n // customId!: TCustomId\n path!: TPath\n fullPath!: TFullPath\n to!: TrimPathRight<TFullPath>\n\n // Optional\n children?: TChildren\n originalIndex?: number\n router?: AnyRouter\n rank!: number\n\n constructor(\n options: RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TLoaderData\n >,\n ) {\n this.options = (options as any) || {}\n this.isRoot = !options?.getParentRoute as any\n Route.__onInit(this)\n }\n\n types!: {\n parentRoute: TParentRoute\n path: TPath\n to: TrimPathRight<TFullPath>\n fullPath: TFullPath\n customId: TCustomId\n id: TId\n searchSchema: TSearchSchema\n fullSearchSchema: TFullSearchSchema\n params: TParams\n allParams: TAllParams\n routeContext: TRouteContext\n allContext: TAllContext\n children: TChildren\n routeTree: TRouteTree\n routerContext: TRouterContext\n loaderData: TLoaderData\n }\n\n init = (opts: { originalIndex: number }) => {\n this.originalIndex = opts.originalIndex\n\n const options = this.options as RouteOptions<\n TParentRoute,\n TCustomId,\n TPath,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TLoaderData\n > &\n RoutePathOptionsIntersection<TCustomId, TPath>\n\n const isRoot = !options?.path && !options?.id\n\n this.parentRoute = this.options?.getParentRoute?.()\n\n if (isRoot) {\n this.path = rootRouteId as TPath\n } else {\n invariant(\n this.parentRoute,\n `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,\n )\n }\n\n let path: undefined | string = isRoot ? rootRouteId : options.path\n\n // If the path is anything other than an index path, trim it up\n if (path && path !== '/') {\n path = trimPath(path)\n }\n\n const customId = options?.id || path\n\n // Strip the parentId prefix from the first level of children\n let id = isRoot\n ? rootRouteId\n : joinPaths([\n (this.parentRoute.id as any) === rootRouteId\n ? ''\n : this.parentRoute.id,\n customId,\n ])\n\n if (path === rootRouteId) {\n path = '/'\n }\n\n if (id !== rootRouteId) {\n id = joinPaths(['/', id])\n }\n\n const fullPath =\n id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path])\n\n this.path = path as TPath\n this.id = id as TId\n // this.customId = customId as TCustomId\n this.fullPath = fullPath as TFullPath\n this.to = fullPath as TrimPathRight<TFullPath>\n }\n\n addChildren = <TNewChildren extends AnyRoute[]>(\n children: TNewChildren,\n ): Route<\n TParentRoute,\n TPath,\n TFullPath,\n TCustomId,\n TId,\n TSearchSchema,\n TFullSearchSchema,\n TParams,\n TAllParams,\n TRouteContext,\n TAllContext,\n TRouterContext,\n TNewChildren,\n TRouteTree\n > => {\n this.children = children as any\n return this as any\n }\n\n update = (\n options: UpdatableRouteOptions<\n TFullSearchSchema,\n TAllParams,\n Expand<\n Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>\n >,\n TLoaderData\n >,\n ) => {\n Object.assign(this.options, options)\n return this\n }\n\n static __onInit = (route: any) => {\n // This is a dummy static method that should get\n // replaced by a framework specific implementation if necessary\n }\n\n useMatch = <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }): TSelected => {\n return useMatch({ ...opts, from: this.id }) as any\n }\n useRouteContext = <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }): TSelected => {\n return useMatch({\n ...opts,\n from: this.id,\n select: (d: any) => (opts?.select ? opts.select(d.context) : d.context),\n } as any)\n }\n useSearch = <TSelected = TFullSearchSchema>(opts?: {\n select?: (search: TFullSearchSchema) => TSelected\n }): TSelected => {\n return useSearch({ ...opts, from: this.id } as any)\n }\n useParams = <TSelected = TAllParams>(opts?: {\n select?: (search: TAllParams) => TSelected\n }): TSelected => {\n return useParams({ ...opts, from: this.id } as any)\n }\n useLoaderData = <TSelected = TLoaderData>(opts?: {\n select?: (search: TLoaderData) => TSelected\n }): TSelected => {\n return useLoaderData({ ...opts, from: this.id } as any) as any\n }\n}\n\nexport type AnyRootRoute = RootRoute<any, any, any>\n\nexport function rootRouteWithContext<TRouterContext extends {}>() {\n return <\n TSearchSchema extends Record<string, any> = {},\n TRouteContext extends RouteContext = RouteContext,\n TLoaderData extends any = unknown,\n >(\n options?: Omit<\n RouteOptions<\n AnyRoute, // TParentRoute\n RootRouteId, // TCustomId\n '', // TPath\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Assign<TRouterContext, TRouteContext>, // TAllContext\n TLoaderData // TLoaderData\n >,\n | 'path'\n | 'id'\n | 'getParentRoute'\n | 'caseSensitive'\n | 'parseParams'\n | 'stringifyParams'\n >,\n ): RootRoute<TSearchSchema, TRouteContext, TRouterContext> => {\n return new RootRoute(options) as any\n }\n}\n\nexport class RootRoute<\n TSearchSchema extends Record<string, any> = {},\n TRouteContext extends RouteContext = RouteContext,\n TRouterContext extends {} = {},\n TLoaderData extends any = unknown,\n> extends Route<\n any, // TParentRoute\n '/', // TPath\n '/', // TFullPath\n string, // TCustomId\n RootRouteId, // TId\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Expand<Assign<TRouterContext, TRouteContext>>, // TAllContext\n TRouterContext, // TRouterContext\n TLoaderData,\n any, // TChildren\n any // TRouteTree\n> {\n constructor(\n options?: Omit<\n RouteOptions<\n AnyRoute, // TParentRoute\n RootRouteId, // TCustomId\n '', // TPath\n TSearchSchema, // TSearchSchema\n TSearchSchema, // TFullSearchSchema\n {}, // TParams\n {}, // TAllParams\n TRouteContext, // TRouteContext\n Assign<TRouterContext, TRouteContext>, // TAllContext\n TLoaderData\n >,\n | 'path'\n | 'id'\n | 'getParentRoute'\n | 'caseSensitive'\n | 'parseParams'\n | 'stringifyParams'\n >,\n ) {\n super(options as any)\n }\n}\n\nexport type ResolveFullPath<\n TParentRoute extends AnyRoute,\n TPath extends string,\n TPrefixed = RoutePrefix<TParentRoute['fullPath'], TPath>,\n> = TPrefixed extends RootRouteId ? '/' : TPrefixed\n\ntype RoutePrefix<\n TPrefix extends string,\n TPath extends string,\n> = string extends TPath\n ? RootRouteId\n : TPath extends string\n ? TPrefix extends RootRouteId\n ? TPath extends '/'\n ? '/'\n : `/${TrimPath<TPath>}`\n : `${TPrefix}/${TPath}` extends '/'\n ? '/'\n : `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TPath>}`>}`\n : never\n\nexport type TrimPath<T extends string> = '' extends T\n ? ''\n : TrimPathRight<TrimPathLeft<T>>\n\nexport type TrimPathLeft<T extends string> =\n T extends `${RootRouteId}/${infer U}`\n ? TrimPathLeft<U>\n : T extends `/${infer U}`\n ? TrimPathLeft<U>\n : T\nexport type TrimPathRight<T extends string> = T extends '/'\n ? '/'\n : T extends `${infer U}/`\n ? TrimPathRight<U>\n : T\n\nexport type RouteMask<TRouteTree extends AnyRoute> = {\n routeTree: TRouteTree\n from: RoutePaths<TRouteTree>\n to?: any\n params?: any\n search?: any\n hash?: any\n state?: any\n unmaskOnReload?: boolean\n}\n\nexport function createRouteMask<\n TRouteTree extends AnyRoute,\n TFrom extends RoutePaths<TRouteTree>,\n TTo extends string,\n>(\n opts: {\n routeTree: TRouteTree\n } & ToSubOptions<TRouteTree, TFrom, TTo>,\n): RouteMask<TRouteTree> {\n return opts as any\n}\n\nexport type RouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n TLoaderData extends any = unknown,\n> = {\n useMatch: <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }) => TSelected\n useRouteContext: <TSelected = TAllContext>(opts?: {\n select?: (search: TAllContext) => TSelected\n }) => TSelected\n useSearch: <TSelected = TFullSearchSchema>(opts?: {\n select?: (search: TFullSearchSchema) => TSelected\n }) => TSelected\n useParams: <TSelected = TAllParams>(opts?: {\n select?: (search: TAllParams) => TSelected\n }) => TSelected\n useLoaderData: <TSelected = TLoaderData>(opts?: {\n select?: (search: TLoaderData) => TSelected\n }) => TSelected\n}\n\nexport type ErrorRouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n> = {\n error: unknown\n info: { componentStack: string }\n} & RouteProps<TFullSearchSchema, TAllParams, TAllContext>\n\nexport type PendingRouteProps<\n TFullSearchSchema extends Record<string, any> = AnySearchSchema,\n TAllParams extends AnyPathParams = AnyPathParams,\n TAllContext extends Record<string, any> = AnyContext,\n> = RouteProps<TFullSearchSchema, TAllParams, TAllContext>\n//\n\nexport type ReactNode = any\n\nexport type SyncRouteComponent<TProps> =\n | ((props: TProps) => ReactNode)\n | React.LazyExoticComponent<(props: TProps) => ReactNode>\n\nexport type AsyncRouteComponent<TProps> = SyncRouteComponent<TProps> & {\n preload?: () => Promise<void>\n}\n\nexport type RouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n TLoaderData extends any = unknown,\n> = AsyncRouteComponent<\n RouteProps<TFullSearchSchema, TAllParams, TAllContext, TLoaderData>\n>\n\nexport type ErrorRouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n> = AsyncRouteComponent<\n ErrorRouteProps<TFullSearchSchema, TAllParams, TAllContext>\n>\n\nexport type PendingRouteComponent<\n TFullSearchSchema extends Record<string, any>,\n TAllParams extends AnyPathParams,\n TAllContext extends Record<string, any>,\n> = AsyncRouteComponent<\n PendingRouteProps<TFullSearchSchema, TAllParams, TAllContext>\n>\n\nexport type AnyRouteComponent = RouteComponent<any, any, any, any>\n"],"names":["rootRouteId","Route","constructor","options","isRoot","getParentRoute","__onInit","init","opts","originalIndex","path","id","parentRoute","invariant","trimPath","customId","joinPaths","fullPath","to","addChildren","children","update","Object","assign","route","useMatch","from","useRouteContext","select","d","context","useSearch","useParams","useLoaderData","rootRouteWithContext","RootRoute","createRouteMask"],"mappings":"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"}
|
package/build/cjs/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sources":["../../src/router.ts"],"sourcesContent":["import { RouterHistory } from '@tanstack/history'\n\n//\n\nimport {\n AnySearchSchema,\n AnyRoute,\n AnyContext,\n AnyPathParams,\n RouteMask,\n} from './route'\nimport { FullSearchSchema } from './routeInfo'\nimport { defaultParseSearch, defaultStringifySearch } from './searchParams'\nimport { PickAsRequired, Updater, NonNullableUpdater } from './utils'\nimport {\n ErrorRouteComponent,\n PendingRouteComponent,\n RouteComponent,\n} from './route'\nimport { RouteMatch } from './RouterProvider'\nimport { ParsedLocation } from './location'\nimport { LocationState } from './location'\nimport { SearchSerializer, SearchParser } from './searchParams'\nimport { RouterContext } from './RouterProvider'\n\n//\n\ndeclare global {\n interface Window {\n __TSR_DEHYDRATED__?: HydrationCtx\n __TSR_ROUTER_CONTEXT__?: React.Context<RouterContext<any>>\n }\n}\n\nexport interface Register {\n // router: Router\n}\n\nexport type AnyRouter = Router<any, any>\n\nexport type RegisteredRouter = Register extends {\n router: infer TRouter extends AnyRouter\n}\n ? TRouter\n : AnyRouter\n\nexport type HydrationCtx = {\n router: DehydratedRouter\n payload: Record<string, any>\n}\n\nexport type RouterContextOptions<TRouteTree extends AnyRoute> =\n AnyContext extends TRouteTree['types']['routerContext']\n ? {\n context?: TRouteTree['types']['routerContext']\n }\n : {\n context: TRouteTree['types']['routerContext']\n }\n\nexport interface RouterOptions<\n TRouteTree extends AnyRoute,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> {\n history?: RouterHistory\n stringifySearch?: SearchSerializer\n parseSearch?: SearchParser\n defaultPreload?: false | 'intent'\n defaultPreloadDelay?: number\n defaultComponent?: RouteComponent<AnySearchSchema, AnyPathParams, AnyContext>\n defaultErrorComponent?: ErrorRouteComponent<\n AnySearchSchema,\n AnyPathParams,\n AnyContext\n >\n defaultPendingComponent?: PendingRouteComponent<\n AnySearchSchema,\n AnyPathParams,\n AnyContext\n >\n defaultMaxAge?: number\n defaultGcMaxAge?: number\n defaultPreloadMaxAge?: number\n caseSensitive?: boolean\n routeTree?: TRouteTree\n basepath?: string\n createRoute?: (opts: { route: AnyRoute; router: AnyRouter }) => void\n context?: TRouteTree['types']['routerContext']\n // dehydrate?: () => TDehydrated\n // hydrate?: (dehydrated: TDehydrated) => void\n routeMasks?: RouteMask<TRouteTree>[]\n unmaskOnReload?: boolean\n}\n\nexport interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {\n status: 'pending' | 'idle'\n matches: RouteMatch<TRouteTree>[]\n pendingMatches: RouteMatch<TRouteTree>[]\n location: ParsedLocation<FullSearchSchema<TRouteTree>>\n resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>\n lastUpdated: number\n}\n\nexport type ListenerFn<TEvent extends RouterEvent> = (event: TEvent) => void\n\nexport interface BuildNextOptions {\n to?: string | number | null\n params?: true | Updater<unknown>\n search?: true | Updater<unknown>\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<LocationState>\n mask?: {\n to?: string | number | null\n params?: true | Updater<unknown>\n search?: true | Updater<unknown>\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<LocationState>\n unmaskOnReload?: boolean\n }\n from?: string\n}\n\nexport interface DehydratedRouterState {\n dehydratedMatches: DehydratedRouteMatch[]\n}\n\nexport type DehydratedRouteMatch = Pick<\n RouteMatch,\n 'fetchedAt' | 'invalid' | 'id' | 'status' | 'updatedAt'\n>\n\nexport interface DehydratedRouter {\n state: DehydratedRouterState\n}\n\nexport type RouterConstructorOptions<\n TRouteTree extends AnyRoute,\n TDehydrated extends Record<string, any>,\n> = Omit<RouterOptions<TRouteTree, TDehydrated>, 'context'> &\n RouterContextOptions<TRouteTree>\n\nexport const componentTypes = [\n 'component',\n 'errorComponent',\n 'pendingComponent',\n] as const\n\nexport type RouterEvents = {\n onBeforeLoad: {\n type: 'onBeforeLoad'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n onLoad: {\n type: 'onLoad'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n onResolved: {\n type: 'onResolved'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n}\n\nexport type RouterEvent = RouterEvents[keyof RouterEvents]\n\nexport type RouterListener<TRouterEvent extends RouterEvent> = {\n eventType: TRouterEvent['type']\n fn: ListenerFn<TRouterEvent>\n}\n\nexport class Router<\n TRouteTree extends AnyRoute = AnyRoute,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> {\n options: PickAsRequired<\n RouterOptions<TRouteTree, TDehydrated>,\n 'stringifySearch' | 'parseSearch' | 'context'\n >\n routeTree: TRouteTree\n // dehydratedData?: TDehydrated\n // resetNextScroll = false\n // tempLocationKey = `${Math.round(Math.random() * 10000000)}`\n\n constructor(options: RouterConstructorOptions<TRouteTree, TDehydrated>) {\n this.options = {\n defaultPreloadDelay: 50,\n context: undefined!,\n ...options,\n stringifySearch: options?.stringifySearch ?? defaultStringifySearch,\n parseSearch: options?.parseSearch ?? defaultParseSearch,\n }\n\n this.routeTree = this.options.routeTree as TRouteTree\n }\n\n subscribers = new Set<RouterListener<RouterEvent>>()\n\n subscribe = <TType extends keyof RouterEvents>(\n eventType: TType,\n fn: ListenerFn<RouterEvents[TType]>,\n ) => {\n const listener: RouterListener<any> = {\n eventType,\n fn,\n }\n\n this.subscribers.add(listener)\n\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n emit = (routerEvent: RouterEvent) => {\n this.subscribers.forEach((listener) => {\n if (listener.eventType === routerEvent.type) {\n listener.fn(routerEvent)\n }\n })\n }\n\n // dehydrate = (): DehydratedRouter => {\n // return {\n // state: {\n // dehydratedMatches: state.matches.map((d) =>\n // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),\n // ),\n // },\n // }\n // }\n\n // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {\n // let _ctx = __do_not_use_server_ctx\n // // Client hydrates from window\n // if (typeof document !== 'undefined') {\n // _ctx = window.__TSR_DEHYDRATED__\n // }\n\n // invariant(\n // _ctx,\n // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',\n // )\n\n // const ctx = _ctx\n // this.dehydratedData = ctx.payload as any\n // this.options.hydrate?.(ctx.payload as any)\n // const dehydratedState = ctx.router.state\n\n // let matches = this.matchRoutes(\n // state.location.pathname,\n // state.location.search,\n // ).map((match) => {\n // const dehydratedMatch = dehydratedState.dehydratedMatches.find(\n // (d) => d.id === match.id,\n // )\n\n // invariant(\n // dehydratedMatch,\n // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,\n // )\n\n // if (dehydratedMatch) {\n // return {\n // ...match,\n // ...dehydratedMatch,\n // }\n // }\n // return match\n // })\n\n // this.setState((s) => {\n // return {\n // ...s,\n // matches: dehydratedState.dehydratedMatches as any,\n // }\n // })\n // }\n\n // TODO:\n // injectedHtml: (string | (() => Promise<string> | string))[] = []\n\n // TODO:\n // injectHtml = async (html: string | (() => Promise<string> | string)) => {\n // this.injectedHtml.push(html)\n // }\n\n // TODO:\n // dehydrateData = <T>(key: any, getData: T | (() => Promise<T> | T)) => {\n // if (typeof document === 'undefined') {\n // const strKey = typeof key === 'string' ? key : JSON.stringify(key)\n\n // this.injectHtml(async () => {\n // const id = `__TSR_DEHYDRATED__${strKey}`\n // const data =\n // typeof getData === 'function' ? await (getData as any)() : getData\n // return `<script id='${id}' suppressHydrationWarning>window[\"__TSR_DEHYDRATED__${escapeJSON(\n // strKey,\n // )}\"] = ${JSON.stringify(data)}\n // ;(() => {\n // var el = document.getElementById('${id}')\n // el.parentElement.removeChild(el)\n // })()\n // </script>`\n // })\n\n // return () => this.hydrateData<T>(key)\n // }\n\n // return () => undefined\n // }\n\n // hydrateData = <T = unknown>(key: any) => {\n // if (typeof document !== 'undefined') {\n // const strKey = typeof key === 'string' ? key : JSON.stringify(key)\n\n // return window[`__TSR_DEHYDRATED__${strKey}` as any] as T\n // }\n\n // return undefined\n // }\n\n // resolveMatchPromise = (matchId: string, key: string, value: any) => {\n // state.matches\n // .find((d) => d.id === matchId)\n // ?.__promisesByKey[key]?.resolve(value)\n // }\n\n // setRouteMatch = (\n // id: string,\n // pending: boolean,\n // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,\n // ) => {\n // const key = pending ? 'pendingMatches' : 'matches'\n\n // this.setState((prev) => {\n // return {\n // ...prev,\n // [key]: prev[key].map((d) => {\n // if (d.id === id) {\n // return functionalUpdate(updater, d)\n // }\n\n // return d\n // }),\n // }\n // })\n // }\n\n // setPendingRouteMatch = (\n // id: string,\n // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,\n // ) => {\n // this.setRouteMatch(id, true, updater)\n // }\n}\n\nfunction 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\n// A function that takes an import() argument which is a function and returns a new function that will\n// proxy arguments from the caller to the imported function, retaining all type\n// information along the way\nexport function lazyFn<\n T extends Record<string, (...args: any[]) => any>,\n TKey extends keyof T = 'default',\n>(fn: () => Promise<T>, key?: TKey) {\n return async (...args: Parameters<T[TKey]>): Promise<ReturnType<T[TKey]>> => {\n const imported = await fn()\n return imported[key || 'default'](...args)\n }\n}\n"],"names":["componentTypes","Router","constructor","options","defaultPreloadDelay","context","undefined","stringifySearch","defaultStringifySearch","parseSearch","defaultParseSearch","routeTree","subscribers","Set","subscribe","eventType","fn","listener","add","delete","emit","routerEvent","forEach","type","lazyFn","key","args","imported"],"mappings":";;;;;;;;;;;;;;;;AAEA;;AAuBA;;AAoHO,MAAMA,cAAc,GAAG,CAC5B,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EACV;AA8BH,MAAMC,MAAM,CAGjB;AAMA;AACA;AACA;EAEAC,WAAWA,CAACC,OAA0D,EAAE;IACtE,IAAI,CAACA,OAAO,GAAG;AACbC,MAAAA,mBAAmB,EAAE,EAAE;AACvBC,MAAAA,OAAO,EAAEC,SAAU;AACnB,MAAA,GAAGH,OAAO;AACVI,MAAAA,eAAe,EAAEJ,OAAO,EAAEI,eAAe,IAAIC,mCAAsB;AACnEC,MAAAA,WAAW,EAAEN,OAAO,EAAEM,WAAW,IAAIC,+BAAAA;KACtC,CAAA;AAED,IAAA,IAAI,CAACC,SAAS,GAAG,IAAI,CAACR,OAAO,CAACQ,SAAuB,CAAA;AACvD,GAAA;AAEAC,EAAAA,WAAW,GAAG,IAAIC,GAAG,EAA+B,CAAA;AAEpDC,EAAAA,SAAS,GAAGA,CACVC,SAAgB,EAChBC,EAAmC,KAChC;AACH,IAAA,MAAMC,QAA6B,GAAG;MACpCF,SAAS;AACTC,MAAAA,EAAAA;KACD,CAAA;AAED,IAAA,IAAI,CAACJ,WAAW,CAACM,GAAG,CAACD,QAAQ,CAAC,CAAA;AAE9B,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACL,WAAW,CAACO,MAAM,CAACF,QAAQ,CAAC,CAAA;KAClC,CAAA;GACF,CAAA;EAEDG,IAAI,GAAIC,WAAwB,IAAK;AACnC,IAAA,IAAI,CAACT,WAAW,CAACU,OAAO,CAAEL,QAAQ,IAAK;AACrC,MAAA,IAAIA,QAAQ,CAACF,SAAS,KAAKM,WAAW,CAACE,IAAI,EAAE;AAC3CN,QAAAA,QAAQ,CAACD,EAAE,CAACK,WAAW,CAAC,CAAA;AAC1B,OAAA;AACF,KAAC,CAAC,CAAA;GACH,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACF,CAAA;;AASA;AACA;AACA;AACO,SAASG,MAAMA,CAGpBR,EAAoB,EAAES,GAAU,EAAE;EAClC,OAAO,OAAO,GAAGC,IAAyB,KAAmC;AAC3E,IAAA,MAAMC,QAAQ,GAAG,MAAMX,EAAE,EAAE,CAAA;IAC3B,OAAOW,QAAQ,CAACF,GAAG,IAAI,SAAS,CAAC,CAAC,GAAGC,IAAI,CAAC,CAAA;GAC3C,CAAA;AACH;;;;;;"}
|
|
1
|
+
{"version":3,"file":"router.js","sources":["../../src/router.ts"],"sourcesContent":["import { RouterHistory } from '@tanstack/history'\n\n//\n\nimport {\n AnySearchSchema,\n AnyRoute,\n AnyContext,\n AnyPathParams,\n RouteMask,\n} from './route'\nimport { FullSearchSchema } from './routeInfo'\nimport { defaultParseSearch, defaultStringifySearch } from './searchParams'\nimport { PickAsRequired, Updater, NonNullableUpdater } from './utils'\nimport {\n ErrorRouteComponent,\n PendingRouteComponent,\n RouteComponent,\n} from './route'\nimport { RouteMatch } from './RouterProvider'\nimport { ParsedLocation } from './location'\nimport { LocationState } from './location'\nimport { SearchSerializer, SearchParser } from './searchParams'\nimport { RouterContext } from './RouterProvider'\n\n//\n\ndeclare global {\n interface Window {\n __TSR_DEHYDRATED__?: HydrationCtx\n __TSR_ROUTER_CONTEXT__?: React.Context<RouterContext<any>>\n }\n}\n\nexport interface Register {\n // router: Router\n}\n\nexport type AnyRouter = Router<AnyRoute, any>\n\nexport type RegisteredRouter = Register extends {\n router: infer TRouter extends AnyRouter\n}\n ? TRouter\n : AnyRouter\n\nexport type HydrationCtx = {\n router: DehydratedRouter\n payload: Record<string, any>\n}\n\nexport type RouterContextOptions<TRouteTree extends AnyRoute> =\n AnyContext extends TRouteTree['types']['routerContext']\n ? {\n context?: TRouteTree['types']['routerContext']\n }\n : {\n context: TRouteTree['types']['routerContext']\n }\n\nexport interface RouterOptions<\n TRouteTree extends AnyRoute,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> {\n history?: RouterHistory\n stringifySearch?: SearchSerializer\n parseSearch?: SearchParser\n defaultPreload?: false | 'intent'\n defaultPreloadDelay?: number\n defaultComponent?: RouteComponent<AnySearchSchema, AnyPathParams, AnyContext>\n defaultErrorComponent?: ErrorRouteComponent<\n AnySearchSchema,\n AnyPathParams,\n AnyContext\n >\n defaultPendingComponent?: PendingRouteComponent<\n AnySearchSchema,\n AnyPathParams,\n AnyContext\n >\n defaultMaxAge?: number\n defaultGcMaxAge?: number\n defaultPreloadMaxAge?: number\n caseSensitive?: boolean\n routeTree?: TRouteTree\n basepath?: string\n createRoute?: (opts: { route: AnyRoute; router: AnyRouter }) => void\n context?: TRouteTree['types']['routerContext']\n // dehydrate?: () => TDehydrated\n // hydrate?: (dehydrated: TDehydrated) => void\n routeMasks?: RouteMask<TRouteTree>[]\n unmaskOnReload?: boolean\n}\n\nexport interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {\n status: 'pending' | 'idle'\n matches: RouteMatch<TRouteTree>[]\n pendingMatches: RouteMatch<TRouteTree>[]\n location: ParsedLocation<FullSearchSchema<TRouteTree>>\n resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>\n lastUpdated: number\n}\n\nexport type ListenerFn<TEvent extends RouterEvent> = (event: TEvent) => void\n\nexport interface BuildNextOptions {\n to?: string | number | null\n params?: true | Updater<unknown>\n search?: true | Updater<unknown>\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<LocationState>\n mask?: {\n to?: string | number | null\n params?: true | Updater<unknown>\n search?: true | Updater<unknown>\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<LocationState>\n unmaskOnReload?: boolean\n }\n from?: string\n}\n\nexport interface DehydratedRouterState {\n dehydratedMatches: DehydratedRouteMatch[]\n}\n\nexport type DehydratedRouteMatch = Pick<\n RouteMatch,\n 'fetchedAt' | 'invalid' | 'id' | 'status' | 'updatedAt'\n>\n\nexport interface DehydratedRouter {\n state: DehydratedRouterState\n}\n\nexport type RouterConstructorOptions<\n TRouteTree extends AnyRoute,\n TDehydrated extends Record<string, any>,\n> = Omit<RouterOptions<TRouteTree, TDehydrated>, 'context'> &\n RouterContextOptions<TRouteTree>\n\nexport const componentTypes = [\n 'component',\n 'errorComponent',\n 'pendingComponent',\n] as const\n\nexport type RouterEvents = {\n onBeforeLoad: {\n type: 'onBeforeLoad'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n onLoad: {\n type: 'onLoad'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n onResolved: {\n type: 'onResolved'\n fromLocation: ParsedLocation\n toLocation: ParsedLocation\n pathChanged: boolean\n }\n}\n\nexport type RouterEvent = RouterEvents[keyof RouterEvents]\n\nexport type RouterListener<TRouterEvent extends RouterEvent> = {\n eventType: TRouterEvent['type']\n fn: ListenerFn<TRouterEvent>\n}\n\nexport class Router<\n TRouteTree extends AnyRoute = AnyRoute,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> {\n options: PickAsRequired<\n RouterOptions<TRouteTree, TDehydrated>,\n 'stringifySearch' | 'parseSearch' | 'context'\n >\n routeTree: TRouteTree\n // dehydratedData?: TDehydrated\n // resetNextScroll = false\n // tempLocationKey = `${Math.round(Math.random() * 10000000)}`\n\n constructor(options: RouterConstructorOptions<TRouteTree, TDehydrated>) {\n this.options = {\n defaultPreloadDelay: 50,\n context: undefined!,\n ...options,\n stringifySearch: options?.stringifySearch ?? defaultStringifySearch,\n parseSearch: options?.parseSearch ?? defaultParseSearch,\n }\n\n this.routeTree = this.options.routeTree as TRouteTree\n }\n\n subscribers = new Set<RouterListener<RouterEvent>>()\n\n subscribe = <TType extends keyof RouterEvents>(\n eventType: TType,\n fn: ListenerFn<RouterEvents[TType]>,\n ) => {\n const listener: RouterListener<any> = {\n eventType,\n fn,\n }\n\n this.subscribers.add(listener)\n\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n emit = (routerEvent: RouterEvent) => {\n this.subscribers.forEach((listener) => {\n if (listener.eventType === routerEvent.type) {\n listener.fn(routerEvent)\n }\n })\n }\n\n // dehydrate = (): DehydratedRouter => {\n // return {\n // state: {\n // dehydratedMatches: state.matches.map((d) =>\n // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),\n // ),\n // },\n // }\n // }\n\n // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {\n // let _ctx = __do_not_use_server_ctx\n // // Client hydrates from window\n // if (typeof document !== 'undefined') {\n // _ctx = window.__TSR_DEHYDRATED__\n // }\n\n // invariant(\n // _ctx,\n // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',\n // )\n\n // const ctx = _ctx\n // this.dehydratedData = ctx.payload as any\n // this.options.hydrate?.(ctx.payload as any)\n // const dehydratedState = ctx.router.state\n\n // let matches = this.matchRoutes(\n // state.location.pathname,\n // state.location.search,\n // ).map((match) => {\n // const dehydratedMatch = dehydratedState.dehydratedMatches.find(\n // (d) => d.id === match.id,\n // )\n\n // invariant(\n // dehydratedMatch,\n // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,\n // )\n\n // if (dehydratedMatch) {\n // return {\n // ...match,\n // ...dehydratedMatch,\n // }\n // }\n // return match\n // })\n\n // this.setState((s) => {\n // return {\n // ...s,\n // matches: dehydratedState.dehydratedMatches as any,\n // }\n // })\n // }\n\n // TODO:\n // injectedHtml: (string | (() => Promise<string> | string))[] = []\n\n // TODO:\n // injectHtml = async (html: string | (() => Promise<string> | string)) => {\n // this.injectedHtml.push(html)\n // }\n\n // TODO:\n // dehydrateData = <T>(key: any, getData: T | (() => Promise<T> | T)) => {\n // if (typeof document === 'undefined') {\n // const strKey = typeof key === 'string' ? key : JSON.stringify(key)\n\n // this.injectHtml(async () => {\n // const id = `__TSR_DEHYDRATED__${strKey}`\n // const data =\n // typeof getData === 'function' ? await (getData as any)() : getData\n // return `<script id='${id}' suppressHydrationWarning>window[\"__TSR_DEHYDRATED__${escapeJSON(\n // strKey,\n // )}\"] = ${JSON.stringify(data)}\n // ;(() => {\n // var el = document.getElementById('${id}')\n // el.parentElement.removeChild(el)\n // })()\n // </script>`\n // })\n\n // return () => this.hydrateData<T>(key)\n // }\n\n // return () => undefined\n // }\n\n // hydrateData = <T = unknown>(key: any) => {\n // if (typeof document !== 'undefined') {\n // const strKey = typeof key === 'string' ? key : JSON.stringify(key)\n\n // return window[`__TSR_DEHYDRATED__${strKey}` as any] as T\n // }\n\n // return undefined\n // }\n\n // resolveMatchPromise = (matchId: string, key: string, value: any) => {\n // state.matches\n // .find((d) => d.id === matchId)\n // ?.__promisesByKey[key]?.resolve(value)\n // }\n\n // setRouteMatch = (\n // id: string,\n // pending: boolean,\n // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,\n // ) => {\n // const key = pending ? 'pendingMatches' : 'matches'\n\n // this.setState((prev) => {\n // return {\n // ...prev,\n // [key]: prev[key].map((d) => {\n // if (d.id === id) {\n // return functionalUpdate(updater, d)\n // }\n\n // return d\n // }),\n // }\n // })\n // }\n\n // setPendingRouteMatch = (\n // id: string,\n // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,\n // ) => {\n // this.setRouteMatch(id, true, updater)\n // }\n}\n\nfunction 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\n// A function that takes an import() argument which is a function and returns a new function that will\n// proxy arguments from the caller to the imported function, retaining all type\n// information along the way\nexport function lazyFn<\n T extends Record<string, (...args: any[]) => any>,\n TKey extends keyof T = 'default',\n>(fn: () => Promise<T>, key?: TKey) {\n return async (...args: Parameters<T[TKey]>): Promise<ReturnType<T[TKey]>> => {\n const imported = await fn()\n return imported[key || 'default'](...args)\n }\n}\n"],"names":["componentTypes","Router","constructor","options","defaultPreloadDelay","context","undefined","stringifySearch","defaultStringifySearch","parseSearch","defaultParseSearch","routeTree","subscribers","Set","subscribe","eventType","fn","listener","add","delete","emit","routerEvent","forEach","type","lazyFn","key","args","imported"],"mappings":";;;;;;;;;;;;;;;;AAEA;;AAuBA;;AAoHO,MAAMA,cAAc,GAAG,CAC5B,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EACV;AA8BH,MAAMC,MAAM,CAGjB;AAMA;AACA;AACA;EAEAC,WAAWA,CAACC,OAA0D,EAAE;IACtE,IAAI,CAACA,OAAO,GAAG;AACbC,MAAAA,mBAAmB,EAAE,EAAE;AACvBC,MAAAA,OAAO,EAAEC,SAAU;AACnB,MAAA,GAAGH,OAAO;AACVI,MAAAA,eAAe,EAAEJ,OAAO,EAAEI,eAAe,IAAIC,mCAAsB;AACnEC,MAAAA,WAAW,EAAEN,OAAO,EAAEM,WAAW,IAAIC,+BAAAA;KACtC,CAAA;AAED,IAAA,IAAI,CAACC,SAAS,GAAG,IAAI,CAACR,OAAO,CAACQ,SAAuB,CAAA;AACvD,GAAA;AAEAC,EAAAA,WAAW,GAAG,IAAIC,GAAG,EAA+B,CAAA;AAEpDC,EAAAA,SAAS,GAAGA,CACVC,SAAgB,EAChBC,EAAmC,KAChC;AACH,IAAA,MAAMC,QAA6B,GAAG;MACpCF,SAAS;AACTC,MAAAA,EAAAA;KACD,CAAA;AAED,IAAA,IAAI,CAACJ,WAAW,CAACM,GAAG,CAACD,QAAQ,CAAC,CAAA;AAE9B,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACL,WAAW,CAACO,MAAM,CAACF,QAAQ,CAAC,CAAA;KAClC,CAAA;GACF,CAAA;EAEDG,IAAI,GAAIC,WAAwB,IAAK;AACnC,IAAA,IAAI,CAACT,WAAW,CAACU,OAAO,CAAEL,QAAQ,IAAK;AACrC,MAAA,IAAIA,QAAQ,CAACF,SAAS,KAAKM,WAAW,CAACE,IAAI,EAAE;AAC3CN,QAAAA,QAAQ,CAACD,EAAE,CAACK,WAAW,CAAC,CAAA;AAC1B,OAAA;AACF,KAAC,CAAC,CAAA;GACH,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACF,CAAA;;AASA;AACA;AACA;AACO,SAASG,MAAMA,CAGpBR,EAAoB,EAAES,GAAU,EAAE;EAClC,OAAO,OAAO,GAAGC,IAAyB,KAAmC;AAC3E,IAAA,MAAMC,QAAQ,GAAG,MAAMX,EAAE,EAAE,CAAA;IAC3B,OAAOW,QAAQ,CAACF,GAAG,IAAI,SAAS,CAAC,CAAC,GAAGC,IAAI,CAAC,CAAA;GAC3C,CAAA;AACH;;;;;;"}
|
package/build/esm/index.js
CHANGED
|
@@ -842,10 +842,12 @@ function RouterProvider({
|
|
|
842
842
|
const latestLocationRef = React.useRef(parseLocation());
|
|
843
843
|
const [preState, setState] = React.useState(() => getInitialRouterState(latestLocationRef.current));
|
|
844
844
|
const [isTransitioning, startReactTransition] = React.useTransition();
|
|
845
|
+
const pendingMatchesRef = React.useRef([]);
|
|
845
846
|
const state = React.useMemo(() => ({
|
|
846
847
|
...preState,
|
|
847
848
|
status: isTransitioning ? 'pending' : 'idle',
|
|
848
|
-
location: isTransitioning ? latestLocationRef.current : preState.location
|
|
849
|
+
location: isTransitioning ? latestLocationRef.current : preState.location,
|
|
850
|
+
pendingMatches: pendingMatchesRef.current
|
|
849
851
|
}), [preState, isTransitioning]);
|
|
850
852
|
React.useLayoutEffect(() => {
|
|
851
853
|
if (!isTransitioning && state.resolvedLocation !== state.location) {
|
|
@@ -855,6 +857,7 @@ function RouterProvider({
|
|
|
855
857
|
toLocation: state.location,
|
|
856
858
|
pathChanged: state.location.href !== state.resolvedLocation?.href
|
|
857
859
|
});
|
|
860
|
+
pendingMatchesRef.current = [];
|
|
858
861
|
setState(s => ({
|
|
859
862
|
...s,
|
|
860
863
|
resolvedLocation: s.location
|
|
@@ -1008,7 +1011,7 @@ function RouterProvider({
|
|
|
1008
1011
|
}
|
|
1009
1012
|
|
|
1010
1013
|
// Create a fresh route match
|
|
1011
|
-
const hasLoaders = !!(route.options.
|
|
1014
|
+
const hasLoaders = !!(route.options.loader || componentTypes.some(d => route.options[d]?.preload));
|
|
1012
1015
|
const routeMatch = {
|
|
1013
1016
|
id: matchId,
|
|
1014
1017
|
routeId: route.id,
|
|
@@ -1339,9 +1342,6 @@ function RouterProvider({
|
|
|
1339
1342
|
matchPromises.push((async () => {
|
|
1340
1343
|
const parentMatchPromise = matchPromises[index - 1];
|
|
1341
1344
|
const route = looseRoutesById[match.routeId];
|
|
1342
|
-
if (match.isFetching) {
|
|
1343
|
-
return getRouteMatch(state, match.id)?.loadPromise;
|
|
1344
|
-
}
|
|
1345
1345
|
const handleIfRedirect = err => {
|
|
1346
1346
|
if (isRedirect(err)) {
|
|
1347
1347
|
if (!preload) {
|
|
@@ -1351,73 +1351,100 @@ function RouterProvider({
|
|
|
1351
1351
|
}
|
|
1352
1352
|
return false;
|
|
1353
1353
|
};
|
|
1354
|
-
|
|
1355
|
-
|
|
1354
|
+
let loadPromise;
|
|
1355
|
+
matches[index] = match = {
|
|
1356
|
+
...match,
|
|
1357
|
+
fetchedAt: Date.now(),
|
|
1358
|
+
invalid: false
|
|
1359
|
+
};
|
|
1360
|
+
if (match.isFetching) {
|
|
1361
|
+
loadPromise = getRouteMatch(state, match.id)?.loadPromise;
|
|
1362
|
+
} else {
|
|
1363
|
+
const cause = state.matches.find(d => d.id === match.id) ? 'stay' : 'enter';
|
|
1364
|
+
const loaderContext = {
|
|
1365
|
+
params: match.params,
|
|
1366
|
+
search: match.search,
|
|
1367
|
+
preload: !!preload,
|
|
1368
|
+
parentMatchPromise,
|
|
1369
|
+
abortController: match.abortController,
|
|
1370
|
+
context: match.context,
|
|
1371
|
+
location: state.location,
|
|
1372
|
+
navigate: opts => navigate({
|
|
1373
|
+
...opts,
|
|
1374
|
+
from: match.pathname
|
|
1375
|
+
}),
|
|
1376
|
+
cause
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
// Default to reloading the route all the time
|
|
1380
|
+
const shouldReload = route.options.shouldReload?.(loaderContext) ?? true;
|
|
1381
|
+
|
|
1382
|
+
// If the user doesn't want the route to reload, just
|
|
1383
|
+
// resolve with the existing loader data
|
|
1384
|
+
|
|
1385
|
+
if (!shouldReload) {
|
|
1386
|
+
loadPromise = Promise.resolve(match.loaderData);
|
|
1387
|
+
} else {
|
|
1388
|
+
// Otherwise, load the route
|
|
1389
|
+
matches[index] = match = {
|
|
1390
|
+
...match,
|
|
1391
|
+
isFetching: true
|
|
1392
|
+
};
|
|
1356
1393
|
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
1357
1394
|
const component = route.options[type];
|
|
1358
1395
|
if (component?.preload) {
|
|
1359
1396
|
await component.preload();
|
|
1360
1397
|
}
|
|
1361
1398
|
}));
|
|
1362
|
-
const loaderPromise = route.options.
|
|
1363
|
-
|
|
1364
|
-
search: match.search,
|
|
1365
|
-
preload: !!preload,
|
|
1366
|
-
parentMatchPromise,
|
|
1367
|
-
abortController: match.abortController,
|
|
1368
|
-
context: match.context,
|
|
1369
|
-
location: state.location,
|
|
1370
|
-
navigate: opts => navigate({
|
|
1371
|
-
...opts,
|
|
1372
|
-
from: match.pathname
|
|
1373
|
-
})
|
|
1374
|
-
});
|
|
1375
|
-
const [_, loaderContext] = await Promise.all([componentsPromise, loaderPromise]);
|
|
1376
|
-
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1377
|
-
matches[index] = match = {
|
|
1378
|
-
...match,
|
|
1379
|
-
error: undefined,
|
|
1380
|
-
status: 'success',
|
|
1381
|
-
isFetching: false,
|
|
1382
|
-
updatedAt: Date.now()
|
|
1383
|
-
};
|
|
1384
|
-
} catch (error) {
|
|
1385
|
-
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1386
|
-
if (handleIfRedirect(error)) return;
|
|
1387
|
-
try {
|
|
1388
|
-
route.options.onError?.(error);
|
|
1389
|
-
} catch (onErrorError) {
|
|
1390
|
-
error = onErrorError;
|
|
1391
|
-
if (handleIfRedirect(onErrorError)) return;
|
|
1392
|
-
}
|
|
1393
|
-
matches[index] = match = {
|
|
1394
|
-
...match,
|
|
1395
|
-
error,
|
|
1396
|
-
status: 'error',
|
|
1397
|
-
isFetching: false,
|
|
1398
|
-
updatedAt: Date.now()
|
|
1399
|
-
};
|
|
1400
|
-
}
|
|
1401
|
-
if (!preload) {
|
|
1402
|
-
setState(s => ({
|
|
1403
|
-
...s,
|
|
1404
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1405
|
-
}));
|
|
1399
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
1400
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
1406
1401
|
}
|
|
1407
|
-
}
|
|
1408
|
-
let loadPromise;
|
|
1409
|
-
matches[index] = match = {
|
|
1410
|
-
...match,
|
|
1411
|
-
isFetching: true,
|
|
1412
|
-
fetchedAt: Date.now(),
|
|
1413
|
-
invalid: false
|
|
1414
|
-
};
|
|
1415
|
-
loadPromise = load();
|
|
1402
|
+
}
|
|
1416
1403
|
matches[index] = match = {
|
|
1417
1404
|
...match,
|
|
1418
1405
|
loadPromise
|
|
1419
1406
|
};
|
|
1420
|
-
|
|
1407
|
+
if (!preload) {
|
|
1408
|
+
setState(s => ({
|
|
1409
|
+
...s,
|
|
1410
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1411
|
+
}));
|
|
1412
|
+
}
|
|
1413
|
+
try {
|
|
1414
|
+
const loaderData = await loadPromise;
|
|
1415
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1416
|
+
matches[index] = match = {
|
|
1417
|
+
...match,
|
|
1418
|
+
error: undefined,
|
|
1419
|
+
status: 'success',
|
|
1420
|
+
isFetching: false,
|
|
1421
|
+
updatedAt: Date.now(),
|
|
1422
|
+
loaderData,
|
|
1423
|
+
loadPromise: undefined
|
|
1424
|
+
};
|
|
1425
|
+
} catch (error) {
|
|
1426
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1427
|
+
if (handleIfRedirect(error)) return;
|
|
1428
|
+
try {
|
|
1429
|
+
route.options.onError?.(error);
|
|
1430
|
+
} catch (onErrorError) {
|
|
1431
|
+
error = onErrorError;
|
|
1432
|
+
if (handleIfRedirect(onErrorError)) return;
|
|
1433
|
+
}
|
|
1434
|
+
matches[index] = match = {
|
|
1435
|
+
...match,
|
|
1436
|
+
error,
|
|
1437
|
+
status: 'error',
|
|
1438
|
+
isFetching: false,
|
|
1439
|
+
updatedAt: Date.now()
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
if (!preload) {
|
|
1443
|
+
setState(s => ({
|
|
1444
|
+
...s,
|
|
1445
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1446
|
+
}));
|
|
1447
|
+
}
|
|
1421
1448
|
})());
|
|
1422
1449
|
});
|
|
1423
1450
|
await Promise.all(matchPromises);
|
|
@@ -1443,6 +1470,7 @@ function RouterProvider({
|
|
|
1443
1470
|
let matches = matchRoutes(next.pathname, next.search, {
|
|
1444
1471
|
debug: true
|
|
1445
1472
|
});
|
|
1473
|
+
pendingMatchesRef.current = matches;
|
|
1446
1474
|
const previousMatches = state.matches;
|
|
1447
1475
|
|
|
1448
1476
|
// Ingest the new matches
|
|
@@ -1468,9 +1496,9 @@ function RouterProvider({
|
|
|
1468
1496
|
if (latestPromise = checkLatest(promise)) {
|
|
1469
1497
|
return latestPromise;
|
|
1470
1498
|
}
|
|
1471
|
-
const exitingMatchIds = previousMatches.filter(id => !
|
|
1472
|
-
const enteringMatchIds =
|
|
1473
|
-
const stayingMatchIds = previousMatches.filter(id =>
|
|
1499
|
+
const exitingMatchIds = previousMatches.filter(id => !pendingMatchesRef.current.includes(id));
|
|
1500
|
+
const enteringMatchIds = pendingMatchesRef.current.filter(id => !previousMatches.includes(id));
|
|
1501
|
+
const stayingMatchIds = previousMatches.filter(id => pendingMatchesRef.current.includes(id))
|
|
1474
1502
|
|
|
1475
1503
|
// setState((s) => ({
|
|
1476
1504
|
// ...s,
|
|
@@ -1650,9 +1678,7 @@ function RouterProvider({
|
|
|
1650
1678
|
unsub();
|
|
1651
1679
|
};
|
|
1652
1680
|
}, [history]);
|
|
1653
|
-
|
|
1654
|
-
if (initialLoad.current) {
|
|
1655
|
-
initialLoad.current = false;
|
|
1681
|
+
React.useLayoutEffect(() => {
|
|
1656
1682
|
startReactTransition(() => {
|
|
1657
1683
|
try {
|
|
1658
1684
|
load();
|
|
@@ -1660,7 +1686,7 @@ function RouterProvider({
|
|
|
1660
1686
|
console.error(err);
|
|
1661
1687
|
}
|
|
1662
1688
|
});
|
|
1663
|
-
}
|
|
1689
|
+
}, []);
|
|
1664
1690
|
const matchRoute = useStableCallback((location, opts) => {
|
|
1665
1691
|
location = {
|
|
1666
1692
|
...location,
|
|
@@ -1756,6 +1782,9 @@ function Matches() {
|
|
|
1756
1782
|
}) : null));
|
|
1757
1783
|
}
|
|
1758
1784
|
const defaultPending = () => null;
|
|
1785
|
+
function SafeFragment(props) {
|
|
1786
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
1787
|
+
}
|
|
1759
1788
|
function Match({
|
|
1760
1789
|
matches
|
|
1761
1790
|
}) {
|
|
@@ -1769,9 +1798,7 @@ function Match({
|
|
|
1769
1798
|
const locationKey = useRouterState().location.state?.key;
|
|
1770
1799
|
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent ?? defaultPending;
|
|
1771
1800
|
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
1772
|
-
const ResolvedSuspenseBoundary = route.options.wrapInSuspense
|
|
1773
|
-
// const ResolvedSuspenseBoundary = SafeFragment
|
|
1774
|
-
|
|
1801
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ? React.Suspense : SafeFragment;
|
|
1775
1802
|
const errorComponent = React.useCallback(props => {
|
|
1776
1803
|
return /*#__PURE__*/React.createElement(routeErrorComponent, {
|
|
1777
1804
|
...props,
|
|
@@ -1821,7 +1848,8 @@ function MatchInner({
|
|
|
1821
1848
|
useMatch: route.useMatch,
|
|
1822
1849
|
useRouteContext: route.useRouteContext,
|
|
1823
1850
|
useSearch: route.useSearch,
|
|
1824
|
-
useParams: route.useParams
|
|
1851
|
+
useParams: route.useParams,
|
|
1852
|
+
useLoaderData: route.useLoaderData
|
|
1825
1853
|
});
|
|
1826
1854
|
}
|
|
1827
1855
|
return /*#__PURE__*/React.createElement(Outlet, null);
|
|
@@ -1892,6 +1920,13 @@ function useMatches(opts) {
|
|
|
1892
1920
|
}
|
|
1893
1921
|
});
|
|
1894
1922
|
}
|
|
1923
|
+
function useLoaderData(opts) {
|
|
1924
|
+
const match = useMatch({
|
|
1925
|
+
...opts,
|
|
1926
|
+
select: undefined
|
|
1927
|
+
});
|
|
1928
|
+
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
1929
|
+
}
|
|
1895
1930
|
|
|
1896
1931
|
function useParams(opts) {
|
|
1897
1932
|
return useRouterState({
|
|
@@ -1997,6 +2032,12 @@ class Route {
|
|
|
1997
2032
|
from: this.id
|
|
1998
2033
|
});
|
|
1999
2034
|
};
|
|
2035
|
+
useLoaderData = opts => {
|
|
2036
|
+
return useLoaderData({
|
|
2037
|
+
...opts,
|
|
2038
|
+
from: this.id
|
|
2039
|
+
});
|
|
2040
|
+
};
|
|
2000
2041
|
}
|
|
2001
2042
|
function rootRouteWithContext() {
|
|
2002
2043
|
return options => {
|
|
@@ -2371,5 +2412,5 @@ function Navigate(props) {
|
|
|
2371
2412
|
return null;
|
|
2372
2413
|
}
|
|
2373
2414
|
|
|
2374
|
-
export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useBlocker, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2415
|
+
export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useBlocker, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2375
2416
|
//# sourceMappingURL=index.js.map
|