@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.
Files changed (327) hide show
  1. package/.DS_Store +0 -0
  2. package/CHANGELOG.md +1 -831
  3. package/LICENSE +1 -21
  4. package/README.md +1 -141
  5. package/as/arrayAsRecord.d.mts +5 -0
  6. package/as/arrayAsRecord.d.ts +5 -0
  7. package/as/arrayAsRecord.js +28 -0
  8. package/as/arrayAsRecord.mjs +26 -0
  9. package/as/arrayAsSet.d.mts +5 -0
  10. package/as/arrayAsSet.d.ts +5 -0
  11. package/as/arrayAsSet.js +13 -0
  12. package/as/arrayAsSet.mjs +11 -0
  13. package/as/arrayAsString.d.mts +5 -0
  14. package/as/arrayAsString.d.ts +5 -0
  15. package/as/arrayAsString.js +13 -0
  16. package/as/arrayAsString.mjs +11 -0
  17. package/as/numberAsString.d.mts +5 -0
  18. package/as/numberAsString.d.ts +5 -0
  19. package/as/numberAsString.js +13 -0
  20. package/as/numberAsString.mjs +11 -0
  21. package/as/recordAsArray.d.mts +5 -0
  22. package/as/recordAsArray.d.ts +5 -0
  23. package/as/recordAsArray.js +25 -0
  24. package/as/recordAsArray.mjs +23 -0
  25. package/as/recordAsString.d.mts +5 -0
  26. package/as/recordAsString.d.ts +5 -0
  27. package/as/recordAsString.js +13 -0
  28. package/as/recordAsString.mjs +11 -0
  29. package/as/setAsArray.d.mts +5 -0
  30. package/as/setAsArray.d.ts +5 -0
  31. package/as/setAsArray.js +13 -0
  32. package/as/setAsArray.mjs +11 -0
  33. package/as/setAsString.d.mts +5 -0
  34. package/as/setAsString.d.ts +5 -0
  35. package/as/setAsString.js +13 -0
  36. package/as/setAsString.mjs +11 -0
  37. package/as/stringAsArray.d.mts +5 -0
  38. package/as/stringAsArray.d.ts +5 -0
  39. package/as/stringAsArray.js +13 -0
  40. package/as/stringAsArray.mjs +11 -0
  41. package/as/stringAsNumber.d.mts +5 -0
  42. package/as/stringAsNumber.d.ts +5 -0
  43. package/as/stringAsNumber.js +16 -0
  44. package/as/stringAsNumber.mjs +14 -0
  45. package/as/stringAsRecord.d.mts +5 -0
  46. package/as/stringAsRecord.d.ts +5 -0
  47. package/as/stringAsRecord.js +15 -0
  48. package/as/stringAsRecord.mjs +13 -0
  49. package/as/stringAsSet.d.mts +5 -0
  50. package/as/stringAsSet.d.ts +5 -0
  51. package/as/stringAsSet.js +13 -0
  52. package/as/stringAsSet.mjs +11 -0
  53. package/babel.d.mts +21 -0
  54. package/babel.d.ts +21 -2
  55. package/babel.js +57 -53
  56. package/babel.mjs +65 -0
  57. package/config/enable$GetSet.js +13 -14
  58. package/config/enable$GetSet.mjs +13 -14
  59. package/config/enableReactComponents.d.mts +9 -0
  60. package/config/enableReactComponents.d.ts +4 -2
  61. package/config/enableReactComponents.js +13 -10
  62. package/config/enableReactComponents.mjs +13 -10
  63. package/config/enableReactNativeComponents.d.mts +22 -0
  64. package/config/enableReactNativeComponents.d.ts +6 -4
  65. package/config/enableReactNativeComponents.js +43 -47
  66. package/config/enableReactNativeComponents.mjs +43 -47
  67. package/config/enableReactTracking.d.mts +7 -0
  68. package/config/enableReactTracking.d.ts +3 -2
  69. package/config/enableReactTracking.js +33 -38
  70. package/config/enableReactTracking.mjs +33 -38
  71. package/config/enableReactUse.d.mts +10 -0
  72. package/config/enableReactUse.d.ts +4 -1
  73. package/config/enableReactUse.js +15 -14
  74. package/config/enableReactUse.mjs +15 -14
  75. package/config/{enable$GetSet.d.ts → enable_GetSet.d.mts} +4 -2
  76. package/config/enable_GetSet.d.ts +10 -0
  77. package/config/enable_PeekAssign.d.mts +10 -0
  78. package/config/enable_PeekAssign.d.ts +4 -2
  79. package/config/enable_PeekAssign.js +13 -14
  80. package/config/enable_PeekAssign.mjs +13 -14
  81. package/helpers/pageHash.d.mts +9 -0
  82. package/helpers/pageHash.d.ts +2 -0
  83. package/helpers/pageHash.js +25 -30
  84. package/helpers/pageHash.mjs +25 -30
  85. package/helpers/pageHashParams.d.mts +9 -0
  86. package/helpers/pageHashParams.d.ts +2 -0
  87. package/helpers/pageHashParams.js +34 -37
  88. package/helpers/pageHashParams.mjs +34 -37
  89. package/helpers/time.d.mts +6 -0
  90. package/helpers/time.d.ts +6 -3
  91. package/helpers/time.js +17 -17
  92. package/helpers/time.mjs +17 -17
  93. package/helpers/trackHistory.d.mts +6 -0
  94. package/helpers/trackHistory.d.ts +4 -2
  95. package/helpers/trackHistory.js +13 -16
  96. package/helpers/trackHistory.mjs +13 -16
  97. package/helpers/undoRedo.d.mts +37 -0
  98. package/helpers/undoRedo.d.ts +5 -3
  99. package/helpers/undoRedo.js +59 -94
  100. package/helpers/undoRedo.mjs +59 -94
  101. package/index.d.mts +404 -0
  102. package/index.d.ts +371 -28
  103. package/index.js +2015 -2166
  104. package/index.mjs +2015 -2166
  105. package/package.json +254 -195
  106. package/persist-plugins/async-storage.d.mts +18 -0
  107. package/persist-plugins/async-storage.d.ts +6 -3
  108. package/persist-plugins/async-storage.js +79 -86
  109. package/persist-plugins/async-storage.mjs +79 -86
  110. package/persist-plugins/indexeddb.d.mts +29 -0
  111. package/persist-plugins/indexeddb.d.ts +6 -3
  112. package/persist-plugins/indexeddb.js +331 -352
  113. package/persist-plugins/indexeddb.mjs +331 -352
  114. package/persist-plugins/local-storage.d.mts +23 -0
  115. package/persist-plugins/local-storage.d.ts +8 -5
  116. package/persist-plugins/local-storage.js +74 -76
  117. package/persist-plugins/local-storage.mjs +74 -76
  118. package/persist-plugins/mmkv.d.mts +18 -0
  119. package/persist-plugins/mmkv.d.ts +6 -3
  120. package/persist-plugins/mmkv.js +82 -86
  121. package/persist-plugins/mmkv.mjs +82 -86
  122. package/react-hooks/createObservableHook.d.mts +5 -0
  123. package/react-hooks/createObservableHook.d.ts +4 -1
  124. package/react-hooks/createObservableHook.js +29 -30
  125. package/react-hooks/createObservableHook.mjs +25 -30
  126. package/react-hooks/useHover.d.mts +5 -0
  127. package/react-hooks/useHover.d.ts +5 -3
  128. package/react-hooks/useHover.js +29 -29
  129. package/react-hooks/useHover.mjs +29 -29
  130. package/react-hooks/useMeasure.d.mts +9 -0
  131. package/react-hooks/useMeasure.d.ts +5 -2
  132. package/react-hooks/useMeasure.js +30 -32
  133. package/react-hooks/useMeasure.mjs +30 -32
  134. package/react-hooks/useObservableNextRouter.d.mts +35 -0
  135. package/react-hooks/useObservableNextRouter.d.ts +9 -7
  136. package/react-hooks/useObservableNextRouter.js +64 -77
  137. package/react-hooks/useObservableNextRouter.mjs +60 -77
  138. package/react.d.mts +157 -0
  139. package/react.d.ts +157 -21
  140. package/react.js +458 -749
  141. package/react.mjs +457 -752
  142. package/sync-plugins/crud.d.mts +54 -0
  143. package/sync-plugins/crud.d.ts +12 -10
  144. package/sync-plugins/crud.js +253 -270
  145. package/sync-plugins/crud.mjs +253 -270
  146. package/sync-plugins/fetch.d.mts +21 -0
  147. package/sync-plugins/fetch.d.ts +7 -4
  148. package/sync-plugins/fetch.js +50 -37
  149. package/sync-plugins/fetch.mjs +50 -37
  150. package/sync-plugins/keel.d.mts +108 -0
  151. package/sync-plugins/keel.d.ts +17 -15
  152. package/sync-plugins/keel.js +229 -462
  153. package/sync-plugins/keel.mjs +227 -464
  154. package/sync-plugins/supabase.d.mts +39 -0
  155. package/sync-plugins/supabase.d.ts +16 -14
  156. package/sync-plugins/supabase.js +128 -128
  157. package/sync-plugins/supabase.mjs +128 -128
  158. package/sync-plugins/tanstack-query.d.mts +14 -0
  159. package/sync-plugins/tanstack-query.d.ts +7 -4
  160. package/sync-plugins/tanstack-query.js +51 -57
  161. package/sync-plugins/tanstack-query.mjs +51 -57
  162. package/sync-plugins/tanstack-react-query.d.mts +8 -0
  163. package/sync-plugins/tanstack-react-query.d.ts +6 -1
  164. package/sync-plugins/tanstack-react-query.js +2 -2
  165. package/sync-plugins/tanstack-react-query.mjs +2 -2
  166. package/sync.d.mts +351 -0
  167. package/sync.d.ts +349 -9
  168. package/sync.js +910 -964
  169. package/sync.mjs +920 -974
  170. package/trace.d.mts +9 -0
  171. package/trace.d.ts +9 -4
  172. package/trace.js +72 -62
  173. package/trace.mjs +72 -62
  174. package/types/babel.d.ts +1 -12
  175. package/babel.js.map +0 -1
  176. package/config/enable$GetSet.js.map +0 -1
  177. package/config/enable$GetSet.mjs.map +0 -1
  178. package/config/enableReactComponents.js.map +0 -1
  179. package/config/enableReactComponents.mjs.map +0 -1
  180. package/config/enableReactNativeComponents.js.map +0 -1
  181. package/config/enableReactNativeComponents.mjs.map +0 -1
  182. package/config/enableReactTracking.js.map +0 -1
  183. package/config/enableReactTracking.mjs.map +0 -1
  184. package/config/enableReactUse.js.map +0 -1
  185. package/config/enableReactUse.mjs.map +0 -1
  186. package/config/enable_PeekAssign.js.map +0 -1
  187. package/config/enable_PeekAssign.mjs.map +0 -1
  188. package/helpers/pageHash.js.map +0 -1
  189. package/helpers/pageHash.mjs.map +0 -1
  190. package/helpers/pageHashParams.js.map +0 -1
  191. package/helpers/pageHashParams.mjs.map +0 -1
  192. package/helpers/time.js.map +0 -1
  193. package/helpers/time.mjs.map +0 -1
  194. package/helpers/trackHistory.js.map +0 -1
  195. package/helpers/trackHistory.mjs.map +0 -1
  196. package/helpers/undoRedo.js.map +0 -1
  197. package/helpers/undoRedo.mjs.map +0 -1
  198. package/history.d.ts +0 -1
  199. package/history.js +0 -24
  200. package/history.js.map +0 -1
  201. package/history.mjs +0 -22
  202. package/history.mjs.map +0 -1
  203. package/index.js.map +0 -1
  204. package/index.mjs.map +0 -1
  205. package/persist-plugins/async-storage.js.map +0 -1
  206. package/persist-plugins/async-storage.mjs.map +0 -1
  207. package/persist-plugins/indexeddb.js.map +0 -1
  208. package/persist-plugins/indexeddb.mjs.map +0 -1
  209. package/persist-plugins/local-storage.js.map +0 -1
  210. package/persist-plugins/local-storage.mjs.map +0 -1
  211. package/persist-plugins/mmkv.js.map +0 -1
  212. package/persist-plugins/mmkv.mjs.map +0 -1
  213. package/react-hooks/createObservableHook.js.map +0 -1
  214. package/react-hooks/createObservableHook.mjs.map +0 -1
  215. package/react-hooks/useHover.js.map +0 -1
  216. package/react-hooks/useHover.mjs.map +0 -1
  217. package/react-hooks/useMeasure.js.map +0 -1
  218. package/react-hooks/useMeasure.mjs.map +0 -1
  219. package/react-hooks/useObservableNextRouter.js.map +0 -1
  220. package/react-hooks/useObservableNextRouter.mjs.map +0 -1
  221. package/react.js.map +0 -1
  222. package/react.mjs.map +0 -1
  223. package/src/ObservableObject.ts +0 -1350
  224. package/src/ObservablePrimitive.ts +0 -62
  225. package/src/babel/index.ts +0 -83
  226. package/src/batching.ts +0 -357
  227. package/src/computed.ts +0 -18
  228. package/src/config/enable$GetSet.ts +0 -30
  229. package/src/config/enableReactComponents.ts +0 -26
  230. package/src/config/enableReactNativeComponents.ts +0 -102
  231. package/src/config/enableReactTracking.ts +0 -62
  232. package/src/config/enableReactUse.ts +0 -32
  233. package/src/config/enable_PeekAssign.ts +0 -31
  234. package/src/config.ts +0 -47
  235. package/src/createObservable.ts +0 -47
  236. package/src/event.ts +0 -26
  237. package/src/globals.ts +0 -235
  238. package/src/helpers/pageHash.ts +0 -41
  239. package/src/helpers/pageHashParams.ts +0 -55
  240. package/src/helpers/time.ts +0 -30
  241. package/src/helpers/trackHistory.ts +0 -29
  242. package/src/helpers/undoRedo.ts +0 -111
  243. package/src/helpers.ts +0 -231
  244. package/src/is.ts +0 -63
  245. package/src/linked.ts +0 -17
  246. package/src/observable.ts +0 -32
  247. package/src/observableInterfaces.ts +0 -151
  248. package/src/observableTypes.ts +0 -232
  249. package/src/observe.ts +0 -89
  250. package/src/old-plugins/firebase.ts +0 -1053
  251. package/src/onChange.ts +0 -146
  252. package/src/persist/configureObservablePersistence.ts +0 -7
  253. package/src/persist/fieldTransformer.ts +0 -149
  254. package/src/persist/observablePersistRemoteFunctionsAdapter.ts +0 -39
  255. package/src/persist/persistObservable.ts +0 -1034
  256. package/src/persist-plugins/async-storage.ts +0 -99
  257. package/src/persist-plugins/indexeddb.ts +0 -439
  258. package/src/persist-plugins/local-storage.ts +0 -86
  259. package/src/persist-plugins/mmkv.ts +0 -91
  260. package/src/proxy.ts +0 -28
  261. package/src/react/Computed.tsx +0 -8
  262. package/src/react/For.tsx +0 -116
  263. package/src/react/Memo.tsx +0 -4
  264. package/src/react/Reactive.tsx +0 -53
  265. package/src/react/Show.tsx +0 -33
  266. package/src/react/Switch.tsx +0 -43
  267. package/src/react/react-globals.ts +0 -3
  268. package/src/react/reactInterfaces.ts +0 -32
  269. package/src/react/reactive-observer.tsx +0 -210
  270. package/src/react/useComputed.ts +0 -36
  271. package/src/react/useEffectOnce.ts +0 -41
  272. package/src/react/useIsMounted.ts +0 -16
  273. package/src/react/useMount.ts +0 -15
  274. package/src/react/useObservable.ts +0 -24
  275. package/src/react/useObservableReducer.ts +0 -52
  276. package/src/react/useObservableState.ts +0 -30
  277. package/src/react/useObserve.ts +0 -54
  278. package/src/react/useObserveEffect.ts +0 -40
  279. package/src/react/usePauseProvider.tsx +0 -16
  280. package/src/react/useSelector.ts +0 -167
  281. package/src/react/useUnmount.ts +0 -8
  282. package/src/react/useWhen.ts +0 -9
  283. package/src/react-hooks/createObservableHook.ts +0 -53
  284. package/src/react-hooks/useHover.ts +0 -40
  285. package/src/react-hooks/useMeasure.ts +0 -48
  286. package/src/react-hooks/useObservableNextRouter.ts +0 -137
  287. package/src/retry.ts +0 -71
  288. package/src/setupTracking.ts +0 -26
  289. package/src/sync/activateSyncedNode.ts +0 -128
  290. package/src/sync/configureObservableSync.ts +0 -7
  291. package/src/sync/persistTypes.ts +0 -216
  292. package/src/sync/syncHelpers.ts +0 -180
  293. package/src/sync/syncObservable.ts +0 -1056
  294. package/src/sync/syncObservableAdapter.ts +0 -31
  295. package/src/sync/syncTypes.ts +0 -189
  296. package/src/sync/synced.ts +0 -21
  297. package/src/sync-plugins/crud.ts +0 -412
  298. package/src/sync-plugins/fetch.ts +0 -80
  299. package/src/sync-plugins/keel.ts +0 -495
  300. package/src/sync-plugins/supabase.ts +0 -249
  301. package/src/sync-plugins/tanstack-query.ts +0 -113
  302. package/src/sync-plugins/tanstack-react-query.ts +0 -12
  303. package/src/trace/traceHelpers.ts +0 -11
  304. package/src/trace/useTraceListeners.ts +0 -34
  305. package/src/trace/useTraceUpdates.ts +0 -24
  306. package/src/trace/useVerifyNotTracking.ts +0 -33
  307. package/src/trace/useVerifyOneRender.ts +0 -10
  308. package/src/trackSelector.ts +0 -52
  309. package/src/tracking.ts +0 -43
  310. package/src/types/babel.d.ts +0 -12
  311. package/src/when.ts +0 -75
  312. package/sync-plugins/crud.js.map +0 -1
  313. package/sync-plugins/crud.mjs.map +0 -1
  314. package/sync-plugins/fetch.js.map +0 -1
  315. package/sync-plugins/fetch.mjs.map +0 -1
  316. package/sync-plugins/keel.js.map +0 -1
  317. package/sync-plugins/keel.mjs.map +0 -1
  318. package/sync-plugins/supabase.js.map +0 -1
  319. package/sync-plugins/supabase.mjs.map +0 -1
  320. package/sync-plugins/tanstack-query.js.map +0 -1
  321. package/sync-plugins/tanstack-query.mjs.map +0 -1
  322. package/sync-plugins/tanstack-react-query.js.map +0 -1
  323. package/sync-plugins/tanstack-react-query.mjs.map +0 -1
  324. package/sync.js.map +0 -1
  325. package/sync.mjs.map +0 -1
  326. package/trace.js.map +0 -1
  327. 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
- }
@@ -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
- };
@@ -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
- }
@@ -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
- }
@@ -1,8 +0,0 @@
1
- import { useMount } from './useMount';
2
-
3
- export function useUnmount(fn: () => void) {
4
- return useMount(() => fn);
5
- }
6
-
7
- // TODOV4 Deprecate
8
- export const useUnmountOnce = useUnmount;
@@ -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
- }