@xtia/jel 0.8.0 → 0.9.1
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/internal/emitter.d.ts +31 -12
- package/internal/emitter.js +27 -12
- package/internal/types.d.ts +1 -1
- package/package.json +1 -1
package/internal/emitter.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { EmitterLike } from "./types";
|
|
2
2
|
type Handler<T> = (value: T) => void;
|
|
3
|
+
type Period = {
|
|
4
|
+
asMilliseconds: number;
|
|
5
|
+
} | {
|
|
6
|
+
asSeconds: number;
|
|
7
|
+
};
|
|
3
8
|
export type ListenFunc<T> = (handler: Handler<T>) => UnsubscribeFunc;
|
|
4
9
|
export type UnsubscribeFunc = () => void;
|
|
5
10
|
export declare class EventEmitter<T> {
|
|
@@ -24,6 +29,7 @@ export declare class EventEmitter<T> {
|
|
|
24
29
|
* @returns Listenable: emits transformed values
|
|
25
30
|
*/
|
|
26
31
|
map<R>(mapFunc: (value: T) => R): EventEmitter<R>;
|
|
32
|
+
mapAsync<R>(mapFunc: (value: T) => Promise<R>): EventEmitter<R>;
|
|
27
33
|
/**
|
|
28
34
|
* Creates a chainable emitter that selectively forwards emissions along the chain
|
|
29
35
|
* @param check Function that takes an emitted value and returns true if the emission should be forwarded along the chain
|
|
@@ -68,8 +74,20 @@ export declare class EventEmitter<T> {
|
|
|
68
74
|
* @param cb
|
|
69
75
|
*/
|
|
70
76
|
fork(...cb: ((branch: this) => void)[]): this;
|
|
77
|
+
/**
|
|
78
|
+
* Creates a chainable emitter that forwards the parent's last emission after a period of time in which the parent doesn't emit
|
|
79
|
+
* @param ms Delay in milliseconds
|
|
80
|
+
* @returns Debounced emitter
|
|
81
|
+
*/
|
|
71
82
|
debounce(ms: number): EventEmitter<T>;
|
|
83
|
+
debounce(period: Period): EventEmitter<T>;
|
|
84
|
+
/**
|
|
85
|
+
* Creates a chainable emitter that forwards the parent's emissions, with a minimum delay between emissions during which parent emssions are ignored
|
|
86
|
+
* @param ms Delay in milliseconds
|
|
87
|
+
* @returns Throttled emitter
|
|
88
|
+
*/
|
|
72
89
|
throttle(ms: number): EventEmitter<T>;
|
|
90
|
+
throttle(period: Period): EventEmitter<T>;
|
|
73
91
|
batch(ms: number): EventEmitter<T[]>;
|
|
74
92
|
/**
|
|
75
93
|
* Creates a chainable emitter that
|
|
@@ -80,6 +98,7 @@ export declare class EventEmitter<T> {
|
|
|
80
98
|
*/
|
|
81
99
|
once(): EventEmitter<T>;
|
|
82
100
|
delay(ms: number): EventEmitter<T>;
|
|
101
|
+
delay(period: Period): EventEmitter<T>;
|
|
83
102
|
scan<S>(updater: (state: S, value: T) => S, initial: S): EventEmitter<S>;
|
|
84
103
|
buffer(count: number): EventEmitter<T[]>;
|
|
85
104
|
/**
|
|
@@ -121,6 +140,7 @@ export declare class EventEmitter<T> {
|
|
|
121
140
|
*/
|
|
122
141
|
or(...emitters: EmitterLike<T>[]): EventEmitter<T>;
|
|
123
142
|
or<U>(...emitters: EmitterLike<U>[]): EventEmitter<T | U>;
|
|
143
|
+
then<R>(handler: (value: T) => R): Promise<R>;
|
|
124
144
|
memo(): Memo<T | undefined>;
|
|
125
145
|
memo(initial: T): Memo<T>;
|
|
126
146
|
memo<U>(initial: U): Memo<T | U>;
|
|
@@ -160,12 +180,10 @@ export declare function createEventSource<T>(initialHandler?: Handler<T>): {
|
|
|
160
180
|
emit: (value: T) => void;
|
|
161
181
|
emitter: EventEmitter<T>;
|
|
162
182
|
};
|
|
163
|
-
export declare function interval(ms: number
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
export declare function timeout(
|
|
167
|
-
asMilliseconds: number;
|
|
168
|
-
}): EventEmitter<void>;
|
|
183
|
+
export declare function interval(ms: number): EventEmitter<number>;
|
|
184
|
+
export declare function interval(period: Period): EventEmitter<number>;
|
|
185
|
+
export declare function timeout(ms: number): EventEmitter<void>;
|
|
186
|
+
export declare function timeout(period: Period): EventEmitter<void>;
|
|
169
187
|
declare class Memo<T> {
|
|
170
188
|
private _value;
|
|
171
189
|
private unsubscribeFunc;
|
|
@@ -181,15 +199,15 @@ export declare class SubjectEmitter<T> extends EventEmitter<T> {
|
|
|
181
199
|
next(value: T): void;
|
|
182
200
|
}
|
|
183
201
|
type EventSource<T, E extends string> = {
|
|
184
|
-
on: (eventName: E, handler:
|
|
202
|
+
on: (eventName: E, handler: Handler<T>) => UnsubscribeFunc;
|
|
185
203
|
} | {
|
|
186
|
-
on: (eventName: E, handler:
|
|
187
|
-
off: (eventName: E, handler:
|
|
204
|
+
on: (eventName: E, handler: Handler<T>) => void | UnsubscribeFunc;
|
|
205
|
+
off: (eventName: E, handler: Handler<T>) => void;
|
|
188
206
|
} | {
|
|
189
|
-
addEventListener: (eventName: E, handler:
|
|
207
|
+
addEventListener: (eventName: E, handler: Handler<T>) => UnsubscribeFunc;
|
|
190
208
|
} | {
|
|
191
|
-
addEventListener: (eventName: E, handler:
|
|
192
|
-
removeEventListener: (eventName: E, handler:
|
|
209
|
+
addEventListener: (eventName: E, handler: Handler<T>) => void | UnsubscribeFunc;
|
|
210
|
+
removeEventListener: (eventName: E, handler: Handler<T>) => void;
|
|
193
211
|
};
|
|
194
212
|
/**
|
|
195
213
|
* Create an EventEmitter from an event source. Event sources can be RxJS observables, existing EventEmitters, or objects that
|
|
@@ -198,6 +216,7 @@ type EventSource<T, E extends string> = {
|
|
|
198
216
|
*/
|
|
199
217
|
export declare function toEventEmitter<T>(source: EmitterLike<T>): EventEmitter<T>;
|
|
200
218
|
export declare function toEventEmitter<T, E extends string>(source: EventSource<T, E>, eventName: E): EventEmitter<T>;
|
|
219
|
+
export declare function toEventEmitter<T>(subscribe: ListenFunc<T>): EventEmitter<T>;
|
|
201
220
|
type Dictionary<T> = Record<string | symbol, T>;
|
|
202
221
|
type ExtractEmitterValue<T> = T extends EmitterLike<infer U> ? U : never;
|
|
203
222
|
type CombinedRecord<T extends Dictionary<EmitterLike<any>>> = {
|
package/internal/emitter.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { isReactiveSource } from "./util";
|
|
2
|
+
function periodAsMilliseconds(t) {
|
|
3
|
+
if (typeof t == "number")
|
|
4
|
+
return t;
|
|
5
|
+
return "asMilliseconds" in t ? t.asMilliseconds : (t.asSeconds * 1000);
|
|
6
|
+
}
|
|
2
7
|
export class EventEmitter {
|
|
3
8
|
constructor(onListen) {
|
|
4
9
|
this.onListen = onListen;
|
|
@@ -34,6 +39,10 @@ export class EventEmitter {
|
|
|
34
39
|
const listen = this.transform((value, emit) => emit(mapFunc(value)));
|
|
35
40
|
return new EventEmitter(listen);
|
|
36
41
|
}
|
|
42
|
+
mapAsync(mapFunc) {
|
|
43
|
+
const listen = this.transform((value, emit) => mapFunc(value).then(emit));
|
|
44
|
+
return new EventEmitter(listen);
|
|
45
|
+
}
|
|
37
46
|
/**
|
|
38
47
|
* Creates a chainable emitter that selectively forwards emissions along the chain
|
|
39
48
|
* @param check Function that takes an emitted value and returns true if the emission should be forwarded along the chain
|
|
@@ -101,14 +110,14 @@ export class EventEmitter {
|
|
|
101
110
|
cb.forEach(cb => cb(this));
|
|
102
111
|
return this;
|
|
103
112
|
}
|
|
104
|
-
debounce(
|
|
113
|
+
debounce(t) {
|
|
105
114
|
let reset = null;
|
|
106
115
|
const listen = this.transform((value, emit) => {
|
|
107
116
|
reset === null || reset === void 0 ? void 0 : reset();
|
|
108
117
|
const timeout = setTimeout(() => {
|
|
109
118
|
reset = null;
|
|
110
119
|
emit(value);
|
|
111
|
-
},
|
|
120
|
+
}, periodAsMilliseconds(t));
|
|
112
121
|
reset = () => {
|
|
113
122
|
reset = null;
|
|
114
123
|
clearTimeout(timeout);
|
|
@@ -116,11 +125,11 @@ export class EventEmitter {
|
|
|
116
125
|
});
|
|
117
126
|
return new EventEmitter(listen);
|
|
118
127
|
}
|
|
119
|
-
throttle(
|
|
128
|
+
throttle(t) {
|
|
120
129
|
let lastTime = -Infinity;
|
|
121
130
|
const listen = this.transform((value, emit) => {
|
|
122
131
|
const now = performance.now();
|
|
123
|
-
if (now >= lastTime +
|
|
132
|
+
if (now >= lastTime + periodAsMilliseconds(t)) {
|
|
124
133
|
lastTime = now;
|
|
125
134
|
emit(value);
|
|
126
135
|
}
|
|
@@ -171,9 +180,9 @@ export class EventEmitter {
|
|
|
171
180
|
});
|
|
172
181
|
return new EventEmitter(listen);
|
|
173
182
|
}
|
|
174
|
-
delay(
|
|
183
|
+
delay(t) {
|
|
175
184
|
return new EventEmitter(this.transform((value, emit) => {
|
|
176
|
-
setTimeout(() => emit(value),
|
|
185
|
+
setTimeout(() => emit(value), periodAsMilliseconds(t));
|
|
177
186
|
}));
|
|
178
187
|
}
|
|
179
188
|
scan(updater, initial) {
|
|
@@ -245,11 +254,10 @@ export class EventEmitter {
|
|
|
245
254
|
if (completed)
|
|
246
255
|
return;
|
|
247
256
|
parentUnsubscribe = this.apply(emit);
|
|
248
|
-
|
|
257
|
+
notifierUnsub = toEventEmitter(notifier).listen(() => {
|
|
249
258
|
completed = true;
|
|
250
259
|
clear();
|
|
251
|
-
};
|
|
252
|
-
notifierUnsub = toEventEmitter(notifier).listen(handler);
|
|
260
|
+
});
|
|
253
261
|
return clear;
|
|
254
262
|
});
|
|
255
263
|
return new EventEmitter(listen);
|
|
@@ -314,6 +322,11 @@ export class EventEmitter {
|
|
|
314
322
|
return () => unsubs.forEach(unsub => unsub());
|
|
315
323
|
});
|
|
316
324
|
}
|
|
325
|
+
then(handler) {
|
|
326
|
+
return new Promise(resolve => {
|
|
327
|
+
this.once().apply(v => resolve(handler(v)));
|
|
328
|
+
});
|
|
329
|
+
}
|
|
317
330
|
memo(initial) {
|
|
318
331
|
return new Memo(this, initial);
|
|
319
332
|
}
|
|
@@ -380,19 +393,19 @@ function createListenable(sourceListen) {
|
|
|
380
393
|
emit: (value) => handlers.forEach(h => h.fn(value)),
|
|
381
394
|
};
|
|
382
395
|
}
|
|
383
|
-
export function interval(
|
|
396
|
+
export function interval(t) {
|
|
384
397
|
let intervalId = null;
|
|
385
398
|
let idx = 0;
|
|
386
399
|
const { emit, listen } = createListenable(() => {
|
|
387
400
|
intervalId = setInterval(() => {
|
|
388
401
|
emit(idx++);
|
|
389
|
-
},
|
|
402
|
+
}, periodAsMilliseconds(t));
|
|
390
403
|
return () => clearInterval(intervalId);
|
|
391
404
|
});
|
|
392
405
|
return new EventEmitter(listen);
|
|
393
406
|
}
|
|
394
407
|
export function timeout(t) {
|
|
395
|
-
const ms =
|
|
408
|
+
const ms = periodAsMilliseconds(t);
|
|
396
409
|
const targetTime = Date.now() + ms;
|
|
397
410
|
let timeoutId = null;
|
|
398
411
|
const { emit, listen } = createListenable(() => {
|
|
@@ -441,6 +454,8 @@ export class SubjectEmitter extends EventEmitter {
|
|
|
441
454
|
export function toEventEmitter(source, eventName) {
|
|
442
455
|
if (source instanceof EventEmitter)
|
|
443
456
|
return source;
|
|
457
|
+
if (typeof source == "function")
|
|
458
|
+
return new EventEmitter(source);
|
|
444
459
|
if (eventName !== undefined) {
|
|
445
460
|
// addEL()
|
|
446
461
|
if ("addEventListener" in source) {
|
package/internal/types.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ type TagWithName = 'input' | 'textarea' | 'select' | 'form';
|
|
|
35
35
|
type ContentlessElement = HTMLElementTagNameMap[ContentlessTag];
|
|
36
36
|
export type ElementDescriptor<Tag extends HTMLTag> = {
|
|
37
37
|
classes?: ElementClassDescriptor;
|
|
38
|
-
attribs?: Record<string, string | number | boolean>;
|
|
38
|
+
attribs?: Record<string, string | number | boolean | undefined>;
|
|
39
39
|
on?: {
|
|
40
40
|
[E in keyof HTMLElementEventMap]+?: (event: HTMLElementEventMap[E]) => void;
|
|
41
41
|
};
|