-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathSpringContext.tsx
66 lines (56 loc) · 1.91 KB
/
SpringContext.tsx
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
import * as React from 'react'
import { useContext, PropsWithChildren } from 'react'
import { useMemoOne } from '@react-spring/shared'
/**
* This context affects all new and existing `SpringValue` objects
* created with the hook API or the renderprops API.
*/
export interface SpringContext {
/** Pause all new and existing animations. */
pause?: boolean
/** Force all new and existing animations to be immediate. */
immediate?: boolean
}
export const SpringContext = makeRenderableContext<
SpringContext,
PropsWithChildren<SpringContext>
>(
Context =>
({ children, ...props }) => {
const inherited = useContext(Context)
// Inherited values are dominant when truthy.
const pause = props.pause || !!inherited.pause
const immediate = props.immediate || !!inherited.immediate
// Memoize the context to avoid unwanted renders.
props = useMemoOne(() => ({ pause, immediate }), [pause, immediate])
return <Context.Provider value={props}>{children}</Context.Provider>
},
{} as SpringContext
)
interface RenderableContext<T, P> extends React.ProviderExoticComponent<P> {
Provider: RenderableContext<T, P>
Consumer: React.Consumer<T>
displayName?: string
}
/** Make the `target` compatible with `useContext` */
function makeRenderableContext<T, P>(
target: (context: React.Context<T>) => React.FunctionComponent<P>,
init: T
): RenderableContext<T, P> {
let context = React.createContext(init)
context = Object.assign(target(context), context)
// https://github.com/facebook/react/pull/28226
if ('_context' in context.Provider) {
context.Provider._context = context
} else {
// @ts-ignore React 18 types disallow this
context.Provider = context
}
if ('_context' in context.Consumer) {
context.Consumer._context = context
} else {
// @ts-expect-error
context.Consumer = context
}
return context as unknown as RenderableContext<T, P>
}