@legendapp/state 3.0.0-alpha.1 → 3.0.0-alpha.3
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/.DS_Store +0 -0
- package/CHANGELOG.md +1 -831
- package/LICENSE +1 -21
- package/README.md +1 -141
- package/as/arrayAsRecord.d.mts +5 -0
- package/as/arrayAsRecord.d.ts +5 -0
- package/as/arrayAsRecord.js +28 -0
- package/as/arrayAsRecord.mjs +26 -0
- package/as/arrayAsSet.d.mts +5 -0
- package/as/arrayAsSet.d.ts +5 -0
- package/as/arrayAsSet.js +13 -0
- package/as/arrayAsSet.mjs +11 -0
- package/as/arrayAsString.d.mts +5 -0
- package/as/arrayAsString.d.ts +5 -0
- package/as/arrayAsString.js +13 -0
- package/as/arrayAsString.mjs +11 -0
- package/as/numberAsString.d.mts +5 -0
- package/as/numberAsString.d.ts +5 -0
- package/as/numberAsString.js +13 -0
- package/as/numberAsString.mjs +11 -0
- package/as/recordAsArray.d.mts +5 -0
- package/as/recordAsArray.d.ts +5 -0
- package/as/recordAsArray.js +25 -0
- package/as/recordAsArray.mjs +23 -0
- package/as/recordAsString.d.mts +5 -0
- package/as/recordAsString.d.ts +5 -0
- package/as/recordAsString.js +13 -0
- package/as/recordAsString.mjs +11 -0
- package/as/setAsArray.d.mts +5 -0
- package/as/setAsArray.d.ts +5 -0
- package/as/setAsArray.js +13 -0
- package/as/setAsArray.mjs +11 -0
- package/as/setAsString.d.mts +5 -0
- package/as/setAsString.d.ts +5 -0
- package/as/setAsString.js +13 -0
- package/as/setAsString.mjs +11 -0
- package/as/stringAsArray.d.mts +5 -0
- package/as/stringAsArray.d.ts +5 -0
- package/as/stringAsArray.js +13 -0
- package/as/stringAsArray.mjs +11 -0
- package/as/stringAsNumber.d.mts +5 -0
- package/as/stringAsNumber.d.ts +5 -0
- package/as/stringAsNumber.js +16 -0
- package/as/stringAsNumber.mjs +14 -0
- package/as/stringAsRecord.d.mts +5 -0
- package/as/stringAsRecord.d.ts +5 -0
- package/as/stringAsRecord.js +15 -0
- package/as/stringAsRecord.mjs +13 -0
- package/as/stringAsSet.d.mts +5 -0
- package/as/stringAsSet.d.ts +5 -0
- package/as/stringAsSet.js +13 -0
- package/as/stringAsSet.mjs +11 -0
- package/babel.d.mts +21 -0
- package/babel.d.ts +21 -2
- package/babel.js +57 -53
- package/babel.mjs +65 -0
- package/config/enable$GetSet.js +13 -14
- package/config/enable$GetSet.mjs +13 -14
- package/config/enableReactComponents.d.mts +9 -0
- package/config/enableReactComponents.d.ts +4 -2
- package/config/enableReactComponents.js +13 -10
- package/config/enableReactComponents.mjs +13 -10
- package/config/enableReactNativeComponents.d.mts +22 -0
- package/config/enableReactNativeComponents.d.ts +6 -4
- package/config/enableReactNativeComponents.js +43 -47
- package/config/enableReactNativeComponents.mjs +43 -47
- package/config/enableReactTracking.d.mts +7 -0
- package/config/enableReactTracking.d.ts +3 -2
- package/config/enableReactTracking.js +33 -38
- package/config/enableReactTracking.mjs +33 -38
- package/config/enableReactUse.d.mts +10 -0
- package/config/enableReactUse.d.ts +4 -1
- package/config/enableReactUse.js +15 -14
- package/config/enableReactUse.mjs +15 -14
- package/config/{enable$GetSet.d.ts → enable_GetSet.d.mts} +4 -2
- package/config/enable_GetSet.d.ts +10 -0
- package/config/enable_PeekAssign.d.mts +10 -0
- package/config/enable_PeekAssign.d.ts +4 -2
- package/config/enable_PeekAssign.js +13 -14
- package/config/enable_PeekAssign.mjs +13 -14
- package/helpers/pageHash.d.mts +9 -0
- package/helpers/pageHash.d.ts +2 -0
- package/helpers/pageHash.js +25 -30
- package/helpers/pageHash.mjs +25 -30
- package/helpers/pageHashParams.d.mts +9 -0
- package/helpers/pageHashParams.d.ts +2 -0
- package/helpers/pageHashParams.js +34 -37
- package/helpers/pageHashParams.mjs +34 -37
- package/helpers/time.d.mts +6 -0
- package/helpers/time.d.ts +6 -3
- package/helpers/time.js +17 -17
- package/helpers/time.mjs +17 -17
- package/helpers/trackHistory.d.mts +6 -0
- package/helpers/trackHistory.d.ts +4 -2
- package/helpers/trackHistory.js +13 -16
- package/helpers/trackHistory.mjs +13 -16
- package/helpers/undoRedo.d.mts +37 -0
- package/helpers/undoRedo.d.ts +5 -3
- package/helpers/undoRedo.js +59 -94
- package/helpers/undoRedo.mjs +59 -94
- package/index.d.mts +404 -0
- package/index.d.ts +371 -28
- package/index.js +2015 -2166
- package/index.mjs +2015 -2166
- package/package.json +254 -195
- package/persist-plugins/async-storage.d.mts +18 -0
- package/persist-plugins/async-storage.d.ts +6 -3
- package/persist-plugins/async-storage.js +79 -86
- package/persist-plugins/async-storage.mjs +79 -86
- package/persist-plugins/indexeddb.d.mts +29 -0
- package/persist-plugins/indexeddb.d.ts +6 -3
- package/persist-plugins/indexeddb.js +331 -352
- package/persist-plugins/indexeddb.mjs +331 -352
- package/persist-plugins/local-storage.d.mts +23 -0
- package/persist-plugins/local-storage.d.ts +8 -5
- package/persist-plugins/local-storage.js +74 -76
- package/persist-plugins/local-storage.mjs +74 -76
- package/persist-plugins/mmkv.d.mts +18 -0
- package/persist-plugins/mmkv.d.ts +6 -3
- package/persist-plugins/mmkv.js +82 -86
- package/persist-plugins/mmkv.mjs +82 -86
- package/react-hooks/createObservableHook.d.mts +5 -0
- package/react-hooks/createObservableHook.d.ts +4 -1
- package/react-hooks/createObservableHook.js +29 -30
- package/react-hooks/createObservableHook.mjs +25 -30
- package/react-hooks/useHover.d.mts +5 -0
- package/react-hooks/useHover.d.ts +5 -3
- package/react-hooks/useHover.js +29 -29
- package/react-hooks/useHover.mjs +29 -29
- package/react-hooks/useMeasure.d.mts +9 -0
- package/react-hooks/useMeasure.d.ts +5 -2
- package/react-hooks/useMeasure.js +30 -32
- package/react-hooks/useMeasure.mjs +30 -32
- package/react-hooks/useObservableNextRouter.d.mts +35 -0
- package/react-hooks/useObservableNextRouter.d.ts +9 -7
- package/react-hooks/useObservableNextRouter.js +64 -77
- package/react-hooks/useObservableNextRouter.mjs +60 -77
- package/react.d.mts +157 -0
- package/react.d.ts +157 -21
- package/react.js +458 -749
- package/react.mjs +457 -752
- package/sync-plugins/crud.d.mts +54 -0
- package/sync-plugins/crud.d.ts +12 -10
- package/sync-plugins/crud.js +253 -270
- package/sync-plugins/crud.mjs +253 -270
- package/sync-plugins/fetch.d.mts +21 -0
- package/sync-plugins/fetch.d.ts +7 -4
- package/sync-plugins/fetch.js +50 -37
- package/sync-plugins/fetch.mjs +50 -37
- package/sync-plugins/keel.d.mts +108 -0
- package/sync-plugins/keel.d.ts +17 -15
- package/sync-plugins/keel.js +229 -462
- package/sync-plugins/keel.mjs +227 -464
- package/sync-plugins/supabase.d.mts +39 -0
- package/sync-plugins/supabase.d.ts +16 -14
- package/sync-plugins/supabase.js +128 -128
- package/sync-plugins/supabase.mjs +128 -128
- package/sync-plugins/tanstack-query.d.mts +14 -0
- package/sync-plugins/tanstack-query.d.ts +7 -4
- package/sync-plugins/tanstack-query.js +51 -57
- package/sync-plugins/tanstack-query.mjs +51 -57
- package/sync-plugins/tanstack-react-query.d.mts +8 -0
- package/sync-plugins/tanstack-react-query.d.ts +6 -1
- package/sync-plugins/tanstack-react-query.js +2 -2
- package/sync-plugins/tanstack-react-query.mjs +2 -2
- package/sync.d.mts +351 -0
- package/sync.d.ts +349 -9
- package/sync.js +910 -964
- package/sync.mjs +920 -974
- package/trace.d.mts +9 -0
- package/trace.d.ts +9 -4
- package/trace.js +72 -62
- package/trace.mjs +72 -62
- package/types/babel.d.ts +1 -12
- package/babel.js.map +0 -1
- package/config/enable$GetSet.js.map +0 -1
- package/config/enable$GetSet.mjs.map +0 -1
- package/config/enableReactComponents.js.map +0 -1
- package/config/enableReactComponents.mjs.map +0 -1
- package/config/enableReactNativeComponents.js.map +0 -1
- package/config/enableReactNativeComponents.mjs.map +0 -1
- package/config/enableReactTracking.js.map +0 -1
- package/config/enableReactTracking.mjs.map +0 -1
- package/config/enableReactUse.js.map +0 -1
- package/config/enableReactUse.mjs.map +0 -1
- package/config/enable_PeekAssign.js.map +0 -1
- package/config/enable_PeekAssign.mjs.map +0 -1
- package/helpers/pageHash.js.map +0 -1
- package/helpers/pageHash.mjs.map +0 -1
- package/helpers/pageHashParams.js.map +0 -1
- package/helpers/pageHashParams.mjs.map +0 -1
- package/helpers/time.js.map +0 -1
- package/helpers/time.mjs.map +0 -1
- package/helpers/trackHistory.js.map +0 -1
- package/helpers/trackHistory.mjs.map +0 -1
- package/helpers/undoRedo.js.map +0 -1
- package/helpers/undoRedo.mjs.map +0 -1
- package/history.d.ts +0 -1
- package/history.js +0 -24
- package/history.js.map +0 -1
- package/history.mjs +0 -22
- package/history.mjs.map +0 -1
- package/index.js.map +0 -1
- package/index.mjs.map +0 -1
- package/persist-plugins/async-storage.js.map +0 -1
- package/persist-plugins/async-storage.mjs.map +0 -1
- package/persist-plugins/indexeddb.js.map +0 -1
- package/persist-plugins/indexeddb.mjs.map +0 -1
- package/persist-plugins/local-storage.js.map +0 -1
- package/persist-plugins/local-storage.mjs.map +0 -1
- package/persist-plugins/mmkv.js.map +0 -1
- package/persist-plugins/mmkv.mjs.map +0 -1
- package/react-hooks/createObservableHook.js.map +0 -1
- package/react-hooks/createObservableHook.mjs.map +0 -1
- package/react-hooks/useHover.js.map +0 -1
- package/react-hooks/useHover.mjs.map +0 -1
- package/react-hooks/useMeasure.js.map +0 -1
- package/react-hooks/useMeasure.mjs.map +0 -1
- package/react-hooks/useObservableNextRouter.js.map +0 -1
- package/react-hooks/useObservableNextRouter.mjs.map +0 -1
- package/react.js.map +0 -1
- package/react.mjs.map +0 -1
- package/src/ObservableObject.ts +0 -1350
- package/src/ObservablePrimitive.ts +0 -62
- package/src/babel/index.ts +0 -83
- package/src/batching.ts +0 -357
- package/src/computed.ts +0 -18
- package/src/config/enable$GetSet.ts +0 -30
- package/src/config/enableReactComponents.ts +0 -26
- package/src/config/enableReactNativeComponents.ts +0 -102
- package/src/config/enableReactTracking.ts +0 -62
- package/src/config/enableReactUse.ts +0 -32
- package/src/config/enable_PeekAssign.ts +0 -31
- package/src/config.ts +0 -47
- package/src/createObservable.ts +0 -47
- package/src/event.ts +0 -26
- package/src/globals.ts +0 -235
- package/src/helpers/pageHash.ts +0 -41
- package/src/helpers/pageHashParams.ts +0 -55
- package/src/helpers/time.ts +0 -30
- package/src/helpers/trackHistory.ts +0 -29
- package/src/helpers/undoRedo.ts +0 -111
- package/src/helpers.ts +0 -231
- package/src/is.ts +0 -63
- package/src/linked.ts +0 -17
- package/src/observable.ts +0 -32
- package/src/observableInterfaces.ts +0 -151
- package/src/observableTypes.ts +0 -232
- package/src/observe.ts +0 -89
- package/src/old-plugins/firebase.ts +0 -1053
- package/src/onChange.ts +0 -146
- package/src/persist/configureObservablePersistence.ts +0 -7
- package/src/persist/fieldTransformer.ts +0 -149
- package/src/persist/observablePersistRemoteFunctionsAdapter.ts +0 -39
- package/src/persist/persistObservable.ts +0 -1034
- package/src/persist-plugins/async-storage.ts +0 -99
- package/src/persist-plugins/indexeddb.ts +0 -439
- package/src/persist-plugins/local-storage.ts +0 -86
- package/src/persist-plugins/mmkv.ts +0 -91
- package/src/proxy.ts +0 -28
- package/src/react/Computed.tsx +0 -8
- package/src/react/For.tsx +0 -116
- package/src/react/Memo.tsx +0 -4
- package/src/react/Reactive.tsx +0 -53
- package/src/react/Show.tsx +0 -33
- package/src/react/Switch.tsx +0 -43
- package/src/react/react-globals.ts +0 -3
- package/src/react/reactInterfaces.ts +0 -32
- package/src/react/reactive-observer.tsx +0 -210
- package/src/react/useComputed.ts +0 -36
- package/src/react/useEffectOnce.ts +0 -41
- package/src/react/useIsMounted.ts +0 -16
- package/src/react/useMount.ts +0 -15
- package/src/react/useObservable.ts +0 -24
- package/src/react/useObservableReducer.ts +0 -52
- package/src/react/useObservableState.ts +0 -30
- package/src/react/useObserve.ts +0 -54
- package/src/react/useObserveEffect.ts +0 -40
- package/src/react/usePauseProvider.tsx +0 -16
- package/src/react/useSelector.ts +0 -167
- package/src/react/useUnmount.ts +0 -8
- package/src/react/useWhen.ts +0 -9
- package/src/react-hooks/createObservableHook.ts +0 -53
- package/src/react-hooks/useHover.ts +0 -40
- package/src/react-hooks/useMeasure.ts +0 -48
- package/src/react-hooks/useObservableNextRouter.ts +0 -137
- package/src/retry.ts +0 -71
- package/src/setupTracking.ts +0 -26
- package/src/sync/activateSyncedNode.ts +0 -128
- package/src/sync/configureObservableSync.ts +0 -7
- package/src/sync/persistTypes.ts +0 -216
- package/src/sync/syncHelpers.ts +0 -180
- package/src/sync/syncObservable.ts +0 -1056
- package/src/sync/syncObservableAdapter.ts +0 -31
- package/src/sync/syncTypes.ts +0 -189
- package/src/sync/synced.ts +0 -21
- package/src/sync-plugins/crud.ts +0 -412
- package/src/sync-plugins/fetch.ts +0 -80
- package/src/sync-plugins/keel.ts +0 -495
- package/src/sync-plugins/supabase.ts +0 -249
- package/src/sync-plugins/tanstack-query.ts +0 -113
- package/src/sync-plugins/tanstack-react-query.ts +0 -12
- package/src/trace/traceHelpers.ts +0 -11
- package/src/trace/useTraceListeners.ts +0 -34
- package/src/trace/useTraceUpdates.ts +0 -24
- package/src/trace/useVerifyNotTracking.ts +0 -33
- package/src/trace/useVerifyOneRender.ts +0 -10
- package/src/trackSelector.ts +0 -52
- package/src/tracking.ts +0 -43
- package/src/types/babel.d.ts +0 -12
- package/src/when.ts +0 -75
- package/sync-plugins/crud.js.map +0 -1
- package/sync-plugins/crud.mjs.map +0 -1
- package/sync-plugins/fetch.js.map +0 -1
- package/sync-plugins/fetch.mjs.map +0 -1
- package/sync-plugins/keel.js.map +0 -1
- package/sync-plugins/keel.mjs.map +0 -1
- package/sync-plugins/supabase.js.map +0 -1
- package/sync-plugins/supabase.mjs.map +0 -1
- package/sync-plugins/tanstack-query.js.map +0 -1
- package/sync-plugins/tanstack-query.mjs.map +0 -1
- package/sync-plugins/tanstack-react-query.js.map +0 -1
- package/sync-plugins/tanstack-react-query.mjs.map +0 -1
- package/sync.js.map +0 -1
- package/sync.mjs.map +0 -1
- package/trace.js.map +0 -1
- package/trace.mjs.map +0 -1
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
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
|
-
}
|
package/src/react/useMount.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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;
|
|
@@ -1,24 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
};
|
package/src/react/useObserve.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Observable, ObservableBoolean, observable } from '@legendapp/state';
|
|
2
|
-
import { Context, ReactNode, createContext, createElement, useState } from 'react';
|
|
3
|
-
|
|
4
|
-
let pauseContext: Context<ObservableBoolean> | undefined = undefined;
|
|
5
|
-
export const getPauseContext = () => {
|
|
6
|
-
return (pauseContext ||= createContext<Observable<boolean>>(null as any));
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export function usePauseProvider() {
|
|
10
|
-
const [value] = useState(() => observable(false));
|
|
11
|
-
return {
|
|
12
|
-
PauseProvider: ({ children }: { children: ReactNode }) =>
|
|
13
|
-
createElement(getPauseContext().Provider, { value }, children),
|
|
14
|
-
isPaused$: value,
|
|
15
|
-
};
|
|
16
|
-
}
|
package/src/react/useSelector.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ListenerParams,
|
|
3
|
-
Observable,
|
|
4
|
-
Selector,
|
|
5
|
-
computeSelector,
|
|
6
|
-
isObservable,
|
|
7
|
-
isPrimitive,
|
|
8
|
-
isPromise,
|
|
9
|
-
syncState,
|
|
10
|
-
trackSelector,
|
|
11
|
-
when,
|
|
12
|
-
} from '@legendapp/state';
|
|
13
|
-
import React, { useContext, useMemo } from 'react';
|
|
14
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
15
|
-
import { reactGlobals } from './react-globals';
|
|
16
|
-
import type { UseSelectorOptions } from './reactInterfaces';
|
|
17
|
-
import { getPauseContext } from './usePauseProvider';
|
|
18
|
-
|
|
19
|
-
interface SelectorFunctions<T> {
|
|
20
|
-
subscribe: (onStoreChange: () => void) => () => void;
|
|
21
|
-
getVersion: () => number;
|
|
22
|
-
run: (selector: Selector<T>) => T;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function createSelectorFunctions<T>(
|
|
26
|
-
options: UseSelectorOptions | undefined,
|
|
27
|
-
isPaused$: Observable<boolean>,
|
|
28
|
-
): SelectorFunctions<T> {
|
|
29
|
-
let version = 0;
|
|
30
|
-
let notify: () => void;
|
|
31
|
-
let dispose: (() => void) | undefined;
|
|
32
|
-
let resubscribe: (() => () => void) | undefined;
|
|
33
|
-
let _selector: Selector<T>;
|
|
34
|
-
let prev: T;
|
|
35
|
-
|
|
36
|
-
let pendingUpdate: any | undefined = undefined;
|
|
37
|
-
|
|
38
|
-
const run = () => {
|
|
39
|
-
// Dispose if already listening
|
|
40
|
-
dispose?.();
|
|
41
|
-
|
|
42
|
-
const {
|
|
43
|
-
value,
|
|
44
|
-
dispose: _dispose,
|
|
45
|
-
resubscribe: _resubscribe,
|
|
46
|
-
} = trackSelector(_selector, _update, undefined, undefined, /*createResubscribe*/ true);
|
|
47
|
-
|
|
48
|
-
dispose = _dispose;
|
|
49
|
-
resubscribe = _resubscribe;
|
|
50
|
-
|
|
51
|
-
return value;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const _update = ({ value }: { value: ListenerParams['value'] }) => {
|
|
55
|
-
if (isPaused$?.peek()) {
|
|
56
|
-
const next = pendingUpdate;
|
|
57
|
-
pendingUpdate = value;
|
|
58
|
-
if (next === undefined) {
|
|
59
|
-
when(
|
|
60
|
-
() => !isPaused$.get(),
|
|
61
|
-
() => {
|
|
62
|
-
const latest = pendingUpdate;
|
|
63
|
-
pendingUpdate = undefined;
|
|
64
|
-
_update({ value: latest });
|
|
65
|
-
},
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
// If skipCheck then don't need to re-run selector
|
|
70
|
-
let changed = options?.skipCheck;
|
|
71
|
-
if (!changed) {
|
|
72
|
-
const newValue = run();
|
|
73
|
-
|
|
74
|
-
// If newValue is different than previous value then it's changed.
|
|
75
|
-
// Also if the selector returns an observable directly then its value will be the same as
|
|
76
|
-
// the value from the listener, and that should always re-render.
|
|
77
|
-
if (newValue !== prev || (!isPrimitive(newValue) && newValue === value)) {
|
|
78
|
-
changed = true;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (changed) {
|
|
82
|
-
version++;
|
|
83
|
-
notify?.();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
subscribe: (onStoreChange: () => void) => {
|
|
90
|
-
notify = onStoreChange;
|
|
91
|
-
|
|
92
|
-
// Workaround for React 18 running twice in dev (part 2)
|
|
93
|
-
if (
|
|
94
|
-
(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
95
|
-
!dispose &&
|
|
96
|
-
resubscribe
|
|
97
|
-
) {
|
|
98
|
-
dispose = resubscribe();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return () => {
|
|
102
|
-
dispose?.();
|
|
103
|
-
dispose = undefined;
|
|
104
|
-
};
|
|
105
|
-
},
|
|
106
|
-
getVersion: () => version,
|
|
107
|
-
run: (selector: Selector<T>) => {
|
|
108
|
-
// Update the cached selector
|
|
109
|
-
_selector = selector;
|
|
110
|
-
|
|
111
|
-
return (prev = run());
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function useSelector<T>(selector: Selector<T>, options?: UseSelectorOptions): T {
|
|
117
|
-
// Short-circuit to skip creating the hook if selector is an observable
|
|
118
|
-
// and running in an observer. If selector is a function it needs to run in its own context.
|
|
119
|
-
if (reactGlobals.inObserver && isObservable(selector) && !options?.suspense) {
|
|
120
|
-
return computeSelector(selector);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
let value;
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const isPaused$ = useContext(getPauseContext());
|
|
127
|
-
const selectorFn = useMemo(() => createSelectorFunctions<T>(options, isPaused$), []);
|
|
128
|
-
const { subscribe, getVersion, run } = selectorFn;
|
|
129
|
-
|
|
130
|
-
// Run the selector
|
|
131
|
-
// Note: The selector needs to run on every render because it may have different results
|
|
132
|
-
// than the previous run if it uses local state
|
|
133
|
-
value = run(selector) as any;
|
|
134
|
-
|
|
135
|
-
useSyncExternalStore(subscribe, getVersion, getVersion);
|
|
136
|
-
|
|
137
|
-
// Suspense support
|
|
138
|
-
if (options?.suspense) {
|
|
139
|
-
// Note: Although it's not possible for an observable to be a promise, the selector may be a
|
|
140
|
-
// function that returns a Promise, so we handle that case too.
|
|
141
|
-
if (
|
|
142
|
-
isPromise(value) ||
|
|
143
|
-
(!value && isObservable(selector) && syncState(selector).isLoaded.get() === false)
|
|
144
|
-
) {
|
|
145
|
-
if (React.use) {
|
|
146
|
-
React.use(value);
|
|
147
|
-
} else {
|
|
148
|
-
throw value;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
} catch (err: unknown) {
|
|
153
|
-
if (
|
|
154
|
-
(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
155
|
-
(err as Error)?.message?.includes('Rendered more')
|
|
156
|
-
) {
|
|
157
|
-
console.warn(
|
|
158
|
-
`[legend-state]: You may want to wrap this component in \`observer\` to fix the error of ${
|
|
159
|
-
(err as Error).message
|
|
160
|
-
}`,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
throw err;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return value;
|
|
167
|
-
}
|
package/src/react/useUnmount.ts
DELETED
package/src/react/useWhen.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Selector, when, whenReady } from '@legendapp/state';
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
|
-
|
|
4
|
-
export function useWhen<T>(predicate: Selector<T>, effect: (value: T) => any | (() => any)) {
|
|
5
|
-
return useMemo(() => when(predicate, effect), []);
|
|
6
|
-
}
|
|
7
|
-
export function useWhenReady<T>(predicate: Selector<T>, effect: (value: T) => any | (() => any)) {
|
|
8
|
-
return useMemo(() => whenReady(predicate, effect), []);
|
|
9
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { isFunction, Observable, observable } from '@legendapp/state';
|
|
2
|
-
import React, { MutableRefObject, Reducer, ReducerState } from 'react';
|
|
3
|
-
|
|
4
|
-
function overrideHooks<TRet>(refObs: MutableRefObject<Observable<TRet> | undefined>) {
|
|
5
|
-
// @ts-expect-error Types don't match React's expected types
|
|
6
|
-
React.useState = function useState(initialState: TRet | (() => TRet)) {
|
|
7
|
-
const obs =
|
|
8
|
-
refObs.current ??
|
|
9
|
-
(refObs.current = observable((isFunction(initialState) ? initialState() : initialState) as any) as any);
|
|
10
|
-
return [obs.get() as TRet, obs.set] as [TRet, React.Dispatch<React.SetStateAction<TRet>>];
|
|
11
|
-
};
|
|
12
|
-
// @ts-expect-error Types don't match React's expected types
|
|
13
|
-
React.useReducer = function useReducer<R extends Reducer<any, any>>(
|
|
14
|
-
reducer: R,
|
|
15
|
-
initializerArg: ReducerState<R>,
|
|
16
|
-
initializer: (arg: ReducerState<R>) => ReducerState<R>,
|
|
17
|
-
) {
|
|
18
|
-
const obs =
|
|
19
|
-
refObs.current ??
|
|
20
|
-
(refObs.current = observable(
|
|
21
|
-
initializerArg !== undefined && isFunction(initializerArg)
|
|
22
|
-
? initializer(initializerArg)
|
|
23
|
-
: initializerArg,
|
|
24
|
-
) as any);
|
|
25
|
-
const dispatch = (action: any) => {
|
|
26
|
-
obs.set(reducer(obs.get(), action));
|
|
27
|
-
};
|
|
28
|
-
return [obs, dispatch];
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function createObservableHook<TArgs extends any[], TRet>(
|
|
33
|
-
fn: (...args: TArgs) => TRet,
|
|
34
|
-
): (...args: TArgs) => Observable<TRet> {
|
|
35
|
-
const _useState = React.useState;
|
|
36
|
-
const _useReducer = React.useReducer;
|
|
37
|
-
|
|
38
|
-
return function (...args: TArgs) {
|
|
39
|
-
const refObs = React.useRef<Observable<TRet>>();
|
|
40
|
-
|
|
41
|
-
// First override the built-in hooks to create/update observables
|
|
42
|
-
overrideHooks(refObs);
|
|
43
|
-
|
|
44
|
-
// Then call the original hook
|
|
45
|
-
fn(...args);
|
|
46
|
-
|
|
47
|
-
// And reset back to the built-in hooks
|
|
48
|
-
React.useState = _useState;
|
|
49
|
-
React.useReducer = _useReducer;
|
|
50
|
-
|
|
51
|
-
return refObs.current as Observable<TRet>;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { Observable } from '@legendapp/state';
|
|
2
|
-
import { useObservable } from '@legendapp/state/react';
|
|
3
|
-
import { useEffect } from 'react';
|
|
4
|
-
|
|
5
|
-
export function useHover<T extends HTMLElement>(ref: React.MutableRefObject<T>): Observable<boolean> {
|
|
6
|
-
const obs = useObservable(false);
|
|
7
|
-
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
const handleMouseOver = () => obs.set(true);
|
|
10
|
-
const handleMouseOut = (e: MouseEvent) => {
|
|
11
|
-
if (obs.peek() === true) {
|
|
12
|
-
let parent = (e as any).toElement as HTMLElement | null;
|
|
13
|
-
let foundRef = false;
|
|
14
|
-
while (parent && !foundRef) {
|
|
15
|
-
if (parent === ref.current) {
|
|
16
|
-
foundRef = true;
|
|
17
|
-
}
|
|
18
|
-
parent = parent.parentElement;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!foundRef) {
|
|
22
|
-
obs.set(false);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const node = ref.current;
|
|
28
|
-
if (node) {
|
|
29
|
-
node.addEventListener('mouseover', handleMouseOver);
|
|
30
|
-
node.addEventListener('mouseout', handleMouseOut);
|
|
31
|
-
|
|
32
|
-
return () => {
|
|
33
|
-
node.removeEventListener('mouseover', handleMouseOver);
|
|
34
|
-
node.removeEventListener('mouseout', handleMouseOut);
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
}, [ref.current]);
|
|
38
|
-
|
|
39
|
-
return obs;
|
|
40
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { ObservableObject } from '@legendapp/state';
|
|
2
|
-
import { useObservable } from '@legendapp/state/react';
|
|
3
|
-
import { RefObject, useLayoutEffect } from 'react';
|
|
4
|
-
|
|
5
|
-
function getSize(el: HTMLElement): { width: number; height: number } | undefined {
|
|
6
|
-
return el
|
|
7
|
-
? {
|
|
8
|
-
width: el.offsetWidth,
|
|
9
|
-
height: el.offsetHeight,
|
|
10
|
-
}
|
|
11
|
-
: undefined;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function useMeasure(ref: RefObject<HTMLElement>): ObservableObject<{
|
|
15
|
-
width: number | undefined;
|
|
16
|
-
height: number | undefined;
|
|
17
|
-
}> {
|
|
18
|
-
const obs = useObservable<{ width: number | undefined; height: number | undefined }>({
|
|
19
|
-
width: undefined,
|
|
20
|
-
height: undefined,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
useLayoutEffect(() => {
|
|
24
|
-
const el = ref.current;
|
|
25
|
-
if (el) {
|
|
26
|
-
const handleResize = () => {
|
|
27
|
-
if (ref.current) {
|
|
28
|
-
const oldSize = obs.peek();
|
|
29
|
-
const newSize = getSize(ref.current);
|
|
30
|
-
if (newSize && (newSize.width !== oldSize.width || newSize.height !== oldSize.height)) {
|
|
31
|
-
obs.set(newSize);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
handleResize();
|
|
36
|
-
|
|
37
|
-
let resizeObserver = new ResizeObserver(handleResize);
|
|
38
|
-
resizeObserver.observe(el);
|
|
39
|
-
|
|
40
|
-
return () => {
|
|
41
|
-
resizeObserver.disconnect();
|
|
42
|
-
(resizeObserver as any) = undefined;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}, [ref.current]);
|
|
46
|
-
|
|
47
|
-
return obs;
|
|
48
|
-
}
|