@reause/rxjs 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +461 -0
- package/dist/index.iife.js +478 -0
- package/dist/index.iife.min.js +1 -0
- package/dist/index.js +471 -0
- package/package.json +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hairyf
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction } from "react";
|
|
2
|
+
import { BehaviorSubject, NextObserver, Observable, ObservableInput, Subject } from "rxjs";
|
|
3
|
+
//#region toObserver/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A write sink `toObserver` can push emissions into.
|
|
6
|
+
*
|
|
7
|
+
* - a ref-like object (`{ current }` — `useRef`'s return value, a
|
|
8
|
+
* `RefObject<T>`, or any hand-written `{ current: T }` holder);
|
|
9
|
+
* - a setter function (`(value: T) => void` — the second tuple member of
|
|
10
|
+
* `useState`, or a `useReducer` dispatch).
|
|
11
|
+
*
|
|
12
|
+
* Plain values are deliberately NOT accepted: writing to a value is
|
|
13
|
+
* meaningless, so the target is always something that can receive a write.
|
|
14
|
+
*/
|
|
15
|
+
export type ObserverTarget<T> = {
|
|
16
|
+
current: T;
|
|
17
|
+
} | ((value: T) => void);
|
|
18
|
+
/**
|
|
19
|
+
* Sugar function converting a write sink into an RxJS
|
|
20
|
+
* [Observer](https://rxjs.dev/guide/observer).
|
|
21
|
+
*
|
|
22
|
+
* Map from @vueuse/rxjs `toObserver`
|
|
23
|
+
* (`source/vueuse/packages/rxjs/toObserver/index.ts`). Upstream is
|
|
24
|
+
* `toObserver<T>(value: Ref<T>): NextObserver<T>` — it returns an observer
|
|
25
|
+
* whose only method is `next`, which synchronously writes the emission into
|
|
26
|
+
* `value.value`.
|
|
27
|
+
*
|
|
28
|
+
* Adjustment for React: a `useRef` write never schedules a re-render, so a
|
|
29
|
+
* 1:1 mirror accepting only a Vue-style `Ref` would silently pin consumers to
|
|
30
|
+
* non-rendering state. The reause version therefore accepts either a
|
|
31
|
+
* ref-like object (`{ current }`, written through `.current`) or a setter
|
|
32
|
+
* function (`(value: T) => void`, called directly) — pass a `useState` setter
|
|
33
|
+
* when the UI must update, or a `useRef` when the latest value only needs to
|
|
34
|
+
* be read later. Everything else matches upstream: the returned observer has
|
|
35
|
+
* ONLY `next` (no `error`/`complete`), each emission is written synchronously,
|
|
36
|
+
* and `toObserver` itself has no side effects.
|
|
37
|
+
*
|
|
38
|
+
* The parameter is named `target` (upstream `value`) because it is a write
|
|
39
|
+
* sink, not a value — there is no Vue-style ref object exposed to users.
|
|
40
|
+
*
|
|
41
|
+
* @__NO_SIDE_EFFECTS__
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const [count, setCount] = useState(0)
|
|
45
|
+
* interval(1000).pipe(take(3)).subscribe(toObserver(setCount)) // re-renders
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const count = useRef(0)
|
|
49
|
+
* interval(1000).pipe(take(3)).subscribe(toObserver(count)) // no re-render
|
|
50
|
+
* count.current // latest emission
|
|
51
|
+
*
|
|
52
|
+
* @param target - A ref-like `{ current }` object or a setter function.
|
|
53
|
+
* @returns An RxJS `NextObserver<T>` whose `next` writes into `target`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toObserver<T>(target: ObserverTarget<T>): NextObserver<T>;
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region useObservable/index.d.ts
|
|
58
|
+
/**
|
|
59
|
+
* Options for `useObservable`.
|
|
60
|
+
*/
|
|
61
|
+
export interface UseObservableOptions<I> {
|
|
62
|
+
/**
|
|
63
|
+
* Error handler forwarded to the `Observable` subscription. Without it RxJS
|
|
64
|
+
* treats any error in the supplied `Observable` as an "unhandled error": it
|
|
65
|
+
* is rethrown on a new call stack and reported to `window.onerror` (or
|
|
66
|
+
* `process.on('error')`), exactly like upstream.
|
|
67
|
+
*/
|
|
68
|
+
onError?: (err: unknown) => void;
|
|
69
|
+
/**
|
|
70
|
+
* The value that should be set if the observable has not emitted.
|
|
71
|
+
*
|
|
72
|
+
* @default undefined
|
|
73
|
+
*/
|
|
74
|
+
initialValue?: I | undefined;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Return of `useObservable`: a writable `[value, setValue]` tuple (upstream
|
|
78
|
+
* returns a single `Readonly<Ref<H | I>>`).
|
|
79
|
+
*/
|
|
80
|
+
export type UseObservableReturn<H, I = undefined> = [value: H | I, setValue: Dispatch<SetStateAction<H | I>>];
|
|
81
|
+
/**
|
|
82
|
+
* Use an RxJS [`Observable`](https://rxjs.dev/guide/observable), return a
|
|
83
|
+
* controllable state, and automatically unsubscribe from it when the component
|
|
84
|
+
* is unmounted.
|
|
85
|
+
*
|
|
86
|
+
* Map from @vueuse/rxjs `useObservable`
|
|
87
|
+
* (`source/vueuse/packages/rxjs/useObservable/`): every emission is written
|
|
88
|
+
* into the state and `options.initialValue` is used until the first one
|
|
89
|
+
* arrives. A failing `Observable` is forwarded to `options.onError`; without a
|
|
90
|
+
* handler RxJS reports the error as unhandled instead of swallowing it.
|
|
91
|
+
*
|
|
92
|
+
* React divergences:
|
|
93
|
+
* - upstream returns a `Readonly<Ref<H | I>>`; the React port returns a
|
|
94
|
+
* useState-like `[value, setValue]` writable tuple (hairyf/reause#174), so
|
|
95
|
+
* the state can also be set from React code — a later emission overwrites it
|
|
96
|
+
* again. Setting a new value re-renders.
|
|
97
|
+
* - upstream's `tryOnScopeDispose` becomes the effect cleanup: the subscription
|
|
98
|
+
* is created once when the component mounts and unsubscribed on unmount.
|
|
99
|
+
* - the `observable` argument is read through a latest-value ref and is **not**
|
|
100
|
+
* part of the effect dependencies — a new identity on a later render does not
|
|
101
|
+
* re-subscribe, matching upstream (Vue creates the subscription once during
|
|
102
|
+
* `setup`). `useObservable(interval(1000), { initialValue: 0 })` therefore
|
|
103
|
+
* keeps one live interval across re-renders instead of restarting it on every
|
|
104
|
+
* render.
|
|
105
|
+
* - `initialValue` is the `useState` initial value, so it only applies to the
|
|
106
|
+
* first render; `onError` is read when the subscription is created.
|
|
107
|
+
*
|
|
108
|
+
* @see https://vueuse.org/rxjs/useObservable/
|
|
109
|
+
* @example
|
|
110
|
+
* const [count, setCount] = useObservable(interval(1000), { initialValue: 0 })
|
|
111
|
+
* // count is 0 until the first emission
|
|
112
|
+
*/
|
|
113
|
+
export declare function useObservable<H, I = undefined>(observable: Observable<H>, options?: UseObservableOptions<I | undefined>): UseObservableReturn<H, I>;
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region useWatchExtractedObservable/index.d.ts
|
|
116
|
+
/**
|
|
117
|
+
* Register a cleanup callback for the current extractor run. Mirrors Vue's
|
|
118
|
+
* `watch` cleanup hook: the registered callbacks run before the next
|
|
119
|
+
* subscription is created and when the hook is torn down (`stop()` /
|
|
120
|
+
* unmount).
|
|
121
|
+
*/
|
|
122
|
+
export type OnCleanup = (cleanupFn: () => void) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Extracts the `Observable` to watch from the resolved source value.
|
|
125
|
+
*
|
|
126
|
+
* Note the parameter list is `(value, onCleanup)` — upstream's extractor also
|
|
127
|
+
* receives Vue's `oldValue` between the two; React has no previous-value
|
|
128
|
+
* tracking for arbitrary sources, so that argument is intentionally absent
|
|
129
|
+
* (see the JSDoc of {@link useWatchExtractedObservable}).
|
|
130
|
+
*/
|
|
131
|
+
export type WatchExtractedObservableExtractor<Value, E> = (value: NonNullable<Value>, onCleanup: OnCleanup) => Observable<E>;
|
|
132
|
+
export interface UseWatchExtractedObservableOptions {
|
|
133
|
+
/**
|
|
134
|
+
* Extra React effect dependencies — the React substitute for Vue's
|
|
135
|
+
* reactive tracking (same convention as `useAsync`'s `options.deps`,
|
|
136
|
+
* `packages/core/useAsync/index.tsx`). The resolved source value's
|
|
137
|
+
* identity is always compared as well, so a new source object re-extracts
|
|
138
|
+
* even without `deps`. Defaults to `[]`.
|
|
139
|
+
*/
|
|
140
|
+
deps?: unknown[];
|
|
141
|
+
/**
|
|
142
|
+
* Error handler forwarded to the `Observable` subscription. Without it
|
|
143
|
+
* RxJS treats an error as unhandled and rethrows it asynchronously
|
|
144
|
+
* (upstream parity).
|
|
145
|
+
*/
|
|
146
|
+
onError?: (err: unknown) => void;
|
|
147
|
+
/** Called when the watched `Observable` completes. */
|
|
148
|
+
onComplete?: () => void;
|
|
149
|
+
}
|
|
150
|
+
export interface UseWatchExtractedObservableReturn {
|
|
151
|
+
/**
|
|
152
|
+
* Stop watching: runs the pending `onCleanup` callbacks, unsubscribes the
|
|
153
|
+
* active subscription and detaches the hook permanently (upstream's
|
|
154
|
+
* `WatchHandle`). Idempotent — later `deps` / source changes no longer
|
|
155
|
+
* subscribe.
|
|
156
|
+
*/
|
|
157
|
+
stop: () => void;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Watch the values of an RxJS [`Observable`](https://rxjs.dev/guide/observable)
|
|
161
|
+
* extracted from a source value — React port of VueUse's
|
|
162
|
+
* `watchExtractedObservable`.
|
|
163
|
+
*
|
|
164
|
+
* Map from @vueuse/rxjs `watchExtractedObservable`
|
|
165
|
+
* (`source/vueuse/packages/rxjs/watchExtractedObservable/`): whenever the
|
|
166
|
+
* resolved source value changes, the previous subscription is unsubscribed
|
|
167
|
+
* and `extractor` derives a new `Observable`, whose emissions are forwarded
|
|
168
|
+
* to `callback`. Automatically unsubscribes when the source changes and when
|
|
169
|
+
* the component unmounts.
|
|
170
|
+
*
|
|
171
|
+
* React adaptation (upstream's Vue reactivity graph is replaced):
|
|
172
|
+
*
|
|
173
|
+
* - `value` is a read-only value source and takes a plain
|
|
174
|
+
* `Value | null | undefined` (upstream: `T | WatchSource<T>`; resolve a
|
|
175
|
+
* React ref or getter at the call site). There
|
|
176
|
+
* is no reactive graph: the effect re-runs when the value's
|
|
177
|
+
* identity changes **or** when `options.deps` change (upstream re-runs
|
|
178
|
+
* whenever the tracked source mutates). A source object mutated **in place**
|
|
179
|
+
* therefore does not re-trigger — pass a new identity or list the mutation
|
|
180
|
+
* inputs in `deps`. `deps` is the React substitute for Vue's reactive
|
|
181
|
+
* tracking, the same convention as `useAsync`'s `options.deps`
|
|
182
|
+
* (`packages/core/useAsync/index.tsx`).
|
|
183
|
+
* - The extractor is `(value, onCleanup) => Observable<E>`: upstream also
|
|
184
|
+
* passes Vue's `oldValue` as the second argument, which has no React
|
|
185
|
+
* equivalent (React keeps no previous-value tracking) and is dropped.
|
|
186
|
+
* - Upstream returns a `WatchHandle` function; the React hook returns
|
|
187
|
+
* `{ stop }` (§2B object return — no state-like writable pair). `stop` is a
|
|
188
|
+
* stable `useCallback`, idempotent, and — like the `WatchHandle` — permanent:
|
|
189
|
+
* it tears down the current subscription, runs the pending `onCleanup`
|
|
190
|
+
* callbacks, and prevents later `deps` / source changes from subscribing
|
|
191
|
+
* again.
|
|
192
|
+
* - `onCleanup` parity: callbacks registered through the `onCleanup` argument
|
|
193
|
+
* are collected per run and invoked before the next subscription is created
|
|
194
|
+
* (upstream's Vue `watch` runs the previous cleanup before the watcher body
|
|
195
|
+
* unsubscribes) and on unmount / `stop()`. They run before the subscription
|
|
196
|
+
* is unsubscribed, mirroring upstream's ordering.
|
|
197
|
+
* - A `null` / `undefined` resolved value subscribes to nothing and drops any
|
|
198
|
+
* previous subscription (upstream parity).
|
|
199
|
+
* - `extractor`, `callback`, `onError` and `onComplete` are read through
|
|
200
|
+
* latest-value refs, so inline identities never re-subscribe; only the
|
|
201
|
+
* resolved source value and `deps` do.
|
|
202
|
+
*
|
|
203
|
+
* @see https://vueuse.org/watchExtractedObservable/
|
|
204
|
+
* @example
|
|
205
|
+
* const player = useRef<AudioPlayer | null>(null)
|
|
206
|
+
* const [progress, setProgress] = useState(0)
|
|
207
|
+
*
|
|
208
|
+
* useWatchExtractedObservable(player, p => p.progress$, (percentage) => {
|
|
209
|
+
* setProgress(percentage * 100)
|
|
210
|
+
* }, { onError: err => console.error(err) })
|
|
211
|
+
*/
|
|
212
|
+
export declare function useWatchExtractedObservable<Value, E>(value: Value | null | undefined, extractor: WatchExtractedObservableExtractor<Value, E>, callback: (snapshot: E) => void, options?: UseWatchExtractedObservableOptions): UseWatchExtractedObservableReturn;
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region useExtractedObservable/index.d.ts
|
|
215
|
+
/**
|
|
216
|
+
* Options for `useExtractedObservable`.
|
|
217
|
+
*
|
|
218
|
+
* Upstream `UseExtractedObservableOptions` extends `UseObservableOptions`
|
|
219
|
+
* with `onComplete`; the React port reuses the same option names (`onError`,
|
|
220
|
+
* `initialValue`) from `useObservable` and adds `deps`, the substitute for
|
|
221
|
+
* Vue's reactive tracking (see {@link useExtractedObservable}).
|
|
222
|
+
*/
|
|
223
|
+
export interface UseExtractedObservableOptions<E> extends UseObservableOptions<E> {
|
|
224
|
+
/** Called when the extracted `Observable` completes. */
|
|
225
|
+
onComplete?: () => void;
|
|
226
|
+
/**
|
|
227
|
+
* Extra React effect dependencies — the React substitute for Vue's
|
|
228
|
+
* reactive tracking (same convention as `useAsync`'s `options.deps`,
|
|
229
|
+
* `packages/core/useAsync/index.tsx`). The resolved source value's identity
|
|
230
|
+
* is always compared as well, so a new source object re-extracts even
|
|
231
|
+
* without `deps`. Defaults to `[]`.
|
|
232
|
+
*/
|
|
233
|
+
deps?: unknown[];
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Extracts the `Observable` to subscribe to from the resolved source value.
|
|
237
|
+
*
|
|
238
|
+
* Note the parameter list is `(value, onCleanup)` — upstream's extractor also
|
|
239
|
+
* receives Vue's `oldValue` between the two; React has no previous-value
|
|
240
|
+
* tracking for arbitrary sources, so that argument is intentionally absent
|
|
241
|
+
* (see the JSDoc of {@link useExtractedObservable}). The signature is shared
|
|
242
|
+
* with the sibling `useWatchExtractedObservable`
|
|
243
|
+
* (`packages/rxjs/useWatchExtractedObservable/index.tsx`).
|
|
244
|
+
*/
|
|
245
|
+
export type ExtractedObservableExtractor<Value, E> = (value: NonNullable<Value>, onCleanup: OnCleanup) => Observable<E>;
|
|
246
|
+
/**
|
|
247
|
+
* Use an RxJS [`Observable`](https://rxjs.dev/guide/observable) as extracted
|
|
248
|
+
* from one or more hooks, and automatically unsubscribe from it when the
|
|
249
|
+
* component is unmounted.
|
|
250
|
+
*
|
|
251
|
+
* Map from @vueuse/rxjs `useExtractedObservable`
|
|
252
|
+
* (`source/vueuse/packages/rxjs/useExtractedObservable/`): whenever the
|
|
253
|
+
* resolved source value changes, the previous subscription is unsubscribed
|
|
254
|
+
* and `extractor` derives a new `Observable` from the new value, whose
|
|
255
|
+
* emissions become the hook's value. Unsubscribing happens both on a source
|
|
256
|
+
* change and on unmount.
|
|
257
|
+
*
|
|
258
|
+
* React adaptation (upstream's Vue reactivity graph is replaced):
|
|
259
|
+
*
|
|
260
|
+
* - `value` is a read-only value source and takes a plain
|
|
261
|
+
* `Value | null | undefined` (upstream: `T | WatchSource<T>`, i.e. a
|
|
262
|
+
* reactive object, an array of sources or a getter). Resolve a React ref or
|
|
263
|
+
* getter at the call site; a list of sources is passed as a plain array and
|
|
264
|
+
* re-extracts when a new array identity arrives. There is no reactive graph:
|
|
265
|
+
* the effect re-runs when the value's identity changes **or** when
|
|
266
|
+
* `options.deps` change (upstream re-runs whenever any tracked source
|
|
267
|
+
* mutates), so a source object mutated **in place** needs a new identity or
|
|
268
|
+
* the mutation inputs listed in `deps`.
|
|
269
|
+
* - the extractor is `(value, onCleanup) => Observable<E>`: upstream also
|
|
270
|
+
* passes Vue's `oldValue` as the second argument, which has no React
|
|
271
|
+
* equivalent (React keeps no previous-value tracking) and is dropped.
|
|
272
|
+
* - upstream returns a `DeepReadonly<ShallowRef<E>>`; the React port returns
|
|
273
|
+
* the value directly (a readonly ref holds no writable value, so the
|
|
274
|
+
* structure is mirrored — §2 return rules). `initialValue` narrows the
|
|
275
|
+
* returned type to `E | I` (`I` being the `initialValue` type and
|
|
276
|
+
* defaulting to `undefined`), the same trick as `useObservable`.
|
|
277
|
+
* - upstream's `watch` options (`immediate` / `deep` / `flush`) are dropped:
|
|
278
|
+
* the effect always extracts on mount (`immediate: true`, upstream's
|
|
279
|
+
* default) and re-extracts on identity / `deps` changes — React has no
|
|
280
|
+
* flush scheduler to configure. Pass `initialValue` to seed the value
|
|
281
|
+
* before the first extraction settles.
|
|
282
|
+
* - `initialValue` is the `useState` initial value, so it only applies to the
|
|
283
|
+
* first render — a later source change keeps the last emitted value
|
|
284
|
+
* (upstream's `obsRef` is never reset either), and a nullish source
|
|
285
|
+
* subscribes to nothing and drops the previous subscription.
|
|
286
|
+
* - `onCleanup` parity: callbacks registered through the `onCleanup` argument
|
|
287
|
+
* are collected per run and invoked before the next subscription is created,
|
|
288
|
+
* before the previous subscription is unsubscribed (upstream's Vue `watch`
|
|
289
|
+
* runs the previous cleanup before the watcher body), and on unmount.
|
|
290
|
+
* - `extractor`, `onError` and `onComplete` are read through latest-value refs,
|
|
291
|
+
* so inline identities never re-subscribe; only the resolved source value
|
|
292
|
+
* and `deps` do.
|
|
293
|
+
* - the option values are handed to the observer directly, so an absent
|
|
294
|
+
* `onError` leaves the error slot `undefined` and RxJS reports the error as
|
|
295
|
+
* unhandled instead of swallowing it (upstream parity).
|
|
296
|
+
* - SSR-safe: nothing touches `window` / `document`, and the subscription only
|
|
297
|
+
* exists inside the mount effect.
|
|
298
|
+
*
|
|
299
|
+
* @see https://vueuse.org/rxjs/useExtractedObservable/
|
|
300
|
+
* @example
|
|
301
|
+
* const [start, setStart] = useState(0)
|
|
302
|
+
* const count = useExtractedObservable(start, start => interval(1000).pipe(
|
|
303
|
+
* startWith(start),
|
|
304
|
+
* scan((total, next) => next + total),
|
|
305
|
+
* ), { initialValue: 0 })
|
|
306
|
+
* // count is 0 until the first emission, then keeps accumulating
|
|
307
|
+
*/
|
|
308
|
+
export declare function useExtractedObservable<Value, E, I = undefined>(value: Value | null | undefined, extractor: ExtractedObservableExtractor<Value, E>, options?: UseExtractedObservableOptions<E | I>): E | I;
|
|
309
|
+
//#endregion
|
|
310
|
+
//#region useFrom/index.d.ts
|
|
311
|
+
/**
|
|
312
|
+
* Create an [`Observable`](https://rxjs.dev/guide/observable) from either an
|
|
313
|
+
* rxjs `ObservableInput` (forwarded to RxJS's
|
|
314
|
+
* [`from()`](https://rxjs.dev/api/index/function/from) unchanged) or a plain
|
|
315
|
+
* value that re-emits whenever it changes across renders.
|
|
316
|
+
*
|
|
317
|
+
* Map from @vueuse/rxjs `from`
|
|
318
|
+
* (`source/vueuse/packages/rxjs/from/`): upstream branches on Vue's `isRef`
|
|
319
|
+
* and `watch`es the ref; React has no reactive refs, so the port branches on
|
|
320
|
+
* observable-/promise-likeness and pushes plain values through an internal
|
|
321
|
+
* effect instead.
|
|
322
|
+
*
|
|
323
|
+
* Branch discriminator (runtime):
|
|
324
|
+
* - a value with a `subscribe` function (Observable-like) or a `then` function
|
|
325
|
+
* (Promise-like) is passed straight to rxjs `from(value)` — upstream parity.
|
|
326
|
+
* - any other plain value is wrapped in a `BehaviorSubject` seeded with the
|
|
327
|
+
* current render value: subscribing immediately receives the current value
|
|
328
|
+
* (the mapped `immediate` semantics), and the Observable re-emits whenever
|
|
329
|
+
* the value changes across renders.
|
|
330
|
+
*
|
|
331
|
+
* React divergences:
|
|
332
|
+
* - upstream's `Ref<T>` branch becomes the plain-value re-emit branch. The
|
|
333
|
+
* subject and its `asObservable()` wrapper are held in refs, so the returned
|
|
334
|
+
* Observable keeps a stable identity across renders and downstream
|
|
335
|
+
* subscriptions are not rebuilt by re-renders.
|
|
336
|
+
* - upstream's `WatchOptions` (`immediate` / `deep` / `flush`) is dropped —
|
|
337
|
+
* React has no Vue `watch`. `immediate` is covered by the seeded
|
|
338
|
+
* `BehaviorSubject` (subscribing receives the current value immediately);
|
|
339
|
+
* `deep` / `flush` are not mapped — handle extra control at the call site
|
|
340
|
+
* with rxjs operators or effect dependencies.
|
|
341
|
+
* - the value source is a plain `T` only — never a getter, `State<T>` or
|
|
342
|
+
* `RefOrValue` (AGENTS.md §2).
|
|
343
|
+
* - on unmount the subject is completed: subscriptions stop and no further
|
|
344
|
+
* emissions are delivered. In dev, React StrictMode remounts effects and
|
|
345
|
+
* runs that cleanup, which completes the subject; the mount effect detects
|
|
346
|
+
* the stopped subject and reseeds it, so re-emission survives the simulated
|
|
347
|
+
* unmount/remount cycle.
|
|
348
|
+
*
|
|
349
|
+
* @see https://vueuse.org/rxjs/from/
|
|
350
|
+
* @example
|
|
351
|
+
* const [count, setCount] = useState(0)
|
|
352
|
+
* const count$ = useFrom(count)
|
|
353
|
+
* // count$ emits 0 immediately; setCount(1) re-emits 1
|
|
354
|
+
* @example
|
|
355
|
+
* const values$ = useFrom(of(1, 2)) // ObservableInput: rxjs from() passthrough
|
|
356
|
+
*/
|
|
357
|
+
export declare function useFrom<T>(value: ObservableInput<T> | T): Observable<T>;
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region useSubject/index.d.ts
|
|
360
|
+
/**
|
|
361
|
+
* Options for `useSubject`.
|
|
362
|
+
*
|
|
363
|
+
* Upstream `UseSubjectOptions` is `useObservable`'s options minus
|
|
364
|
+
* `initialValue`: a `BehaviorSubject` seeds the state with its own current
|
|
365
|
+
* value and a plain `Subject` starts out `undefined`, so there is nothing for
|
|
366
|
+
* the caller to supply.
|
|
367
|
+
*/
|
|
368
|
+
export type UseSubjectOptions<I = undefined> = Omit<UseObservableOptions<I>, 'initialValue'>;
|
|
369
|
+
/**
|
|
370
|
+
* Return of `useSubject`: a writable `[value, setValue]` tuple (upstream
|
|
371
|
+
* returns a single `Ref<H>` / `Ref<H | undefined>`).
|
|
372
|
+
*/
|
|
373
|
+
export type UseSubjectReturn<H> = [value: H, setValue: Dispatch<SetStateAction<H>>];
|
|
374
|
+
/**
|
|
375
|
+
* Bind an RxJS [`Subject`](https://rxjs.dev/guide/subject) to a controllable
|
|
376
|
+
* state and propagate value changes both ways.
|
|
377
|
+
*
|
|
378
|
+
* Map from @vueuse/rxjs `useSubject`
|
|
379
|
+
* (`source/vueuse/packages/rxjs/useSubject/`): the state is initialized from a
|
|
380
|
+
* `BehaviorSubject`'s current value (or `undefined` for a plain `Subject`),
|
|
381
|
+
* every emission is written into the state, and writing through the returned
|
|
382
|
+
* setter is pushed back into the subject.
|
|
383
|
+
*
|
|
384
|
+
* React divergences:
|
|
385
|
+
* - upstream returns a `Ref<H>` / `Ref<H | undefined>` that the caller mutates
|
|
386
|
+
* directly; the React port returns a `useState`-like writable
|
|
387
|
+
* `[value, setValue]` tuple (hairyf/reause#218).
|
|
388
|
+
* - `setValue` calls `subject.next(...)` — it does **not** set React state
|
|
389
|
+
* directly. Upstream keeps two writable places (`value.value` and the
|
|
390
|
+
* subject, bridged by `watch`); here the subject is the single source of
|
|
391
|
+
* truth, so a write is observable by every other subscriber of the subject
|
|
392
|
+
* and the exposed value follows the emission that comes back through the
|
|
393
|
+
* subscription. Unlike upstream's `watch` — which skips an unchanged
|
|
394
|
+
* primitive — the write is forwarded unconditionally, so `setValue(current)`
|
|
395
|
+
* still calls `subject.next(current)` and other subscribers see it
|
|
396
|
+
* (hairyf/reause#218).
|
|
397
|
+
* - the setter accepts a functional update (`useState` parity, hairyf/reause#174);
|
|
398
|
+
* it is resolved against the latest value seen by the hook, so two functional
|
|
399
|
+
* updates in the same tick compose instead of both reading the same stale
|
|
400
|
+
* value.
|
|
401
|
+
* - upstream's `tryOnScopeDispose` becomes the effect cleanup: the subscription
|
|
402
|
+
* is created once when the component mounts and unsubscribed on unmount.
|
|
403
|
+
* - the `subject` argument is deliberately **not** an effect dependency — a new
|
|
404
|
+
* identity on a later render neither re-subscribes (Vue's `tryOnScopeDispose`
|
|
405
|
+
* also registers exactly once, during `setup`) nor re-targets `setValue`,
|
|
406
|
+
* which keeps writing into the subject the hook is subscribed to.
|
|
407
|
+
* - `onError` is read when the subscription is created.
|
|
408
|
+
* - SSR-safe: nothing touches `window` / `document`, and the subscription is
|
|
409
|
+
* only created in the mount effect.
|
|
410
|
+
*
|
|
411
|
+
* @see https://vueuse.org/rxjs/useSubject/
|
|
412
|
+
* @example
|
|
413
|
+
* const subject = new BehaviorSubject('initial')
|
|
414
|
+
* const [value, setValue] = useSubject(subject)
|
|
415
|
+
* // value is 'initial'; setValue('next') pushes 'next' into the subject
|
|
416
|
+
*/
|
|
417
|
+
export declare function useSubject<H>(subject: BehaviorSubject<H>, options?: UseSubjectOptions): UseSubjectReturn<H>;
|
|
418
|
+
export declare function useSubject<H>(subject: Subject<H>, options?: UseSubjectOptions): UseSubjectReturn<H | undefined>;
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region useSubscription/index.d.ts
|
|
421
|
+
/**
|
|
422
|
+
* Anything with an RxJS-style `unsubscribe` — upstream types the argument as
|
|
423
|
+
* `Unsubscribable`, which is written structurally here because `rxjs@6` (the
|
|
424
|
+
* version this package resolves, `rxjs` stays a `>=6.0.0` peer) keeps that
|
|
425
|
+
* interface in `rxjs/internal/types` instead of re-exporting it from the
|
|
426
|
+
* package root. A structural type accepts `rxjs@6`'s and `rxjs@7`'s
|
|
427
|
+
* `Unsubscribable` / `Subscription` alike and keeps the peer range honest.
|
|
428
|
+
*/
|
|
429
|
+
export interface UnsubscribableLike {
|
|
430
|
+
unsubscribe: () => void;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Use an RxJS [`Subscription`](https://rxjs.dev/guide/subscription) without
|
|
434
|
+
* worrying about unsubscribing from it or creating memory leaks.
|
|
435
|
+
*
|
|
436
|
+
* Map from @vueuse/rxjs `useSubscription`
|
|
437
|
+
* (`source/vueuse/packages/rxjs/useSubscription/`): the subscription is handed
|
|
438
|
+
* to the hook and torn down automatically when the component unmounts, so the
|
|
439
|
+
* call site never needs its own cleanup.
|
|
440
|
+
*
|
|
441
|
+
* React divergences:
|
|
442
|
+
* - upstream's `tryOnScopeDispose(() => subscription.unsubscribe())` becomes
|
|
443
|
+
* the effect cleanup: the subscription lives from mount until unmount. There
|
|
444
|
+
* is no state, so the hook returns nothing (upstream parity).
|
|
445
|
+
* - like `useObservable` (`packages/rxjs/useObservable/index.tsx`), the
|
|
446
|
+
* argument is deliberately **not** an effect dependency — a new `subscription`
|
|
447
|
+
* identity on a later render does not re-subscribe (Vue's
|
|
448
|
+
* `tryOnScopeDispose` also registers exactly once, during `setup`). Create
|
|
449
|
+
* the subscription with `useState`'s lazy initializer, `useRef` or a module
|
|
450
|
+
* scope when the surrounding component re-renders.
|
|
451
|
+
* - SSR-safe: nothing touches `window` / `document`, and the cleanup only runs
|
|
452
|
+
* on real unmount.
|
|
453
|
+
*
|
|
454
|
+
* @see https://vueuse.org/rxjs/useSubscription/
|
|
455
|
+
* @example
|
|
456
|
+
* const [count, setCount] = useState(0)
|
|
457
|
+
* useSubscription(interval(1000).subscribe(() => setCount(c => c + 1)))
|
|
458
|
+
* // unsubscribes when the component unmounts
|
|
459
|
+
*/
|
|
460
|
+
export declare function useSubscription(subscription: UnsubscribableLike): void;
|
|
461
|
+
//#endregion
|