@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.
@@ -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
- asMilliseconds: number;
165
- }): EventEmitter<number>;
166
- export declare function timeout(t: number | {
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: (value: T) => void) => UnsubscribeFunc;
202
+ on: (eventName: E, handler: Handler<T>) => UnsubscribeFunc;
185
203
  } | {
186
- on: (eventName: E, handler: (value: T) => void) => void | UnsubscribeFunc;
187
- off: (eventName: E, handler: (value: T) => void) => void;
204
+ on: (eventName: E, handler: Handler<T>) => void | UnsubscribeFunc;
205
+ off: (eventName: E, handler: Handler<T>) => void;
188
206
  } | {
189
- addEventListener: (eventName: E, handler: (value: T) => void) => UnsubscribeFunc;
207
+ addEventListener: (eventName: E, handler: Handler<T>) => UnsubscribeFunc;
190
208
  } | {
191
- addEventListener: (eventName: E, handler: (value: T) => void) => void | UnsubscribeFunc;
192
- removeEventListener: (eventName: E, handler: (value: T) => void) => void;
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>>> = {
@@ -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(ms) {
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
- }, ms);
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(ms) {
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 + ms) {
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(ms) {
183
+ delay(t) {
175
184
  return new EventEmitter(this.transform((value, emit) => {
176
- setTimeout(() => emit(value), ms);
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
- const handler = () => {
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(ms) {
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
- }, typeof ms == "number" ? ms : ms.asMilliseconds);
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 = typeof t === "number" ? t : t.asMilliseconds;
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) {
@@ -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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtia/jel",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "repository": {
5
5
  "url": "https://github.com/tiadrop/jel-ts",
6
6
  "type": "github"