/
hooks.ts
107 lines (82 loc) · 2.55 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { Event } from "./event";
import { Store } from "./store";
import { ComponentInstance, DependFilter, stackInstances } from "./component";
const getLastInstance = (): ComponentInstance | null => {
return stackInstances[stackInstances.length - 1] ?? null;
};
const getInstance = (): ComponentInstance => {
const instance = getLastInstance();
if (!instance) throw new Error("Hook use outside component");
return instance;
};
interface CalledEventState<Value> {
called: boolean;
payload?: Value;
}
interface UseDepend {
<Value>(
unit: Event<Value> | Store<Value>,
filter?: DependFilter<Value>,
): CalledEventState<Value>;
}
const useDepend: UseDepend = <Value>(
unit: Event<Value> | Store<Value>,
filter?: DependFilter<Value>,
): CalledEventState<Value> => {
const instance = getInstance();
let eventState: { payload?: Value } = {};
let called = false;
if (unit.type === "event") {
instance.depends.set(unit, filter);
eventState = instance.api.getEventState(unit);
called = instance.api.isCalledEvent(unit);
} else {
instance.depends.set(unit.changed, filter);
eventState = instance.api.getEventState(unit.changed);
called = instance.api.isCalledEvent(unit.changed);
}
return "payload" in eventState
? { called, payload: eventState.payload }
: { called };
};
interface UseDispatch {
<Value>(unit: Event<Value> | Store<Value>): (value: Value) => void;
(unit: Event<void> | Store<void>): () => void;
}
const useDispatch: UseDispatch = <Value>(
unit: Event<Value> | Store<Value>,
): ((value?: Value) => void) => {
const instance = getInstance();
return (value) => {
if (unit.type === "event") {
instance.api.callEvent(unit, value);
} else {
instance.api.changeValue(unit, value);
}
};
};
interface UseValue {
<Value>(store: Store<Value>, bindDepend: boolean): Value;
}
const useValue: UseValue = (store, bindDepend = false) => {
const instance = getInstance();
if (bindDepend) useDepend(store);
return instance.api.getValue(store);
};
interface UseTake {
<Value>(store: Store<Value>): () => Value;
}
const useTake: UseTake = (store) => {
const instance = getInstance();
return () => instance.api.getValue(store);
};
interface UsePromise {
<Value>(promise: Promise<Value>): Promise<Value>;
}
const usePromise: UsePromise = (promise) => {
const instance = getInstance();
instance.promises.add(promise);
return promise;
};
export type { UseDepend, UseDispatch, UseValue, UseTake, UsePromise };
export { useDepend, useDispatch, useValue, useTake, usePromise };