@ispb/react-lazy 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # React Lazy
2
+
3
+ `@ispb/react-lazy` provides React hooks and components for rendering values that arrive asynchronously. It supports promises, RxJS observables, and a shared loading/fulfilled/rejected event model.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install @ispb/react-lazy
9
+ ```
10
+
11
+ React 19 is a peer dependency. The observable helpers also use RxJS.
12
+
13
+ ## Promises
14
+
15
+ Use `Asyncified` to load a value and render it when available. The promise factory receives an `AbortController`; pass its signal to work that supports cancellation.
16
+
17
+ ```tsx
18
+ import { useCallback } from "react"
19
+ import { Asyncified } from "@ispb/react-lazy"
20
+
21
+ type User = { name: string }
22
+
23
+ export function UserView() {
24
+ const loadUser = useCallback((controller: AbortController) => fetch("/api/user", { signal: controller.signal }).then(response => {
25
+ if (!response.ok) {
26
+ throw new Error("Could not load user")
27
+ }
28
+ return response.json() as Promise<User>
29
+ }), [])
30
+
31
+ return <Asyncified<User>
32
+ promise={loadUser}
33
+ children={(user, { retry, isReloading }) => <>
34
+ <p>{user.name}{isReloading ? " (refreshing...)" : ""}</p>
35
+ <button onClick={() => retry()}>Reload</button>
36
+ </>}
37
+ overrides={{
38
+ onLoading: () => <p>Loading user...</p>,
39
+ onError: ({ reason }) => <p role="alert">{String(reason)}</p>,
40
+ }}
41
+ />
42
+ }
43
+ ```
44
+
45
+ The promise factory can also be supplied as `() => PromiseLike<T>` if it does not need cancellation. It should be stable between renders (for example, memoize it with `useCallback`); changing the factory starts a new request. An optional `defer: { initial }` renders an initial value immediately and starts loading after mount.
46
+
47
+ For more control, `useAsyncLazy` returns the event plus a `retry()` function:
48
+
49
+ ```tsx
50
+ import { useCallback } from "react"
51
+ import { Lazy, useAsyncLazy } from "@ispb/react-lazy"
52
+
53
+ function UserPanel() {
54
+ const loadUser = useCallback(() => fetch("/api/user").then(response => response.json() as Promise<User>), [])
55
+ const event = useAsyncLazy(loadUser)
56
+
57
+ return <Lazy event={event} overrides={{
58
+ onLoading: () => <p>Loading...</p>,
59
+ onError: ({ reason }) => <p role="alert">{String(reason)}</p>,
60
+ }}>
61
+ {(user, state) => <>
62
+ <p>{user.name}</p>
63
+ <button disabled={state.isLoading} onClick={() => event.retry()}>Retry</button>
64
+ </>}
65
+ </Lazy>
66
+ }
67
+ ```
68
+
69
+ ## RxJS Observables
70
+
71
+ `Observing` subscribes when mounted, renders each emitted value, routes errors through the lazy error handling, and unsubscribes when the observable changes or the component unmounts.
72
+
73
+ ```tsx
74
+ import { Observing } from "@ispb/react-lazy"
75
+ import { interval, map } from "rxjs"
76
+
77
+ const values = interval(1000).pipe(map(count => `Value ${count}`))
78
+
79
+ export function ValueView() {
80
+ return <Observing of={values}
81
+ overrides={{ onLoading: () => <p>Waiting for first value...</p> }}>
82
+ {value => <p>{value}</p>}
83
+ </Observing>
84
+ }
85
+ ```
86
+
87
+ Use `useObservableLazy({ of })` when you need the resulting `LazyEvent<T>` in your own component, or `observing(factory)` to wrap an existing component.
88
+
89
+ ## Lazy Events and Rendering
90
+
91
+ A `LazyEvent<T>` is one of:
92
+
93
+ ```ts
94
+ { status: "loading" }
95
+ { status: "fulfilled", value: T }
96
+ { status: "rejected", reason: unknown }
97
+ ```
98
+
99
+ Pass an event to `<Lazy>`. Its children can be a node or a render function receiving the value and a `LazyState<T>`. On an initial load, `Lazy` renders `null` unless `onLoading` is provided. If a previously settled event starts loading again, the previous content remains visible and is passed to `onReloading` with `reloading: true`. Rejected events are thrown unless `onError` is provided.
100
+
101
+ Lazy options can be set on an individual component using `overrides`, or for a subtree using `LazyContext.Provider`:
102
+
103
+ ```tsx
104
+ import { LazyContext } from "@ispb/react-lazy"
105
+
106
+ <LazyContext.Provider value={{
107
+ onLoading: () => <p>Loading...</p>,
108
+ onError: ({ message }) => <p role="alert">{message ?? "Request failed"}</p>,
109
+ defaultMessage: "Please wait",
110
+ }}>
111
+ {children}
112
+ </LazyContext.Provider>
113
+ ```
114
+
115
+ Available options are `onLoading`, `onReloading`, `onError`, `defaultMessage`, `loadingMessage`, `reloadingMessage`, and `errorMessage`. Per-component overrides take precedence over context options.
116
+
117
+ ## Hooks
118
+
119
+ - `useAsyncLazy` adapts a promise to a lazy event and exposes `retry`.
120
+ - `useObservableLazy` adapts an RxJS observable to a lazy event; `useObservableLazyWrapped` handles an observable that emits lazy events.
121
+ - `useLazyState` derives loading, reloading, fulfilled, and rejected flags from an event.
122
+ - `useLazyMap` maps a fulfilled value; `useLazyChain` maps it to another lazy event; `useLazyFlatten` flattens nested lazy events.
123
+ - `useLazyCombine` combines a record of lazy events into one event.
124
+ - `useLazyAsPromise` and `useLazyAsObservable` adapt a lazy event to a promise or RxJS subject.
125
+ - `isLoading`, `isFulfilled`, and `isRejected` are type guards for lazy events.
126
+
127
+ The package also exports `Asyncified`, `asyncified`, `Observing`, `observing`, `Lazy`, and `lazified` for component-based and higher-order-component integrations.
128
+
129
+ ## License
130
+
131
+ [MIT](https://choosealicense.com/licenses/mit/)
@@ -0,0 +1,44 @@
1
+ import { ReactNode } from "react";
2
+ import { ValueOrFactory } from "value-or-factory";
3
+ import { LazyHOCOptions } from "./hoc.js";
4
+ import { LazyState } from "./state.js";
5
+ import { LazyEvent, LazyOverrides } from "./types.js";
6
+ /**
7
+ * Options for the async hook.
8
+ * @typeParam D The data type.
9
+ */
10
+ export interface AsyncLazyOptions<D> {
11
+ /**
12
+ * A promise or a function that returns a promise. This MUST be memoized - the function will re-run every time a new value is received.
13
+ */
14
+ readonly promise: ValueOrFactory<PromiseLike<D>, [AbortController]>;
15
+ /**
16
+ * Don't execute immediately.
17
+ */
18
+ readonly defer?: AsyncLazyDefer<D> | undefined;
19
+ }
20
+ export interface AsyncLazyDefer<D> {
21
+ /**
22
+ * The initial value to provide.
23
+ */
24
+ readonly initial: D;
25
+ }
26
+ export type AsyncLazyEvent<D> = LazyEvent<D> & {
27
+ readonly retry: Retry;
28
+ };
29
+ export declare function useAsyncLazy<D>(input: AsyncLazyOptions<D> | (() => PromiseLike<D>)): AsyncLazyEvent<D>;
30
+ export type AsyncLazyState<D> = LazyState<D> & {
31
+ readonly retry: Retry;
32
+ };
33
+ export interface AsyncifiedOptions<D, P> extends AsyncLazyOptions<D>, LazyHOCOptions<AsyncLazyState<D>, P> {
34
+ }
35
+ export declare function asyncified<I extends {}, D extends {}, P extends {}>(factory: (props: I) => AsyncifiedOptions<D, P>): (component: import("react").ComponentType<D & P>) => (props: I) => import("react").JSX.Element;
36
+ export type Retry = (suppressReload?: boolean | undefined) => void;
37
+ export interface AsyncifiedProps<D> extends AsyncLazyOptions<D> {
38
+ readonly children: ValueOrFactory<ReactNode, [D, AsyncLazyState<D>]>;
39
+ /**
40
+ * The lazy overrides.
41
+ */
42
+ readonly overrides?: LazyOverrides | undefined;
43
+ }
44
+ export declare const Asyncified: <D>(props: AsyncifiedProps<D>) => import("react").JSX.Element;
package/dist/async.js ADDED
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import { callOrGet } from "value-or-factory";
4
+ import { Lazy } from "./components.js";
5
+ import { lazified } from "./hoc.js";
6
+ import { useIsFirstMount } from "./internal.js";
7
+ export function useAsyncLazy(input) {
8
+ const options = typeof input === "function" ? { promise: input } : input;
9
+ const [event, setEvent] = useState(options.defer === undefined ? { status: "loading" } : { status: "fulfilled", value: options.defer.initial });
10
+ const run = useCallback((controller) => {
11
+ callOrGet(options.promise, controller).then(value => {
12
+ setEvent({
13
+ status: "fulfilled",
14
+ value,
15
+ });
16
+ }, reason => {
17
+ setEvent({
18
+ status: "rejected",
19
+ reason,
20
+ });
21
+ });
22
+ }, [
23
+ options.promise
24
+ ]);
25
+ const retry = useCallback((suppressReload = false) => {
26
+ if (!suppressReload) {
27
+ setEvent({
28
+ status: "loading"
29
+ });
30
+ }
31
+ const controller = new AbortController();
32
+ run(controller);
33
+ return () => {
34
+ controller.abort();
35
+ };
36
+ }, [
37
+ run
38
+ ]);
39
+ const isFirstMount = useIsFirstMount();
40
+ useEffect(() => {
41
+ if (isFirstMount) {
42
+ if (options.defer !== undefined) {
43
+ return;
44
+ }
45
+ }
46
+ else {
47
+ setEvent({
48
+ status: "loading"
49
+ });
50
+ }
51
+ const controller = new AbortController();
52
+ run(controller);
53
+ return () => {
54
+ controller.abort();
55
+ };
56
+ }, [
57
+ run,
58
+ ]);
59
+ return {
60
+ ...event,
61
+ retry
62
+ };
63
+ }
64
+ export function asyncified(factory) {
65
+ return lazified((props) => {
66
+ const options = factory(props);
67
+ const event = useAsyncLazy(options);
68
+ return {
69
+ event,
70
+ passthrough: state => callOrGet(options.passthrough, { ...state, retry: event.retry }),
71
+ overrides: options.overrides,
72
+ };
73
+ });
74
+ }
75
+ export const Asyncified = (props) => {
76
+ const event = useAsyncLazy(props);
77
+ return _jsx(Lazy, { event: event, overrides: props.overrides, children: (value, state) => callOrGet(props.children, value, { ...state, retry: event.retry }) });
78
+ };
79
+ //# sourceMappingURL=async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.js","sourceRoot":"","sources":["../src/async.tsx"],"names":[],"mappings":";AACA,OAAO,EAAa,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACnE,OAAO,EAAkB,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAkB,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAiC/C,MAAM,UAAU,YAAY,CAAI,KAAmD;IAC/E,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IAC7J,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,UAA2B,EAAE,EAAE;QACpD,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAChD,QAAQ,CAAC;gBACL,MAAM,EAAE,WAAW;gBACnB,KAAK;aACR,CAAC,CAAA;QACN,CAAC,EAAE,MAAM,CAAC,EAAE;YACR,QAAQ,CAAC;gBACL,MAAM,EAAE,UAAU;gBAClB,MAAM;aACT,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;IACN,CAAC,EAAE;QACC,OAAO,CAAC,OAAO;KAClB,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,cAAc,GAAG,KAAK,EAAE,EAAE;QACjD,IAAI,CAAC,cAAc,EAAE,CAAC;YAClB,QAAQ,CAAC;gBACL,MAAM,EAAE,SAAS;aACpB,CAAC,CAAA;QACN,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,GAAG,CAAC,UAAU,CAAC,CAAA;QACf,OAAO,GAAG,EAAE;YACR,UAAU,CAAC,KAAK,EAAE,CAAA;QACtB,CAAC,CAAA;IACL,CAAC,EAAE;QACC,GAAG;KACN,CAAC,CAAA;IACF,MAAM,YAAY,GAAG,eAAe,EAAE,CAAA;IACtC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,YAAY,EAAE,CAAC;YACf,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAM;YACV,CAAC;QACL,CAAC;aACI,CAAC;YACF,QAAQ,CAAC;gBACL,MAAM,EAAE,SAAS;aACpB,CAAC,CAAA;QACN,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,GAAG,CAAC,UAAU,CAAC,CAAA;QACf,OAAO,GAAG,EAAE;YACR,UAAU,CAAC,KAAK,EAAE,CAAA;QACtB,CAAC,CAAA;IACL,CAAC,EAAE;QACC,GAAG;KACN,CAAC,CAAA;IACF,OAAO;QACH,GAAG,KAAK;QACR,KAAK;KACR,CAAA;AACL,CAAC;AAOD,MAAM,UAAU,UAAU,CAA2C,OAA8C;IAC/G,OAAO,QAAQ,CAAC,CAAC,KAAQ,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QAC9B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QACnC,OAAO;YACH,KAAK;YACL,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YACtF,SAAS,EAAE,OAAO,CAAC,SAAS;SAC/B,CAAA;IACL,CAAC,CAAC,CAAA;AACN,CAAC;AAeD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAK,KAAyB,EAAE,EAAE;IACxD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACjC,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EACrB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAAI,CAAA;AAC1G,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+ import { LazyState } from "./state.js";
3
+ import { LazyEvent, LazyOverrides } from "./types.js";
4
+ export interface LazyProps<D> {
5
+ readonly event: LazyEvent<D>;
6
+ readonly overrides?: LazyOverrides | undefined;
7
+ readonly children: ReactNode | ((value: D, state: LazyState<D>) => ReactNode);
8
+ }
9
+ export declare function Lazy<D>(props: LazyProps<D>): ReactNode;
@@ -0,0 +1,36 @@
1
+ import { useContext } from "react";
2
+ import { LazyContext } from "./hooks.js";
3
+ import { useLazyState } from "./state.js";
4
+ export function Lazy(props) {
5
+ const context = useContext(LazyContext);
6
+ const options = { ...context, ...props.overrides };
7
+ const state = useLazyState(props.event);
8
+ if (state.isLoading && !state.isSettled) {
9
+ if (options.onLoading === undefined) {
10
+ return null;
11
+ }
12
+ return options.onLoading({
13
+ message: options.loadingMessage ?? options.defaultMessage
14
+ });
15
+ }
16
+ const onReloading = options.onReloading ?? ((props) => props.children);
17
+ return onReloading({
18
+ reloading: state.isLoading,
19
+ message: options.reloadingMessage ?? options.defaultMessage,
20
+ children: (() => {
21
+ if (state.isRejected) {
22
+ if (options.onError === undefined) {
23
+ throw state.reason;
24
+ }
25
+ return options.onError({
26
+ reason: state.reason,
27
+ message: options.errorMessage ?? options.defaultMessage,
28
+ });
29
+ }
30
+ else {
31
+ return typeof props.children === "function" ? props.children(state.value, state) : props.children;
32
+ }
33
+ })()
34
+ });
35
+ }
36
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.tsx"],"names":[],"mappings":"AACA,OAAO,EAAgC,UAAU,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAa,YAAY,EAAE,MAAM,YAAY,CAAA;AAWpD,MAAM,UAAU,IAAI,CAAI,KAAmB;IACvC,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;IAClD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACvC,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,OAAO,IAAI,CAAA;QACf,CAAC;QACD,OAAO,OAAO,CAAC,SAAS,CAAC;YACrB,OAAO,EAAE,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc;SAC5D,CAAC,CAAA;IACN,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,KAAwB,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IACzF,OAAO,WAAW,CAAC;QACf,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,cAAc;QAC3D,QAAQ,EAAE,CAAC,GAAG,EAAE;YACZ,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACnB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBAChC,MAAM,KAAK,CAAC,MAAM,CAAA;gBACtB,CAAC;gBACD,OAAO,OAAO,CAAC,OAAO,CAAC;oBACnB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,OAAO,EAAE,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,cAAc;iBAC1D,CAAC,CAAA;YACN,CAAC;iBACI,CAAC;gBACF,OAAO,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAA;YACrG,CAAC;QACL,CAAC,CAAC,EAAE;KACP,CAAC,CAAA;AACN,CAAC"}
package/dist/hoc.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { ComponentType } from "react";
2
+ import { ValueOrFactory } from "value-or-factory";
3
+ import { LazyState } from "./state.js";
4
+ import { LazyEvent, LazyOverrides } from "./types.js";
5
+ export interface LazyBuilder<D, P> extends LazyHOCOptions<LazyState<D>, P> {
6
+ readonly event: LazyEvent<D>;
7
+ }
8
+ export declare function lazified<I extends {}, D extends {}, P extends {}>(build: (props: I) => LazyBuilder<D, P>): (component: ComponentType<D & P>) => (props: I) => import("react").JSX.Element;
9
+ export interface LazyHOCOptions<S, P> {
10
+ /**
11
+ * Properties to pass through to the component.
12
+ */
13
+ readonly passthrough: ValueOrFactory<P, [S]>;
14
+ /**
15
+ * Overrides for lazy settings.
16
+ */
17
+ readonly overrides?: LazyOverrides | undefined;
18
+ }
package/dist/hoc.js ADDED
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createElement } from "react";
3
+ import { callOrGet } from "value-or-factory";
4
+ import { Lazy } from "./components.js";
5
+ export function lazified(build) {
6
+ return (component) => {
7
+ return (props) => {
8
+ const built = build(props);
9
+ return _jsx(Lazy, { event: built.event, overrides: built.overrides, children: (value, state) => createElement(component, { ...callOrGet(built.passthrough, state), ...value }) });
10
+ };
11
+ };
12
+ }
13
+ //# sourceMappingURL=hoc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hoc.js","sourceRoot":"","sources":["../src/hoc.tsx"],"names":[],"mappings":";AACA,OAAO,EAAiB,aAAa,EAAE,MAAM,OAAO,CAAA;AACpD,OAAO,EAAE,SAAS,EAAkB,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAUtC,MAAM,UAAU,QAAQ,CAA2C,KAAsC;IACrG,OAAO,CAAC,SAA+B,EAAE,EAAE;QACvC,OAAO,CAAC,KAAQ,EAAE,EAAE;YAChB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;YAC1B,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAC3B,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,GAAI,CAAA;QACtH,CAAC,CAAA;IACL,CAAC,CAAA;AACL,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { Observable, Subject } from "rxjs";
2
+ import { ExtractLazy, LazyEvent, LazyFulfilled, LazyLoading, LazyRejected } from "./types.js";
3
+ export declare const LazyContext: import("react").Context<Partial<import("./types.js").LazyOptions>>;
4
+ export declare function isLoading<T>(event: LazyEvent<T>): event is LazyLoading;
5
+ export declare function isFulfilled<T>(event: LazyEvent<T>): event is LazyFulfilled<T>;
6
+ export declare function isRejected<T>(event: LazyEvent<T>): event is LazyRejected;
7
+ export declare function useLazyFlatten<O>(event: LazyEvent<LazyEvent<O>>): LazyEvent<O>;
8
+ export declare function useLazyChain<I, O>(event: LazyEvent<I>, map: (value: I) => LazyEvent<O>): LazyEvent<O>;
9
+ export declare function useLazyMap<I, O>(event: LazyEvent<I>, map: (value: I) => O): LazyLoading | LazyRejected | {
10
+ status: "fulfilled";
11
+ value: O;
12
+ };
13
+ export declare function useObservableAsPromise<T>(observable: Observable<T>): Promise<T>;
14
+ export declare function useLazyAsPromise<T>(event: LazyEvent<T>): Promise<T>;
15
+ export declare function useLazyAsObservable<T>(event: LazyEvent<T>): Subject<T>;
16
+ export declare function useLazyCombine<T extends Record<string, LazyEvent<unknown>>>(lazies: T): LazyEvent<{
17
+ [K in keyof T]: ExtractLazy<T[K]>;
18
+ }>;
package/dist/hooks.js ADDED
@@ -0,0 +1,137 @@
1
+ import pDefer from "p-defer";
2
+ import { createContext, useEffect, useMemo, useState } from "react";
3
+ import { Subject } from "rxjs";
4
+ export const LazyContext = createContext({});
5
+ export function isLoading(event) {
6
+ if (event.status === "loading") {
7
+ return true;
8
+ }
9
+ else {
10
+ return false;
11
+ }
12
+ }
13
+ export function isFulfilled(event) {
14
+ if (event.status === "fulfilled") {
15
+ return true;
16
+ }
17
+ else {
18
+ return false;
19
+ }
20
+ }
21
+ export function isRejected(event) {
22
+ if (event.status === "rejected") {
23
+ return true;
24
+ }
25
+ else {
26
+ return false;
27
+ }
28
+ }
29
+ export function useLazyFlatten(event) {
30
+ return useLazyChain(event, event => event);
31
+ }
32
+ export function useLazyChain(event, map) {
33
+ return useMemo(() => {
34
+ if (event.status === "fulfilled") {
35
+ return map(event.value);
36
+ }
37
+ else {
38
+ return event;
39
+ }
40
+ }, [
41
+ event
42
+ ]);
43
+ }
44
+ export function useLazyMap(event, map) {
45
+ return useMemo(() => {
46
+ if (event.status === "fulfilled") {
47
+ return {
48
+ status: "fulfilled",
49
+ value: map(event.value)
50
+ };
51
+ }
52
+ else {
53
+ return event;
54
+ }
55
+ }, [
56
+ event
57
+ ]);
58
+ }
59
+ export function useObservableAsPromise(observable) {
60
+ const [promise, setPromise] = useState(new Promise(() => void 0));
61
+ useEffect(() => {
62
+ const sub = observable.subscribe({
63
+ next: value => {
64
+ setPromise(Promise.resolve(value));
65
+ },
66
+ error: reason => {
67
+ setPromise(Promise.reject(reason));
68
+ }
69
+ });
70
+ return () => {
71
+ sub.unsubscribe();
72
+ };
73
+ }, [
74
+ promise
75
+ ]);
76
+ return promise;
77
+ }
78
+ export function useLazyAsPromise(event) {
79
+ const [promise, setPromise] = useState(() => pDefer());
80
+ useEffect(() => {
81
+ if (event.status === "fulfilled") {
82
+ promise.resolve(event.value);
83
+ }
84
+ else if (event.status === "rejected") {
85
+ promise.reject(event.reason);
86
+ }
87
+ else {
88
+ setPromise(pDefer());
89
+ }
90
+ }, [
91
+ event
92
+ ]);
93
+ return promise.promise;
94
+ }
95
+ export function useLazyAsObservable(event) {
96
+ const subject = useMemo(() => new Subject(), []);
97
+ useEffect(() => {
98
+ if (event.status === "fulfilled") {
99
+ subject.next(event.value);
100
+ }
101
+ else if (event.status === "rejected") {
102
+ subject.error(event.reason);
103
+ }
104
+ }, [
105
+ event
106
+ ]);
107
+ return subject;
108
+ }
109
+ export function useLazyCombine(lazies) {
110
+ const entries = Object.entries(lazies);
111
+ if (entries.map(entry => entry[1]).some(isLoading)) {
112
+ return {
113
+ status: "loading",
114
+ };
115
+ }
116
+ else {
117
+ const failed = entries.map(entry => entry[1]).filter(isRejected).at(0);
118
+ if (failed !== undefined) {
119
+ return {
120
+ status: "rejected",
121
+ reason: failed
122
+ };
123
+ }
124
+ else {
125
+ return {
126
+ status: "fulfilled",
127
+ value: Object.fromEntries(entries.map(([key, value]) => {
128
+ return [
129
+ key,
130
+ value.status === "fulfilled" ? value.value : undefined,
131
+ ];
132
+ }))
133
+ };
134
+ }
135
+ }
136
+ }
137
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from "./async.js";
2
+ export * from "./components.js";
3
+ export * from "./hoc.js";
4
+ export * from "./hooks.js";
5
+ export * from "./observable.js";
6
+ export * from "./state.js";
7
+ export * from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./async.js";
2
+ export * from "./components.js";
3
+ export * from "./hoc.js";
4
+ export * from "./hooks.js";
5
+ export * from "./observable.js";
6
+ export * from "./state.js";
7
+ export * from "./types.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
@@ -0,0 +1,4 @@
1
+ export declare function useIsFirstMount(): boolean;
2
+ export declare function usePrevious<T>(value: {
3
+ readonly current: T;
4
+ } | undefined): T | undefined;
@@ -0,0 +1,20 @@
1
+ import { useRef } from "react";
2
+ export function useIsFirstMount() {
3
+ const isFirst = useRef(true);
4
+ if (isFirst.current) {
5
+ isFirst.current = false;
6
+ return true;
7
+ }
8
+ return isFirst.current;
9
+ }
10
+ export function usePrevious(value) {
11
+ const previous = useRef(value?.current);
12
+ const first = useIsFirstMount();
13
+ if (!first) {
14
+ if (value !== undefined) {
15
+ previous.current = value.current;
16
+ }
17
+ }
18
+ return previous.current;
19
+ }
20
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAE9B,MAAM,UAAU,eAAe;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAA;QACvB,OAAO,IAAI,CAAA;IACf,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,WAAW,CAAI,KAA0C;IACrE,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IACvC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAA;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;QACpC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from "react";
2
+ import { Observable, ObservedValueOf } from "rxjs";
3
+ import { LazyHOCOptions } from "./hoc.js";
4
+ import { LazyState } from "./state.js";
5
+ import { LazyEvent, LazyOverrides } from "./types.js";
6
+ export type ObservableLazyInput = Observable<any>;
7
+ export type ObservableLazyOutput<X extends ObservableLazyInput> = X extends Observable<any> ? ObservedValueOf<X> : {
8
+ [K in keyof X]: ObservedValueOf<X[K]>;
9
+ };
10
+ export interface ObservableLazyOptions<D> {
11
+ readonly of: Observable<D>;
12
+ }
13
+ export declare function useObservableLazyWrapped<D>(options: ObservableLazyOptions<LazyEvent<D>>): LazyEvent<D>;
14
+ export declare function useObservableLazy<D>(options: ObservableLazyOptions<D>): LazyEvent<D>;
15
+ export interface ObservingOptions<D, P> extends ObservableLazyOptions<D>, LazyHOCOptions<LazyState<D>, P> {
16
+ }
17
+ export declare function observing<I extends {}, D extends {}, P extends {}>(factory: (props: I) => ObservingOptions<D, P>): (component: import("react").ComponentType<D & P>) => (props: I) => import("react").JSX.Element;
18
+ export interface ObservingProps<D> extends ObservableLazyOptions<D> {
19
+ readonly children: (value: D, state: LazyState<D>) => ReactNode;
20
+ readonly overrides?: LazyOverrides | undefined;
21
+ }
22
+ export declare const Observing: <D>(props: ObservingProps<D>) => import("react").JSX.Element;
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Lazy } from "./components.js";
4
+ import { lazified } from "./hoc.js";
5
+ import { useLazyFlatten } from "./hooks.js";
6
+ import { useIsFirstMount } from "./internal.js";
7
+ export function useObservableLazyWrapped(options) {
8
+ return useLazyFlatten(useObservableLazy(options));
9
+ }
10
+ export function useObservableLazy(options) {
11
+ const [event, setEvent] = useState({ status: "loading" });
12
+ const isFirstMount = useIsFirstMount();
13
+ useEffect(() => {
14
+ if (!isFirstMount) {
15
+ setEvent({
16
+ status: "loading"
17
+ });
18
+ }
19
+ const sub = options.of.subscribe({
20
+ next: value => {
21
+ setEvent({
22
+ status: "fulfilled",
23
+ value
24
+ });
25
+ },
26
+ error: reason => {
27
+ setEvent({
28
+ status: "rejected",
29
+ reason
30
+ });
31
+ }
32
+ });
33
+ return () => {
34
+ sub.unsubscribe();
35
+ };
36
+ }, [
37
+ options.of
38
+ ]);
39
+ return event;
40
+ }
41
+ export function observing(factory) {
42
+ return lazified((props) => {
43
+ const options = factory(props);
44
+ const event = useObservableLazy(options);
45
+ return {
46
+ event,
47
+ passthrough: options.passthrough,
48
+ overrides: options.overrides,
49
+ };
50
+ });
51
+ }
52
+ export const Observing = (props) => {
53
+ const event = useObservableLazy(props);
54
+ return _jsx(Lazy, { event: event, overrides: props.overrides, children: props.children });
55
+ };
56
+ //# sourceMappingURL=observable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observable.js","sourceRoot":"","sources":["../src/observable.tsx"],"names":[],"mappings":";AACA,OAAO,EAAa,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAkB,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAa/C,MAAM,UAAU,wBAAwB,CAAI,OAA4C;IACpF,OAAO,cAAc,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAI,OAAiC;IAClE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC,CAAA;IAChF,MAAM,YAAY,GAAG,eAAe,EAAE,CAAA;IACtC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,QAAQ,CAAC;gBACL,MAAM,EAAE,SAAS;aACpB,CAAC,CAAA;QACN,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC;YAC7B,IAAI,EAAE,KAAK,CAAC,EAAE;gBACV,QAAQ,CAAC;oBACL,MAAM,EAAE,WAAW;oBACnB,KAAK;iBACR,CAAC,CAAA;YACN,CAAC;YACD,KAAK,EAAE,MAAM,CAAC,EAAE;gBACZ,QAAQ,CAAC;oBACL,MAAM,EAAE,UAAU;oBAClB,MAAM;iBACT,CAAC,CAAA;YACN,CAAC;SACJ,CAAC,CAAA;QACF,OAAO,GAAG,EAAE;YACR,GAAG,CAAC,WAAW,EAAE,CAAA;QACrB,CAAC,CAAA;IACL,CAAC,EAAE;QACC,OAAO,CAAC,EAAE;KACb,CAAC,CAAA;IACF,OAAO,KAAK,CAAA;AAChB,CAAC;AAKD,MAAM,UAAU,SAAS,CAA2C,OAA6C;IAC7G,OAAO,QAAQ,CAAC,CAAC,KAAQ,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QAC9B,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;QACxC,OAAO;YACH,KAAK;YACL,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;SAC/B,CAAA;IACL,CAAC,CAAC,CAAA;AACN,CAAC;AASD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAK,KAAwB,EAAE,EAAE;IACtD,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;IACtC,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EACrB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAI,CAAA;AACpC,CAAC,CAAA"}