about summary refs log tree commit diff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/functions.ts87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/lib/functions.ts b/src/lib/functions.ts
index b45c7fa6d..e0d44ce2d 100644
--- a/src/lib/functions.ts
+++ b/src/lib/functions.ts
@@ -9,3 +9,90 @@ export function dedupArray<T>(arr: T[]): T[] {
   const s = new Set(arr)
   return [...s]
 }
+
+/**
+ * Taken from @tanstack/query-core utils.ts
+ * Modified to support Date object comparisons
+ *
+ * This function returns `a` if `b` is deeply equal.
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
+ * This can be used for structural sharing between JSON values for example.
+ */
+export function replaceEqualDeep(a: any, b: any): any {
+  if (a === b) {
+    return a
+  }
+
+  if (a instanceof Date && b instanceof Date) {
+    return a.getTime() === b.getTime() ? a : b
+  }
+
+  const array = isPlainArray(a) && isPlainArray(b)
+
+  if (array || (isPlainObject(a) && isPlainObject(b))) {
+    const aItems = array ? a : Object.keys(a)
+    const aSize = aItems.length
+    const bItems = array ? b : Object.keys(b)
+    const bSize = bItems.length
+    const copy: any = array ? [] : {}
+
+    let equalItems = 0
+
+    for (let i = 0; i < bSize; i++) {
+      const key = array ? i : bItems[i]
+      if (
+        !array &&
+        a[key] === undefined &&
+        b[key] === undefined &&
+        aItems.includes(key)
+      ) {
+        copy[key] = undefined
+        equalItems++
+      } else {
+        copy[key] = replaceEqualDeep(a[key], b[key])
+        if (copy[key] === a[key] && a[key] !== undefined) {
+          equalItems++
+        }
+      }
+    }
+
+    return aSize === bSize && equalItems === aSize ? a : copy
+  }
+
+  return b
+}
+
+export function isPlainArray(value: unknown) {
+  return Array.isArray(value) && value.length === Object.keys(value).length
+}
+
+// Copied from: https://github.com/jonschlinkert/is-plain-object
+export function isPlainObject(o: any): o is Object {
+  if (!hasObjectPrototype(o)) {
+    return false
+  }
+
+  // If has no constructor
+  const ctor = o.constructor
+  if (ctor === undefined) {
+    return true
+  }
+
+  // If has modified prototype
+  const prot = ctor.prototype
+  if (!hasObjectPrototype(prot)) {
+    return false
+  }
+
+  // If constructor does not have an Object-specific method
+  if (!prot.hasOwnProperty('isPrototypeOf')) {
+    return false
+  }
+
+  // Most likely a plain Object
+  return true
+}
+
+function hasObjectPrototype(o: any): boolean {
+  return Object.prototype.toString.call(o) === '[object Object]'
+}