Skip to content

Commit aed9c72

Browse files
committed
feat: introduce AbstractEvent and upgrade to node 20.x
1 parent 1c8f31e commit aed9c72

19 files changed

+781
-104
lines changed

.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"message": "Use `globalThis` instead"
4040
}
4141
],
42+
"prefer-rest-params": 0,
4243
"require-yield": 0,
4344
"eqeqeq": ["error", "smart"],
4445
"spaced-comment": [

README.md

+73
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,79 @@ master:[![pipeline status](https://gitlab.com/MatrixAI/open-source/js-events/bad
55

66
Events for push-flow abstractions.
77

8+
### `AbstractEvent`
9+
10+
```ts
11+
// For when you just want a regular event without `detail`
12+
// Note that the `detail` type is `null`
13+
class Event1 extends AbstractEvent {}
14+
15+
// For when you want a event with `detail`
16+
class Event2 extends AbstractEvent<string> {}
17+
18+
// Allow caller to customise the `detail` type
19+
// Note that the `detail` type is `unknown`
20+
// This would be rare to use, prefer `Event4`
21+
class Event3<T> extends AbstractEvent<T> {}
22+
23+
// Allow caller to customise the `detail` type
24+
// But this is more accurate as not passing anything
25+
// Would mean the `detail` is in fact `null`
26+
class Event4<T = null> extends AbstractEvent<T> {}
27+
28+
// When you need to customise the constructor signature
29+
class Event5 extends AbstractEvent<string> {
30+
constructor(options: CustomEventInit<string>) {
31+
// Make sure you pass `arguments`!
32+
super(Event5.name, options, arguments);
33+
}
34+
}
35+
```
36+
37+
When redispatching an event, you must call `event.clone()`. The same instance cannot be redispatched. When the event is cloned, all constructor parameters are shallow-copied.
38+
39+
### `Evented`
40+
41+
We combine `Evented` with `AbstractEvent` to gain type-safety and convenience of the wildcard any handler.
42+
43+
```ts
44+
class EventCustom extends AbstractEvent {}
45+
46+
interface X extends Evented {}
47+
@Evented()
48+
class X {}
49+
50+
const x = new X();
51+
52+
// Handle specific event, use the `name` property as the key
53+
x.addEventListener(EventCustom.name, (e) => {
54+
console.log(e as EventCustom);
55+
});
56+
57+
// Handle any event
58+
x.addEventListener((e) => {
59+
// This is the wrapped underlying event
60+
console.log((e as EventAny).detail);
61+
})
62+
```
63+
64+
Note that all events pass through the any event handler, it is not a "fall through" handler.
65+
66+
You can use this style to handle relevant events to perform side-effects, as well as propagate upwards irrelevant events.
67+
68+
Note that some side-effects you perform may trigger an infinite loop by causing something to emit the specific event type that you are handling. In these cases you should specialise handling of those events with a `once: true` option, so that they are only handled once.
69+
70+
```ts
71+
x.addEventListener(EventInfinite.name, (e) => {
72+
console.log(e as EventInfinite);
73+
performActionThatMayTriggerEventInfinite();
74+
}, { once: true });
75+
```
76+
77+
This will terminate the infinite loop on the first time it gets handled.
78+
79+
Therefore it is a good idea to always be as specific with your event types as possible.
80+
881
## Installation
982

1083
```sh

docs/assets/highlight.css

+38-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
:root {
2-
--light-hl-0: #795E26;
3-
--dark-hl-0: #DCDCAA;
4-
--light-hl-1: #000000;
5-
--dark-hl-1: #D4D4D4;
6-
--light-hl-2: #A31515;
7-
--dark-hl-2: #CE9178;
8-
--light-hl-3: #0000FF;
9-
--dark-hl-3: #569CD6;
10-
--light-hl-4: #008000;
11-
--dark-hl-4: #6A9955;
2+
--light-hl-0: #008000;
3+
--dark-hl-0: #6A9955;
4+
--light-hl-1: #0000FF;
5+
--dark-hl-1: #569CD6;
6+
--light-hl-2: #000000;
7+
--dark-hl-2: #D4D4D4;
8+
--light-hl-3: #267F99;
9+
--dark-hl-3: #4EC9B0;
10+
--light-hl-4: #001080;
11+
--dark-hl-4: #9CDCFE;
12+
--light-hl-5: #795E26;
13+
--dark-hl-5: #DCDCAA;
14+
--light-hl-6: #0070C1;
15+
--dark-hl-6: #4FC1FF;
16+
--light-hl-7: #AF00DB;
17+
--dark-hl-7: #C586C0;
18+
--light-hl-8: #A31515;
19+
--dark-hl-8: #CE9178;
1220
--light-code-background: #FFFFFF;
1321
--dark-code-background: #1E1E1E;
1422
}
@@ -19,6 +27,10 @@
1927
--hl-2: var(--light-hl-2);
2028
--hl-3: var(--light-hl-3);
2129
--hl-4: var(--light-hl-4);
30+
--hl-5: var(--light-hl-5);
31+
--hl-6: var(--light-hl-6);
32+
--hl-7: var(--light-hl-7);
33+
--hl-8: var(--light-hl-8);
2234
--code-background: var(--light-code-background);
2335
} }
2436

@@ -28,6 +40,10 @@
2840
--hl-2: var(--dark-hl-2);
2941
--hl-3: var(--dark-hl-3);
3042
--hl-4: var(--dark-hl-4);
43+
--hl-5: var(--dark-hl-5);
44+
--hl-6: var(--dark-hl-6);
45+
--hl-7: var(--dark-hl-7);
46+
--hl-8: var(--dark-hl-8);
3147
--code-background: var(--dark-code-background);
3248
} }
3349

@@ -37,6 +53,10 @@
3753
--hl-2: var(--light-hl-2);
3854
--hl-3: var(--light-hl-3);
3955
--hl-4: var(--light-hl-4);
56+
--hl-5: var(--light-hl-5);
57+
--hl-6: var(--light-hl-6);
58+
--hl-7: var(--light-hl-7);
59+
--hl-8: var(--light-hl-8);
4060
--code-background: var(--light-code-background);
4161
}
4262

@@ -46,6 +66,10 @@
4666
--hl-2: var(--dark-hl-2);
4767
--hl-3: var(--dark-hl-3);
4868
--hl-4: var(--dark-hl-4);
69+
--hl-5: var(--dark-hl-5);
70+
--hl-6: var(--dark-hl-6);
71+
--hl-7: var(--dark-hl-7);
72+
--hl-8: var(--dark-hl-8);
4973
--code-background: var(--dark-code-background);
5074
}
5175

@@ -54,4 +78,8 @@
5478
.hl-2 { color: var(--hl-2); }
5579
.hl-3 { color: var(--hl-3); }
5680
.hl-4 { color: var(--hl-4); }
81+
.hl-5 { color: var(--hl-5); }
82+
.hl-6 { color: var(--hl-6); }
83+
.hl-7 { color: var(--hl-7); }
84+
.hl-8 { color: var(--hl-8); }
5785
pre, code { background: var(--code-background); }

docs/assets/search.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)