-
Notifications
You must be signed in to change notification settings - Fork 2
/
event.ts
79 lines (65 loc) · 1.95 KB
/
event.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
type Change<T> = {(current?: T, previous?: T): void};
export type Event<T> = {
register(callback: Change<T>): () => boolean;
fire(caller: (callback: Change<T>) => void): void;
};
export function Event<T>(): Event<T> {
let callbacks: Change<T>[] = [];
let unregister = (callback: Change<T>) => {
var index = callbacks.indexOf(callback);
if (index === -1) {
return false;
}
callbacks.splice(index, 1);
return true;
};
return {
register: callback => {
callbacks.push(callback);
return () => unregister(callback);
},
fire: caller => {
callbacks.forEach(callback => caller(callback));
},
}
}
export type Property<T> = {
(value?: T | { (): T }): T;
register(callback: Change<T>): () => boolean;
};
export function Property<T>(initial: T): Property<T> {
// hide our internal state away in a closure
let { register, fire } = Event<T>();
let hasFired = false;
let current: T = initial;
let setValue = (value: T) => {
// setValue always fires the first time, even without a change in value.
if (current === value && hasFired) {
return current;
}
hasFired = true;
let previous = current;
current = value;
fire(callback => callback(current, previous));
return current;
};
// property is just a function with a single, optional argument
let property = <Property<T>>function(value?: T | { (): T}): T {
if (value === undefined) {
return current;
}
if (typeof value === "function") {
setTimeout(() => {
var val = (<() => T>value)();
setValue(val);
});
}
else {
setValue(<T>value);
}
};
// also allows callbacks to register for change events
property.register = register;
return property;
}