@xtia/timeline 1.0.12 → 1.1.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Timeline
2
2
 
3
- ### A Type‑Safe Choreography Engine for Deterministic Timelines
3
+ ### Not Just Another Animation Library
4
4
 
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.
5
+ Timeline is a type-safe, deterministic choreography system that can control state transitions in any environment, whether that's a simple or complex CSS animation, managing a microcontroller's output, or synchronising complex hardware sequences.
6
6
 
7
7
  * [API Reference](#reference)
8
8
  * [Playground](https://stackblitz.com/edit/timeline-string-tween?file=src%2Fmain.ts)
@@ -21,7 +21,7 @@ const timeline = new Timeline();
21
21
  timeline
22
22
  .range(0, 1000)
23
23
  .tween("#646", "#000")
24
- .listen(
24
+ .apply(
25
25
  value => element.style.background = value
26
26
  );
27
27
 
@@ -29,20 +29,18 @@ timeline
29
29
  const message = "Hi, planet!";
30
30
  timeline
31
31
  .range(500, 2000)
32
+ .ease("easeOut")
32
33
  .tween(0, message.length)
33
34
  .map(n => message.substring(0, n))
34
- .listen(
35
+ .apply(
35
36
  s => element.textContent = s
36
37
  );
37
38
 
38
- // use an easing function
39
+ // control anything:
39
40
  timeline
40
- .range(0, 3000)
41
- .ease("bounce")
42
- .tween("50%", "0%")
43
- .listen(
44
- value => element.style.marginLeft = value
45
- );
41
+ .range(1000, 2000)
42
+ .tween(0, 255)
43
+ .listen(value => microcontroller.setPWM(value))
46
44
 
47
45
  // make it go
48
46
  timeline.play();
@@ -56,11 +54,11 @@ timeline.play();
56
54
  const firstFiveSeconds = timeline.range(0, 5000);
57
55
  ```
58
56
 
59
- The range object is *listenable* and emits a progression value (between 0 and 1) when the Timeline's internal position passes through or over that period.
57
+ The range object is *applyable* and emits a progression value (between 0 and 1) when the Timeline's internal position passes through or over that period.
60
58
 
61
59
  ```ts
62
60
  firstFiveSeconds
63
- .listen(
61
+ .apply(
64
62
  value => console.log(`${value} is between 0 and 1`)
65
63
  );
66
64
  ```
@@ -74,20 +72,20 @@ const asPercent = firstFiveSeconds.map(n => n * 100);
74
72
  // use the result in a log message
75
73
  asPercent
76
74
  .map(n => n.toFixed(2))
77
- .listen(
75
+ .apply(
78
76
  n => console.log(`We are ${n}% through the first five seconds`)
79
77
  );
80
78
 
81
79
  // and in a css property
82
80
  asPercent
83
81
  .map(n => `${n}%`)
84
- .listen(
82
+ .apply(
85
83
  n => progressBar.style.width = n
86
84
  );
87
85
 
88
86
  // apply easing
89
87
  const eased = firstFiveSeconds.ease("easeInOut");
90
- eased.listen(
88
+ eased.apply(
91
89
  v => console.log(`Eased value: ${v}`)
92
90
  );
93
91
 
@@ -98,7 +96,7 @@ range
98
96
  .dedupe()
99
97
  .tap(n => console.log("Showing frame #", n))
100
98
  .map(n => `animation-frame-${n}.png`)
101
- .listen(filename => img.src = filename);
99
+ .apply(filename => img.src = filename);
102
100
 
103
101
  // each step in a chain is a 'pure', independent emitter that emits a
104
102
  // transformation of its parent's emissions
@@ -129,7 +127,7 @@ Custom easers can be passed to `ease()` as `(progress: number) => number`:
129
127
  ```ts
130
128
  timeline
131
129
  .range(0, 1000)
132
- .ease(n => Math.sqrt(n))
130
+ .ease(n => n * n)
133
131
  .tween(/*...*/);
134
132
  ```
135
133
 
@@ -146,7 +144,7 @@ const sixSecondsIn = fiveSecondsdIn.delta(1000);
146
144
  Points emit `PointEvent` objects when their position is reached or passed.
147
145
 
148
146
  ```ts
149
- twoSecondsIn.listen(event => {
147
+ twoSecondsIn.apply(event => {
150
148
  // event.direction (-1 | 1) tells us the direction of the seek that
151
149
  // triggered the point. This allows for reversible point events
152
150
  document.body.classList.toggle("someClass", event.direction > 0);
@@ -181,30 +179,30 @@ const range = timeline.range(0, 2000);
181
179
  range
182
180
  .ease("overshootIn")
183
181
  .tween(300, 500)
184
- .listen(v => element.scrollTop = v);
182
+ .apply(v => element.scrollTop = v);
185
183
 
186
184
  // number arrays
187
185
  range
188
186
  .tween([0, 180], [360, 180])
189
- .listen((angles) => pieChart.setValues(angles));
187
+ .apply((angles) => pieChart.setValues(angles));
190
188
 
191
189
  // strings
192
190
  range
193
191
  .tween("#000000", "#ff00ff")
194
- .listen(v => element.style.color = v);
192
+ .apply(v => element.style.color = v);
195
193
 
196
194
  // blendable objects
197
195
  // (T extends { blend(from: this, to: this): this })
198
196
  import { RGBA } from "@xtia/rgba";
199
197
  range
200
198
  .tween(RGBA.parse("#c971a7"), RGBA.parse("#fff"))
201
- .listen(v => element.style.background = v);
199
+ .apply(v => element.style.background = v);
202
200
 
203
201
  import { Angle } from "@xtia/mezr";
204
202
  range
205
203
  .tween(Angle.degrees(45), Angle.turns(.5))
206
204
  .map(a => `rotate(${a.asDegrees}deg)`)
207
- .listen(v => element.style.transform = v);
205
+ .apply(v => element.style.transform = v);
208
206
 
209
207
  ```
210
208
 
@@ -218,14 +216,14 @@ timeline
218
216
  .range(0, 2000)
219
217
  .ease("elastic")
220
218
  .tween("0px 0px 0px #0000", "15px 15px 20px #0005")
221
- .listen(s => element.style.textShadow = s);
219
+ .apply(s => element.style.textShadow = s);
222
220
 
223
221
  // text progress bar
224
222
  timeline
225
223
  .range(0, 2000)
226
224
  .tween("--------", "########")
227
225
  .dedupe()
228
- .listen(v => document.title = v);
226
+ .apply(v => document.title = v);
229
227
  ```
230
228
 
231
229
  Try out the [shadow tweening example at StackBlitz](https://stackblitz.com/edit/timeline-string-tween?file=src%2Fmain.ts)
@@ -238,13 +236,13 @@ To create a Timeline that immediately starts playing, pass `true` to its constru
238
236
  // immediately fade in an element
239
237
  new Timeline(true)
240
238
  .range(0, 1000)
241
- .listen(v => element.style.opacity = v);
239
+ .apply(v => element.style.opacity = v);
242
240
 
243
241
  // note, an `animate(duration)` function is exported for
244
242
  // disposable, single-use animations such as this:
245
243
  import { animate } from "@xtia/timeline";
246
244
  animate(1000)
247
- .listen(v => element.style.opacity = v);
245
+ .apply(v => element.style.opacity = v);
248
246
  ```
249
247
 
250
248
  Normally a Timeline will simply stop playing when it reaches the end. This can be changed by passing a second argument (`endAction`) to the constructor.
@@ -302,19 +300,19 @@ window.addEventListener(
302
300
  setInterval(() => timeline.seek(Date.now()), 1000);
303
301
  timeline
304
302
  .point(new Date("2026-10-31").getTime())
305
- .listen(() => console.log("Happy anniversary 🏳️‍⚧️💗"));
303
+ .apply(() => console.log("Happy anniversary 🏳️‍⚧️💗"));
306
304
 
307
305
  // show a progress bar for loaded resources
308
306
  const loadingTimeline = new Timeline();
309
307
  loadingTimeline
310
308
  .range(0, resourceUrls.length)
311
309
  .tween("0%", "100%");
312
- .listen(v => progressBar.style.width = v);
310
+ .apply(v => progressBar.style.width = v);
313
311
 
314
312
  // and do something when they're loaded
315
313
  loadingTimeline
316
314
  .end
317
- .listen(startGame);
315
+ .apply(startGame);
318
316
 
319
317
  // to drive it, just seek forward by 1 for each loaded resource
320
318
  resourceUrls.forEach(url => {
@@ -435,7 +433,7 @@ timeline
435
433
  .range(start, duration)
436
434
  .ease(easer)
437
435
  .tween(from, to)
438
- .listen(apply);
436
+ .apply(apply);
439
437
  ```
440
438
 
441
439
  Returns a [`ChainingInterface`](#chaininginterface-interface) representing the point at which the tween ends.
@@ -491,6 +489,33 @@ Seeks the parent Timeline to this point.
491
489
 
492
490
  Smooth-seeks the parent Timeline to this point over a specified duration and resolves the returned Promise on completion.
493
491
 
492
+ ##### `promise(): Promise<-1 | 1>`
493
+
494
+ Creates a `Promise` that will be resolved when the Timeline first seeks to/past this point.
495
+
496
+ The resolved value indicates the direction of the seek that triggered resolution.
497
+
498
+ ##### `forwardOnly(): Emitter<PointEvent>`
499
+
500
+ Creates an emitter that forwards emissions triggered by forward-moving seeks.
501
+
502
+ ##### `reverseOnly(): Emitter<PointEvent>`
503
+
504
+ Creates an emitter that forwards emissions triggered by backward-moving seeks.
505
+
506
+ ##### `applyDirectional(apply, revert): UnsubscribeFunc`
507
+
508
+ Registers an emission handler that calls one function for forward seeks to or past the point, and another for backward seeks from or past the point.
509
+
510
+ ```ts
511
+ point
512
+ .applyDirectional(
513
+ element.classList.add("faded"),
514
+ element.classList.remove("faded"),
515
+ );
516
+ ```
517
+
518
+
494
519
 
495
520
 
496
521
  ### `PointEvent` interface
@@ -508,7 +533,7 @@ Allows point listeners to undo effects when the Timeline is reversed.
508
533
  ```ts
509
534
  timeline
510
535
  .point(4000)
511
- .listen(
536
+ .apply(
512
537
  event => element.classList.toggle(
513
538
  "visible",
514
539
  event.direction > 0
@@ -565,10 +590,22 @@ Creates a new range on the parent Timeline. The location and duration of the new
565
590
 
566
591
  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.
567
592
 
568
- ##### `contains(point)`
593
+ ##### `subdivide(n): TimelineRange[]`
594
+
595
+ Creates the specified number of ranges, each of `(parent.duration / count)` duration, spread evenly over this range.
596
+
597
+ ##### `shift(delta): TimelineRange`
598
+
599
+ Creates a new range by offsetting the parent by a given time delta.
600
+
601
+ ##### `contains(point): boolean`
569
602
 
570
603
  Returns true if the given [`TimelinePoint`](#timelinepoint-interface) sits within this range.
571
604
 
605
+ ##### `overlaps(range): boolean`
606
+
607
+ Returns true if the given range overlaps with this range.
608
+
572
609
 
573
610
 
574
611
 
@@ -634,9 +671,20 @@ If `check(value)` returns true, the value will be emitted.
634
671
 
635
672
  Creates an emitter that discards emitted values that are the same as the last value emitted by the new emitter
636
673
 
674
+ ##### `sample<T>(items): T`
675
+
676
+ Creates a chainable emitter that takes a value from an array according to progression.
677
+
678
+ ```ts
679
+ range
680
+ .sample(["a", "b", "c"])
681
+ .apply(v => console.log(v));
682
+ // logs 'b' when a seek lands halfway through range
683
+ ```
684
+
637
685
  ##### `offset(delta): RangeProgression`
638
686
 
639
- Creates an emitter that offsets its parent's values by the given delta, wrapping at 1
687
+ Creates an emitter that offsets its parent's values by the given delta, wrapping at 1.
640
688
 
641
689
  ##### `fork(cb: (branch) => void): RangeProgression`
642
690
 
@@ -650,19 +698,18 @@ range
650
698
  .fork(branch => {
651
699
  branch
652
700
  .map(s => `Loading: ${s}`)
653
- .listen(s => document.title = s)
701
+ .apply(s => document.title = s)
654
702
  })
655
- .listen(v => progressBar.style.width = v);
703
+ .apply(v => progressBar.style.width = v);
656
704
  ```
657
705
 
658
706
 
659
707
 
660
-
661
708
  ### `Emitter<T>` interface
662
709
 
663
710
  #### Methods
664
711
 
665
- ##### `listen(handler: Handler<T>): UnsubscribeFunc`
712
+ ##### `apply(handler: Handler<T>): UnsubscribeFunc`
666
713
 
667
714
  Attaches a handler to the emitter and returns a function that will unsubscribe the handler.
668
715
 
@@ -696,9 +743,9 @@ range
696
743
  .fork(branch => {
697
744
  branch
698
745
  .map(s => `Loading: ${s}`)
699
- .listen(s => document.title = s)
746
+ .apply(s => document.title = s)
700
747
  })
701
- .listen(v => progressBar.style.width = v);
748
+ .apply(v => progressBar.style.width = v);
702
749
  ```
703
750
 
704
751
 
@@ -16,11 +16,17 @@ export declare class Emitter<T> {
16
16
  */
17
17
  protected redirect: (listen: ListenFunc<T>) => Emitter<T>;
18
18
  /**
19
- * Registers a function to receive emitted values
19
+ * Compatibility alias for `apply()` - registers a function to receive emitted values
20
20
  * @param handler
21
21
  * @returns A function to deregister the handler
22
22
  */
23
23
  listen(handler: Handler<T>): UnsubscribeFunc;
24
+ /**
25
+ * Registers a function to receive emitted values
26
+ * @param handler
27
+ * @returns A function to deregister the handler
28
+ */
29
+ apply(handler: Handler<T>): UnsubscribeFunc;
24
30
  /**
25
31
  * Creates a chainable emitter that applies arbitrary transformation to values emitted by its parent
26
32
  * @param mapFunc
@@ -65,9 +71,9 @@ export declare class Emitter<T> {
65
71
  * .fork(branch => {
66
72
  * branch
67
73
  * .map(s => `Loading: ${s}`)
68
- * .listen(s => document.title = s)
74
+ * .apply(s => document.title = s)
69
75
  * })
70
- * .listen(v => progressBar.style.width = v);
76
+ * .apply(v => progressBar.style.width = v);
71
77
  * ```
72
78
  * @param cb
73
79
  */
@@ -106,7 +112,7 @@ export declare class RangeProgression extends Emitter<number> {
106
112
  * ```ts
107
113
  * range
108
114
  * .tween("0px 0px 0px #0000", "4px 4px 8px #0005")
109
- * .listen(s => element.style.textShadow = s);
115
+ * .apply(s => element.style.textShadow = s);
110
116
  * ```
111
117
  *
112
118
  * @param from Value to interpolate from
@@ -132,7 +138,7 @@ export declare class RangeProgression extends Emitter<number> {
132
138
  * ```ts
133
139
  * range
134
140
  * .sample(["a", "b", "c"])
135
- * .listen(v => console.log(v));
141
+ * .apply(v => console.log(v));
136
142
  * // logs 'b' when a seek lands halfway through range
137
143
  * ```
138
144
  * @param source array to sample
@@ -15,7 +15,7 @@ export class Emitter {
15
15
  this.redirect = (listen) => new Emitter(listen);
16
16
  }
17
17
  /**
18
- * Registers a function to receive emitted values
18
+ * Compatibility alias for `apply()` - registers a function to receive emitted values
19
19
  * @param handler
20
20
  * @returns A function to deregister the handler
21
21
  */
@@ -24,6 +24,16 @@ export class Emitter {
24
24
  handler(value);
25
25
  });
26
26
  }
27
+ /**
28
+ * Registers a function to receive emitted values
29
+ * @param handler
30
+ * @returns A function to deregister the handler
31
+ */
32
+ apply(handler) {
33
+ return this.onListen((value) => {
34
+ handler(value);
35
+ });
36
+ }
27
37
  /**
28
38
  * Creates a chainable emitter that applies arbitrary transformation to values emitted by its parent
29
39
  * @param mapFunc
@@ -111,9 +121,9 @@ export class Emitter {
111
121
  * .fork(branch => {
112
122
  * branch
113
123
  * .map(s => `Loading: ${s}`)
114
- * .listen(s => document.title = s)
124
+ * .apply(s => document.title = s)
115
125
  * })
116
- * .listen(v => progressBar.style.width = v);
126
+ * .apply(v => progressBar.style.width = v);
117
127
  * ```
118
128
  * @param cb
119
129
  */
@@ -148,7 +158,7 @@ export class RangeProgression extends Emitter {
148
158
  * ```ts
149
159
  * range
150
160
  * .sample(["a", "b", "c"])
151
- * .listen(v => console.log(v));
161
+ * .apply(v => console.log(v));
152
162
  * // logs 'b' when a seek lands halfway through range
153
163
  * ```
154
164
  * @param source array to sample
@@ -174,7 +184,7 @@ export class RangeProgression extends Emitter {
174
184
  }
175
185
  return new RangeProgression(handler => this.onListen(progress => {
176
186
  const snapped = Math.round(progress * steps) / steps;
177
- handler(clamp(snapped));
187
+ handler(snapped);
178
188
  }));
179
189
  }
180
190
  /**
@@ -1,5 +1,5 @@
1
1
  import { Easer } from "./easing";
2
- import { Emitter, ListenFunc } from "./emitters";
2
+ import { Emitter, ListenFunc, UnsubscribeFunc } from "./emitters";
3
3
  import { TimelineRange } from "./range";
4
4
  import { Timeline } from "./timeline";
5
5
  export type PointEvent = {
@@ -41,4 +41,42 @@ export declare class TimelinePoint extends Emitter<PointEvent> {
41
41
  */
42
42
  seek(): void;
43
43
  seek(duration: number, easer?: Easer): Promise<void>;
44
+ /**
45
+ * Creates an emitter that only emits on forward-moving seeks
46
+ * @returns
47
+ */
48
+ forwardOnly(): Emitter<PointEvent>;
49
+ /**
50
+ * Creates an emitter that only emits on backward-moving seeks
51
+ * @returns
52
+ */
53
+ reverseOnly(): Emitter<PointEvent>;
54
+ /**
55
+ * Creates a Promise that will be resolved when the Timeline first seeks to/past this point
56
+ *
57
+ * The resolved value indicates the direction of the seek that triggered resolution
58
+ *
59
+ * @returns A Promise, resolved when the point is triggered by a seek
60
+ */
61
+ promise(): Promise<1 | -1>;
62
+ /**
63
+ * Registers a pair of functions to handle seeks that reach or pass this point, depending on seek direction
64
+ *
65
+ * @example
66
+ * ```
67
+ * point
68
+ * .applyDirectional(
69
+ * element.classList.add("faded"),
70
+ * element.classList.remove("faded"),
71
+ * );
72
+ * ```
73
+ *
74
+ * Note, for deterministic consistency, a forward-seek triggers points when it
75
+ * *passes or reaches* them, while a backward-seek triggers points when it
76
+ * *passes or departs from* them.
77
+ * @param apply Handler for forward-moving seeks that pass or reach this point
78
+ * @param revert Handler for backward-moving seeks that pass this point
79
+ * @returns A function to deregister both handlers
80
+ */
81
+ applyDirectional(apply: () => void, revert: () => void): UnsubscribeFunc;
44
82
  }
package/internal/point.js CHANGED
@@ -41,4 +41,67 @@ export class TimelinePoint extends Emitter {
41
41
  seek(duration = 0, easer) {
42
42
  return this.timeline.seek(this.position, duration, easer);
43
43
  }
44
+ /**
45
+ * Creates an emitter that only emits on forward-moving seeks
46
+ * @returns
47
+ */
48
+ forwardOnly() {
49
+ return new Emitter(handler => {
50
+ return this.onListen((ev) => {
51
+ if (ev.direction > 0)
52
+ handler(ev);
53
+ });
54
+ });
55
+ }
56
+ /**
57
+ * Creates an emitter that only emits on backward-moving seeks
58
+ * @returns
59
+ */
60
+ reverseOnly() {
61
+ return new Emitter(handler => {
62
+ return this.onListen((ev) => {
63
+ if (ev.direction < 0)
64
+ handler(ev);
65
+ });
66
+ });
67
+ }
68
+ /**
69
+ * Creates a Promise that will be resolved when the Timeline first seeks to/past this point
70
+ *
71
+ * The resolved value indicates the direction of the seek that triggered resolution
72
+ *
73
+ * @returns A Promise, resolved when the point is triggered by a seek
74
+ */
75
+ promise() {
76
+ return new Promise(resolve => {
77
+ let remove = this.apply((ev) => {
78
+ remove();
79
+ resolve(ev.direction);
80
+ });
81
+ });
82
+ }
83
+ /**
84
+ * Registers a pair of functions to handle seeks that reach or pass this point, depending on seek direction
85
+ *
86
+ * @example
87
+ * ```
88
+ * point
89
+ * .applyDirectional(
90
+ * element.classList.add("faded"),
91
+ * element.classList.remove("faded"),
92
+ * );
93
+ * ```
94
+ *
95
+ * Note, for deterministic consistency, a forward-seek triggers points when it
96
+ * *passes or reaches* them, while a backward-seek triggers points when it
97
+ * *passes or departs from* them.
98
+ * @param apply Handler for forward-moving seeks that pass or reach this point
99
+ * @param revert Handler for backward-moving seeks that pass this point
100
+ * @returns A function to deregister both handlers
101
+ */
102
+ applyDirectional(apply, revert) {
103
+ return this.onListen(eventData => eventData.direction > 0
104
+ ? apply()
105
+ : revert());
106
+ }
44
107
  }
@@ -32,8 +32,22 @@ export declare class TimelineRange extends RangeProgression {
32
32
  */
33
33
  spread(count: number): TimelinePoint[];
34
34
  /**
35
- * Progresses the Timeline across the range
36
- * @param easer
35
+ * Creates the specified number of ranges, each of `(parent.duration / count)` duration, spread
36
+ * evenly over this range
37
+ * @param count Number of sub-ranges to create
38
+ * @returns Array of sub-ranges
39
+ */
40
+ subdivide(count: number): TimelineRange[];
41
+ /**
42
+ * Creates a new range by offsetting the parent by a given time delta
43
+ * @param delta
44
+ * @returns Offset range
45
+ */
46
+ shift(delta: number): TimelineRange;
47
+ /**
48
+ * Progresses the Timeline across the range at 1000 units per second
49
+ * @param easer Optional easing function
50
+ * @returns Promise, resolved when the end is reached
37
51
  */
38
52
  play(easer?: Easer | keyof typeof easers): Promise<void>;
39
53
  /**
package/internal/range.js CHANGED
@@ -44,8 +44,27 @@ export class TimelineRange extends RangeProgression {
44
44
  ];
45
45
  }
46
46
  /**
47
- * Progresses the Timeline across the range
48
- * @param easer
47
+ * Creates the specified number of ranges, each of `(parent.duration / count)` duration, spread
48
+ * evenly over this range
49
+ * @param count Number of sub-ranges to create
50
+ * @returns Array of sub-ranges
51
+ */
52
+ subdivide(count) {
53
+ const duration = this.duration / count;
54
+ return Array.from({ length: count }, (_, i) => this.timeline.range(this.startPosition + i * duration, duration));
55
+ }
56
+ /**
57
+ * Creates a new range by offsetting the parent by a given time delta
58
+ * @param delta
59
+ * @returns Offset range
60
+ */
61
+ shift(delta) {
62
+ return this.timeline.range(this.startPosition + delta, this.duration);
63
+ }
64
+ /**
65
+ * Progresses the Timeline across the range at 1000 units per second
66
+ * @param easer Optional easing function
67
+ * @returns Promise, resolved when the end is reached
49
68
  */
50
69
  play(easer) {
51
70
  this.timeline.pause();
@@ -78,7 +97,7 @@ export class TimelineRange extends RangeProgression {
78
97
  */
79
98
  scale(factor, anchor = 0) {
80
99
  if (factor <= 0) {
81
- throw new RangeError('scale factor must be > 0');
100
+ throw new RangeError('Scale factor must be > 0');
82
101
  }
83
102
  const clampedAnchor = clamp(anchor, 0, 1);
84
103
  const oldLen = this.endPosition - this.startPosition;
@@ -184,7 +184,7 @@ export class Timeline {
184
184
  if (this.smoothSeeker !== null) {
185
185
  this.smoothSeeker.pause();
186
186
  // ensure any awaits are resolved for the previous seek
187
- this.smoothSeeker.seek(this.smoothSeeker.end);
187
+ this.smoothSeeker.end.seek();
188
188
  this.smoothSeeker = null;
189
189
  }
190
190
  if (duration === 0) {
@@ -193,8 +193,8 @@ export class Timeline {
193
193
  }
194
194
  const seeker = new Timeline(true);
195
195
  this.smoothSeeker = seeker;
196
- seeker.range(0, duration).ease(easer).tween(this.currentTime, toPosition).listen(v => this.seekDirect(v));
197
- return new Promise(r => seeker.end.listen(() => r()));
196
+ seeker.range(0, duration).ease(easer).tween(this.currentTime, toPosition).apply(v => this.seekDirect(v));
197
+ return new Promise(r => seeker.end.apply(() => r()));
198
198
  }
199
199
  seekDirect(toPosition) {
200
200
  const fromPosition = this._currentTime;
@@ -321,7 +321,7 @@ export class Timeline {
321
321
  const duration = typeof durationOrToPoint == "number"
322
322
  ? durationOrToPoint
323
323
  : (durationOrToPoint.position - startPosition);
324
- this.range(startPosition, duration).ease(easer).tween(from, to).listen(apply);
324
+ this.range(startPosition, duration).ease(easer).tween(from, to).apply(apply);
325
325
  return this.createChainingInterface(startPosition + duration);
326
326
  }
327
327
  at(position, action, reverse) {
@@ -329,7 +329,7 @@ export class Timeline {
329
329
  if (reverse === true)
330
330
  reverse = action;
331
331
  if (action)
332
- point.listen(reverse
332
+ point.apply(reverse
333
333
  ? (event => event.direction < 0 ? reverse() : action)
334
334
  : action);
335
335
  return this.createChainingInterface(point.position);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtia/timeline",
3
- "version": "1.0.12",
3
+ "version": "1.1.1",
4
4
  "repository": {
5
5
  "url": "https://github.com/tiadrop/timeline",
6
6
  "type": "github"