@xtia/timeline 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  **Timeline** is a general‑purpose, environment-agnostic choreography engine that lets you orchestrate any sequence of value changes; numbers, vectors, colour tokens, custom blendable objects, or arbitrary data structures.
6
6
 
7
+ * [API Reference](#reference)
7
8
 
8
9
  ## Basic Use:
9
10
 
@@ -33,8 +34,9 @@ timeline
33
34
  );
34
35
 
35
36
  // use an easing function
36
- typingRange
37
+ timeline
37
38
  .end
39
+ .delta(500)
38
40
  .range(3000)
39
41
  .ease("bounce")
40
42
  .tween("50%", "0%")
@@ -93,7 +95,7 @@ eased.listen(
93
95
  const frames = eased
94
96
  .tween(0, 30)
95
97
  .map(Math.floor)
96
- .noRepeat()
98
+ .dedupe()
97
99
  .tap(n => console.log("Showing frame #", n))
98
100
  .map(n => `animation-frame-${n}.png`)
99
101
  .listen(filename => img.src = filename);
@@ -164,7 +166,6 @@ Tween emitters can interpolate numbers, arrays of numbers, strings, and objects
164
166
 
165
167
  ```ts
166
168
  // tween four values in a CSS string
167
- // see this live: https://codepen.io/xtaltia/pen/PwZYbKY
168
169
  timeline
169
170
  .range(0, 2000)
170
171
  .ease("elastic")
@@ -175,9 +176,12 @@ timeline
175
176
  timeline
176
177
  .range(0, 2000)
177
178
  .tween("--------", "########")
179
+ .dedupe()
178
180
  .listen(v => document.title = v);
179
181
  ```
180
182
 
183
+ You can try out the [shadow tweening example at StackBlitz](https://stackblitz.com/edit/timeline-string-tween?file=src%2Fmain.ts)
184
+
181
185
  ## Autoplay and Looping Strategies
182
186
 
183
187
  To create a Timeline that immediately starts playing, pass `true` to its constructor:
@@ -259,10 +263,12 @@ loadingTimeline
259
263
  .tween("0%", "100%");
260
264
  .listen(v => progressBar.style.width = v);
261
265
 
266
+ // and do something when they're loaded
262
267
  loadingTimeline
263
268
  .end
264
269
  .listen(startGame);
265
270
 
271
+ // to drive it, just seek forward by 1 for each loaded resource
266
272
  resourceUrls.forEach(url => {
267
273
  preload(url).then(
268
274
  () => loadingTimeline.currentTime++
@@ -278,7 +284,7 @@ timeline.seek(timeline.end, 400, "overshootIn");
278
284
 
279
285
  ## Backward-compatibility
280
286
 
281
- Despite the massive overhaul, the previous API is present and expanded and upgrading to 1.0.0 should be frictionless in the vast majority of cases.
287
+ Despite the massive overhaul, the previous API is present and expanded and upgrading to 1.0.0 should be frictionless in the vast majority of cases.
282
288
 
283
289
  #### Breaking changes
284
290
 
@@ -287,7 +293,7 @@ Despite the massive overhaul, the previous API is present and expanded and upgr
287
293
  #### Mitigation
288
294
 
289
295
  * `timeline.tween()` now accepts TimelinePoint as a starting position, and provides an overload that replaces the `duration: number` parameter with `end: TimelinePoint`.
290
- * Should you encounter a case where this change still causes issue, eg `tl.tween(0, tl.end / 2, ...)`, `tl.end.position` is equivalent to the old API's `tl.end`.
296
+ * Should you encounter a case where this change still causes issue, eg `timeline.tween(0, timeline.end / 2, ...)`, `timeline.end.position` is equivalent to the old API's `timeline.end`.
291
297
 
292
298
  #### Enhancements (non-breaking)
293
299
 
@@ -298,4 +304,402 @@ Despite the massive overhaul, the previous API is present and expanded and upgr
298
304
 
299
305
  * `timeline.position` will be replaced with `timeline.currentTime` to be consistent with other seekable concepts.
300
306
  * `"loop"` endAction is now `"restart"` to disambiguate from new looping strategies.
301
- * `timeline.step()` is redundant now that `currentTime` is writable; use `timeline.currentTime += delta` instead.
307
+ * `timeline.step()` is redundant now that `currentTime` is writable; use `timeline.currentTime += delta` instead.
308
+
309
+
310
+
311
+ ## Reference
312
+
313
+ ### `Timeline` class
314
+
315
+ A self-contained collection of points and ranges that trigger events as the Timeline seeks to and through them.
316
+
317
+ #### Properties
318
+
319
+ ##### `currentTime: number`
320
+
321
+ Reads or sets the Timeline's current time position. Setting this property will perform a `seek()`, triggering any listener that is passed or landed on.
322
+
323
+ ##### `timeScale: number`
324
+
325
+ Controls the speed at which a Timeline will progress when driven by the `play()` method (including by autoplay).
326
+
327
+ ##### `isPlaying: boolean`
328
+
329
+ Returns true if the Timeline is actively being driven by the `play()` method (including by autoplay).
330
+
331
+ ##### `end: `[`TimelinePoint`](#timelinepoint-interface)
332
+
333
+ Returns the **current** final point in the Timeline.
334
+
335
+ ##### `start: `[`TimelinePoint`](#timelinepoint-interface)
336
+
337
+ Returns a point representing position 0.
338
+
339
+ #### Methods
340
+
341
+ ##### `point(position): `[`TimelinePoint`](#timelinepoint-interface)
342
+
343
+ Returns a point that represents a specific position on the Timeline.
344
+
345
+ If `position` is greater than that Timeline's end-position, the end-position will be extended to `position`.
346
+
347
+ *Note*, for deterministic consistency, points will be triggered if a forward-moving seek lands exactly on the point's position (or passes it entirely), while a backward-moving seek will trigger points that are passed or moved from.
348
+
349
+ ##### `range(start, duration): `[`TimelineRange`](#timelinerange-interface)
350
+
351
+ Returns a range that represents a section of the Timeline.
352
+
353
+ If the end of the range is beyond the Timeline's end-position, the end-position will be extended to the end of the range.
354
+
355
+ If `duration` is omitted, the range will extend from `start` to the **current** end-position of the Timeline.
356
+
357
+ If `start` is omitted, the range will start at 0 and represent the full **current** range of the Timeline.
358
+
359
+ ##### `seek(toPosition): void`
360
+
361
+ Sets the Timeline's internal position (`currentTime`), triggering in chronological order listeners attached to any [`TimelinePoint`](#timelinepoint-interface) or [`TimelineRange`](#timelinerange-interface) that are passed or landed on.
362
+
363
+ ##### `seek(toPosition, duration, easer?): Promise<void>`
364
+
365
+ Performs an interruptable 'smooth seek' to a specified position, lasting `duration` milliseconds, with optional easing.
366
+
367
+ Returns a Promise that will be resolved when the smooth seek is completed (or is interrupted by another seek\*).
368
+
369
+ \* Resolution on interruption is not finalised in the library's design and the effect should be considered exceptional; relying on it is not recommended. Future versions might reject the promise when its seek is interrupted.
370
+
371
+ ##### `play(): void`
372
+
373
+ Begins playing through the Timeline, from its current position, at (1000 x `timeScale`) units per second, updating 60 times per second.
374
+
375
+ ##### `play(fps): void`
376
+
377
+ Begins playing through the Timeline, from its current position, at (1000 x `timeScale`) units per second, updating `fps` times per second.
378
+
379
+ ##### `tween<T>(start, duration, apply, from, to, easer?): `[`ChainingInterface`](#chaininginterface-interface)
380
+
381
+ Creates a [`TimelineRange`](#timelinerange-interface) and attaches a tweening listener.
382
+
383
+ Equivalent to
384
+
385
+ ```ts
386
+ timeline
387
+ .range(start, duration)
388
+ .ease(easer)
389
+ .tween(from, to)
390
+ .listen(apply);
391
+ ```
392
+
393
+ Returns a [`ChainingInterface`](#chaininginterface-interface) representing the point at which the tween ends.
394
+
395
+ ##### `tween<T>(start, end, apply, from, to, easer?): `[`ChainingInterface`](#chaininginterface-interface)
396
+
397
+ As above, but if the second argument is a [`TimelinePoint`](#timelinepoint-interface), it will specify when on the Timeline the tween will *end*.
398
+
399
+ ##### `at(position, apply, reverse?): `[`ChainingInterface`](#chaininginterface-interface)
400
+
401
+ Creates a [`TimelinePoint`](#timelinepoint-interface) and attaches a listener that will trigger when the Timeline seeks past or to that point.
402
+
403
+ If `reverse` is a function, that will be called instead of `apply` when the seek that triggered the event was moving backwards. If `reverse` is `true`, `apply` will be called regardless of which direction the seek moved. If `reverse` is false or omitted, this listener will ignore backward-moving seeks.
404
+
405
+
406
+
407
+
408
+ ### `TimelinePoint` interface
409
+
410
+ Represents a single point on a [`Timeline`](#timeline-class).
411
+
412
+ ##### Inherits [`Emitter<PointEvent>`](#emittert-interface)
413
+
414
+ Listeners will be invoked with a [`PointEvent`](#pointevent-interface) when a seek passes or lands on the point.
415
+
416
+ *Note*, during a point event, the parent Timeline's `currentTime` property will return that point's position, even if the Timeline is configured with a [*wrap* end action](#autoplay-and-looping-strategies) and its true position is beyond its end. For deterministic consistency, ranges will emit values for the point's position before the point emits.
417
+
418
+ #### Properties
419
+
420
+ ##### `position: number`
421
+
422
+ This point's position on the Timeline.
423
+
424
+ #### Methods
425
+
426
+ ##### `range(duration): TimelineRange`
427
+
428
+ Creates a [`TimelineRange`](#timelinerange-interface) on the Timeline to which the point belongs, of the specified duration.
429
+
430
+ ##### `to(endPoint): TimelineRange`
431
+
432
+ Creates a [`TimelineRange`](#timelinerange-interface) on the Timeline to which the point belongs, ending at the specified point.
433
+
434
+ ##### `delta(timeOffset): TimelinePoint`
435
+
436
+ Creates a `TimelinePoint` at an offset from the this point.
437
+
438
+
439
+
440
+
441
+ ### `PointEvent` interface
442
+
443
+ Provides information relevant to [`TimelinePoint`](#timelinepoint-interface) events.
444
+
445
+ #### Properties
446
+
447
+ ##### `direction: -1 | 1`
448
+
449
+ Provides the direction of the seek that triggered a point event. `direction === 1` indicates that the seek moved forward and `direction === -1` indicates that the seek was moving backwards.
450
+
451
+ Allows point listeners to undo effects when the Timeline is reversed.
452
+
453
+ ```ts
454
+ timeline
455
+ .point(4000)
456
+ .listen(
457
+ event => element.classList.toggle(
458
+ "visible",
459
+ event.direction > 0
460
+ )
461
+ );
462
+ ```
463
+
464
+
465
+
466
+
467
+ ### `TimelineRange` interface
468
+
469
+ Represents a fixed-length, fixed position section of a [`Timeline`](#timeline-class).
470
+
471
+ ##### Inherits [`RangeProgression`](#rangeprogression-interface)
472
+
473
+ Emits a normalised progression (0..1) of the range when the parent Timeline seeks over or into it.
474
+
475
+ #### Properties
476
+
477
+ ##### `start: `[`TimelinePoint`](#timelinepoint-interface)
478
+
479
+ The point on the Timeline at which this range starts.
480
+
481
+ ##### `end: `[`TimelinePoint`](#timelinepoint-interface)
482
+
483
+ The point on the Timeline at which this range ends.
484
+
485
+ ##### `duration: number`
486
+
487
+ The length of the range.
488
+
489
+ #### Methods
490
+
491
+ ##### `bisect(position?): [TimelineRange, TimelineRange]`
492
+
493
+ Creates two ranges representing two distinct sections of the parent. `position` is relative to the parent's start.
494
+
495
+ ##### `spread(count): `[`TimelinePoint`](#timelinepoint-interface)[]
496
+
497
+ Creates and returns `count` points spread evenly over the range.
498
+
499
+ ##### `play(easer?): Promise<void>`
500
+
501
+ Instructs the Timeline to which this range belongs to play through the represented range. This playthrough counts as a smooth seek for seek interruption purposes.
502
+
503
+ Returns a Promise that will be resolved when the range playthrough completes.
504
+
505
+ ##### `grow(delta, anchor?): TimelineRange`
506
+
507
+ Creates a new range on the parent Timeline. The location and duration of the new range are copied from this range and grown from an anchor point, specified as a normalised (0..1) progression of the parent range.
508
+
509
+ ##### `grow(delta, anchor?): TimelineRange`
510
+
511
+ Creates a new range on the parent Timeline. The location and duration of the new range are copied from this range and scaled multiplicatively from an anchor point, specified as a normalised (0..1) progression of the parent range.
512
+
513
+ ##### `contains(point)`
514
+
515
+ Returns true if the given [`TimelinePoint`](#timelinepoint-interface) sits within this range.
516
+
517
+
518
+
519
+
520
+ ### `RangeProgression` interface
521
+
522
+ Represents a step in an immutable [`TimelineRange`](#timelinerange-interface) event transformation pipeline.
523
+
524
+ ##### Inherits [`Emitter<number>`](#emittert-interface)
525
+
526
+ Listeners will be invoked when a seek passes or lands within a range.
527
+
528
+ #### Methods
529
+
530
+ ##### `ease(easer?): RangeProgression`
531
+
532
+ Creates an emitter that applies an easing function to parent emissions.
533
+
534
+ ##### `tween<T>(from, to): `[`Emitter<T>`](#emittert-interface)
535
+
536
+ Creates an emitter blends two values, biased by progression emitted by the parent.
537
+
538
+ `T` may be `string`, `number`, `number[]` or an object type that includes
539
+
540
+ ```ts
541
+ blend(from: this, to: this, progress: number): this
542
+ ```
543
+
544
+ ##### `snap(steps): RangeProgression`
545
+
546
+ Creates an emitter that quantises progression emitted by the parent to the nearest of `steps` discrete values.
547
+
548
+ ##### `threshold(threshold): RangeProgression`
549
+
550
+ Creates an emitter that emits 0 when the parent emits a value below `threshold` and 1 when a parent emission is equal to or greater than `threshold`.
551
+
552
+ ```ts
553
+ emittedValue = parentEmission < threshold ? 0 : 1
554
+ ```
555
+
556
+ ##### `clamp(min?, max?): RangeProgression`
557
+
558
+ Creates an emitter that clamps progression between `min` and `max`.
559
+
560
+ ##### `repeat(count): RangeProgression`
561
+
562
+ Creates an emitter that multiplies progression and wraps at 1, thereby mapping to a repeating scale.
563
+
564
+ ##### `tap(cb): RangeProgression`
565
+
566
+ Creates an emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
567
+
568
+ ##### `filter(check: (value) => boolean): RangeProgression`
569
+
570
+ Creates an emitter that selectively discards parent emissions.
571
+
572
+ If `check(value)` returns true, the value will be emitted.
573
+
574
+ ##### `dedupe(): RangeProgression`
575
+
576
+ Creates an emitter that discards emitted values that are the same as the last value emitted by the new emitter
577
+
578
+ ##### `offset(delta): RangeProgression`
579
+
580
+ Creates an emitter that offsets its parent's values by the given delta, wrapping at 1
581
+
582
+ ##### `fork(cb: (branch) => void): RangeProgression`
583
+
584
+ Immediately invokes `cb` with this emitter and returns this emitter for further chaining.
585
+
586
+ Allows branching without breaking a composition chain, eg:
587
+
588
+ ```ts
589
+ range
590
+ .tween("0%", "100%")
591
+ .fork(branch => {
592
+ branch
593
+ .map(s => `Loading: ${s}`)
594
+ .listen(s => document.title = s)
595
+ })
596
+ .listen(v => progressBar.style.width = v);
597
+ ```
598
+
599
+
600
+
601
+
602
+ ### `Emitter<T>` interface
603
+
604
+ #### Methods
605
+
606
+ ##### `listen(handler: Handler<T>): UnsubscribeFunc`
607
+
608
+ Attaches a handler to the emitter and returns a function that will unsubscribe the handler.
609
+
610
+ ##### `map<R>(mapFunc: (value: T) => R): Emitter<R>`
611
+
612
+ Creates an emitter that performs an arbitrary transformation.
613
+
614
+ ##### `filter(check: (value: T) => boolean): Emitter<T>`
615
+
616
+ Creates an emitter that selectively discards parent emissions.
617
+
618
+ If `check(value)` returns true, the value will be emitted.
619
+
620
+ ##### `dedupe(compare?: (a: T, b: T) => boolean): Emitter<T>`
621
+
622
+ Creates an emitter that discards emitted values that are the same as the last value emitted by the new emitter
623
+
624
+ ##### `tap(cb: Handler<T>): Emitter<T>`
625
+
626
+ Creates an emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
627
+
628
+ ##### `fork(cb: (branch: Emitter<T>) => void): Emitter<T>`
629
+
630
+ Immediately invokes `cb` with this emitter and returns this emitter for further chaining.
631
+
632
+ Allows branching without breaking a composition chain, eg:
633
+
634
+ ```ts
635
+ range
636
+ .tween("0%", "100%")
637
+ .fork(branch => {
638
+ branch
639
+ .map(s => `Loading: ${s}`)
640
+ .listen(s => document.title = s)
641
+ })
642
+ .listen(v => progressBar.style.width = v);
643
+ ```
644
+
645
+
646
+
647
+
648
+ ### `animate(duration)` function
649
+
650
+ Creates and returns a [`TimelineRange`](#timelinerange-interface) that will automatically play over `duration` milliseconds.
651
+
652
+ ### `ChainingInterface` interface
653
+
654
+ Conveys composable sequential tweens and events with the simplified API. Each instance represents a specific point on the parent Timeline.
655
+
656
+ ```ts
657
+ timeline
658
+ .tween(0, 1000, doThing, 0, 100)
659
+ .thenWait(500)
660
+ .then(doOtherThing)
661
+ .thenWait(250)
662
+ .thenTween(2000, dothing, 100, 0);
663
+ ```
664
+
665
+ #### Properties
666
+
667
+ ##### `end: `[`TimelinePoint`](#timelinepoint-interface)
668
+
669
+ The point on the Timeline at which the effect of the previous chained call ends.
670
+
671
+ #### Methods
672
+
673
+ ##### `thenTween(duration, apply, from, to, easer): ChainingInterface`
674
+
675
+ Adds a tween, beginning at the point the interface represents. Returns a new `ChainingInterface` representing the end of the new tween.
676
+
677
+ ##### `then(action: () => void): ChainingInterface`
678
+
679
+ Adds a point event at the point the interface represents.
680
+
681
+ ##### `thenWait(duration): ChainingInterface`
682
+
683
+ Creates a new `ChainingInterface` by offsetting the parent by `duration`.
684
+
685
+
686
+
687
+ ### `easers` const
688
+
689
+ The following easers are provided:
690
+
691
+ `linear`, `easeIn`, `easeIn4`, `easeOut`, `easeOut4`, `circleIn`, `circleIn4`, `circleOut`, `circleOut4`, `easeInOut`, `elastic`, `overshootIn`, `sine`, `invert`, `bounce`, `noise`, `pingpong`
692
+
693
+ Methods that accept an easing function accept both `(progress: number) => number` and any of the names above.
694
+
695
+ ```ts
696
+ timeline
697
+ .tween(s, e, a, f, t, v => Math.sqrt(v))
698
+ .thenTween(s, e, a, f, t, c, "elastic");
699
+
700
+ timeline
701
+ .range(0, 1000)
702
+ .ease("circleOut")
703
+ .ease(easers.easeIn)
704
+ // ...
705
+ ```
package/index.js CHANGED
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.easers = exports.animate = exports.Timeline = void 0;
3
+ exports.easers = exports.RangeProgression = exports.Emitter = exports.TimelineRange = exports.TimelinePoint = exports.animate = exports.Timeline = void 0;
4
4
  var timeline_1 = require("./internal/timeline");
5
5
  Object.defineProperty(exports, "Timeline", { enumerable: true, get: function () { return timeline_1.Timeline; } });
6
6
  Object.defineProperty(exports, "animate", { enumerable: true, get: function () { return timeline_1.animate; } });
7
+ var point_1 = require("./internal/point");
8
+ Object.defineProperty(exports, "TimelinePoint", { enumerable: true, get: function () { return point_1.TimelinePoint; } });
9
+ var range_1 = require("./internal/range");
10
+ Object.defineProperty(exports, "TimelineRange", { enumerable: true, get: function () { return range_1.TimelineRange; } });
11
+ var emitters_1 = require("./internal/emitters");
12
+ Object.defineProperty(exports, "Emitter", { enumerable: true, get: function () { return emitters_1.Emitter; } });
13
+ Object.defineProperty(exports, "RangeProgression", { enumerable: true, get: function () { return emitters_1.RangeProgression; } });
7
14
  var easing_1 = require("./internal/easing");
8
15
  Object.defineProperty(exports, "easers", { enumerable: true, get: function () { return easing_1.easers; } });
@@ -1,17 +1,19 @@
1
1
  import { Easer, easers } from "./easing";
2
- import { Blendable } from "./tween";
3
- /** @internal */
4
- export declare function createEmitter<T>(listen: ListenFunc<T>): Emitter<T>;
5
- /** @internal */
6
- export declare function createEmitter<T, API extends object>(onListen: ListenFunc<T>, api: Omit<API, keyof Emitter<T>>): Emitter<T> & API;
7
- /** @internal */
8
- export declare function createProgressEmitter<API extends object>(onListen: ListenFunc<number>, api: Omit<API, keyof RangeProgression>): RangeProgression & API;
9
- /** @internal */
10
- export declare function createProgressEmitter(onListen: ListenFunc<number>): RangeProgression;
2
+ import { Tweenable } from "./tween";
11
3
  type Handler<T> = (value: T) => void;
12
- type ListenFunc<T> = (handler: Handler<T>) => UnsubscribeFunc;
4
+ export type ListenFunc<T> = (handler: Handler<T>) => UnsubscribeFunc;
13
5
  export type UnsubscribeFunc = () => void;
14
- export interface Emitter<T> {
6
+ export declare class Emitter<T> {
7
+ protected onListen: ListenFunc<T>;
8
+ protected constructor(onListen: ListenFunc<T>);
9
+ /**
10
+ * Used by tap() to create a clone of an Emitter with a redirected onListen
11
+ * Should be overridden in all Emitter subclasses
12
+ * @see {@link TimelineRange.redirect}
13
+ * @param listen
14
+ * @returns {this}
15
+ */
16
+ protected redirect: (listen: ListenFunc<T>) => Emitter<T>;
15
17
  /**
16
18
  * Registers a function to receive emitted values
17
19
  * @param handler
@@ -37,7 +39,7 @@ export interface Emitter<T> {
37
39
  * If no `compare` function is provided, values will be compared via `===`
38
40
  * @returns Listenable: emits non-repeating values
39
41
  */
40
- noRepeat(compare?: (a: T, b: T) => boolean): Emitter<T>;
42
+ dedupe(compare?: (a: T, b: T) => boolean): Emitter<T>;
41
43
  /**
42
44
  * Creates a chainable emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
43
45
  *
@@ -49,9 +51,29 @@ export interface Emitter<T> {
49
51
  * @param cb A function to be called as a side effect for each value emitted by the parent emitter.
50
52
  * @returns A new emitter that forwards all values from the parent, invoking `cb` as a side effect.
51
53
  */
52
- tap(cb: Handler<T>): Emitter<T>;
54
+ tap(cb: Handler<T>): this;
55
+ /**
56
+ * Immediately passes this emitter to a callback and returns this emitter
57
+ *
58
+ * Allows branching without breaking a composition chain
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * range
63
+ * .tween("0%", "100%")
64
+ * .fork(branch => {
65
+ * branch
66
+ * .map(s => `Loading: ${s}`)
67
+ * .listen(s => document.title = s)
68
+ * })
69
+ * .listen(v => progressBar.style.width = v);
70
+ * ```
71
+ * @param cb
72
+ */
73
+ fork(cb: (branch: this) => void): this;
53
74
  }
54
- export interface RangeProgression extends Emitter<number> {
75
+ export declare class RangeProgression extends Emitter<number> {
76
+ protected redirect: (listen: ListenFunc<number>) => RangeProgression;
55
77
  /**
56
78
  * Creates a chainable progress emitter that applies an easing function to its parent's emitted values
57
79
  *
@@ -59,6 +81,7 @@ export interface RangeProgression extends Emitter<number> {
59
81
  * @returns Listenable: emits eased progression values
60
82
  */
61
83
  ease(easer?: Easer | keyof typeof easers): RangeProgression;
84
+ ease(easer?: undefined): RangeProgression;
62
85
  /**
63
86
  * Creates a chainable emitter that interpolates two given values by progression emitted by its parent
64
87
  *
@@ -99,7 +122,7 @@ export interface RangeProgression extends Emitter<number> {
99
122
  * @param to Value to interpolate to
100
123
  * @returns Listenable: emits interpolated values
101
124
  */
102
- tween<T extends Blendable | number[]>(from: T, to: T): Emitter<T>;
125
+ tween<T extends Tweenable>(from: T, to: T): Emitter<T>;
103
126
  /**
104
127
  * Creates a chainable progress emitter that quantises progress, as emitted by its parent, to the nearest of `steps` discrete values.
105
128
  *
@@ -124,21 +147,23 @@ export interface RangeProgression extends Emitter<number> {
124
147
  clamp(min?: number, max?: number): RangeProgression;
125
148
  /**
126
149
  * Creates a chainable progress emitter that maps incoming values to a repeating linear scale
127
- * @param count Number of repetitions
128
- */
129
- repeat(count: number): RangeProgression;
130
- /**
131
- * Creates a chainable progress emitter that mirrors emissions from the parent emitter, invoking the provided callback `cb` as a side effect for each emission.
132
- *
133
- * The callback `cb` is called exactly once per parent emission, regardless of how many listeners are attached to the returned emitter.
134
- * All listeners attached to the returned emitter receive the same values as the parent emitter.
135
150
  *
136
- * *Note*, the side effect `cb` is only invoked when there is at least one listener attached to the returned emitter
151
+ * ```plain
152
+ * count=2
153
+ *‎ 1
154
+ *‎ | / /
155
+ *‎ o| / /
156
+ *‎ u| / /
157
+ *‎ t| / /
158
+ *‎ | / /
159
+ *‎ |/_____/_____
160
+ *‎ 0 in 1
161
+ * ```
137
162
  *
138
- * @param cb A function to be called as a side effect for each value emitted by the parent emitter.
139
- * @returns A new emitter that forwards all values from the parent, invoking `cb` as a side effect.
163
+ * @param count Number of repetitions
164
+ * @returns Listenable: emits scaled and repeating values
140
165
  */
141
- tap(cb: (value: number) => void): RangeProgression;
166
+ repeat(count: number): RangeProgression;
142
167
  /**
143
168
  * Creates a chainable progress emitter that selectively forwards emissions along the chain
144
169
  * @param check Function that takes an emitted value and returns true if the emission should be forwarded along the chain
@@ -149,9 +174,9 @@ export interface RangeProgression extends Emitter<number> {
149
174
  * Creates a chainable progress emitter that discards emitted values that are the same as the last value emitted by the new emitter
150
175
  * @returns Listenable: emits non-repeating values
151
176
  */
152
- noRepeat(): RangeProgression;
177
+ dedupe(): RangeProgression;
153
178
  /**
154
- * Creates a chainable progress emitter that offsets its parent's values by the given delta, wrapping between 0 and 1
179
+ * Creates a chainable progress emitter that offsets its parent's values by the given delta, wrapping at 1
155
180
  *
156
181
  * ```plain
157
182
  *‎ 1
@@ -165,6 +190,7 @@ export interface RangeProgression extends Emitter<number> {
165
190
  * ```
166
191
  *
167
192
  * @param delta
193
+ * @returns Listenable: emits offset values
168
194
  */
169
195
  offset(delta: number): RangeProgression;
170
196
  }