mirror of
https://github.com/dergigi/boris.git
synced 2025-12-17 22:54:30 +01:00
feat: initialize markr nostr bookmark client
- Add project structure with TypeScript, React, and Vite - Implement nostr authentication using browser extension (NIP-07) - Add NIP-51 compliant bookmark fetching and display - Create minimal UI with login and bookmark components - Integrate applesauce-core and applesauce-react libraries - Add responsive styling with dark/light mode support - Include comprehensive README with setup instructions This is a minimal MVP for a nostr bookmark client that allows users to view their bookmarks according to NIP-51 specification.
This commit is contained in:
21
node_modules/observable-hooks/LICENSE
generated
vendored
Normal file
21
node_modules/observable-hooks/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 CRIMX<straybugs@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
101
node_modules/observable-hooks/README.md
generated
vendored
Normal file
101
node_modules/observable-hooks/README.md
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
# [observable-hooks](https://github.com/crimx/observable-hooks)
|
||||
|
||||
[](https://www.npmjs.com/package/observable-hooks)
|
||||
[](https://bundlephobia.com/result?p=observable-hooks)
|
||||
[](https://travis-ci.com/crimx/observable-hooks)
|
||||
[](https://coveralls.io/github/crimx/observable-hooks?branch=main)
|
||||
|
||||
[](http://commitizen.github.io/cz-cli/)
|
||||
[](https://conventionalcommits.org)
|
||||
[](https://standardjs.com)
|
||||
[](https://github.com/prettier/prettier)
|
||||
|
||||

|
||||
|
||||
React hooks for RxJS Observables. Simple, flexible, testable and performant.
|
||||
|
||||
- Seamless integration of React and RxJS.
|
||||
- Props and states to Observables.
|
||||
- Observables to states and props events.
|
||||
- Conditional rendering with stream of React Components.
|
||||
- Render-as-You-Fetch with React Suspense.
|
||||
- No `tap` hack needed. With Epic-like signature Observable operation is pure and testable.
|
||||
- Full-powered RxJS. Do whatever you want with Observables. No limitation nor compromise.
|
||||
- Fully tested. We believe in stability first. This project will always maintain a 100% coverage.
|
||||
- Tiny and fast. A lot of efforts had been put into improving integration. This library should have zero visible impact on performance.
|
||||
- Compatible with RxJS 6 & 7.
|
||||
|
||||
## Why?
|
||||
|
||||
React added hooks for [reusing stateful logic](https://reactjs.org/docs/hooks-intro.html#its-hard-to-reuse-stateful-logic-between-components).
|
||||
|
||||
Observable is a powerful way to encapsulate both sync and async logic.
|
||||
|
||||
[Testing](https://rxjs-dev.firebaseapp.com/guide/testing/marble-testing) Observables is also way easier than testing other async implementations.
|
||||
|
||||
With [observable-hooks](https://github.com/crimx/observable-hooks) we can create rich reusable Components with ease.
|
||||
|
||||
## What It Is Not
|
||||
|
||||
This library is not for replacing state management tools like Redux but to reduce the need of dumping everything into global state.
|
||||
|
||||
Using this library does not mean you have to turn everything observable which is not encouraged. It plays well side by side with other hooks. Use it only on places where it's needed.
|
||||
|
||||
## At First Glance
|
||||
|
||||
```jsx
|
||||
import * as React from "react";
|
||||
import { useObservableState } from "observable-hooks";
|
||||
import { timer } from "rxjs";
|
||||
import { switchMap, mapTo, startWith } from "rxjs/operators";
|
||||
|
||||
const App = () => {
|
||||
const [isTyping, updateIsTyping] = useObservableState(
|
||||
transformTypingStatus,
|
||||
false
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input type="text" onKeyDown={updateIsTyping} />
|
||||
<p>{isTyping ? "Good you are typing." : "Why stop typing?"}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Logic is pure and can be tested like Epic in redux-observable
|
||||
function transformTypingStatus(event$) {
|
||||
return event$.pipe(
|
||||
switchMap(() => timer(1000).pipe(mapTo(false), startWith(true)))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
yarn
|
||||
|
||||
```bash
|
||||
yarn add observable-hooks
|
||||
```
|
||||
|
||||
npm
|
||||
|
||||
```bash
|
||||
npm install --save observable-hooks
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Read the docs at <https://observable-hooks.js.org>.
|
||||
|
||||
Here is how I designed the API. Might give you a perspective on when use what.
|
||||
|
||||

|
||||
|
||||
Examples are in [here](https://github.com/crimx/observable-hooks/tree/main/examples). Play on CodeSandbox:
|
||||
|
||||
- [Pomodoro Timer Example](https://codesandbox.io/s/github/crimx/observable-hooks/tree/main/examples/pomodoro-timer)
|
||||
- [Typeahead Example](https://codesandbox.io/s/github/crimx/observable-hooks/tree/main/examples/typeahead)
|
||||
|
||||
Note that there are also some useful [utilities](https://observable-hooks.js.org/modules/_helpers_.html) for common use cases to reduce garbage collection.
|
||||
571
node_modules/observable-hooks/dist/index.d.mts
generated
vendored
Normal file
571
node_modules/observable-hooks/dist/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
import { Observable, PartialObserver, Subscription, BehaviorSubject, Subject } from 'rxjs';
|
||||
import { MutableRefObject, RefObject } from 'react';
|
||||
|
||||
/**
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useObservable<TOutput, TObservable extends Observable<TOutput> = Observable<TOutput>>(init: () => TObservable): TObservable;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
declare function useObservable<TOutput, TInputs extends Readonly<any[]>, TObservable extends Observable<TOutput> = Observable<TOutput>>(init: (inputs$: Observable<[...TInputs]>) => TObservable, inputs: [...TInputs]): TObservable;
|
||||
|
||||
/**
|
||||
* Same as [[useObservable]] excepts using `useLayoutEffect`.
|
||||
*
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useLayoutObservable<TOutput>(init: () => Observable<TOutput>): Observable<TOutput>;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
declare function useLayoutObservable<TOutput, TInputs extends Readonly<any[]>>(init: (inputs$: Observable<[...TInputs]>) => Observable<TOutput>, inputs: [...TInputs]): Observable<TOutput>;
|
||||
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* @template TEvent Output value of Observable.
|
||||
*/
|
||||
declare function useObservableCallback<TEvent = void>(): [
|
||||
(event: TEvent) => void,
|
||||
Observable<TEvent>
|
||||
];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useObservableCallback<TOutput, TInput = TOutput>(init: (events$: Observable<TInput>) => Observable<TOutput>): [(event: TInput) => void, Observable<TOutput>];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* (From v2.1.0) Optionally accepts a selector function that transforms
|
||||
* a list of event arguments into a single value.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
* @template TParams A tuple of event callback parameters.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param selector A function that transforms an array of event arguments
|
||||
* into a single value.
|
||||
*/
|
||||
declare function useObservableCallback<TOutput = undefined, TInput = TOutput, TParams extends Readonly<any[]> = [TInput]>(init: (events$: Observable<TInput>) => Observable<TOutput>, selector: (args: TParams) => TInput): [(...args: TParams) => void, Observable<TOutput>];
|
||||
|
||||
/**
|
||||
* Accepts an Observable and optional `next`, `error`, `complete` functions.
|
||||
* These functions must be in correct order.
|
||||
* Use `undefined` or `null` for placeholder.
|
||||
*
|
||||
* Subscription will unsubscribe when unmount, you can also
|
||||
* unsubscribe manually.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen
|
||||
* which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* Note that changes of callbacks will not trigger
|
||||
* an emission. If you need that just create another
|
||||
* Observable of the callback with [[useObservable]].
|
||||
*
|
||||
* (From v2.0) You can access closure directly inside callback like in `useEffect`.
|
||||
* `useSubscription` will ensure the latest callback is called.
|
||||
*
|
||||
* (From v2.3.4) when the Observable changes `useSubscription` will automatically
|
||||
* unsubscribe the old one and resubscribe to the new one.
|
||||
*
|
||||
* ⚠ **Note:** Due to the design of RxJS, once an error occurs in an observable, the observable
|
||||
* is killed.
|
||||
* You should prevent errors from reaching observables or `catchError` in sub-observables.
|
||||
* You can also make the observable as state and replace it on error.
|
||||
* `useSubscription` will automatically switch to the new one.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
declare function useSubscription<TInput>(input$: Observable<TInput>, observer?: PartialObserver<TInput>): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
declare function useSubscription<TInput>(input$: Observable<TInput>, next?: ((value: TInput) => void) | null | undefined, error?: ((error: any) => void) | null | undefined, complete?: (() => void) | null | undefined): MutableRefObject<Subscription | undefined>;
|
||||
|
||||
/**
|
||||
* Same as [[useSubscription]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* Useful when values are needed before DOM paint.
|
||||
*
|
||||
* Use it scarcely as it runs synchronously before browser paint.
|
||||
* Too many synchronous emissions from the observable could
|
||||
* stretch the commit phase.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
declare function useLayoutSubscription<TInput>(input$: Observable<TInput>, observer?: PartialObserver<TInput>): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
declare function useLayoutSubscription<TInput>(input$: Observable<TInput>, next?: ((value: TInput) => void) | null | undefined, error?: ((error: any) => void) | null | undefined, complete?: (() => void) | null | undefined): MutableRefObject<Subscription | undefined>;
|
||||
|
||||
/**
|
||||
* Enhance an Observable by making errors catch-able to ErrorBoundary.
|
||||
*
|
||||
* It catches Observable error and re-throw it as React render error.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @returns Observable with the same input type
|
||||
*/
|
||||
declare function useRenderThrow<TInput>(input$: Observable<TInput>): Observable<TInput>;
|
||||
|
||||
/**
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reducer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: BehaviorSubject<TState>): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: Observable<TState>): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
declare function useObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>) => Observable<TState>): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>, initialState: TState) => Observable<TState>, initialState: TState | (() => TState)): [TState, (input: TInput) => void];
|
||||
|
||||
/**
|
||||
* Same as [[useObservableState]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useLayoutObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useLayoutObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reduer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: BehaviorSubject<TState>): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: Observable<TState>): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>) => Observable<TState>): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>, initialState: TState) => Observable<TState>, initialState: TState | (() => TState)): [TState, (input: TInput) => void];
|
||||
|
||||
/**
|
||||
* Optimized for safely getting synchronous values from hot or pure observables
|
||||
* without triggering extra initial re-rendering.
|
||||
*
|
||||
* ⚠ If the observable is cold and with side effects
|
||||
* they will be performed at least twice!
|
||||
*
|
||||
* By default this hook will subscribe to the observable at least twice.
|
||||
* The first time is for getting synchronous value to prevent extra initial re-rendering.
|
||||
* In concurrent mode this may happen more than one time.
|
||||
*
|
||||
* @template TState State.
|
||||
*
|
||||
* @param state$ An observable of state value.
|
||||
*/
|
||||
declare function useObservableEagerState<TState>(state$: Observable<TState>): TState;
|
||||
|
||||
/**
|
||||
* Gets the value at path of state. Similar to lodash `get`.
|
||||
* Only changes of the resulted value will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
*/
|
||||
declare function useObservableGetState<TState>(state$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void>(state$: Observable<TState>, initialState: TInitial): TState | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState>(state$: Observable<TState>, initialState: TState[A] | (() => TState[A]), pA: A): TState[A];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState>(state$: Observable<TState>, initialState: TInitial, pA: A): TState[A] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A]>(state$: Observable<TState>, initialState: TState[A][B] | (() => TState[A][B]), pA: A, pB: B): TState[A][B];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B): TState[A][B] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B]>(state$: Observable<TState>, initialState: TState[A][B][C] | (() => TState[A][B][C]), pA: A, pB: B, pC: C): TState[A][B][C];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C): TState[A][B][C] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C]>(state$: Observable<TState>, initialState: TState[A][B][C][D] | (() => TState[A][B][C][D]), pA: A, pB: B, pC: C, pD: D): TState[A][B][C][D];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D): TState[A][B][C][D] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E] | (() => TState[A][B][C][D][E]), pA: A, pB: B, pC: C, pD: D, pE: E): TState[A][B][C][D][E];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E): TState[A][B][C][D][E] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F] | (() => TState[A][B][C][D][E][F]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F): TState[A][B][C][D][E][F];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F): TState[A][B][C][D][E][F] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G] | (() => TState[A][B][C][D][E][F][G]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G): TState[A][B][C][D][E][F][G];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G): TState[A][B][C][D][E][F][G] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G][H] | (() => TState[A][B][C][D][E][F][G][H]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H): TState[A][B][C][D][E][F][G][H];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H): TState[A][B][C][D][E][F][G][H] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G][H][I] | (() => TState[A][B][C][D][E][F][G][H][I]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I): TState[A][B][C][D][E][F][G][H][I];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I): TState[A][B][C][D][E][F][G][H][I] | TInitial;
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H], J extends keyof TState[A][B][C][D][E][F][G][H][I]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I, pJ: J): TState[A][B][C][D][E][F][G][H][I][J] | TInitial;
|
||||
|
||||
/**
|
||||
* Creates an object composed of the picked state properties. Similar to lodash `pick`.
|
||||
* Changes of any of these properties will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
* @param keys keys of state
|
||||
*/
|
||||
declare function useObservablePickState<TState, TKeys extends keyof TState, TInitial extends null | undefined | void>(state$: Observable<TState>, initialState: TInitial, ...keys: TKeys[]): {
|
||||
[K in TKeys]: TState[K];
|
||||
} | TInitial;
|
||||
declare function useObservablePickState<TState, TKeys extends keyof TState>(state$: Observable<TState>, initialState: {
|
||||
[K in TKeys]: TState[K];
|
||||
} | (() => {
|
||||
[K in TKeys]: TState[K];
|
||||
}), ...keys: TKeys[]): {
|
||||
[K in TKeys]: TState[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewires Observable to Relay-like Suspense resource.
|
||||
*/
|
||||
declare class ObservableResource<TInput, TOutput extends TInput = TInput> {
|
||||
/**
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* Only force update when Suspense needs to restart.
|
||||
*/
|
||||
readonly shouldUpdate$$: Subject<true>;
|
||||
get isDestroyed(): boolean;
|
||||
readonly valueRef$$: BehaviorSubject<{
|
||||
current: TOutput;
|
||||
} | undefined>;
|
||||
input$: Observable<TInput>;
|
||||
private _handler_;
|
||||
private _error_;
|
||||
private _subscription_;
|
||||
private _isDestroyed_;
|
||||
private readonly _observer_;
|
||||
/**
|
||||
* @param input$ An Observable.
|
||||
* @param isSuccess A function that determines if the value emitted from
|
||||
* `input$` is of success state. If false a Suspense is triggered.
|
||||
* Default all true.
|
||||
*/
|
||||
constructor(input$: Observable<TInput>, isSuccess?: TInput extends TOutput ? (value: TInput) => boolean : (value: TInput) => value is TOutput);
|
||||
read(): TOutput;
|
||||
reload(newInput$?: Observable<TInput>): void;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the Observable resource.
|
||||
*
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* This hook triggers extra re-rendering when Suspense should restart.
|
||||
*
|
||||
* @param resource Observable resource
|
||||
*/
|
||||
declare function useObservableSuspense<TInput, TOutput extends TInput = TInput>(resource: ObservableResource<TInput, TOutput>): TOutput;
|
||||
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue>(initialValue: TValue): [MutableRefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue>(initialValue: TValue | null): [RefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue A optional initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue = undefined>(initialValue?: TValue): [MutableRefObject<TValue | undefined>, BehaviorSubject<TValue | undefined>];
|
||||
|
||||
/**
|
||||
* Useful utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the first argument it receives.
|
||||
*/
|
||||
declare const identity: <T>(value: T) => T;
|
||||
/**
|
||||
* Maps an Observable of Arraylike to an Observable
|
||||
* of the first item.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const text$ = useObservable(pluckFirst, [props.text])
|
||||
* ```
|
||||
*
|
||||
* @param inputs$ An Observable of array-like.
|
||||
*
|
||||
*/
|
||||
declare const pluckFirst: <TArr extends ArrayLike<any>>(inputs$: Observable<TArr>) => Observable<TArr[0]>;
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget value.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, textChange$] = useObservableCallback<
|
||||
* string,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetValue)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
declare const pluckCurrentTargetValue: <TEvent extends {
|
||||
currentTarget: {
|
||||
value: any;
|
||||
};
|
||||
}>(event$: Observable<TEvent>) => Observable<TEvent["currentTarget"]["value"]>;
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget checked.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, checked$] = useObservableCallback<
|
||||
* boolean,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetChecked)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
declare const pluckCurrentTargetChecked: <TEvent extends {
|
||||
currentTarget: {
|
||||
checked: any;
|
||||
};
|
||||
}>(event$: Observable<TEvent>) => Observable<TEvent["currentTarget"]["checked"]>;
|
||||
/**
|
||||
* One-time ref init.
|
||||
* @param init A function that returns a value. Will be called only once.
|
||||
* @returns A ref object with the returned value.
|
||||
*/
|
||||
declare const useRefFn: <T>(init: () => T) => MutableRefObject<T>;
|
||||
/**
|
||||
* Force re-renders Component.
|
||||
*/
|
||||
declare const useForceUpdate: () => (() => void);
|
||||
|
||||
export { ObservableResource, identity, pluckCurrentTargetChecked, pluckCurrentTargetValue, pluckFirst, useForceUpdate, useLayoutObservable, useLayoutObservableState, useLayoutSubscription, useObservable, useObservableCallback, useObservableEagerState, useObservableGetState, useObservablePickState, useObservableRef, useObservableState, useObservableSuspense, useRefFn, useRenderThrow, useSubscription };
|
||||
571
node_modules/observable-hooks/dist/index.d.ts
generated
vendored
Normal file
571
node_modules/observable-hooks/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
import { Observable, PartialObserver, Subscription, BehaviorSubject, Subject } from 'rxjs';
|
||||
import { MutableRefObject, RefObject } from 'react';
|
||||
|
||||
/**
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useObservable<TOutput, TObservable extends Observable<TOutput> = Observable<TOutput>>(init: () => TObservable): TObservable;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
declare function useObservable<TOutput, TInputs extends Readonly<any[]>, TObservable extends Observable<TOutput> = Observable<TOutput>>(init: (inputs$: Observable<[...TInputs]>) => TObservable, inputs: [...TInputs]): TObservable;
|
||||
|
||||
/**
|
||||
* Same as [[useObservable]] excepts using `useLayoutEffect`.
|
||||
*
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useLayoutObservable<TOutput>(init: () => Observable<TOutput>): Observable<TOutput>;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
declare function useLayoutObservable<TOutput, TInputs extends Readonly<any[]>>(init: (inputs$: Observable<[...TInputs]>) => Observable<TOutput>, inputs: [...TInputs]): Observable<TOutput>;
|
||||
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* @template TEvent Output value of Observable.
|
||||
*/
|
||||
declare function useObservableCallback<TEvent = void>(): [
|
||||
(event: TEvent) => void,
|
||||
Observable<TEvent>
|
||||
];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
declare function useObservableCallback<TOutput, TInput = TOutput>(init: (events$: Observable<TInput>) => Observable<TOutput>): [(event: TInput) => void, Observable<TOutput>];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* (From v2.1.0) Optionally accepts a selector function that transforms
|
||||
* a list of event arguments into a single value.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
* @template TParams A tuple of event callback parameters.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param selector A function that transforms an array of event arguments
|
||||
* into a single value.
|
||||
*/
|
||||
declare function useObservableCallback<TOutput = undefined, TInput = TOutput, TParams extends Readonly<any[]> = [TInput]>(init: (events$: Observable<TInput>) => Observable<TOutput>, selector: (args: TParams) => TInput): [(...args: TParams) => void, Observable<TOutput>];
|
||||
|
||||
/**
|
||||
* Accepts an Observable and optional `next`, `error`, `complete` functions.
|
||||
* These functions must be in correct order.
|
||||
* Use `undefined` or `null` for placeholder.
|
||||
*
|
||||
* Subscription will unsubscribe when unmount, you can also
|
||||
* unsubscribe manually.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen
|
||||
* which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* Note that changes of callbacks will not trigger
|
||||
* an emission. If you need that just create another
|
||||
* Observable of the callback with [[useObservable]].
|
||||
*
|
||||
* (From v2.0) You can access closure directly inside callback like in `useEffect`.
|
||||
* `useSubscription` will ensure the latest callback is called.
|
||||
*
|
||||
* (From v2.3.4) when the Observable changes `useSubscription` will automatically
|
||||
* unsubscribe the old one and resubscribe to the new one.
|
||||
*
|
||||
* ⚠ **Note:** Due to the design of RxJS, once an error occurs in an observable, the observable
|
||||
* is killed.
|
||||
* You should prevent errors from reaching observables or `catchError` in sub-observables.
|
||||
* You can also make the observable as state and replace it on error.
|
||||
* `useSubscription` will automatically switch to the new one.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
declare function useSubscription<TInput>(input$: Observable<TInput>, observer?: PartialObserver<TInput>): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
declare function useSubscription<TInput>(input$: Observable<TInput>, next?: ((value: TInput) => void) | null | undefined, error?: ((error: any) => void) | null | undefined, complete?: (() => void) | null | undefined): MutableRefObject<Subscription | undefined>;
|
||||
|
||||
/**
|
||||
* Same as [[useSubscription]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* Useful when values are needed before DOM paint.
|
||||
*
|
||||
* Use it scarcely as it runs synchronously before browser paint.
|
||||
* Too many synchronous emissions from the observable could
|
||||
* stretch the commit phase.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
declare function useLayoutSubscription<TInput>(input$: Observable<TInput>, observer?: PartialObserver<TInput>): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
declare function useLayoutSubscription<TInput>(input$: Observable<TInput>, next?: ((value: TInput) => void) | null | undefined, error?: ((error: any) => void) | null | undefined, complete?: (() => void) | null | undefined): MutableRefObject<Subscription | undefined>;
|
||||
|
||||
/**
|
||||
* Enhance an Observable by making errors catch-able to ErrorBoundary.
|
||||
*
|
||||
* It catches Observable error and re-throw it as React render error.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @returns Observable with the same input type
|
||||
*/
|
||||
declare function useRenderThrow<TInput>(input$: Observable<TInput>): Observable<TInput>;
|
||||
|
||||
/**
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reducer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: BehaviorSubject<TState>): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: Observable<TState>): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useObservableState<TState>(input$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
declare function useObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>) => Observable<TState>): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>, initialState: TState) => Observable<TState>, initialState: TState | (() => TState)): [TState, (input: TInput) => void];
|
||||
|
||||
/**
|
||||
* Same as [[useObservableState]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useLayoutObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useLayoutObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reduer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: BehaviorSubject<TState>): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: Observable<TState>): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState>(input$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>) => Observable<TState>): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
declare function useLayoutObservableState<TState, TInput = TState>(init: (input$: Observable<TInput>, initialState: TState) => Observable<TState>, initialState: TState | (() => TState)): [TState, (input: TInput) => void];
|
||||
|
||||
/**
|
||||
* Optimized for safely getting synchronous values from hot or pure observables
|
||||
* without triggering extra initial re-rendering.
|
||||
*
|
||||
* ⚠ If the observable is cold and with side effects
|
||||
* they will be performed at least twice!
|
||||
*
|
||||
* By default this hook will subscribe to the observable at least twice.
|
||||
* The first time is for getting synchronous value to prevent extra initial re-rendering.
|
||||
* In concurrent mode this may happen more than one time.
|
||||
*
|
||||
* @template TState State.
|
||||
*
|
||||
* @param state$ An observable of state value.
|
||||
*/
|
||||
declare function useObservableEagerState<TState>(state$: Observable<TState>): TState;
|
||||
|
||||
/**
|
||||
* Gets the value at path of state. Similar to lodash `get`.
|
||||
* Only changes of the resulted value will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
*/
|
||||
declare function useObservableGetState<TState>(state$: Observable<TState>, initialState: TState | (() => TState)): TState;
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void>(state$: Observable<TState>, initialState: TInitial): TState | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState>(state$: Observable<TState>, initialState: TState[A] | (() => TState[A]), pA: A): TState[A];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState>(state$: Observable<TState>, initialState: TInitial, pA: A): TState[A] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A]>(state$: Observable<TState>, initialState: TState[A][B] | (() => TState[A][B]), pA: A, pB: B): TState[A][B];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B): TState[A][B] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B]>(state$: Observable<TState>, initialState: TState[A][B][C] | (() => TState[A][B][C]), pA: A, pB: B, pC: C): TState[A][B][C];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C): TState[A][B][C] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C]>(state$: Observable<TState>, initialState: TState[A][B][C][D] | (() => TState[A][B][C][D]), pA: A, pB: B, pC: C, pD: D): TState[A][B][C][D];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D): TState[A][B][C][D] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E] | (() => TState[A][B][C][D][E]), pA: A, pB: B, pC: C, pD: D, pE: E): TState[A][B][C][D][E];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E): TState[A][B][C][D][E] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F] | (() => TState[A][B][C][D][E][F]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F): TState[A][B][C][D][E][F];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F): TState[A][B][C][D][E][F] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G] | (() => TState[A][B][C][D][E][F][G]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G): TState[A][B][C][D][E][F][G];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G): TState[A][B][C][D][E][F][G] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G][H] | (() => TState[A][B][C][D][E][F][G][H]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H): TState[A][B][C][D][E][F][G][H];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H): TState[A][B][C][D][E][F][G][H] | TInitial;
|
||||
declare function useObservableGetState<TState, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H]>(state$: Observable<TState>, initialState: TState[A][B][C][D][E][F][G][H][I] | (() => TState[A][B][C][D][E][F][G][H][I]), pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I): TState[A][B][C][D][E][F][G][H][I];
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I): TState[A][B][C][D][E][F][G][H][I] | TInitial;
|
||||
declare function useObservableGetState<TState, TInitial extends null | undefined | void, A extends keyof TState, B extends keyof TState[A], C extends keyof TState[A][B], D extends keyof TState[A][B][C], E extends keyof TState[A][B][C][D], F extends keyof TState[A][B][C][D][E], G extends keyof TState[A][B][C][D][E][F], H extends keyof TState[A][B][C][D][E][F][G], I extends keyof TState[A][B][C][D][E][F][G][H], J extends keyof TState[A][B][C][D][E][F][G][H][I]>(state$: Observable<TState>, initialState: TInitial, pA: A, pB: B, pC: C, pD: D, pE: E, pF: F, pG: G, pH: H, pI: I, pJ: J): TState[A][B][C][D][E][F][G][H][I][J] | TInitial;
|
||||
|
||||
/**
|
||||
* Creates an object composed of the picked state properties. Similar to lodash `pick`.
|
||||
* Changes of any of these properties will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
* @param keys keys of state
|
||||
*/
|
||||
declare function useObservablePickState<TState, TKeys extends keyof TState, TInitial extends null | undefined | void>(state$: Observable<TState>, initialState: TInitial, ...keys: TKeys[]): {
|
||||
[K in TKeys]: TState[K];
|
||||
} | TInitial;
|
||||
declare function useObservablePickState<TState, TKeys extends keyof TState>(state$: Observable<TState>, initialState: {
|
||||
[K in TKeys]: TState[K];
|
||||
} | (() => {
|
||||
[K in TKeys]: TState[K];
|
||||
}), ...keys: TKeys[]): {
|
||||
[K in TKeys]: TState[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewires Observable to Relay-like Suspense resource.
|
||||
*/
|
||||
declare class ObservableResource<TInput, TOutput extends TInput = TInput> {
|
||||
/**
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* Only force update when Suspense needs to restart.
|
||||
*/
|
||||
readonly shouldUpdate$$: Subject<true>;
|
||||
get isDestroyed(): boolean;
|
||||
readonly valueRef$$: BehaviorSubject<{
|
||||
current: TOutput;
|
||||
} | undefined>;
|
||||
input$: Observable<TInput>;
|
||||
private _handler_;
|
||||
private _error_;
|
||||
private _subscription_;
|
||||
private _isDestroyed_;
|
||||
private readonly _observer_;
|
||||
/**
|
||||
* @param input$ An Observable.
|
||||
* @param isSuccess A function that determines if the value emitted from
|
||||
* `input$` is of success state. If false a Suspense is triggered.
|
||||
* Default all true.
|
||||
*/
|
||||
constructor(input$: Observable<TInput>, isSuccess?: TInput extends TOutput ? (value: TInput) => boolean : (value: TInput) => value is TOutput);
|
||||
read(): TOutput;
|
||||
reload(newInput$?: Observable<TInput>): void;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the Observable resource.
|
||||
*
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* This hook triggers extra re-rendering when Suspense should restart.
|
||||
*
|
||||
* @param resource Observable resource
|
||||
*/
|
||||
declare function useObservableSuspense<TInput, TOutput extends TInput = TInput>(resource: ObservableResource<TInput, TOutput>): TOutput;
|
||||
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue>(initialValue: TValue): [MutableRefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue>(initialValue: TValue | null): [RefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue A optional initial value of the BehaviorSubject.
|
||||
*/
|
||||
declare function useObservableRef<TValue = undefined>(initialValue?: TValue): [MutableRefObject<TValue | undefined>, BehaviorSubject<TValue | undefined>];
|
||||
|
||||
/**
|
||||
* Useful utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the first argument it receives.
|
||||
*/
|
||||
declare const identity: <T>(value: T) => T;
|
||||
/**
|
||||
* Maps an Observable of Arraylike to an Observable
|
||||
* of the first item.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const text$ = useObservable(pluckFirst, [props.text])
|
||||
* ```
|
||||
*
|
||||
* @param inputs$ An Observable of array-like.
|
||||
*
|
||||
*/
|
||||
declare const pluckFirst: <TArr extends ArrayLike<any>>(inputs$: Observable<TArr>) => Observable<TArr[0]>;
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget value.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, textChange$] = useObservableCallback<
|
||||
* string,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetValue)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
declare const pluckCurrentTargetValue: <TEvent extends {
|
||||
currentTarget: {
|
||||
value: any;
|
||||
};
|
||||
}>(event$: Observable<TEvent>) => Observable<TEvent["currentTarget"]["value"]>;
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget checked.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, checked$] = useObservableCallback<
|
||||
* boolean,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetChecked)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
declare const pluckCurrentTargetChecked: <TEvent extends {
|
||||
currentTarget: {
|
||||
checked: any;
|
||||
};
|
||||
}>(event$: Observable<TEvent>) => Observable<TEvent["currentTarget"]["checked"]>;
|
||||
/**
|
||||
* One-time ref init.
|
||||
* @param init A function that returns a value. Will be called only once.
|
||||
* @returns A ref object with the returned value.
|
||||
*/
|
||||
declare const useRefFn: <T>(init: () => T) => MutableRefObject<T>;
|
||||
/**
|
||||
* Force re-renders Component.
|
||||
*/
|
||||
declare const useForceUpdate: () => (() => void);
|
||||
|
||||
export { ObservableResource, identity, pluckCurrentTargetChecked, pluckCurrentTargetValue, pluckFirst, useForceUpdate, useLayoutObservable, useLayoutObservableState, useLayoutSubscription, useObservable, useObservableCallback, useObservableEagerState, useObservableGetState, useObservablePickState, useObservableRef, useObservableState, useObservableSuspense, useRefFn, useRenderThrow, useSubscription };
|
||||
443
node_modules/observable-hooks/dist/index.js
generated
vendored
Normal file
443
node_modules/observable-hooks/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,443 @@
|
||||
'use strict';
|
||||
|
||||
var rxjs = require('rxjs');
|
||||
var react = require('react');
|
||||
var operators = require('rxjs/operators');
|
||||
|
||||
// src/internal/use-observable-internal.ts
|
||||
function useObservableInternal(useCustomEffect, init, inputs) {
|
||||
if (!inputs) {
|
||||
return react.useState(init)[0];
|
||||
}
|
||||
const [inputs$] = react.useState(() => new rxjs.BehaviorSubject(inputs));
|
||||
const [source$] = react.useState(() => init(inputs$));
|
||||
const firstEffectRef = react.useRef(true);
|
||||
useCustomEffect(() => {
|
||||
if (firstEffectRef.current) {
|
||||
firstEffectRef.current = false;
|
||||
return;
|
||||
}
|
||||
inputs$.next(inputs);
|
||||
}, inputs);
|
||||
return source$;
|
||||
}
|
||||
function useObservable(init, inputs) {
|
||||
return useObservableInternal(react.useEffect, init, inputs);
|
||||
}
|
||||
var identity = (value) => value;
|
||||
var pluckFirst = (inputs$) => operators.map((input) => input[0])(inputs$);
|
||||
var pluckCurrentTargetValue = (event$) => operators.map(
|
||||
(event) => event.currentTarget.value
|
||||
)(event$);
|
||||
var pluckCurrentTargetChecked = (event$) => operators.map(
|
||||
(event) => event.currentTarget.checked
|
||||
)(event$);
|
||||
var getEmptySubject = () => new rxjs.Subject();
|
||||
var useRefFn = (init) => {
|
||||
const firstRef = react.useRef(true);
|
||||
const ref = react.useRef(null);
|
||||
if (firstRef.current) {
|
||||
firstRef.current = false;
|
||||
ref.current = init();
|
||||
}
|
||||
return ref;
|
||||
};
|
||||
var increment = (n) => n + 1 | 0;
|
||||
var useForceUpdate = () => {
|
||||
const updateState = react.useState(0)[1];
|
||||
return react.useRef(() => updateState(increment)).current;
|
||||
};
|
||||
var useIsomorphicLayoutEffect = /* @__PURE__ */ (() => (
|
||||
/* istanbul ignore next */
|
||||
typeof window === "undefined" ? react.useEffect : react.useLayoutEffect
|
||||
))();
|
||||
|
||||
// src/use-layout-observable.ts
|
||||
function useLayoutObservable(init, inputs) {
|
||||
return useObservableInternal(useIsomorphicLayoutEffect, init, inputs);
|
||||
}
|
||||
function useObservableCallback(init = identity, selector) {
|
||||
const [events$] = react.useState(getEmptySubject);
|
||||
const [outputs$] = react.useState(() => init(events$));
|
||||
const callback = react.useRef((...args) => {
|
||||
events$.next(selector ? selector(args) : args[0]);
|
||||
}).current;
|
||||
return [callback, outputs$];
|
||||
}
|
||||
var toObserver = (args) => args[1]?.next ? args[1] : {
|
||||
next: args[1],
|
||||
error: args[2],
|
||||
complete: args[3]
|
||||
};
|
||||
function useSubscriptionInternal(useCustomEffect, args) {
|
||||
const argsRef = react.useRef(args);
|
||||
const observerRef = react.useRef();
|
||||
const subscriptionRef = react.useRef();
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
argsRef.current = args;
|
||||
observerRef.current = toObserver(args);
|
||||
});
|
||||
useCustomEffect(() => {
|
||||
const input$ = argsRef.current[0];
|
||||
if (!observerRef.current) {
|
||||
observerRef.current = toObserver(argsRef.current);
|
||||
}
|
||||
const subscription = input$.subscribe({
|
||||
next: (value) => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.next?.(value);
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.error ? observerRef.current.error(error) : console.error(error);
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.complete?.();
|
||||
}
|
||||
}
|
||||
});
|
||||
subscriptionRef.current = subscription;
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [args[0]]);
|
||||
return subscriptionRef;
|
||||
}
|
||||
|
||||
// src/use-subscription.ts
|
||||
function useSubscription(input$, observerOrNext$, error, complete) {
|
||||
return useSubscriptionInternal(react.useEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete
|
||||
]);
|
||||
}
|
||||
|
||||
// src/use-layout-subscription.ts
|
||||
function useLayoutSubscription(input$, observerOrNext$, error, complete) {
|
||||
return useSubscriptionInternal(useIsomorphicLayoutEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete
|
||||
]);
|
||||
}
|
||||
function useRenderThrow(input$) {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const errorRef = react.useRef();
|
||||
const output$ = useObservable(
|
||||
(inputs$) => inputs$.pipe(
|
||||
operators.switchMap(([input$2]) => {
|
||||
errorRef.current = null;
|
||||
return input$2.pipe(
|
||||
operators.catchError((error) => {
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
return rxjs.NEVER;
|
||||
})
|
||||
);
|
||||
})
|
||||
),
|
||||
[input$]
|
||||
);
|
||||
if (errorRef.current) {
|
||||
throw errorRef.current;
|
||||
}
|
||||
return output$;
|
||||
}
|
||||
function useObservableStateInternal(useSubscription2, state$OrInit, initialState) {
|
||||
if (rxjs.isObservable(state$OrInit)) {
|
||||
const state$ = state$OrInit;
|
||||
const [state, setState] = react.useState(() => {
|
||||
if (state$ instanceof rxjs.BehaviorSubject || state$.value !== void 0) {
|
||||
return state$.value;
|
||||
}
|
||||
if (typeof initialState === "function") {
|
||||
return initialState();
|
||||
}
|
||||
return initialState;
|
||||
});
|
||||
useSubscription2(state$, setState);
|
||||
react.useDebugValue(state);
|
||||
return state;
|
||||
} else {
|
||||
const init = state$OrInit;
|
||||
const [state, setState] = react.useState(initialState);
|
||||
const [input$] = react.useState(getEmptySubject);
|
||||
const [state$] = react.useState(() => init(input$, state));
|
||||
const callback = react.useRef((state2) => input$.next(state2)).current;
|
||||
useSubscription2(state$, setState);
|
||||
react.useDebugValue(state);
|
||||
return [state, callback];
|
||||
}
|
||||
}
|
||||
|
||||
// src/use-observable-state.ts
|
||||
function useObservableState(state$OrInit, initialState) {
|
||||
return useObservableStateInternal(
|
||||
useSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
|
||||
// src/use-layout-observable-state.ts
|
||||
function useLayoutObservableState(state$OrInit, initialState) {
|
||||
return useObservableStateInternal(
|
||||
useLayoutSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
function useObservableEagerState(state$) {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const state$Ref = react.useRef(state$);
|
||||
const errorRef = react.useRef();
|
||||
const isAsyncEmissionRef = react.useRef(false);
|
||||
const didSyncEmit = react.useRef(false);
|
||||
const [state, setState] = react.useState(() => {
|
||||
let state2;
|
||||
state$.subscribe({
|
||||
next: (value) => {
|
||||
didSyncEmit.current = true;
|
||||
state2 = value;
|
||||
},
|
||||
error: (error) => {
|
||||
errorRef.current = error;
|
||||
}
|
||||
}).unsubscribe();
|
||||
return state2;
|
||||
});
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
state$Ref.current = state$;
|
||||
});
|
||||
react.useEffect(() => {
|
||||
errorRef.current = null;
|
||||
const input$ = state$Ref.current;
|
||||
let secondInitialValue = state;
|
||||
const subscription = input$.subscribe({
|
||||
next: (value) => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
return;
|
||||
}
|
||||
if (isAsyncEmissionRef.current) {
|
||||
setState(() => value);
|
||||
} else {
|
||||
secondInitialValue = value;
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
return;
|
||||
}
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
}
|
||||
});
|
||||
if (!isAsyncEmissionRef.current) {
|
||||
if (secondInitialValue !== state) {
|
||||
setState(() => secondInitialValue);
|
||||
}
|
||||
}
|
||||
isAsyncEmissionRef.current = true;
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [state$]);
|
||||
if (errorRef.current) {
|
||||
throw errorRef.current;
|
||||
}
|
||||
if (didSyncEmit.current) {
|
||||
react.useDebugValue(state);
|
||||
return state;
|
||||
} else {
|
||||
throw new Error("Observable did not synchronously emit a value.");
|
||||
}
|
||||
}
|
||||
function useObservableGetState(state$, initialState, ...path) {
|
||||
const value = useObservableState(
|
||||
useObservable(
|
||||
() => state$.pipe(operators.map((state) => path.reduce(getValue, state)))
|
||||
),
|
||||
initialState
|
||||
);
|
||||
react.useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
function getValue(obj, key) {
|
||||
return obj[key];
|
||||
}
|
||||
function useObservablePickState(state$, initialState, ...keys) {
|
||||
const value = useObservableState(
|
||||
useObservable(
|
||||
() => state$.pipe(
|
||||
operators.distinctUntilChanged((s1, s2) => keys.every((k) => s1[k] === s2[k])),
|
||||
operators.map(
|
||||
(state) => keys.reduce(
|
||||
// eslint-disable-next-line no-sequences
|
||||
(o, k) => (o[k] = state[k], o),
|
||||
{}
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
initialState
|
||||
);
|
||||
react.useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
function useObservableSuspense(resource) {
|
||||
const resourceValue = resource.read();
|
||||
const forceUpdate = useForceUpdate();
|
||||
const [state, setState] = react.useState(resourceValue);
|
||||
useSubscription(resource.valueRef$$, (valueRef) => {
|
||||
if (valueRef) {
|
||||
setState(valueRef.current);
|
||||
}
|
||||
});
|
||||
useSubscription(resource.shouldUpdate$$, forceUpdate);
|
||||
react.useDebugValue(state);
|
||||
return state;
|
||||
}
|
||||
function useObservableRef(initialValue) {
|
||||
const [value$] = react.useState(() => new rxjs.BehaviorSubject(initialValue));
|
||||
const [ref] = react.useState(() => ({
|
||||
get current() {
|
||||
return value$.value;
|
||||
},
|
||||
set current(value) {
|
||||
value$.next(value);
|
||||
}
|
||||
}));
|
||||
return [ref, value$];
|
||||
}
|
||||
var createHandler = () => {
|
||||
const handler = {};
|
||||
handler.b = new Promise((resolve) => {
|
||||
handler.a = resolve;
|
||||
});
|
||||
return handler;
|
||||
};
|
||||
var ObservableResource = class {
|
||||
/**
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* Only force update when Suspense needs to restart.
|
||||
*/
|
||||
shouldUpdate$$ = new rxjs.Subject();
|
||||
get isDestroyed() {
|
||||
return this._d;
|
||||
}
|
||||
valueRef$$ = new rxjs.BehaviorSubject(void 0);
|
||||
input$;
|
||||
_h = createHandler();
|
||||
_e = null;
|
||||
_b;
|
||||
_d = false;
|
||||
_o;
|
||||
/**
|
||||
* @param input$ An Observable.
|
||||
* @param isSuccess A function that determines if the value emitted from
|
||||
* `input$` is of success state. If false a Suspense is triggered.
|
||||
* Default all true.
|
||||
*/
|
||||
constructor(input$, isSuccess) {
|
||||
this.input$ = input$;
|
||||
this._o = {
|
||||
next: (value) => {
|
||||
this._e = null;
|
||||
if (!isSuccess || isSuccess(value)) {
|
||||
if (this.valueRef$$.value?.current !== value) {
|
||||
this.valueRef$$.next({ current: value });
|
||||
}
|
||||
if (this._h) {
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
} else if (!this._h) {
|
||||
this._h = createHandler();
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this._e = error;
|
||||
if (this._h) {
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
} else {
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
if (this._h) {
|
||||
this._e = new Error("Suspender ended unexpectedly.");
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
this._b = input$.subscribe(this._o);
|
||||
}
|
||||
read() {
|
||||
if (this._e) {
|
||||
throw this._e;
|
||||
}
|
||||
if (this._h) {
|
||||
throw this._h.b;
|
||||
}
|
||||
return this.valueRef$$.value?.current;
|
||||
}
|
||||
reload(newInput$) {
|
||||
if (this._d) {
|
||||
throw new Error("Cannot reload a destroyed Observable Resource");
|
||||
}
|
||||
if (newInput$) {
|
||||
this.input$ = newInput$;
|
||||
}
|
||||
this._b.unsubscribe();
|
||||
this._e = null;
|
||||
if (this._h) {
|
||||
this._h.a();
|
||||
this._h = createHandler();
|
||||
}
|
||||
this._b = this.input$.subscribe(this._o);
|
||||
}
|
||||
destroy() {
|
||||
this._d = true;
|
||||
this._b.unsubscribe();
|
||||
this.shouldUpdate$$.complete();
|
||||
if (this._h) {
|
||||
this._e = new Error("Resource has been destroyed.");
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.ObservableResource = ObservableResource;
|
||||
exports.identity = identity;
|
||||
exports.pluckCurrentTargetChecked = pluckCurrentTargetChecked;
|
||||
exports.pluckCurrentTargetValue = pluckCurrentTargetValue;
|
||||
exports.pluckFirst = pluckFirst;
|
||||
exports.useForceUpdate = useForceUpdate;
|
||||
exports.useLayoutObservable = useLayoutObservable;
|
||||
exports.useLayoutObservableState = useLayoutObservableState;
|
||||
exports.useLayoutSubscription = useLayoutSubscription;
|
||||
exports.useObservable = useObservable;
|
||||
exports.useObservableCallback = useObservableCallback;
|
||||
exports.useObservableEagerState = useObservableEagerState;
|
||||
exports.useObservableGetState = useObservableGetState;
|
||||
exports.useObservablePickState = useObservablePickState;
|
||||
exports.useObservableRef = useObservableRef;
|
||||
exports.useObservableState = useObservableState;
|
||||
exports.useObservableSuspense = useObservableSuspense;
|
||||
exports.useRefFn = useRefFn;
|
||||
exports.useRenderThrow = useRenderThrow;
|
||||
exports.useSubscription = useSubscription;
|
||||
422
node_modules/observable-hooks/dist/index.mjs
generated
vendored
Normal file
422
node_modules/observable-hooks/dist/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,422 @@
|
||||
import { BehaviorSubject, Subject, NEVER, isObservable } from 'rxjs';
|
||||
import { useRef, useState, useEffect, useDebugValue, useLayoutEffect } from 'react';
|
||||
import { map, switchMap, catchError, distinctUntilChanged } from 'rxjs/operators';
|
||||
|
||||
// src/internal/use-observable-internal.ts
|
||||
function useObservableInternal(useCustomEffect, init, inputs) {
|
||||
if (!inputs) {
|
||||
return useState(init)[0];
|
||||
}
|
||||
const [inputs$] = useState(() => new BehaviorSubject(inputs));
|
||||
const [source$] = useState(() => init(inputs$));
|
||||
const firstEffectRef = useRef(true);
|
||||
useCustomEffect(() => {
|
||||
if (firstEffectRef.current) {
|
||||
firstEffectRef.current = false;
|
||||
return;
|
||||
}
|
||||
inputs$.next(inputs);
|
||||
}, inputs);
|
||||
return source$;
|
||||
}
|
||||
function useObservable(init, inputs) {
|
||||
return useObservableInternal(useEffect, init, inputs);
|
||||
}
|
||||
var identity = (value) => value;
|
||||
var pluckFirst = (inputs$) => map((input) => input[0])(inputs$);
|
||||
var pluckCurrentTargetValue = (event$) => map(
|
||||
(event) => event.currentTarget.value
|
||||
)(event$);
|
||||
var pluckCurrentTargetChecked = (event$) => map(
|
||||
(event) => event.currentTarget.checked
|
||||
)(event$);
|
||||
var getEmptySubject = () => new Subject();
|
||||
var useRefFn = (init) => {
|
||||
const firstRef = useRef(true);
|
||||
const ref = useRef(null);
|
||||
if (firstRef.current) {
|
||||
firstRef.current = false;
|
||||
ref.current = init();
|
||||
}
|
||||
return ref;
|
||||
};
|
||||
var increment = (n) => n + 1 | 0;
|
||||
var useForceUpdate = () => {
|
||||
const updateState = useState(0)[1];
|
||||
return useRef(() => updateState(increment)).current;
|
||||
};
|
||||
var useIsomorphicLayoutEffect = /* @__PURE__ */ (() => (
|
||||
/* istanbul ignore next */
|
||||
typeof window === "undefined" ? useEffect : useLayoutEffect
|
||||
))();
|
||||
|
||||
// src/use-layout-observable.ts
|
||||
function useLayoutObservable(init, inputs) {
|
||||
return useObservableInternal(useIsomorphicLayoutEffect, init, inputs);
|
||||
}
|
||||
function useObservableCallback(init = identity, selector) {
|
||||
const [events$] = useState(getEmptySubject);
|
||||
const [outputs$] = useState(() => init(events$));
|
||||
const callback = useRef((...args) => {
|
||||
events$.next(selector ? selector(args) : args[0]);
|
||||
}).current;
|
||||
return [callback, outputs$];
|
||||
}
|
||||
var toObserver = (args) => args[1]?.next ? args[1] : {
|
||||
next: args[1],
|
||||
error: args[2],
|
||||
complete: args[3]
|
||||
};
|
||||
function useSubscriptionInternal(useCustomEffect, args) {
|
||||
const argsRef = useRef(args);
|
||||
const observerRef = useRef();
|
||||
const subscriptionRef = useRef();
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
argsRef.current = args;
|
||||
observerRef.current = toObserver(args);
|
||||
});
|
||||
useCustomEffect(() => {
|
||||
const input$ = argsRef.current[0];
|
||||
if (!observerRef.current) {
|
||||
observerRef.current = toObserver(argsRef.current);
|
||||
}
|
||||
const subscription = input$.subscribe({
|
||||
next: (value) => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.next?.(value);
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.error ? observerRef.current.error(error) : console.error(error);
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current.complete?.();
|
||||
}
|
||||
}
|
||||
});
|
||||
subscriptionRef.current = subscription;
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [args[0]]);
|
||||
return subscriptionRef;
|
||||
}
|
||||
|
||||
// src/use-subscription.ts
|
||||
function useSubscription(input$, observerOrNext$, error, complete) {
|
||||
return useSubscriptionInternal(useEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete
|
||||
]);
|
||||
}
|
||||
|
||||
// src/use-layout-subscription.ts
|
||||
function useLayoutSubscription(input$, observerOrNext$, error, complete) {
|
||||
return useSubscriptionInternal(useIsomorphicLayoutEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete
|
||||
]);
|
||||
}
|
||||
function useRenderThrow(input$) {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const errorRef = useRef();
|
||||
const output$ = useObservable(
|
||||
(inputs$) => inputs$.pipe(
|
||||
switchMap(([input$2]) => {
|
||||
errorRef.current = null;
|
||||
return input$2.pipe(
|
||||
catchError((error) => {
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
return NEVER;
|
||||
})
|
||||
);
|
||||
})
|
||||
),
|
||||
[input$]
|
||||
);
|
||||
if (errorRef.current) {
|
||||
throw errorRef.current;
|
||||
}
|
||||
return output$;
|
||||
}
|
||||
function useObservableStateInternal(useSubscription2, state$OrInit, initialState) {
|
||||
if (isObservable(state$OrInit)) {
|
||||
const state$ = state$OrInit;
|
||||
const [state, setState] = useState(() => {
|
||||
if (state$ instanceof BehaviorSubject || state$.value !== void 0) {
|
||||
return state$.value;
|
||||
}
|
||||
if (typeof initialState === "function") {
|
||||
return initialState();
|
||||
}
|
||||
return initialState;
|
||||
});
|
||||
useSubscription2(state$, setState);
|
||||
useDebugValue(state);
|
||||
return state;
|
||||
} else {
|
||||
const init = state$OrInit;
|
||||
const [state, setState] = useState(initialState);
|
||||
const [input$] = useState(getEmptySubject);
|
||||
const [state$] = useState(() => init(input$, state));
|
||||
const callback = useRef((state2) => input$.next(state2)).current;
|
||||
useSubscription2(state$, setState);
|
||||
useDebugValue(state);
|
||||
return [state, callback];
|
||||
}
|
||||
}
|
||||
|
||||
// src/use-observable-state.ts
|
||||
function useObservableState(state$OrInit, initialState) {
|
||||
return useObservableStateInternal(
|
||||
useSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
|
||||
// src/use-layout-observable-state.ts
|
||||
function useLayoutObservableState(state$OrInit, initialState) {
|
||||
return useObservableStateInternal(
|
||||
useLayoutSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
function useObservableEagerState(state$) {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const state$Ref = useRef(state$);
|
||||
const errorRef = useRef();
|
||||
const isAsyncEmissionRef = useRef(false);
|
||||
const didSyncEmit = useRef(false);
|
||||
const [state, setState] = useState(() => {
|
||||
let state2;
|
||||
state$.subscribe({
|
||||
next: (value) => {
|
||||
didSyncEmit.current = true;
|
||||
state2 = value;
|
||||
},
|
||||
error: (error) => {
|
||||
errorRef.current = error;
|
||||
}
|
||||
}).unsubscribe();
|
||||
return state2;
|
||||
});
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
state$Ref.current = state$;
|
||||
});
|
||||
useEffect(() => {
|
||||
errorRef.current = null;
|
||||
const input$ = state$Ref.current;
|
||||
let secondInitialValue = state;
|
||||
const subscription = input$.subscribe({
|
||||
next: (value) => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
return;
|
||||
}
|
||||
if (isAsyncEmissionRef.current) {
|
||||
setState(() => value);
|
||||
} else {
|
||||
secondInitialValue = value;
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
return;
|
||||
}
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
}
|
||||
});
|
||||
if (!isAsyncEmissionRef.current) {
|
||||
if (secondInitialValue !== state) {
|
||||
setState(() => secondInitialValue);
|
||||
}
|
||||
}
|
||||
isAsyncEmissionRef.current = true;
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [state$]);
|
||||
if (errorRef.current) {
|
||||
throw errorRef.current;
|
||||
}
|
||||
if (didSyncEmit.current) {
|
||||
useDebugValue(state);
|
||||
return state;
|
||||
} else {
|
||||
throw new Error("Observable did not synchronously emit a value.");
|
||||
}
|
||||
}
|
||||
function useObservableGetState(state$, initialState, ...path) {
|
||||
const value = useObservableState(
|
||||
useObservable(
|
||||
() => state$.pipe(map((state) => path.reduce(getValue, state)))
|
||||
),
|
||||
initialState
|
||||
);
|
||||
useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
function getValue(obj, key) {
|
||||
return obj[key];
|
||||
}
|
||||
function useObservablePickState(state$, initialState, ...keys) {
|
||||
const value = useObservableState(
|
||||
useObservable(
|
||||
() => state$.pipe(
|
||||
distinctUntilChanged((s1, s2) => keys.every((k) => s1[k] === s2[k])),
|
||||
map(
|
||||
(state) => keys.reduce(
|
||||
// eslint-disable-next-line no-sequences
|
||||
(o, k) => (o[k] = state[k], o),
|
||||
{}
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
initialState
|
||||
);
|
||||
useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
function useObservableSuspense(resource) {
|
||||
const resourceValue = resource.read();
|
||||
const forceUpdate = useForceUpdate();
|
||||
const [state, setState] = useState(resourceValue);
|
||||
useSubscription(resource.valueRef$$, (valueRef) => {
|
||||
if (valueRef) {
|
||||
setState(valueRef.current);
|
||||
}
|
||||
});
|
||||
useSubscription(resource.shouldUpdate$$, forceUpdate);
|
||||
useDebugValue(state);
|
||||
return state;
|
||||
}
|
||||
function useObservableRef(initialValue) {
|
||||
const [value$] = useState(() => new BehaviorSubject(initialValue));
|
||||
const [ref] = useState(() => ({
|
||||
get current() {
|
||||
return value$.value;
|
||||
},
|
||||
set current(value) {
|
||||
value$.next(value);
|
||||
}
|
||||
}));
|
||||
return [ref, value$];
|
||||
}
|
||||
var createHandler = () => {
|
||||
const handler = {};
|
||||
handler.b = new Promise((resolve) => {
|
||||
handler.a = resolve;
|
||||
});
|
||||
return handler;
|
||||
};
|
||||
var ObservableResource = class {
|
||||
/**
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* Only force update when Suspense needs to restart.
|
||||
*/
|
||||
shouldUpdate$$ = new Subject();
|
||||
get isDestroyed() {
|
||||
return this._d;
|
||||
}
|
||||
valueRef$$ = new BehaviorSubject(void 0);
|
||||
input$;
|
||||
_h = createHandler();
|
||||
_e = null;
|
||||
_b;
|
||||
_d = false;
|
||||
_o;
|
||||
/**
|
||||
* @param input$ An Observable.
|
||||
* @param isSuccess A function that determines if the value emitted from
|
||||
* `input$` is of success state. If false a Suspense is triggered.
|
||||
* Default all true.
|
||||
*/
|
||||
constructor(input$, isSuccess) {
|
||||
this.input$ = input$;
|
||||
this._o = {
|
||||
next: (value) => {
|
||||
this._e = null;
|
||||
if (!isSuccess || isSuccess(value)) {
|
||||
if (this.valueRef$$.value?.current !== value) {
|
||||
this.valueRef$$.next({ current: value });
|
||||
}
|
||||
if (this._h) {
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
} else if (!this._h) {
|
||||
this._h = createHandler();
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this._e = error;
|
||||
if (this._h) {
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
} else {
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
if (this._h) {
|
||||
this._e = new Error("Suspender ended unexpectedly.");
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
this._b = input$.subscribe(this._o);
|
||||
}
|
||||
read() {
|
||||
if (this._e) {
|
||||
throw this._e;
|
||||
}
|
||||
if (this._h) {
|
||||
throw this._h.b;
|
||||
}
|
||||
return this.valueRef$$.value?.current;
|
||||
}
|
||||
reload(newInput$) {
|
||||
if (this._d) {
|
||||
throw new Error("Cannot reload a destroyed Observable Resource");
|
||||
}
|
||||
if (newInput$) {
|
||||
this.input$ = newInput$;
|
||||
}
|
||||
this._b.unsubscribe();
|
||||
this._e = null;
|
||||
if (this._h) {
|
||||
this._h.a();
|
||||
this._h = createHandler();
|
||||
}
|
||||
this._b = this.input$.subscribe(this._o);
|
||||
}
|
||||
destroy() {
|
||||
this._d = true;
|
||||
this._b.unsubscribe();
|
||||
this.shouldUpdate$$.complete();
|
||||
if (this._h) {
|
||||
this._e = new Error("Resource has been destroyed.");
|
||||
const { a: resolve } = this._h;
|
||||
this._h = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export { ObservableResource, identity, pluckCurrentTargetChecked, pluckCurrentTargetValue, pluckFirst, useForceUpdate, useLayoutObservable, useLayoutObservableState, useLayoutSubscription, useObservable, useObservableCallback, useObservableEagerState, useObservableGetState, useObservablePickState, useObservableRef, useObservableState, useObservableSuspense, useRefFn, useRenderThrow, useSubscription };
|
||||
80
node_modules/observable-hooks/package.json
generated
vendored
Normal file
80
node_modules/observable-hooks/package.json
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "observable-hooks",
|
||||
"version": "4.2.4",
|
||||
"description": "React hooks for RxJS Observables. Simple, flexible, testable and performant.",
|
||||
"main": "dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/index.d.mts",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types": "dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"src/**/*",
|
||||
"dist/**/*",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:crimx/observable-hooks.git"
|
||||
},
|
||||
"keywords": [
|
||||
"react",
|
||||
"hooks",
|
||||
"observable",
|
||||
"rxjs",
|
||||
"async"
|
||||
],
|
||||
"author": "CRIMX<straybugs@gmail.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"prepublishOnly": "pnpm run build",
|
||||
"build": "tsup",
|
||||
"build:min": "MINIFY=true tsup && node scripts/gzip.mjs",
|
||||
"test": "jest --coverage",
|
||||
"release": "standard-version"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0",
|
||||
"rxjs": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/globals": "^29.5.0",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/react": "^16.9.19",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/react-test-renderer": "^16.8.2",
|
||||
"@types/scheduler": "0.16.1",
|
||||
"@types/use-subscription": "1.0.0",
|
||||
"scheduler": "0.0.0-experimental-33c3af284",
|
||||
"experimental_react": "npm:react@0.0.0-experimental-33c3af284",
|
||||
"experimental_react-dom": "npm:react-dom@0.0.0-experimental-33c3af284",
|
||||
"experimental_react-test-renderer": "npm:react-test-renderer@0.0.0-experimental-33c3af284",
|
||||
"gzip-size": "^7.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"pretty-bytes": "^6.1.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-test-renderer": "^16.13.1",
|
||||
"rxjs": "^7.8.1",
|
||||
"standard-version": "^9.5.0",
|
||||
"ts-jest": "^29.0.5",
|
||||
"tsup": "^7.2.0",
|
||||
"typescript": "^4.9.5",
|
||||
"use-subscription": "1.4.1",
|
||||
"vitest": "^0.31.0",
|
||||
"yoctocolors": "^1.0.0"
|
||||
}
|
||||
}
|
||||
118
node_modules/observable-hooks/src/helpers.ts
generated
vendored
Normal file
118
node_modules/observable-hooks/src/helpers.ts
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Useful utilities
|
||||
*/
|
||||
import {
|
||||
MutableRefObject,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { map } from "rxjs/operators";
|
||||
|
||||
/**
|
||||
* Returns the first argument it receives.
|
||||
*/
|
||||
export const identity = <T>(value: T): T => value;
|
||||
|
||||
/**
|
||||
* Maps an Observable of Arraylike to an Observable
|
||||
* of the first item.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const text$ = useObservable(pluckFirst, [props.text])
|
||||
* ```
|
||||
*
|
||||
* @param inputs$ An Observable of array-like.
|
||||
*
|
||||
*/
|
||||
export const pluckFirst = <TArr extends ArrayLike<any>>(
|
||||
inputs$: Observable<TArr>
|
||||
): Observable<TArr[0]> => map<TArr, 0>(input => input[0])(inputs$);
|
||||
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget value.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, textChange$] = useObservableCallback<
|
||||
* string,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetValue)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export const pluckCurrentTargetValue = <
|
||||
TEvent extends { currentTarget: { value: any } }
|
||||
>(
|
||||
event$: Observable<TEvent>
|
||||
): Observable<TEvent["currentTarget"]["value"]> =>
|
||||
map<TEvent, TEvent["currentTarget"]["value"]>(
|
||||
event => event.currentTarget.value
|
||||
)(event$);
|
||||
|
||||
/**
|
||||
* Maps an Observable of DOM events to an Observable
|
||||
* of the currentTarget checked.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```typescript
|
||||
* const [onChange, checked$] = useObservableCallback<
|
||||
* boolean,
|
||||
* React.FormEvent<HTMLInputElement>
|
||||
* >(pluckCurrentTargetChecked)
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export const pluckCurrentTargetChecked = <
|
||||
TEvent extends { currentTarget: { checked: any } }
|
||||
>(
|
||||
event$: Observable<TEvent>
|
||||
): Observable<TEvent["currentTarget"]["checked"]> =>
|
||||
map<TEvent, TEvent["currentTarget"]["checked"]>(
|
||||
event => event.currentTarget.checked
|
||||
)(event$);
|
||||
|
||||
/**
|
||||
* Return an empty Subject
|
||||
* @ignore
|
||||
*/
|
||||
export const getEmptySubject = <T>() => new Subject<T>();
|
||||
|
||||
/**
|
||||
* One-time ref init.
|
||||
* @param init A function that returns a value. Will be called only once.
|
||||
* @returns A ref object with the returned value.
|
||||
*/
|
||||
export const useRefFn = <T>(init: () => T) => {
|
||||
const firstRef = useRef(true);
|
||||
const ref = useRef<T | null>(null);
|
||||
if (firstRef.current) {
|
||||
firstRef.current = false;
|
||||
ref.current = init();
|
||||
}
|
||||
return ref as MutableRefObject<T>;
|
||||
};
|
||||
|
||||
const increment = (n: number): number => (n + 1) | 0;
|
||||
|
||||
/**
|
||||
* Force re-renders Component.
|
||||
*/
|
||||
export const useForceUpdate = (): (() => void) => {
|
||||
const updateState = useState(0)[1];
|
||||
return useRef(() => updateState(increment)).current;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prevent React warning when using useLayoutEffect on server.
|
||||
*/
|
||||
export const useIsomorphicLayoutEffect = /* @__PURE__ */ (() =>
|
||||
/* istanbul ignore next */
|
||||
typeof window === "undefined" ? useEffect : useLayoutEffect)();
|
||||
22
node_modules/observable-hooks/src/index.ts
generated
vendored
Normal file
22
node_modules/observable-hooks/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
export { useObservable } from "./use-observable";
|
||||
export { useLayoutObservable } from "./use-layout-observable";
|
||||
export { useObservableCallback } from "./use-observable-callback";
|
||||
export { useSubscription } from "./use-subscription";
|
||||
export { useLayoutSubscription } from "./use-layout-subscription";
|
||||
export { useRenderThrow } from "./use-render-throw";
|
||||
export { useObservableState } from "./use-observable-state";
|
||||
export { useLayoutObservableState } from "./use-layout-observable-state";
|
||||
export { useObservableEagerState } from "./use-observable-eager-state";
|
||||
export { useObservableGetState } from "./use-observable-get-state";
|
||||
export { useObservablePickState } from "./use-observable-pick-state";
|
||||
export { useObservableSuspense } from "./use-observable-suspense";
|
||||
export { useObservableRef } from "./use-observable-ref";
|
||||
export { ObservableResource } from "./observable-resource";
|
||||
export {
|
||||
useRefFn,
|
||||
useForceUpdate,
|
||||
identity,
|
||||
pluckFirst,
|
||||
pluckCurrentTargetValue,
|
||||
pluckCurrentTargetChecked,
|
||||
} from "./helpers";
|
||||
42
node_modules/observable-hooks/src/internal/use-observable-internal.ts
generated
vendored
Normal file
42
node_modules/observable-hooks/src/internal/use-observable-internal.ts
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Observable, BehaviorSubject } from "rxjs";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param useCustomEffect useEffect or useLayoutEffect
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
export function useObservableInternal<TOutput, TInputs extends Readonly<any[]>>(
|
||||
useCustomEffect: typeof useEffect,
|
||||
init:
|
||||
| (() => Observable<TOutput>)
|
||||
| ((inputs$: Observable<[...TInputs]>) => Observable<TOutput>),
|
||||
inputs?: [...TInputs]
|
||||
): Observable<TOutput> {
|
||||
// Even though hooks are under conditional block
|
||||
// it is for a completely different use case
|
||||
// which unlikely coexists with the other one.
|
||||
// A warning is also added to the docs.
|
||||
if (!inputs) {
|
||||
return useState(init as () => Observable<TOutput>)[0];
|
||||
}
|
||||
|
||||
const [inputs$] = useState(() => new BehaviorSubject(inputs));
|
||||
const [source$] = useState(() => init(inputs$));
|
||||
|
||||
const firstEffectRef = useRef(true);
|
||||
useCustomEffect(() => {
|
||||
if (firstEffectRef.current) {
|
||||
firstEffectRef.current = false;
|
||||
return;
|
||||
}
|
||||
inputs$.next(inputs);
|
||||
}, inputs);
|
||||
|
||||
return source$;
|
||||
}
|
||||
55
node_modules/observable-hooks/src/internal/use-observable-state-internal.ts
generated
vendored
Normal file
55
node_modules/observable-hooks/src/internal/use-observable-state-internal.ts
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Observable, isObservable, Subject, BehaviorSubject } from "rxjs";
|
||||
import { useState, useRef, useDebugValue } from "react";
|
||||
import type { useSubscription as useSubscriptionType } from "../use-subscription";
|
||||
import { getEmptySubject } from "../helpers";
|
||||
|
||||
export function useObservableStateInternal<TState, TInput = TState>(
|
||||
useSubscription: typeof useSubscriptionType,
|
||||
state$OrInit:
|
||||
| Observable<TState>
|
||||
| ((
|
||||
input$: Observable<TInput>,
|
||||
initialState?: TState
|
||||
) => Observable<TState>),
|
||||
initialState?: TState | (() => TState)
|
||||
): TState | undefined | [TState | undefined, (input: TInput) => void] {
|
||||
// Even though hooks are under conditional block
|
||||
// it is for a completely different use case
|
||||
// which unlikely coexists with the other one.
|
||||
// A warning is also added to the docs.
|
||||
if (isObservable(state$OrInit)) {
|
||||
const state$ = state$OrInit;
|
||||
const [state, setState] = useState<TState | undefined>(() => {
|
||||
if (
|
||||
state$ instanceof BehaviorSubject ||
|
||||
(state$ as BehaviorSubject<TState>).value !== undefined
|
||||
) {
|
||||
return (state$ as BehaviorSubject<TState>).value;
|
||||
}
|
||||
if (typeof initialState === "function") {
|
||||
return (initialState as () => TState)();
|
||||
}
|
||||
return initialState;
|
||||
});
|
||||
|
||||
useSubscription(state$, setState);
|
||||
|
||||
useDebugValue(state);
|
||||
|
||||
return state;
|
||||
} else {
|
||||
const init = state$OrInit;
|
||||
const [state, setState] = useState<TState | undefined>(initialState);
|
||||
|
||||
const [input$] = useState<Subject<TInput>>(getEmptySubject);
|
||||
|
||||
const [state$] = useState(() => init(input$, state));
|
||||
const callback = useRef((state: TInput) => input$.next(state)).current;
|
||||
|
||||
useSubscription(state$, setState);
|
||||
|
||||
useDebugValue(state);
|
||||
|
||||
return [state, callback];
|
||||
}
|
||||
}
|
||||
89
node_modules/observable-hooks/src/internal/use-subscription-internal.ts
generated
vendored
Normal file
89
node_modules/observable-hooks/src/internal/use-subscription-internal.ts
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import { MutableRefObject, useEffect, useRef } from "react";
|
||||
import { Observable, PartialObserver, Subscription } from "rxjs";
|
||||
import { useIsomorphicLayoutEffect } from "../helpers";
|
||||
|
||||
interface Observer<T> {
|
||||
next?: (value: T) => void;
|
||||
error?: (err: any) => void;
|
||||
complete?: () => void;
|
||||
}
|
||||
|
||||
type Args<TInput> = [
|
||||
Observable<TInput>, // inputs$
|
||||
PartialObserver<TInput> | ((value: TInput) => void) | null | undefined,
|
||||
((error: any) => void) | null | undefined,
|
||||
(() => void) | null | undefined
|
||||
];
|
||||
|
||||
const toObserver = <T>(args: Args<T>): Observer<T> =>
|
||||
(args[1] as PartialObserver<T>)?.next
|
||||
? (args[1] as Observer<T>)
|
||||
: {
|
||||
next: args[1] as Observer<T>["next"],
|
||||
error: args[2] as Observer<T>["error"],
|
||||
complete: args[3] as Observer<T>["complete"],
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param useCustomEffect useEffect or useLayoutEffect
|
||||
* @param args collected arguments
|
||||
*/
|
||||
export function useSubscriptionInternal<TInput>(
|
||||
useCustomEffect: typeof useEffect,
|
||||
args: Args<TInput>
|
||||
): MutableRefObject<Subscription | undefined> {
|
||||
const argsRef = useRef(args);
|
||||
const observerRef = useRef<Observer<TInput>>();
|
||||
const subscriptionRef = useRef<Subscription>();
|
||||
|
||||
// Update the latest observable and callbacks
|
||||
// synchronously after render being committed
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
argsRef.current = args;
|
||||
observerRef.current = toObserver(args);
|
||||
});
|
||||
|
||||
useCustomEffect(() => {
|
||||
// keep in closure for checking staleness
|
||||
const input$ = argsRef.current[0];
|
||||
|
||||
/* istanbul ignore if: Just in case the layoutEffect order is agnostic */
|
||||
if (!observerRef.current) {
|
||||
observerRef.current = toObserver(argsRef.current);
|
||||
}
|
||||
|
||||
const subscription = input$.subscribe({
|
||||
next: value => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current!.next?.(value);
|
||||
}
|
||||
// else: stale observable
|
||||
},
|
||||
error: error => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current!.error
|
||||
? observerRef.current!.error(error)
|
||||
: console.error(error);
|
||||
}
|
||||
// else: stale observable
|
||||
},
|
||||
complete: () => {
|
||||
if (input$ === argsRef.current[0]) {
|
||||
observerRef.current!.complete?.();
|
||||
}
|
||||
// else: stale observable
|
||||
},
|
||||
});
|
||||
|
||||
subscriptionRef.current = subscription;
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [args[0]]);
|
||||
|
||||
return subscriptionRef;
|
||||
}
|
||||
156
node_modules/observable-hooks/src/observable-resource.ts
generated
vendored
Normal file
156
node_modules/observable-hooks/src/observable-resource.ts
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
import {
|
||||
BehaviorSubject,
|
||||
Observable,
|
||||
Observer,
|
||||
Subject,
|
||||
Subscription,
|
||||
} from "rxjs";
|
||||
|
||||
interface Handler<T = any> {
|
||||
suspender_: Promise<T>;
|
||||
resolve_: (value?: T) => void;
|
||||
}
|
||||
|
||||
const createHandler = (): Handler => {
|
||||
const handler: Partial<Handler> = {};
|
||||
handler.suspender_ = new Promise(resolve => {
|
||||
handler.resolve_ = resolve;
|
||||
});
|
||||
return handler as Handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewires Observable to Relay-like Suspense resource.
|
||||
*/
|
||||
export class ObservableResource<TInput, TOutput extends TInput = TInput> {
|
||||
/**
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* Only force update when Suspense needs to restart.
|
||||
*/
|
||||
public readonly shouldUpdate$$ = new Subject<true>();
|
||||
|
||||
public get isDestroyed(): boolean {
|
||||
return this._isDestroyed_;
|
||||
}
|
||||
|
||||
public readonly valueRef$$ = new BehaviorSubject<
|
||||
{ current: TOutput } | undefined
|
||||
>(undefined);
|
||||
|
||||
public input$: Observable<TInput>;
|
||||
|
||||
private _handler_: Handler | null = createHandler();
|
||||
|
||||
private _error_: unknown = null;
|
||||
|
||||
private _subscription_: Subscription;
|
||||
|
||||
private _isDestroyed_ = false;
|
||||
|
||||
private readonly _observer_: Observer<TInput>;
|
||||
|
||||
/**
|
||||
* @param input$ An Observable.
|
||||
* @param isSuccess A function that determines if the value emitted from
|
||||
* `input$` is of success state. If false a Suspense is triggered.
|
||||
* Default all true.
|
||||
*/
|
||||
public constructor(
|
||||
input$: Observable<TInput>,
|
||||
isSuccess?: TInput extends TOutput
|
||||
? (value: TInput) => boolean
|
||||
: (value: TInput) => value is TOutput
|
||||
) {
|
||||
this.input$ = input$;
|
||||
|
||||
this._observer_ = {
|
||||
next: (value: TInput): void => {
|
||||
this._error_ = null;
|
||||
if (!isSuccess || isSuccess(value)) {
|
||||
if (this.valueRef$$.value?.current !== value) {
|
||||
this.valueRef$$.next({ current: value as TOutput });
|
||||
}
|
||||
if (this._handler_) {
|
||||
// This will also remove the initial
|
||||
// suspender if sync values are emitted.
|
||||
const { resolve_: resolve } = this._handler_;
|
||||
this._handler_ = null;
|
||||
resolve();
|
||||
}
|
||||
} else if (!this._handler_) {
|
||||
// start a new Suspense
|
||||
this._handler_ = createHandler();
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
error: (error: unknown): void => {
|
||||
this._error_ = error;
|
||||
if (this._handler_) {
|
||||
const { resolve_: resolve } = this._handler_;
|
||||
this._handler_ = null;
|
||||
// Errors thrown from the request is not catch-able by error boundaries.
|
||||
// Here we resolve the suspender and let this.read throw the error.
|
||||
resolve();
|
||||
} else {
|
||||
this.shouldUpdate$$.next(true);
|
||||
}
|
||||
},
|
||||
complete: (): void => {
|
||||
if (this._handler_) {
|
||||
this._error_ = new Error("Suspender ended unexpectedly.");
|
||||
const { resolve_: resolve } = this._handler_;
|
||||
this._handler_ = null;
|
||||
// Errors thrown from the request is not catch-able by error boundaries.
|
||||
// Here we resolve the suspender and let this.read throw the error.
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this._subscription_ = input$.subscribe(this._observer_);
|
||||
}
|
||||
|
||||
public read(): TOutput {
|
||||
if (this._error_) {
|
||||
throw this._error_;
|
||||
}
|
||||
if (this._handler_) {
|
||||
throw this._handler_.suspender_;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
|
||||
return this.valueRef$$.value?.current!;
|
||||
}
|
||||
|
||||
public reload(newInput$?: Observable<TInput>): void {
|
||||
if (this._isDestroyed_) {
|
||||
throw new Error("Cannot reload a destroyed Observable Resource");
|
||||
}
|
||||
|
||||
if (newInput$) {
|
||||
this.input$ = newInput$;
|
||||
}
|
||||
|
||||
this._subscription_.unsubscribe();
|
||||
|
||||
this._error_ = null;
|
||||
|
||||
if (this._handler_) {
|
||||
this._handler_.resolve_();
|
||||
this._handler_ = createHandler();
|
||||
}
|
||||
|
||||
this._subscription_ = this.input$.subscribe(this._observer_);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this._isDestroyed_ = true;
|
||||
this._subscription_.unsubscribe();
|
||||
this.shouldUpdate$$.complete();
|
||||
if (this._handler_) {
|
||||
this._error_ = new Error("Resource has been destroyed.");
|
||||
const { resolve_: resolve } = this._handler_;
|
||||
this._handler_ = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
112
node_modules/observable-hooks/src/use-layout-observable-state.ts
generated
vendored
Normal file
112
node_modules/observable-hooks/src/use-layout-observable-state.ts
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
import { BehaviorSubject, Observable } from "rxjs";
|
||||
import { useLayoutSubscription } from "./use-layout-subscription";
|
||||
import { useObservableStateInternal } from "./internal/use-observable-state-internal";
|
||||
|
||||
/**
|
||||
* Same as [[useObservableState]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useLayoutObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useLayoutObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reduer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
export function useLayoutObservableState<TState>(
|
||||
input$: BehaviorSubject<TState>
|
||||
): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
export function useLayoutObservableState<TState>(
|
||||
input$: Observable<TState>
|
||||
): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
export function useLayoutObservableState<TState>(
|
||||
input$: Observable<TState>,
|
||||
initialState: TState | (() => TState)
|
||||
): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
export function useLayoutObservableState<TState, TInput = TState>(
|
||||
init: (input$: Observable<TInput>) => Observable<TState>
|
||||
): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
export function useLayoutObservableState<TState, TInput = TState>(
|
||||
init: (
|
||||
input$: Observable<TInput>,
|
||||
initialState: TState
|
||||
) => Observable<TState>,
|
||||
initialState: TState | (() => TState)
|
||||
): [TState, (input: TInput) => void];
|
||||
export function useLayoutObservableState<TState, TInput = TState>(
|
||||
state$OrInit:
|
||||
| Observable<TState>
|
||||
| ((
|
||||
input$: Observable<TInput>,
|
||||
initialState?: TState
|
||||
) => Observable<TState>),
|
||||
initialState?: TState | (() => TState)
|
||||
): TState | undefined | [TState | undefined, (input: TInput) => void] {
|
||||
return useObservableStateInternal(
|
||||
useLayoutSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
54
node_modules/observable-hooks/src/use-layout-observable.ts
generated
vendored
Normal file
54
node_modules/observable-hooks/src/use-layout-observable.ts
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Observable } from "rxjs";
|
||||
import { useIsomorphicLayoutEffect } from "./helpers";
|
||||
import { useObservableInternal } from "./internal/use-observable-internal";
|
||||
|
||||
/**
|
||||
* Same as [[useObservable]] excepts using `useLayoutEffect`.
|
||||
*
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useLayoutObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
export function useLayoutObservable<TOutput>(
|
||||
init: () => Observable<TOutput>
|
||||
): Observable<TOutput>;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
export function useLayoutObservable<TOutput, TInputs extends Readonly<any[]>>(
|
||||
init: (inputs$: Observable<[...TInputs]>) => Observable<TOutput>,
|
||||
inputs: [...TInputs]
|
||||
): Observable<TOutput>;
|
||||
export function useLayoutObservable<TOutput, TInputs extends Readonly<any[]>>(
|
||||
init:
|
||||
| (() => Observable<TOutput>)
|
||||
| ((inputs$: Observable<[...TInputs]>) => Observable<TOutput>),
|
||||
inputs?: [...TInputs]
|
||||
): Observable<TOutput> {
|
||||
return useObservableInternal(useIsomorphicLayoutEffect, init, inputs);
|
||||
}
|
||||
55
node_modules/observable-hooks/src/use-layout-subscription.ts
generated
vendored
Normal file
55
node_modules/observable-hooks/src/use-layout-subscription.ts
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { MutableRefObject } from "react";
|
||||
import { Observable, PartialObserver, Subscription } from "rxjs";
|
||||
import { useIsomorphicLayoutEffect } from "./helpers";
|
||||
import { useSubscriptionInternal } from "./internal/use-subscription-internal";
|
||||
|
||||
/**
|
||||
* Same as [[useSubscription]] except the subscription is established
|
||||
* under `useLayoutEffect`.
|
||||
*
|
||||
* Useful when values are needed before DOM paint.
|
||||
*
|
||||
* Use it scarcely as it runs synchronously before browser paint.
|
||||
* Too many synchronous emissions from the observable could
|
||||
* stretch the commit phase.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
export function useLayoutSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
observer?: PartialObserver<TInput>
|
||||
): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
export function useLayoutSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
next?: ((value: TInput) => void) | null | undefined,
|
||||
error?: ((error: any) => void) | null | undefined,
|
||||
complete?: (() => void) | null | undefined
|
||||
): MutableRefObject<Subscription | undefined>;
|
||||
export function useLayoutSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
observerOrNext$?:
|
||||
| PartialObserver<TInput>
|
||||
| ((value: TInput) => void)
|
||||
| null
|
||||
| undefined,
|
||||
error?: ((error: any) => void) | null | undefined,
|
||||
complete?: (() => void) | null | undefined
|
||||
): MutableRefObject<Subscription | undefined> {
|
||||
return useSubscriptionInternal(useIsomorphicLayoutEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete,
|
||||
]);
|
||||
}
|
||||
80
node_modules/observable-hooks/src/use-observable-callback.ts
generated
vendored
Normal file
80
node_modules/observable-hooks/src/use-observable-callback.ts
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { useRef, useState } from "react";
|
||||
import { getEmptySubject, identity } from "./helpers";
|
||||
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* @template TEvent Output value of Observable.
|
||||
*/
|
||||
export function useObservableCallback<TEvent = void>(): [
|
||||
(event: TEvent) => void,
|
||||
Observable<TEvent>
|
||||
];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
export function useObservableCallback<TOutput, TInput = TOutput>(
|
||||
init: (events$: Observable<TInput>) => Observable<TOutput>
|
||||
): [(event: TInput) => void, Observable<TOutput>];
|
||||
/**
|
||||
* Returns a callback function and an events Observable.
|
||||
*
|
||||
* When the callback is called, the Observable will
|
||||
* emit the first argument of the callback.
|
||||
*
|
||||
* (From v2.1.0) Optionally accepts a selector function that transforms
|
||||
* a list of event arguments into a single value.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableCallback` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`. Use ref or [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInput Selected values.
|
||||
* @template TParams A tuple of event callback parameters.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param selector A function that transforms an array of event arguments
|
||||
* into a single value.
|
||||
*/
|
||||
export function useObservableCallback<
|
||||
TOutput = undefined,
|
||||
TInput = TOutput,
|
||||
TParams extends Readonly<any[]> = [TInput]
|
||||
>(
|
||||
init: (events$: Observable<TInput>) => Observable<TOutput>,
|
||||
selector: (args: TParams) => TInput
|
||||
): [(...args: TParams) => void, Observable<TOutput>];
|
||||
export function useObservableCallback<
|
||||
TOutput,
|
||||
TInput = TOutput,
|
||||
TParams extends Readonly<any[]> = [TInput]
|
||||
>(
|
||||
init = identity as (events$: Observable<TInput>) => Observable<TOutput>,
|
||||
selector?: (args: TParams) => TInput
|
||||
): [(...args: TParams) => void, Observable<TOutput>] {
|
||||
const [events$] = useState<Subject<TInput>>(getEmptySubject);
|
||||
const [outputs$] = useState(() => init(events$));
|
||||
const callback = useRef((...args: TParams) => {
|
||||
events$.next(selector ? selector(args) : args[0]);
|
||||
}).current;
|
||||
return [callback, outputs$];
|
||||
}
|
||||
111
node_modules/observable-hooks/src/use-observable-eager-state.ts
generated
vendored
Normal file
111
node_modules/observable-hooks/src/use-observable-eager-state.ts
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
import { useDebugValue, useEffect, useRef, useState } from "react";
|
||||
import { Observable } from "rxjs";
|
||||
import { useForceUpdate, useIsomorphicLayoutEffect } from "./helpers";
|
||||
|
||||
/**
|
||||
* Optimized for safely getting synchronous values from hot or pure observables
|
||||
* without triggering extra initial re-rendering.
|
||||
*
|
||||
* ⚠ If the observable is cold and with side effects
|
||||
* they will be performed at least twice!
|
||||
*
|
||||
* By default this hook will subscribe to the observable at least twice.
|
||||
* The first time is for getting synchronous value to prevent extra initial re-rendering.
|
||||
* In concurrent mode this may happen more than one time.
|
||||
*
|
||||
* @template TState State.
|
||||
*
|
||||
* @param state$ An observable of state value.
|
||||
*/
|
||||
export function useObservableEagerState<TState>(
|
||||
state$: Observable<TState>
|
||||
): TState {
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
const state$Ref = useRef(state$);
|
||||
const errorRef = useRef<Error | null>();
|
||||
const isAsyncEmissionRef = useRef(false);
|
||||
|
||||
const didSyncEmit = useRef(false);
|
||||
|
||||
const [state, setState] = useState<TState>(() => {
|
||||
let state: TState;
|
||||
state$
|
||||
.subscribe({
|
||||
next: value => {
|
||||
didSyncEmit.current = true;
|
||||
state = value;
|
||||
},
|
||||
error: error => {
|
||||
errorRef.current = error;
|
||||
},
|
||||
})
|
||||
.unsubscribe();
|
||||
return state!;
|
||||
});
|
||||
|
||||
// update the latest observable
|
||||
// synchronously after render being committed
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
state$Ref.current = state$;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
errorRef.current = null;
|
||||
|
||||
// keep in closure for checking staleness
|
||||
const input$ = state$Ref.current;
|
||||
|
||||
let secondInitialValue = state;
|
||||
|
||||
const subscription = input$.subscribe({
|
||||
next: value => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
// stale observable
|
||||
return;
|
||||
}
|
||||
if (isAsyncEmissionRef.current) {
|
||||
// ignore synchronous value
|
||||
// prevent initial re-rendering
|
||||
setState(() => value);
|
||||
} else {
|
||||
secondInitialValue = value;
|
||||
}
|
||||
},
|
||||
error: error => {
|
||||
if (input$ !== state$Ref.current) {
|
||||
// stale observable
|
||||
return;
|
||||
}
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
},
|
||||
});
|
||||
|
||||
if (!isAsyncEmissionRef.current) {
|
||||
// fix #86 where sync emission may happen before useEffect
|
||||
if (secondInitialValue !== state) {
|
||||
setState(() => secondInitialValue);
|
||||
}
|
||||
}
|
||||
|
||||
isAsyncEmissionRef.current = true;
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [state$]);
|
||||
|
||||
if (errorRef.current) {
|
||||
// Let error boundary catch the error
|
||||
throw errorRef.current;
|
||||
}
|
||||
|
||||
if (didSyncEmit.current) {
|
||||
useDebugValue(state);
|
||||
|
||||
return state;
|
||||
} else {
|
||||
throw new Error("Observable did not synchronously emit a value.");
|
||||
}
|
||||
}
|
||||
366
node_modules/observable-hooks/src/use-observable-get-state.ts
generated
vendored
Normal file
366
node_modules/observable-hooks/src/use-observable-get-state.ts
generated
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
import { useDebugValue } from "react";
|
||||
import { Observable } from "rxjs";
|
||||
import { map } from "rxjs/operators";
|
||||
import { useObservableState } from "./use-observable-state";
|
||||
import { useObservable } from "./use-observable";
|
||||
|
||||
/**
|
||||
* Gets the value at path of state. Similar to lodash `get`.
|
||||
* Only changes of the resulted value will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
*/
|
||||
export function useObservableGetState<TState>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState | (() => TState)
|
||||
): TState;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void
|
||||
>(state$: Observable<TState>, initialState: TInitial): TState | TInitial;
|
||||
export function useObservableGetState<TState, A extends keyof TState>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A] | (() => TState[A]),
|
||||
pA: A
|
||||
): TState[A];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A
|
||||
): TState[A] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A][B] | (() => TState[A][B]),
|
||||
pA: A,
|
||||
pB: B
|
||||
): TState[A][B];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B
|
||||
): TState[A][B] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A][B][C] | (() => TState[A][B][C]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C
|
||||
): TState[A][B][C];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C
|
||||
): TState[A][B][C] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A][B][C][D] | (() => TState[A][B][C][D]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D
|
||||
): TState[A][B][C][D];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D
|
||||
): TState[A][B][C][D] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A][B][C][D][E] | (() => TState[A][B][C][D][E]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E
|
||||
): TState[A][B][C][D][E];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E
|
||||
): TState[A][B][C][D][E] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TState[A][B][C][D][E][F] | (() => TState[A][B][C][D][E][F]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F
|
||||
): TState[A][B][C][D][E][F];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F
|
||||
): TState[A][B][C][D][E][F] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState:
|
||||
| TState[A][B][C][D][E][F][G]
|
||||
| (() => TState[A][B][C][D][E][F][G]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G
|
||||
): TState[A][B][C][D][E][F][G];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G
|
||||
): TState[A][B][C][D][E][F][G] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F],
|
||||
H extends keyof TState[A][B][C][D][E][F][G]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState:
|
||||
| TState[A][B][C][D][E][F][G][H]
|
||||
| (() => TState[A][B][C][D][E][F][G][H]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G,
|
||||
pH: H
|
||||
): TState[A][B][C][D][E][F][G][H];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F],
|
||||
H extends keyof TState[A][B][C][D][E][F][G]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G,
|
||||
pH: H
|
||||
): TState[A][B][C][D][E][F][G][H] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F],
|
||||
H extends keyof TState[A][B][C][D][E][F][G],
|
||||
I extends keyof TState[A][B][C][D][E][F][G][H]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState:
|
||||
| TState[A][B][C][D][E][F][G][H][I]
|
||||
| (() => TState[A][B][C][D][E][F][G][H][I]),
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G,
|
||||
pH: H,
|
||||
pI: I
|
||||
): TState[A][B][C][D][E][F][G][H][I];
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F],
|
||||
H extends keyof TState[A][B][C][D][E][F][G],
|
||||
I extends keyof TState[A][B][C][D][E][F][G][H]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G,
|
||||
pH: H,
|
||||
pI: I
|
||||
): TState[A][B][C][D][E][F][G][H][I] | TInitial;
|
||||
export function useObservableGetState<
|
||||
TState,
|
||||
TInitial extends null | undefined | void,
|
||||
A extends keyof TState,
|
||||
B extends keyof TState[A],
|
||||
C extends keyof TState[A][B],
|
||||
D extends keyof TState[A][B][C],
|
||||
E extends keyof TState[A][B][C][D],
|
||||
F extends keyof TState[A][B][C][D][E],
|
||||
G extends keyof TState[A][B][C][D][E][F],
|
||||
H extends keyof TState[A][B][C][D][E][F][G],
|
||||
I extends keyof TState[A][B][C][D][E][F][G][H],
|
||||
J extends keyof TState[A][B][C][D][E][F][G][H][I]
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
pA: A,
|
||||
pB: B,
|
||||
pC: C,
|
||||
pD: D,
|
||||
pE: E,
|
||||
pF: F,
|
||||
pG: G,
|
||||
pH: H,
|
||||
pI: I,
|
||||
pJ: J
|
||||
): TState[A][B][C][D][E][F][G][H][I][J] | TInitial;
|
||||
export function useObservableGetState<TState, TInit>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInit | (() => TInit),
|
||||
...path: any[]
|
||||
) {
|
||||
const value = useObservableState(
|
||||
useObservable(() =>
|
||||
state$.pipe(map(state => path.reduce(getValue, state)))
|
||||
),
|
||||
initialState
|
||||
);
|
||||
useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
|
||||
return obj[key];
|
||||
}
|
||||
55
node_modules/observable-hooks/src/use-observable-pick-state.ts
generated
vendored
Normal file
55
node_modules/observable-hooks/src/use-observable-pick-state.ts
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { useDebugValue } from "react";
|
||||
import { Observable } from "rxjs";
|
||||
import { map, distinctUntilChanged } from "rxjs/operators";
|
||||
import { useObservableState } from "./use-observable-state";
|
||||
import { useObservable } from "./use-observable";
|
||||
|
||||
/**
|
||||
* Creates an object composed of the picked state properties. Similar to lodash `pick`.
|
||||
* Changes of any of these properties will trigger a rerendering.
|
||||
* Errors are thrown on unreachable path.
|
||||
*
|
||||
* @param state$ Output state.
|
||||
* @param keys keys of state
|
||||
*/
|
||||
export function useObservablePickState<
|
||||
TState,
|
||||
TKeys extends keyof TState,
|
||||
TInitial extends null | undefined | void
|
||||
>(
|
||||
state$: Observable<TState>,
|
||||
initialState: TInitial,
|
||||
...keys: TKeys[]
|
||||
): { [K in TKeys]: TState[K] } | TInitial;
|
||||
export function useObservablePickState<TState, TKeys extends keyof TState>(
|
||||
state$: Observable<TState>,
|
||||
initialState:
|
||||
| { [K in TKeys]: TState[K] }
|
||||
| (() => { [K in TKeys]: TState[K] }),
|
||||
...keys: TKeys[]
|
||||
): { [K in TKeys]: TState[K] };
|
||||
export function useObservablePickState<TState, TKeys extends keyof TState>(
|
||||
state$: Observable<TState>,
|
||||
initialState:
|
||||
| { [K in TKeys]: TState[K] }
|
||||
| (() => { [K in TKeys]: TState[K] }),
|
||||
...keys: TKeys[]
|
||||
): { [K in TKeys]: TState[K] } {
|
||||
const value = useObservableState(
|
||||
useObservable(() =>
|
||||
state$.pipe(
|
||||
distinctUntilChanged((s1, s2) => keys.every(k => s1[k] === s2[k])),
|
||||
map(state =>
|
||||
keys.reduce(
|
||||
// eslint-disable-next-line no-sequences
|
||||
(o, k) => ((o[k] = state[k]), o),
|
||||
{} as { [K in TKeys]: TState[K] }
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
initialState
|
||||
);
|
||||
useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
48
node_modules/observable-hooks/src/use-observable-ref.ts
generated
vendored
Normal file
48
node_modules/observable-hooks/src/use-observable-ref.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { MutableRefObject, RefObject } from "react";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { useState } from "react";
|
||||
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
export function useObservableRef<TValue>(
|
||||
initialValue: TValue
|
||||
): [MutableRefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue The initial value of the BehaviorSubject.
|
||||
*/
|
||||
export function useObservableRef<TValue>(
|
||||
initialValue: TValue | null
|
||||
): [RefObject<TValue>, BehaviorSubject<TValue>];
|
||||
/**
|
||||
* Returns a mutable ref object and a BehaviorSubject.
|
||||
*
|
||||
* Whenever ref.current is changed, the BehaviorSubject will emit the new value.
|
||||
*
|
||||
* @param initialValue A optional initial value of the BehaviorSubject.
|
||||
*/
|
||||
export function useObservableRef<TValue = undefined>(
|
||||
initialValue?: TValue
|
||||
): [MutableRefObject<TValue | undefined>, BehaviorSubject<TValue | undefined>];
|
||||
export function useObservableRef<TValue>(
|
||||
initialValue?: TValue
|
||||
): [MutableRefObject<TValue | undefined>, BehaviorSubject<TValue | undefined>] {
|
||||
const [value$] = useState(() => new BehaviorSubject(initialValue));
|
||||
const [ref] = useState<MutableRefObject<TValue | undefined>>(() => ({
|
||||
get current(): TValue | undefined {
|
||||
return value$.value;
|
||||
},
|
||||
set current(value: TValue | undefined) {
|
||||
value$.next(value);
|
||||
},
|
||||
}));
|
||||
return [ref, value$];
|
||||
}
|
||||
109
node_modules/observable-hooks/src/use-observable-state.ts
generated
vendored
Normal file
109
node_modules/observable-hooks/src/use-observable-state.ts
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
import { BehaviorSubject, Observable } from "rxjs";
|
||||
import { useSubscription } from "./use-subscription";
|
||||
import { useObservableStateInternal } from "./internal/use-observable-state-internal";
|
||||
|
||||
/**
|
||||
* A sugar hook for getting values from an Observable.
|
||||
*
|
||||
* It can be used in two ways:
|
||||
*
|
||||
* 1. Offer an Observable and an optional initial state.
|
||||
* ```js
|
||||
* const output = useObservableState(input$, initialState)
|
||||
* ```
|
||||
* 2. Offer an epic-like function and an optional initial state.
|
||||
* ```js
|
||||
* const [output, onInput] = useObservableState(
|
||||
* (input$, initialState) => input$.pipe(...),
|
||||
* initialState
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* The optional `initialState` is internally passed to `useState(initialState)`.
|
||||
* This means it can be either a state value or a function that returns the state
|
||||
* which is for expensive initialization.
|
||||
*
|
||||
* The `initialState`(or its returned result) is also passed to the `init` function.
|
||||
* This is useful if you want to implement reducer pattern which requires an initial state.
|
||||
*
|
||||
* ⚠ **Note:** These two ways use different hooks, choose either one each time
|
||||
* and do not change to the other one during Component's life cycle.
|
||||
*
|
||||
* ⚠ **Note:** `useObservableState` will call the epic-like `init` function only once
|
||||
* and always return the same Observable.
|
||||
* It is not safe to access closure directly inside `init`.
|
||||
* Use [[useObservable]] with `withLatestFrom` instead.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ A BehaviorSubject.
|
||||
*/
|
||||
export function useObservableState<TState>(
|
||||
input$: BehaviorSubject<TState>
|
||||
): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
*/
|
||||
export function useObservableState<TState>(
|
||||
input$: Observable<TState>
|
||||
): TState | undefined;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
*
|
||||
* @param input$ An Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
export function useObservableState<TState>(
|
||||
input$: Observable<TState>,
|
||||
initialState: TState | (() => TState)
|
||||
): TState;
|
||||
/**
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
*/
|
||||
export function useObservableState<TState, TInput = TState>(
|
||||
init: (input$: Observable<TInput>) => Observable<TState>
|
||||
): [TState | undefined, (input: TInput) => void];
|
||||
/**
|
||||
* Different input output types with initial state.
|
||||
*
|
||||
* @template TState Output state.
|
||||
* @template TInput Input values.
|
||||
*
|
||||
* @param init A epic-like function that, when applied to an Observable
|
||||
* and the initial state value, returns an Observable.
|
||||
* @param initialState Optional initial state.
|
||||
* Can be the state value or a function that returns the state.
|
||||
*/
|
||||
export function useObservableState<TState, TInput = TState>(
|
||||
init: (
|
||||
input$: Observable<TInput>,
|
||||
initialState: TState
|
||||
) => Observable<TState>,
|
||||
initialState: TState | (() => TState)
|
||||
): [TState, (input: TInput) => void];
|
||||
export function useObservableState<TState, TInput = TState>(
|
||||
state$OrInit:
|
||||
| Observable<TState>
|
||||
| ((
|
||||
input$: Observable<TInput>,
|
||||
initialState?: TState
|
||||
) => Observable<TState>),
|
||||
initialState?: TState | (() => TState)
|
||||
): TState | undefined | [TState | undefined, (input: TInput) => void] {
|
||||
return useObservableStateInternal(
|
||||
useSubscription,
|
||||
state$OrInit,
|
||||
initialState
|
||||
);
|
||||
}
|
||||
33
node_modules/observable-hooks/src/use-observable-suspense.ts
generated
vendored
Normal file
33
node_modules/observable-hooks/src/use-observable-suspense.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useDebugValue, useState } from "react";
|
||||
import { useSubscription } from "./use-subscription";
|
||||
import { useForceUpdate } from "./helpers";
|
||||
import { ObservableResource } from "./observable-resource";
|
||||
|
||||
/**
|
||||
* Consume the Observable resource.
|
||||
*
|
||||
* Unlike Promise, Observable is a multiple push mechanism.
|
||||
* This hook triggers extra re-rendering when Suspense should restart.
|
||||
*
|
||||
* @param resource Observable resource
|
||||
*/
|
||||
export function useObservableSuspense<TInput, TOutput extends TInput = TInput>(
|
||||
resource: ObservableResource<TInput, TOutput>
|
||||
): TOutput {
|
||||
const resourceValue = resource.read();
|
||||
const forceUpdate = useForceUpdate();
|
||||
const [state, setState] = useState<TOutput>(resourceValue);
|
||||
|
||||
useSubscription(resource.valueRef$$, valueRef => {
|
||||
/* Guard code. Value should always be ready when reaching this far. */
|
||||
/* istanbul ignore else */
|
||||
if (valueRef) {
|
||||
setState(valueRef.current);
|
||||
}
|
||||
});
|
||||
|
||||
useSubscription(resource.shouldUpdate$$, forceUpdate);
|
||||
|
||||
useDebugValue(state);
|
||||
return state;
|
||||
}
|
||||
57
node_modules/observable-hooks/src/use-observable.ts
generated
vendored
Normal file
57
node_modules/observable-hooks/src/use-observable.ts
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import { Observable } from "rxjs";
|
||||
import { useObservableInternal } from "./internal/use-observable-internal";
|
||||
import { useEffect } from "react";
|
||||
|
||||
/**
|
||||
* Accepts a function that returns an Observable.
|
||||
* Optionally accepts an array of dependencies which
|
||||
* will be turned into Observable and be passed to the
|
||||
* `init` function.
|
||||
*
|
||||
* React functional components are called many times during their lifecycle.
|
||||
* Create or transform Observables in `init` function so that the operations
|
||||
* won't be repeatedly performed.
|
||||
*
|
||||
* ⚠ **Note:** `useObservable` will call `init` once and always return
|
||||
* the same Observable. It is not safe to access closure (except other Observables)
|
||||
* directly inside `init`.
|
||||
* You should use ref or pass them as dependencies through the second argument.
|
||||
*
|
||||
* ⚠ **Note:** Due to rules of hooks you can either offer or omit the
|
||||
* dependencies array but do not change to one another during Component's life cycle.
|
||||
* The length of the dependencies array must also be fixed.
|
||||
*
|
||||
* @template TOutput Output value in Observable
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
*/
|
||||
export function useObservable<
|
||||
TOutput,
|
||||
TObservable extends Observable<TOutput> = Observable<TOutput>
|
||||
>(init: () => TObservable): TObservable;
|
||||
/**
|
||||
* @template TOutput Output value within Observable.
|
||||
* @template TInputs A readonly tuple of all dependencies.
|
||||
*
|
||||
* @param init A pure function that, when applied to an Observable,
|
||||
* returns an Observable.
|
||||
* @param inputs An dependency array with fixed length. When one of the dependencies
|
||||
* changes the Observable in `init` will emit an array of all the dependencies.
|
||||
*/
|
||||
export function useObservable<
|
||||
TOutput,
|
||||
TInputs extends Readonly<any[]>,
|
||||
TObservable extends Observable<TOutput> = Observable<TOutput>
|
||||
>(
|
||||
init: (inputs$: Observable<[...TInputs]>) => TObservable,
|
||||
inputs: [...TInputs]
|
||||
): TObservable;
|
||||
export function useObservable<TOutput, TInputs extends Readonly<any[]>>(
|
||||
init:
|
||||
| (() => Observable<TOutput>)
|
||||
| ((inputs$: Observable<[...TInputs]>) => Observable<TOutput>),
|
||||
inputs?: [...TInputs]
|
||||
): Observable<TOutput> {
|
||||
return useObservableInternal(useEffect, init, inputs);
|
||||
}
|
||||
46
node_modules/observable-hooks/src/use-render-throw.ts
generated
vendored
Normal file
46
node_modules/observable-hooks/src/use-render-throw.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useRef } from "react";
|
||||
import { Observable, NEVER } from "rxjs";
|
||||
import { catchError, switchMap } from "rxjs/operators";
|
||||
import { useForceUpdate } from "./helpers";
|
||||
import { useObservable } from "./use-observable";
|
||||
|
||||
/**
|
||||
* Enhance an Observable by making errors catch-able to ErrorBoundary.
|
||||
*
|
||||
* It catches Observable error and re-throw it as React render error.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @returns Observable with the same input type
|
||||
*/
|
||||
export function useRenderThrow<TInput>(
|
||||
input$: Observable<TInput>
|
||||
): Observable<TInput> {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const errorRef = useRef<Error | null>();
|
||||
|
||||
const output$ = useObservable(
|
||||
inputs$ =>
|
||||
inputs$.pipe(
|
||||
switchMap(([input$]) => {
|
||||
errorRef.current = null;
|
||||
return input$.pipe(
|
||||
catchError(error => {
|
||||
errorRef.current = error;
|
||||
forceUpdate();
|
||||
return NEVER;
|
||||
})
|
||||
);
|
||||
})
|
||||
),
|
||||
[input$]
|
||||
);
|
||||
|
||||
if (errorRef.current) {
|
||||
// Let error boundary catch the error
|
||||
throw errorRef.current;
|
||||
}
|
||||
|
||||
return output$;
|
||||
}
|
||||
73
node_modules/observable-hooks/src/use-subscription.ts
generated
vendored
Normal file
73
node_modules/observable-hooks/src/use-subscription.ts
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Observable, PartialObserver, Subscription } from "rxjs";
|
||||
import { MutableRefObject, useEffect } from "react";
|
||||
import { useSubscriptionInternal } from "./internal/use-subscription-internal";
|
||||
|
||||
/**
|
||||
* Accepts an Observable and optional `next`, `error`, `complete` functions.
|
||||
* These functions must be in correct order.
|
||||
* Use `undefined` or `null` for placeholder.
|
||||
*
|
||||
* Subscription will unsubscribe when unmount, you can also
|
||||
* unsubscribe manually.
|
||||
*
|
||||
* ⚠ **Note:** To make it concurrent mode compatible, the subscription happens
|
||||
* after the render is committed to the screen
|
||||
* which means even the Observable emits synchronous values
|
||||
* they will arrive after the first rendering.
|
||||
*
|
||||
* Note that changes of callbacks will not trigger
|
||||
* an emission. If you need that just create another
|
||||
* Observable of the callback with [[useObservable]].
|
||||
*
|
||||
* (From v2.0) You can access closure directly inside callback like in `useEffect`.
|
||||
* `useSubscription` will ensure the latest callback is called.
|
||||
*
|
||||
* (From v2.3.4) when the Observable changes `useSubscription` will automatically
|
||||
* unsubscribe the old one and resubscribe to the new one.
|
||||
*
|
||||
* ⚠ **Note:** Due to the design of RxJS, once an error occurs in an observable, the observable
|
||||
* is killed.
|
||||
* You should prevent errors from reaching observables or `catchError` in sub-observables.
|
||||
* You can also make the observable as state and replace it on error.
|
||||
* `useSubscription` will automatically switch to the new one.
|
||||
*
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param observer Observer
|
||||
*/
|
||||
export function useSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
observer?: PartialObserver<TInput>
|
||||
): MutableRefObject<Subscription | undefined>;
|
||||
/**
|
||||
* @template TInput Input value within Observable.
|
||||
*
|
||||
* @param input$ Input Observable.
|
||||
* @param next Notify when a new value is emitted.
|
||||
* @param error Notify when a new error is thrown.
|
||||
* @param complete Notify when the Observable is complete.
|
||||
*/
|
||||
export function useSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
next?: ((value: TInput) => void) | null | undefined,
|
||||
error?: ((error: any) => void) | null | undefined,
|
||||
complete?: (() => void) | null | undefined
|
||||
): MutableRefObject<Subscription | undefined>;
|
||||
export function useSubscription<TInput>(
|
||||
input$: Observable<TInput>,
|
||||
observerOrNext$?:
|
||||
| PartialObserver<TInput>
|
||||
| ((value: TInput) => void)
|
||||
| null
|
||||
| undefined,
|
||||
error?: ((error: any) => void) | null | undefined,
|
||||
complete?: (() => void) | null | undefined
|
||||
): MutableRefObject<Subscription | undefined> {
|
||||
return useSubscriptionInternal(useEffect, [
|
||||
input$,
|
||||
observerOrNext$,
|
||||
error,
|
||||
complete,
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user