aboutsummaryrefslogtreecommitdiff
path: root/packages/web-util/src/components/utils.ts
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-12-12 10:57:14 -0300
committerSebastian <sebasjm@gmail.com>2022-12-12 10:57:14 -0300
commit880961034c81e85e191c6c4b845d96506bbd4ea7 (patch)
treee4dcf91f4ea8f7f26760098304f6c9db267803b6 /packages/web-util/src/components/utils.ts
parent5fc8f95a5d4ce8dea03b2dbec7eb5c37e7ff3f15 (diff)
downloadwallet-core-880961034c81e85e191c6c4b845d96506bbd4ea7.tar.gz
wallet-core-880961034c81e85e191c6c4b845d96506bbd4ea7.tar.bz2
wallet-core-880961034c81e85e191c6c4b845d96506bbd4ea7.zip
compose, testing and async into web-util
Diffstat (limited to 'packages/web-util/src/components/utils.ts')
-rw-r--r--packages/web-util/src/components/utils.ts36
1 files changed, 36 insertions, 0 deletions
diff --git a/packages/web-util/src/components/utils.ts b/packages/web-util/src/components/utils.ts
new file mode 100644
index 000000000..71824e14f
--- /dev/null
+++ b/packages/web-util/src/components/utils.ts
@@ -0,0 +1,36 @@
+import { createElement, VNode } from "preact";
+
+export type StateFunc<S> = (p: S) => VNode;
+
+export type StateViewMap<StateType extends { status: string }> = {
+ [S in StateType as S["status"]]: StateFunc<S>;
+};
+
+export type RecursiveState<S extends object> = S | (() => RecursiveState<S>);
+
+export function compose<SType extends { status: string }, PType>(
+ hook: (p: PType) => RecursiveState<SType>,
+ viewMap: StateViewMap<SType>,
+): (p: PType) => VNode {
+ function withHook(stateHook: () => RecursiveState<SType>): () => VNode {
+ function ComposedComponent(): VNode {
+ const state = stateHook();
+
+ if (typeof state === "function") {
+ const subComponent = withHook(state);
+ return createElement(subComponent, {});
+ }
+
+ const statusName = state.status as unknown as SType["status"];
+ const viewComponent = viewMap[statusName] as unknown as StateFunc<SType>;
+ return createElement(viewComponent, state);
+ }
+
+ return ComposedComponent;
+ }
+
+ return (p: PType) => {
+ const h = withHook(() => hook(p));
+ return h();
+ };
+}