@tanstack/react-router 1.78.3 → 1.81.0
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/Match.cjs +10 -11
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +8 -4
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +8 -9
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/RouterProvider.d.cts +3 -3
- package/dist/cjs/Transitioner.cjs +9 -8
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/fileRoute.cjs +15 -3
- package/dist/cjs/fileRoute.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +12 -19
- package/dist/cjs/link.cjs +4 -1
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +1 -1
- package/dist/cjs/path.cjs +12 -2
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +2 -1
- package/dist/cjs/route.cjs +33 -9
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +20 -38
- package/dist/cjs/router.cjs +15 -4
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +25 -11
- package/dist/cjs/routerContext.cjs.map +1 -1
- package/dist/cjs/routerContext.d.cts +1 -1
- package/dist/cjs/structuralSharing.d.cts +12 -0
- package/dist/cjs/useLoaderData.cjs +4 -2
- package/dist/cjs/useLoaderData.cjs.map +1 -1
- package/dist/cjs/useLoaderData.d.cts +12 -9
- package/dist/cjs/useLoaderDeps.cjs +3 -2
- package/dist/cjs/useLoaderDeps.cjs.map +1 -1
- package/dist/cjs/useLoaderDeps.d.cts +12 -8
- package/dist/cjs/useLocation.cjs.map +1 -1
- package/dist/cjs/useLocation.d.cts +6 -3
- package/dist/cjs/useMatch.cjs +2 -1
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/useMatch.d.cts +10 -8
- package/dist/cjs/useParams.cjs +3 -1
- package/dist/cjs/useParams.cjs.map +1 -1
- package/dist/cjs/useParams.d.cts +12 -8
- package/dist/cjs/useRouteContext.cjs.map +1 -1
- package/dist/cjs/useRouteContext.d.cts +11 -8
- package/dist/cjs/useRouterState.cjs +18 -1
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/cjs/useRouterState.d.cts +6 -3
- package/dist/cjs/useSearch.cjs +3 -1
- package/dist/cjs/useSearch.cjs.map +1 -1
- package/dist/cjs/useSearch.d.cts +12 -8
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +10 -4
- package/dist/esm/Match.js +10 -11
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.d.ts +8 -9
- package/dist/esm/Matches.js +8 -4
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +3 -3
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/Transitioner.js +10 -9
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/fileRoute.d.ts +12 -19
- package/dist/esm/fileRoute.js +15 -3
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/link.d.ts +1 -1
- package/dist/esm/link.js +4 -1
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/path.d.ts +2 -1
- package/dist/esm/path.js +12 -2
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/route.d.ts +20 -38
- package/dist/esm/route.js +33 -9
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +25 -11
- package/dist/esm/router.js +15 -4
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/routerContext.d.ts +1 -1
- package/dist/esm/routerContext.js.map +1 -1
- package/dist/esm/structuralSharing.d.ts +12 -0
- package/dist/esm/useLoaderData.d.ts +12 -9
- package/dist/esm/useLoaderData.js +4 -2
- package/dist/esm/useLoaderData.js.map +1 -1
- package/dist/esm/useLoaderDeps.d.ts +12 -8
- package/dist/esm/useLoaderDeps.js +3 -2
- package/dist/esm/useLoaderDeps.js.map +1 -1
- package/dist/esm/useLocation.d.ts +6 -3
- package/dist/esm/useLocation.js.map +1 -1
- package/dist/esm/useMatch.d.ts +10 -8
- package/dist/esm/useMatch.js +2 -1
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useParams.d.ts +12 -8
- package/dist/esm/useParams.js +3 -1
- package/dist/esm/useParams.js.map +1 -1
- package/dist/esm/useRouteContext.d.ts +11 -8
- package/dist/esm/useRouteContext.js.map +1 -1
- package/dist/esm/useRouterState.d.ts +6 -3
- package/dist/esm/useRouterState.js +18 -1
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/esm/useSearch.d.ts +12 -8
- package/dist/esm/useSearch.js +3 -1
- package/dist/esm/useSearch.js.map +1 -1
- package/dist/esm/utils.d.ts +10 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/Match.tsx +6 -7
- package/src/Matches.tsx +52 -24
- package/src/RouterProvider.tsx +4 -1
- package/src/Transitioner.tsx +9 -10
- package/src/fileRoute.ts +29 -29
- package/src/link.tsx +6 -3
- package/src/path.ts +16 -1
- package/src/route.ts +57 -101
- package/src/router.ts +60 -4
- package/src/routerContext.tsx +1 -1
- package/src/structuralSharing.ts +49 -0
- package/src/useLoaderData.tsx +76 -28
- package/src/useLoaderDeps.tsx +55 -20
- package/src/useLocation.tsx +30 -8
- package/src/useMatch.tsx +71 -21
- package/src/useParams.tsx +70 -21
- package/src/useRouteContext.ts +45 -23
- package/src/useRouterState.tsx +45 -6
- package/src/useSearch.tsx +69 -20
- package/src/utils.ts +16 -3
package/dist/cjs/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\n\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\nexport type PickOptional<T> = {\n [K in keyof T as undefined extends T[K] ? K : never]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\n// export type Expand<T> = T\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = Omit<\n TRight,\n keyof TLeft\n> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n}\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type Assign<TLeft, TRight> = keyof TLeft extends never\n ? TRight\n : keyof TRight extends never\n ? TLeft\n : keyof TLeft & keyof TRight extends never\n ? TLeft & TRight\n : Omit<TLeft, keyof TRight> & TRight\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\nexport type MergeUnionObjects<TUnion> = TUnion extends MergeUnionPrimitive\n ? never\n : TUnion\n\nexport type MergeUnionObject<TUnion> =\n MergeUnionObjects<TUnion> extends infer TObj\n ? {\n [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any\n ? TKey extends keyof TObj\n ? TObj[TKey]\n : never\n : never\n }\n : never\n\nexport type MergeUnionPrimitive =\n | ReadonlyArray<any>\n | number\n | string\n | bigint\n | boolean\n | symbol\n\nexport type MergeUnionPrimitives<TUnion> = TUnion extends MergeUnionPrimitive\n ? TUnion\n : TUnion extends object\n ? never\n : TUnion\n\nexport type MergeUnion<TUnion> =\n | MergeUnionPrimitives<TUnion>\n | MergeUnionObject<TUnion>\n\nexport type Constrain<T, TConstaint, TDefault = TConstaint> =\n | (T extends TConstaint ? T : never)\n | TDefault\n\nexport function last<T>(arr: Array<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\nexport function functionalUpdate<TResult>(\n updater: Updater<TResult> | NonNullableUpdater<TResult>,\n previous: TResult,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nexport function pick<TValue, TKey extends keyof TValue>(\n parent: TValue,\n keys: Array<TKey>,\n): Pick<TValue, TKey> {\n return keys.reduce((obj: any, key: TKey) => {\n obj[key] = parent[key]\n return obj\n }, {} as any)\n}\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T): T {\n if (prev === _next) {\n return prev\n }\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (array || (isPlainObject(prev) && isPlainObject(next))) {\n const prevItems = array ? prev : Object.keys(prev)\n const prevSize = prevItems.length\n const nextItems = array ? next : Object.keys(next)\n const nextSize = nextItems.length\n const copy: any = array ? [] : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : (nextItems[i] as any)\n if (\n ((!array && prevItems.includes(key)) || array) &&\n prev[key] === undefined &&\n next[key] === undefined\n ) {\n copy[key] = undefined\n equalItems++\n } else {\n copy[key] = replaceEqualDeep(prev[key], next[key])\n if (copy[key] === prev[key] && prev[key] !== undefined) {\n equalItems++\n }\n }\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n }\n\n return next\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\nexport function isPlainArray(value: unknown): value is Array<unknown> {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nfunction getObjectKeys(obj: any, ignoreUndefined: boolean) {\n let keys = Object.keys(obj)\n if (ignoreUndefined) {\n keys = keys.filter((key) => obj[key] !== undefined)\n }\n return keys\n}\n\nexport function deepEqual(\n a: any,\n b: any,\n opts?: { partial?: boolean; ignoreUndefined?: boolean },\n): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const ignoreUndefined = opts?.ignoreUndefined ?? true\n const aKeys = getObjectKeys(a, ignoreUndefined)\n const bKeys = getObjectKeys(b, ignoreUndefined)\n\n if (!opts?.partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return bKeys.every((key) => deepEqual(a[key], b[key], opts))\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n return !a.some((item, index) => !deepEqual(item, b[index], opts))\n }\n\n return false\n}\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (const item of keysA) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, item) ||\n !Object.is(objA[item as keyof T], objB[item as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type StrictOrFrom<\n TFrom,\n TStrict extends boolean = true,\n> = TStrict extends false\n ? {\n from?: never\n strict: TStrict\n }\n : {\n from: StringLiteral<TFrom> | TFrom\n strict?: TStrict\n }\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n *\n * @deprecated use `jsesc` instead\n */\nexport function escapeJSON(jsonString: string) {\n return jsonString\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n .replace(/'/g, \"\\\\'\") // Escape single quotes\n .replace(/\"/g, '\\\\\"') // Escape double quotes\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n value?: T\n}\n\nexport function createControlledPromise<T>(onResolve?: (value: T) => void) {\n let resolveLoadPromise!: (value: T) => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<T>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = (value: T) => {\n controlledPromise.status = 'resolved'\n controlledPromise.value = value\n resolveLoadPromise(value)\n onResolve?.(value)\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n\n/**\n * React hook to wrap `IntersectionObserver`.\n *\n * This hook will create an `IntersectionObserver` and observe the ref passed to it.\n *\n * When the intersection changes, the callback will be called with the `IntersectionObserverEntry`.\n *\n * @param ref - The ref to observe\n * @param intersectionObserverOptions - The options to pass to the IntersectionObserver\n * @param options - The options to pass to the hook\n * @param callback - The callback to call when the intersection changes\n * @returns The IntersectionObserver instance\n * @example\n * ```tsx\n * const MyComponent = () => {\n * const ref = React.useRef<HTMLDivElement>(null)\n * useIntersectionObserver(\n * ref,\n * (entry) => { doSomething(entry) },\n * { rootMargin: '10px' },\n * { disabled: false }\n * )\n * return <div ref={ref} />\n * ```\n */\nexport function useIntersectionObserver<T extends Element>(\n ref: React.RefObject<T>,\n callback: (entry: IntersectionObserverEntry | undefined) => void,\n intersectionObserverOptions: IntersectionObserverInit = {},\n options: { disabled?: boolean } = {},\n): IntersectionObserver | null {\n const isIntersectionObserverAvailable = React.useRef(\n typeof IntersectionObserver === 'function',\n )\n\n const observerRef = React.useRef<IntersectionObserver | null>(null)\n\n React.useEffect(() => {\n if (\n !ref.current ||\n !isIntersectionObserverAvailable.current ||\n options.disabled\n ) {\n return\n }\n\n observerRef.current = new IntersectionObserver(([entry]) => {\n callback(entry)\n }, intersectionObserverOptions)\n\n observerRef.current.observe(ref.current)\n\n return () => {\n observerRef.current?.disconnect()\n }\n }, [callback, intersectionObserverOptions, options.disabled, ref])\n\n return observerRef.current\n}\n\n/**\n * React hook to take a `React.ForwardedRef` and returns a `ref` that can be used on a DOM element.\n *\n * @param ref - The forwarded ref\n * @returns The inner ref returned by `useRef`\n * @example\n * ```tsx\n * const MyComponent = React.forwardRef((props, ref) => {\n * const innerRef = useForwardedRef(ref)\n * return <div ref={innerRef} />\n * })\n * ```\n */\nexport function useForwardedRef<T>(ref?: React.ForwardedRef<T>) {\n const innerRef = React.useRef<T>(null)\n\n React.useEffect(() => {\n if (!ref) return\n if (typeof ref === 'function') {\n ref(innerRef.current)\n } else {\n ref.current = innerRef.current\n }\n })\n\n return innerRef\n}\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\nimport type { RouteIds } from './routeInfo'\nimport type { AnyRouter } from './router'\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\nexport type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue\n ? TYesResult\n : TNoResult\n\nexport type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<\n TValue,\n TKey\n> &\n Required<Pick<TValue, TKey>>\n\nexport type PickRequired<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n}\n\nexport type PickOptional<T> = {\n [K in keyof T as undefined extends T[K] ? K : never]: T[K]\n}\n\n// from https://stackoverflow.com/a/76458160\nexport type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never\n\n// export type Expand<T> = T\nexport type Expand<T> = T extends object\n ? T extends infer O\n ? O extends Function\n ? O\n : { [K in keyof O]: O[K] }\n : never\n : T\n\nexport type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>\n }\n : T\n\nexport type MakeDifferenceOptional<TLeft, TRight> = Omit<\n TRight,\n keyof TLeft\n> & {\n [K in keyof TLeft & keyof TRight]?: TRight[K]\n}\n\n// from https://stackoverflow.com/a/53955431\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type IsUnion<T, U extends T = T> = (\n T extends any ? (U extends T ? false : true) : never\n) extends false\n ? false\n : true\n\nexport type Assign<TLeft, TRight> = keyof TLeft extends never\n ? TRight\n : keyof TRight extends never\n ? TLeft\n : keyof TLeft & keyof TRight extends never\n ? TLeft & TRight\n : Omit<TLeft, keyof TRight> & TRight\n\nexport type Timeout = ReturnType<typeof setTimeout>\n\nexport type Updater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev?: TPrevious) => TResult)\n\nexport type NonNullableUpdater<TPrevious, TResult = TPrevious> =\n | TResult\n | ((prev: TPrevious) => TResult)\n\nexport type MergeUnionObjects<TUnion> = TUnion extends MergeUnionPrimitive\n ? never\n : TUnion\n\nexport type MergeUnionObject<TUnion> =\n MergeUnionObjects<TUnion> extends infer TObj\n ? {\n [TKey in TObj extends any ? keyof TObj : never]?: TObj extends any\n ? TKey extends keyof TObj\n ? TObj[TKey]\n : never\n : never\n }\n : never\n\nexport type MergeUnionPrimitive =\n | ReadonlyArray<any>\n | number\n | string\n | bigint\n | boolean\n | symbol\n\nexport type MergeUnionPrimitives<TUnion> = TUnion extends MergeUnionPrimitive\n ? TUnion\n : TUnion extends object\n ? never\n : TUnion\n\nexport type MergeUnion<TUnion> =\n | MergeUnionPrimitives<TUnion>\n | MergeUnionObject<TUnion>\n\nexport type Constrain<T, TConstraint, TDefault = TConstraint> =\n | (T extends TConstraint ? T : never)\n | TDefault\n\nexport type ValidateJSON<T> = ((...args: Array<any>) => any) extends T\n ? unknown extends T\n ? never\n : 'Function is not serializable'\n : { [K in keyof T]: ValidateJSON<T[K]> }\n\nexport function last<T>(arr: Array<T>) {\n return arr[arr.length - 1]\n}\n\nfunction isFunction(d: any): d is Function {\n return typeof d === 'function'\n}\n\nexport function functionalUpdate<TResult>(\n updater: Updater<TResult> | NonNullableUpdater<TResult>,\n previous: TResult,\n): TResult {\n if (isFunction(updater)) {\n return updater(previous)\n }\n\n return updater\n}\n\nexport function pick<TValue, TKey extends keyof TValue>(\n parent: TValue,\n keys: Array<TKey>,\n): Pick<TValue, TKey> {\n return keys.reduce((obj: any, key: TKey) => {\n obj[key] = parent[key]\n return obj\n }, {} as any)\n}\n\n/**\n * This function returns `prev` if `_next` is deeply equal.\n * If not, it will replace any deeply equal children of `b` with those of `a`.\n * This can be used for structural sharing between immutable JSON values for example.\n * Do not use this with signals\n */\nexport function replaceEqualDeep<T>(prev: any, _next: T): T {\n if (prev === _next) {\n return prev\n }\n\n const next = _next as any\n\n const array = isPlainArray(prev) && isPlainArray(next)\n\n if (array || (isPlainObject(prev) && isPlainObject(next))) {\n const prevItems = array ? prev : Object.keys(prev)\n const prevSize = prevItems.length\n const nextItems = array ? next : Object.keys(next)\n const nextSize = nextItems.length\n const copy: any = array ? [] : {}\n\n let equalItems = 0\n\n for (let i = 0; i < nextSize; i++) {\n const key = array ? i : (nextItems[i] as any)\n if (\n ((!array && prevItems.includes(key)) || array) &&\n prev[key] === undefined &&\n next[key] === undefined\n ) {\n copy[key] = undefined\n equalItems++\n } else {\n copy[key] = replaceEqualDeep(prev[key], next[key])\n if (copy[key] === prev[key] && prev[key] !== undefined) {\n equalItems++\n }\n }\n }\n\n return prevSize === nextSize && equalItems === prevSize ? prev : copy\n }\n\n return next\n}\n\n// Copied from: https://github.com/jonschlinkert/is-plain-object\nexport function isPlainObject(o: any) {\n if (!hasObjectPrototype(o)) {\n return false\n }\n\n // If has modified constructor\n const ctor = o.constructor\n if (typeof ctor === 'undefined') {\n return true\n }\n\n // If has modified prototype\n const prot = ctor.prototype\n if (!hasObjectPrototype(prot)) {\n return false\n }\n\n // If constructor does not have an Object-specific method\n if (!prot.hasOwnProperty('isPrototypeOf')) {\n return false\n }\n\n // Most likely a plain Object\n return true\n}\n\nfunction hasObjectPrototype(o: any) {\n return Object.prototype.toString.call(o) === '[object Object]'\n}\n\nexport function isPlainArray(value: unknown): value is Array<unknown> {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nfunction getObjectKeys(obj: any, ignoreUndefined: boolean) {\n let keys = Object.keys(obj)\n if (ignoreUndefined) {\n keys = keys.filter((key) => obj[key] !== undefined)\n }\n return keys\n}\n\nexport function deepEqual(\n a: any,\n b: any,\n opts?: { partial?: boolean; ignoreUndefined?: boolean },\n): boolean {\n if (a === b) {\n return true\n }\n\n if (typeof a !== typeof b) {\n return false\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n const ignoreUndefined = opts?.ignoreUndefined ?? true\n const aKeys = getObjectKeys(a, ignoreUndefined)\n const bKeys = getObjectKeys(b, ignoreUndefined)\n\n if (!opts?.partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return bKeys.every((key) => deepEqual(a[key], b[key], opts))\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false\n }\n return !a.some((item, index) => !deepEqual(item, b[index], opts))\n }\n\n return false\n}\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (const item of keysA) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, item) ||\n !Object.is(objA[item as keyof T], objB[item as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n\nexport type StringLiteral<T> = T extends string\n ? string extends T\n ? string\n : T\n : never\n\nexport type StrictOrFrom<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean = true,\n> = TStrict extends false\n ? {\n from?: never\n strict: TStrict\n }\n : {\n from: StringLiteral<Constrain<TFrom, RouteIds<TRouter['routeTree']>>>\n strict?: TStrict\n }\n\nexport type ThrowOrOptional<T, TThrow extends boolean> = TThrow extends true\n ? T\n : T | undefined\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n *\n * @deprecated use `jsesc` instead\n */\nexport function escapeJSON(jsonString: string) {\n return jsonString\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n .replace(/'/g, \"\\\\'\") // Escape single quotes\n .replace(/\"/g, '\\\\\"') // Escape double quotes\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n value?: T\n}\n\nexport function createControlledPromise<T>(onResolve?: (value: T) => void) {\n let resolveLoadPromise!: (value: T) => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<T>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = (value: T) => {\n controlledPromise.status = 'resolved'\n controlledPromise.value = value\n resolveLoadPromise(value)\n onResolve?.(value)\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n\n/**\n * React hook to wrap `IntersectionObserver`.\n *\n * This hook will create an `IntersectionObserver` and observe the ref passed to it.\n *\n * When the intersection changes, the callback will be called with the `IntersectionObserverEntry`.\n *\n * @param ref - The ref to observe\n * @param intersectionObserverOptions - The options to pass to the IntersectionObserver\n * @param options - The options to pass to the hook\n * @param callback - The callback to call when the intersection changes\n * @returns The IntersectionObserver instance\n * @example\n * ```tsx\n * const MyComponent = () => {\n * const ref = React.useRef<HTMLDivElement>(null)\n * useIntersectionObserver(\n * ref,\n * (entry) => { doSomething(entry) },\n * { rootMargin: '10px' },\n * { disabled: false }\n * )\n * return <div ref={ref} />\n * ```\n */\nexport function useIntersectionObserver<T extends Element>(\n ref: React.RefObject<T>,\n callback: (entry: IntersectionObserverEntry | undefined) => void,\n intersectionObserverOptions: IntersectionObserverInit = {},\n options: { disabled?: boolean } = {},\n): IntersectionObserver | null {\n const isIntersectionObserverAvailable = React.useRef(\n typeof IntersectionObserver === 'function',\n )\n\n const observerRef = React.useRef<IntersectionObserver | null>(null)\n\n React.useEffect(() => {\n if (\n !ref.current ||\n !isIntersectionObserverAvailable.current ||\n options.disabled\n ) {\n return\n }\n\n observerRef.current = new IntersectionObserver(([entry]) => {\n callback(entry)\n }, intersectionObserverOptions)\n\n observerRef.current.observe(ref.current)\n\n return () => {\n observerRef.current?.disconnect()\n }\n }, [callback, intersectionObserverOptions, options.disabled, ref])\n\n return observerRef.current\n}\n\n/**\n * React hook to take a `React.ForwardedRef` and returns a `ref` that can be used on a DOM element.\n *\n * @param ref - The forwarded ref\n * @returns The inner ref returned by `useRef`\n * @example\n * ```tsx\n * const MyComponent = React.forwardRef((props, ref) => {\n * const innerRef = useForwardedRef(ref)\n * return <div ref={innerRef} />\n * })\n * ```\n */\nexport function useForwardedRef<T>(ref?: React.ForwardedRef<T>) {\n const innerRef = React.useRef<T>(null)\n\n React.useEffect(() => {\n if (!ref) return\n if (typeof ref === 'function') {\n ref(innerRef.current)\n } else {\n ref.current = innerRef.current\n }\n })\n\n return innerRef\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqHO,SAAS,KAAQ,KAAe;AAC9B,SAAA,IAAI,IAAI,SAAS,CAAC;AAC3B;AAEA,SAAS,WAAW,GAAuB;AACzC,SAAO,OAAO,MAAM;AACtB;AAEgB,SAAA,iBACd,SACA,UACS;AACL,MAAA,WAAW,OAAO,GAAG;AACvB,WAAO,QAAQ,QAAQ;AAAA,EAAA;AAGlB,SAAA;AACT;AAEgB,SAAA,KACd,QACA,MACoB;AACpB,SAAO,KAAK,OAAO,CAAC,KAAU,QAAc;AACtC,QAAA,GAAG,IAAI,OAAO,GAAG;AACd,WAAA;AAAA,EACT,GAAG,EAAS;AACd;AAQgB,SAAA,iBAAoB,MAAW,OAAa;AAC1D,MAAI,SAAS,OAAO;AACX,WAAA;AAAA,EAAA;AAGT,QAAM,OAAO;AAEb,QAAM,QAAQ,aAAa,IAAI,KAAK,aAAa,IAAI;AAErD,MAAI,SAAU,cAAc,IAAI,KAAK,cAAc,IAAI,GAAI;AACzD,UAAM,YAAY,QAAQ,OAAO,OAAO,KAAK,IAAI;AACjD,UAAM,WAAW,UAAU;AAC3B,UAAM,YAAY,QAAQ,OAAO,OAAO,KAAK,IAAI;AACjD,UAAM,WAAW,UAAU;AAC3B,UAAM,OAAY,QAAQ,CAAA,IAAK,CAAC;AAEhC,QAAI,aAAa;AAEjB,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAM,MAAM,QAAQ,IAAK,UAAU,CAAC;AACpC,WACI,CAAC,SAAS,UAAU,SAAS,GAAG,KAAM,UACxC,KAAK,GAAG,MAAM,UACd,KAAK,GAAG,MAAM,QACd;AACA,aAAK,GAAG,IAAI;AACZ;AAAA,MAAA,OACK;AACA,aAAA,GAAG,IAAI,iBAAiB,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AAC7C,YAAA,KAAK,GAAG,MAAM,KAAK,GAAG,KAAK,KAAK,GAAG,MAAM,QAAW;AACtD;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAGF,WAAO,aAAa,YAAY,eAAe,WAAW,OAAO;AAAA,EAAA;AAG5D,SAAA;AACT;AAGO,SAAS,cAAc,GAAQ;AAChC,MAAA,CAAC,mBAAmB,CAAC,GAAG;AACnB,WAAA;AAAA,EAAA;AAIT,QAAM,OAAO,EAAE;AACX,MAAA,OAAO,SAAS,aAAa;AACxB,WAAA;AAAA,EAAA;AAIT,QAAM,OAAO,KAAK;AACd,MAAA,CAAC,mBAAmB,IAAI,GAAG;AACtB,WAAA;AAAA,EAAA;AAIT,MAAI,CAAC,KAAK,eAAe,eAAe,GAAG;AAClC,WAAA;AAAA,EAAA;AAIF,SAAA;AACT;AAEA,SAAS,mBAAmB,GAAQ;AAClC,SAAO,OAAO,UAAU,SAAS,KAAK,CAAC,MAAM;AAC/C;AAEO,SAAS,aAAa,OAAyC;AAC7D,SAAA,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,OAAO,KAAK,KAAK,EAAE;AACrE;AAEA,SAAS,cAAc,KAAU,iBAA0B;AACrD,MAAA,OAAO,OAAO,KAAK,GAAG;AAC1B,MAAI,iBAAiB;AACnB,WAAO,KAAK,OAAO,CAAC,QAAQ,IAAI,GAAG,MAAM,MAAS;AAAA,EAAA;AAE7C,SAAA;AACT;AAEgB,SAAA,UACd,GACA,GACA,MACS;AACT,MAAI,MAAM,GAAG;AACJ,WAAA;AAAA,EAAA;AAGL,MAAA,OAAO,MAAM,OAAO,GAAG;AAClB,WAAA;AAAA,EAAA;AAGT,MAAI,cAAc,CAAC,KAAK,cAAc,CAAC,GAAG;AAClC,UAAA,mBAAkB,6BAAM,oBAAmB;AAC3C,UAAA,QAAQ,cAAc,GAAG,eAAe;AACxC,UAAA,QAAQ,cAAc,GAAG,eAAe;AAE9C,QAAI,EAAC,6BAAM,YAAW,MAAM,WAAW,MAAM,QAAQ;AAC5C,aAAA;AAAA,IAAA;AAGT,WAAO,MAAM,MAAM,CAAC,QAAQ,UAAU,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;AAAA,EAAA;AAG7D,MAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;AACpC,QAAA,EAAE,WAAW,EAAE,QAAQ;AAClB,aAAA;AAAA,IAAA;AAET,WAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAU,CAAC,UAAU,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;AAAA,EAAA;AAG3D,SAAA;AACT;AAEO,SAAS,kBACd,IACG;AACG,QAAA,QAAQA,iBAAM,OAAO,EAAE;AAC7B,QAAM,UAAU;AAEV,QAAA,MAAMA,iBAAM,OAAO,IAAI,SAAqB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACxE,SAAO,IAAI;AACb;AAEgB,SAAA,QAAW,MAAS,MAAS;AAC3C,MAAI,OAAO,GAAG,MAAM,IAAI,GAAG;AAClB,WAAA;AAAA,EAAA;AAIP,MAAA,OAAO,SAAS,YAChB,SAAS,QACT,OAAO,SAAS,YAChB,SAAS,MACT;AACO,WAAA;AAAA,EAAA;AAGH,QAAA,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,OAAO,KAAK,IAAI,EAAE,QAAQ;AACtC,WAAA;AAAA,EAAA;AAGT,aAAW,QAAQ,OAAO;AACxB,QACE,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,KAChD,CAAC,OAAO,GAAG,KAAK,IAAe,GAAG,KAAK,IAAe,CAAC,GACvD;AACO,aAAA;AAAA,IAAA;AAAA,EACT;AAEK,SAAA;AACT;AA0BO,MAAM,kBACX,OAAO,WAAW,cAAcA,iBAAM,kBAAkBA,iBAAM;AAMzD,SAAS,WAAW,YAAoB;AACtC,SAAA,WACJ,QAAQ,OAAO,MAAM,EACrB,QAAQ,MAAM,KAAK,EACnB,QAAQ,MAAM,KAAK;AACxB;AASO,SAAS,wBAA2B,WAAgC;AACrE,MAAA;AACA,MAAA;AAEJ,QAAM,oBAAoB,IAAI,QAAW,CAAC,SAAS,WAAW;AACvC,yBAAA;AACD,wBAAA;AAAA,EAAA,CACrB;AAED,oBAAkB,SAAS;AAET,oBAAA,UAAU,CAAC,UAAa;AACxC,sBAAkB,SAAS;AAC3B,sBAAkB,QAAQ;AAC1B,uBAAmB,KAAK;AACxB,2CAAY;AAAA,EACd;AAEkB,oBAAA,SAAS,CAAC,MAAM;AAChC,sBAAkB,SAAS;AAC3B,sBAAkB,CAAC;AAAA,EACrB;AAEO,SAAA;AACT;AAKO,SAAS,YAAe,OAAoB;AAE3C,QAAA,MAAMA,iBAAM,OAAqC;AAAA,IACrD;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AAEK,QAAA,UAAU,IAAI,QAAQ;AAK5B,MAAI,UAAU,SAAS;AACrB,QAAI,UAAU;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EAAA;AAIF,SAAO,IAAI,QAAQ;AACrB;AA2BgB,SAAA,wBACd,KACA,UACA,8BAAwD,CACxD,GAAA,UAAkC,IACL;AAC7B,QAAM,kCAAkCA,iBAAM;AAAA,IAC5C,OAAO,yBAAyB;AAAA,EAClC;AAEM,QAAA,cAAcA,iBAAM,OAAoC,IAAI;AAElEA,mBAAM,UAAU,MAAM;AACpB,QACE,CAAC,IAAI,WACL,CAAC,gCAAgC,WACjC,QAAQ,UACR;AACA;AAAA,IAAA;AAGF,gBAAY,UAAU,IAAI,qBAAqB,CAAC,CAAC,KAAK,MAAM;AAC1D,eAAS,KAAK;AAAA,OACb,2BAA2B;AAElB,gBAAA,QAAQ,QAAQ,IAAI,OAAO;AAEvC,WAAO,MAAM;;AACX,wBAAY,YAAZ,mBAAqB;AAAA,IACvB;AAAA,EAAA,GACC,CAAC,UAAU,6BAA6B,QAAQ,UAAU,GAAG,CAAC;AAEjE,SAAO,YAAY;AACrB;AAeO,SAAS,gBAAmB,KAA6B;AACxD,QAAA,WAAWA,iBAAM,OAAU,IAAI;AAErCA,mBAAM,UAAU,MAAM;AACpB,QAAI,CAAC,IAAK;AACN,QAAA,OAAO,QAAQ,YAAY;AAC7B,UAAI,SAAS,OAAO;AAAA,IAAA,OACf;AACL,UAAI,UAAU,SAAS;AAAA,IAAA;AAAA,EACzB,CACD;AAEM,SAAA;AACT;;;;;;;;;;;;;;;;"}
|
package/dist/cjs/utils.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RouteIds } from './routeInfo.cjs';
|
|
2
|
+
import { AnyRouter } from './router.cjs';
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
export type NoInfer<T> = [T][T extends any ? 0 : never];
|
|
3
5
|
export type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue ? TYesResult : TNoResult;
|
|
@@ -30,7 +32,10 @@ export type MergeUnionObject<TUnion> = MergeUnionObjects<TUnion> extends infer T
|
|
|
30
32
|
export type MergeUnionPrimitive = ReadonlyArray<any> | number | string | bigint | boolean | symbol;
|
|
31
33
|
export type MergeUnionPrimitives<TUnion> = TUnion extends MergeUnionPrimitive ? TUnion : TUnion extends object ? never : TUnion;
|
|
32
34
|
export type MergeUnion<TUnion> = MergeUnionPrimitives<TUnion> | MergeUnionObject<TUnion>;
|
|
33
|
-
export type Constrain<T,
|
|
35
|
+
export type Constrain<T, TConstraint, TDefault = TConstraint> = (T extends TConstraint ? T : never) | TDefault;
|
|
36
|
+
export type ValidateJSON<T> = ((...args: Array<any>) => any) extends T ? unknown extends T ? never : 'Function is not serializable' : {
|
|
37
|
+
[K in keyof T]: ValidateJSON<T[K]>;
|
|
38
|
+
};
|
|
34
39
|
export declare function last<T>(arr: Array<T>): T | undefined;
|
|
35
40
|
export declare function functionalUpdate<TResult>(updater: Updater<TResult> | NonNullableUpdater<TResult>, previous: TResult): TResult;
|
|
36
41
|
export declare function pick<TValue, TKey extends keyof TValue>(parent: TValue, keys: Array<TKey>): Pick<TValue, TKey>;
|
|
@@ -50,14 +55,15 @@ export declare function deepEqual(a: any, b: any, opts?: {
|
|
|
50
55
|
export declare function useStableCallback<T extends (...args: Array<any>) => any>(fn: T): T;
|
|
51
56
|
export declare function shallow<T>(objA: T, objB: T): boolean;
|
|
52
57
|
export type StringLiteral<T> = T extends string ? string extends T ? string : T : never;
|
|
53
|
-
export type StrictOrFrom<TFrom, TStrict extends boolean = true> = TStrict extends false ? {
|
|
58
|
+
export type StrictOrFrom<TRouter extends AnyRouter, TFrom, TStrict extends boolean = true> = TStrict extends false ? {
|
|
54
59
|
from?: never;
|
|
55
60
|
strict: TStrict;
|
|
56
61
|
} : {
|
|
57
|
-
from: StringLiteral<TFrom
|
|
62
|
+
from: StringLiteral<Constrain<TFrom, RouteIds<TRouter['routeTree']>>>;
|
|
58
63
|
strict?: TStrict;
|
|
59
64
|
};
|
|
60
|
-
export
|
|
65
|
+
export type ThrowOrOptional<T, TThrow extends boolean> = TThrow extends true ? T : T | undefined;
|
|
66
|
+
export declare const useLayoutEffect: typeof React.useEffect;
|
|
61
67
|
/**
|
|
62
68
|
*
|
|
63
69
|
* @deprecated use `jsesc` instead
|
package/dist/esm/Match.js
CHANGED
|
@@ -74,7 +74,7 @@ const Match = React.memo(function MatchImpl({
|
|
|
74
74
|
const MatchInner = React.memo(function MatchInnerImpl({
|
|
75
75
|
matchId
|
|
76
76
|
}) {
|
|
77
|
-
var _a, _b, _c;
|
|
77
|
+
var _a, _b, _c, _d, _e;
|
|
78
78
|
const router = useRouter();
|
|
79
79
|
const { match, matchIndex, routeId } = useRouterState({
|
|
80
80
|
select: (s) => {
|
|
@@ -84,9 +84,10 @@ const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
84
84
|
return {
|
|
85
85
|
routeId: routeId2,
|
|
86
86
|
matchIndex: matchIndex2,
|
|
87
|
-
match: pick(match2, ["id", "status", "error"
|
|
87
|
+
match: pick(match2, ["id", "status", "error"])
|
|
88
88
|
};
|
|
89
|
-
}
|
|
89
|
+
},
|
|
90
|
+
structuralSharing: true
|
|
90
91
|
});
|
|
91
92
|
const route = router.routesById[routeId];
|
|
92
93
|
const out = React.useMemo(() => {
|
|
@@ -107,7 +108,7 @@ const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
107
108
|
}
|
|
108
109
|
if (match.status === "redirected") {
|
|
109
110
|
invariant(isRedirect(match.error), "Expected a redirect error");
|
|
110
|
-
throw match.loadPromise;
|
|
111
|
+
throw (_b = router.getMatch(match.id)) == null ? void 0 : _b.loadPromise;
|
|
111
112
|
}
|
|
112
113
|
if (match.status === "error") {
|
|
113
114
|
if (router.isServer) {
|
|
@@ -122,7 +123,7 @@ const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
122
123
|
);
|
|
123
124
|
}
|
|
124
125
|
if (isServerSideError(match.error)) {
|
|
125
|
-
const deserializeError = ((
|
|
126
|
+
const deserializeError = ((_c = router.options.errorSerializer) == null ? void 0 : _c.deserialize) ?? defaultDeserializeError;
|
|
126
127
|
throw deserializeError(match.error.data);
|
|
127
128
|
} else {
|
|
128
129
|
throw match.error;
|
|
@@ -130,7 +131,7 @@ const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
130
131
|
}
|
|
131
132
|
if (match.status === "pending") {
|
|
132
133
|
const pendingMinMs = route.options.pendingMinMs ?? router.options.defaultPendingMinMs;
|
|
133
|
-
if (pendingMinMs && !((
|
|
134
|
+
if (pendingMinMs && !((_d = router.getMatch(match.id)) == null ? void 0 : _d.minPendingPromise)) {
|
|
134
135
|
if (!router.isServer) {
|
|
135
136
|
const minPendingPromise = createControlledPromise();
|
|
136
137
|
Promise.resolve().then(() => {
|
|
@@ -148,7 +149,7 @@ const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
148
149
|
}, pendingMinMs);
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
|
-
throw match.loadPromise;
|
|
152
|
+
throw (_e = router.getMatch(match.id)) == null ? void 0 : _e.loadPromise;
|
|
152
153
|
}
|
|
153
154
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
154
155
|
out,
|
|
@@ -165,7 +166,7 @@ const Outlet = React.memo(function OutletImpl() {
|
|
|
165
166
|
}
|
|
166
167
|
});
|
|
167
168
|
const route = router.routesById[routeId];
|
|
168
|
-
const
|
|
169
|
+
const parentGlobalNotFound = useRouterState({
|
|
169
170
|
select: (s) => {
|
|
170
171
|
const matches = s.matches;
|
|
171
172
|
const parentMatch = matches.find((d) => d.id === matchId);
|
|
@@ -173,9 +174,7 @@ const Outlet = React.memo(function OutletImpl() {
|
|
|
173
174
|
parentMatch,
|
|
174
175
|
`Could not find parent match for matchId "${matchId}"`
|
|
175
176
|
);
|
|
176
|
-
return
|
|
177
|
-
parentGlobalNotFound: parentMatch.globalNotFound
|
|
178
|
-
};
|
|
177
|
+
return parentMatch.globalNotFound;
|
|
179
178
|
}
|
|
180
179
|
});
|
|
181
180
|
const childMatchId = useRouterState({
|
package/dist/esm/Match.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n return (\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n )\n})\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, matchIndex, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error', 'loadPromise']),\n }\n },\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp /> : <Outlet />\n }, [route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw match.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw match.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const { parentGlobalNotFound } = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return {\n parentGlobalNotFound: parentMatch.globalNotFound,\n }\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n"],"names":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAAA;AAChC;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC2D;AAC7D;AAAA;AAIE;AAEA;AACJ;AACA;AAAiC;AAsBnC;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAY;AAGV;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAAA;AAClB;AACF;AAIA;AACF;AAEM;AAAiC;AAEvC;AAAY;AAAA;AAIZ;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AAAA;AAGnB;AAAY;AAGd;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEA;AAA0C;AAE5C;AACA;AACA;AAAA;AACE;AACmD;AAE9C;AAAA;AAC6B;AACpC;AAAA;AAIJ;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAAA;AAI/B;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;;;"}
|
|
1
|
+
{"version":3,"file":"Match.js","sources":["../../src/Match.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport invariant from 'tiny-invariant'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { createControlledPromise, pick } from './utils'\nimport { CatchNotFound, isNotFound } from './not-found'\nimport { isRedirect } from './redirects'\nimport { matchContext } from './matchContext'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport { SafeFragment } from './SafeFragment'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { rootRouteId } from './root'\nimport type { AnyRoute } from './route'\n\nexport const Match = React.memo(function MatchImpl({\n matchId,\n}: {\n matchId: string\n}) {\n const router = useRouter()\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n invariant(\n routeId,\n `Could not find routeId for matchId \"${matchId}\". Please file an issue!`,\n )\n\n const route: AnyRoute = router.routesById[routeId]\n\n const PendingComponent =\n route.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n const routeErrorComponent =\n route.options.errorComponent ?? router.options.defaultErrorComponent\n\n const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch\n\n const routeNotFoundComponent = route.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.options.notFoundComponent ??\n router.options.notFoundRoute?.options.component)\n : route.options.notFoundComponent\n\n const ResolvedSuspenseBoundary =\n // If we're on the root route, allow forcefully wrapping in suspense\n (!route.isRoot || route.options.wrapInSuspense) &&\n (route.options.wrapInSuspense ??\n PendingComponent ??\n (route.options.errorComponent as any)?.preload)\n ? React.Suspense\n : SafeFragment\n\n const ResolvedCatchBoundary = routeErrorComponent\n ? CatchBoundary\n : SafeFragment\n\n const ResolvedNotFoundBoundary = routeNotFoundComponent\n ? CatchNotFound\n : SafeFragment\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n return (\n <matchContext.Provider value={matchId}>\n <ResolvedSuspenseBoundary fallback={pendingElement}>\n <ResolvedCatchBoundary\n getResetKey={() => resetKey}\n errorComponent={routeErrorComponent || ErrorComponent}\n onCatch={(error, errorInfo) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) throw error\n warning(false, `Error in route match: ${matchId}`)\n routeOnCatch?.(error, errorInfo)\n }}\n >\n <ResolvedNotFoundBoundary\n fallback={(error) => {\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent ||\n (error.routeId && error.routeId !== routeId) ||\n (!error.routeId && !route.isRoot)\n )\n throw error\n\n return React.createElement(routeNotFoundComponent, error as any)\n }}\n >\n <MatchInner matchId={matchId} />\n </ResolvedNotFoundBoundary>\n </ResolvedCatchBoundary>\n </ResolvedSuspenseBoundary>\n </matchContext.Provider>\n )\n})\n\nexport const MatchInner = React.memo(function MatchInnerImpl({\n matchId,\n}: {\n matchId: string\n}): any {\n const router = useRouter()\n\n const { match, matchIndex, routeId } = useRouterState({\n select: (s) => {\n const matchIndex = s.matches.findIndex((d) => d.id === matchId)\n const match = s.matches[matchIndex]!\n const routeId = match.routeId as string\n return {\n routeId,\n matchIndex,\n match: pick(match, ['id', 'status', 'error']),\n }\n },\n structuralSharing: true as any,\n })\n\n const route = router.routesById[routeId]!\n\n const out = React.useMemo(() => {\n const Comp = route.options.component ?? router.options.defaultComponent\n return Comp ? <Comp /> : <Outlet />\n }, [route.options.component, router.options.defaultComponent])\n\n // function useChangedDiff(value: any) {\n // const ref = React.useRef(value)\n // const changed = ref.current !== value\n // if (changed) {\n // console.log(\n // 'Changed:',\n // value,\n // Object.fromEntries(\n // Object.entries(value).filter(\n // ([key, val]) => val !== ref.current[key],\n // ),\n // ),\n // )\n // }\n // ref.current = value\n // }\n\n // useChangedDiff(match)\n\n const RouteErrorComponent =\n (route.options.errorComponent ?? router.options.defaultErrorComponent) ||\n ErrorComponent\n\n if (match.status === 'notFound') {\n let error: unknown\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n\n error = deserializeError(match.error.data)\n } else {\n error = match.error\n }\n\n invariant(isNotFound(error), 'Expected a notFound error')\n\n return renderRouteNotFound(router, route, error)\n }\n\n if (match.status === 'redirected') {\n // Redirects should be handled by the router transition. If we happen to\n // encounter a redirect here, it's a bug. Let's warn, but render nothing.\n invariant(isRedirect(match.error), 'Expected a redirect error')\n\n // warning(\n // false,\n // 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',\n // )\n throw router.getMatch(match.id)?.loadPromise\n }\n\n if (match.status === 'error') {\n // If we're on the server, we need to use React's new and super\n // wonky api for throwing errors from a server side render inside\n // of a suspense boundary. This is the only way to get\n // renderToPipeableStream to not hang indefinitely.\n // We'll serialize the error and rethrow it on the client.\n if (router.isServer) {\n return (\n <RouteErrorComponent\n error={match.error}\n info={{\n componentStack: '',\n }}\n />\n )\n }\n\n if (isServerSideError(match.error)) {\n const deserializeError =\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n throw deserializeError(match.error.data)\n } else {\n throw match.error\n }\n }\n\n if (match.status === 'pending') {\n // We're pending, and if we have a minPendingMs, we need to wait for it\n const pendingMinMs =\n route.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {\n // Create a promise that will resolve after the minPendingMs\n if (!router.isServer) {\n const minPendingPromise = createControlledPromise<void>()\n\n Promise.resolve().then(() => {\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise,\n }))\n })\n\n setTimeout(() => {\n minPendingPromise.resolve()\n\n // We've handled the minPendingPromise, so we can delete it\n router.updateMatch(match.id, (prev) => ({\n ...prev,\n minPendingPromise: undefined,\n }))\n }, pendingMinMs)\n }\n }\n throw router.getMatch(match.id)?.loadPromise\n }\n\n return (\n <>\n {out}\n {router.AfterEachMatch ? (\n <router.AfterEachMatch match={match} matchIndex={matchIndex} />\n ) : null}\n </>\n )\n})\n\nexport const Outlet = React.memo(function OutletImpl() {\n const router = useRouter()\n const matchId = React.useContext(matchContext)\n const routeId = useRouterState({\n select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,\n })\n\n const route = router.routesById[routeId]!\n\n const parentGlobalNotFound = useRouterState({\n select: (s) => {\n const matches = s.matches\n const parentMatch = matches.find((d) => d.id === matchId)\n invariant(\n parentMatch,\n `Could not find parent match for matchId \"${matchId}\"`,\n )\n return parentMatch.globalNotFound\n },\n })\n\n const childMatchId = useRouterState({\n select: (s) => {\n const matches = s.matches\n const index = matches.findIndex((d) => d.id === matchId)\n return matches[index + 1]?.id\n },\n })\n\n if (parentGlobalNotFound) {\n return renderRouteNotFound(router, route, undefined)\n }\n\n if (!childMatchId) {\n return null\n }\n\n const nextMatch = <Match matchId={childMatchId} />\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n if (matchId === rootRouteId) {\n return (\n <React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>\n )\n }\n\n return nextMatch\n})\n"],"names":["matchIndex","match","routeId"],"mappings":";;;;;;;;;;;;;;;;AAkBO;AAA4C;AAEnD;;AAGE;AACA;AAA+B;;AACd;AAAyC;AAAA;AAG1D;AAAA;AACE;AAC8C;AAG1C;AAEN;AAGA;AAEA;AAGA;AAEA;AAAqC;AAAA;AAGK;AAGpC;AAAA;AAAA;AAOA;AAEA;AAIA;AAIN;AAAgC;AACb;AAIjB;AAEI;AAAC;AAAA;AACoB;AACoB;AAGjC;AACI;AACR;AAAsB;AACxB;AAEA;AAAC;AAAA;AAKK;AAIM;AAED;AAAwD;AACjE;AAE8B;AAAA;AAAA;AAChC;AAKV;AAEO;AAAsD;AAE7D;;AAGE;AAEA;AAAsD;AAE5CA;AACAC;AACN;AACO;AAAA;AACLC;AACAF;AAC4C;AAC9C;AACF;AACmB;AAGf;AAEA;AACJ;AACA;AAAiC;AAsBnC;AAII;AACE;AACA;AACF;AAGQ;AAAiC;AAEzC;AAAc;AAGN;AAEH;AAAwC;AAG7C;AAGF;AAMA;AAAiC;AAG/B;AAMF;AAEI;AAAA;AAAC;AAAA;AACc;AACP;AACY;AAAA;AAClB;AACF;AAIA;AACF;AAEM;AAAiC;AAEvC;AAAY;AAAA;AAIZ;AAEF;AAGA;AAEM;AACF;AAEQ;AACN;AAAwC;AACnC;AACH;AACA;AAGJ;AACE;AAGA;AAAwC;AACnC;AACgB;AACnB;AACW;AAAA;AAGnB;AAAiC;AAGnC;AAEK;AAAA;AAGG;AAGV;AAEO;AACL;AACM;AACN;AAA+B;;AACd;AAAyC;AAAA;AAGpD;AAEN;AAA4C;AAExC;AACA;AACA;AAAA;AACE;AACmD;AAErD;AAAmB;AAAA;AAIvB;AAAoC;;AAEhC;AACA;AACO;AAAoB;AAAA;AAI/B;AACS;AAA4C;AAGrD;AACS;AAAA;AAGT;AAEM;AAIN;AACE;AACuD;AAIlD;AACT;;;;;;"}
|
package/dist/esm/Matches.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StructuralSharingOption, ValidateSelected } from './structuralSharing.js';
|
|
1
2
|
import { AnyRoute, ReactNode, StaticDataRouteOption } from './route.js';
|
|
2
3
|
import { AnyRouter, RegisteredRouter } from './router.js';
|
|
3
4
|
import { ResolveRelativePath, ToOptions } from './link.js';
|
|
@@ -84,12 +85,10 @@ export type MakeMatchRouteOptions<TRouter extends AnyRouter = RegisteredRouter,
|
|
|
84
85
|
};
|
|
85
86
|
export declare function MatchRoute<TRouter extends AnyRouter = RegisteredRouter, TFrom extends RoutePaths<TRouter['routeTree']> = RoutePaths<TRouter['routeTree']>, TTo extends string = '', TMaskFrom extends RoutePaths<TRouter['routeTree']> = TFrom, TMaskTo extends string = ''>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any;
|
|
86
87
|
export type MakeRouteMatchUnion<TRouter extends AnyRouter = RegisteredRouter, TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>> = TRoute extends any ? RouteMatch<TRoute['id'], TRoute['fullPath'], TRoute['types']['allParams'], TRoute['types']['fullSearchSchema'], TRoute['types']['loaderData'], TRoute['types']['allContext'], TRoute['types']['loaderDeps']> : never;
|
|
87
|
-
export
|
|
88
|
-
select?: (matches: Array<
|
|
89
|
-
}
|
|
90
|
-
export
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
export declare function useChildMatches<TRouter extends AnyRouter = RegisteredRouter,
|
|
94
|
-
select?: (matches: Array<TRouteMatch>) => T;
|
|
95
|
-
}): T;
|
|
88
|
+
export interface UseMatchesBaseOptions<TRouter extends AnyRouter, TSelected, TStructuralSharing> {
|
|
89
|
+
select?: (matches: Array<MakeRouteMatchUnion<TRouter>>) => ValidateSelected<TRouter, TSelected, TStructuralSharing>;
|
|
90
|
+
}
|
|
91
|
+
export type UseMatchesResult<TRouter extends AnyRouter, TSelected> = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected;
|
|
92
|
+
export declare function useMatches<TRouter extends AnyRouter = RegisteredRouter, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>): UseMatchesResult<TRouter, TSelected>;
|
|
93
|
+
export declare function useParentMatches<TRouter extends AnyRouter = RegisteredRouter, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>): UseMatchesResult<TRouter, TSelected>;
|
|
94
|
+
export declare function useChildMatches<TRouter extends AnyRouter = RegisteredRouter, TSelected = unknown, TStructuralSharing extends boolean = boolean>(opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>): UseMatchesResult<TRouter, TSelected>;
|
package/dist/esm/Matches.js
CHANGED
|
@@ -56,7 +56,8 @@ function MatchesInner() {
|
|
|
56
56
|
function useMatchRoute() {
|
|
57
57
|
const router = useRouter();
|
|
58
58
|
useRouterState({
|
|
59
|
-
select: (s) => [s.location.href, s.resolvedLocation.href, s.status]
|
|
59
|
+
select: (s) => [s.location.href, s.resolvedLocation.href, s.status],
|
|
60
|
+
structuralSharing: true
|
|
60
61
|
});
|
|
61
62
|
return React.useCallback(
|
|
62
63
|
(opts) => {
|
|
@@ -84,7 +85,8 @@ function useMatches(opts) {
|
|
|
84
85
|
select: (state) => {
|
|
85
86
|
const matches = state.matches;
|
|
86
87
|
return (opts == null ? void 0 : opts.select) ? opts.select(matches) : matches;
|
|
87
|
-
}
|
|
88
|
+
},
|
|
89
|
+
structuralSharing: opts == null ? void 0 : opts.structuralSharing
|
|
88
90
|
});
|
|
89
91
|
}
|
|
90
92
|
function useParentMatches(opts) {
|
|
@@ -96,7 +98,8 @@ function useParentMatches(opts) {
|
|
|
96
98
|
matches.findIndex((d) => d.id === contextMatchId)
|
|
97
99
|
);
|
|
98
100
|
return (opts == null ? void 0 : opts.select) ? opts.select(matches) : matches;
|
|
99
|
-
}
|
|
101
|
+
},
|
|
102
|
+
structuralSharing: opts == null ? void 0 : opts.structuralSharing
|
|
100
103
|
});
|
|
101
104
|
}
|
|
102
105
|
function useChildMatches(opts) {
|
|
@@ -107,7 +110,8 @@ function useChildMatches(opts) {
|
|
|
107
110
|
matches.findIndex((d) => d.id === contextMatchId) + 1
|
|
108
111
|
);
|
|
109
112
|
return (opts == null ? void 0 : opts.select) ? opts.select(matches) : matches;
|
|
110
|
-
}
|
|
113
|
+
},
|
|
114
|
+
structuralSharing: opts == null ? void 0 : opts.structuralSharing
|
|
111
115
|
});
|
|
112
116
|
}
|
|
113
117
|
export {
|
package/dist/esm/Matches.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Matches.js","sources":["../../src/Matches.tsx"],"sourcesContent":["import * as React from 'react'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport { SafeFragment } from './SafeFragment'\nimport type { AnyRoute, ReactNode, StaticDataRouteOption } from './route'\nimport type { AnyRouter, RegisteredRouter } from './router'\nimport type { ResolveRelativePath, ToOptions } from './link'\nimport type {\n AllContext,\n AllLoaderData,\n AllParams,\n FullSearchSchema,\n ParseRoute,\n RouteById,\n RouteByPath,\n RouteIds,\n RoutePaths,\n} from './routeInfo'\nimport type {\n Constrain,\n ControlledPromise,\n DeepPartial,\n NoInfer,\n} from './utils'\n\nexport type AnyMatchAndValue = { match: any; value: any }\n\nexport type FindValueByIndex<\n TKey,\n TValue extends ReadonlyArray<any>,\n> = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never\n\nexport type FindValueByKey<TKey, TValue> =\n TValue extends ReadonlyArray<any>\n ? FindValueByIndex<TKey, TValue>\n : TValue[TKey & keyof TValue]\n\nexport type CreateMatchAndValue<TMatch, TValue> = TValue extends any\n ? {\n match: TMatch\n value: TValue\n }\n : never\n\nexport type NextMatchAndValue<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? CreateMatchAndValue<\n TMatchAndValue['match'],\n FindValueByKey<TKey, TMatchAndValue['value']>\n >\n : never\n\nexport type IsMatchKeyOf<TValue> =\n TValue extends ReadonlyArray<any>\n ? number extends TValue['length']\n ? `${number}`\n : keyof TValue & `${number}`\n : TValue extends object\n ? keyof TValue & string\n : never\n\nexport type IsMatchPath<\n TParentPath extends string,\n TMatchAndValue extends AnyMatchAndValue,\n> = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`\n\nexport type IsMatchResult<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? TKey extends keyof TMatchAndValue['value']\n ? TMatchAndValue['match']\n : never\n : never\n\nexport type IsMatchParse<\n TPath,\n TMatchAndValue extends AnyMatchAndValue,\n TParentPath extends string = '',\n> = TPath extends `${string}.${string}`\n ? TPath extends `${infer TFirst}.${infer TRest}`\n ? IsMatchParse<\n TRest,\n NextMatchAndValue<TFirst, TMatchAndValue>,\n `${TParentPath}${TFirst}.`\n >\n : never\n : {\n path: IsMatchPath<TParentPath, TMatchAndValue>\n result: IsMatchResult<TPath, TMatchAndValue>\n }\n\nexport type IsMatch<TMatch, TPath> = IsMatchParse<\n TPath,\n TMatch extends any ? { match: TMatch; value: TMatch } : never\n>\n\n/**\n * Narrows matches based on a path\n * @experimental\n */\nexport const isMatch = <TMatch, TPath extends string>(\n match: TMatch,\n path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,\n): match is IsMatch<TMatch, TPath>['result'] => {\n const parts = (path as string).split('.')\n let part\n let value: any = match\n\n while ((part = parts.shift()) != null && value != null) {\n value = value[part]\n }\n\n return value != null\n}\n\nexport type MakeRouteMatchFromRoute<TRoute extends AnyRoute> = RouteMatch<\n TRoute['types']['id'],\n TRoute['types']['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n>\n\nexport interface RouteMatch<\n TRouteId,\n TFullPath,\n TAllParams,\n TFullSearchSchema,\n TLoaderData,\n TAllContext,\n TLoaderDeps,\n> {\n id: string\n routeId: TRouteId\n fullPath: TFullPath\n index: number\n pathname: string\n params: TAllParams\n status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'\n isFetching: false | 'beforeLoad' | 'loader'\n error: unknown\n paramsError: unknown\n searchError: unknown\n updatedAt: number\n loadPromise?: ControlledPromise<void>\n beforeLoadPromise?: ControlledPromise<void>\n loaderPromise?: ControlledPromise<void>\n loaderData?: TLoaderData\n __routeContext: Record<string, unknown>\n __beforeLoadContext: Record<string, unknown>\n context: TAllContext\n search: TFullSearchSchema\n fetchCount: number\n abortController: AbortController\n cause: 'preload' | 'enter' | 'stay'\n loaderDeps: TLoaderDeps\n preload: boolean\n invalid: boolean\n meta?: Array<React.JSX.IntrinsicElements['meta']>\n links?: Array<React.JSX.IntrinsicElements['link']>\n scripts?: Array<React.JSX.IntrinsicElements['script']>\n headers?: Record<string, string>\n globalNotFound?: boolean\n staticData: StaticDataRouteOption\n minPendingPromise?: ControlledPromise<void>\n pendingTimeout?: ReturnType<typeof setTimeout>\n}\n\nexport type MakeRouteMatch<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TRouteId = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n> = RouteMatch<\n TRouteId,\n RouteById<TRouteTree, TRouteId>['types']['fullPath'],\n TStrict extends false\n ? AllParams<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allParams'],\n TStrict extends false\n ? FullSearchSchema<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'],\n TStrict extends false\n ? AllLoaderData<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['loaderData'],\n TStrict extends false\n ? AllContext<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allContext'],\n RouteById<TRouteTree, TRouteId>['types']['loaderDeps']\n>\n\nexport type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>\n\nexport function Matches() {\n const router = useRouter()\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n router.isServer || (typeof document !== 'undefined' && window.__TSR__)\n ? SafeFragment\n : React.Suspense\n\n const inner = (\n <ResolvedSuspense fallback={pendingElement}>\n <Transitioner />\n <MatchesInner />\n </ResolvedSuspense>\n )\n\n return router.options.InnerWrap ? (\n <router.options.InnerWrap>{inner}</router.options.InnerWrap>\n ) : (\n inner\n )\n}\n\nfunction MatchesInner() {\n const matchId = useRouterState({\n select: (s) => {\n return s.matches[0]?.id\n },\n })\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n return (\n <matchContext.Provider value={matchId}>\n <CatchBoundary\n getResetKey={() => resetKey}\n errorComponent={ErrorComponent}\n onCatch={(error) => {\n warning(\n false,\n `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,\n )\n warning(false, error.message || error.toString())\n }}\n >\n {matchId ? <Match matchId={matchId} /> : null}\n </CatchBoundary>\n </matchContext.Provider>\n )\n}\n\nexport interface MatchRouteOptions {\n pending?: boolean\n caseSensitive?: boolean\n includeSearch?: boolean\n fuzzy?: boolean\n}\n\nexport type UseMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n TOptions extends ToOptions<\n TRouter,\n TFrom,\n TTo,\n TMaskFrom,\n TMaskTo\n > = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n TRelaxedOptions = Omit<TOptions, 'search' | 'params'> &\n DeepPartial<Pick<TOptions, 'search' | 'params'>>,\n> = TRelaxedOptions & MatchRouteOptions\n\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {\n const router = useRouter()\n\n useRouterState({\n select: (s) => [s.location.href, s.resolvedLocation.href, s.status],\n })\n\n return React.useCallback(\n <\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 TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>,\n >(\n opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n ):\n | false\n | RouteByPath<TRouter['routeTree'], TResolved>['types']['allParams'] => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n },\n [router],\n )\n}\n\nexport type MakeMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> = TFrom,\n TMaskTo extends string = '',\n> = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\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 | ((\n params?: RouteByPath<\n TRouter['routeTree'],\n ResolveRelativePath<TFrom, NoInfer<TTo>>\n >['types']['allParams'],\n ) => ReactNode)\n | React.ReactNode\n}\n\nexport function MatchRoute<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> = TFrom,\n TMaskTo extends string = '',\n>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any)\n\n if (typeof props.children === 'function') {\n return (props.children as any)(params)\n }\n\n return params ? props.children : null\n}\n\nexport type MakeRouteMatchUnion<\n TRouter extends AnyRouter = RegisteredRouter,\n TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,\n> = TRoute extends any\n ? RouteMatch<\n TRoute['id'],\n TRoute['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n >\n : never\n\nexport function useMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TRouteMatch = MakeRouteMatchUnion<TRouter>,\n T = Array<TRouteMatch>,\n>(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {\n return useRouterState({\n select: (state) => {\n const matches = state.matches\n return opts?.select\n ? opts.select(matches as Array<TRouteMatch>)\n : (matches as T)\n },\n })\n}\n\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TRouteMatch = MakeRouteMatchUnion<TRouter>,\n T = Array<TRouteMatch>,\n>(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === contextMatchId),\n )\n return opts?.select\n ? opts.select(matches as Array<TRouteMatch>)\n : (matches as T)\n },\n })\n}\n\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TRouteMatch = MakeRouteMatchUnion<TRouter>,\n T = Array<TRouteMatch>,\n>(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === contextMatchId) + 1,\n )\n return opts?.select\n ? opts.select(matches as Array<TRouteMatch>)\n : (matches as T)\n },\n })\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Matches.js","sources":["../../src/Matches.tsx"],"sourcesContent":["import * as React from 'react'\nimport warning from 'tiny-warning'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport { SafeFragment } from './SafeFragment'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type { AnyRoute, ReactNode, StaticDataRouteOption } from './route'\nimport type { AnyRouter, RegisteredRouter, RouterState } from './router'\nimport type { ResolveRelativePath, ToOptions } from './link'\nimport type {\n AllContext,\n AllLoaderData,\n AllParams,\n FullSearchSchema,\n ParseRoute,\n RouteById,\n RouteByPath,\n RouteIds,\n RoutePaths,\n} from './routeInfo'\nimport type {\n Constrain,\n ControlledPromise,\n DeepPartial,\n NoInfer,\n} from './utils'\n\nexport type AnyMatchAndValue = { match: any; value: any }\n\nexport type FindValueByIndex<\n TKey,\n TValue extends ReadonlyArray<any>,\n> = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never\n\nexport type FindValueByKey<TKey, TValue> =\n TValue extends ReadonlyArray<any>\n ? FindValueByIndex<TKey, TValue>\n : TValue[TKey & keyof TValue]\n\nexport type CreateMatchAndValue<TMatch, TValue> = TValue extends any\n ? {\n match: TMatch\n value: TValue\n }\n : never\n\nexport type NextMatchAndValue<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? CreateMatchAndValue<\n TMatchAndValue['match'],\n FindValueByKey<TKey, TMatchAndValue['value']>\n >\n : never\n\nexport type IsMatchKeyOf<TValue> =\n TValue extends ReadonlyArray<any>\n ? number extends TValue['length']\n ? `${number}`\n : keyof TValue & `${number}`\n : TValue extends object\n ? keyof TValue & string\n : never\n\nexport type IsMatchPath<\n TParentPath extends string,\n TMatchAndValue extends AnyMatchAndValue,\n> = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`\n\nexport type IsMatchResult<\n TKey,\n TMatchAndValue extends AnyMatchAndValue,\n> = TMatchAndValue extends any\n ? TKey extends keyof TMatchAndValue['value']\n ? TMatchAndValue['match']\n : never\n : never\n\nexport type IsMatchParse<\n TPath,\n TMatchAndValue extends AnyMatchAndValue,\n TParentPath extends string = '',\n> = TPath extends `${string}.${string}`\n ? TPath extends `${infer TFirst}.${infer TRest}`\n ? IsMatchParse<\n TRest,\n NextMatchAndValue<TFirst, TMatchAndValue>,\n `${TParentPath}${TFirst}.`\n >\n : never\n : {\n path: IsMatchPath<TParentPath, TMatchAndValue>\n result: IsMatchResult<TPath, TMatchAndValue>\n }\n\nexport type IsMatch<TMatch, TPath> = IsMatchParse<\n TPath,\n TMatch extends any ? { match: TMatch; value: TMatch } : never\n>\n\n/**\n * Narrows matches based on a path\n * @experimental\n */\nexport const isMatch = <TMatch, TPath extends string>(\n match: TMatch,\n path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,\n): match is IsMatch<TMatch, TPath>['result'] => {\n const parts = (path as string).split('.')\n let part\n let value: any = match\n\n while ((part = parts.shift()) != null && value != null) {\n value = value[part]\n }\n\n return value != null\n}\n\nexport type MakeRouteMatchFromRoute<TRoute extends AnyRoute> = RouteMatch<\n TRoute['types']['id'],\n TRoute['types']['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n>\n\nexport interface RouteMatch<\n TRouteId,\n TFullPath,\n TAllParams,\n TFullSearchSchema,\n TLoaderData,\n TAllContext,\n TLoaderDeps,\n> {\n id: string\n routeId: TRouteId\n fullPath: TFullPath\n index: number\n pathname: string\n params: TAllParams\n status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'\n isFetching: false | 'beforeLoad' | 'loader'\n error: unknown\n paramsError: unknown\n searchError: unknown\n updatedAt: number\n loadPromise?: ControlledPromise<void>\n beforeLoadPromise?: ControlledPromise<void>\n loaderPromise?: ControlledPromise<void>\n loaderData?: TLoaderData\n __routeContext: Record<string, unknown>\n __beforeLoadContext: Record<string, unknown>\n context: TAllContext\n search: TFullSearchSchema\n fetchCount: number\n abortController: AbortController\n cause: 'preload' | 'enter' | 'stay'\n loaderDeps: TLoaderDeps\n preload: boolean\n invalid: boolean\n meta?: Array<React.JSX.IntrinsicElements['meta']>\n links?: Array<React.JSX.IntrinsicElements['link']>\n scripts?: Array<React.JSX.IntrinsicElements['script']>\n headers?: Record<string, string>\n globalNotFound?: boolean\n staticData: StaticDataRouteOption\n minPendingPromise?: ControlledPromise<void>\n pendingTimeout?: ReturnType<typeof setTimeout>\n}\n\nexport type MakeRouteMatch<\n TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],\n TRouteId = RouteIds<TRouteTree>,\n TStrict extends boolean = true,\n> = RouteMatch<\n TRouteId,\n RouteById<TRouteTree, TRouteId>['types']['fullPath'],\n TStrict extends false\n ? AllParams<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allParams'],\n TStrict extends false\n ? FullSearchSchema<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'],\n TStrict extends false\n ? AllLoaderData<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['loaderData'],\n TStrict extends false\n ? AllContext<TRouteTree>\n : RouteById<TRouteTree, TRouteId>['types']['allContext'],\n RouteById<TRouteTree, TRouteId>['types']['loaderDeps']\n>\n\nexport type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>\n\nexport function Matches() {\n const router = useRouter()\n\n const pendingElement = router.options.defaultPendingComponent ? (\n <router.options.defaultPendingComponent />\n ) : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n router.isServer || (typeof document !== 'undefined' && window.__TSR__)\n ? SafeFragment\n : React.Suspense\n\n const inner = (\n <ResolvedSuspense fallback={pendingElement}>\n <Transitioner />\n <MatchesInner />\n </ResolvedSuspense>\n )\n\n return router.options.InnerWrap ? (\n <router.options.InnerWrap>{inner}</router.options.InnerWrap>\n ) : (\n inner\n )\n}\n\nfunction MatchesInner() {\n const matchId = useRouterState({\n select: (s) => {\n return s.matches[0]?.id\n },\n })\n\n const resetKey = useRouterState({\n select: (s) => s.loadedAt,\n })\n\n return (\n <matchContext.Provider value={matchId}>\n <CatchBoundary\n getResetKey={() => resetKey}\n errorComponent={ErrorComponent}\n onCatch={(error) => {\n warning(\n false,\n `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,\n )\n warning(false, error.message || error.toString())\n }}\n >\n {matchId ? <Match matchId={matchId} /> : null}\n </CatchBoundary>\n </matchContext.Provider>\n )\n}\n\nexport interface MatchRouteOptions {\n pending?: boolean\n caseSensitive?: boolean\n includeSearch?: boolean\n fuzzy?: boolean\n}\n\nexport type UseMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n TOptions extends ToOptions<\n TRouter,\n TFrom,\n TTo,\n TMaskFrom,\n TMaskTo\n > = ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n TRelaxedOptions = Omit<TOptions, 'search' | 'params'> &\n DeepPartial<Pick<TOptions, 'search' | 'params'>>,\n> = TRelaxedOptions & MatchRouteOptions\n\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {\n const router = useRouter()\n\n useRouterState({\n select: (s) => [s.location.href, s.resolvedLocation.href, s.status],\n structuralSharing: true as any,\n })\n\n return React.useCallback(\n <\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 TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>,\n >(\n opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n ):\n | false\n | RouteByPath<TRouter['routeTree'], TResolved>['types']['allParams'] => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n },\n [router],\n )\n}\n\nexport type MakeMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> = TFrom,\n TMaskTo extends string = '',\n> = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\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 | ((\n params?: RouteByPath<\n TRouter['routeTree'],\n ResolveRelativePath<TFrom, NoInfer<TTo>>\n >['types']['allParams'],\n ) => ReactNode)\n | React.ReactNode\n}\n\nexport function MatchRoute<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> = RoutePaths<\n TRouter['routeTree']\n >,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> = TFrom,\n TMaskTo extends string = '',\n>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any)\n\n if (typeof props.children === 'function') {\n return (props.children as any)(params)\n }\n\n return params ? props.children : null\n}\n\nexport type MakeRouteMatchUnion<\n TRouter extends AnyRouter = RegisteredRouter,\n TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,\n> = TRoute extends any\n ? RouteMatch<\n TRoute['id'],\n TRoute['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema'],\n TRoute['types']['loaderData'],\n TRoute['types']['allContext'],\n TRoute['types']['loaderDeps']\n >\n : never\n\nexport interface UseMatchesBaseOptions<\n TRouter extends AnyRouter,\n TSelected,\n TStructuralSharing,\n> {\n select?: (\n matches: Array<MakeRouteMatchUnion<TRouter>>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n}\n\nexport type UseMatchesResult<\n TRouter extends AnyRouter,\n TSelected,\n> = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected\n\nexport function useMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n return useRouterState({\n select: (state: RouterState<TRouter['routeTree']>) => {\n const matches = state.matches\n return opts?.select\n ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)\n : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any) as UseMatchesResult<TRouter, TSelected>\n}\n\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === contextMatchId),\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === contextMatchId) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ export declare function RouterContextProvider<TRouter extends AnyRouter = Regist
|
|
|
29
29
|
children: React.ReactNode;
|
|
30
30
|
}): import("react/jsx-runtime").JSX.Element;
|
|
31
31
|
export declare function RouterProvider<TRouter extends AnyRouter = RegisteredRouter, TDehydrated extends Record<string, any> = Record<string, any>>({ router, ...rest }: RouterProps<TRouter, TDehydrated>): import("react/jsx-runtime").JSX.Element;
|
|
32
|
-
export type RouterProps<TRouter extends AnyRouter = RegisteredRouter, TDehydrated extends Record<string, any> = Record<string, any>> = Omit<RouterOptions<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>, TDehydrated>, 'context'> & {
|
|
33
|
-
router: Router<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>>;
|
|
34
|
-
context?: Partial<RouterOptions<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>, TDehydrated>['context']>;
|
|
32
|
+
export type RouterProps<TRouter extends AnyRouter = RegisteredRouter, TDehydrated extends Record<string, any> = Record<string, any>> = Omit<RouterOptions<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>, NonNullable<TRouter['options']['defaultStructuralSharing']>, TDehydrated>, 'context'> & {
|
|
33
|
+
router: Router<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>, NonNullable<TRouter['options']['defaultStructuralSharing']>>;
|
|
34
|
+
context?: Partial<RouterOptions<TRouter['routeTree'], NonNullable<TRouter['options']['trailingSlash']>, NonNullable<TRouter['options']['defaultStructuralSharing']>, TDehydrated>['context']>;
|
|
35
35
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouterProvider.js","sources":["../../src/RouterProvider.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Matches } from './Matches'\nimport { getRouterContext } from './routerContext'\nimport type { NavigateOptions, ToOptions } from './link'\nimport type { ParsedLocation } from './location'\nimport type { RoutePaths } from './routeInfo'\nimport type {\n AnyRouter,\n RegisteredRouter,\n Router,\n RouterOptions,\n} from './router'\n\nexport interface CommitLocationOptions {\n replace?: boolean\n resetScroll?: boolean\n viewTransition?: boolean\n /**\n * @deprecated All navigations use React transitions under the hood now\n **/\n startTransition?: boolean\n ignoreBlocker?: boolean\n}\n\nexport interface MatchLocation {\n to?: string | number | null\n fuzzy?: boolean\n caseSensitive?: boolean\n from?: string\n}\n\nexport type NavigateFn = <\n TRouter extends RegisteredRouter,\n TTo extends string | undefined,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n opts: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => Promise<void>\n\nexport type BuildLocationFn = <\n TRouter extends RegisteredRouter,\n TTo extends string | undefined,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n opts: ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n leaveParams?: boolean\n _includeValidateSearch?: boolean\n },\n) => ParsedLocation\n\nexport type InjectedHtmlEntry = string | (() => Promise<string> | string)\n\nexport function RouterContextProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({\n router,\n children,\n ...rest\n}: RouterProps<TRouter, TDehydrated> & {\n children: React.ReactNode\n}) {\n // Allow the router to update options on the router instance\n router.update({\n ...router.options,\n ...rest,\n context: {\n ...router.options.context,\n ...rest.context,\n },\n } as any)\n\n const routerContext = getRouterContext()\n\n const provider = (\n <routerContext.Provider value={router}>{children}</routerContext.Provider>\n )\n\n if (router.options.Wrap) {\n return <router.options.Wrap>{provider}</router.options.Wrap>\n }\n\n return provider\n}\n\nexport function RouterProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({ router, ...rest }: RouterProps<TRouter, TDehydrated>) {\n return (\n <RouterContextProvider router={router} {...rest}>\n <Matches />\n </RouterContextProvider>\n )\n}\n\nexport type RouterProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> = Omit<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n TDehydrated\n >,\n 'context'\n> & {\n router: Router<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>\n >\n context?: Partial<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n TDehydrated\n >['context']\n >\n}\n"],"names":[],"mappings":";;;AAwDO,SAAS,sBAGd;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAEG;AAED,SAAO,OAAO;AAAA,IACZ,GAAG,OAAO;AAAA,IACV,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,OAAO,QAAQ;AAAA,MAClB,GAAG,KAAK;AAAA,IAAA;AAAA,EACV,CACM;AAER,QAAM,gBAAgB,iBAAiB;AAEvC,QAAM,WACH,oBAAA,cAAc,UAAd,EAAuB,OAAO,QAAS,UAAS;AAG/C,MAAA,OAAO,QAAQ,MAAM;AACvB,WAAQ,oBAAA,OAAO,QAAQ,MAAf,EAAqB,UAAS,UAAA;AAAA,EAAA;AAGjC,SAAA;AACT;AAEO,SAAS,eAGd,EAAE,QAAQ,GAAG,QAA2C;AACxD,6BACG,uBAAsB,EAAA,QAAiB,GAAG,MACzC,UAAA,oBAAC,UAAQ,CAAA,GACX;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"RouterProvider.js","sources":["../../src/RouterProvider.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Matches } from './Matches'\nimport { getRouterContext } from './routerContext'\nimport type { NavigateOptions, ToOptions } from './link'\nimport type { ParsedLocation } from './location'\nimport type { RoutePaths } from './routeInfo'\nimport type {\n AnyRouter,\n RegisteredRouter,\n Router,\n RouterOptions,\n} from './router'\n\nexport interface CommitLocationOptions {\n replace?: boolean\n resetScroll?: boolean\n viewTransition?: boolean\n /**\n * @deprecated All navigations use React transitions under the hood now\n **/\n startTransition?: boolean\n ignoreBlocker?: boolean\n}\n\nexport interface MatchLocation {\n to?: string | number | null\n fuzzy?: boolean\n caseSensitive?: boolean\n from?: string\n}\n\nexport type NavigateFn = <\n TRouter extends RegisteredRouter,\n TTo extends string | undefined,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n opts: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => Promise<void>\n\nexport type BuildLocationFn = <\n TRouter extends RegisteredRouter,\n TTo extends string | undefined,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n opts: ToOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n leaveParams?: boolean\n _includeValidateSearch?: boolean\n },\n) => ParsedLocation\n\nexport type InjectedHtmlEntry = string | (() => Promise<string> | string)\n\nexport function RouterContextProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({\n router,\n children,\n ...rest\n}: RouterProps<TRouter, TDehydrated> & {\n children: React.ReactNode\n}) {\n // Allow the router to update options on the router instance\n router.update({\n ...router.options,\n ...rest,\n context: {\n ...router.options.context,\n ...rest.context,\n },\n } as any)\n\n const routerContext = getRouterContext()\n\n const provider = (\n <routerContext.Provider value={router}>{children}</routerContext.Provider>\n )\n\n if (router.options.Wrap) {\n return <router.options.Wrap>{provider}</router.options.Wrap>\n }\n\n return provider\n}\n\nexport function RouterProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({ router, ...rest }: RouterProps<TRouter, TDehydrated>) {\n return (\n <RouterContextProvider router={router} {...rest}>\n <Matches />\n </RouterContextProvider>\n )\n}\n\nexport type RouterProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> = Omit<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n NonNullable<TRouter['options']['defaultStructuralSharing']>,\n TDehydrated\n >,\n 'context'\n> & {\n router: Router<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n NonNullable<TRouter['options']['defaultStructuralSharing']>\n >\n context?: Partial<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n NonNullable<TRouter['options']['defaultStructuralSharing']>,\n TDehydrated\n >['context']\n >\n}\n"],"names":[],"mappings":";;;AAwDO,SAAS,sBAGd;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAEG;AAED,SAAO,OAAO;AAAA,IACZ,GAAG,OAAO;AAAA,IACV,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,OAAO,QAAQ;AAAA,MAClB,GAAG,KAAK;AAAA,IAAA;AAAA,EACV,CACM;AAER,QAAM,gBAAgB,iBAAiB;AAEvC,QAAM,WACH,oBAAA,cAAc,UAAd,EAAuB,OAAO,QAAS,UAAS;AAG/C,MAAA,OAAO,QAAQ,MAAM;AACvB,WAAQ,oBAAA,OAAO,QAAQ,MAAf,EAAqB,UAAS,UAAA;AAAA,EAAA;AAGjC,SAAA;AACT;AAEO,SAAS,eAGd,EAAE,QAAQ,GAAG,QAA2C;AACxD,6BACG,uBAAsB,EAAA,QAAiB,GAAG,MACzC,UAAA,oBAAC,UAAQ,CAAA,GACX;AAEJ;"}
|
package/dist/esm/Transitioner.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { usePrevious, useLayoutEffect } from "./utils.js";
|
|
3
3
|
import { useRouter } from "./useRouter.js";
|
|
4
4
|
import { useRouterState } from "./useRouterState.js";
|
|
5
5
|
import { trimPathRight } from "./path.js";
|
|
6
6
|
function Transitioner() {
|
|
7
7
|
const router = useRouter();
|
|
8
8
|
const mountLoadForRouter = React.useRef({ router, mounted: false });
|
|
9
|
-
const
|
|
10
|
-
select: (
|
|
9
|
+
const isLoading = useRouterState({
|
|
10
|
+
select: ({ isLoading: isLoading2 }) => isLoading2
|
|
11
11
|
});
|
|
12
12
|
const [isTransitioning, startReactTransition_] = React.useTransition();
|
|
13
13
|
const hasPendingMatches = useRouterState({
|
|
14
|
-
select: (s) => s.matches.some((d) => d.status === "pending")
|
|
14
|
+
select: (s) => s.matches.some((d) => d.status === "pending"),
|
|
15
|
+
structuralSharing: true
|
|
15
16
|
});
|
|
16
|
-
const previousIsLoading = usePrevious(
|
|
17
|
-
const isAnyPending =
|
|
17
|
+
const previousIsLoading = usePrevious(isLoading);
|
|
18
|
+
const isAnyPending = isLoading || isTransitioning || hasPendingMatches;
|
|
18
19
|
const previousIsAnyPending = usePrevious(isAnyPending);
|
|
19
|
-
const isPagePending =
|
|
20
|
+
const isPagePending = isLoading || hasPendingMatches;
|
|
20
21
|
const previousIsPagePending = usePrevious(isPagePending);
|
|
21
22
|
if (!router.isServer) {
|
|
22
23
|
router.startReactTransition = startReactTransition_;
|
|
@@ -54,7 +55,7 @@ function Transitioner() {
|
|
|
54
55
|
tryLoad();
|
|
55
56
|
}, [router]);
|
|
56
57
|
useLayoutEffect(() => {
|
|
57
|
-
if (previousIsLoading && !
|
|
58
|
+
if (previousIsLoading && !isLoading) {
|
|
58
59
|
const toLocation = router.state.location;
|
|
59
60
|
const fromLocation = router.state.resolvedLocation;
|
|
60
61
|
const pathChanged = fromLocation.pathname !== toLocation.pathname;
|
|
@@ -66,7 +67,7 @@ function Transitioner() {
|
|
|
66
67
|
pathChanged
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
|
-
}, [previousIsLoading, router,
|
|
70
|
+
}, [previousIsLoading, router, isLoading]);
|
|
70
71
|
useLayoutEffect(() => {
|
|
71
72
|
if (previousIsPagePending && !isPagePending) {
|
|
72
73
|
const toLocation = router.state.location;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transitioner.js","sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as React from 'react'\nimport {
|
|
1
|
+
{"version":3,"file":"Transitioner.js","sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useLayoutEffect, usePrevious } from './utils'\nimport { useRouter } from './useRouter'\nimport { useRouterState } from './useRouterState'\nimport { trimPathRight } from './path'\n\nexport function Transitioner() {\n const router = useRouter()\n const mountLoadForRouter = React.useRef({ router, mounted: false })\n const isLoading = useRouterState({\n select: ({ isLoading }) => isLoading,\n })\n\n const [isTransitioning, startReactTransition_] = React.useTransition()\n // Track pending state changes\n const hasPendingMatches = useRouterState({\n select: (s) => s.matches.some((d) => d.status === 'pending'),\n structuralSharing: true,\n })\n\n const previousIsLoading = usePrevious(isLoading)\n\n const isAnyPending = isLoading || isTransitioning || hasPendingMatches\n const previousIsAnyPending = usePrevious(isAnyPending)\n\n const isPagePending = isLoading || hasPendingMatches\n const previousIsPagePending = usePrevious(isPagePending)\n\n if (!router.isServer) {\n router.startReactTransition = startReactTransition_\n }\n\n // Subscribe to location changes\n // and try to load the new location\n React.useEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n const nextLocation = router.buildLocation({\n to: router.latestLocation.pathname,\n search: true,\n params: true,\n hash: true,\n state: true,\n _includeValidateSearch: true,\n })\n\n if (\n trimPathRight(router.latestLocation.href) !==\n trimPathRight(nextLocation.href)\n ) {\n router.commitLocation({ ...nextLocation, replace: true })\n }\n\n return () => {\n unsub()\n }\n }, [router, router.history])\n\n // Try to load the initial location\n useLayoutEffect(() => {\n if (\n (typeof window !== 'undefined' && window.__TSR__?.dehydrated) ||\n (mountLoadForRouter.current.router === router &&\n mountLoadForRouter.current.mounted)\n ) {\n return\n }\n mountLoadForRouter.current = { router, mounted: true }\n\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n\n tryLoad()\n }, [router])\n\n useLayoutEffect(() => {\n // The router was loading and now it's not\n if (previousIsLoading && !isLoading) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n\n router.emit({\n type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches\n fromLocation,\n toLocation,\n pathChanged,\n })\n }\n }, [previousIsLoading, router, isLoading])\n\n useLayoutEffect(() => {\n // emit onBeforeRouteMount\n if (previousIsPagePending && !isPagePending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n\n router.emit({\n type: 'onBeforeRouteMount',\n fromLocation,\n toLocation,\n pathChanged,\n })\n }\n }, [isPagePending, previousIsPagePending, router])\n\n useLayoutEffect(() => {\n // The router was pending and now it's not\n if (previousIsAnyPending && !isAnyPending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n\n router.emit({\n type: 'onResolved',\n fromLocation,\n toLocation,\n pathChanged,\n })\n\n router.__store.setState((s) => ({\n ...s,\n status: 'idle',\n resolvedLocation: s.location,\n }))\n\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n if (router.state.location.hash !== '') {\n const el = document.getElementById(router.state.location.hash)\n if (el) {\n el.scrollIntoView()\n }\n }\n }\n }\n }, [isAnyPending, previousIsAnyPending, router])\n\n return null\n}\n"],"names":["isLoading"],"mappings":"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"}
|
package/dist/esm/fileRoute.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { UseParamsRoute } from './useParams.js';
|
|
2
|
+
import { UseMatchRoute } from './useMatch.js';
|
|
3
|
+
import { UseSearchRoute } from './useSearch.js';
|
|
1
4
|
import { Constrain } from './utils.js';
|
|
2
5
|
import { AnyContext, AnyPathParams, AnyRoute, AnySearchValidator, FileBaseRouteOptions, ResolveParams, RootRoute, Route, RouteConstraints, RouteLoaderFn, UpdatableRouteOptions } from './route.js';
|
|
3
|
-
import { MakeRouteMatch } from './Matches.js';
|
|
4
6
|
import { RegisteredRouter } from './router.js';
|
|
5
7
|
import { RouteById, RouteIds } from './routeInfo.js';
|
|
8
|
+
import { UseLoaderDepsRoute } from './useLoaderDeps.js';
|
|
9
|
+
import { UseLoaderDataRoute } from './useLoaderData.js';
|
|
10
|
+
import { UseRouteContextRoute } from './useRouteContext.js';
|
|
6
11
|
export interface FileRoutesByPath {
|
|
7
12
|
}
|
|
8
13
|
export interface FileRouteTypes {
|
|
@@ -41,24 +46,12 @@ export declare class LazyRoute<TRoute extends AnyRoute> {
|
|
|
41
46
|
constructor(opts: {
|
|
42
47
|
id: string;
|
|
43
48
|
} & LazyRouteOptions);
|
|
44
|
-
useMatch: <
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
useSearch: <TSelected = TRoute["types"]["fullSearchSchema"]>(opts?: {
|
|
51
|
-
select?: (s: TRoute["types"]["fullSearchSchema"]) => TSelected;
|
|
52
|
-
}) => TSelected;
|
|
53
|
-
useParams: <TSelected = TRoute["types"]["allParams"]>(opts?: {
|
|
54
|
-
select?: (s: TRoute["types"]["allParams"]) => TSelected;
|
|
55
|
-
}) => TSelected;
|
|
56
|
-
useLoaderDeps: <TSelected = TRoute["types"]["loaderDeps"]>(opts?: {
|
|
57
|
-
select?: (s: TRoute["types"]["loaderDeps"]) => TSelected;
|
|
58
|
-
}) => TSelected;
|
|
59
|
-
useLoaderData: <TSelected = TRoute["types"]["loaderData"]>(opts?: {
|
|
60
|
-
select?: (s: TRoute["types"]["loaderData"]) => TSelected;
|
|
61
|
-
}) => TSelected;
|
|
49
|
+
useMatch: UseMatchRoute<TRoute['id']>;
|
|
50
|
+
useRouteContext: UseRouteContextRoute<TRoute['id']>;
|
|
51
|
+
useSearch: UseSearchRoute<TRoute['id']>;
|
|
52
|
+
useParams: UseParamsRoute<TRoute['id']>;
|
|
53
|
+
useLoaderDeps: UseLoaderDepsRoute<TRoute['id']>;
|
|
54
|
+
useLoaderData: UseLoaderDataRoute<TRoute['id']>;
|
|
62
55
|
useNavigate: () => import('./useNavigate.js').UseNavigateResult<string>;
|
|
63
56
|
}
|
|
64
57
|
export declare function createLazyRoute<TId extends RouteIds<RegisteredRouter['routeTree']>, TRoute extends AnyRoute = RouteById<RegisteredRouter['routeTree'], TId>>(id: TId): (opts: LazyRouteOptions) => LazyRoute<TRoute>;
|