@tanstack/react-router 1.48.4 → 1.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Matches.cjs +3 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +5 -4
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +4 -5
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +3 -1
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +1 -1
- package/dist/cjs/path.cjs +6 -9
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/route.cjs +1 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +80 -61
- package/dist/cjs/router.cjs +90 -57
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +22 -9
- package/dist/cjs/transformer.cjs +39 -0
- package/dist/cjs/transformer.cjs.map +1 -0
- package/dist/cjs/transformer.d.cts +5 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/Matches.d.ts +5 -4
- package/dist/esm/Matches.js +3 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/fileRoute.d.ts +4 -5
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/link.d.ts +1 -1
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.js +6 -9
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/route.d.ts +80 -61
- package/dist/esm/route.js +1 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +22 -9
- package/dist/esm/router.js +91 -58
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/transformer.d.ts +5 -0
- package/dist/esm/transformer.js +39 -0
- package/dist/esm/transformer.js.map +1 -0
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +11 -7
- package/src/fileRoute.ts +28 -22
- package/src/index.tsx +5 -1
- package/src/link.tsx +10 -6
- package/src/path.ts +7 -10
- package/src/route.ts +375 -190
- package/src/router.ts +144 -75
- package/src/transformer.ts +49 -0
- package/src/utils.ts +5 -0
package/dist/esm/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../src/link.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { flushSync } from 'react-dom'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport {\n deepEqual,\n functionalUpdate,\n useForwardedRef,\n useIntersectionObserver,\n} from './utils'\nimport { exactPathTest, removeTrailingSlash } from './path'\nimport type { AnyRouter, ParsedLocation } from '.'\nimport type { HistoryState } from '@tanstack/history'\nimport type {\n AllParams,\n CatchAllPaths,\n FullSearchSchema,\n FullSearchSchemaInput,\n RouteByPath,\n RouteByToPath,\n RoutePaths,\n RouteToPath,\n} from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type {\n Expand,\n MakeDifferenceOptional,\n NoInfer,\n NonNullableUpdater,\n PickRequired,\n Updater,\n WithoutEmpty,\n} from './utils'\n\nexport type CleanPath<T extends string> = T extends `${infer L}//${infer R}`\n ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>\n : T extends `${infer L}//`\n ? `${CleanPath<L>}/`\n : T extends `//${infer L}`\n ? `/${CleanPath<L>}`\n : T\n\nexport type Split<TValue, TIncludeTrailingSlash = true> = TValue extends unknown\n ? string extends TValue\n ? Array<string>\n : TValue extends string\n ? CleanPath<TValue> extends ''\n ? []\n : TIncludeTrailingSlash extends true\n ? CleanPath<TValue> extends `${infer T}/`\n ? [...Split<T>, '/']\n : CleanPath<TValue> extends `/${infer U}`\n ? Split<U>\n : CleanPath<TValue> extends `${infer T}/${infer U}`\n ? [...Split<T>, ...Split<U>]\n : [TValue]\n : CleanPath<TValue> extends `${infer T}/${infer U}`\n ? [...Split<T>, ...Split<U>]\n : TValue extends string\n ? [TValue]\n : never\n : never\n : never\n\nexport type ParsePathParams<\n T extends string,\n TAcc = never,\n> = T extends `${string}$${infer TPossiblyParam}`\n ? TPossiblyParam extends `${infer TParam}/${infer TRest}`\n ? ParsePathParams<TRest, TParam extends '' ? '_splat' : TParam | TAcc>\n : TPossiblyParam extends ''\n ? '_splat'\n : TPossiblyParam | TAcc\n : TAcc\n\nexport type Join<T, TDelimiter extends string = '/'> = T extends []\n ? ''\n : T extends [infer L extends string]\n ? L\n : T extends [\n infer L extends string,\n ...infer Tail extends [...Array<string>],\n ]\n ? CleanPath<`${L}${TDelimiter}${Join<Tail>}`>\n : never\n\nexport type Last<T extends Array<any>> = T extends [...infer _, infer L]\n ? L\n : never\n\nexport type RemoveTrailingSlashes<T> = T extends `${infer R}/` ? R : T\n\nexport type RemoveLeadingSlashes<T> = T extends `/${infer R}` ? R : T\n\nexport type ResolvePaths<TRouter extends AnyRouter, TSearchPath> =\n RouteByPath<\n TRouter['routeTree'],\n RemoveTrailingSlashes<TSearchPath>\n > extends never\n ? RouteToPath<TRouter, TRouter['routeTree']>\n : RouteToPath<\n TRouter,\n RouteByPath<TRouter['routeTree'], RemoveTrailingSlashes<TSearchPath>>\n >\n\nexport type SearchPaths<\n TRouter extends AnyRouter,\n TSearchPath extends string,\n TPaths = ResolvePaths<TRouter, TSearchPath>,\n> = TPaths extends `${RemoveTrailingSlashes<TSearchPath>}${infer TRest}`\n ? TRest\n : never\n\nexport type SearchRelativePathAutoComplete<\n TRouter extends AnyRouter,\n TTo extends string,\n TSearchPath extends string,\n> = `${TTo}/${RemoveLeadingSlashes<SearchPaths<TRouter, TSearchPath>>}`\n\nexport type RelativeToParentPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = RemoveTrailingSlashes<\n ResolveRelativePath<TFrom, TTo>\n >,\n> =\n | SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>\n | (TResolvedPath extends '' ? never : `${TTo}/../`)\n\nexport type RelativeToCurrentPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TRestTo extends string,\n TResolvedPath extends\n string = RemoveTrailingSlashes<`${RemoveTrailingSlashes<TFrom>}/${RemoveLeadingSlashes<TRestTo>}`>,\n> = SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>\n\nexport type AbsolutePathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n> =\n | (string extends TFrom\n ? './'\n : TFrom extends `/`\n ? never\n : SearchPaths<TRouter, TFrom> extends ''\n ? never\n : './')\n | (string extends TFrom ? '../' : TFrom extends `/` ? never : '../')\n | RouteToPath<TRouter, TRouter['routeTree']>\n | (TFrom extends '/'\n ? never\n : string extends TFrom\n ? never\n : RemoveLeadingSlashes<SearchPaths<TRouter, TFrom>>)\n\nexport type RelativeToPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n> = TTo extends `..${string}`\n ? RelativeToParentPathAutoComplete<TRouter, TFrom, RemoveTrailingSlashes<TTo>>\n : TTo extends `./${infer TRestTTo}`\n ? RelativeToCurrentPathAutoComplete<\n TRouter,\n TFrom,\n RemoveTrailingSlashes<TTo>,\n TRestTTo\n >\n : AbsolutePathAutoComplete<TRouter, TFrom>\n\nexport type NavigateOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & NavigateOptionProps\n\nexport interface NavigateOptionProps {\n // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.\n replace?: boolean\n resetScroll?: boolean\n /** @deprecated All navigations now use startTransition under the hood */\n startTransition?: boolean\n // if set to `true`, the router will wrap the resulting navigation in a document.startViewTransition() call.\n viewTransition?: boolean\n ignoreBlocker?: boolean\n}\n\nexport type ToOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ToSubOptions<TRouter, TFrom, TTo> & MaskOptions<TRouter, TMaskFrom, TMaskTo>\n\nexport interface MaskOptions<\n in out TRouter extends AnyRouter,\n in out TMaskFrom extends RoutePaths<TRouter['routeTree']> | string,\n in out TMaskTo extends string,\n> {\n _fromLocation?: ParsedLocation\n mask?: ToMaskOptions<TRouter, TMaskFrom, TMaskTo>\n}\n\nexport type ToMaskOptions<\n TRouteTree extends AnyRouter = RegisteredRouter,\n TMaskFrom extends RoutePaths<TRouteTree['routeTree']> | string = string,\n TMaskTo extends string = '',\n> = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {\n unmaskOnReload?: boolean\n}\n\nexport type ToSubOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n SearchParamOptions<TRouter, TFrom, TTo> &\n PathParamOptions<TRouter, TFrom, TTo>\n\nexport interface ToSubOptionsProps<\n in out TRouter extends AnyRouter = RegisteredRouter,\n in out TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n in out TTo extends string = '',\n> {\n to?: ToPathOption<TRouter, TFrom, TTo> & {}\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<HistoryState>\n // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required\n from?: FromPathOption<TRouter, TFrom> & {}\n}\n\nexport type ParamsReducerFn<\n in out TRouter extends AnyRouter,\n in out TParamVariant extends ParamVariant,\n in out TFrom,\n in out TTo,\n> = (\n current: Expand<ResolveFromParams<TRouter, TParamVariant, TFrom>>,\n) => Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n\ntype ParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n | (ParamsReducerFn<TRouter, TParamVariant, TFrom, TTo> & {})\n\ntype ParamVariant = 'PATH' | 'SEARCH'\n\nexport type ResolveRoute<\n TRouter extends AnyRouter,\n TFrom,\n TTo,\n TPath = ResolveRelativePath<TFrom, TTo>,\n> = TPath extends string\n ? TFrom extends TPath\n ? RouteByPath<TRouter['routeTree'], TPath>\n : RouteByToPath<TRouter, TPath>\n : never\n\ntype ResolveFromParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchema'\n\ntype ResolveFromAllParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchema<TRouter['routeTree']>\n\ntype ResolveFromParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n> = string extends TFrom\n ? ResolveFromAllParams<TRouter, TParamVariant>\n : RouteByPath<\n TRouter['routeTree'],\n TFrom\n >['types'][ResolveFromParamType<TParamVariant>]\n\ntype ResolveToParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchemaInput'\n\ntype ResolveAllToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchemaInput<TRouter['routeTree']>\n\nexport type ResolveToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? string extends TPath\n ? ResolveAllToParams<TRouter, TParamVariant>\n : TPath extends CatchAllPaths\n ? ResolveAllToParams<TRouter, TParamVariant>\n : ResolveRoute<\n TRouter,\n TFrom,\n TTo\n >['types'][ResolveToParamType<TParamVariant>]\n : never\n\ntype ResolveRelativeToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n TToParams = ResolveToParams<TRouter, TParamVariant, TFrom, TTo>,\n> = TParamVariant extends 'SEARCH'\n ? TToParams\n : string extends TFrom\n ? TToParams\n : MakeDifferenceOptional<\n ResolveFromParams<TRouter, TParamVariant, TFrom>,\n TToParams\n >\n\ninterface MakeOptionalSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search?: true | (ParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {})\n}\n\ninterface MakeOptionalPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params?: true | (ParamsReducer<TRouter, 'PATH', TFrom, TTo> & {})\n}\n\ntype MakeRequiredParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | (string extends TFrom\n ? never\n : ResolveFromParams<TRouter, TParamVariant, TFrom> extends WithoutEmpty<\n PickRequired<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n >\n ? true\n : never)\n | (ParamsReducer<TRouter, TParamVariant, TFrom, TTo> & {})\n\nexport interface MakeRequiredPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params: MakeRequiredParamsReducer<TRouter, 'PATH', TFrom, TTo> & {}\n}\n\nexport interface MakeRequiredSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search: MakeRequiredParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {}\n}\n\nexport type IsRequiredParams<TParams> =\n Record<never, never> extends TParams ? never : true\n\nexport type IsRequired<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? string extends TPath\n ? never\n : TPath extends CatchAllPaths\n ? never\n : IsRequiredParams<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n : never\n\nexport type SearchParamOptions<\n TRouter extends AnyRouter,\n TFrom,\n TTo extends string,\n> =\n IsRequired<TRouter, 'SEARCH', TFrom, TTo> extends never\n ? MakeOptionalSearchParams<TRouter, TFrom, TTo>\n : MakeRequiredSearchParams<TRouter, TFrom, TTo>\n\nexport type PathParamOptions<\n TRouter extends AnyRouter,\n TFrom,\n TTo extends string,\n> =\n IsRequired<TRouter, 'PATH', TFrom, TTo> extends never\n ? MakeOptionalPathParams<TRouter, TFrom, TTo>\n : MakeRequiredPathParams<TRouter, TFrom, TTo>\n\nexport type ToPathOption<\n TRouter extends AnyRouter = AnyRouter,\n TFrom extends string = string,\n TTo extends string = string,\n> =\n | CheckPath<TRouter, TTo, never, TFrom, TTo>\n | RelativeToPathAutoComplete<\n TRouter,\n NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',\n NoInfer<TTo> & string\n >\n\nexport type CheckFromPath<\n TRouter extends AnyRouter,\n TPass,\n TFail,\n TFrom,\n> = string extends TFrom\n ? TPass\n : RouteByPath<TRouter['routeTree'], TFrom> extends never\n ? TFail\n : TPass\n\nexport type FromPathOption<TRouter extends AnyRouter, TFrom> =\n | CheckFromPath<\n TRouter,\n string extends TFrom ? TFrom & {} : TFrom,\n never,\n TFrom\n >\n | RoutePaths<TRouter['routeTree']>\n\nexport interface ActiveOptions {\n exact?: boolean\n includeHash?: boolean\n includeSearch?: boolean\n}\n\nexport type LinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & LinkOptionsProps\n\nexport interface LinkOptionsProps {\n /**\n * The standard anchor tag target attribute\n */\n target?: HTMLAnchorElement['target']\n /**\n * Configurable options to determine if the link should be considered active or not\n * @default {exact:true,includeHash:true}\n */\n activeOptions?: ActiveOptions\n /**\n * The preloading strategy for this link\n * - `false` - No preloading\n * - `'intent'` - Preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.\n * - `'viewport'` - Preload the linked route when it enters the viewport\n */\n preload?: false | 'intent' | 'viewport'\n /**\n * When a preload strategy is set, this delays the preload by this many milliseconds.\n * If the user exits the link before this delay, the preload will be cancelled.\n */\n preloadDelay?: number\n /**\n * Control whether the link should be disabled or not\n * If set to `true`, the link will be rendered without an `href` attribute\n * @default false\n */\n disabled?: boolean\n}\n\nexport type CheckPath<TRouter extends AnyRouter, TPass, TFail, TFrom, TTo> =\n string extends ResolveRelativePath<TFrom, TTo>\n ? TPass\n : ResolveRelativePath<TFrom, TTo> extends CatchAllPaths\n ? TPass\n : ResolveRoute<TRouter, TFrom, TTo> extends never\n ? TFail\n : TPass\n\nexport type ResolveRelativePath<TFrom, TTo = '.'> = string extends TFrom\n ? TTo\n : string extends TTo\n ? TFrom\n : TFrom extends string\n ? TTo extends string\n ? TTo extends '.'\n ? TFrom\n : TTo extends `./`\n ? Join<[TFrom, '/']>\n : TTo extends `./${infer TRest}`\n ? ResolveRelativePath<TFrom, TRest>\n : TTo extends `/${infer TRest}`\n ? TTo\n : Split<TTo> extends ['..', ...infer ToRest]\n ? Split<TFrom> extends [...infer FromRest, infer FromTail]\n ? ToRest extends ['/']\n ? Join<['/', ...FromRest, '/']>\n : ResolveRelativePath<Join<FromRest>, Join<ToRest>>\n : never\n : Split<TTo> extends ['.', ...infer ToRest]\n ? ToRest extends ['/']\n ? Join<[TFrom, '/']>\n : ResolveRelativePath<TFrom, Join<ToRest>>\n : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>\n : never\n : never\n\n// type Test1 = ResolveRelativePath<'/', '/posts'>\n// // ^?\n// type Test4 = ResolveRelativePath<'/posts/1/comments', '../..'>\n// // ^?\n// type Test5 = ResolveRelativePath<'/posts/1/comments', '../../..'>\n// // ^?\n// type Test6 = ResolveRelativePath<'/posts/1/comments', './1'>\n// // ^?\n// type Test7 = ResolveRelativePath<'/posts/1/comments', './1/2'>\n// // ^?\n// type Test8 = ResolveRelativePath<'/posts/1/comments', '../edit'>\n// // ^?\n// type Test9 = ResolveRelativePath<'/posts/1/comments', '1'>\n// // ^?\n// type Test10 = ResolveRelativePath<'/posts/1/comments', './1'>\n// // ^?\n// type Test11 = ResolveRelativePath<'/posts/1/comments', './1/2'>\n// // ^?\n\ntype LinkCurrentTargetElement = {\n preloadTimeout?: null | ReturnType<typeof setTimeout>\n}\n\nconst preloadWarning = 'Error preloading route! ☝️'\n\nexport function useLinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n forwardedRef?: React.ForwardedRef<Element>,\n): React.ComponentPropsWithRef<'a'> {\n const router = useRouter()\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n const innerRef = useForwardedRef(forwardedRef)\n\n const {\n // custom props\n activeProps = () => ({ className: 'active' }),\n inactiveProps = () => ({}),\n activeOptions,\n hash,\n search,\n params,\n to,\n state,\n mask,\n preload: userPreload,\n preloadDelay: userPreloadDelay,\n replace,\n startTransition,\n resetScroll,\n viewTransition,\n // element props\n children,\n target,\n disabled,\n style,\n className,\n onClick,\n onFocus,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n ignoreBlocker,\n ...rest\n } = options\n\n // If this link simply reloads the current route,\n // make sure it has a new key so it will trigger a data refresh\n\n // If this `to` is a valid external URL, return\n // null for LinkUtils\n\n const type: 'internal' | 'external' = React.useMemo(() => {\n try {\n new URL(`${to}`)\n return 'external'\n } catch {}\n return 'internal'\n }, [to])\n\n const next = React.useMemo(\n () => router.buildLocation(options as any),\n [router, options],\n )\n const preload = React.useMemo(\n () => userPreload ?? router.options.defaultPreload,\n [router.options.defaultPreload, userPreload],\n )\n const preloadDelay =\n userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0\n\n const isActive = useRouterState({\n select: (s) => {\n // Compare path/hash for matches\n const currentPathSplit = removeTrailingSlash(\n s.location.pathname,\n router.basepath,\n ).split('/')\n const nextPathSplit = removeTrailingSlash(\n next.pathname,\n router.basepath,\n ).split('/')\n const pathIsFuzzyEqual = nextPathSplit.every(\n (d, i) => d === currentPathSplit[i],\n )\n // Combine the matches based on user router.options\n const pathTest = activeOptions?.exact\n ? exactPathTest(s.location.pathname, next.pathname, router.basepath)\n : pathIsFuzzyEqual\n const hashTest = activeOptions?.includeHash\n ? s.location.hash === next.hash\n : true\n const searchTest =\n (activeOptions?.includeSearch ?? true)\n ? deepEqual(s.location.search, next.search, !activeOptions?.exact)\n : true\n\n // The final \"active\" test\n return pathTest && hashTest && searchTest\n },\n })\n\n const doPreload = React.useCallback(() => {\n router.preloadRoute(options as any).catch((err) => {\n console.warn(err)\n console.warn(preloadWarning)\n })\n }, [options, router])\n\n const preloadViewportIoCallback = React.useCallback(\n (entry: IntersectionObserverEntry | undefined) => {\n if (entry?.isIntersecting) {\n doPreload()\n }\n },\n [doPreload],\n )\n\n useIntersectionObserver(\n innerRef,\n preloadViewportIoCallback,\n { rootMargin: '100px' },\n { disabled: !!disabled || preload !== 'viewport' },\n )\n\n if (type === 'external') {\n return {\n ...rest,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n type,\n href: to,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n ...(onClick && { onClick }),\n ...(onFocus && { onFocus }),\n ...(onMouseEnter && { onMouseEnter }),\n ...(onMouseLeave && { onMouseLeave }),\n ...(onTouchStart && { onTouchStart }),\n }\n }\n\n // The click handler\n const handleClick = (e: MouseEvent) => {\n if (\n !disabled &&\n !isCtrlEvent(e) &&\n !e.defaultPrevented &&\n (!target || target === '_self') &&\n e.button === 0\n ) {\n e.preventDefault()\n\n flushSync(() => {\n setIsTransitioning(true)\n })\n\n const unsub = router.subscribe('onResolved', () => {\n unsub()\n setIsTransitioning(false)\n })\n\n // All is well? Navigate!\n router.commitLocation({\n ...next,\n replace,\n resetScroll,\n startTransition,\n viewTransition,\n ignoreBlocker,\n })\n }\n }\n\n // The click handler\n const handleFocus = (_: MouseEvent) => {\n if (disabled) return\n if (preload) {\n doPreload()\n }\n }\n\n const handleTouchStart = handleFocus\n\n const handleEnter = (e: MouseEvent) => {\n if (disabled) return\n const eventTarget = (e.target || {}) as LinkCurrentTargetElement\n\n if (preload) {\n if (eventTarget.preloadTimeout) {\n return\n }\n\n eventTarget.preloadTimeout = setTimeout(() => {\n eventTarget.preloadTimeout = null\n doPreload()\n }, preloadDelay)\n }\n }\n\n const handleLeave = (e: MouseEvent) => {\n if (disabled) return\n const eventTarget = (e.target || {}) as LinkCurrentTargetElement\n\n if (eventTarget.preloadTimeout) {\n clearTimeout(eventTarget.preloadTimeout)\n eventTarget.preloadTimeout = null\n }\n }\n\n const composeHandlers =\n (handlers: Array<undefined | ((e: any) => void)>) =>\n (e: { persist?: () => void; defaultPrevented: boolean }) => {\n e.persist?.()\n handlers.filter(Boolean).forEach((handler) => {\n if (e.defaultPrevented) return\n handler!(e)\n })\n }\n\n // Get the active props\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive\n ? (functionalUpdate(activeProps as any, {}) ?? {})\n : {}\n\n // Get the inactive props\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive ? {} : functionalUpdate(inactiveProps, {})\n\n const resolvedClassName = [\n className,\n resolvedActiveProps.className,\n resolvedInactiveProps.className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const resolvedStyle = {\n ...style,\n ...resolvedActiveProps.style,\n ...resolvedInactiveProps.style,\n }\n\n return {\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n ...rest,\n href: disabled\n ? undefined\n : next.maskedLocation\n ? router.history.createHref(next.maskedLocation.href)\n : router.history.createHref(next.href),\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n onClick: composeHandlers([onClick, handleClick]),\n onFocus: composeHandlers([onFocus, handleFocus]),\n onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),\n onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),\n onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),\n disabled: !!disabled,\n target,\n ...(Object.keys(resolvedStyle).length && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && {\n role: 'link',\n 'aria-disabled': true,\n }),\n ...(isActive && { 'data-status': 'active', 'aria-current': 'page' }),\n ...(isTransitioning && { 'data-transitioning': 'transitioning' }),\n }\n}\n\nexport type UseLinkPropsOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ActiveLinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n React.AnchorHTMLAttributes<HTMLAnchorElement>\n\nexport type ActiveLinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & ActiveLinkOptionProps\n\ntype ActiveLinkAnchorProps = Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement> & {\n [key: `data-${string}`]: unknown\n },\n 'children'\n>\n\nexport interface ActiveLinkOptionProps {\n /**\n * A function that returns additional props for the `active` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n activeProps?: ActiveLinkAnchorProps | (() => ActiveLinkAnchorProps)\n /**\n * A function that returns additional props for the `inactive` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n inactiveProps?: ActiveLinkAnchorProps | (() => ActiveLinkAnchorProps)\n}\n\nexport type LinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = ActiveLinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n LinkPropsChildren\n\nexport interface LinkPropsChildren {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | React.ReactNode\n | ((state: {\n isActive: boolean\n isTransitioning: boolean\n }) => React.ReactNode)\n}\n\ntype LinkComponentReactProps<TComp> = React.PropsWithoutRef<\n TComp extends React.FC<infer TProps> | React.Component<infer TProps>\n ? TProps\n : TComp extends keyof React.JSX.IntrinsicElements\n ? Omit<React.HTMLProps<TComp>, 'children' | 'preload'>\n : never\n> &\n React.RefAttributes<\n TComp extends\n | React.FC<{ ref: infer TRef }>\n | React.Component<{ ref: infer TRef }>\n ? TRef\n : TComp extends keyof React.JSX.IntrinsicElements\n ? React.ComponentRef<TComp>\n : never\n >\n\nexport type LinkComponentProps<\n TComp,\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = LinkComponentReactProps<TComp> &\n LinkProps<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type LinkComponent<TComp> = <\n TRouter extends RegisteredRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n>(\n props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => React.ReactElement\n\nexport function createLink<const TComp>(Comp: TComp): LinkComponent<TComp> {\n return React.forwardRef(function CreatedLink(props, ref) {\n return <Link {...(props as any)} _asChild={Comp} ref={ref} />\n }) as any\n}\n\nexport const Link: LinkComponent<'a'> = React.forwardRef<Element, any>(\n (props, ref) => {\n const { _asChild, ...rest } = props\n const { type, ref: innerRef, ...linkProps } = useLinkProps(rest, ref)\n\n const children =\n typeof rest.children === 'function'\n ? rest.children({\n isActive: (linkProps as any)['data-status'] === 'active',\n })\n : rest.children\n\n if (typeof _asChild === 'undefined') {\n // the ReturnType of useLinkProps returns the correct type for a <a> element, not a general component that has a delete prop\n // @ts-expect-error\n delete linkProps.disabled\n }\n\n return React.createElement(\n _asChild ? _asChild : 'a',\n {\n ...linkProps,\n ref: innerRef,\n },\n children,\n )\n },\n) as any\n\nfunction isCtrlEvent(e: MouseEvent) {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n}\n"],"names":[],"mappings":";;;;;;;;AA4iBA;AAEgB;AAUd;AACA;AACM;AAEA;AAAA;AAAA;;AAGmB;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACS;AACK;AACd;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AASC;AACA;AACE;AACG;AAAA;AACD;AACD;AAAA;AAGT;AAAmB;AACwB;AACzB;AAElB;AAAsB;AACgB;AACO;AAE7C;AAGA;AAAgC;AAG5B;AAAyB;AACZ;AACJ;AAET;AAAsB;AACf;AACE;AAET;AAAuC;AACH;AAG9B;AAGN;AAGA;AAMA;AAA+B;AACjC;AAGI;AACJ;AACE;AACA;AAA2B;AAC5B;AAGH;AAAwC;AAEpC;AACY;;AACZ;AACF;AACU;AAGZ;AAAA;AACE;AACA;AACsB;AAC2B;AAGnD;AACS;AAAA;AACF;AACE;AACL;AACM;AACqB;AACJ;AACI;AACN;AACQ;AACJ;AACA;AACU;AACA;AACA;AAAA;AAKjC;AACJ;AAOE;AAEA;AACE;AAAuB;AAGzB;AACQ;AACN;AAAwB;AAI1B;AAAsB;AACjB;AACH;AACA;AACA;AACA;AACA;AACD;AACH;AAII;AACJ;AACA;AACY;;AACZ;AAGF;AAEM;AACJ;AACM;AAEN;AACE;AACE;AAAA;AAGU;AACV;AACU;;AACG;AACjB;AAGI;AACJ;AACM;AAEN;AACE;AACA;AAA6B;AAC/B;AAGF;;AAGI;AACA;AACE;AACA;AAAU;AACX;AAIC;AAKN;AAGA;AAA0B;AACxB;AACoB;AACE;AAKxB;AAAsB;AACjB;AACoB;AACE;AAGpB;AAAA;AACF;AACA;AACA;AAKsC;AACpC;AAC0C;AACA;AACU;AACA;AACK;AAClD;AACZ;AACgE;AACR;AACxC;AACR;AACW;AACnB;AACkE;AACH;AAEnE;AA+FO;AACL;AACE;AAA2D;AAE/D;AAEO;AAAuC;AAE1C;AACM;AAEN;AAEoB;AACoC;AAIpD;AAGF;AAAiB;AAGnB;AAAa;AACW;AACtB;AACK;AACE;AACP;AACA;AAAA;AAGN;AAEA;AACS;AACT;;;;;;"}
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../src/link.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { flushSync } from 'react-dom'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport {\n deepEqual,\n functionalUpdate,\n useForwardedRef,\n useIntersectionObserver,\n} from './utils'\nimport { exactPathTest, removeTrailingSlash } from './path'\nimport type { AnyRouter, ParsedLocation } from '.'\nimport type { HistoryState } from '@tanstack/history'\nimport type {\n AllParams,\n CatchAllPaths,\n FullSearchSchema,\n FullSearchSchemaInput,\n RouteByPath,\n RouteByToPath,\n RoutePaths,\n RouteToPath,\n} from './routeInfo'\nimport type { RegisteredRouter } from './router'\nimport type {\n Expand,\n MakeDifferenceOptional,\n NoInfer,\n NonNullableUpdater,\n PickRequired,\n Updater,\n WithoutEmpty,\n} from './utils'\n\nexport type CleanPath<T extends string> = T extends `${infer L}//${infer R}`\n ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>\n : T extends `${infer L}//`\n ? `${CleanPath<L>}/`\n : T extends `//${infer L}`\n ? `/${CleanPath<L>}`\n : T\n\nexport type Split<TValue, TIncludeTrailingSlash = true> = TValue extends unknown\n ? string extends TValue\n ? Array<string>\n : TValue extends string\n ? CleanPath<TValue> extends ''\n ? []\n : TIncludeTrailingSlash extends true\n ? CleanPath<TValue> extends `${infer T}/`\n ? [...Split<T>, '/']\n : CleanPath<TValue> extends `/${infer U}`\n ? Split<U>\n : CleanPath<TValue> extends `${infer T}/${infer U}`\n ? [...Split<T>, ...Split<U>]\n : [TValue]\n : CleanPath<TValue> extends `${infer T}/${infer U}`\n ? [...Split<T>, ...Split<U>]\n : TValue extends string\n ? [TValue]\n : never\n : never\n : never\n\nexport type ParsePathParams<\n T extends string,\n TAcc = never,\n> = T extends `${string}$${string}`\n ? T extends `${string}$${infer TPossiblyParam}`\n ? TPossiblyParam extends `${string}/${string}`\n ? TPossiblyParam extends `${infer TParam}/${infer TRest}`\n ? ParsePathParams<TRest, TParam extends '' ? TAcc : TParam | TAcc>\n : never\n : TPossiblyParam extends ''\n ? TAcc\n : TPossiblyParam | TAcc\n : TAcc\n : TAcc\n\nexport type Join<T, TDelimiter extends string = '/'> = T extends []\n ? ''\n : T extends [infer L extends string]\n ? L\n : T extends [\n infer L extends string,\n ...infer Tail extends [...Array<string>],\n ]\n ? CleanPath<`${L}${TDelimiter}${Join<Tail>}`>\n : never\n\nexport type Last<T extends Array<any>> = T extends [...infer _, infer L]\n ? L\n : never\n\nexport type RemoveTrailingSlashes<T> = T extends `${infer R}/` ? R : T\n\nexport type RemoveLeadingSlashes<T> = T extends `/${infer R}` ? R : T\n\nexport type ResolvePaths<TRouter extends AnyRouter, TSearchPath> =\n RouteByPath<\n TRouter['routeTree'],\n RemoveTrailingSlashes<TSearchPath>\n > extends never\n ? RouteToPath<TRouter, TRouter['routeTree']>\n : RouteToPath<\n TRouter,\n RouteByPath<TRouter['routeTree'], RemoveTrailingSlashes<TSearchPath>>\n >\n\nexport type SearchPaths<\n TRouter extends AnyRouter,\n TSearchPath extends string,\n TPaths = ResolvePaths<TRouter, TSearchPath>,\n> = TPaths extends `${RemoveTrailingSlashes<TSearchPath>}${infer TRest}`\n ? TRest\n : never\n\nexport type SearchRelativePathAutoComplete<\n TRouter extends AnyRouter,\n TTo extends string,\n TSearchPath extends string,\n> = `${TTo}/${RemoveLeadingSlashes<SearchPaths<TRouter, TSearchPath>>}`\n\nexport type RelativeToParentPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TResolvedPath extends string = RemoveTrailingSlashes<\n ResolveRelativePath<TFrom, TTo>\n >,\n> =\n | SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>\n | (TResolvedPath extends '' ? never : `${TTo}/../`)\n\nexport type RelativeToCurrentPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n TRestTo extends string,\n TResolvedPath extends\n string = RemoveTrailingSlashes<`${RemoveTrailingSlashes<TFrom>}/${RemoveLeadingSlashes<TRestTo>}`>,\n> = SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>\n\nexport type AbsolutePathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n> =\n | (string extends TFrom\n ? './'\n : TFrom extends `/`\n ? never\n : SearchPaths<TRouter, TFrom> extends ''\n ? never\n : './')\n | (string extends TFrom ? '../' : TFrom extends `/` ? never : '../')\n | RouteToPath<TRouter, TRouter['routeTree']>\n | (TFrom extends '/'\n ? never\n : string extends TFrom\n ? never\n : RemoveLeadingSlashes<SearchPaths<TRouter, TFrom>>)\n\nexport type RelativeToPathAutoComplete<\n TRouter extends AnyRouter,\n TFrom extends string,\n TTo extends string,\n> = TTo extends `..${string}`\n ? RelativeToParentPathAutoComplete<TRouter, TFrom, RemoveTrailingSlashes<TTo>>\n : TTo extends `./${infer TRestTTo}`\n ? RelativeToCurrentPathAutoComplete<\n TRouter,\n TFrom,\n RemoveTrailingSlashes<TTo>,\n TRestTTo\n >\n : AbsolutePathAutoComplete<TRouter, TFrom>\n\nexport type NavigateOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & NavigateOptionProps\n\nexport interface NavigateOptionProps {\n // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.\n replace?: boolean\n resetScroll?: boolean\n /** @deprecated All navigations now use startTransition under the hood */\n startTransition?: boolean\n // if set to `true`, the router will wrap the resulting navigation in a document.startViewTransition() call.\n viewTransition?: boolean\n ignoreBlocker?: boolean\n}\n\nexport type ToOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ToSubOptions<TRouter, TFrom, TTo> & MaskOptions<TRouter, TMaskFrom, TMaskTo>\n\nexport interface MaskOptions<\n in out TRouter extends AnyRouter,\n in out TMaskFrom extends RoutePaths<TRouter['routeTree']> | string,\n in out TMaskTo extends string,\n> {\n _fromLocation?: ParsedLocation\n mask?: ToMaskOptions<TRouter, TMaskFrom, TMaskTo>\n}\n\nexport type ToMaskOptions<\n TRouteTree extends AnyRouter = RegisteredRouter,\n TMaskFrom extends RoutePaths<TRouteTree['routeTree']> | string = string,\n TMaskTo extends string = '',\n> = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {\n unmaskOnReload?: boolean\n}\n\nexport type ToSubOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n SearchParamOptions<TRouter, TFrom, TTo> &\n PathParamOptions<TRouter, TFrom, TTo>\n\nexport interface ToSubOptionsProps<\n in out TRouter extends AnyRouter = RegisteredRouter,\n in out TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n in out TTo extends string = '',\n> {\n to?: ToPathOption<TRouter, TFrom, TTo> & {}\n hash?: true | Updater<string>\n state?: true | NonNullableUpdater<HistoryState>\n // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required\n from?: FromPathOption<TRouter, TFrom> & {}\n}\n\nexport type ParamsReducerFn<\n in out TRouter extends AnyRouter,\n in out TParamVariant extends ParamVariant,\n in out TFrom,\n in out TTo,\n> = (\n current: Expand<ResolveFromParams<TRouter, TParamVariant, TFrom>>,\n) => Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n\ntype ParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | Expand<ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>>\n | (ParamsReducerFn<TRouter, TParamVariant, TFrom, TTo> & {})\n\ntype ParamVariant = 'PATH' | 'SEARCH'\n\nexport type ResolveRoute<\n TRouter extends AnyRouter,\n TFrom,\n TTo,\n TPath = ResolveRelativePath<TFrom, TTo>,\n> = TPath extends string\n ? TFrom extends TPath\n ? RouteByPath<TRouter['routeTree'], TPath>\n : RouteByToPath<TRouter, TPath>\n : never\n\ntype ResolveFromParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchema'\n\ntype ResolveFromAllParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchema<TRouter['routeTree']>\n\ntype ResolveFromParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n> = string extends TFrom\n ? ResolveFromAllParams<TRouter, TParamVariant>\n : RouteByPath<\n TRouter['routeTree'],\n TFrom\n >['types'][ResolveFromParamType<TParamVariant>]\n\ntype ResolveToParamType<TParamVariant extends ParamVariant> =\n TParamVariant extends 'PATH' ? 'allParams' : 'fullSearchSchemaInput'\n\ntype ResolveAllToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n> = TParamVariant extends 'PATH'\n ? AllParams<TRouter['routeTree']>\n : FullSearchSchemaInput<TRouter['routeTree']>\n\nexport type ResolveToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? string extends TPath\n ? ResolveAllToParams<TRouter, TParamVariant>\n : TPath extends CatchAllPaths\n ? ResolveAllToParams<TRouter, TParamVariant>\n : ResolveRoute<\n TRouter,\n TFrom,\n TTo\n >['types'][ResolveToParamType<TParamVariant>]\n : never\n\ntype ResolveRelativeToParams<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n TToParams = ResolveToParams<TRouter, TParamVariant, TFrom, TTo>,\n> = TParamVariant extends 'SEARCH'\n ? TToParams\n : string extends TFrom\n ? TToParams\n : MakeDifferenceOptional<\n ResolveFromParams<TRouter, TParamVariant, TFrom>,\n TToParams\n >\n\ninterface MakeOptionalSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search?: true | (ParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {})\n}\n\ninterface MakeOptionalPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params?: true | (ParamsReducer<TRouter, 'PATH', TFrom, TTo> & {})\n}\n\ntype MakeRequiredParamsReducer<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n | (string extends TFrom\n ? never\n : ResolveFromParams<TRouter, TParamVariant, TFrom> extends WithoutEmpty<\n PickRequired<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n >\n ? true\n : never)\n | (ParamsReducer<TRouter, TParamVariant, TFrom, TTo> & {})\n\nexport interface MakeRequiredPathParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n params: MakeRequiredParamsReducer<TRouter, 'PATH', TFrom, TTo> & {}\n}\n\nexport interface MakeRequiredSearchParams<\n in out TRouter extends AnyRouter,\n in out TFrom,\n in out TTo,\n> {\n search: MakeRequiredParamsReducer<TRouter, 'SEARCH', TFrom, TTo> & {}\n}\n\nexport type IsRequiredParams<TParams> =\n Record<never, never> extends TParams ? never : true\n\nexport type IsRequired<\n TRouter extends AnyRouter,\n TParamVariant extends ParamVariant,\n TFrom,\n TTo,\n> =\n ResolveRelativePath<TFrom, TTo> extends infer TPath\n ? string extends TPath\n ? never\n : TPath extends CatchAllPaths\n ? never\n : IsRequiredParams<\n ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>\n >\n : never\n\nexport type SearchParamOptions<\n TRouter extends AnyRouter,\n TFrom,\n TTo extends string,\n> =\n IsRequired<TRouter, 'SEARCH', TFrom, TTo> extends never\n ? MakeOptionalSearchParams<TRouter, TFrom, TTo>\n : MakeRequiredSearchParams<TRouter, TFrom, TTo>\n\nexport type PathParamOptions<\n TRouter extends AnyRouter,\n TFrom,\n TTo extends string,\n> =\n IsRequired<TRouter, 'PATH', TFrom, TTo> extends never\n ? MakeOptionalPathParams<TRouter, TFrom, TTo>\n : MakeRequiredPathParams<TRouter, TFrom, TTo>\n\nexport type ToPathOption<\n TRouter extends AnyRouter = AnyRouter,\n TFrom extends string = string,\n TTo extends string = string,\n> =\n | CheckPath<TRouter, TTo, never, TFrom, TTo>\n | RelativeToPathAutoComplete<\n TRouter,\n NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',\n NoInfer<TTo> & string\n >\n\nexport type CheckFromPath<\n TRouter extends AnyRouter,\n TPass,\n TFail,\n TFrom,\n> = string extends TFrom\n ? TPass\n : RouteByPath<TRouter['routeTree'], TFrom> extends never\n ? TFail\n : TPass\n\nexport type FromPathOption<TRouter extends AnyRouter, TFrom> =\n | CheckFromPath<\n TRouter,\n string extends TFrom ? TFrom & {} : TFrom,\n never,\n TFrom\n >\n | RoutePaths<TRouter['routeTree']>\n\nexport interface ActiveOptions {\n exact?: boolean\n includeHash?: boolean\n includeSearch?: boolean\n}\n\nexport type LinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & LinkOptionsProps\n\nexport interface LinkOptionsProps {\n /**\n * The standard anchor tag target attribute\n */\n target?: HTMLAnchorElement['target']\n /**\n * Configurable options to determine if the link should be considered active or not\n * @default {exact:true,includeHash:true}\n */\n activeOptions?: ActiveOptions\n /**\n * The preloading strategy for this link\n * - `false` - No preloading\n * - `'intent'` - Preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.\n * - `'viewport'` - Preload the linked route when it enters the viewport\n */\n preload?: false | 'intent' | 'viewport'\n /**\n * When a preload strategy is set, this delays the preload by this many milliseconds.\n * If the user exits the link before this delay, the preload will be cancelled.\n */\n preloadDelay?: number\n /**\n * Control whether the link should be disabled or not\n * If set to `true`, the link will be rendered without an `href` attribute\n * @default false\n */\n disabled?: boolean\n}\n\nexport type CheckPath<TRouter extends AnyRouter, TPass, TFail, TFrom, TTo> =\n string extends ResolveRelativePath<TFrom, TTo>\n ? TPass\n : ResolveRelativePath<TFrom, TTo> extends CatchAllPaths\n ? TPass\n : ResolveRoute<TRouter, TFrom, TTo> extends never\n ? TFail\n : TPass\n\nexport type ResolveRelativePath<TFrom, TTo = '.'> = string extends TFrom\n ? TTo\n : string extends TTo\n ? TFrom\n : TFrom extends string\n ? TTo extends string\n ? TTo extends '.'\n ? TFrom\n : TTo extends `./`\n ? Join<[TFrom, '/']>\n : TTo extends `./${infer TRest}`\n ? ResolveRelativePath<TFrom, TRest>\n : TTo extends `/${infer TRest}`\n ? TTo\n : Split<TTo> extends ['..', ...infer ToRest]\n ? Split<TFrom> extends [...infer FromRest, infer FromTail]\n ? ToRest extends ['/']\n ? Join<['/', ...FromRest, '/']>\n : ResolveRelativePath<Join<FromRest>, Join<ToRest>>\n : never\n : Split<TTo> extends ['.', ...infer ToRest]\n ? ToRest extends ['/']\n ? Join<[TFrom, '/']>\n : ResolveRelativePath<TFrom, Join<ToRest>>\n : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>\n : never\n : never\n\n// type Test1 = ResolveRelativePath<'/', '/posts'>\n// // ^?\n// type Test4 = ResolveRelativePath<'/posts/1/comments', '../..'>\n// // ^?\n// type Test5 = ResolveRelativePath<'/posts/1/comments', '../../..'>\n// // ^?\n// type Test6 = ResolveRelativePath<'/posts/1/comments', './1'>\n// // ^?\n// type Test7 = ResolveRelativePath<'/posts/1/comments', './1/2'>\n// // ^?\n// type Test8 = ResolveRelativePath<'/posts/1/comments', '../edit'>\n// // ^?\n// type Test9 = ResolveRelativePath<'/posts/1/comments', '1'>\n// // ^?\n// type Test10 = ResolveRelativePath<'/posts/1/comments', './1'>\n// // ^?\n// type Test11 = ResolveRelativePath<'/posts/1/comments', './1/2'>\n// // ^?\n\ntype LinkCurrentTargetElement = {\n preloadTimeout?: null | ReturnType<typeof setTimeout>\n}\n\nconst preloadWarning = 'Error preloading route! ☝️'\n\nexport function useLinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n forwardedRef?: React.ForwardedRef<Element>,\n): React.ComponentPropsWithRef<'a'> {\n const router = useRouter()\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n const innerRef = useForwardedRef(forwardedRef)\n\n const {\n // custom props\n activeProps = () => ({ className: 'active' }),\n inactiveProps = () => ({}),\n activeOptions,\n hash,\n search,\n params,\n to,\n state,\n mask,\n preload: userPreload,\n preloadDelay: userPreloadDelay,\n replace,\n startTransition,\n resetScroll,\n viewTransition,\n // element props\n children,\n target,\n disabled,\n style,\n className,\n onClick,\n onFocus,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n ignoreBlocker,\n ...rest\n } = options\n\n // If this link simply reloads the current route,\n // make sure it has a new key so it will trigger a data refresh\n\n // If this `to` is a valid external URL, return\n // null for LinkUtils\n\n const type: 'internal' | 'external' = React.useMemo(() => {\n try {\n new URL(`${to}`)\n return 'external'\n } catch {}\n return 'internal'\n }, [to])\n\n const next = React.useMemo(\n () => router.buildLocation(options as any),\n [router, options],\n )\n const preload = React.useMemo(\n () => userPreload ?? router.options.defaultPreload,\n [router.options.defaultPreload, userPreload],\n )\n const preloadDelay =\n userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0\n\n const isActive = useRouterState({\n select: (s) => {\n // Compare path/hash for matches\n const currentPathSplit = removeTrailingSlash(\n s.location.pathname,\n router.basepath,\n ).split('/')\n const nextPathSplit = removeTrailingSlash(\n next.pathname,\n router.basepath,\n ).split('/')\n const pathIsFuzzyEqual = nextPathSplit.every(\n (d, i) => d === currentPathSplit[i],\n )\n // Combine the matches based on user router.options\n const pathTest = activeOptions?.exact\n ? exactPathTest(s.location.pathname, next.pathname, router.basepath)\n : pathIsFuzzyEqual\n const hashTest = activeOptions?.includeHash\n ? s.location.hash === next.hash\n : true\n const searchTest =\n (activeOptions?.includeSearch ?? true)\n ? deepEqual(s.location.search, next.search, !activeOptions?.exact)\n : true\n\n // The final \"active\" test\n return pathTest && hashTest && searchTest\n },\n })\n\n const doPreload = React.useCallback(() => {\n router.preloadRoute(options as any).catch((err) => {\n console.warn(err)\n console.warn(preloadWarning)\n })\n }, [options, router])\n\n const preloadViewportIoCallback = React.useCallback(\n (entry: IntersectionObserverEntry | undefined) => {\n if (entry?.isIntersecting) {\n doPreload()\n }\n },\n [doPreload],\n )\n\n useIntersectionObserver(\n innerRef,\n preloadViewportIoCallback,\n { rootMargin: '100px' },\n { disabled: !!disabled || preload !== 'viewport' },\n )\n\n if (type === 'external') {\n return {\n ...rest,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n type,\n href: to,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n ...(onClick && { onClick }),\n ...(onFocus && { onFocus }),\n ...(onMouseEnter && { onMouseEnter }),\n ...(onMouseLeave && { onMouseLeave }),\n ...(onTouchStart && { onTouchStart }),\n }\n }\n\n // The click handler\n const handleClick = (e: MouseEvent) => {\n if (\n !disabled &&\n !isCtrlEvent(e) &&\n !e.defaultPrevented &&\n (!target || target === '_self') &&\n e.button === 0\n ) {\n e.preventDefault()\n\n flushSync(() => {\n setIsTransitioning(true)\n })\n\n const unsub = router.subscribe('onResolved', () => {\n unsub()\n setIsTransitioning(false)\n })\n\n // All is well? Navigate!\n router.commitLocation({\n ...next,\n replace,\n resetScroll,\n startTransition,\n viewTransition,\n ignoreBlocker,\n })\n }\n }\n\n // The click handler\n const handleFocus = (_: MouseEvent) => {\n if (disabled) return\n if (preload) {\n doPreload()\n }\n }\n\n const handleTouchStart = handleFocus\n\n const handleEnter = (e: MouseEvent) => {\n if (disabled) return\n const eventTarget = (e.target || {}) as LinkCurrentTargetElement\n\n if (preload) {\n if (eventTarget.preloadTimeout) {\n return\n }\n\n eventTarget.preloadTimeout = setTimeout(() => {\n eventTarget.preloadTimeout = null\n doPreload()\n }, preloadDelay)\n }\n }\n\n const handleLeave = (e: MouseEvent) => {\n if (disabled) return\n const eventTarget = (e.target || {}) as LinkCurrentTargetElement\n\n if (eventTarget.preloadTimeout) {\n clearTimeout(eventTarget.preloadTimeout)\n eventTarget.preloadTimeout = null\n }\n }\n\n const composeHandlers =\n (handlers: Array<undefined | ((e: any) => void)>) =>\n (e: { persist?: () => void; defaultPrevented: boolean }) => {\n e.persist?.()\n handlers.filter(Boolean).forEach((handler) => {\n if (e.defaultPrevented) return\n handler!(e)\n })\n }\n\n // Get the active props\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive\n ? (functionalUpdate(activeProps as any, {}) ?? {})\n : {}\n\n // Get the inactive props\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive ? {} : functionalUpdate(inactiveProps, {})\n\n const resolvedClassName = [\n className,\n resolvedActiveProps.className,\n resolvedInactiveProps.className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const resolvedStyle = {\n ...style,\n ...resolvedActiveProps.style,\n ...resolvedInactiveProps.style,\n }\n\n return {\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n ...rest,\n href: disabled\n ? undefined\n : next.maskedLocation\n ? router.history.createHref(next.maskedLocation.href)\n : router.history.createHref(next.href),\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n onClick: composeHandlers([onClick, handleClick]),\n onFocus: composeHandlers([onFocus, handleFocus]),\n onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),\n onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),\n onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),\n disabled: !!disabled,\n target,\n ...(Object.keys(resolvedStyle).length && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && {\n role: 'link',\n 'aria-disabled': true,\n }),\n ...(isActive && { 'data-status': 'active', 'aria-current': 'page' }),\n ...(isTransitioning && { 'data-transitioning': 'transitioning' }),\n }\n}\n\nexport type UseLinkPropsOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n> = ActiveLinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n React.AnchorHTMLAttributes<HTMLAnchorElement>\n\nexport type ActiveLinkOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & ActiveLinkOptionProps\n\ntype ActiveLinkAnchorProps = Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement> & {\n [key: `data-${string}`]: unknown\n },\n 'children'\n>\n\nexport interface ActiveLinkOptionProps {\n /**\n * A function that returns additional props for the `active` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n activeProps?: ActiveLinkAnchorProps | (() => ActiveLinkAnchorProps)\n /**\n * A function that returns additional props for the `inactive` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n inactiveProps?: ActiveLinkAnchorProps | (() => ActiveLinkAnchorProps)\n}\n\nexport type LinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = ActiveLinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n LinkPropsChildren\n\nexport interface LinkPropsChildren {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | React.ReactNode\n | ((state: {\n isActive: boolean\n isTransitioning: boolean\n }) => React.ReactNode)\n}\n\ntype LinkComponentReactProps<TComp> = React.PropsWithoutRef<\n TComp extends React.FC<infer TProps> | React.Component<infer TProps>\n ? TProps\n : TComp extends keyof React.JSX.IntrinsicElements\n ? Omit<React.HTMLProps<TComp>, 'children' | 'preload'>\n : never\n> &\n React.RefAttributes<\n TComp extends\n | React.FC<{ ref: infer TRef }>\n | React.Component<{ ref: infer TRef }>\n ? TRef\n : TComp extends keyof React.JSX.IntrinsicElements\n ? React.ComponentRef<TComp>\n : never\n >\n\nexport type LinkComponentProps<\n TComp,\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = LinkComponentReactProps<TComp> &\n LinkProps<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type LinkComponent<TComp> = <\n TRouter extends RegisteredRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n>(\n props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => React.ReactElement\n\nexport function createLink<const TComp>(Comp: TComp): LinkComponent<TComp> {\n return React.forwardRef(function CreatedLink(props, ref) {\n return <Link {...(props as any)} _asChild={Comp} ref={ref} />\n }) as any\n}\n\nexport const Link: LinkComponent<'a'> = React.forwardRef<Element, any>(\n (props, ref) => {\n const { _asChild, ...rest } = props\n const { type, ref: innerRef, ...linkProps } = useLinkProps(rest, ref)\n\n const children =\n typeof rest.children === 'function'\n ? rest.children({\n isActive: (linkProps as any)['data-status'] === 'active',\n })\n : rest.children\n\n if (typeof _asChild === 'undefined') {\n // the ReturnType of useLinkProps returns the correct type for a <a> element, not a general component that has a delete prop\n // @ts-expect-error\n delete linkProps.disabled\n }\n\n return React.createElement(\n _asChild ? _asChild : 'a',\n {\n ...linkProps,\n ref: innerRef,\n },\n children,\n )\n },\n) as any\n\nfunction isCtrlEvent(e: MouseEvent) {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n}\n"],"names":[],"mappings":";;;;;;;;AAgjBA;AAEgB;AAUd;AACA;AACM;AAEA;AAAA;AAAA;;AAGmB;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACS;AACK;AACd;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AASC;AACA;AACE;AACG;AAAA;AACD;AACD;AAAA;AAGT;AAAmB;AACwB;AACzB;AAElB;AAAsB;AACgB;AACO;AAE7C;AAGA;AAAgC;AAG5B;AAAyB;AACZ;AACJ;AAET;AAAsB;AACf;AACE;AAET;AAAuC;AACH;AAG9B;AAGN;AAGA;AAMA;AAA+B;AACjC;AAGI;AACJ;AACE;AACA;AAA2B;AAC5B;AAGH;AAAwC;AAEpC;AACY;;AACZ;AACF;AACU;AAGZ;AAAA;AACE;AACA;AACsB;AAC2B;AAGnD;AACS;AAAA;AACF;AACE;AACL;AACM;AACqB;AACJ;AACI;AACN;AACQ;AACJ;AACA;AACU;AACA;AACA;AAAA;AAKjC;AACJ;AAOE;AAEA;AACE;AAAuB;AAGzB;AACQ;AACN;AAAwB;AAI1B;AAAsB;AACjB;AACH;AACA;AACA;AACA;AACA;AACD;AACH;AAII;AACJ;AACA;AACY;;AACZ;AAGF;AAEM;AACJ;AACM;AAEN;AACE;AACE;AAAA;AAGU;AACV;AACU;;AACG;AACjB;AAGI;AACJ;AACM;AAEN;AACE;AACA;AAA6B;AAC/B;AAGF;;AAGI;AACA;AACE;AACA;AAAU;AACX;AAIC;AAKN;AAGA;AAA0B;AACxB;AACoB;AACE;AAKxB;AAAsB;AACjB;AACoB;AACE;AAGpB;AAAA;AACF;AACA;AACA;AAKsC;AACpC;AAC0C;AACA;AACU;AACA;AACK;AAClD;AACZ;AACgE;AACR;AACxC;AACR;AACW;AACnB;AACkE;AACH;AAEnE;AA+FO;AACL;AACE;AAA2D;AAE/D;AAEO;AAAuC;AAE1C;AACM;AAEN;AAEoB;AACoC;AAIpD;AAGF;AAAiB;AAGnB;AAAa;AACW;AACtB;AACK;AACE;AACP;AACA;AAAA;AAGN;AAEA;AACS;AACT;;;;;;"}
|
package/dist/esm/path.js
CHANGED
|
@@ -196,15 +196,12 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
196
196
|
const isLastRouteSegment = i >= routeSegments.length - 1;
|
|
197
197
|
if (routeSegment) {
|
|
198
198
|
if (routeSegment.type === "wildcard") {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
return false;
|
|
199
|
+
const _splat = decodeURI(
|
|
200
|
+
joinPaths(baseSegments.slice(i).map((d) => d.value))
|
|
201
|
+
);
|
|
202
|
+
params["*"] = _splat;
|
|
203
|
+
params["_splat"] = _splat;
|
|
204
|
+
return true;
|
|
208
205
|
}
|
|
209
206
|
if (routeSegment.type === "pathname") {
|
|
210
207
|
if (routeSegment.value === "/" && !(baseSegment == null ? void 0 : baseSegment.value)) {
|
package/dist/esm/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base)\n to = removeBasepath(basepath, to)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const joined = joinPaths([basepath, ...baseSegments.map((d) => d.value)])\n return cleanPath(joined)\n}\n\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n if (part === '$' || part === '*') {\n return {\n type: 'wildcard',\n value: part,\n }\n }\n\n if (part.charAt(0) === '$') {\n return {\n type: 'param',\n value: part,\n }\n }\n\n return {\n type: 'pathname',\n value: decodeURIComponent(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n}\n\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n}: InterpolatePathOptions) {\n const interpolatedPathSegments = parsePathname(path)\n const encodedParams: any = {}\n\n for (const [key, value] of Object.entries(params)) {\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n encodedParams[key] = isValueString ? encodeURI(value) : value\n } else {\n encodedParams[key] = isValueString ? encodeURIComponent(value) : value\n }\n }\n\n return joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n const value = encodedParams._splat\n if (leaveWildcards) return `${segment.value}${value ?? ''}`\n return value\n }\n\n if (segment.type === 'param') {\n if (leaveParams) {\n const value = encodedParams[segment.value]\n return `${segment.value}${value ?? ''}`\n }\n return encodedParams![segment.value.substring(1)] ?? 'undefined'\n }\n\n return segment.value\n }),\n )\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(basepath: string, pathname: string) {\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case basepath === '/':\n return pathname\n\n // shortcut for removing the basepath from the equal pathname\n case pathname === basepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case pathname[basepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname in case there is any\n case pathname.startsWith(basepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from)\n // Default to to $ (wildcard)\n const to = removeBasepath(basepath, `${matchLocation.to ?? '$'}`)\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n if (baseSegment?.value) {\n const _splat = decodeURI(\n joinPaths(baseSegments.slice(i).map((d) => d.value)),\n )\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n return false\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n if (baseSegment.value.charAt(0) !== '$') {\n params[routeSegment.value.substring(1)] = decodeURIComponent(\n baseSegment.value,\n )\n }\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport interface Segment {\n type: 'pathname' | 'param' | 'wildcard'\n value: string\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base)\n to = removeBasepath(basepath, to)\n\n let baseSegments = parsePathname(base)\n const toSegments = parsePathname(to)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n toSegments.forEach((toSegment, index) => {\n if (toSegment.value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === toSegments.length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (toSegment.value === '..') {\n baseSegments.pop()\n } else if (toSegment.value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n })\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)?.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: 'pathname', value: '/' })\n }\n }\n\n const joined = joinPaths([basepath, ...baseSegments.map((d) => d.value)])\n return cleanPath(joined)\n}\n\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return []\n }\n\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n if (part === '$' || part === '*') {\n return {\n type: 'wildcard',\n value: part,\n }\n }\n\n if (part.charAt(0) === '$') {\n return {\n type: 'param',\n value: part,\n }\n }\n\n return {\n type: 'pathname',\n value: decodeURIComponent(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: 'pathname',\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n}\n\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n}: InterpolatePathOptions) {\n const interpolatedPathSegments = parsePathname(path)\n const encodedParams: any = {}\n\n for (const [key, value] of Object.entries(params)) {\n const isValueString = typeof value === 'string'\n\n if (['*', '_splat'].includes(key)) {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n encodedParams[key] = isValueString ? encodeURI(value) : value\n } else {\n encodedParams[key] = isValueString ? encodeURIComponent(value) : value\n }\n }\n\n return joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === 'wildcard') {\n const value = encodedParams._splat\n if (leaveWildcards) return `${segment.value}${value ?? ''}`\n return value\n }\n\n if (segment.type === 'param') {\n if (leaveParams) {\n const value = encodedParams[segment.value]\n return `${segment.value}${value ?? ''}`\n }\n return encodedParams![segment.value.substring(1)] ?? 'undefined'\n }\n\n return segment.value\n }),\n )\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(basepath: string, pathname: string) {\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case basepath === '/':\n return pathname\n\n // shortcut for removing the basepath from the equal pathname\n case pathname === basepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case pathname[basepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname in case there is any\n case pathname.startsWith(basepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n): Record<string, string> | undefined {\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from)\n // Default to to $ (wildcard)\n const to = removeBasepath(basepath, `${matchLocation.to ?? '$'}`)\n\n // Parse the from and to\n const baseSegments = parsePathname(from)\n const routeSegments = parsePathname(to)\n\n if (!from.startsWith('/')) {\n baseSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n if (!to.startsWith('/')) {\n routeSegments.unshift({\n type: 'pathname',\n value: '/',\n })\n }\n\n const params: Record<string, string> = {}\n\n const isMatch = (() => {\n for (\n let i = 0;\n i < Math.max(baseSegments.length, routeSegments.length);\n i++\n ) {\n const baseSegment = baseSegments[i]\n const routeSegment = routeSegments[i]\n\n const isLastBaseSegment = i >= baseSegments.length - 1\n const isLastRouteSegment = i >= routeSegments.length - 1\n\n if (routeSegment) {\n if (routeSegment.type === 'wildcard') {\n const _splat = decodeURI(\n joinPaths(baseSegments.slice(i).map((d) => d.value)),\n )\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === 'pathname') {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n return true\n }\n\n if (baseSegment) {\n if (matchLocation.caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !==\n baseSegment.value.toLowerCase()\n ) {\n return false\n }\n }\n }\n\n if (!baseSegment) {\n return false\n }\n\n if (routeSegment.type === 'param') {\n if (baseSegment.value === '/') {\n return false\n }\n if (baseSegment.value.charAt(0) !== '$') {\n params[routeSegment.value.substring(1)] = decodeURIComponent(\n baseSegment.value,\n )\n }\n }\n }\n\n if (!isLastBaseSegment && isLastRouteSegment) {\n params['**'] = joinPaths(baseSegments.slice(i + 1).map((d) => d.value))\n return !!matchLocation.fuzzy && routeSegment?.value !== '/'\n }\n }\n\n return true\n })()\n\n return isMatch ? params : undefined\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/route.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { NavigateOptions, ParsePathParams, ToMaskOptions } from './link.js';
|
|
|
5
5
|
import { ParsedLocation } from './location.js';
|
|
6
6
|
import { RouteById, RouteIds, RoutePaths } from './routeInfo.js';
|
|
7
7
|
import { AnyRouter, RegisteredRouter, Router } from './router.js';
|
|
8
|
-
import { Assign, Expand, NoInfer, PickRequired } from './utils.js';
|
|
8
|
+
import { Assign, Constrain, Expand, NoInfer, PickRequired } from './utils.js';
|
|
9
9
|
import { BuildLocationFn, NavigateFn } from './RouterProvider.js';
|
|
10
10
|
import { NotFoundError } from './not-found.js';
|
|
11
11
|
import { LazyRoute } from './fileRoute.js';
|
|
@@ -32,9 +32,14 @@ export type RoutePathOptionsIntersection<TCustomId, TPath> = {
|
|
|
32
32
|
path: TPath;
|
|
33
33
|
id: TCustomId;
|
|
34
34
|
};
|
|
35
|
-
export type RouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId extends string = string, TPath extends string = string, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TParams = AnyPathParams, TAllParams = TParams,
|
|
36
|
-
export type
|
|
37
|
-
export
|
|
35
|
+
export type RouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId extends string = string, TPath extends string = string, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TParams = AnyPathParams, TAllParams = TParams, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext> = BaseRouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TLoaderDeps, TLoaderDataReturn, TRouterContext, TRouteContextFn, TBeforeLoadFn> & UpdatableRouteOptions<NoInfer<TParentRoute>, NoInfer<TCustomId>, NoInfer<TAllParams>, NoInfer<TSearchValidator>, NoInfer<TLoaderData>, NoInfer<TLoaderDeps>, NoInfer<TRouterContext>, NoInfer<TRouteContextFn>, NoInfer<TBeforeLoadFn>>;
|
|
36
|
+
export type ParseSplatParams<TPath extends string> = TPath extends `${string}$` ? '_splat' : TPath extends `${string}$/${string}` ? '_splat' : never;
|
|
37
|
+
export interface SplatParams {
|
|
38
|
+
_splat?: string;
|
|
39
|
+
}
|
|
40
|
+
export type ResolveParams<TPath extends string> = ParseSplatParams<TPath> extends never ? Record<ParsePathParams<TPath>, string> : Record<ParsePathParams<TPath>, string> & SplatParams;
|
|
41
|
+
export type ParseParamsFn<TPath extends string, TParams> = (rawParams: ResolveParams<TPath>) => TParams extends Record<ParsePathParams<TPath>, any> ? TParams : Record<ParsePathParams<TPath>, any>;
|
|
42
|
+
export type StringifyParamsFn<TPath extends string, TParams> = (params: TParams) => ResolveParams<TPath>;
|
|
38
43
|
export type ParamsOptions<TPath extends string, TParams> = {
|
|
39
44
|
params?: {
|
|
40
45
|
parse: ParseParamsFn<TPath, TParams>;
|
|
@@ -49,24 +54,26 @@ export type ParamsOptions<TPath extends string, TParams> = {
|
|
|
49
54
|
*/
|
|
50
55
|
stringifyParams?: StringifyParamsFn<TPath, TParams>;
|
|
51
56
|
};
|
|
52
|
-
export interface FullSearchSchemaOption<
|
|
53
|
-
search:
|
|
57
|
+
export interface FullSearchSchemaOption<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator> {
|
|
58
|
+
search: Expand<ResolveFullSearchSchema<TParentRoute, TSearchValidator>>;
|
|
54
59
|
}
|
|
55
|
-
export type
|
|
60
|
+
export type RouteContextFn<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator, in out TParams, in out TRouterContext> = (ctx: RouteContextOptions<TParentRoute, TSearchValidator, TParams, TRouterContext>) => any;
|
|
61
|
+
export type BeforeLoadFn<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn> = (ctx: BeforeLoadContextOptions<TParentRoute, TSearchValidator, TParams, TRouterContext, TRouteContextFn>) => any;
|
|
62
|
+
export type FileBaseRouteOptions<TParentRoute extends AnyRoute = AnyRoute, TPath extends string = string, TSearchValidator extends AnySearchValidator = undefined, TParams = {}, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext> = ParamsOptions<TPath, TParams> & {
|
|
56
63
|
validateSearch?: TSearchValidator;
|
|
57
|
-
shouldReload?: boolean | ((match: LoaderFnContext<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
shouldReload?: boolean | ((match: LoaderFnContext<TParentRoute, TParams, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => any);
|
|
65
|
+
context?: Constrain<TRouteContextFn, RouteContextFn<TParentRoute, TSearchValidator, TParams, TRouterContext>>;
|
|
66
|
+
beforeLoad?: Constrain<TBeforeLoadFn, BeforeLoadFn<TParentRoute, TSearchValidator, TParams, TRouterContext, TRouteContextFn>>;
|
|
67
|
+
loaderDeps?: (opts: FullSearchSchemaOption<TParentRoute, TSearchValidator>) => TLoaderDeps;
|
|
68
|
+
loader?: (ctx: LoaderFnContext<TParentRoute, TParams, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => TLoaderDataReturn | Promise<TLoaderDataReturn>;
|
|
69
|
+
};
|
|
70
|
+
export type BaseRouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId extends string = string, TPath extends string = string, TSearchValidator extends AnySearchValidator = undefined, TParams = {}, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext> = RoutePathOptions<TCustomId, TPath> & FileBaseRouteOptions<TParentRoute, TPath, TSearchValidator, TParams, TLoaderDeps, TLoaderDataReturn, TRouterContext, TRouteContextFn, TBeforeLoadFn> & {
|
|
63
71
|
getParentRoute: () => TParentRoute;
|
|
64
72
|
};
|
|
65
|
-
export interface
|
|
73
|
+
export interface ContextOptions<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator, in out TParams> extends FullSearchSchemaOption<TParentRoute, TSearchValidator> {
|
|
66
74
|
abortController: AbortController;
|
|
67
75
|
preload: boolean;
|
|
68
|
-
params: Expand<
|
|
69
|
-
context: TParentAllContext;
|
|
76
|
+
params: Expand<ResolveAllParamsFromParent<TParentRoute, TParams>>;
|
|
70
77
|
location: ParsedLocation;
|
|
71
78
|
/**
|
|
72
79
|
* @deprecated Use `throw redirect({ to: '/somewhere' })` instead
|
|
@@ -75,7 +82,13 @@ export interface BeforeLoadContext<TFullSearchSchema, TAllParams, TParentAllCont
|
|
|
75
82
|
buildLocation: BuildLocationFn;
|
|
76
83
|
cause: 'preload' | 'enter' | 'stay';
|
|
77
84
|
}
|
|
78
|
-
export
|
|
85
|
+
export interface RouteContextOptions<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator, in out TParams, in out TRouterContext> extends ContextOptions<TParentRoute, TSearchValidator, TParams> {
|
|
86
|
+
context: Expand<RouteContextParameter<TParentRoute, TRouterContext>>;
|
|
87
|
+
}
|
|
88
|
+
export interface BeforeLoadContextOptions<in out TParentRoute extends AnyRoute, in out TSearchValidator extends AnySearchValidator, in out TParams, in out TRouterContext, in out TRouteContextFn> extends ContextOptions<TParentRoute, TSearchValidator, TParams> {
|
|
89
|
+
context: Expand<BeforeLoadContextParameter<TParentRoute, TRouterContext, TRouteContextFn>>;
|
|
90
|
+
}
|
|
91
|
+
export type UpdatableRouteOptions<TParentRoute extends AnyRoute, TRouteId, TAllParams, TSearchValidator extends AnySearchValidator, TLoaderData, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn> = {
|
|
79
92
|
caseSensitive?: boolean;
|
|
80
93
|
wrapInSuspense?: boolean;
|
|
81
94
|
component?: RouteComponent;
|
|
@@ -86,18 +99,19 @@ export type UpdatableRouteOptions<TParentRoute extends AnyRoute, TRouteId, TAllP
|
|
|
86
99
|
pendingMinMs?: number;
|
|
87
100
|
staleTime?: number;
|
|
88
101
|
gcTime?: number;
|
|
102
|
+
preload?: boolean;
|
|
89
103
|
preloadStaleTime?: number;
|
|
90
104
|
preloadGcTime?: number;
|
|
91
105
|
preSearchFilters?: Array<SearchFilter<ResolveFullSearchSchema<TParentRoute, TSearchValidator>>>;
|
|
92
106
|
postSearchFilters?: Array<SearchFilter<ResolveFullSearchSchema<TParentRoute, TSearchValidator>>>;
|
|
93
107
|
onCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
94
108
|
onError?: (err: any) => void;
|
|
95
|
-
onEnter?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData,
|
|
96
|
-
onStay?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData,
|
|
97
|
-
onLeave?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData,
|
|
109
|
+
onEnter?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData, ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>, TLoaderDeps>) => void;
|
|
110
|
+
onStay?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData, ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>, TLoaderDeps>) => void;
|
|
111
|
+
onLeave?: (match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData, ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>, TLoaderDeps>) => void;
|
|
98
112
|
meta?: (ctx: {
|
|
99
|
-
matches: Array<RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData,
|
|
100
|
-
match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData,
|
|
113
|
+
matches: Array<RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData, ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>, TLoaderDeps>>;
|
|
114
|
+
match: RouteMatch<TRouteId, TAllParams, ResolveFullSearchSchema<TParentRoute, TSearchValidator>, TLoaderData, ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>, TLoaderDeps>;
|
|
101
115
|
params: TAllParams;
|
|
102
116
|
loaderData: TLoaderData;
|
|
103
117
|
}) => Array<React.JSX.IntrinsicElements['meta']>;
|
|
@@ -157,13 +171,13 @@ export type SearchValidatorFn<TInput, TOutput> = (input: TInput) => TOutput;
|
|
|
157
171
|
export type SearchValidator<TInput, TOutput> = SearchValidatorObj<TInput, TOutput> | SearchValidatorFn<TInput, TOutput> | SearchValidatorAdapter<TInput, TOutput> | undefined;
|
|
158
172
|
export type AnySearchValidator = SearchValidator<any, any>;
|
|
159
173
|
export type DefaultSearchValidator = SearchValidator<Record<string, unknown>, AnySearchSchema>;
|
|
160
|
-
export type RouteLoaderFn<in out
|
|
161
|
-
export interface LoaderFnContext<in out
|
|
174
|
+
export type RouteLoaderFn<in out TParentRoute extends AnyRoute = AnyRoute, in out TParams = {}, in out TLoaderDeps = {}, in out TRouterContext = {}, in out TRouteContextFn = AnyContext, in out TBeforeLoadFn = AnyContext, TLoaderData = undefined> = (match: LoaderFnContext<TParentRoute, TParams, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => TLoaderData | Promise<TLoaderData>;
|
|
175
|
+
export interface LoaderFnContext<in out TParentRoute extends AnyRoute = AnyRoute, in out TParams = {}, in out TLoaderDeps = {}, in out TRouterContext = {}, in out TRouteContextFn = AnyContext, in out TBeforeLoadFn = AnyContext> {
|
|
162
176
|
abortController: AbortController;
|
|
163
177
|
preload: boolean;
|
|
164
|
-
params: Expand<
|
|
178
|
+
params: Expand<ResolveAllParamsFromParent<TParentRoute, TParams>>;
|
|
165
179
|
deps: TLoaderDeps;
|
|
166
|
-
context:
|
|
180
|
+
context: Expand<ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>>;
|
|
167
181
|
location: ParsedLocation;
|
|
168
182
|
/**
|
|
169
183
|
* @deprecated Use `throw redirect({ to: '/somewhere' })` instead
|
|
@@ -192,7 +206,7 @@ export type InferAllParams<TRoute> = TRoute extends {
|
|
|
192
206
|
allParams: infer TAllParams;
|
|
193
207
|
};
|
|
194
208
|
} ? TAllParams : {};
|
|
195
|
-
export type InferAllContext<TRoute> = TRoute extends {
|
|
209
|
+
export type InferAllContext<TRoute> = unknown extends TRoute ? TRoute : TRoute extends {
|
|
196
210
|
types: {
|
|
197
211
|
allContext: infer TAllContext;
|
|
198
212
|
};
|
|
@@ -203,16 +217,24 @@ export type ResolveSearchSchemaFn<TSearchValidator extends AnySearchValidator> =
|
|
|
203
217
|
export type ResolveSearchSchema<TSearchValidator extends AnySearchValidator> = unknown extends TSearchValidator ? TSearchValidator : TSearchValidator extends AnySearchValidatorAdapter ? TSearchValidator['types']['output'] : TSearchValidator extends AnySearchValidatorObj ? ResolveSearchSchemaFn<TSearchValidator['parse']> : ResolveSearchSchemaFn<TSearchValidator>;
|
|
204
218
|
export type ResolveFullSearchSchema<TParentRoute extends AnyRoute, TSearchValidator extends AnySearchValidator> = unknown extends TParentRoute ? ResolveSearchSchema<TSearchValidator> : Assign<InferFullSearchSchema<TParentRoute>, ResolveSearchSchema<TSearchValidator>>;
|
|
205
219
|
export type ResolveFullSearchSchemaInput<TParentRoute extends AnyRoute, TSearchValidator extends AnySearchValidator> = Assign<InferFullSearchSchemaInput<TParentRoute>, ResolveSearchSchemaInput<TSearchValidator>>;
|
|
206
|
-
export type
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
export type
|
|
220
|
+
export type LooseReturnType<T> = T extends (...args: Array<any>) => infer TReturn ? TReturn : never;
|
|
221
|
+
export type LooseAsyncReturnType<T> = T extends (...args: Array<any>) => infer TReturn ? TReturn extends Promise<infer TReturn> ? TReturn : TReturn : never;
|
|
222
|
+
export type ContextReturnType<TContextFn> = unknown extends TContextFn ? TContextFn : LooseReturnType<TContextFn> extends never ? AnyContext : LooseReturnType<TContextFn>;
|
|
223
|
+
export type ContextAsyncReturnType<TContextFn> = unknown extends TContextFn ? TContextFn : LooseAsyncReturnType<TContextFn> extends never ? AnyContext : LooseAsyncReturnType<TContextFn>;
|
|
224
|
+
export type RouteContextParameter<TParentRoute extends AnyRoute, TRouterContext> = unknown extends TParentRoute ? TRouterContext : Assign<TRouterContext, InferAllContext<TParentRoute>>;
|
|
225
|
+
export type ResolveRouteContext<TRouteContextFn, TBeforeLoadFn> = Assign<ContextReturnType<TRouteContextFn>, ContextAsyncReturnType<TBeforeLoadFn>>;
|
|
226
|
+
export type BeforeLoadContextParameter<TParentRoute extends AnyRoute, TRouterContext, TRouteContextFn> = Assign<RouteContextParameter<TParentRoute, TRouterContext>, ContextReturnType<TRouteContextFn>>;
|
|
227
|
+
export type ResolveAllContext<TParentRoute extends AnyRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn> = Assign<BeforeLoadContextParameter<TParentRoute, TRouterContext, TRouteContextFn>, ContextAsyncReturnType<TBeforeLoadFn>>;
|
|
210
228
|
export type ResolveLoaderData<TLoaderDataReturn> = [TLoaderDataReturn] extends [
|
|
211
229
|
never
|
|
212
230
|
] ? undefined : TLoaderDataReturn;
|
|
213
231
|
export interface AnyRoute extends Route<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any> {
|
|
214
232
|
}
|
|
215
|
-
export type AnyRouteWithContext<TContext> =
|
|
233
|
+
export type AnyRouteWithContext<TContext> = AnyRoute & {
|
|
234
|
+
types: {
|
|
235
|
+
allContext: TContext;
|
|
236
|
+
};
|
|
237
|
+
};
|
|
216
238
|
export type ResolveAllParamsFromParent<TParentRoute extends AnyRoute, TParams> = Assign<InferAllParams<TParentRoute>, TParams>;
|
|
217
239
|
export type RouteConstraints = {
|
|
218
240
|
TParentRoute: AnyRoute;
|
|
@@ -261,9 +283,9 @@ export declare class RouteApi<TId extends RouteIds<RegisteredRouter['routeTree']
|
|
|
261
283
|
useNavigate: () => UseNavigateResult<TRoute["fullPath"]>;
|
|
262
284
|
notFound: (opts?: NotFoundError) => NotFoundError;
|
|
263
285
|
}
|
|
264
|
-
export declare class Route<in out TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, in out TPath extends RouteConstraints['TPath'] = '/', in out TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, in out TCustomId extends RouteConstraints['TCustomId'] = string, in out TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, in out TSearchValidator extends AnySearchValidator = DefaultSearchValidator, in out TParams =
|
|
286
|
+
export declare class Route<in out TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, in out TPath extends RouteConstraints['TPath'] = '/', in out TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, in out TCustomId extends RouteConstraints['TCustomId'] = string, in out TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, in out TSearchValidator extends AnySearchValidator = DefaultSearchValidator, in out TParams = ResolveParams<TPath>, in out TAllParams = ResolveAllParamsFromParent<TParentRoute, TParams>, in out TRouterContext = AnyContext, in out TRouteContextFn = AnyContext, in out TBeforeLoadFn = AnyContext, in out TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, in out TLoaderData = ResolveLoaderData<TLoaderDataReturn>, in out TChildren = unknown> {
|
|
265
287
|
isRoot: TParentRoute extends Route<any> ? true : false;
|
|
266
|
-
options: RouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TAllParams,
|
|
288
|
+
options: RouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TAllParams, TLoaderDeps, TLoaderDataReturn, TLoaderData, TRouterContext, TRouteContextFn, TBeforeLoadFn>;
|
|
267
289
|
parentRoute: TParentRoute;
|
|
268
290
|
id: TId;
|
|
269
291
|
path: TPath;
|
|
@@ -278,7 +300,7 @@ export declare class Route<in out TParentRoute extends RouteConstraints['TParent
|
|
|
278
300
|
/**
|
|
279
301
|
* @deprecated Use the `createRoute` function instead.
|
|
280
302
|
*/
|
|
281
|
-
constructor(options?: RouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TAllParams,
|
|
303
|
+
constructor(options?: RouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TAllParams, TLoaderDeps, TLoaderDataReturn, TLoaderData, TRouterContext, TRouteContextFn, TBeforeLoadFn>);
|
|
282
304
|
types: {
|
|
283
305
|
parentRoute: TParentRoute;
|
|
284
306
|
path: TPath;
|
|
@@ -293,8 +315,11 @@ export declare class Route<in out TParentRoute extends RouteConstraints['TParent
|
|
|
293
315
|
fullSearchSchemaInput: ResolveFullSearchSchemaInput<TParentRoute, TSearchValidator>;
|
|
294
316
|
params: TParams;
|
|
295
317
|
allParams: TAllParams;
|
|
296
|
-
|
|
297
|
-
|
|
318
|
+
routerContext: TRouterContext;
|
|
319
|
+
routeContext: ResolveRouteContext<TRouteContextFn, TBeforeLoadFn>;
|
|
320
|
+
routeContextFn: TRouteContextFn;
|
|
321
|
+
beforeLoadFn: TBeforeLoadFn;
|
|
322
|
+
allContext: ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>;
|
|
298
323
|
children: TChildren;
|
|
299
324
|
loaderData: TLoaderData;
|
|
300
325
|
loaderDeps: TLoaderDeps;
|
|
@@ -302,17 +327,17 @@ export declare class Route<in out TParentRoute extends RouteConstraints['TParent
|
|
|
302
327
|
init: (opts: {
|
|
303
328
|
originalIndex: number;
|
|
304
329
|
}) => void;
|
|
305
|
-
addChildren<const TNewChildren extends Record<string, AnyRoute> | ReadonlyArray<AnyRoute>>(children: TNewChildren): Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TAllParams,
|
|
330
|
+
addChildren<const TNewChildren extends Record<string, AnyRoute> | ReadonlyArray<AnyRoute>>(children: TNewChildren): Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TAllParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, TNewChildren>;
|
|
306
331
|
updateLoader: <TNewLoaderData = unknown>(options: {
|
|
307
|
-
loader: RouteLoaderFn<
|
|
308
|
-
}) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TAllParams,
|
|
309
|
-
update: (options: UpdatableRouteOptions<TParentRoute, TCustomId, TAllParams, TSearchValidator, TLoaderData,
|
|
332
|
+
loader: RouteLoaderFn<TParentRoute, TParams, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn, TNewLoaderData>;
|
|
333
|
+
}) => Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TAllParams, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TNewLoaderData, TChildren>;
|
|
334
|
+
update: (options: UpdatableRouteOptions<TParentRoute, TCustomId, TAllParams, TSearchValidator, TLoaderData, TLoaderDeps, TRouterContext, TRouteContextFn, TBeforeLoadFn>) => this;
|
|
310
335
|
lazy: (lazyFn: () => Promise<LazyRoute<any>>) => this;
|
|
311
336
|
useMatch: <TRouter extends AnyRouter = AnyRouter, TRouteTree extends AnyRoute = TRouter["routeTree"], TRouteMatch = MakeRouteMatch<TRouteTree, TId>, TSelected = TRouteMatch>(opts?: {
|
|
312
337
|
select?: (match: TRouteMatch) => TSelected;
|
|
313
338
|
}) => TSelected;
|
|
314
|
-
useRouteContext: <TSelected = Expand<
|
|
315
|
-
select?: (search: Expand<
|
|
339
|
+
useRouteContext: <TSelected = Expand<Assign<Assign<RouteContextParameter<TParentRoute, TRouterContext>, ContextReturnType<TRouteContextFn>>, ContextAsyncReturnType<TBeforeLoadFn>>>>(opts?: {
|
|
340
|
+
select?: (search: Expand<ResolveAllContext<TParentRoute, TRouterContext, TRouteContextFn, TBeforeLoadFn>>) => TSelected;
|
|
316
341
|
}) => TSelected;
|
|
317
342
|
useSearch: <TSelected = Expand<ResolveFullSearchSchema<TParentRoute, TSearchValidator>>>(opts?: {
|
|
318
343
|
select?: (search: Expand<ResolveFullSearchSchema<TParentRoute, TSearchValidator>>) => TSelected;
|
|
@@ -328,25 +353,22 @@ export declare class Route<in out TParentRoute extends RouteConstraints['TParent
|
|
|
328
353
|
}) => TSelected;
|
|
329
354
|
useNavigate: () => UseNavigateResult<TFullPath>;
|
|
330
355
|
}
|
|
331
|
-
export declare function createRoute<TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, TPath extends RouteConstraints['TPath'] = '/', TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, TCustomId extends RouteConstraints['TCustomId'] = string, TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TParams =
|
|
356
|
+
export declare function createRoute<TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute, TPath extends RouteConstraints['TPath'] = '/', TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, TPath>, TCustomId extends RouteConstraints['TCustomId'] = string, TId extends RouteConstraints['TId'] = ResolveId<TParentRoute, TCustomId, TPath>, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TParams = ResolveParams<TPath>, TAllParams = ResolveAllParamsFromParent<TParentRoute, TParams>, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>, TChildren = unknown>(options: RouteOptions<TParentRoute, TCustomId, TPath, TSearchValidator, TParams, TAllParams, TLoaderDeps, TLoaderDataReturn, TLoaderData, AnyContext, TRouteContextFn, TBeforeLoadFn>): Route<TParentRoute, TPath, TFullPath, TCustomId, TId, TSearchValidator, TParams, TAllParams, AnyContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, TChildren>;
|
|
332
357
|
export type AnyRootRoute = RootRoute<any, any, any, any, any, any, any, any>;
|
|
333
|
-
export type RootRouteOptions<TSearchValidator extends AnySearchValidator = DefaultSearchValidator,
|
|
358
|
+
export type RootRouteOptions<TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>> = Omit<RouteOptions<any, // TParentRoute
|
|
334
359
|
RootRouteId, // TCustomId
|
|
335
360
|
'', // TPath
|
|
336
361
|
TSearchValidator, {}, // TParams
|
|
337
362
|
{}, // TAllParams
|
|
338
|
-
TRouteContextReturn, // TRouteContextReturn
|
|
339
|
-
TRouteContext, // TRouteContext
|
|
340
|
-
TRouterContext, // TParentAllContext
|
|
341
|
-
Assign<TRouterContext, TRouteContext>, // TAllContext
|
|
342
363
|
TLoaderDeps, TLoaderDataReturn, // TLoaderDataReturn,
|
|
343
|
-
TLoaderData
|
|
344
|
-
|
|
364
|
+
TLoaderData, // TLoaderData,
|
|
365
|
+
TRouterContext, TRouteContextFn, TBeforeLoadFn>, 'path' | 'id' | 'getParentRoute' | 'caseSensitive' | 'parseParams' | 'stringifyParams' | 'params'>;
|
|
366
|
+
export declare function createRootRouteWithContext<TRouterContext extends {}>(): <TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>>(options?: RootRouteOptions<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData>) => RootRoute<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderData, ResolveLoaderData<TLoaderData>, unknown>;
|
|
345
367
|
/**
|
|
346
368
|
* @deprecated Use the `createRootRouteWithContext` function instead.
|
|
347
369
|
*/
|
|
348
370
|
export declare const rootRouteWithContext: typeof createRootRouteWithContext;
|
|
349
|
-
export declare class RootRoute<in out TSearchValidator extends AnySearchValidator = DefaultSearchValidator,
|
|
371
|
+
export declare class RootRoute<in out TSearchValidator extends AnySearchValidator = DefaultSearchValidator, in out TRouterContext = {}, in out TRouteContextFn = AnyContext, in out TBeforeLoadFn = AnyContext, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, in out TLoaderData = ResolveLoaderData<TLoaderDataReturn>, TChildren = unknown> extends Route<any, // TParentRoute
|
|
350
372
|
'/', // TPath
|
|
351
373
|
'/', // TFullPath
|
|
352
374
|
string, // TCustomId
|
|
@@ -354,17 +376,14 @@ RootRouteId, // TId
|
|
|
354
376
|
TSearchValidator, // TSearchValidator
|
|
355
377
|
{}, // TParams
|
|
356
378
|
{}, // TAllParams
|
|
357
|
-
|
|
358
|
-
TRouteContext, // TRouteContext
|
|
359
|
-
Assign<TRouterContext, TRouteContext>, // TAllContext
|
|
360
|
-
TLoaderDeps, TLoaderDataReturn, TLoaderData, TChildren> {
|
|
379
|
+
TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, TChildren> {
|
|
361
380
|
/**
|
|
362
381
|
* @deprecated `RootRoute` is now an internal implementation detail. Use `createRootRoute()` instead.
|
|
363
382
|
*/
|
|
364
|
-
constructor(options?: RootRouteOptions<TSearchValidator,
|
|
365
|
-
addChildren<const TNewChildren extends Record<string, AnyRoute> | ReadonlyArray<AnyRoute>>(children: TNewChildren): RootRoute<TSearchValidator,
|
|
383
|
+
constructor(options?: RootRouteOptions<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData>);
|
|
384
|
+
addChildren<const TNewChildren extends Record<string, AnyRoute> | ReadonlyArray<AnyRoute>>(children: TNewChildren): RootRoute<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, TNewChildren>;
|
|
366
385
|
}
|
|
367
|
-
export declare function createRootRoute<TSearchValidator extends AnySearchValidator = DefaultSearchValidator,
|
|
386
|
+
export declare function createRootRoute<TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TRouterContext = {}, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>>(options?: RootRouteOptions<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData>): RootRoute<TSearchValidator, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, unknown>;
|
|
368
387
|
export type ResolveFullPath<TParentRoute extends AnyRoute, TPath extends string, TPrefixed = RoutePrefix<TParentRoute['fullPath'], TPath>> = TPrefixed extends RootRouteId ? '/' : TPrefixed;
|
|
369
388
|
type RoutePrefix<TPrefix extends string, TPath extends string> = string extends TPath ? RootRouteId : TPath extends string ? TPrefix extends RootRouteId ? TPath extends '/' ? '/' : `/${TrimPath<TPath>}` : `${TPrefix}/${TPath}` extends '/' ? '/' : `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TPath>}`>}` : never;
|
|
370
389
|
export type TrimPath<T extends string> = '' extends T ? '' : TrimPathRight<TrimPathLeft<T>>;
|
|
@@ -411,7 +430,7 @@ export type AsyncRouteComponent<TProps> = SyncRouteComponent<TProps> & {
|
|
|
411
430
|
export type RouteComponent<TProps = any> = AsyncRouteComponent<TProps>;
|
|
412
431
|
export type ErrorRouteComponent = RouteComponent<ErrorComponentProps>;
|
|
413
432
|
export type NotFoundRouteComponent = SyncRouteComponent<NotFoundRouteProps>;
|
|
414
|
-
export declare class NotFoundRoute<TParentRoute extends AnyRootRoute,
|
|
415
|
-
constructor(options: Omit<RouteOptions<TParentRoute, string, string, TSearchValidator, {}, {},
|
|
433
|
+
export declare class NotFoundRoute<TParentRoute extends AnyRootRoute, TRouterContext = AnyContext, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TSearchValidator extends AnySearchValidator = DefaultSearchValidator, TLoaderDeps extends Record<string, any> = {}, TLoaderDataReturn = {}, TLoaderData = ResolveLoaderData<TLoaderDataReturn>, TChildren = unknown> extends Route<TParentRoute, '/404', '/404', '404', '404', TSearchValidator, {}, {}, TRouterContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderDataReturn, TLoaderData, TChildren> {
|
|
434
|
+
constructor(options: Omit<RouteOptions<TParentRoute, string, string, TSearchValidator, {}, {}, TLoaderDeps, TLoaderDataReturn, TLoaderData, TRouterContext, TRouteContextFn, TBeforeLoadFn>, 'caseSensitive' | 'parseParams' | 'stringifyParams' | 'path' | 'id' | 'params'>);
|
|
416
435
|
}
|
|
417
436
|
export {};
|