@tanstack/react-router 1.31.25 → 1.31.26

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.
@@ -172,14 +172,18 @@ function removeLayoutSegments(routePath) {
172
172
  return newSegments.join("/");
173
173
  }
174
174
  function usePrevious(value) {
175
- const ref = React__namespace.useRef(value);
176
- if (ref.current !== value) {
177
- const prevValue = ref.current;
178
- ref.current = value;
179
- return prevValue;
180
- } else {
181
- return ref.current;
182
- }
175
+ const ref = React__namespace.useRef({
176
+ value,
177
+ prev: null
178
+ });
179
+ const current = ref.current.value;
180
+ if (value !== current) {
181
+ ref.current = {
182
+ value,
183
+ prev: current
184
+ };
185
+ }
186
+ return ref.current.prev;
183
187
  }
184
188
  exports.createControlledPromise = createControlledPromise;
185
189
  exports.deepEqual = deepEqual;
@@ -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\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\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 UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\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 : 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\n// from https://github.com/type-challenges/type-challenges/issues/737\ntype LastInUnion<T> =\n UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (\n x: infer L,\n ) => 0\n ? L\n : never\nexport type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never]\n ? []\n : [...UnionToTuple<Exclude<T, TLast>>, TLast]\n\n//\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]\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) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): 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 aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\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<TFrom, TReturnIntersection extends boolean = false> =\n | {\n from: StringLiteral<TFrom> | TFrom\n strict?: true\n }\n | {\n from?: never\n strict: false\n experimental_returnIntersection?: TReturnIntersection\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 function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function usePrevious<T>(value: T): T {\n const ref = React.useRef<T>(value)\n\n if (ref.current !== value) {\n const prevValue = ref.current\n ref.current = value\n return prevValue\n } else {\n return ref.current\n }\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'\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\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\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 UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\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 : 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\n// from https://github.com/type-challenges/type-challenges/issues/737\ntype LastInUnion<T> =\n UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (\n x: infer L,\n ) => 0\n ? L\n : never\nexport type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never]\n ? []\n : [...UnionToTuple<Exclude<T, TLast>>, TLast]\n\n//\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]\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) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): 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 aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\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<TFrom, TReturnIntersection extends boolean = false> =\n | {\n from: StringLiteral<TFrom> | TFrom\n strict?: true\n }\n | {\n from?: never\n strict: false\n experimental_returnIntersection?: TReturnIntersection\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 function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\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"],"names":["React"],"mappings":"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"}
@@ -70,5 +70,8 @@ export declare function createControlledPromise<T>(onResolve?: () => void): Cont
70
70
  * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'
71
71
  */
72
72
  export declare function removeLayoutSegments(routePath: string): string;
73
- export declare function usePrevious<T>(value: T): T;
73
+ /**
74
+ * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3
75
+ */
76
+ export declare function usePrevious<T>(value: T): T | null;
74
77
  export {};
@@ -70,5 +70,8 @@ export declare function createControlledPromise<T>(onResolve?: () => void): Cont
70
70
  * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'
71
71
  */
72
72
  export declare function removeLayoutSegments(routePath: string): string;
73
- export declare function usePrevious<T>(value: T): T;
73
+ /**
74
+ * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3
75
+ */
76
+ export declare function usePrevious<T>(value: T): T | null;
74
77
  export {};
package/dist/esm/utils.js CHANGED
@@ -153,14 +153,18 @@ function removeLayoutSegments(routePath) {
153
153
  return newSegments.join("/");
154
154
  }
155
155
  function usePrevious(value) {
156
- const ref = React.useRef(value);
157
- if (ref.current !== value) {
158
- const prevValue = ref.current;
159
- ref.current = value;
160
- return prevValue;
161
- } else {
162
- return ref.current;
163
- }
156
+ const ref = React.useRef({
157
+ value,
158
+ prev: null
159
+ });
160
+ const current = ref.current.value;
161
+ if (value !== current) {
162
+ ref.current = {
163
+ value,
164
+ prev: current
165
+ };
166
+ }
167
+ return ref.current.prev;
164
168
  }
165
169
  export {
166
170
  createControlledPromise,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","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\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\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 UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\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 : 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\n// from https://github.com/type-challenges/type-challenges/issues/737\ntype LastInUnion<T> =\n UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (\n x: infer L,\n ) => 0\n ? L\n : never\nexport type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never]\n ? []\n : [...UnionToTuple<Exclude<T, TLast>>, TLast]\n\n//\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]\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) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): 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 aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\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<TFrom, TReturnIntersection extends boolean = false> =\n | {\n from: StringLiteral<TFrom> | TFrom\n strict?: true\n }\n | {\n from?: never\n strict: false\n experimental_returnIntersection?: TReturnIntersection\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 function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function usePrevious<T>(value: T): T {\n const ref = React.useRef<T>(value)\n\n if (ref.current !== value) {\n const prevValue = ref.current\n ref.current = value\n return prevValue\n } else {\n return ref.current\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","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\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\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 UnionToIntersection<T> = (\n T extends any ? (k: T) => void : never\n) extends (k: infer I) => any\n ? I\n : never\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 : 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\n// from https://github.com/type-challenges/type-challenges/issues/737\ntype LastInUnion<T> =\n UnionToIntersection<T extends unknown ? (x: T) => 0 : never> extends (\n x: infer L,\n ) => 0\n ? L\n : never\nexport type UnionToTuple<T, TLast = LastInUnion<T>> = [T] extends [never]\n ? []\n : [...UnionToTuple<Exclude<T, TLast>>, TLast]\n\n//\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]\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) {\n return Array.isArray(value) && value.length === Object.keys(value).length\n}\n\nexport function deepEqual(a: any, b: any, partial: boolean = false): 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 aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n\n if (!partial && aKeys.length !== bKeys.length) {\n return false\n }\n\n return !bKeys.some(\n (key) => !(key in a) || !deepEqual(a[key], b[key], partial),\n )\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return !a.some((item, index) => !deepEqual(item, b[index], partial))\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<TFrom, TReturnIntersection extends boolean = false> =\n | {\n from: StringLiteral<TFrom> | TFrom\n strict?: true\n }\n | {\n from?: never\n strict: false\n experimental_returnIntersection?: TReturnIntersection\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 function removeTrailingSlash(value: string): string {\n if (value.endsWith('/') && value !== '/') {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(pathName1: string, pathName2: string): boolean {\n return removeTrailingSlash(pathName1) === removeTrailingSlash(pathName2)\n}\n\nexport type ControlledPromise<T> = Promise<T> & {\n resolve: (value: T) => void\n reject: (value: any) => void\n status: 'pending' | 'resolved' | 'rejected'\n}\n\nexport function createControlledPromise<T>(onResolve?: () => void) {\n let resolveLoadPromise!: () => void\n let rejectLoadPromise!: (value: any) => void\n\n const controlledPromise = new Promise<void>((resolve, reject) => {\n resolveLoadPromise = resolve\n rejectLoadPromise = reject\n }) as ControlledPromise<T>\n\n controlledPromise.status = 'pending'\n\n controlledPromise.resolve = () => {\n controlledPromise.status = 'resolved'\n resolveLoadPromise()\n onResolve?.()\n }\n\n controlledPromise.reject = (e) => {\n controlledPromise.status = 'rejected'\n rejectLoadPromise(e)\n }\n\n return controlledPromise\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\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"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.31.25",
3
+ "version": "1.31.26",
4
4
  "description": "",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/utils.ts CHANGED
@@ -353,14 +353,28 @@ export function removeLayoutSegments(routePath: string): string {
353
353
  return newSegments.join('/')
354
354
  }
355
355
 
356
- export function usePrevious<T>(value: T): T {
357
- const ref = React.useRef<T>(value)
358
-
359
- if (ref.current !== value) {
360
- const prevValue = ref.current
361
- ref.current = value
362
- return prevValue
363
- } else {
364
- return ref.current
356
+ /**
357
+ * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3
358
+ */
359
+ export function usePrevious<T>(value: T): T | null {
360
+ // initialise the ref with previous and current values
361
+ const ref = React.useRef<{ value: T; prev: T | null }>({
362
+ value: value,
363
+ prev: null,
364
+ })
365
+
366
+ const current = ref.current.value
367
+
368
+ // if the value passed into hook doesn't match what we store as "current"
369
+ // move the "current" to the "previous"
370
+ // and store the passed value as "current"
371
+ if (value !== current) {
372
+ ref.current = {
373
+ value: value,
374
+ prev: current,
375
+ }
365
376
  }
377
+
378
+ // return the previous value only
379
+ return ref.current.prev
366
380
  }