@xtia/timeline 1.0.11 → 1.0.12
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 +11 -0
- package/internal/emitters.d.ts +14 -0
- package/internal/emitters.js +21 -1
- package/internal/point.d.ts +4 -1
- package/internal/point.js +1 -1
- package/internal/tween.d.ts +4 -2
- package/internal/tween.js +23 -10
- package/internal/utils.d.ts +1 -1
- package/internal/utils.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -483,6 +483,13 @@ Creates a [`TimelineRange`](#timelinerange-interface) on the Timeline to which t
|
|
|
483
483
|
|
|
484
484
|
Creates a `TimelinePoint` at an offset from the this point.
|
|
485
485
|
|
|
486
|
+
##### `seek(): void`
|
|
487
|
+
|
|
488
|
+
Seeks the parent Timeline to this point.
|
|
489
|
+
|
|
490
|
+
##### `seek(duration: number, easer?: Easer): Promise<void>`
|
|
491
|
+
|
|
492
|
+
Smooth-seeks the parent Timeline to this point over a specified duration and resolves the returned Promise on completion.
|
|
486
493
|
|
|
487
494
|
|
|
488
495
|
|
|
@@ -593,6 +600,10 @@ blend(from: this, to: this, progress: number): this
|
|
|
593
600
|
|
|
594
601
|
Creates an emitter that quantises progression emitted by the parent to the nearest of `steps` discrete values.
|
|
595
602
|
|
|
603
|
+
##### `sample<T>(values: ArrayLike<T>): `[`Emitter<T>`](#emittert-interface)
|
|
604
|
+
|
|
605
|
+
Creates an emitter that emits values from an array according to progression.
|
|
606
|
+
|
|
596
607
|
##### `threshold(threshold): RangeProgression`
|
|
597
608
|
|
|
598
609
|
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`.
|
package/internal/emitters.d.ts
CHANGED
|
@@ -125,6 +125,20 @@ export declare class RangeProgression extends Emitter<number> {
|
|
|
125
125
|
*/
|
|
126
126
|
tween<T extends Tweenable>(from: T, to: T): Emitter<T>;
|
|
127
127
|
tween<T extends BlendableWith<T, R>, R>(from: T, to: R): Emitter<T>;
|
|
128
|
+
/**
|
|
129
|
+
* Creates a chainable emitter that takes a value from an array according to progression
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* range
|
|
134
|
+
* .sample(["a", "b", "c"])
|
|
135
|
+
* .listen(v => console.log(v));
|
|
136
|
+
* // logs 'b' when a seek lands halfway through range
|
|
137
|
+
* ```
|
|
138
|
+
* @param source array to sample
|
|
139
|
+
* @returns Listenable: emits the sampled values
|
|
140
|
+
*/
|
|
141
|
+
sample<T>(source: ArrayLike<T>): Emitter<T>;
|
|
128
142
|
/**
|
|
129
143
|
* Creates a chainable progress emitter that quantises progress, as emitted by its parent, to the nearest of `steps` discrete values.
|
|
130
144
|
*
|
package/internal/emitters.js
CHANGED
|
@@ -141,6 +141,26 @@ export class RangeProgression extends Emitter {
|
|
|
141
141
|
const tween = createTween(from, to);
|
|
142
142
|
return new Emitter(handler => this.onListen(progress => handler(tween(progress))));
|
|
143
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Creates a chainable emitter that takes a value from an array according to progression
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* range
|
|
150
|
+
* .sample(["a", "b", "c"])
|
|
151
|
+
* .listen(v => console.log(v));
|
|
152
|
+
* // logs 'b' when a seek lands halfway through range
|
|
153
|
+
* ```
|
|
154
|
+
* @param source array to sample
|
|
155
|
+
* @returns Listenable: emits the sampled values
|
|
156
|
+
*/
|
|
157
|
+
sample(source) {
|
|
158
|
+
return new Emitter(handler => this.onListen(progress => {
|
|
159
|
+
const clampedProgress = clamp(progress);
|
|
160
|
+
const index = Math.floor(clampedProgress * (source.length - 1));
|
|
161
|
+
handler(source[index]);
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
144
164
|
/**
|
|
145
165
|
* Creates a chainable progress emitter that quantises progress, as emitted by its parent, to the nearest of `steps` discrete values.
|
|
146
166
|
*
|
|
@@ -154,7 +174,7 @@ export class RangeProgression extends Emitter {
|
|
|
154
174
|
}
|
|
155
175
|
return new RangeProgression(handler => this.onListen(progress => {
|
|
156
176
|
const snapped = Math.round(progress * steps) / steps;
|
|
157
|
-
handler(clamp(snapped
|
|
177
|
+
handler(clamp(snapped));
|
|
158
178
|
}));
|
|
159
179
|
}
|
|
160
180
|
/**
|
package/internal/point.d.ts
CHANGED
|
@@ -36,6 +36,9 @@ export declare class TimelinePoint extends Emitter<PointEvent> {
|
|
|
36
36
|
* @returns Listenable: emits a PointEvent when the point is reached or passed by a Timeline seek
|
|
37
37
|
*/
|
|
38
38
|
delta(timeOffset: number): TimelinePoint;
|
|
39
|
+
/**
|
|
40
|
+
* Seeks the parent Timeline to this point
|
|
41
|
+
*/
|
|
39
42
|
seek(): void;
|
|
40
|
-
seek(duration
|
|
43
|
+
seek(duration: number, easer?: Easer): Promise<void>;
|
|
41
44
|
}
|
package/internal/point.js
CHANGED
|
@@ -39,6 +39,6 @@ export class TimelinePoint extends Emitter {
|
|
|
39
39
|
return this.timeline.point(this.position + timeOffset);
|
|
40
40
|
}
|
|
41
41
|
seek(duration = 0, easer) {
|
|
42
|
-
this.timeline.seek(this.position, duration, easer);
|
|
42
|
+
return this.timeline.seek(this.position, duration, easer);
|
|
43
43
|
}
|
|
44
44
|
}
|
package/internal/tween.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ export interface Blendable {
|
|
|
7
7
|
export interface BlendableWith<T, R> {
|
|
8
8
|
blend(target: R, progress: number): T;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
export declare function createTween<T extends
|
|
10
|
+
type TweenFunc<T> = (progress: number) => T;
|
|
11
|
+
export declare function createTween<T extends Tweenable>(from: T, to: T): TweenFunc<T>;
|
|
12
|
+
export declare function createTween<T extends BlendableWith<T, R>, R>(from: T, to: R): TweenFunc<T>;
|
|
13
|
+
export {};
|
package/internal/tween.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { clamp } from "./utils";
|
|
2
|
+
const tokenTypes = {
|
|
3
|
+
none: 0,
|
|
4
|
+
number: 1,
|
|
5
|
+
colour: 2,
|
|
6
|
+
};
|
|
2
7
|
export function createTween(from, to) {
|
|
3
8
|
if (from === to)
|
|
4
9
|
return () => from;
|
|
@@ -24,8 +29,9 @@ function createStringTween(from, to) {
|
|
|
24
29
|
if (tokenCount !== toChunks.filter(c => c.token).length) {
|
|
25
30
|
return createStringMerge(from, to);
|
|
26
31
|
}
|
|
27
|
-
// where token prefix mismatch, use merging
|
|
28
|
-
if (fromChunks.some((chunk, i) => toChunks[i].prefix !== chunk.prefix
|
|
32
|
+
// where token prefix/type mismatch, use merging
|
|
33
|
+
if (fromChunks.some((chunk, i) => toChunks[i].prefix !== chunk.prefix ||
|
|
34
|
+
toChunks[i].type !== chunk.type)) {
|
|
29
35
|
return createStringMerge(from, to);
|
|
30
36
|
}
|
|
31
37
|
// convert token chunks to individual string tween funcs
|
|
@@ -33,9 +39,9 @@ function createStringTween(from, to) {
|
|
|
33
39
|
const fromToken = chunk.token;
|
|
34
40
|
const toToken = toChunks[i].token;
|
|
35
41
|
const prefix = chunk.prefix;
|
|
36
|
-
if (
|
|
42
|
+
if (chunk.type === tokenTypes.none)
|
|
37
43
|
return () => prefix;
|
|
38
|
-
if (
|
|
44
|
+
if (chunk.type === tokenTypes.colour) {
|
|
39
45
|
const fromColour = parseColour(fromToken);
|
|
40
46
|
const toColour = parseColour(toToken);
|
|
41
47
|
return progress => prefix + blendColours(fromColour, toColour, progress);
|
|
@@ -65,7 +71,7 @@ function createStringMerge(from, to) {
|
|
|
65
71
|
if (!to)
|
|
66
72
|
return () => from;
|
|
67
73
|
const split = (s) => {
|
|
68
|
-
// prefer Intl.Segmenter if available (Node
|
|
74
|
+
// prefer Intl.Segmenter if available (Node 14, modern browsers)
|
|
69
75
|
if (typeof Intl !== "undefined" && Intl.Segmenter) {
|
|
70
76
|
const seg = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
71
77
|
return Array.from(seg.segment(s), (seg) => seg.segment);
|
|
@@ -86,7 +92,7 @@ function createStringMerge(from, to) {
|
|
|
86
92
|
const fromP = pad(a);
|
|
87
93
|
const toP = pad(b);
|
|
88
94
|
return (progress) => {
|
|
89
|
-
const clampedProgress = clamp(progress
|
|
95
|
+
const clampedProgress = clamp(progress);
|
|
90
96
|
const replaceCount = Math.floor(clampedProgress * maxLen);
|
|
91
97
|
const result = new Array(maxLen);
|
|
92
98
|
for (let i = 0; i < maxLen; ++i) {
|
|
@@ -122,20 +128,27 @@ function blendColours(from, to, bias) {
|
|
|
122
128
|
return ("#" + blended.map(n => Math.round(n).toString(16).padStart(2, "0")).join("")).replace(/ff$/, "");
|
|
123
129
|
}
|
|
124
130
|
const tweenableTokenRegex = /(#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b|[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)/g;
|
|
125
|
-
|
|
131
|
+
function tokenise(s) {
|
|
126
132
|
const chunks = [];
|
|
127
133
|
let lastIdx = 0;
|
|
128
134
|
let m;
|
|
129
135
|
while ((m = tweenableTokenRegex.exec(s))) {
|
|
130
136
|
const token = m[0];
|
|
131
137
|
const prefix = s.slice(lastIdx, m.index); // literal before token
|
|
132
|
-
|
|
138
|
+
const type = getTokenType(token);
|
|
139
|
+
chunks.push({ prefix, token, type });
|
|
133
140
|
lastIdx = m.index + token.length;
|
|
134
141
|
}
|
|
135
142
|
// trailing literal after the last token – stored as a final chunk
|
|
136
143
|
const tail = s.slice(lastIdx);
|
|
137
144
|
if (tail.length) {
|
|
138
|
-
chunks.push({ prefix: tail, token: "" });
|
|
145
|
+
chunks.push({ prefix: tail, token: "", type: tokenTypes.none });
|
|
139
146
|
}
|
|
140
147
|
return chunks;
|
|
141
|
-
}
|
|
148
|
+
}
|
|
149
|
+
;
|
|
150
|
+
function getTokenType(token) {
|
|
151
|
+
if (token.startsWith("#"))
|
|
152
|
+
return tokenTypes.colour;
|
|
153
|
+
return tokenTypes.number;
|
|
154
|
+
}
|
package/internal/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export declare const clamp: (value: number, min
|
|
2
|
+
export declare const clamp: (value: number, min?: number, max?: number) => number;
|
|
3
3
|
/** @internal */
|
|
4
4
|
export type Widen<T> = T extends number ? number : T extends string ? string : T;
|
package/internal/utils.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
2
|
+
export const clamp = (value, min = 0, max = 1) => Math.min(Math.max(value, min), max);
|