rask-ui 0.18.2 → 0.19.0
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 +4 -1
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +5 -9
- package/dist/error.d.ts +3 -14
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +14 -15
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/observation.d.ts +1 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +11 -6
- package/dist/useAction.d.ts +18 -0
- package/dist/useAction.d.ts.map +1 -0
- package/dist/useAction.js +43 -0
- package/dist/useAsync.d.ts +26 -20
- package/dist/useAsync.d.ts.map +1 -1
- package/dist/useAsync.js +100 -41
- package/dist/useCatchError.d.ts +5 -0
- package/dist/useCatchError.d.ts.map +1 -0
- package/dist/useCatchError.js +16 -0
- package/dist/useDerived.js +1 -1
- package/dist/useSuspend.d.ts +40 -0
- package/dist/useSuspend.d.ts.map +1 -0
- package/dist/useSuspend.js +48 -0
- package/dist/useSuspendAsync.d.ts +18 -0
- package/dist/useSuspendAsync.d.ts.map +1 -0
- package/dist/useSuspendAsync.js +37 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,7 +48,10 @@ RASK provides a set of reactive hooks for building interactive UIs. These hooks
|
|
|
48
48
|
- **`useState`** - Create reactive state objects
|
|
49
49
|
- **`useEffect`** - Run side effects when dependencies change
|
|
50
50
|
- **`useDerived`** - Derive values from state with automatic caching
|
|
51
|
-
- **`useAsync`** -
|
|
51
|
+
- **`useAsync`** - Fetch async values with automatic observation and cancellation
|
|
52
|
+
- **`useAction`** - Perform async operations with queuing and retry support
|
|
53
|
+
- **`useSuspend`** - Suspend until multiple async values resolve
|
|
54
|
+
- **`useCatchError`** - Catch and handle component errors (hook-based error boundary)
|
|
52
55
|
- **`useRouter`** - Type-safe client-side routing
|
|
53
56
|
- **`createContext`** / **`useContext`** - Share data through the component tree
|
|
54
57
|
- **`useView`** - Compose state and methods into reusable objects
|
package/dist/component.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,QAAQ,WAML;IACH,OAAO,CAAC,aAAa,CAAc;IAEnC,qBAAqB,IAAI,OAAO;IAMhC,kBAAkB,IAAI,IAAI;IAG1B,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAe/C,MAAM;CAOP;AAID,wBAAgB,mBAAmB,2CAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAUf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,QAAQ,WAML;IACH,OAAO,CAAC,aAAa,CAAc;IAEnC,qBAAqB,IAAI,OAAO;IAMhC,kBAAkB,IAAI,IAAI;IAG1B,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAe/C,MAAM;CAOP;AAID,wBAAgB,mBAAmB,2CAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAUf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;CA6CP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
|
package/dist/component.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createComponentVNode, Component, } from "inferno";
|
|
2
2
|
import { getCurrentObserver, Observer, Signal } from "./observation";
|
|
3
3
|
import { syncBatch } from "./batch";
|
|
4
|
-
import {
|
|
4
|
+
import { CatchErrorContext } from "./useCatchError";
|
|
5
5
|
export class RaskStatelessComponent extends Component {
|
|
6
6
|
isNotified = false;
|
|
7
7
|
isReconciling = false;
|
|
@@ -158,10 +158,12 @@ export class RaskStatefulComponent extends Component {
|
|
|
158
158
|
this.isRendering = false;
|
|
159
159
|
}
|
|
160
160
|
catch (error) {
|
|
161
|
-
|
|
161
|
+
const notifyError = this.contexts.get(CatchErrorContext) ||
|
|
162
|
+
this.context.getContext?.(CatchErrorContext);
|
|
163
|
+
if (typeof notifyError !== "function") {
|
|
162
164
|
throw error;
|
|
163
165
|
}
|
|
164
|
-
|
|
166
|
+
notifyError(error);
|
|
165
167
|
}
|
|
166
168
|
finally {
|
|
167
169
|
stopObserving();
|
|
@@ -183,12 +185,6 @@ function createReactiveProps(comp) {
|
|
|
183
185
|
reactiveProps[prop] = value;
|
|
184
186
|
continue;
|
|
185
187
|
}
|
|
186
|
-
// Skip objects/arrays - they're already reactive if they're proxies
|
|
187
|
-
// No need to wrap them in additional signals
|
|
188
|
-
if (typeof value === "object" && value !== null && PROXY_MARKER in value) {
|
|
189
|
-
reactiveProps[prop] = value;
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
188
|
// Only create reactive getters for primitives
|
|
193
189
|
Object.defineProperty(reactiveProps, prop, {
|
|
194
190
|
enumerable: true,
|
package/dist/error.d.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export declare
|
|
3
|
-
children: any;
|
|
4
|
-
error: (error: unknown) => VNode;
|
|
5
|
-
}, {
|
|
1
|
+
export declare const CatchErrorContext: import("./createContext").Context<(error: unknown) => void>;
|
|
2
|
+
export declare function useCatchError(): {
|
|
6
3
|
error: unknown;
|
|
7
|
-
}
|
|
8
|
-
getChildContext(): {
|
|
9
|
-
notifyError: (error: unknown) => void;
|
|
10
|
-
};
|
|
11
|
-
state: {
|
|
12
|
-
error: null;
|
|
13
|
-
};
|
|
14
|
-
render(): any;
|
|
15
|
-
}
|
|
4
|
+
};
|
|
16
5
|
//# sourceMappingURL=error.d.ts.map
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,4CAAyB,OAAO,KAAK,IAAI,CAAG,CAAC;AAE3E,wBAAgB,aAAa;WAQK,OAAO;EAOxC"}
|
package/dist/error.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
state = { error: null };
|
|
11
|
-
render() {
|
|
12
|
-
if (this.state.error) {
|
|
13
|
-
return this.props.error(this.state.error);
|
|
14
|
-
}
|
|
15
|
-
return this.props.children;
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
import { createContext, useInjectContext } from "./createContext";
|
|
3
|
+
import { getCurrentComponent } from "./component";
|
|
4
|
+
export const CatchErrorContext = createContext();
|
|
5
|
+
export function useCatchError() {
|
|
6
|
+
const currentComponent = getCurrentComponent();
|
|
7
|
+
if (!currentComponent || currentComponent.isRendering) {
|
|
8
|
+
throw new Error("Only use the useCatchError hook in setup");
|
|
16
9
|
}
|
|
10
|
+
const inject = useInjectContext(CatchErrorContext);
|
|
11
|
+
const state = useState({
|
|
12
|
+
error: null,
|
|
13
|
+
});
|
|
14
|
+
inject((error) => (state.error = error));
|
|
15
|
+
return state;
|
|
17
16
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ export { useCleanup, useMountEffect, RaskStatefulComponent, RaskStatelessCompone
|
|
|
3
3
|
export { createContext, useContext, useInjectContext } from "./createContext";
|
|
4
4
|
export { useState, assignState } from "./useState";
|
|
5
5
|
export { useAsync, Async } from "./useAsync";
|
|
6
|
-
export {
|
|
6
|
+
export { useAction, Action } from "./useAction";
|
|
7
|
+
export { useSuspend } from "./useSuspend";
|
|
8
|
+
export { useCatchError } from "./useCatchError";
|
|
7
9
|
export { useRef } from "./useRef";
|
|
8
10
|
export { useView } from "./useView";
|
|
9
11
|
export { useEffect } from "./useEffect";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export { useCleanup, useMountEffect, RaskStatefulComponent, RaskStatelessCompone
|
|
|
3
3
|
export { createContext, useContext, useInjectContext } from "./createContext";
|
|
4
4
|
export { useState, assignState } from "./useState";
|
|
5
5
|
export { useAsync } from "./useAsync";
|
|
6
|
-
export {
|
|
6
|
+
export { useAction } from "./useAction";
|
|
7
|
+
export { useSuspend } from "./useSuspend";
|
|
8
|
+
export { useCatchError } from "./useCatchError";
|
|
7
9
|
export { useRef } from "./useRef";
|
|
8
10
|
export { useView } from "./useView";
|
|
9
11
|
export { useEffect } from "./useEffect";
|
package/dist/observation.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export declare class Observer {
|
|
|
77
77
|
private subsHead;
|
|
78
78
|
private subsTail;
|
|
79
79
|
private readonly onNotify;
|
|
80
|
-
constructor(onNotify: () => void);
|
|
80
|
+
constructor(onNotify: () => void, shouldQueue?: boolean);
|
|
81
81
|
/** Called from Signal.notify() */
|
|
82
82
|
_notify(): void;
|
|
83
83
|
/** Subscribe this observer to a signal */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AASH,wBAAgB,kBAAkB,yBAEjC;AAED;;;GAGG;AACH,cAAM,YAAY;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IAGnB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAGzC,cAAc,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC3C,cAAc,EAAE,YAAY,GAAG,IAAI,CAAQ;IAG3C,MAAM,UAAQ;IAGd,cAAc,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM;CAK9D;AAED;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,IAAI,CAA6B;IAGzC,OAAO,CAAC,KAAK,CAAK;IAElB,8DAA8D;IAC9D,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY;IAe5C,wDAAwD;IACxD,YAAY,CAAC,GAAG,EAAE,YAAY;IAe9B;;OAEG;IACH,MAAM;CAgBP;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB,UAAU,UAAS;IAGnB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAA6B;IAG7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;gBAE1B,QAAQ,EAAE,MAAM,IAAI;
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AASH,wBAAgB,kBAAkB,yBAEjC;AAED;;;GAGG;AACH,cAAM,YAAY;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IAGnB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAGzC,cAAc,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC3C,cAAc,EAAE,YAAY,GAAG,IAAI,CAAQ;IAG3C,MAAM,UAAQ;IAGd,cAAc,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM;CAK9D;AAED;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,IAAI,CAA6B;IAGzC,OAAO,CAAC,KAAK,CAAK;IAElB,8DAA8D;IAC9D,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY;IAe5C,wDAAwD;IACxD,YAAY,CAAC,GAAG,EAAE,YAAY;IAe9B;;OAEG;IACH,MAAM;CAgBP;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB,UAAU,UAAS;IAGnB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAA6B;IAG7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;gBAE1B,QAAQ,EAAE,MAAM,IAAI,EAAE,WAAW,UAAO;IAcpD,kCAAkC;IAClC,OAAO;IAMP,0CAA0C;IAC1C,eAAe,CAAC,MAAM,EAAE,MAAM;IAe9B,oDAAoD;IACpD,OAAO,CAAC,YAAY;IAiBpB,kCAAkC;IAClC,OAAO;IAUP,sCAAsC;IACtC,OAAO;CAKR"}
|
package/dist/observation.js
CHANGED
|
@@ -133,14 +133,19 @@ export class Observer {
|
|
|
133
133
|
subsTail = null;
|
|
134
134
|
// Only ONE notify callback closure per observer
|
|
135
135
|
onNotify;
|
|
136
|
-
constructor(onNotify) {
|
|
136
|
+
constructor(onNotify, shouldQueue = true) {
|
|
137
137
|
const onNotifyQueued = onNotify;
|
|
138
138
|
onNotifyQueued.__queued = false;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
if (shouldQueue) {
|
|
140
|
+
this.onNotify = () => {
|
|
141
|
+
if (onNotifyQueued.__queued)
|
|
142
|
+
return;
|
|
143
|
+
queue(onNotify);
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.onNotify = onNotify;
|
|
148
|
+
}
|
|
144
149
|
}
|
|
145
150
|
/** Called from Signal.notify() */
|
|
146
151
|
_notify() {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type QueuedAction<P> = {
|
|
2
|
+
params: P;
|
|
3
|
+
error: Error | null;
|
|
4
|
+
retry(): void;
|
|
5
|
+
cancel(): void;
|
|
6
|
+
};
|
|
7
|
+
export type ActionState<P> = {
|
|
8
|
+
isPending: boolean;
|
|
9
|
+
queue: QueuedAction<P>[];
|
|
10
|
+
};
|
|
11
|
+
export type Action<P = null> = [
|
|
12
|
+
ActionState<P>,
|
|
13
|
+
[
|
|
14
|
+
P
|
|
15
|
+
] extends [null] ? () => void : (params: P) => void
|
|
16
|
+
];
|
|
17
|
+
export declare function useAction<P = null>(fn: [P] extends [null] ? () => Promise<void> : (params: P) => Promise<void>): Action<P>;
|
|
18
|
+
//# sourceMappingURL=useAction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAction.d.ts","sourceRoot":"","sources":["../src/useAction.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,IAAI,IAAI;IAC7B,WAAW,CAAC,CAAC,CAAC;IACd;QAAC,CAAC;KAAC,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI;CACtD,CAAC;AAEF,wBAAgB,SAAS,CAAC,CAAC,GAAG,IAAI,EAChC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1E,MAAM,CAAC,CAAC,CAAC,CAkDX"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
export function useAction(fn) {
|
|
3
|
+
const state = useState({
|
|
4
|
+
isPending: false,
|
|
5
|
+
queue: [],
|
|
6
|
+
});
|
|
7
|
+
const processQueue = () => {
|
|
8
|
+
const next = state.queue[0];
|
|
9
|
+
if (!next) {
|
|
10
|
+
state.isPending = false;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
state.isPending = true;
|
|
14
|
+
fn(next.params)
|
|
15
|
+
.then(() => {
|
|
16
|
+
state.queue.shift();
|
|
17
|
+
processQueue();
|
|
18
|
+
})
|
|
19
|
+
.catch((error) => {
|
|
20
|
+
next.error = error;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
const run = (params) => {
|
|
24
|
+
params = (params || null);
|
|
25
|
+
let actionProxy;
|
|
26
|
+
const index = state.queue.push({
|
|
27
|
+
params,
|
|
28
|
+
error: null,
|
|
29
|
+
retry() {
|
|
30
|
+
processQueue();
|
|
31
|
+
},
|
|
32
|
+
cancel() {
|
|
33
|
+
state.queue.splice(state.queue.indexOf(actionProxy), 1);
|
|
34
|
+
processQueue();
|
|
35
|
+
},
|
|
36
|
+
}) - 1;
|
|
37
|
+
actionProxy = state.queue[index];
|
|
38
|
+
if (index === 0) {
|
|
39
|
+
processQueue();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return [state, run];
|
|
43
|
+
}
|
package/dist/useAsync.d.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
export type AsyncState<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export type AsyncState<T> = {
|
|
2
|
+
error: Error;
|
|
3
|
+
isLoading: true;
|
|
4
|
+
isRefreshing: false;
|
|
5
|
+
value: null;
|
|
6
|
+
} | {
|
|
7
|
+
error: Error;
|
|
8
|
+
isLoading: false;
|
|
9
|
+
isRefreshing: true;
|
|
10
|
+
value: T;
|
|
6
11
|
} | {
|
|
7
|
-
isPending: true;
|
|
8
|
-
value: T | I;
|
|
9
|
-
params: P;
|
|
10
12
|
error: null;
|
|
13
|
+
isLoading: true;
|
|
14
|
+
isRefreshing: false;
|
|
15
|
+
value: null;
|
|
11
16
|
} | {
|
|
12
|
-
isPending: false;
|
|
13
|
-
params: null;
|
|
14
|
-
value: T;
|
|
15
17
|
error: null;
|
|
18
|
+
isLoading: false;
|
|
19
|
+
isRefreshing: true;
|
|
20
|
+
value: T;
|
|
16
21
|
} | {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
error: null;
|
|
23
|
+
isLoading: false;
|
|
24
|
+
isRefreshing: false;
|
|
25
|
+
value: T;
|
|
21
26
|
};
|
|
22
|
-
export type Async<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export declare function
|
|
27
|
+
export type Async<T extends NonNullable<any>> = [
|
|
28
|
+
AsyncState<T>,
|
|
29
|
+
() => Promise<void>
|
|
30
|
+
];
|
|
31
|
+
export declare function isAsync(value: unknown): boolean;
|
|
32
|
+
export declare function useAsync<T extends NonNullable<any>>(fn: (signal?: AbortSignal) => Promise<T>): Async<T>;
|
|
27
33
|
//# sourceMappingURL=useAsync.d.ts.map
|
package/dist/useAsync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEN,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,IAAI;IAC9C,UAAU,CAAC,CAAC,CAAC;IACb,MAAM,OAAO,CAAC,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,WAWrC;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,EACjD,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GA0InC,KAAK,CAAC,CAAC,CAAC,CACd"}
|
package/dist/useAsync.js
CHANGED
|
@@ -1,72 +1,131 @@
|
|
|
1
|
+
import { syncBatch } from "./batch";
|
|
1
2
|
import { useCleanup, getCurrentComponent } from "./component";
|
|
3
|
+
import { Observer } from "./observation";
|
|
2
4
|
import { assignState, useState } from "./useState";
|
|
3
|
-
export function
|
|
5
|
+
export function isAsync(value) {
|
|
6
|
+
if (value === null || typeof value !== "object") {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return Boolean("isLoading" in value &&
|
|
10
|
+
"isRefreshing" in value &&
|
|
11
|
+
"error" in value &&
|
|
12
|
+
"value" in value);
|
|
13
|
+
}
|
|
14
|
+
export function useAsync(fn) {
|
|
4
15
|
const currentComponent = getCurrentComponent();
|
|
5
16
|
if (!currentComponent || currentComponent.isRendering) {
|
|
6
|
-
throw new Error("Only use
|
|
17
|
+
throw new Error("Only use useAsync in component setup");
|
|
7
18
|
}
|
|
8
|
-
const value = args.length === 2 ? args[0] : null;
|
|
9
|
-
const fn = args.length === 2 ? args[1] : args[0];
|
|
10
19
|
const state = useState({
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
isLoading: true,
|
|
21
|
+
isRefreshing: false,
|
|
22
|
+
value: null,
|
|
13
23
|
error: null,
|
|
14
|
-
params: null,
|
|
15
24
|
});
|
|
25
|
+
const refreshResolvers = [];
|
|
16
26
|
let currentAbortController;
|
|
17
|
-
const
|
|
27
|
+
const refresh = () => {
|
|
18
28
|
currentAbortController?.abort();
|
|
19
29
|
const abortController = (currentAbortController = new AbortController());
|
|
20
|
-
const
|
|
30
|
+
const stopObserving = observer.observe();
|
|
31
|
+
const promise = fn(abortController.signal);
|
|
32
|
+
stopObserving();
|
|
21
33
|
promise
|
|
22
34
|
.then((result) => {
|
|
23
35
|
if (abortController.signal.aborted) {
|
|
24
36
|
return;
|
|
25
37
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
syncBatch(() => {
|
|
39
|
+
assignState(state, {
|
|
40
|
+
isLoading: false,
|
|
41
|
+
isRefreshing: false,
|
|
42
|
+
value: result,
|
|
43
|
+
error: null,
|
|
44
|
+
});
|
|
31
45
|
});
|
|
46
|
+
refreshResolvers.forEach((resolver) => resolver.resolve());
|
|
47
|
+
refreshResolvers.length = 0;
|
|
32
48
|
})
|
|
33
49
|
.catch((error) => {
|
|
34
50
|
if (abortController.signal.aborted) {
|
|
35
51
|
return;
|
|
36
52
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
syncBatch(() => {
|
|
54
|
+
assignState(state, {
|
|
55
|
+
isLoading: state.isLoading,
|
|
56
|
+
isRefreshing: state.isRefreshing,
|
|
57
|
+
value: state.value,
|
|
58
|
+
error,
|
|
59
|
+
});
|
|
42
60
|
});
|
|
61
|
+
refreshResolvers.forEach((resolver) => resolver.reject(error));
|
|
62
|
+
refreshResolvers.length = 0;
|
|
43
63
|
});
|
|
44
64
|
return promise;
|
|
45
65
|
};
|
|
46
|
-
|
|
66
|
+
const observer = new Observer(() => {
|
|
67
|
+
syncBatch(() => {
|
|
68
|
+
if (state.isLoading) {
|
|
69
|
+
refresh();
|
|
70
|
+
}
|
|
71
|
+
else if (state.error && state.value === null) {
|
|
72
|
+
assignState(state, {
|
|
73
|
+
isLoading: true,
|
|
74
|
+
isRefreshing: false,
|
|
75
|
+
value: state.value,
|
|
76
|
+
error: null,
|
|
77
|
+
});
|
|
78
|
+
refresh();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
assignState(state, {
|
|
82
|
+
isLoading: false,
|
|
83
|
+
isRefreshing: true,
|
|
84
|
+
value: state.value,
|
|
85
|
+
error: null,
|
|
86
|
+
});
|
|
87
|
+
refresh();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
useCleanup(() => {
|
|
92
|
+
currentAbortController?.abort();
|
|
93
|
+
observer.dispose();
|
|
94
|
+
});
|
|
95
|
+
refresh();
|
|
47
96
|
return [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
state,
|
|
98
|
+
async () => {
|
|
99
|
+
if (state.isLoading && !state.error) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
syncBatch(() => {
|
|
103
|
+
if (state.error && state.value === null) {
|
|
104
|
+
assignState(state, {
|
|
105
|
+
isLoading: true,
|
|
106
|
+
isRefreshing: false,
|
|
107
|
+
value: state.value,
|
|
108
|
+
error: null,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
assignState(state, {
|
|
113
|
+
isLoading: false,
|
|
114
|
+
isRefreshing: true,
|
|
115
|
+
value: state.value,
|
|
116
|
+
error: null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
let resolve;
|
|
121
|
+
let reject;
|
|
122
|
+
const promise = new Promise((res, rej) => {
|
|
123
|
+
resolve = res;
|
|
124
|
+
reject = rej;
|
|
69
125
|
});
|
|
126
|
+
refreshResolvers.push({ resolve, reject });
|
|
127
|
+
refresh();
|
|
128
|
+
return promise;
|
|
70
129
|
},
|
|
71
130
|
];
|
|
72
131
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCatchError.d.ts","sourceRoot":"","sources":["../src/useCatchError.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,4CAAyB,OAAO,KAAK,IAAI,CAAG,CAAC;AAE3E,wBAAgB,aAAa;WAQK,OAAO;EAOxC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
import { createContext, useInjectContext } from "./createContext";
|
|
3
|
+
import { getCurrentComponent } from "./component";
|
|
4
|
+
export const CatchErrorContext = createContext();
|
|
5
|
+
export function useCatchError() {
|
|
6
|
+
const currentComponent = getCurrentComponent();
|
|
7
|
+
if (!currentComponent || currentComponent.isRendering) {
|
|
8
|
+
throw new Error("Only use the useCatchError hook in setup");
|
|
9
|
+
}
|
|
10
|
+
const inject = useInjectContext(CatchErrorContext);
|
|
11
|
+
const state = useState({
|
|
12
|
+
error: null,
|
|
13
|
+
});
|
|
14
|
+
inject((error) => (state.error = error));
|
|
15
|
+
return state;
|
|
16
|
+
}
|
package/dist/useDerived.js
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AsyncState } from "./useAsync";
|
|
2
|
+
type SuspendState<T extends Record<string, () => any>> = {
|
|
3
|
+
error: Error;
|
|
4
|
+
isLoading: true;
|
|
5
|
+
isRefreshing: false;
|
|
6
|
+
values: {
|
|
7
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? ReturnType<T[K]>["value"] : ReturnType<T[K]>;
|
|
8
|
+
};
|
|
9
|
+
} | {
|
|
10
|
+
error: Error;
|
|
11
|
+
isLoading: false;
|
|
12
|
+
isRefreshing: true;
|
|
13
|
+
values: {
|
|
14
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
error: null;
|
|
18
|
+
isLoading: true;
|
|
19
|
+
isRefreshing: false;
|
|
20
|
+
values: {
|
|
21
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? ReturnType<T[K]>["value"] : ReturnType<T[K]>;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
error: null;
|
|
25
|
+
isLoading: false;
|
|
26
|
+
isRefreshing: true;
|
|
27
|
+
values: {
|
|
28
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
error: null;
|
|
32
|
+
isLoading: false;
|
|
33
|
+
isRefreshing: false;
|
|
34
|
+
values: {
|
|
35
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export declare function useSuspend<T extends Record<string, any>>(asyncs: T): SuspendState<T>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=useSuspend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSuspend.d.ts","sourceRoot":"","sources":["../src/useSuspend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AAIjD,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,IACjD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,CAAC;AAEN,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,mBAsDlE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isAsync } from "./useAsync";
|
|
2
|
+
import { useEffect } from "./useEffect";
|
|
3
|
+
import { assignState, useState } from "./useState";
|
|
4
|
+
export function useSuspend(asyncs) {
|
|
5
|
+
const state = useState({
|
|
6
|
+
isLoading: true,
|
|
7
|
+
isRefreshing: false,
|
|
8
|
+
error: null,
|
|
9
|
+
values: Object.keys(asyncs).reduce((aggr, key) => {
|
|
10
|
+
let value = asyncs[key]();
|
|
11
|
+
if (isAsync(value)) {
|
|
12
|
+
value = value.value;
|
|
13
|
+
}
|
|
14
|
+
aggr[key] = value;
|
|
15
|
+
return aggr;
|
|
16
|
+
}, {}),
|
|
17
|
+
});
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let isLoading = false;
|
|
20
|
+
let isRefreshing = false;
|
|
21
|
+
let error;
|
|
22
|
+
const values = {};
|
|
23
|
+
for (const key in asyncs) {
|
|
24
|
+
let value = asyncs[key]();
|
|
25
|
+
if (!isAsync(value)) {
|
|
26
|
+
values[key] = value;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
values[key] = value.value;
|
|
30
|
+
if (value.isLoading) {
|
|
31
|
+
isLoading = true;
|
|
32
|
+
}
|
|
33
|
+
else if (value.isRefreshing) {
|
|
34
|
+
isRefreshing = true;
|
|
35
|
+
}
|
|
36
|
+
if (value.error) {
|
|
37
|
+
error = value.error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
state.isLoading = isLoading;
|
|
41
|
+
state.isRefreshing = isLoading ? false : isRefreshing;
|
|
42
|
+
state.error = error || null;
|
|
43
|
+
if (!state.isLoading && !state.isRefreshing && !error) {
|
|
44
|
+
assignState(state.values, values);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return state;
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AsyncState } from "./useAsync";
|
|
2
|
+
type SuspendAsyncState<T extends Record<string, AsyncState<any>>> = {
|
|
3
|
+
values: {
|
|
4
|
+
[K in keyof T]: T[K]["value"];
|
|
5
|
+
};
|
|
6
|
+
} & ({
|
|
7
|
+
isPending: true;
|
|
8
|
+
error: null;
|
|
9
|
+
} | {
|
|
10
|
+
isPending: false;
|
|
11
|
+
error: string;
|
|
12
|
+
} | {
|
|
13
|
+
isPending: false;
|
|
14
|
+
error: null;
|
|
15
|
+
});
|
|
16
|
+
export declare function useSuspendAsync<T extends Record<string, AsyncState<any>>>(asyncs: T): SuspendAsyncState<T>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=useSuspendAsync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSuspendAsync.d.ts","sourceRoot":"","sources":["../src/useSuspendAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI;IAClE,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;KAC9B,CAAC;CACH,GAAG,CACA;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,IAAI,CAAC;CACb,CACJ,CAAC;AAEF,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EACvE,MAAM,EAAE,CAAC,wBAyCV"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect } from "./useEffect";
|
|
2
|
+
import { useState } from "./useState";
|
|
3
|
+
export function useSuspendAsync(asyncs) {
|
|
4
|
+
const state = useState({
|
|
5
|
+
isPending: false,
|
|
6
|
+
error: null,
|
|
7
|
+
values: Object.keys(asyncs).reduce((aggr, key) => ({ ...aggr, [key]: asyncs[key].value }), {}),
|
|
8
|
+
});
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
let isPending = false;
|
|
11
|
+
let error = "";
|
|
12
|
+
for (const key in asyncs) {
|
|
13
|
+
if (asyncs[key].error) {
|
|
14
|
+
error += asyncs[key].error + "\n";
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (asyncs[key].isPending) {
|
|
18
|
+
isPending = true;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (error) {
|
|
23
|
+
state.isPending = false;
|
|
24
|
+
state.error = error;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (isPending) {
|
|
28
|
+
state.isPending = false;
|
|
29
|
+
state.error = null;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const key in asyncs) {
|
|
33
|
+
state.values[key] = asyncs[key].value;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return state;
|
|
37
|
+
}
|