react-saga-redux 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +63 -0
- package/dist/index.d.mts +569 -0
- package/dist/index.d.ts +569 -0
- package/dist/index.js +1188 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1138 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +100 -0
- package/src/components/Context.ts +50 -0
- package/src/components/Props.ts +111 -0
- package/src/components/Provider.tsx +105 -0
- package/src/components/connect.tsx +813 -0
- package/src/connect/invalidArgFactory.ts +14 -0
- package/src/connect/mapDispatchToProps.ts +25 -0
- package/src/connect/mapProps.ts +43 -0
- package/src/connect/mapStateToProps.ts +14 -0
- package/src/connect/mergeProps.ts +78 -0
- package/src/connect/selectorFactory.ts +242 -0
- package/src/connect/verifySubselectors.ts +26 -0
- package/src/connect/wrapMapToProps.ts +110 -0
- package/src/exports.ts +54 -0
- package/src/hooks/useDispatch.ts +104 -0
- package/src/hooks/useReduxContext.ts +42 -0
- package/src/hooks/useSelector.ts +286 -0
- package/src/hooks/useStore.ts +123 -0
- package/src/index-rsc.ts +34 -0
- package/src/index.ts +1 -0
- package/src/types.ts +180 -0
- package/src/utils/Subscription.ts +183 -0
- package/src/utils/batch.ts +4 -0
- package/src/utils/bindActionCreators.ts +16 -0
- package/src/utils/constants.ts +23 -0
- package/src/utils/hoistStatics.ts +139 -0
- package/src/utils/isPlainObject.ts +17 -0
- package/src/utils/react-is.ts +97 -0
- package/src/utils/react.ts +3 -0
- package/src/utils/shallowEqual.ts +36 -0
- package/src/utils/useIsomorphicLayoutEffect.ts +40 -0
- package/src/utils/useSyncExternalStore.ts +9 -0
- package/src/utils/verifyPlainObject.ts +14 -0
- package/src/utils/warning.ts +21 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClassAttributes,
|
|
3
|
+
ComponentClass,
|
|
4
|
+
ComponentType,
|
|
5
|
+
FunctionComponent,
|
|
6
|
+
JSX,
|
|
7
|
+
} from 'react'
|
|
8
|
+
|
|
9
|
+
import type { Action, UnknownAction, Dispatch } from 'redux'
|
|
10
|
+
|
|
11
|
+
import type { NonReactStatics } from './utils/hoistStatics'
|
|
12
|
+
|
|
13
|
+
import type { ConnectProps } from './components/connect'
|
|
14
|
+
|
|
15
|
+
import type { UseSelectorOptions } from './hooks/useSelector'
|
|
16
|
+
|
|
17
|
+
export type FixTypeLater = any
|
|
18
|
+
|
|
19
|
+
export type EqualityFn<T> = (a: T, b: T) => boolean
|
|
20
|
+
|
|
21
|
+
export type ExtendedEqualityFn<T, P> = (a: T, b: T, c: P, d: P) => boolean
|
|
22
|
+
|
|
23
|
+
export type AnyIfEmpty<T extends object> = keyof T extends never ? any : T
|
|
24
|
+
|
|
25
|
+
export type DistributiveOmit<T, K extends keyof T> = T extends unknown
|
|
26
|
+
? Omit<T, K>
|
|
27
|
+
: never
|
|
28
|
+
|
|
29
|
+
export interface DispatchProp<A extends Action<string> = UnknownAction> {
|
|
30
|
+
dispatch: Dispatch<A>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A property P will be present if:
|
|
35
|
+
* - it is present in DecorationTargetProps
|
|
36
|
+
*
|
|
37
|
+
* Its value will be dependent on the following conditions
|
|
38
|
+
* - if property P is present in InjectedProps and its definition extends the definition
|
|
39
|
+
* in DecorationTargetProps, then its definition will be that of DecorationTargetProps[P]
|
|
40
|
+
* - if property P is not present in InjectedProps then its definition will be that of
|
|
41
|
+
* DecorationTargetProps[P]
|
|
42
|
+
* - if property P is present in InjectedProps but does not extend the
|
|
43
|
+
* DecorationTargetProps[P] definition, its definition will be that of InjectedProps[P]
|
|
44
|
+
*/
|
|
45
|
+
export type Matching<InjectedProps, DecorationTargetProps> = {
|
|
46
|
+
[P in keyof DecorationTargetProps]: P extends keyof InjectedProps
|
|
47
|
+
? InjectedProps[P] extends DecorationTargetProps[P]
|
|
48
|
+
? DecorationTargetProps[P]
|
|
49
|
+
: InjectedProps[P]
|
|
50
|
+
: DecorationTargetProps[P]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* a property P will be present if :
|
|
55
|
+
* - it is present in both DecorationTargetProps and InjectedProps
|
|
56
|
+
* - InjectedProps[P] can satisfy DecorationTargetProps[P]
|
|
57
|
+
* ie: decorated component can accept more types than decorator is injecting
|
|
58
|
+
*
|
|
59
|
+
* For decoration, inject props or ownProps are all optionally
|
|
60
|
+
* required by the decorated (right hand side) component.
|
|
61
|
+
* But any property required by the decorated component must be satisfied by the injected property.
|
|
62
|
+
*/
|
|
63
|
+
export type Shared<InjectedProps, DecorationTargetProps> = {
|
|
64
|
+
[P in Extract<
|
|
65
|
+
keyof InjectedProps,
|
|
66
|
+
keyof DecorationTargetProps
|
|
67
|
+
>]?: InjectedProps[P] extends DecorationTargetProps[P]
|
|
68
|
+
? DecorationTargetProps[P]
|
|
69
|
+
: never
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Infers prop type from component C
|
|
73
|
+
export type GetProps<C> =
|
|
74
|
+
C extends ComponentType<infer P>
|
|
75
|
+
? C extends ComponentClass<P>
|
|
76
|
+
? ClassAttributes<InstanceType<C>> & P
|
|
77
|
+
: P
|
|
78
|
+
: never
|
|
79
|
+
|
|
80
|
+
// Applies LibraryManagedAttributes (proper handling of defaultProps
|
|
81
|
+
// and propTypes).
|
|
82
|
+
export type GetLibraryManagedProps<C> = JSX.LibraryManagedAttributes<
|
|
83
|
+
C,
|
|
84
|
+
GetProps<C>
|
|
85
|
+
>
|
|
86
|
+
|
|
87
|
+
// Applies LibraryManagedAttributes (proper handling of defaultProps
|
|
88
|
+
// and propTypes), as well as defines WrappedComponent.
|
|
89
|
+
export type ConnectedComponent<
|
|
90
|
+
C extends ComponentType<any>,
|
|
91
|
+
P,
|
|
92
|
+
> = FunctionComponent<P> &
|
|
93
|
+
NonReactStatics<C> & {
|
|
94
|
+
WrappedComponent: C
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type ConnectPropsMaybeWithoutContext<TActualOwnProps> =
|
|
98
|
+
TActualOwnProps extends { context: any }
|
|
99
|
+
? Omit<ConnectProps, 'context'>
|
|
100
|
+
: ConnectProps
|
|
101
|
+
|
|
102
|
+
type Identity<T> = T
|
|
103
|
+
export type Mapped<T> = Identity<{ [k in keyof T]: T[k] }>
|
|
104
|
+
|
|
105
|
+
// Injects props and removes them from the prop requirements.
|
|
106
|
+
// Will not pass through the injected props if they are passed in during
|
|
107
|
+
// render. Also adds new prop requirements from TNeedsProps.
|
|
108
|
+
// Uses distributive omit to preserve discriminated unions part of original prop type.
|
|
109
|
+
// Note> Most of the time TNeedsProps is empty, because the overloads in `Connect`
|
|
110
|
+
// just pass in `{}`. The real props we need come from the component.
|
|
111
|
+
export type InferableComponentEnhancerWithProps<TInjectedProps, TNeedsProps> = <
|
|
112
|
+
C extends ComponentType<Matching<TInjectedProps, GetProps<C>>>,
|
|
113
|
+
>(
|
|
114
|
+
component: C,
|
|
115
|
+
) => ConnectedComponent<
|
|
116
|
+
C,
|
|
117
|
+
Mapped<
|
|
118
|
+
DistributiveOmit<
|
|
119
|
+
GetLibraryManagedProps<C>,
|
|
120
|
+
keyof Shared<TInjectedProps, GetLibraryManagedProps<C>>
|
|
121
|
+
> &
|
|
122
|
+
TNeedsProps &
|
|
123
|
+
ConnectPropsMaybeWithoutContext<TNeedsProps & GetProps<C>>
|
|
124
|
+
>
|
|
125
|
+
>
|
|
126
|
+
|
|
127
|
+
// Injects props and removes them from the prop requirements.
|
|
128
|
+
// Will not pass through the injected props if they are passed in during
|
|
129
|
+
// render.
|
|
130
|
+
export type InferableComponentEnhancer<TInjectedProps> =
|
|
131
|
+
InferableComponentEnhancerWithProps<TInjectedProps, {}>
|
|
132
|
+
|
|
133
|
+
export type InferThunkActionCreatorType<
|
|
134
|
+
TActionCreator extends (...args: any[]) => any,
|
|
135
|
+
> = TActionCreator extends (
|
|
136
|
+
...args: infer TParams
|
|
137
|
+
) => (...args: any[]) => infer TReturn
|
|
138
|
+
? (...args: TParams) => TReturn
|
|
139
|
+
: TActionCreator
|
|
140
|
+
|
|
141
|
+
export type HandleThunkActionCreator<TActionCreator> = TActionCreator extends (
|
|
142
|
+
...args: any[]
|
|
143
|
+
) => any
|
|
144
|
+
? InferThunkActionCreatorType<TActionCreator>
|
|
145
|
+
: TActionCreator
|
|
146
|
+
|
|
147
|
+
// redux-thunk middleware returns thunk's return value from dispatch call
|
|
148
|
+
// https://github.com/reduxjs/redux-thunk#composition
|
|
149
|
+
export type ResolveThunks<TDispatchProps> = TDispatchProps extends {
|
|
150
|
+
[key: string]: any
|
|
151
|
+
}
|
|
152
|
+
? {
|
|
153
|
+
[C in keyof TDispatchProps]: HandleThunkActionCreator<TDispatchProps[C]>
|
|
154
|
+
}
|
|
155
|
+
: TDispatchProps
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* This interface allows you to easily create a hook that is properly typed for your
|
|
159
|
+
* store's root state.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
*
|
|
163
|
+
* interface RootState {
|
|
164
|
+
* property: string;
|
|
165
|
+
* }
|
|
166
|
+
*
|
|
167
|
+
* const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector;
|
|
168
|
+
*/
|
|
169
|
+
export interface TypedUseSelectorHook<TState> {
|
|
170
|
+
<TSelected>(
|
|
171
|
+
selector: (state: TState) => TSelected,
|
|
172
|
+
equalityFn?: EqualityFn<NoInfer<TSelected>>,
|
|
173
|
+
): TSelected
|
|
174
|
+
<Selected = unknown>(
|
|
175
|
+
selector: (state: TState) => Selected,
|
|
176
|
+
options?: UseSelectorOptions<Selected>,
|
|
177
|
+
): Selected
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type NoInfer<T> = [T][T extends any ? 0 : never]
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { defaultNoopBatch as batch } from './batch'
|
|
2
|
+
|
|
3
|
+
// encapsulates the subscription logic for connecting a component to the redux store, as
|
|
4
|
+
// well as nesting subscriptions of descendant components, so that we can ensure the
|
|
5
|
+
// ancestor components re-render before descendants
|
|
6
|
+
|
|
7
|
+
type VoidFunc = () => void
|
|
8
|
+
|
|
9
|
+
type Listener = {
|
|
10
|
+
callback: VoidFunc
|
|
11
|
+
next: Listener | null
|
|
12
|
+
prev: Listener | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createListenerCollection() {
|
|
16
|
+
let first: Listener | null = null
|
|
17
|
+
let last: Listener | null = null
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
clear() {
|
|
21
|
+
first = null
|
|
22
|
+
last = null
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
notify() {
|
|
26
|
+
batch(() => {
|
|
27
|
+
let listener = first
|
|
28
|
+
while (listener) {
|
|
29
|
+
listener.callback()
|
|
30
|
+
listener = listener.next
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
get() {
|
|
36
|
+
const listeners: Listener[] = []
|
|
37
|
+
let listener = first
|
|
38
|
+
while (listener) {
|
|
39
|
+
listeners.push(listener)
|
|
40
|
+
listener = listener.next
|
|
41
|
+
}
|
|
42
|
+
return listeners
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
subscribe(callback: () => void) {
|
|
46
|
+
let isSubscribed = true
|
|
47
|
+
|
|
48
|
+
const listener: Listener = (last = {
|
|
49
|
+
callback,
|
|
50
|
+
next: null,
|
|
51
|
+
prev: last,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if (listener.prev) {
|
|
55
|
+
listener.prev.next = listener
|
|
56
|
+
} else {
|
|
57
|
+
first = listener
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return function unsubscribe() {
|
|
61
|
+
if (!isSubscribed || first === null) return
|
|
62
|
+
isSubscribed = false
|
|
63
|
+
|
|
64
|
+
if (listener.next) {
|
|
65
|
+
listener.next.prev = listener.prev
|
|
66
|
+
} else {
|
|
67
|
+
last = listener.prev
|
|
68
|
+
}
|
|
69
|
+
if (listener.prev) {
|
|
70
|
+
listener.prev.next = listener.next
|
|
71
|
+
} else {
|
|
72
|
+
first = listener.next
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type ListenerCollection = ReturnType<typeof createListenerCollection>
|
|
80
|
+
|
|
81
|
+
export interface Subscription {
|
|
82
|
+
addNestedSub: (listener: VoidFunc) => VoidFunc
|
|
83
|
+
notifyNestedSubs: VoidFunc
|
|
84
|
+
handleChangeWrapper: VoidFunc
|
|
85
|
+
isSubscribed: () => boolean
|
|
86
|
+
onStateChange?: VoidFunc | null
|
|
87
|
+
trySubscribe: VoidFunc
|
|
88
|
+
tryUnsubscribe: VoidFunc
|
|
89
|
+
getListeners: () => ListenerCollection
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const nullListeners = {
|
|
93
|
+
notify() {},
|
|
94
|
+
get: () => [],
|
|
95
|
+
} as unknown as ListenerCollection
|
|
96
|
+
|
|
97
|
+
export function createSubscription(store: any, parentSub?: Subscription) {
|
|
98
|
+
let unsubscribe: VoidFunc | undefined
|
|
99
|
+
let listeners: ListenerCollection = nullListeners
|
|
100
|
+
|
|
101
|
+
// Reasons to keep the subscription active
|
|
102
|
+
let subscriptionsAmount = 0
|
|
103
|
+
|
|
104
|
+
// Is this specific subscription subscribed (or only nested ones?)
|
|
105
|
+
let selfSubscribed = false
|
|
106
|
+
|
|
107
|
+
function addNestedSub(listener: () => void) {
|
|
108
|
+
trySubscribe()
|
|
109
|
+
|
|
110
|
+
const cleanupListener = listeners.subscribe(listener)
|
|
111
|
+
|
|
112
|
+
// cleanup nested sub
|
|
113
|
+
let removed = false
|
|
114
|
+
return () => {
|
|
115
|
+
if (!removed) {
|
|
116
|
+
removed = true
|
|
117
|
+
cleanupListener()
|
|
118
|
+
tryUnsubscribe()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function notifyNestedSubs() {
|
|
124
|
+
listeners.notify()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function handleChangeWrapper() {
|
|
128
|
+
if (subscription.onStateChange) {
|
|
129
|
+
subscription.onStateChange()
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isSubscribed() {
|
|
134
|
+
return selfSubscribed
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function trySubscribe() {
|
|
138
|
+
subscriptionsAmount++
|
|
139
|
+
if (!unsubscribe) {
|
|
140
|
+
unsubscribe = parentSub
|
|
141
|
+
? parentSub.addNestedSub(handleChangeWrapper)
|
|
142
|
+
: store.subscribe(handleChangeWrapper)
|
|
143
|
+
|
|
144
|
+
listeners = createListenerCollection()
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function tryUnsubscribe() {
|
|
149
|
+
subscriptionsAmount--
|
|
150
|
+
if (unsubscribe && subscriptionsAmount === 0) {
|
|
151
|
+
unsubscribe()
|
|
152
|
+
unsubscribe = undefined
|
|
153
|
+
listeners.clear()
|
|
154
|
+
listeners = nullListeners
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function trySubscribeSelf() {
|
|
159
|
+
if (!selfSubscribed) {
|
|
160
|
+
selfSubscribed = true
|
|
161
|
+
trySubscribe()
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function tryUnsubscribeSelf() {
|
|
166
|
+
if (selfSubscribed) {
|
|
167
|
+
selfSubscribed = false
|
|
168
|
+
tryUnsubscribe()
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const subscription: Subscription = {
|
|
173
|
+
addNestedSub,
|
|
174
|
+
notifyNestedSubs,
|
|
175
|
+
handleChangeWrapper,
|
|
176
|
+
isSubscribed,
|
|
177
|
+
trySubscribe: trySubscribeSelf,
|
|
178
|
+
tryUnsubscribe: tryUnsubscribeSelf,
|
|
179
|
+
getListeners: () => listeners,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return subscription
|
|
183
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ActionCreatorsMapObject, Dispatch } from 'redux'
|
|
2
|
+
|
|
3
|
+
export default function bindActionCreators(
|
|
4
|
+
actionCreators: ActionCreatorsMapObject,
|
|
5
|
+
dispatch: Dispatch,
|
|
6
|
+
): ActionCreatorsMapObject {
|
|
7
|
+
const boundActionCreators: ActionCreatorsMapObject = {}
|
|
8
|
+
|
|
9
|
+
for (const key in actionCreators) {
|
|
10
|
+
const actionCreator = actionCreators[key]
|
|
11
|
+
if (typeof actionCreator === 'function') {
|
|
12
|
+
boundActionCreators[key] = (...args) => dispatch(actionCreator(...args))
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return boundActionCreators
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents default log level values
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_LEVELS = {
|
|
5
|
+
trace: 10,
|
|
6
|
+
debug: 20,
|
|
7
|
+
info: 30,
|
|
8
|
+
warn: 40,
|
|
9
|
+
error: 50,
|
|
10
|
+
fatal: 60,
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents sort order direction: `ascending` or `descending`
|
|
15
|
+
*/
|
|
16
|
+
export const SORTING_ORDER = {
|
|
17
|
+
ASC: 'ASC',
|
|
18
|
+
DESC: 'DESC',
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
// Type exports (optional but useful)
|
|
22
|
+
export type DefaultLevels = typeof DEFAULT_LEVELS;
|
|
23
|
+
export type SortingOrder = typeof SORTING_ORDER;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copied directly from:
|
|
2
|
+
// https://github.com/mridgway/hoist-non-react-statics/blob/main/src/index.js
|
|
3
|
+
// https://unpkg.com/browse/@types/hoist-non-react-statics@3.3.6/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Copyright 2015, Yahoo! Inc.
|
|
7
|
+
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
|
|
8
|
+
*/
|
|
9
|
+
import type { ForwardRefExoticComponent, MemoExoticComponent } from 'react'
|
|
10
|
+
import { ForwardRef, Memo, isMemo } from '../utils/react-is'
|
|
11
|
+
|
|
12
|
+
const REACT_STATICS = {
|
|
13
|
+
childContextTypes: true,
|
|
14
|
+
contextType: true,
|
|
15
|
+
contextTypes: true,
|
|
16
|
+
defaultProps: true,
|
|
17
|
+
displayName: true,
|
|
18
|
+
getDefaultProps: true,
|
|
19
|
+
getDerivedStateFromError: true,
|
|
20
|
+
getDerivedStateFromProps: true,
|
|
21
|
+
mixins: true,
|
|
22
|
+
propTypes: true,
|
|
23
|
+
type: true,
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
const KNOWN_STATICS = {
|
|
27
|
+
name: true,
|
|
28
|
+
length: true,
|
|
29
|
+
prototype: true,
|
|
30
|
+
caller: true,
|
|
31
|
+
callee: true,
|
|
32
|
+
arguments: true,
|
|
33
|
+
arity: true,
|
|
34
|
+
} as const
|
|
35
|
+
|
|
36
|
+
const FORWARD_REF_STATICS = {
|
|
37
|
+
$$typeof: true,
|
|
38
|
+
render: true,
|
|
39
|
+
defaultProps: true,
|
|
40
|
+
displayName: true,
|
|
41
|
+
propTypes: true,
|
|
42
|
+
} as const
|
|
43
|
+
|
|
44
|
+
const MEMO_STATICS = {
|
|
45
|
+
$$typeof: true,
|
|
46
|
+
compare: true,
|
|
47
|
+
defaultProps: true,
|
|
48
|
+
displayName: true,
|
|
49
|
+
propTypes: true,
|
|
50
|
+
type: true,
|
|
51
|
+
} as const
|
|
52
|
+
|
|
53
|
+
const TYPE_STATICS = {
|
|
54
|
+
[ForwardRef]: FORWARD_REF_STATICS,
|
|
55
|
+
[Memo]: MEMO_STATICS,
|
|
56
|
+
} as const
|
|
57
|
+
|
|
58
|
+
function getStatics(component: any) {
|
|
59
|
+
// React v16.11 and below
|
|
60
|
+
if (isMemo(component)) {
|
|
61
|
+
return MEMO_STATICS
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// React v16.12 and above
|
|
65
|
+
return TYPE_STATICS[component['$$typeof']] || REACT_STATICS
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type NonReactStatics<
|
|
69
|
+
Source,
|
|
70
|
+
C extends {
|
|
71
|
+
[key: string]: true
|
|
72
|
+
} = {},
|
|
73
|
+
> = {
|
|
74
|
+
[key in Exclude<
|
|
75
|
+
keyof Source,
|
|
76
|
+
Source extends MemoExoticComponent<any>
|
|
77
|
+
? keyof typeof MEMO_STATICS | keyof C
|
|
78
|
+
: Source extends ForwardRefExoticComponent<any>
|
|
79
|
+
? keyof typeof FORWARD_REF_STATICS | keyof C
|
|
80
|
+
: keyof typeof REACT_STATICS | keyof typeof KNOWN_STATICS | keyof C
|
|
81
|
+
>]: Source[key]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const defineProperty = Object.defineProperty
|
|
85
|
+
const getOwnPropertyNames = Object.getOwnPropertyNames
|
|
86
|
+
const getOwnPropertySymbols = Object.getOwnPropertySymbols
|
|
87
|
+
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
|
|
88
|
+
const getPrototypeOf = Object.getPrototypeOf
|
|
89
|
+
const objectPrototype = Object.prototype
|
|
90
|
+
|
|
91
|
+
export default function hoistNonReactStatics<
|
|
92
|
+
Target,
|
|
93
|
+
Source,
|
|
94
|
+
CustomStatic extends {
|
|
95
|
+
[key: string]: true
|
|
96
|
+
} = {},
|
|
97
|
+
>(
|
|
98
|
+
targetComponent: Target,
|
|
99
|
+
sourceComponent: Source,
|
|
100
|
+
): Target & NonReactStatics<Source, CustomStatic> {
|
|
101
|
+
if (typeof sourceComponent !== 'string') {
|
|
102
|
+
// don't hoist over string (html) components
|
|
103
|
+
|
|
104
|
+
if (objectPrototype) {
|
|
105
|
+
const inheritedComponent = getPrototypeOf(sourceComponent)
|
|
106
|
+
if (inheritedComponent && inheritedComponent !== objectPrototype) {
|
|
107
|
+
hoistNonReactStatics(targetComponent, inheritedComponent)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let keys: (string | symbol)[] = getOwnPropertyNames(sourceComponent)
|
|
112
|
+
|
|
113
|
+
if (getOwnPropertySymbols) {
|
|
114
|
+
keys = keys.concat(getOwnPropertySymbols(sourceComponent))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const targetStatics = getStatics(targetComponent)
|
|
118
|
+
const sourceStatics = getStatics(sourceComponent)
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
121
|
+
const key = keys[i]
|
|
122
|
+
if (
|
|
123
|
+
!KNOWN_STATICS[key as keyof typeof KNOWN_STATICS] &&
|
|
124
|
+
!(sourceStatics && sourceStatics[key as keyof typeof sourceStatics]) &&
|
|
125
|
+
!(targetStatics && targetStatics[key as keyof typeof targetStatics])
|
|
126
|
+
) {
|
|
127
|
+
const descriptor = getOwnPropertyDescriptor(sourceComponent, key)
|
|
128
|
+
try {
|
|
129
|
+
// Avoid failures from read-only properties
|
|
130
|
+
defineProperty(targetComponent, key, descriptor!)
|
|
131
|
+
} catch (e) {
|
|
132
|
+
// ignore
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return targetComponent as any
|
|
139
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {any} obj The object to inspect.
|
|
3
|
+
* @returns {boolean} True if the argument appears to be a plain object.
|
|
4
|
+
*/
|
|
5
|
+
export default function isPlainObject(obj: unknown) {
|
|
6
|
+
if (typeof obj !== 'object' || obj === null) return false
|
|
7
|
+
|
|
8
|
+
const proto = Object.getPrototypeOf(obj)
|
|
9
|
+
if (proto === null) return true
|
|
10
|
+
|
|
11
|
+
let baseProto = proto
|
|
12
|
+
while (Object.getPrototypeOf(baseProto) !== null) {
|
|
13
|
+
baseProto = Object.getPrototypeOf(baseProto)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return proto === baseProto
|
|
17
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { ElementType, MemoExoticComponent, ReactElement } from 'react'
|
|
2
|
+
import { React } from './react'
|
|
3
|
+
|
|
4
|
+
// Directly ported from:
|
|
5
|
+
// https://unpkg.com/browse/react-is@19.0.0/cjs/react-is.production.js
|
|
6
|
+
// It's very possible this could change in the future, but given that
|
|
7
|
+
// we only use these in `connect`, this is a low priority.
|
|
8
|
+
|
|
9
|
+
export const IS_REACT_19 = /* @__PURE__ */ React.version.startsWith('19')
|
|
10
|
+
|
|
11
|
+
const REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for(
|
|
12
|
+
IS_REACT_19 ? 'react.transitional.element' : 'react.element',
|
|
13
|
+
)
|
|
14
|
+
const REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for('react.portal')
|
|
15
|
+
const REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for('react.fragment')
|
|
16
|
+
const REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for('react.strict_mode')
|
|
17
|
+
const REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for('react.profiler')
|
|
18
|
+
const REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for('react.consumer')
|
|
19
|
+
const REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for('react.context')
|
|
20
|
+
const REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for('react.forward_ref')
|
|
21
|
+
const REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for('react.suspense')
|
|
22
|
+
const REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for(
|
|
23
|
+
'react.suspense_list',
|
|
24
|
+
)
|
|
25
|
+
const REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for('react.memo')
|
|
26
|
+
const REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for('react.lazy')
|
|
27
|
+
const REACT_OFFSCREEN_TYPE = /* @__PURE__ */ Symbol.for('react.offscreen')
|
|
28
|
+
const REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for(
|
|
29
|
+
'react.client.reference',
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
export const ForwardRef = REACT_FORWARD_REF_TYPE
|
|
33
|
+
export const Memo = REACT_MEMO_TYPE
|
|
34
|
+
|
|
35
|
+
export function isValidElementType(type: any): type is ElementType {
|
|
36
|
+
return typeof type === 'string' ||
|
|
37
|
+
typeof type === 'function' ||
|
|
38
|
+
type === REACT_FRAGMENT_TYPE ||
|
|
39
|
+
type === REACT_PROFILER_TYPE ||
|
|
40
|
+
type === REACT_STRICT_MODE_TYPE ||
|
|
41
|
+
type === REACT_SUSPENSE_TYPE ||
|
|
42
|
+
type === REACT_SUSPENSE_LIST_TYPE ||
|
|
43
|
+
type === REACT_OFFSCREEN_TYPE ||
|
|
44
|
+
(typeof type === 'object' &&
|
|
45
|
+
type !== null &&
|
|
46
|
+
(type.$$typeof === REACT_LAZY_TYPE ||
|
|
47
|
+
type.$$typeof === REACT_MEMO_TYPE ||
|
|
48
|
+
type.$$typeof === REACT_CONTEXT_TYPE ||
|
|
49
|
+
type.$$typeof === REACT_CONSUMER_TYPE ||
|
|
50
|
+
type.$$typeof === REACT_FORWARD_REF_TYPE ||
|
|
51
|
+
type.$$typeof === REACT_CLIENT_REFERENCE ||
|
|
52
|
+
type.getModuleId !== undefined))
|
|
53
|
+
? !0
|
|
54
|
+
: !1
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function typeOf(object: any): symbol | undefined {
|
|
58
|
+
if (typeof object === 'object' && object !== null) {
|
|
59
|
+
const { $$typeof } = object
|
|
60
|
+
|
|
61
|
+
switch ($$typeof) {
|
|
62
|
+
case REACT_ELEMENT_TYPE:
|
|
63
|
+
switch (((object = object.type), object)) {
|
|
64
|
+
case REACT_FRAGMENT_TYPE:
|
|
65
|
+
case REACT_PROFILER_TYPE:
|
|
66
|
+
case REACT_STRICT_MODE_TYPE:
|
|
67
|
+
case REACT_SUSPENSE_TYPE:
|
|
68
|
+
case REACT_SUSPENSE_LIST_TYPE:
|
|
69
|
+
return object
|
|
70
|
+
default:
|
|
71
|
+
switch (((object = object && object.$$typeof), object)) {
|
|
72
|
+
case REACT_CONTEXT_TYPE:
|
|
73
|
+
case REACT_FORWARD_REF_TYPE:
|
|
74
|
+
case REACT_LAZY_TYPE:
|
|
75
|
+
case REACT_MEMO_TYPE:
|
|
76
|
+
return object
|
|
77
|
+
case REACT_CONSUMER_TYPE:
|
|
78
|
+
return object
|
|
79
|
+
default:
|
|
80
|
+
return $$typeof
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
case REACT_PORTAL_TYPE:
|
|
84
|
+
return $$typeof
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function isContextConsumer(object: any): object is ReactElement {
|
|
90
|
+
return IS_REACT_19
|
|
91
|
+
? typeOf(object) === REACT_CONSUMER_TYPE
|
|
92
|
+
: typeOf(object) === REACT_CONTEXT_TYPE
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isMemo(object: any): object is MemoExoticComponent<any> {
|
|
96
|
+
return typeOf(object) === REACT_MEMO_TYPE
|
|
97
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function is(x: unknown, y: unknown) {
|
|
2
|
+
if (x === y) {
|
|
3
|
+
return x !== 0 || y !== 0 || 1 / x === 1 / y
|
|
4
|
+
} else {
|
|
5
|
+
return x !== x && y !== y
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function shallowEqual(objA: any, objB: any) {
|
|
10
|
+
if (is(objA, objB)) return true
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
typeof objA !== 'object' ||
|
|
14
|
+
objA === null ||
|
|
15
|
+
typeof objB !== 'object' ||
|
|
16
|
+
objB === null
|
|
17
|
+
) {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const keysA = Object.keys(objA)
|
|
22
|
+
const keysB = Object.keys(objB)
|
|
23
|
+
|
|
24
|
+
if (keysA.length !== keysB.length) return false
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < keysA.length; i++) {
|
|
27
|
+
if (
|
|
28
|
+
!Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
|
|
29
|
+
!is(objA[keysA[i]], objB[keysA[i]])
|
|
30
|
+
) {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return true
|
|
36
|
+
}
|