@legendapp/state 2.2.0-next.7 → 2.2.0-next.71
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/README.md +4 -2
- package/babel.js.map +1 -1
- package/config/enable$get.d.ts +8 -0
- package/config/enable$get.js +24 -0
- package/config/enable$get.js.map +1 -0
- package/config/enable$get.mjs +21 -0
- package/config/enable$get.mjs.map +1 -0
- package/config/enableReactComponents.js.map +1 -1
- package/config/enableReactComponents.mjs.map +1 -1
- package/config/enableReactNativeComponents.js.map +1 -1
- package/config/enableReactNativeComponents.mjs.map +1 -1
- package/config/enableReactTracking.d.ts +0 -9
- package/config/enableReactTracking.js.map +1 -1
- package/config/enableReactTracking.mjs.map +1 -1
- package/config/enableReactUse.d.ts +1 -1
- package/config/enableReactUse.js +1 -0
- package/config/enableReactUse.js.map +1 -1
- package/config/enableReactUse.mjs +1 -0
- package/config/enableReactUse.mjs.map +1 -1
- package/config/enable_peek.d.ts +8 -0
- package/config/{enableDirectPeek.js → enable_peek.js} +6 -3
- package/config/enable_peek.js.map +1 -0
- package/config/{enableDirectPeek.mjs → enable_peek.mjs} +5 -3
- package/config/enable_peek.mjs.map +1 -0
- package/helpers/fetch.d.ts +4 -3
- package/helpers/fetch.js.map +1 -1
- package/helpers/fetch.mjs.map +1 -1
- package/helpers/pageHash.js.map +1 -1
- package/helpers/pageHash.mjs.map +1 -1
- package/helpers/pageHashParams.js.map +1 -1
- package/helpers/pageHashParams.mjs.map +1 -1
- package/helpers/time.d.ts +2 -2
- package/helpers/time.js.map +1 -1
- package/helpers/time.mjs.map +1 -1
- package/history.js +2 -2
- package/history.js.map +1 -1
- package/history.mjs +3 -3
- package/history.mjs.map +1 -1
- package/index.d.ts +30 -9
- package/index.js +877 -661
- package/index.js.map +1 -1
- package/index.mjs +874 -658
- package/index.mjs.map +1 -1
- package/package.json +22 -25
- package/persist-plugins/async-storage.d.ts +3 -3
- package/persist-plugins/async-storage.js +8 -7
- package/persist-plugins/async-storage.js.map +1 -1
- package/persist-plugins/async-storage.mjs +9 -8
- package/persist-plugins/async-storage.mjs.map +1 -1
- package/persist-plugins/fetch.js.map +1 -1
- package/persist-plugins/fetch.mjs.map +1 -1
- package/persist-plugins/firebase.d.ts +1 -1
- package/persist-plugins/firebase.js +12 -11
- package/persist-plugins/firebase.js.map +1 -1
- package/persist-plugins/firebase.mjs +13 -12
- package/persist-plugins/firebase.mjs.map +1 -1
- package/persist-plugins/indexeddb.d.ts +10 -10
- package/persist-plugins/indexeddb.js +2 -2
- package/persist-plugins/indexeddb.js.map +1 -1
- package/persist-plugins/indexeddb.mjs +2 -2
- package/persist-plugins/indexeddb.mjs.map +1 -1
- package/persist-plugins/local-storage.d.ts +3 -4
- package/persist-plugins/local-storage.js +19 -7
- package/persist-plugins/local-storage.js.map +1 -1
- package/persist-plugins/local-storage.mjs +20 -9
- package/persist-plugins/local-storage.mjs.map +1 -1
- package/persist-plugins/mmkv.d.ts +8 -8
- package/persist-plugins/mmkv.js +5 -4
- package/persist-plugins/mmkv.js.map +1 -1
- package/persist-plugins/mmkv.mjs +6 -5
- package/persist-plugins/mmkv.mjs.map +1 -1
- package/persist-plugins/query.js.map +1 -1
- package/persist-plugins/query.mjs.map +1 -1
- package/persist.d.ts +2 -14
- package/persist.js +1250 -268
- package/persist.js.map +1 -1
- package/persist.mjs +1250 -269
- package/persist.mjs.map +1 -1
- package/react-hooks/createObservableHook.js +1 -1
- package/react-hooks/createObservableHook.js.map +1 -1
- package/react-hooks/createObservableHook.mjs +1 -1
- package/react-hooks/createObservableHook.mjs.map +1 -1
- package/react-hooks/useFetch.d.ts +4 -3
- package/react-hooks/useFetch.js.map +1 -1
- package/react-hooks/useFetch.mjs.map +1 -1
- package/react-hooks/useHover.js.map +1 -1
- package/react-hooks/useHover.mjs.map +1 -1
- package/react-hooks/useMeasure.js.map +1 -1
- package/react-hooks/useMeasure.mjs.map +1 -1
- package/react-hooks/useObservableNextRouter.js.map +1 -1
- package/react-hooks/useObservableNextRouter.mjs.map +1 -1
- package/react-hooks/useObservableQuery.js.map +1 -1
- package/react-hooks/useObservableQuery.mjs.map +1 -1
- package/react-hooks/usePersistedObservable.d.ts +5 -3
- package/react-hooks/usePersistedObservable.js +5 -2
- package/react-hooks/usePersistedObservable.js.map +1 -1
- package/react-hooks/usePersistedObservable.mjs +5 -2
- package/react-hooks/usePersistedObservable.mjs.map +1 -1
- package/react.js +61 -75
- package/react.js.map +1 -1
- package/react.mjs +61 -75
- package/react.mjs.map +1 -1
- package/src/ObservableObject.ts +1184 -0
- package/src/ObservablePrimitive.ts +62 -0
- package/src/babel/index.ts +70 -0
- package/src/batching.ts +372 -0
- package/src/computed.ts +16 -0
- package/src/config/enable$get.ts +30 -0
- package/src/config/enableReactComponents.ts +26 -0
- package/src/config/enableReactNativeComponents.ts +102 -0
- package/src/config/enableReactTracking.ts +60 -0
- package/src/config/enableReactUse.ts +23 -0
- package/src/config/enable_peek.ts +31 -0
- package/src/config.ts +47 -0
- package/src/createObservable.ts +46 -0
- package/src/event.ts +26 -0
- package/src/globals.ts +224 -0
- package/src/helpers/fetch.ts +26 -0
- package/src/helpers/pageHash.ts +41 -0
- package/src/helpers/pageHashParams.ts +55 -0
- package/src/helpers/time.ts +30 -0
- package/src/helpers.ts +221 -0
- package/src/history/trackHistory.ts +29 -0
- package/src/is.ts +56 -0
- package/src/linked.ts +6 -0
- package/src/observable.ts +32 -0
- package/src/observableInterfaces.ts +165 -0
- package/src/observableTypes.ts +221 -0
- package/src/observe.ts +89 -0
- package/src/onChange.ts +136 -0
- package/src/persist/configureObservablePersistence.ts +7 -0
- package/src/persist/fieldTransformer.ts +149 -0
- package/src/persist/observablePersistRemoteFunctionsAdapter.ts +39 -0
- package/src/persist/persistObservable.ts +1029 -0
- package/src/persist-plugins/async-storage.ts +102 -0
- package/src/persist-plugins/fetch.ts +33 -0
- package/src/persist-plugins/firebase.ts +1050 -0
- package/src/persist-plugins/indexeddb.ts +433 -0
- package/src/persist-plugins/local-storage.ts +90 -0
- package/src/persist-plugins/mmkv.ts +90 -0
- package/src/persist-plugins/query.ts +133 -0
- package/src/persistTypes.ts +226 -0
- package/src/proxy.ts +28 -0
- package/src/react/Computed.tsx +7 -0
- package/src/react/For.tsx +116 -0
- package/src/react/Memo.tsx +4 -0
- package/src/react/Reactive.tsx +53 -0
- package/src/react/Show.tsx +33 -0
- package/src/react/Switch.tsx +43 -0
- package/src/react/react-globals.ts +3 -0
- package/src/react/{reactInterfaces.d.ts → reactInterfaces.ts} +15 -7
- package/src/react/reactive-observer.tsx +210 -0
- package/src/react/useComputed.ts +36 -0
- package/src/react/useEffectOnce.ts +41 -0
- package/src/react/useIsMounted.ts +16 -0
- package/src/react/useMount.ts +15 -0
- package/src/react/useObservable.ts +24 -0
- package/src/react/useObservableReducer.ts +52 -0
- package/src/react/useObservableState.ts +30 -0
- package/src/react/useObserve.ts +54 -0
- package/src/react/useObserveEffect.ts +40 -0
- package/src/react/usePauseProvider.tsx +13 -0
- package/src/react/useSelector.ts +167 -0
- package/src/react/useUnmount.ts +8 -0
- package/src/react/useWhen.ts +9 -0
- package/src/react-hooks/createObservableHook.ts +53 -0
- package/src/react-hooks/useFetch.ts +16 -0
- package/src/react-hooks/useHover.ts +40 -0
- package/src/react-hooks/useMeasure.ts +48 -0
- package/src/react-hooks/useObservableNextRouter.ts +137 -0
- package/src/react-hooks/useObservableQuery.ts +205 -0
- package/src/react-hooks/usePersistedObservable.ts +24 -0
- package/src/retry.ts +69 -0
- package/src/setupTracking.ts +26 -0
- package/src/sync/activateSyncedNode.ts +146 -0
- package/src/sync/configureObservableSync.ts +7 -0
- package/src/sync/syncHelpers.ts +15 -0
- package/src/sync/syncObservable.ts +989 -0
- package/src/sync/syncObservableAdapter.ts +30 -0
- package/src/sync/synced.ts +20 -0
- package/src/sync-plugins/fetch.ts +42 -0
- package/src/syncTypes.ts +163 -0
- package/src/trace/traceHelpers.ts +11 -0
- package/src/trace/useTraceListeners.ts +34 -0
- package/src/trace/useTraceUpdates.ts +24 -0
- package/src/trace/useVerifyNotTracking.ts +33 -0
- package/src/trace/useVerifyOneRender.ts +10 -0
- package/src/trackSelector.ts +52 -0
- package/src/tracking.ts +43 -0
- package/src/types/babel.d.ts +12 -0
- package/src/when.ts +70 -0
- package/sync-plugins/fetch.d.ts +11 -0
- package/sync-plugins/fetch.js +24 -0
- package/sync-plugins/fetch.js.map +1 -0
- package/sync-plugins/fetch.mjs +22 -0
- package/sync-plugins/fetch.mjs.map +1 -0
- package/sync.d.ts +8 -0
- package/sync.js +919 -0
- package/sync.js.map +1 -0
- package/sync.mjs +912 -0
- package/sync.mjs.map +1 -0
- package/trace.js +13 -10
- package/trace.js.map +1 -1
- package/trace.mjs +11 -8
- package/trace.mjs.map +1 -1
- package/types/babel.d.ts +3 -3
- package/config/enableDirectAccess.d.ts +0 -7
- package/config/enableDirectAccess.js +0 -25
- package/config/enableDirectAccess.js.map +0 -1
- package/config/enableDirectAccess.mjs +0 -23
- package/config/enableDirectAccess.mjs.map +0 -1
- package/config/enableDirectPeek.d.ts +0 -7
- package/config/enableDirectPeek.js.map +0 -1
- package/config/enableDirectPeek.mjs.map +0 -1
- package/config/enableReactDirectRender.d.ts +0 -2
- package/config/enableReactDirectRender.js +0 -78
- package/config/enableReactDirectRender.js.map +0 -1
- package/config/enableReactDirectRender.mjs +0 -75
- package/config/enableReactDirectRender.mjs.map +0 -1
- package/src/ObservableObject.d.ts +0 -14
- package/src/ObservablePrimitive.d.ts +0 -7
- package/src/babel/index.d.ts +0 -17
- package/src/batching.d.ts +0 -6
- package/src/computed.d.ts +0 -4
- package/src/config/enableDirectAccess.d.ts +0 -7
- package/src/config/enableDirectPeek.d.ts +0 -7
- package/src/config/enableReactComponents.d.ts +0 -7
- package/src/config/enableReactDirectRender.d.ts +0 -2
- package/src/config/enableReactNativeComponents.d.ts +0 -20
- package/src/config/enableReactTracking.d.ts +0 -15
- package/src/config/enableReactUse.d.ts +0 -7
- package/src/config.d.ts +0 -8
- package/src/createObservable.d.ts +0 -2
- package/src/event.d.ts +0 -2
- package/src/globals.d.ts +0 -32
- package/src/helpers/fetch.d.ts +0 -6
- package/src/helpers/pageHash.d.ts +0 -7
- package/src/helpers/pageHashParams.d.ts +0 -7
- package/src/helpers/time.d.ts +0 -3
- package/src/helpers.d.ts +0 -13
- package/src/history/trackHistory.d.ts +0 -4
- package/src/is.d.ts +0 -10
- package/src/observable.d.ts +0 -16
- package/src/observableInterfaces.d.ts +0 -456
- package/src/observe.d.ts +0 -6
- package/src/onChange.d.ts +0 -7
- package/src/persist/configureObservablePersistence.d.ts +0 -3
- package/src/persist/fieldTransformer.d.ts +0 -8
- package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +0 -2
- package/src/persist/persistActivateNode.d.ts +0 -1
- package/src/persist/persistHelpers.d.ts +0 -1
- package/src/persist/persistObservable.d.ts +0 -25
- package/src/persist-plugins/async-storage.d.ts +0 -14
- package/src/persist-plugins/fetch.d.ts +0 -10
- package/src/persist-plugins/firebase.d.ts +0 -51
- package/src/persist-plugins/indexeddb.d.ts +0 -25
- package/src/persist-plugins/local-storage.d.ts +0 -21
- package/src/persist-plugins/mmkv.d.ts +0 -14
- package/src/persist-plugins/query.d.ts +0 -18
- package/src/proxy.d.ts +0 -5
- package/src/react/Computed.d.ts +0 -5
- package/src/react/For.d.ts +0 -15
- package/src/react/Memo.d.ts +0 -3
- package/src/react/Reactive.d.ts +0 -9
- package/src/react/Show.d.ts +0 -18
- package/src/react/Switch.d.ts +0 -14
- package/src/react/react-globals.d.ts +0 -3
- package/src/react/reactive-observer.d.ts +0 -14
- package/src/react/useComputed.d.ts +0 -5
- package/src/react/useEffectOnce.d.ts +0 -1
- package/src/react/useIsMounted.d.ts +0 -2
- package/src/react/useMount.d.ts +0 -2
- package/src/react/useObservable.d.ts +0 -9
- package/src/react/useObservableReducer.d.ts +0 -7
- package/src/react/useObservableState.d.ts +0 -2
- package/src/react/useObserve.d.ts +0 -4
- package/src/react/useObserveEffect.d.ts +0 -4
- package/src/react/usePauseProvider.d.ts +0 -8
- package/src/react/useSelector.d.ts +0 -3
- package/src/react/useUnmount.d.ts +0 -2
- package/src/react/useWhen.d.ts +0 -3
- package/src/react-hooks/createObservableHook.d.ts +0 -2
- package/src/react-hooks/useFetch.d.ts +0 -6
- package/src/react-hooks/useHover.d.ts +0 -3
- package/src/react-hooks/useMeasure.d.ts +0 -6
- package/src/react-hooks/useObservableNextRouter.d.ts +0 -33
- package/src/react-hooks/useObservableQuery.d.ts +0 -6
- package/src/react-hooks/usePersistedObservable.d.ts +0 -11
- package/src/retry.d.ts +0 -9
- package/src/setupTracking.d.ts +0 -2
- package/src/trace/traceHelpers.d.ts +0 -2
- package/src/trace/useTraceListeners.d.ts +0 -1
- package/src/trace/useTraceUpdates.d.ts +0 -1
- package/src/trace/useVerifyNotTracking.d.ts +0 -1
- package/src/trace/useVerifyOneRender.d.ts +0 -1
- package/src/trackSelector.d.ts +0 -7
- package/src/tracking.d.ts +0 -13
- package/src/when.d.ts +0 -3
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import type { FC, LegacyRef, ReactNode } from 'react';
|
|
2
|
-
import type { Observable
|
|
2
|
+
import type { Observable } from '../observableTypes';
|
|
3
|
+
import type { Selector } from '../observableInterfaces';
|
|
4
|
+
|
|
3
5
|
export type ShapeWithNew$<T> = Partial<Omit<T, 'children'>> & {
|
|
4
6
|
[K in keyof T as K extends `$${string & K}` ? K : `$${string & K}`]?: Selector<T[K]>;
|
|
5
|
-
} & {
|
|
6
|
-
|
|
7
|
-
};
|
|
7
|
+
} & { children?: Selector<ReactNode> };
|
|
8
|
+
|
|
8
9
|
export interface BindKey<P> {
|
|
9
10
|
handler?: keyof P;
|
|
10
11
|
getValue?: (e: any) => any;
|
|
11
12
|
defaultValue?: any;
|
|
12
13
|
selector?: (propsOut: Record<string, any>, p: Observable<any>) => any;
|
|
13
14
|
}
|
|
15
|
+
|
|
14
16
|
export type BindKeys<P = any> = Record<keyof P, BindKey<P>>;
|
|
17
|
+
|
|
15
18
|
export type FCReactiveObject<T> = {
|
|
16
19
|
[K in keyof T]: FC<ShapeWithNew$<T[K]>>;
|
|
17
20
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
export type FCReactive<P, P2> = P &
|
|
23
|
+
FC<
|
|
24
|
+
ShapeWithNew$<P2> & {
|
|
25
|
+
ref?: LegacyRef<P> | undefined;
|
|
26
|
+
}
|
|
27
|
+
>;
|
|
28
|
+
|
|
21
29
|
export interface UseSelectorOptions {
|
|
22
30
|
suspense?: boolean;
|
|
23
31
|
skipCheck?: boolean;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { isFunction, isObservable, Selector } from '@legendapp/state';
|
|
2
|
+
import { ChangeEvent, FC, forwardRef, memo, useCallback } from 'react';
|
|
3
|
+
import { reactGlobals } from './react-globals';
|
|
4
|
+
import type { BindKeys } from './reactInterfaces';
|
|
5
|
+
import { useSelector } from './useSelector';
|
|
6
|
+
|
|
7
|
+
export type ShapeWithPick$<T, T2 extends keyof T = keyof T> = Partial<T> & {
|
|
8
|
+
[K in T2 as K extends `$${string & K}` ? K : `$${string & K}`]?: Selector<T[K]>;
|
|
9
|
+
};
|
|
10
|
+
export type ShapeWith$<T> = Partial<T> & {
|
|
11
|
+
[K in keyof T as K extends `$${string & K}` ? K : `$${string & K}`]?: Selector<T[K]>;
|
|
12
|
+
};
|
|
13
|
+
export type ObjectShapeWith$<T> = {
|
|
14
|
+
[K in keyof T]: T[K] extends FC<infer P> ? FC<ShapeWith$<P>> : T[K];
|
|
15
|
+
};
|
|
16
|
+
export type ExtractFCPropsType<T> = T extends FC<infer P> ? P : never;
|
|
17
|
+
|
|
18
|
+
// Extracting the forwardRef inspired by https://github.com/mobxjs/mobx/blob/main/packages/mobx-react-lite/src/observer.ts
|
|
19
|
+
export const hasSymbol = /* @__PURE__ */ typeof Symbol === 'function' && Symbol.for;
|
|
20
|
+
|
|
21
|
+
// TODOV2: Change bindKeys to an options object, where one of the options is "convertChildren" so that behavior can be optional
|
|
22
|
+
function createReactiveComponent<P = object>(
|
|
23
|
+
component: FC<P>,
|
|
24
|
+
observe: boolean,
|
|
25
|
+
reactive?: boolean,
|
|
26
|
+
bindKeys?: BindKeys<P>,
|
|
27
|
+
) {
|
|
28
|
+
const ReactForwardRefSymbol = hasSymbol
|
|
29
|
+
? Symbol.for('react.forward_ref')
|
|
30
|
+
: // eslint-disable-next-line react/display-name, @typescript-eslint/no-unused-vars
|
|
31
|
+
typeof forwardRef === 'function' && forwardRef((props: any) => null)['$$typeof'];
|
|
32
|
+
|
|
33
|
+
const ReactMemoSymbol = hasSymbol
|
|
34
|
+
? Symbol.for('react.memo')
|
|
35
|
+
: // eslint-disable-next-line react/display-name, @typescript-eslint/no-unused-vars
|
|
36
|
+
typeof forwardRef === 'function' && memo((props) => null)['$$typeof'];
|
|
37
|
+
|
|
38
|
+
// If this component is already reactive bail out early
|
|
39
|
+
// This can happen with Fast Refresh.
|
|
40
|
+
if ((component as any)['__legend_proxied']) return component;
|
|
41
|
+
|
|
42
|
+
let useForwardRef = false;
|
|
43
|
+
let useMemo = false;
|
|
44
|
+
let render = component;
|
|
45
|
+
|
|
46
|
+
// Unwrap memo on the component
|
|
47
|
+
if (ReactMemoSymbol && (render as any)['$$typeof'] === ReactMemoSymbol && (render as any)['type']) {
|
|
48
|
+
useMemo = true;
|
|
49
|
+
render = (render as any)['type'];
|
|
50
|
+
}
|
|
51
|
+
// Unwrap forwardRef on the component
|
|
52
|
+
if (ReactForwardRefSymbol && (render as any)['$$typeof'] === ReactForwardRefSymbol) {
|
|
53
|
+
useForwardRef = true;
|
|
54
|
+
render = (render as any)['render'];
|
|
55
|
+
if (process.env.NODE_ENV === 'development' && typeof render !== 'function') {
|
|
56
|
+
throw new Error(`[legend-state] \`render\` property of ForwardRef was not a function`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const proxyHandler: ProxyHandler<any> = {
|
|
61
|
+
apply(target, thisArg, argArray) {
|
|
62
|
+
// If this is a reactive component, convert all props ending in $
|
|
63
|
+
// to regular props and set up a useSelector listener
|
|
64
|
+
if (reactive) {
|
|
65
|
+
const props = argArray[0];
|
|
66
|
+
const propsOut = {} as Record<string, any>;
|
|
67
|
+
const keys = Object.keys(props);
|
|
68
|
+
for (let i = 0; i < keys.length; i++) {
|
|
69
|
+
const key = keys[i];
|
|
70
|
+
const p = props[key];
|
|
71
|
+
|
|
72
|
+
// Convert children if it's a function
|
|
73
|
+
if (key === 'children' && (isFunction(p) || isObservable(p))) {
|
|
74
|
+
props[key] = useSelector(p, { skipCheck: true });
|
|
75
|
+
}
|
|
76
|
+
// Convert reactive props
|
|
77
|
+
else if (key.startsWith('$') || key.endsWith('$')) {
|
|
78
|
+
// TODOV3 Add this warning and then remove the deprecated endsWith option
|
|
79
|
+
// if (
|
|
80
|
+
// process.env.NODE_ENV === 'development' &&
|
|
81
|
+
// !internal.globalState.noDepWarn &&
|
|
82
|
+
// key.endsWith('$')
|
|
83
|
+
// ) {
|
|
84
|
+
// console.warn(
|
|
85
|
+
// `[legend-state] Reactive props will be changed to start with $ instead of end with $ in version 2.0. So please change ${key} to $${key.replace(
|
|
86
|
+
// '$',
|
|
87
|
+
// '',
|
|
88
|
+
// )}. See https://legendapp.com/open-source/state/migrating for more details.`,
|
|
89
|
+
// );
|
|
90
|
+
// }
|
|
91
|
+
const k = key.endsWith('$') ? key.slice(0, -1) : key.slice(1);
|
|
92
|
+
// Return raw value and listen to the selector for changes
|
|
93
|
+
|
|
94
|
+
const bind = bindKeys?.[k as keyof P];
|
|
95
|
+
const shouldBind = bind && isObservable(p);
|
|
96
|
+
|
|
97
|
+
propsOut[k] = shouldBind && bind?.selector ? bind.selector(propsOut, p) : useSelector(p);
|
|
98
|
+
|
|
99
|
+
// If this key is one of the bind keys set up a two-way binding
|
|
100
|
+
if (shouldBind) {
|
|
101
|
+
// Use the bind's defaultValue if value is undefined
|
|
102
|
+
if (bind.defaultValue !== undefined && propsOut[k] === undefined) {
|
|
103
|
+
propsOut[k] = bind.defaultValue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (bind.handler && bind.getValue) {
|
|
107
|
+
// Hook up the change lander
|
|
108
|
+
const handlerFn = (e: ChangeEvent) => {
|
|
109
|
+
p.set(bind.getValue!(e));
|
|
110
|
+
props[bind.handler!]?.(e);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
(propsOut[bind.handler as string] as any) =
|
|
114
|
+
// If in development mode, don't memoize the handler. fix fast refresh bug
|
|
115
|
+
process.env.NODE_ENV === 'development'
|
|
116
|
+
? handlerFn
|
|
117
|
+
: useCallback(handlerFn, [props[bind.handler], bindKeys]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Delete the reactive key
|
|
122
|
+
delete propsOut[key];
|
|
123
|
+
} else if (propsOut[key] === undefined) {
|
|
124
|
+
propsOut[key] = p;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
argArray[0] = propsOut;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If observing wrap the whole render in a useSelector to listen to it
|
|
131
|
+
if (observe) {
|
|
132
|
+
return useSelector(
|
|
133
|
+
() => {
|
|
134
|
+
reactGlobals.inObserver = true;
|
|
135
|
+
try {
|
|
136
|
+
return Reflect.apply(target, thisArg, argArray);
|
|
137
|
+
} finally {
|
|
138
|
+
reactGlobals.inObserver = false;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{ skipCheck: true },
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
return Reflect.apply(target, thisArg, argArray);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const proxy = new Proxy(render, proxyHandler);
|
|
150
|
+
|
|
151
|
+
let ret;
|
|
152
|
+
|
|
153
|
+
if (useForwardRef) {
|
|
154
|
+
ret = forwardRef(proxy);
|
|
155
|
+
(ret as any)['__legend_proxied'] = true;
|
|
156
|
+
} else {
|
|
157
|
+
ret = proxy;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return observe || useMemo ? memo(ret) : ret;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function observer<P extends FC<any>>(component: P): P {
|
|
164
|
+
return createReactiveComponent(component, true);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function reactive<T extends FC<any>>(
|
|
168
|
+
component: T,
|
|
169
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
170
|
+
): T | FC<ShapeWith$<ExtractFCPropsType<T>>>;
|
|
171
|
+
export function reactive<T extends FC<any>, T2 extends keyof ExtractFCPropsType<T>>(
|
|
172
|
+
component: T,
|
|
173
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
174
|
+
): T | FC<ShapeWithPick$<ExtractFCPropsType<T>, T2>>;
|
|
175
|
+
export function reactive<T extends FC<any>>(
|
|
176
|
+
component: T,
|
|
177
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
178
|
+
): T | FC<ShapeWith$<ExtractFCPropsType<T>>> {
|
|
179
|
+
return createReactiveComponent(component, false, true, bindKeys);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function reactiveObserver<T extends FC<any>>(
|
|
183
|
+
component: T,
|
|
184
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
185
|
+
): T | FC<ShapeWith$<ExtractFCPropsType<T>>>;
|
|
186
|
+
export function reactiveObserver<T extends FC<any>, T2 extends keyof ExtractFCPropsType<T>>(
|
|
187
|
+
component: T,
|
|
188
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
189
|
+
): T | FC<ShapeWithPick$<ExtractFCPropsType<T>, T2>>;
|
|
190
|
+
export function reactiveObserver<T extends FC<any>>(
|
|
191
|
+
component: T,
|
|
192
|
+
bindKeys?: BindKeys<ExtractFCPropsType<T>>,
|
|
193
|
+
): T | FC<ShapeWith$<ExtractFCPropsType<T>>> {
|
|
194
|
+
return createReactiveComponent(component, true, true, bindKeys);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function reactiveComponents<P extends Record<string, FC>>(components: P): ObjectShapeWith$<P> {
|
|
198
|
+
return new Proxy(
|
|
199
|
+
{},
|
|
200
|
+
{
|
|
201
|
+
get(target: Record<string, any>, p: string) {
|
|
202
|
+
if (!target[p] && components[p]) {
|
|
203
|
+
target[p] = createReactiveComponent(components[p], false, true) as FC<ShapeWith$<P>>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return target[p];
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
) as ObjectShapeWith$<P>;
|
|
210
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { computed, isArray, isFunction, Observable, ObservableParam } from '@legendapp/state';
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
export function useComputed<T>(compute: () => T | Promise<T>): Observable<T>;
|
|
5
|
+
export function useComputed<T>(compute: () => T | Promise<T>, deps: any[]): Observable<T>;
|
|
6
|
+
export function useComputed<T, T2 = T>(
|
|
7
|
+
compute: (() => T | Promise<T>) | ObservableParam<T>,
|
|
8
|
+
set: (value: T2) => void,
|
|
9
|
+
): Observable<T>;
|
|
10
|
+
export function useComputed<T, T2 = T>(
|
|
11
|
+
compute: (() => T | Promise<T>) | ObservableParam<T>,
|
|
12
|
+
set: (value: T2) => void,
|
|
13
|
+
deps: any[],
|
|
14
|
+
): Observable<T>;
|
|
15
|
+
export function useComputed<T, T2 = T>(
|
|
16
|
+
compute: (() => T | Promise<T>) | ObservableParam<T>,
|
|
17
|
+
set?: ((value: T2) => void) | any[],
|
|
18
|
+
deps?: any[],
|
|
19
|
+
): Observable<T> {
|
|
20
|
+
if (!deps && isArray(set)) {
|
|
21
|
+
deps = set;
|
|
22
|
+
set = undefined;
|
|
23
|
+
}
|
|
24
|
+
const ref = useRef<{ compute?: (() => T | Promise<T>) | ObservableParam<T>; set?: (value: T2) => void }>({});
|
|
25
|
+
ref.current.compute = compute;
|
|
26
|
+
ref.current.set = set as (value: T2) => void;
|
|
27
|
+
|
|
28
|
+
return useMemo(
|
|
29
|
+
() =>
|
|
30
|
+
computed<T, T2>(
|
|
31
|
+
() => (isFunction(ref.current.compute) ? ref.current.compute() : ref.current.compute) as any,
|
|
32
|
+
(set ? (value) => ref.current.set!(value) : undefined) as (value: T2) => void,
|
|
33
|
+
),
|
|
34
|
+
deps || [],
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isFunction } from '@legendapp/state';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
export const useEffectOnce = (effect: () => void | (() => void), deps: any[]) => {
|
|
5
|
+
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
6
|
+
const refDispose = useRef<{ dispose?: void | (() => void); num: number }>({ num: 0 });
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
// This is a hack to work around StrictMode running effects twice.
|
|
10
|
+
// On the first run it returns a cleanup function that queues the dispose function
|
|
11
|
+
// in a microtask. This way it will run at the end of the frame after StrictMode's second
|
|
12
|
+
// run of the effect. If it's run a second time then the microtasked dispose will do nothing,
|
|
13
|
+
// but the effect will return the dispose again so that when it actually unmounts it will dispose.
|
|
14
|
+
// If not in StrictMode, then the dispose function will run in the microtask.
|
|
15
|
+
// It's possible that this is not safe in 100% of cases, but I'm not sure what the
|
|
16
|
+
// dangerous cases would be. The side effect is that the listener is still active
|
|
17
|
+
// until the end of the frame, but that's probably not a problem.
|
|
18
|
+
const { current } = refDispose;
|
|
19
|
+
current.num++;
|
|
20
|
+
const dispose = () => {
|
|
21
|
+
if (current.dispose && current.num < 2) {
|
|
22
|
+
(current.dispose as () => void)();
|
|
23
|
+
current.dispose = undefined;
|
|
24
|
+
}
|
|
25
|
+
current.num--;
|
|
26
|
+
};
|
|
27
|
+
if (current.dispose === undefined) {
|
|
28
|
+
const ret = effect() ?? null;
|
|
29
|
+
// If ret is a function, then it's a dispose function.
|
|
30
|
+
if (ret && isFunction(ret)) {
|
|
31
|
+
current.dispose = ret;
|
|
32
|
+
return () => queueMicrotask(dispose);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
return dispose;
|
|
36
|
+
}
|
|
37
|
+
}, deps);
|
|
38
|
+
} else {
|
|
39
|
+
useEffect(effect, deps);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Observable } from '@legendapp/state';
|
|
2
|
+
import { useMountOnce } from './useMount';
|
|
3
|
+
import { useObservable } from './useObservable';
|
|
4
|
+
|
|
5
|
+
export function useIsMounted(): Observable<boolean> {
|
|
6
|
+
const obs = useObservable(false);
|
|
7
|
+
|
|
8
|
+
const { set } = obs;
|
|
9
|
+
useMountOnce(() => {
|
|
10
|
+
set(true);
|
|
11
|
+
|
|
12
|
+
return () => set(false);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return obs;
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isPromise } from '@legendapp/state';
|
|
2
|
+
import { useEffectOnce } from './useEffectOnce';
|
|
3
|
+
|
|
4
|
+
export function useMount(fn: () => (void | (() => void)) | Promise<void>) {
|
|
5
|
+
return useEffectOnce(() => {
|
|
6
|
+
const ret = fn();
|
|
7
|
+
// Allow the function to be async but if so ignore its return value
|
|
8
|
+
if (!isPromise(ret)) {
|
|
9
|
+
return ret;
|
|
10
|
+
}
|
|
11
|
+
}, []);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// TODOV4 Deprecate
|
|
15
|
+
export const useMountOnce = useMount;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { observable, Observable, RecursiveValueOrFunction } from '@legendapp/state';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A React hook that creates a new observable
|
|
6
|
+
*
|
|
7
|
+
* @param initialValue The initial value of the observable or a function that returns the initial value
|
|
8
|
+
*
|
|
9
|
+
* @see https://www.legendapp.com/dev/state/react/#useObservable
|
|
10
|
+
*/
|
|
11
|
+
export function useObservable<T>(): Observable<T | undefined>;
|
|
12
|
+
export function useObservable<T>(
|
|
13
|
+
value: Promise<RecursiveValueOrFunction<T>> | (() => RecursiveValueOrFunction<T>) | RecursiveValueOrFunction<T>,
|
|
14
|
+
): Observable<T>;
|
|
15
|
+
export function useObservable<T>(value: T): Observable<T>;
|
|
16
|
+
export function useObservable<T>(value?: T): Observable<any>;
|
|
17
|
+
export function useObservable<T>(initialValue?: T | (() => T) | (() => Promise<T>)): Observable<T> {
|
|
18
|
+
const ref = useRef<Observable<T>>();
|
|
19
|
+
if (!ref.current) {
|
|
20
|
+
// Create the observable from the default value
|
|
21
|
+
ref.current = observable<T>(initialValue as any);
|
|
22
|
+
}
|
|
23
|
+
return ref.current;
|
|
24
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Observable } from '@legendapp/state';
|
|
2
|
+
import { isFunction } from '@legendapp/state';
|
|
3
|
+
import type {
|
|
4
|
+
Dispatch,
|
|
5
|
+
DispatchWithoutAction,
|
|
6
|
+
Reducer,
|
|
7
|
+
ReducerAction,
|
|
8
|
+
ReducerState,
|
|
9
|
+
ReducerStateWithoutAction,
|
|
10
|
+
ReducerWithoutAction,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import { useObservable } from './useObservable';
|
|
13
|
+
|
|
14
|
+
export function useObservableReducer<R extends ReducerWithoutAction<any>, I>(
|
|
15
|
+
reducer: R,
|
|
16
|
+
initializerArg: I,
|
|
17
|
+
initializer: (arg: I) => ReducerStateWithoutAction<R>,
|
|
18
|
+
): [Observable<ReducerStateWithoutAction<R>>, DispatchWithoutAction];
|
|
19
|
+
export function useObservableReducer<R extends ReducerWithoutAction<any>>(
|
|
20
|
+
reducer: R,
|
|
21
|
+
initializerArg: ReducerStateWithoutAction<R>,
|
|
22
|
+
initializer?: undefined,
|
|
23
|
+
): [Observable<ReducerStateWithoutAction<R>>, DispatchWithoutAction];
|
|
24
|
+
export function useObservableReducer<R extends Reducer<any, any>, I>(
|
|
25
|
+
reducer: R,
|
|
26
|
+
initializerArg: I & ReducerState<R>,
|
|
27
|
+
initializer: (arg: I & ReducerState<R>) => ReducerState<R>,
|
|
28
|
+
): [Observable<ReducerState<R>>, Dispatch<ReducerAction<R>>];
|
|
29
|
+
export function useObservableReducer<R extends Reducer<any, any>, I>(
|
|
30
|
+
reducer: R,
|
|
31
|
+
initializerArg: I,
|
|
32
|
+
initializer: (arg: I) => ReducerState<R>,
|
|
33
|
+
): [Observable<ReducerState<R>>, Dispatch<ReducerAction<R>>];
|
|
34
|
+
export function useObservableReducer<R extends Reducer<any, any>>(
|
|
35
|
+
reducer: R,
|
|
36
|
+
initialState: ReducerState<R>,
|
|
37
|
+
initializer?: undefined,
|
|
38
|
+
): [Observable<ReducerState<R>>, Dispatch<ReducerAction<R>>];
|
|
39
|
+
export function useObservableReducer<R extends Reducer<any, any>, I>(
|
|
40
|
+
reducer: R,
|
|
41
|
+
initializerArg: I & ReducerState<R>,
|
|
42
|
+
initializer: ((arg: I & ReducerState<R>) => ReducerState<R>) | undefined,
|
|
43
|
+
): [Observable<ReducerState<R>>, Dispatch<ReducerAction<R>>] {
|
|
44
|
+
const obs = useObservable(() =>
|
|
45
|
+
initializerArg !== undefined && isFunction(initializerArg) ? initializer!(initializerArg) : initializerArg,
|
|
46
|
+
);
|
|
47
|
+
const dispatch = (action: any) => {
|
|
48
|
+
obs.set(reducer(obs.get(), action));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return [obs as Observable<ReducerState<R>>, dispatch];
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isFunction, observable, type Observable } from '@legendapp/state';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useSelector } from './useSelector';
|
|
4
|
+
|
|
5
|
+
export function useObservableState<T>(initialValue?: T | (() => T) | (() => Promise<T>)): [Observable<T>, T] {
|
|
6
|
+
// Create a memoized observable
|
|
7
|
+
return useMemo(
|
|
8
|
+
() =>
|
|
9
|
+
// Wrap the return array in a Proxy to detect whether the value is accessed
|
|
10
|
+
new Proxy(
|
|
11
|
+
[
|
|
12
|
+
observable<T>((isFunction(initialValue) ? initialValue() : initialValue) as any),
|
|
13
|
+
// Second element of the array just needs to exist for the Proxy to access it
|
|
14
|
+
// but we can't ensure it's updated with the real value, and it doesn't really matter since it's proxied,
|
|
15
|
+
// so just make it undefined. Alternatively the Proxy handler could manually return 2 for the "length" prop
|
|
16
|
+
// but this seems easier and less code.
|
|
17
|
+
undefined,
|
|
18
|
+
],
|
|
19
|
+
proxyHandler,
|
|
20
|
+
),
|
|
21
|
+
[],
|
|
22
|
+
) as [Observable<T>, T];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const proxyHandler: ProxyHandler<any[]> = {
|
|
26
|
+
get(target, prop, receiver) {
|
|
27
|
+
// If the value is accessed at index 1 then `useSelector` to track it for changes
|
|
28
|
+
return prop === '1' ? useSelector(target[0]) : Reflect.get(target, prop, receiver);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computeSelector,
|
|
3
|
+
isFunction,
|
|
4
|
+
ObservableParam,
|
|
5
|
+
observe,
|
|
6
|
+
ObserveEvent,
|
|
7
|
+
ObserveEventCallback,
|
|
8
|
+
Selector,
|
|
9
|
+
} from '@legendapp/state';
|
|
10
|
+
import { useRef } from 'react';
|
|
11
|
+
import type { ObserveOptions } from '../observe';
|
|
12
|
+
import { useUnmountOnce } from './useUnmount';
|
|
13
|
+
|
|
14
|
+
export function useObserve<T>(run: (e: ObserveEvent<T>) => T | void, options?: ObserveOptions): () => void;
|
|
15
|
+
export function useObserve<T>(
|
|
16
|
+
selector: Selector<T>,
|
|
17
|
+
reaction?: (e: ObserveEventCallback<T>) => any,
|
|
18
|
+
options?: ObserveOptions,
|
|
19
|
+
): () => void;
|
|
20
|
+
export function useObserve<T>(
|
|
21
|
+
selector: Selector<T> | ((e: ObserveEvent<T>) => any),
|
|
22
|
+
reactionOrOptions?: ((e: ObserveEventCallback<T>) => any) | ObserveOptions,
|
|
23
|
+
options?: ObserveOptions,
|
|
24
|
+
): () => void {
|
|
25
|
+
let reaction: ((e: ObserveEventCallback<T>) => any) | undefined;
|
|
26
|
+
if (isFunction(reactionOrOptions)) {
|
|
27
|
+
reaction = reactionOrOptions;
|
|
28
|
+
} else {
|
|
29
|
+
options = reactionOrOptions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const ref = useRef<{
|
|
33
|
+
selector?: Selector<T> | ((e: ObserveEvent<T>) => T | void) | ObservableParam<T>;
|
|
34
|
+
reaction?: (e: ObserveEventCallback<T>) => any;
|
|
35
|
+
dispose?: () => void;
|
|
36
|
+
}>({});
|
|
37
|
+
|
|
38
|
+
ref.current.selector = selector;
|
|
39
|
+
ref.current.reaction = reaction;
|
|
40
|
+
|
|
41
|
+
if (!ref.current.dispose) {
|
|
42
|
+
ref.current.dispose = observe<T>(
|
|
43
|
+
((e: ObserveEventCallback<T>) => computeSelector(ref.current.selector, e)) as any,
|
|
44
|
+
(e) => ref.current.reaction?.(e),
|
|
45
|
+
options,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
useUnmountOnce(() => {
|
|
50
|
+
ref.current?.dispose?.();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return ref.current.dispose;
|
|
54
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isFunction, ObservableParam, observe, ObserveEvent, ObserveEventCallback, Selector } from '@legendapp/state';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import type { ObserveOptions } from '../observe';
|
|
4
|
+
import { useMountOnce } from './useMount';
|
|
5
|
+
|
|
6
|
+
export function useObserveEffect<T>(run: (e: ObserveEvent<T>) => T | void, options?: ObserveOptions): void;
|
|
7
|
+
export function useObserveEffect<T>(
|
|
8
|
+
selector: Selector<T>,
|
|
9
|
+
reaction?: (e: ObserveEventCallback<T>) => any,
|
|
10
|
+
options?: ObserveOptions,
|
|
11
|
+
): void;
|
|
12
|
+
export function useObserveEffect<T>(
|
|
13
|
+
selector: Selector<T> | ((e: ObserveEvent<T>) => any),
|
|
14
|
+
reactionOrOptions?: ((e: ObserveEventCallback<T>) => any) | ObserveOptions,
|
|
15
|
+
options?: ObserveOptions,
|
|
16
|
+
): void {
|
|
17
|
+
let reaction: ((e: ObserveEventCallback<T>) => any) | undefined;
|
|
18
|
+
if (isFunction(reactionOrOptions)) {
|
|
19
|
+
reaction = reactionOrOptions;
|
|
20
|
+
} else {
|
|
21
|
+
options = reactionOrOptions;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ref = useRef<{
|
|
25
|
+
selector: Selector<T> | ((e: ObserveEvent<T>) => T | void) | ObservableParam<T>;
|
|
26
|
+
reaction?: (e: ObserveEventCallback<T>) => any;
|
|
27
|
+
}>({ selector });
|
|
28
|
+
ref.current = { selector, reaction };
|
|
29
|
+
|
|
30
|
+
useMountOnce(() =>
|
|
31
|
+
observe<T>(
|
|
32
|
+
((e: ObserveEventCallback<T>) => {
|
|
33
|
+
const { selector } = ref.current as { selector: (e: ObserveEvent<T>) => T | void };
|
|
34
|
+
return isFunction(selector) ? selector(e) : selector;
|
|
35
|
+
}) as any,
|
|
36
|
+
(e) => ref.current.reaction?.(e),
|
|
37
|
+
options,
|
|
38
|
+
),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Observable, observable } from '@legendapp/state';
|
|
2
|
+
import { ReactNode, createContext, createElement, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
export const PauseContext = createContext<Observable<boolean>>(null as any);
|
|
5
|
+
|
|
6
|
+
export function usePauseProvider() {
|
|
7
|
+
const [value] = useState(() => observable(false));
|
|
8
|
+
return {
|
|
9
|
+
PauseProvider: ({ children }: { children: ReactNode }) =>
|
|
10
|
+
createElement(PauseContext.Provider, { value }, children),
|
|
11
|
+
isPaused$: value,
|
|
12
|
+
};
|
|
13
|
+
}
|