anim-engine 0.3.2 → 0.4.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.
Files changed (34) hide show
  1. package/README.md +7 -7
  2. package/dist/animation/create-animation.js +1 -1
  3. package/dist/animation/index.d.ts +1 -0
  4. package/dist/domain/color.d.ts +2 -0
  5. package/dist/domain/easing.js +1 -35
  6. package/dist/domain/index.d.ts +2 -2
  7. package/dist/domain/interpolation.d.ts +25 -0
  8. package/dist/domain/ticker.d.ts +0 -16
  9. package/dist/index.d.ts +10 -13
  10. package/dist/index.js +8 -7
  11. package/dist/lerp/create-lerp.d.ts +1 -8
  12. package/dist/lerp/create-lerp.js +1 -1
  13. package/dist/lerp/index.d.ts +1 -0
  14. package/dist/lerp-rgba/hex-to-rgba.d.ts +13 -0
  15. package/dist/lerp-rgba/hex-to-rgba.js +48 -0
  16. package/dist/lerp-rgba/index.d.ts +2 -0
  17. package/dist/lerp-rgba/lerp-rgba.d.ts +13 -0
  18. package/dist/{color/lerp-oklab.js → lerp-rgba/lerp-rgba.js} +3 -48
  19. package/dist/smooth-clamp/{smooth-clamp.js → create-smooth-clamp.js} +1 -1
  20. package/dist/smooth-clamp/index.d.ts +1 -0
  21. package/dist/smooth-damp/create-smooth-damp.d.ts +1 -9
  22. package/dist/smooth-damp/create-smooth-damp.js +1 -1
  23. package/dist/smooth-damp/index.d.ts +1 -0
  24. package/dist/spring/create-spring.d.ts +1 -10
  25. package/dist/spring/create-spring.js +1 -1
  26. package/dist/spring/index.d.ts +1 -0
  27. package/dist/ticker/get-ticker.d.ts +17 -0
  28. package/dist/{domain/ticker.js → ticker/get-ticker.js} +1 -1
  29. package/dist/ticker/index.d.ts +1 -0
  30. package/dist/timeline/create-timeline.js +3 -4
  31. package/dist/timeline/index.d.ts +1 -0
  32. package/package.json +1 -1
  33. package/dist/color/lerp-oklab.d.ts +0 -26
  34. /package/dist/smooth-clamp/{smooth-clamp.d.ts → create-smooth-clamp.d.ts} +0 -0
package/README.md CHANGED
@@ -81,7 +81,7 @@ By restricting itself to numeric values, the engine eliminates string parsing, c
81
81
  | 🧩 **Composable models** | Animations, keyframes, and timelines compose cleanly — put tweens inside timelines, nest keyframes anywhere. |
82
82
  | 🔄 **Continuous primitives** | Spring, smooth damp, and lerp chase live targets with zero setup — pass `() => value` for dynamic targets. |
83
83
  | 🚫 **No GC pressure** | Zero object allocations in hot update paths. State is mutated in place. |
84
- | 🎨 **Perceptual color** | Oklab interpolation via `lerpOklab` — no muddy browns. Compose it into any `onUpdate`. |
84
+ | 🎨 **Perceptual color** | Oklab interpolation via `lerpRgba` — no muddy browns. Compose it into any `onUpdate`. |
85
85
  | 📐 **TypeScript-first** | Full type exports, exhaustive discriminated unions, no `any`. |
86
86
  | 🔧 **Ticker control** | Bring your own game loop or use the built-in rAF ticker. Explicit — never auto-starts. |
87
87
 
@@ -112,7 +112,7 @@ Interpolations have `start()`/`stop()`/`kill()` controls, auto-start on creation
112
112
  | Primitive | Returns | Description |
113
113
  | ----------------------------------------- | -------------------- | --------------------------------------------- |
114
114
  | [`createSmoothClamp`](#createsmoothclamp) | `(n: number) => n` | Asymptotic clamp — saturates toward threshold |
115
- | [`lerpOklab` / `hexToRgba`](#color) | `RgbaTuple` / parser | Perceptually uniform color interpolation |
115
+ | [`lerpRgba` / `hexToRgba`](#color) | `RgbaTuple` / parser | Perceptually uniform color interpolation |
116
116
 
117
117
  ## Usage
118
118
 
@@ -381,7 +381,7 @@ Uses `threshold * (normalized / (1 + |normalized|))` for asymptotic saturation.
381
381
  Perceptually uniform Oklab interpolation. Straight RGB lerp produces muddy transitions — red→green goes through brown, blue→yellow goes through grey. Oklab matches human perception: equal steps look like equal changes.
382
382
 
383
383
  ```ts
384
- import { lerpOklab, hexToRgba } from "anim-engine";
384
+ import { lerpRgba, hexToRgba } from "anim-engine";
385
385
 
386
386
  hexToRgba("#ff6b6b"); // → [1, 0.42, 0.42, 1]
387
387
  hexToRgba("#f80"); // → [1, 0.533, 0, 1] (shorthand)
@@ -396,7 +396,7 @@ createAnimation({
396
396
  durationMs: 2000,
397
397
  ease: "outCubic",
398
398
  onUpdate: (t) => {
399
- const [r, g, b, a] = lerpOklab(fromColor, toColor, t);
399
+ const [r, g, b, a] = lerpRgba(fromColor, toColor, t);
400
400
  sprite.setColor(r, g, b, a);
401
401
  },
402
402
  });
@@ -405,7 +405,7 @@ createAnimation({
405
405
  **With continuous primitives** — drive the blend factor via spring, damp, or lerp:
406
406
 
407
407
  ```ts
408
- import { createSpring, lerpOklab, hexToRgba } from "anim-engine";
408
+ import { createSpring, lerpRgba, hexToRgba } from "anim-engine";
409
409
 
410
410
  const fromColor = hexToRgba("#ff6b6b");
411
411
  const toColor = hexToRgba("#4ecdc4");
@@ -416,7 +416,7 @@ const spring = createSpring({
416
416
  stiffness: 180,
417
417
  damping: 12,
418
418
  onUpdate: (t) => {
419
- const [r, g, b] = lerpOklab(fromColor, toColor, t);
419
+ const [r, g, b] = lerpRgba(fromColor, toColor, t);
420
420
  sprite.setColor(r, g, b, 1);
421
421
  },
422
422
  });
@@ -658,7 +658,7 @@ requestAnimationFrame(gameLoop);
658
658
  | `createSmoothClamp(threshold)` | Asymptotic clamp factory |
659
659
  | `getTicker()` | Singleton ticker |
660
660
  | `cubicBezier(p1x, p1y, p2x, p2y)` | Custom cubic bezier easing |
661
- | `lerpOklab(from, to, t)` | Oklab color interpolation |
661
+ | `lerpRgba(from, to, t)` | Oklab color interpolation |
662
662
  | `hexToRgba(hex)` | Parse hex color to normalized RGBA |
663
663
 
664
664
  ### Type exports
@@ -1,6 +1,6 @@
1
1
  import { resolveEasing } from "../domain/easing.js";
2
- import { getTicker } from "../domain/ticker.js";
3
2
  import { resolveValue } from "../domain/resolve-value.js";
3
+ import { getTicker } from "../ticker/get-ticker.js";
4
4
  import { createKeyframeRunner, createTweenRunner } from "./runner.js";
5
5
  //#region src/animation/create-animation.ts
6
6
  var isKeyframeMode = (options) => {
@@ -0,0 +1 @@
1
+ export { createAnimation } from './create-animation';
@@ -0,0 +1,2 @@
1
+ export type RgbaTuple = readonly [number, number, number, number];
2
+ export type LerpRgba = (from: RgbaTuple, to: RgbaTuple, progress: number) => RgbaTuple;
@@ -18,40 +18,6 @@ var bounceOut = (x) => {
18
18
  else if (x < 2.5 / d1) return n1 * (x -= 2.25 / d1) * x + .9375;
19
19
  else return n1 * (x -= 2.625 / d1) * x + .984375;
20
20
  };
21
- /** All 31 named easing identifiers, ordered by type. */
22
- var EASE_NAMES = [
23
- "linear",
24
- "inQuad",
25
- "outQuad",
26
- "inOutQuad",
27
- "inCubic",
28
- "outCubic",
29
- "inOutCubic",
30
- "inQuart",
31
- "outQuart",
32
- "inOutQuart",
33
- "inQuint",
34
- "outQuint",
35
- "inOutQuint",
36
- "inSine",
37
- "outSine",
38
- "inOutSine",
39
- "inExpo",
40
- "outExpo",
41
- "inOutExpo",
42
- "inCirc",
43
- "outCirc",
44
- "inOutCirc",
45
- "inBack",
46
- "outBack",
47
- "inOutBack",
48
- "inElastic",
49
- "outElastic",
50
- "inOutElastic",
51
- "inBounce",
52
- "outBounce",
53
- "inOutBounce"
54
- ];
55
21
  var EASING_FUNCTIONS = {
56
22
  linear: (x) => x,
57
23
  inQuad: (x) => x * x,
@@ -152,4 +118,4 @@ var cubicBezier = (p1x, p1y, p2x, p2y) => {
152
118
  };
153
119
  };
154
120
  //#endregion
155
- export { EASE_NAMES, EASING_FUNCTIONS, cubicBezier, resolveEasing };
121
+ export { EASING_FUNCTIONS, cubicBezier, resolveEasing };
@@ -1,10 +1,10 @@
1
1
  export type { AnimationStatus } from './animation';
2
- export type { InterpolationStatus, Interpolation } from './interpolation';
2
+ export type { InterpolationStatus, Interpolation, LerpOptions, SmoothDampOptions, SpringOptions, } from './interpolation';
3
3
  export type { EaseName, EaseFunction } from './easing';
4
4
  export { EASE_NAMES, cubicBezier, EASING_FUNCTIONS, resolveEasing } from './easing';
5
- export { getTicker } from './ticker';
6
5
  export type { Ticker, TickHandler } from './ticker';
7
6
  export { resolveValue } from './resolve-value';
8
7
  export type { DynamicValue } from './resolve-value';
9
8
  export type { Animation, AnimationOptions, SingleTweenOptions, KeyframeAnimationOptions, Keyframe, } from './animation';
10
9
  export type { TimelineLayer, Timeline } from './timeline';
10
+ export type { RgbaTuple, LerpRgba } from './color';
@@ -1,3 +1,4 @@
1
+ import { DynamicValue } from './resolve-value';
1
2
  export type InterpolationStatus = "active" | "inactive" | "dead";
2
3
  export type Interpolation = {
3
4
  start: () => void;
@@ -8,3 +9,27 @@ export type Interpolation = {
8
9
  velocity: number;
9
10
  status: InterpolationStatus;
10
11
  };
12
+ export type LerpOptions = {
13
+ to: () => number;
14
+ smoothTimeMs: DynamicValue;
15
+ precision?: number;
16
+ onUpdate?: (value: number, velocity: number) => void;
17
+ onEnded?: () => void;
18
+ };
19
+ export type SmoothDampOptions = {
20
+ to: () => number;
21
+ smoothTimeMs: DynamicValue;
22
+ maxSpeed?: DynamicValue;
23
+ precision?: number;
24
+ onUpdate?: (value: number, velocity: number) => void;
25
+ onEnded?: () => void;
26
+ };
27
+ export type SpringOptions = {
28
+ to: () => number;
29
+ stiffness?: DynamicValue;
30
+ damping?: DynamicValue;
31
+ mass?: DynamicValue;
32
+ precision?: number;
33
+ onUpdate?: (value: number, velocity: number) => void;
34
+ onEnded?: () => void;
35
+ };
@@ -6,19 +6,3 @@ export type Ticker = {
6
6
  add: (handler: TickHandler) => void;
7
7
  remove: (handler: TickHandler) => void;
8
8
  };
9
- /** Returns the default ticker singleton. Created lazily on first access. */
10
- export declare const getTicker: () => Ticker;
11
- /**
12
- * Create a ticker that drives active animations.
13
- *
14
- * Does NOT auto-start. The user must explicitly call either:
15
- * - `start()` — begins a `requestAnimationFrame` loop
16
- * - `update(deltaMs)` — drive manually from a game loop
17
- *
18
- * `add()` and `remove()` register/unregister animations without
19
- * side effects on the rAF loop.
20
- *
21
- * Uses a flat array with undefined-tombstone removal for safe concurrent
22
- * modification during iteration. Compacted after each frame.
23
- */
24
- export declare const createTicker: () => Ticker;
package/dist/index.d.ts CHANGED
@@ -1,13 +1,10 @@
1
- export { createAnimation } from './animation/create-animation';
2
- export { createTimeline } from './timeline/create-timeline';
3
- export { createSpring } from './spring/create-spring';
4
- export { createSmoothDamp } from './smooth-damp/create-smooth-damp';
5
- export { createLerp } from './lerp/create-lerp';
6
- export { createSmoothClamp } from './smooth-clamp/smooth-clamp';
7
- export { lerpOklab, hexToRgba } from './color/lerp-oklab';
8
- export { getTicker, EASE_NAMES, cubicBezier } from './domain';
9
- export type { EaseName, Interpolation, AnimationStatus, InterpolationStatus, DynamicValue, Animation, Keyframe, AnimationOptions, KeyframeAnimationOptions, TimelineLayer, Timeline, Ticker, } from './domain';
10
- export type { SpringOptions } from './spring/create-spring';
11
- export type { SmoothDampOptions } from './smooth-damp/create-smooth-damp';
12
- export type { LerpOptions } from './lerp/create-lerp';
13
- export type { RgbaTuple } from './color/lerp-oklab';
1
+ export { createAnimation } from './animation';
2
+ export { createTimeline } from './timeline';
3
+ export { createLerp } from './lerp';
4
+ export { createSmoothDamp } from './smooth-damp';
5
+ export { createSmoothClamp } from './smooth-clamp';
6
+ export { createSpring } from './spring';
7
+ export { lerpRgba, hexToRgba } from './lerp-rgba';
8
+ export { getTicker } from './ticker';
9
+ export { cubicBezier } from './domain';
10
+ export type { EaseName, Interpolation, AnimationStatus, InterpolationStatus, DynamicValue, Animation, Keyframe, AnimationOptions, KeyframeAnimationOptions, TimelineLayer, Timeline, Ticker, LerpOptions, SmoothDampOptions, SpringOptions, RgbaTuple, } from './domain';
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
- import { EASE_NAMES, cubicBezier } from "./domain/easing.js";
2
- import { getTicker } from "./domain/ticker.js";
1
+ import { cubicBezier } from "./domain/easing.js";
2
+ import { getTicker } from "./ticker/get-ticker.js";
3
3
  import { createAnimation } from "./animation/create-animation.js";
4
4
  import { createTimeline } from "./timeline/create-timeline.js";
5
- import { createSpring } from "./spring/create-spring.js";
6
- import { createSmoothDamp } from "./smooth-damp/create-smooth-damp.js";
7
5
  import { createLerp } from "./lerp/create-lerp.js";
8
- import { createSmoothClamp } from "./smooth-clamp/smooth-clamp.js";
9
- import { hexToRgba, lerpOklab } from "./color/lerp-oklab.js";
10
- export { EASE_NAMES, createAnimation, createLerp, createSmoothClamp, createSmoothDamp, createSpring, createTimeline, cubicBezier, getTicker, hexToRgba, lerpOklab };
6
+ import { createSmoothDamp } from "./smooth-damp/create-smooth-damp.js";
7
+ import { createSmoothClamp } from "./smooth-clamp/create-smooth-clamp.js";
8
+ import { createSpring } from "./spring/create-spring.js";
9
+ import { lerpRgba } from "./lerp-rgba/lerp-rgba.js";
10
+ import { hexToRgba } from "./lerp-rgba/hex-to-rgba.js";
11
+ export { createAnimation, createLerp, createSmoothClamp, createSmoothDamp, createSpring, createTimeline, cubicBezier, getTicker, hexToRgba, lerpRgba };
@@ -1,9 +1,2 @@
1
- import { Interpolation, DynamicValue } from '../domain';
2
- export type LerpOptions = {
3
- to: () => number;
4
- smoothTimeMs: DynamicValue;
5
- precision?: number;
6
- onUpdate?: (value: number, velocity: number) => void;
7
- onEnded?: () => void;
8
- };
1
+ import { Interpolation, LerpOptions } from '../domain';
9
2
  export declare const createLerp: (options: LerpOptions) => Interpolation;
@@ -1,5 +1,5 @@
1
- import { getTicker } from "../domain/ticker.js";
2
1
  import { resolveValue } from "../domain/resolve-value.js";
2
+ import { getTicker } from "../ticker/get-ticker.js";
3
3
  import { lerpStep } from "./step.js";
4
4
  //#region src/lerp/create-lerp.ts
5
5
  var createLerp = (options) => {
@@ -0,0 +1 @@
1
+ export { createLerp } from './create-lerp';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Parse a hex color string into an RGBA tuple.
3
+ *
4
+ * Accepts formats:
5
+ * - `#RGB`
6
+ * - `#RGBA`
7
+ * - `#RRGGBB`
8
+ * - `#RRGGBBAA`
9
+ *
10
+ * @param hex - Hex color string with optional leading `#`.
11
+ * @returns An RGBA tuple [R, G, B, A], each 0–1.
12
+ */
13
+ export declare const hexToRgba: (hex: string) => [number, number, number, number];
@@ -0,0 +1,48 @@
1
+ //#region src/lerp-rgba/hex-to-rgba.ts
2
+ /**
3
+ * Parse a hex color string into an RGBA tuple.
4
+ *
5
+ * Accepts formats:
6
+ * - `#RGB`
7
+ * - `#RGBA`
8
+ * - `#RRGGBB`
9
+ * - `#RRGGBBAA`
10
+ *
11
+ * @param hex - Hex color string with optional leading `#`.
12
+ * @returns An RGBA tuple [R, G, B, A], each 0–1.
13
+ */
14
+ var hexToRgba = (hex) => {
15
+ const cleaned = hex.startsWith("#") ? hex.slice(1) : hex;
16
+ if (!/^[0-9a-fA-F]+$/.test(cleaned)) return [
17
+ 0,
18
+ 0,
19
+ 0,
20
+ 1
21
+ ];
22
+ if (cleaned.length === 3) return [
23
+ parseInt(cleaned[0] + cleaned[0], 16) / 255,
24
+ parseInt(cleaned[1] + cleaned[1], 16) / 255,
25
+ parseInt(cleaned[2] + cleaned[2], 16) / 255,
26
+ 1
27
+ ];
28
+ if (cleaned.length === 4) return [
29
+ parseInt(cleaned[0] + cleaned[0], 16) / 255,
30
+ parseInt(cleaned[1] + cleaned[1], 16) / 255,
31
+ parseInt(cleaned[2] + cleaned[2], 16) / 255,
32
+ parseInt(cleaned[3] + cleaned[3], 16) / 255
33
+ ];
34
+ if (cleaned.length >= 6) return [
35
+ parseInt(cleaned.slice(0, 2), 16) / 255,
36
+ parseInt(cleaned.slice(2, 4), 16) / 255,
37
+ parseInt(cleaned.slice(4, 6), 16) / 255,
38
+ cleaned.length >= 8 ? parseInt(cleaned.slice(6, 8), 16) / 255 : 1
39
+ ];
40
+ return [
41
+ 0,
42
+ 0,
43
+ 0,
44
+ 1
45
+ ];
46
+ };
47
+ //#endregion
48
+ export { hexToRgba };
@@ -0,0 +1,2 @@
1
+ export { lerpRgba } from './lerp-rgba';
2
+ export { hexToRgba } from './hex-to-rgba';
@@ -0,0 +1,13 @@
1
+ import { LerpRgba } from '../domain';
2
+ /**
3
+ * Interpolate between two RGBA colors in Oklab space.
4
+ *
5
+ * The RGB channels are converted to Oklab, lerped perceptually uniformly,
6
+ * and converted back. The alpha channel is lerped linearly.
7
+ *
8
+ * @param from - Starting RGBA tuple [R, G, B, A], each 0–1.
9
+ * @param to - Ending RGBA tuple [R, G, B, A], each 0–1.
10
+ * @param progress - Interpolation factor (0 = from, 1 = to).
11
+ * @returns A new RGBA tuple [R, G, B, A], each 0–1.
12
+ */
13
+ export declare const lerpRgba: LerpRgba;
@@ -1,4 +1,4 @@
1
- //#region src/color/lerp-oklab.ts
1
+ //#region src/lerp-rgba/lerp-rgba.ts
2
2
  /**
3
3
  * Pre-computed constants for Oklab conversion.
4
4
  *
@@ -121,7 +121,7 @@ var clamp = (value) => {
121
121
  * @param progress - Interpolation factor (0 = from, 1 = to).
122
122
  * @returns A new RGBA tuple [R, G, B, A], each 0–1.
123
123
  */
124
- var lerpOklab = (from, to, progress) => {
124
+ var lerpRgba = (from, to, progress) => {
125
125
  const clampedProgress = clamp(progress);
126
126
  const [lFrom, aFrom, bFrom] = rgbToOklab(from[0], from[1], from[2]);
127
127
  const [lTo, aTo, bTo] = rgbToOklab(to[0], to[1], to[2]);
@@ -133,50 +133,5 @@ var lerpOklab = (from, to, progress) => {
133
133
  clamp(from[3] + (to[3] - from[3]) * clampedProgress)
134
134
  ];
135
135
  };
136
- /**
137
- * Parse a hex color string into an RGBA tuple.
138
- *
139
- * Accepts formats:
140
- * - `#RGB`
141
- * - `#RGBA`
142
- * - `#RRGGBB`
143
- * - `#RRGGBBAA`
144
- *
145
- * @param hex - Hex color string with optional leading `#`.
146
- * @returns An RGBA tuple [R, G, B, A], each 0–1.
147
- */
148
- var hexToRgba = (hex) => {
149
- const cleaned = hex.startsWith("#") ? hex.slice(1) : hex;
150
- if (!/^[0-9a-fA-F]+$/.test(cleaned)) return [
151
- 0,
152
- 0,
153
- 0,
154
- 1
155
- ];
156
- if (cleaned.length === 3) return [
157
- parseInt(cleaned[0] + cleaned[0], 16) / 255,
158
- parseInt(cleaned[1] + cleaned[1], 16) / 255,
159
- parseInt(cleaned[2] + cleaned[2], 16) / 255,
160
- 1
161
- ];
162
- if (cleaned.length === 4) return [
163
- parseInt(cleaned[0] + cleaned[0], 16) / 255,
164
- parseInt(cleaned[1] + cleaned[1], 16) / 255,
165
- parseInt(cleaned[2] + cleaned[2], 16) / 255,
166
- parseInt(cleaned[3] + cleaned[3], 16) / 255
167
- ];
168
- if (cleaned.length >= 6) return [
169
- parseInt(cleaned.slice(0, 2), 16) / 255,
170
- parseInt(cleaned.slice(2, 4), 16) / 255,
171
- parseInt(cleaned.slice(4, 6), 16) / 255,
172
- cleaned.length >= 8 ? parseInt(cleaned.slice(6, 8), 16) / 255 : 1
173
- ];
174
- return [
175
- 0,
176
- 0,
177
- 0,
178
- 1
179
- ];
180
- };
181
136
  //#endregion
182
- export { hexToRgba, lerpOklab };
137
+ export { lerpRgba };
@@ -1,4 +1,4 @@
1
- //#region src/smooth-clamp/smooth-clamp.ts
1
+ //#region src/smooth-clamp/create-smooth-clamp.ts
2
2
  /**
3
3
  * Creates a smooth clamp function that maps input toward a threshold
4
4
  * without ever exceeding it. Uses `x / (1 + |x|)` for a natural-feeling
@@ -0,0 +1 @@
1
+ export { createSmoothClamp } from './create-smooth-clamp';
@@ -1,10 +1,2 @@
1
- import { Interpolation, DynamicValue } from '../domain';
2
- export type SmoothDampOptions = {
3
- to: () => number;
4
- smoothTimeMs: DynamicValue;
5
- maxSpeed?: DynamicValue;
6
- precision?: number;
7
- onUpdate?: (value: number, velocity: number) => void;
8
- onEnded?: () => void;
9
- };
1
+ import { Interpolation, SmoothDampOptions } from '../domain';
10
2
  export declare const createSmoothDamp: (options: SmoothDampOptions) => Interpolation;
@@ -1,5 +1,5 @@
1
- import { getTicker } from "../domain/ticker.js";
2
1
  import { resolveValue } from "../domain/resolve-value.js";
2
+ import { getTicker } from "../ticker/get-ticker.js";
3
3
  import { smoothDampStep } from "./step.js";
4
4
  //#region src/smooth-damp/create-smooth-damp.ts
5
5
  var createSmoothDamp = (options) => {
@@ -0,0 +1 @@
1
+ export { createSmoothDamp } from './create-smooth-damp';
@@ -1,11 +1,2 @@
1
- import { Interpolation, DynamicValue } from '../domain';
2
- export type SpringOptions = {
3
- to: () => number;
4
- stiffness?: DynamicValue;
5
- damping?: DynamicValue;
6
- mass?: DynamicValue;
7
- precision?: number;
8
- onUpdate?: (value: number, velocity: number) => void;
9
- onEnded?: () => void;
10
- };
1
+ import { Interpolation, SpringOptions } from '../domain';
11
2
  export declare const createSpring: (options: SpringOptions) => Interpolation;
@@ -1,5 +1,5 @@
1
- import { getTicker } from "../domain/ticker.js";
2
1
  import { resolveValue } from "../domain/resolve-value.js";
2
+ import { getTicker } from "../ticker/get-ticker.js";
3
3
  import { verletStep } from "./verlet.js";
4
4
  //#region src/spring/create-spring.ts
5
5
  var createSpring = (options) => {
@@ -0,0 +1 @@
1
+ export { createSpring } from './create-spring';
@@ -0,0 +1,17 @@
1
+ import { Ticker } from '../domain';
2
+ /** Returns the default ticker singleton. Created lazily on first access. */
3
+ export declare const getTicker: () => Ticker;
4
+ /**
5
+ * Create a ticker that drives active animations.
6
+ *
7
+ * Does NOT auto-start. The user must explicitly call either:
8
+ * - `start()` — begins a `requestAnimationFrame` loop
9
+ * - `update(deltaMs)` — drive manually from a game loop
10
+ *
11
+ * `add()` and `remove()` register/unregister animations without
12
+ * side effects on the rAF loop.
13
+ *
14
+ * Uses a flat array with undefined-tombstone removal for safe concurrent
15
+ * modification during iteration. Compacted after each frame.
16
+ */
17
+ export declare const createTicker: () => Ticker;
@@ -1,4 +1,4 @@
1
- //#region src/domain/ticker.ts
1
+ //#region src/ticker/get-ticker.ts
2
2
  var singleton;
3
3
  /** Returns the default ticker singleton. Created lazily on first access. */
4
4
  var getTicker = () => {
@@ -0,0 +1 @@
1
+ export { getTicker } from './get-ticker';
@@ -1,9 +1,9 @@
1
1
  import { resolveEasing } from "../domain/easing.js";
2
- import { getTicker } from "../domain/ticker.js";
3
2
  import { resolveValue } from "../domain/resolve-value.js";
3
+ import { getTicker } from "../ticker/get-ticker.js";
4
4
  import { createKeyframeRunner } from "../animation/runner.js";
5
5
  //#region src/timeline/create-timeline.ts
6
- var noop = () => {};
6
+ var noOp = () => {};
7
7
  var buildFromConfigs = (rawLayers) => {
8
8
  const activeLayers = [];
9
9
  let previousEndAt = 0;
@@ -39,8 +39,7 @@ var buildFromConfigs = (rawLayers) => {
39
39
  };
40
40
  };
41
41
  var createTimeline = (layers, options) => {
42
- const { onStarted, onEnded } = options ?? {};
43
- const onProgress = options?.onProgress ?? noop;
42
+ const { onStarted, onEnded, onProgress = noOp } = options ?? {};
44
43
  const rawLayers = layers;
45
44
  let state = buildFromConfigs(rawLayers);
46
45
  let activeLayers = state.activeLayers;
@@ -0,0 +1 @@
1
+ export { createTimeline } from './create-timeline';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anim-engine",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "JavaScript library for animating numbers",
6
6
  "license": "MIT",
@@ -1,26 +0,0 @@
1
- export type RgbaTuple = readonly [number, number, number, number];
2
- /**
3
- * Interpolate between two RGBA colors in Oklab space.
4
- *
5
- * The RGB channels are converted to Oklab, lerped perceptually uniformly,
6
- * and converted back. The alpha channel is lerped linearly.
7
- *
8
- * @param from - Starting RGBA tuple [R, G, B, A], each 0–1.
9
- * @param to - Ending RGBA tuple [R, G, B, A], each 0–1.
10
- * @param progress - Interpolation factor (0 = from, 1 = to).
11
- * @returns A new RGBA tuple [R, G, B, A], each 0–1.
12
- */
13
- export declare const lerpOklab: (from: RgbaTuple, to: RgbaTuple, progress: number) => [number, number, number, number];
14
- /**
15
- * Parse a hex color string into an RGBA tuple.
16
- *
17
- * Accepts formats:
18
- * - `#RGB`
19
- * - `#RGBA`
20
- * - `#RRGGBB`
21
- * - `#RRGGBBAA`
22
- *
23
- * @param hex - Hex color string with optional leading `#`.
24
- * @returns An RGBA tuple [R, G, B, A], each 0–1.
25
- */
26
- export declare const hexToRgba: (hex: string) => [number, number, number, number];