@xtia/jel 0.7.2 → 0.8.0
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/index.d.ts +3 -2
- package/index.js +2 -2
- package/internal/emitter.d.ts +19 -4
- package/internal/emitter.js +56 -1
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { DomEntity, ElementClassDescriptor, ElementDescriptor, DOMContent, DomHelper, StyleAccessor, JelEntity } from "./internal/types";
|
|
2
2
|
import { $ } from "./internal/element";
|
|
3
|
+
import { DomEntity } from "./internal/types";
|
|
3
4
|
export { createEntity } from "./internal/util";
|
|
4
|
-
export { createEventSource, interval, timeout, SubjectEmitter, toEventEmitter } from "./internal/emitter";
|
|
5
|
+
export { createEventSource, interval, timeout, SubjectEmitter, toEventEmitter, type EventEmitter, combineEmitters } from "./internal/emitter";
|
|
5
6
|
export { $ };
|
|
6
|
-
export declare const $body:
|
|
7
|
+
export declare const $body: DomEntity<HTMLElement>;
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $ } from "./internal/element";
|
|
2
2
|
export { createEntity } from "./internal/util";
|
|
3
|
-
export { createEventSource, interval, timeout, SubjectEmitter, toEventEmitter } from "./internal/emitter";
|
|
3
|
+
export { createEventSource, interval, timeout, SubjectEmitter, toEventEmitter, combineEmitters } from "./internal/emitter";
|
|
4
4
|
export { $ };
|
|
5
|
-
export const $body = $(document.body);
|
|
5
|
+
export const $body = "document" in globalThis ? $(document.body) : undefined;
|
package/internal/emitter.d.ts
CHANGED
|
@@ -121,6 +121,9 @@ export declare class EventEmitter<T> {
|
|
|
121
121
|
*/
|
|
122
122
|
or(...emitters: EmitterLike<T>[]): EventEmitter<T>;
|
|
123
123
|
or<U>(...emitters: EmitterLike<U>[]): EventEmitter<T | U>;
|
|
124
|
+
memo(): Memo<T | undefined>;
|
|
125
|
+
memo(initial: T): Memo<T>;
|
|
126
|
+
memo<U>(initial: U): Memo<T | U>;
|
|
124
127
|
}
|
|
125
128
|
/**
|
|
126
129
|
* Creates a linked EventEmitter and emit() pair
|
|
@@ -157,16 +160,19 @@ export declare function createEventSource<T>(initialHandler?: Handler<T>): {
|
|
|
157
160
|
emit: (value: T) => void;
|
|
158
161
|
emitter: EventEmitter<T>;
|
|
159
162
|
};
|
|
160
|
-
export declare function createListenable<T>(sourceListen?: () => UnsubscribeFunc | undefined): {
|
|
161
|
-
listen: (fn: (v: T) => void) => UnsubscribeFunc;
|
|
162
|
-
emit: (value: T) => void;
|
|
163
|
-
};
|
|
164
163
|
export declare function interval(ms: number | {
|
|
165
164
|
asMilliseconds: number;
|
|
166
165
|
}): EventEmitter<number>;
|
|
167
166
|
export declare function timeout(t: number | {
|
|
168
167
|
asMilliseconds: number;
|
|
169
168
|
}): EventEmitter<void>;
|
|
169
|
+
declare class Memo<T> {
|
|
170
|
+
private _value;
|
|
171
|
+
private unsubscribeFunc;
|
|
172
|
+
get value(): T;
|
|
173
|
+
constructor(source: EmitterLike<T>, initial: T);
|
|
174
|
+
dispose(): void;
|
|
175
|
+
}
|
|
170
176
|
export declare class SubjectEmitter<T> extends EventEmitter<T> {
|
|
171
177
|
private emit;
|
|
172
178
|
private _value;
|
|
@@ -192,4 +198,13 @@ type EventSource<T, E extends string> = {
|
|
|
192
198
|
*/
|
|
193
199
|
export declare function toEventEmitter<T>(source: EmitterLike<T>): EventEmitter<T>;
|
|
194
200
|
export declare function toEventEmitter<T, E extends string>(source: EventSource<T, E>, eventName: E): EventEmitter<T>;
|
|
201
|
+
type Dictionary<T> = Record<string | symbol, T>;
|
|
202
|
+
type ExtractEmitterValue<T> = T extends EmitterLike<infer U> ? U : never;
|
|
203
|
+
type CombinedRecord<T extends Dictionary<EmitterLike<any>>> = {
|
|
204
|
+
readonly [K in keyof T]: ExtractEmitterValue<T[K]>;
|
|
205
|
+
};
|
|
206
|
+
export declare function combineEmitters<U extends Dictionary<EmitterLike<any>>>(emitters: U): EventEmitter<CombinedRecord<U>>;
|
|
207
|
+
export declare function combineEmitters<U extends EmitterLike<any>[]>(emitters: [...U]): EventEmitter<{
|
|
208
|
+
[K in keyof U]: ExtractEmitterValue<U[K]>;
|
|
209
|
+
}>;
|
|
195
210
|
export {};
|
package/internal/emitter.js
CHANGED
|
@@ -314,6 +314,9 @@ export class EventEmitter {
|
|
|
314
314
|
return () => unsubs.forEach(unsub => unsub());
|
|
315
315
|
});
|
|
316
316
|
}
|
|
317
|
+
memo(initial) {
|
|
318
|
+
return new Memo(this, initial);
|
|
319
|
+
}
|
|
317
320
|
}
|
|
318
321
|
/**
|
|
319
322
|
* Creates a linked EventEmitter and emit() pair
|
|
@@ -355,7 +358,7 @@ export function createEventSource(initialHandler) {
|
|
|
355
358
|
emitter: new EventEmitter(listen)
|
|
356
359
|
};
|
|
357
360
|
}
|
|
358
|
-
|
|
361
|
+
function createListenable(sourceListen) {
|
|
359
362
|
const handlers = [];
|
|
360
363
|
let onRemoveLast;
|
|
361
364
|
const addListener = (fn) => {
|
|
@@ -401,6 +404,22 @@ export function timeout(t) {
|
|
|
401
404
|
});
|
|
402
405
|
return new EventEmitter(listen);
|
|
403
406
|
}
|
|
407
|
+
class Memo {
|
|
408
|
+
get value() {
|
|
409
|
+
return this._value;
|
|
410
|
+
}
|
|
411
|
+
constructor(source, initial) {
|
|
412
|
+
this._value = initial;
|
|
413
|
+
const emitter = toEventEmitter(source);
|
|
414
|
+
this.unsubscribeFunc = emitter.listen(v => this._value = v);
|
|
415
|
+
}
|
|
416
|
+
dispose() {
|
|
417
|
+
this.unsubscribeFunc();
|
|
418
|
+
this.unsubscribeFunc = () => {
|
|
419
|
+
throw new Error("Memo object already disposed");
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
404
423
|
export class SubjectEmitter extends EventEmitter {
|
|
405
424
|
constructor(initial) {
|
|
406
425
|
const { emit, listen } = createListenable();
|
|
@@ -456,3 +475,39 @@ export function toEventEmitter(source, eventName) {
|
|
|
456
475
|
}
|
|
457
476
|
throw new Error("Invalid event source");
|
|
458
477
|
}
|
|
478
|
+
function combineArray(emitters) {
|
|
479
|
+
let values = Array.from({ length: emitters.length });
|
|
480
|
+
const { emit, listen } = createListenable(() => {
|
|
481
|
+
const unsubFuncs = emitters.map((emitter, idx) => {
|
|
482
|
+
return emitter.listen(v => {
|
|
483
|
+
values[idx] = { value: v };
|
|
484
|
+
if (values.every(v => v !== undefined))
|
|
485
|
+
emit(values.map(vc => vc.value));
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
return () => unsubFuncs.forEach(f => f());
|
|
489
|
+
});
|
|
490
|
+
return new EventEmitter(listen);
|
|
491
|
+
}
|
|
492
|
+
function combineRecord(emitters) {
|
|
493
|
+
const keys = Object.keys(emitters);
|
|
494
|
+
let values = {};
|
|
495
|
+
const { emit, listen } = createListenable(() => {
|
|
496
|
+
const unsubFuncs = keys.map(key => {
|
|
497
|
+
return emitters[key].listen(v => {
|
|
498
|
+
values[key] = { value: v };
|
|
499
|
+
if (keys.every(k => values[k] !== undefined)) {
|
|
500
|
+
const record = Object.fromEntries(Object.entries(values).map(([k, vc]) => [k, vc.value]));
|
|
501
|
+
emit(record);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
return () => unsubFuncs.forEach(f => f());
|
|
506
|
+
});
|
|
507
|
+
return new EventEmitter(listen);
|
|
508
|
+
}
|
|
509
|
+
export function combineEmitters(emitters) {
|
|
510
|
+
if (Array.isArray(emitters))
|
|
511
|
+
return combineArray(emitters.map(toEventEmitter));
|
|
512
|
+
return combineRecord(Object.fromEntries(Object.entries(emitters).map(([k, e]) => [k, toEventEmitter(e)])));
|
|
513
|
+
}
|