-
-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathindex.ts
More file actions
117 lines (100 loc) · 2.8 KB
/
index.ts
File metadata and controls
117 lines (100 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector.js'
import type { Derived, Store } from '@tanstack/store'
export * from '@tanstack/store'
/**
* @private
*/
export type NoInfer<T> = [T][T extends any ? 0 : never]
export function useStore<TState, TSelected = NoInfer<TState>>(
store: Store<TState, any>,
selector?: (state: NoInfer<TState>) => TSelected,
): TSelected
export function useStore<TState, TSelected = NoInfer<TState>>(
store: Derived<TState, any>,
selector?: (state: NoInfer<TState>) => TSelected,
): TSelected
export function useStore<TState, TSelected = NoInfer<TState>>(
store: Store<TState, any> | Derived<TState, any>,
selector: (state: NoInfer<TState>) => TSelected = (d) => d as any,
): TSelected {
const slice = useSyncExternalStoreWithSelector(
store.subscribe,
() => store.state,
() => store.state,
selector,
shallow,
)
return slice
}
export function shallow<T>(objA: T, objB: T) {
if (Object.is(objA, objB)) {
return true
}
if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false
}
if (objA instanceof Map && objB instanceof Map) {
if (objA.size !== objB.size) return false
for (const [k, v] of objA) {
if (!objB.has(k) || !Object.is(v, objB.get(k))) return false
}
return true
}
if (objA instanceof Set && objB instanceof Set) {
if (objA.size !== objB.size) return false
for (const v of objA) {
if (!objB.has(v)) return false
}
return true
}
if (objA instanceof Date && objB instanceof Date) {
if (objA.getTime() !== objB.getTime()) return false
return true
}
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
if (keysA.length !== keysB.length) {
return false
}
if (keysA.length > 0) {
for (const key of keysA) {
if (
!Object.prototype.hasOwnProperty.call(objB, key) ||
!Object.is(objA[key as keyof T], objB[key as keyof T])
) {
return false
}
}
return true
}
if (keysA.length === 0) {
const descriptorsA = Object.getOwnPropertyDescriptors(objA)
const descriptorsB = Object.getOwnPropertyDescriptors(objB)
const getterKeysA = Object.keys(descriptorsA).filter(
(key) => descriptorsA[key]?.get !== undefined,
)
const getterKeysB = Object.keys(descriptorsB).filter(
(key) => descriptorsB[key]?.get !== undefined,
)
if (getterKeysA.length !== getterKeysB.length) {
return false
}
for (const key of getterKeysA) {
if (
!getterKeysB.includes(key) ||
!Object.is(
(objA as Record<string, unknown>)[key],
(objB as Record<string, unknown>)[key],
)
) {
return false
}
}
}
return true
}