coily 0.12.1 → 0.13.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.
@@ -4,78 +4,96 @@ interface SpringState {
4
4
  readonly velocity: number;
5
5
  }
6
6
  interface BaseOptions {
7
+ /**
8
+ * Decimal places of the resting threshold: a spring rests once its
9
+ * remaining motion cannot reach half a unit in the last place,
10
+ * 0.5 × 10⁻ᵖ. Values are never rounded — precision only decides rest.
11
+ * @default 2
12
+ */
13
+ readonly precision?: number | undefined;
14
+ }
15
+ interface WithMass {
7
16
  /**
8
17
  * Mass of the spring system.
9
18
  * @default 1
10
19
  */
11
- mass?: number | undefined;
20
+ readonly mass?: number | undefined;
21
+ }
22
+ interface WithoutMass {
12
23
  /**
13
- * Precision for resting threshold.
14
- * @default 2
24
+ * Mass is derived from the other parameters in this input shape
25
+ * and cannot be provided.
15
26
  */
16
- precision?: number | undefined;
27
+ readonly mass?: undefined;
17
28
  }
18
29
  interface WithTension {
19
30
  /**
20
31
  * Spring stiffness coefficient.
21
32
  * Must be greater than 0.
22
33
  */
23
- tension: number;
34
+ readonly tension: number;
24
35
  }
25
36
  interface WithDamping {
26
37
  /**
27
38
  * Viscous damping coefficient.
28
39
  * Must be greater than or equal to 0.
29
40
  */
30
- damping: number;
41
+ readonly damping: number;
31
42
  }
32
43
  interface WithDampingRatio {
33
44
  /**
34
45
  * Ratio of damping to critical damping (0 = undamped, 1 = critically damped).
35
46
  * Must be greater than or equal to 0.
36
47
  */
37
- dampingRatio: number;
48
+ readonly dampingRatio: number;
38
49
  }
39
50
  interface WithBounce {
40
51
  /**
41
52
  * Bounciness of the spring. Converted to dampingRatio as `1 - bounce`.
42
53
  * [-1, 1]
43
54
  */
44
- bounce: number;
55
+ readonly bounce: number;
45
56
  }
46
57
  interface WithDuration {
47
58
  /**
48
59
  * Target settle duration in milliseconds.
49
60
  * Must be greater than 0.
50
61
  */
51
- duration: number;
62
+ readonly duration: number;
52
63
  }
53
64
  interface WithDisplacement {
54
65
  /**
55
66
  * Initial displacement used for duration-based envelope calculation.
56
67
  * @default 1
57
68
  */
58
- displacement?: number | undefined;
69
+ readonly displacement?: number | undefined;
59
70
  }
60
- interface DirectOptions extends BaseOptions, WithTension, WithDamping {}
61
- interface TensionRatioOptions extends BaseOptions, WithTension, WithDampingRatio {}
62
- interface TensionBounceOptions extends BaseOptions, WithTension, WithBounce {}
63
- interface DampingRatioOptions extends BaseOptions, WithDamping, WithDampingRatio {}
64
- interface DampingBounceOptions extends BaseOptions, WithDamping, WithBounce {}
65
- interface TensionDampingRatioOptions extends BaseOptions, WithTension, WithDamping, WithDampingRatio {}
66
- interface TensionDampingBounceOptions extends BaseOptions, WithTension, WithDamping, WithBounce {}
67
- interface DurationOptions extends BaseOptions, WithDampingRatio, WithDuration, WithDisplacement {}
68
- interface BounceDurationOptions extends BaseOptions, WithBounce, WithDuration, WithDisplacement {}
69
- interface TensionDurationOptions extends BaseOptions, WithTension, WithDampingRatio, WithDuration, WithDisplacement {}
70
- interface TensionBounceDurationOptions extends BaseOptions, WithTension, WithBounce, WithDuration, WithDisplacement {}
71
- interface DampingDurationOptions extends BaseOptions, WithDamping, WithDampingRatio, WithDuration, WithDisplacement {}
72
- interface DampingBounceDurationOptions extends BaseOptions, WithDamping, WithBounce, WithDuration, WithDisplacement {}
73
- type SpringOptions = DirectOptions | TensionRatioOptions | TensionBounceOptions | DampingRatioOptions | DampingBounceOptions | TensionDampingRatioOptions | TensionDampingBounceOptions | DurationOptions | BounceDurationOptions | TensionDurationOptions | TensionBounceDurationOptions | DampingDurationOptions | DampingBounceDurationOptions;
71
+ interface DirectOptions extends BaseOptions, WithMass, WithTension, WithDamping {}
72
+ interface TensionRatioOptions extends BaseOptions, WithMass, WithTension, WithDampingRatio {}
73
+ interface TensionBounceOptions extends BaseOptions, WithMass, WithTension, WithBounce {}
74
+ interface DampingRatioOptions extends BaseOptions, WithMass, WithDamping, WithDampingRatio {}
75
+ interface DampingBounceOptions extends BaseOptions, WithMass, WithDamping, WithBounce {}
76
+ interface TensionDampingRatioOptions extends BaseOptions, WithoutMass, WithTension, WithDamping, WithDampingRatio {}
77
+ interface TensionDampingBounceOptions extends BaseOptions, WithoutMass, WithTension, WithDamping, WithBounce {}
78
+ interface DurationOptions extends BaseOptions, WithMass, WithDampingRatio, WithDuration, WithDisplacement {}
79
+ interface BounceDurationOptions extends BaseOptions, WithMass, WithBounce, WithDuration, WithDisplacement {}
80
+ interface TensionDurationOptions extends BaseOptions, WithoutMass, WithTension, WithDampingRatio, WithDuration, WithDisplacement {}
81
+ interface TensionBounceDurationOptions extends BaseOptions, WithoutMass, WithTension, WithBounce, WithDuration, WithDisplacement {}
82
+ interface DampingDurationOptions extends BaseOptions, WithoutMass, WithDamping, WithDampingRatio, WithDuration, WithDisplacement {}
83
+ interface DampingBounceDurationOptions extends BaseOptions, WithoutMass, WithDamping, WithBounce, WithDuration, WithDisplacement {}
84
+ type SpringOptionKeys = 'mass' | 'tension' | 'damping' | 'dampingRatio' | 'bounce' | 'duration' | 'displacement' | 'precision';
85
+ /**
86
+ * Marks every option key foreign to `T` as "absent or undefined", so mixing
87
+ * properties from different input shapes fails to type-check instead of
88
+ * silently resolving to an unintended shape at runtime.
89
+ */
90
+ type Exact<T> = T & { [K in Exclude<SpringOptionKeys, keyof T>]?: undefined; };
91
+ type SpringOptions = Exact<DirectOptions> | Exact<TensionRatioOptions> | Exact<TensionBounceOptions> | Exact<DampingRatioOptions> | Exact<DampingBounceOptions> | Exact<TensionDampingRatioOptions> | Exact<TensionDampingBounceOptions> | Exact<DurationOptions> | Exact<BounceDurationOptions> | Exact<TensionDurationOptions> | Exact<TensionBounceDurationOptions> | Exact<DampingDurationOptions> | Exact<DampingBounceDurationOptions>;
74
92
  /**
75
- * Immutable spring configuration.
93
+ * Immutable spring configuration. Instances are frozen — to change a spring's
94
+ * behavior, assign a new config via `spring.config`.
76
95
  */
77
96
  declare class SpringConfig {
78
- #private;
79
97
  static readonly default: SpringConfig;
80
98
  readonly mass: number;
81
99
  readonly tension: number;
@@ -84,11 +102,9 @@ declare class SpringConfig {
84
102
  readonly naturalFrequency: number;
85
103
  readonly criticalDamping: number;
86
104
  readonly dampingRatio: number;
87
- readonly precisionMultiplier: number;
105
+ /** Resting threshold in value units: half a unit in the last `precision` place. */
88
106
  readonly restingMagnitude: number;
89
107
  constructor(input: SpringOptions);
90
- static version(config: SpringConfig): number;
91
- static assign(target: SpringConfig, source: SpringConfig): void;
92
108
  /**
93
109
  * Analytically estimates the time remaining for a spring to come to rest,
94
110
  * given the current displacement and velocity.
@@ -114,43 +130,43 @@ declare class SpringConfig {
114
130
  * Direct physical parameters. You control stiffness and friction exactly;
115
131
  * mass defaults to 1.
116
132
  */
117
- declare function defineSpring(input: DirectOptions): SpringConfig;
133
+ declare function defineSpring(input: Exact<DirectOptions>): SpringConfig;
118
134
  /**
119
135
  * Tension sets the stiffness; dampingRatio controls oscillation character
120
136
  * (0 = undamped, 1 = critically damped, >1 = overdamped).
121
137
  * Damping is derived as `2 * dampingRatio * sqrt(mass * tension)`.
122
138
  */
123
- declare function defineSpring(input: TensionRatioOptions): SpringConfig;
139
+ declare function defineSpring(input: Exact<TensionRatioOptions>): SpringConfig;
124
140
  /**
125
141
  * Tension sets the stiffness; bounce controls how oscillatory the spring is,
126
142
  * from -1 (overdamped, no oscillation) to 1 (maximum bounce).
127
143
  * Damping is derived to match the requested bounciness.
128
144
  */
129
- declare function defineSpring(input: TensionBounceOptions): SpringConfig;
145
+ declare function defineSpring(input: Exact<TensionBounceOptions>): SpringConfig;
130
146
  /**
131
147
  * Damping is given directly; dampingRatio is used to derive tension
132
148
  * as `damping² / (4 * dampingRatio² * mass)`.
133
149
  * dampingRatio must be greater than 0.
134
150
  */
135
- declare function defineSpring(input: DampingRatioOptions): SpringConfig;
151
+ declare function defineSpring(input: Exact<DampingRatioOptions>): SpringConfig;
136
152
  /**
137
153
  * Damping is given directly; bounce controls how oscillatory the spring is.
138
154
  * Tension is derived to match the requested bounciness.
139
155
  * bounce must be less than 1.
140
156
  */
141
- declare function defineSpring(input: DampingBounceOptions): SpringConfig;
157
+ declare function defineSpring(input: Exact<DampingBounceOptions>): SpringConfig;
142
158
  /**
143
159
  * All three physical knobs specified — mass is derived
144
160
  * as `damping² / (4 * dampingRatio² * tension)`.
145
161
  * dampingRatio must be greater than 0.
146
162
  */
147
- declare function defineSpring(input: TensionDampingRatioOptions): SpringConfig;
163
+ declare function defineSpring(input: Exact<TensionDampingRatioOptions>): SpringConfig;
148
164
  /**
149
165
  * All three physical knobs specified — mass is derived
150
166
  * from tension, damping, and the requested bounciness.
151
167
  * bounce must be less than 1.
152
168
  */
153
- declare function defineSpring(input: TensionDampingBounceOptions): SpringConfig;
169
+ declare function defineSpring(input: Exact<TensionDampingBounceOptions>): SpringConfig;
154
170
  /**
155
171
  * Duration-based configuration. The spring is tuned so that its envelope
156
172
  * decays to the resting threshold within the given duration.
@@ -158,7 +174,7 @@ declare function defineSpring(input: TensionDampingBounceOptions): SpringConfig;
158
174
  * to match your actual animation range for accurate timing.
159
175
  * Tension and damping are both derived from dampingRatio and duration.
160
176
  */
161
- declare function defineSpring(input: DurationOptions): SpringConfig;
177
+ declare function defineSpring(input: Exact<DurationOptions>): SpringConfig;
162
178
  /**
163
179
  * Duration-based configuration. The spring is tuned so that its envelope
164
180
  * decays to the resting threshold within the given duration.
@@ -167,14 +183,14 @@ declare function defineSpring(input: DurationOptions): SpringConfig;
167
183
  * Bounce controls how oscillatory the motion is while settling.
168
184
  * Tension and damping are both derived.
169
185
  */
170
- declare function defineSpring(input: BounceDurationOptions): SpringConfig;
186
+ declare function defineSpring(input: Exact<BounceDurationOptions>): SpringConfig;
171
187
  /**
172
188
  * Duration-based with a tension constraint. Mass is derived from tension
173
189
  * and the computed natural frequency; damping follows from mass and dampingRatio.
174
190
  * Duration assumes a displacement of 1 by default — provide `displacement`
175
191
  * to match your actual animation range for accurate timing.
176
192
  */
177
- declare function defineSpring(input: TensionDurationOptions): SpringConfig;
193
+ declare function defineSpring(input: Exact<TensionDurationOptions>): SpringConfig;
178
194
  /**
179
195
  * Duration-based with a tension constraint. Bounce controls how oscillatory
180
196
  * the motion is while settling. Mass is derived from tension and the
@@ -182,14 +198,14 @@ declare function defineSpring(input: TensionDurationOptions): SpringConfig;
182
198
  * Duration assumes a displacement of 1 by default — provide `displacement`
183
199
  * to match your actual animation range for accurate timing.
184
200
  */
185
- declare function defineSpring(input: TensionBounceDurationOptions): SpringConfig;
201
+ declare function defineSpring(input: Exact<TensionBounceDurationOptions>): SpringConfig;
186
202
  /**
187
203
  * Duration-based with a damping constraint. Mass is derived from damping,
188
204
  * dampingRatio, and the computed natural frequency; tension follows from mass.
189
205
  * Duration assumes a displacement of 1 by default — provide `displacement`
190
206
  * to match your actual animation range for accurate timing.
191
207
  */
192
- declare function defineSpring(input: DampingDurationOptions): SpringConfig;
208
+ declare function defineSpring(input: Exact<DampingDurationOptions>): SpringConfig;
193
209
  /**
194
210
  * Duration-based with a damping constraint. Bounce controls how oscillatory
195
211
  * the motion is while settling. Mass is derived from damping and the
@@ -197,11 +213,21 @@ declare function defineSpring(input: DampingDurationOptions): SpringConfig;
197
213
  * Duration assumes a displacement of 1 by default — provide `displacement`
198
214
  * to match your actual animation range for accurate timing.
199
215
  */
200
- declare function defineSpring(input: DampingBounceDurationOptions): SpringConfig;
216
+ declare function defineSpring(input: Exact<DampingBounceDurationOptions>): SpringConfig;
217
+ //#endregion
218
+ //#region src/flush-queue.d.ts
219
+ declare class FlushQueue {
220
+ #private;
221
+ request(callback: () => void): void;
222
+ batch(fn: () => void): void;
223
+ enter(): void;
224
+ exit(): void;
225
+ }
201
226
  //#endregion
202
227
  //#region src/motion.d.ts
203
228
  declare class Motion {
204
229
  #private;
230
+ _pass: number;
205
231
  constructor(config: SpringConfig, position: number, velocity: number);
206
232
  get position(): number;
207
233
  set position(value: number);
@@ -211,18 +237,25 @@ declare class Motion {
211
237
  get isResting(): boolean;
212
238
  configure(config: SpringConfig): void;
213
239
  tick(dt: number, emit?: boolean): void;
240
+ finish(): void;
214
241
  onUpdate(callback: () => void): () => void;
215
242
  onStart(callback: () => void): () => void;
216
243
  onStop(callback: () => void): () => void;
244
+ onDispose(callback: () => void): () => void;
217
245
  dispose(): void;
218
246
  }
219
247
  //#endregion
220
248
  //#region src/motion-set.d.ts
221
249
  declare class MotionSet {
222
250
  #private;
251
+ reduced: boolean;
252
+ onWake: (() => void) | null;
253
+ readonly flushes: FlushQueue;
223
254
  constructor(debug?: boolean);
255
+ get size(): number;
224
256
  add(motion: Motion): void;
225
257
  remove(motion: Motion): void;
258
+ finishAll(): void;
226
259
  tick(dt: number): void;
227
260
  }
228
261
  //#endregion
@@ -255,99 +288,99 @@ declare class Spring {
255
288
  set config(value: SpringConfig | null);
256
289
  get timeRemaining(): number;
257
290
  get isResting(): boolean;
291
+ get settled(): Promise<void>;
258
292
  jumpTo(value: number): void;
259
293
  dispose(): void;
260
294
  onUpdate(callback: () => void): () => void;
261
295
  onStart(callback: () => void): () => void;
262
296
  onStop(callback: () => void): () => void;
297
+ onDispose(callback: () => void): () => void;
263
298
  }
264
299
  //#endregion
265
- //#region src/vector2.d.ts
266
- interface Vector2 {
267
- x: number;
268
- y: number;
269
- }
270
- //#endregion
271
- //#region src/spring2d.d.ts
272
- interface Spring2DWithOffset {
273
- spring: Spring2D;
274
- offset?: Vector2 | undefined;
275
- }
276
- type Spring2DTarget = Vector2 | Spring2D | Spring2DWithOffset;
277
- interface DisplacedSpring2DPosition {
278
- target?: Spring2DTarget | undefined;
279
- value?: Vector2 | undefined;
300
+ //#region src/spring-object.d.ts
301
+ /**
302
+ * Compile-time validation of a value shape: every channel must be a `number`,
303
+ * every branch a plain object or array with at least one channel. Used as
304
+ * `value: T & Shape<T>` so an invalid channel errors on that property rather
305
+ * than on the whole argument. Purely structural — interfaces satisfy it
306
+ * without index signatures — and mirrored by the runtime
307
+ * validation for untyped callers. Optional and `undefined`-typed channels
308
+ * are rejected: a channel that may be absent would make two springs of the
309
+ * same declared shape structurally incompatible at runtime.
310
+ */
311
+ type Shape<T> = 0 extends 1 & T ? T : T extends number ? number : T extends ((...args: never) => unknown) | (abstract new (...args: never) => unknown) ? never : T extends readonly never[] ? never : T extends object ? keyof T extends never ? never : { [K in keyof T]-?: 0 extends 1 & T[K] ? T[K] : undefined extends T[K] ? never : Shape<T[K]>; } : never;
312
+ /**
313
+ * A partial view of a value shape: the same nesting with any subset of the
314
+ * numeric channels present. Absent (or `undefined`) channels are left alone.
315
+ */
316
+ type PartialShape<T> = T extends number ? number : { readonly [K in keyof T]?: PartialShape<T[K]> | undefined; };
317
+ /**
318
+ * A deep-readonly view of a value shape. Composite reads (`target`, `value`,
319
+ * `velocity`) return the spring's live mirror objects — refreshed in place
320
+ * on every read — so their channels are typed read-only.
321
+ */
322
+ type ReadonlyShape<T> = T extends number ? number : { readonly [K in keyof T]: ReadonlyShape<T[K]>; };
323
+ /**
324
+ * Configuration for a spring object: a single `SpringConfig` applied to every
325
+ * channel, or an object mirroring the value shape with configs at any level.
326
+ * A config at a subtree applies to every channel below it; deeper configs win.
327
+ * `null` reverts to the default config (or the leader's while following).
328
+ * Configs are always `SpringConfig` instances (from `defineSpring`), so a
329
+ * plain object is unambiguously a config shape and any non-config leaf it
330
+ * reaches is an error.
331
+ */
332
+ type ConfigShape<T> = SpringConfig | null | (T extends number ? never : { readonly [K in keyof T]?: ConfigShape<T[K]> | undefined; });
333
+ interface SpringObjectWithOffset<T extends object> {
334
+ readonly spring: SpringObject<T>;
335
+ readonly offset?: PartialShape<T> | undefined;
280
336
  }
281
- type Spring2DPosition = Vector2 | DisplacedSpring2DPosition;
282
- declare class Spring2D {
337
+ type SpringObjectTarget<T extends object> = PartialShape<T> | SpringObject<T> | SpringObjectWithOffset<T>;
338
+ declare class SpringObject<in out T extends object> {
283
339
  #private;
284
- constructor(motions: MotionSet, position: Spring2DPosition, config?: SpringConfig);
285
- get target(): Vector2;
286
- set target(value: Spring2DTarget);
287
- get value(): Readonly<Vector2>;
288
- set value(value: Vector2);
289
- get velocity(): Readonly<Vector2>;
290
- set velocity(value: Vector2);
340
+ constructor(motions: MotionSet, value: T & Shape<T>, config?: ConfigShape<T>);
341
+ get target(): ReadonlyShape<T>;
342
+ set target(value: SpringObjectTarget<T>);
343
+ get value(): ReadonlyShape<T>;
344
+ set value(value: PartialShape<T>);
345
+ get velocity(): ReadonlyShape<T>;
346
+ set velocity(value: PartialShape<T>);
291
347
  get config(): SpringConfig | null;
292
- get mass(): number;
293
- get tension(): number;
294
- get damping(): number;
295
- get dampingRatio(): number;
296
- get precision(): number;
297
- set config(value: SpringConfig | null);
348
+ set config(value: ConfigShape<T>);
298
349
  get timeRemaining(): number;
299
350
  get isResting(): boolean;
300
- jumpTo(value: Vector2): void;
351
+ get settled(): Promise<void>;
352
+ jumpTo(value: PartialShape<T>): void;
301
353
  dispose(): void;
302
354
  onUpdate(callback: () => void): () => void;
303
355
  onStart(callback: () => void): () => void;
304
356
  onStop(callback: () => void): () => void;
357
+ onDispose(callback: () => void): () => void;
305
358
  }
306
359
  //#endregion
307
360
  //#region src/ticker.d.ts
308
361
  interface TickerOptions {
309
- /**
310
- * The target frames per second for the simulation loop
311
- *
312
- * must be greater than 0, defaults to 60
313
- */
314
- fps?: number | undefined;
315
- /**
316
- * The maximum elapsed time (in ms) before a frame is considered a lag spike
317
- * (e.g. from a backgrounded tab). When exceeded, `adjustedLag` is used instead
318
- * of the real elapsed time. Set to 0 to disable lag detection.
319
- *
320
- * must be greater than or equal to 0, defaults to 500
321
- */
322
- lagThreshold?: number | undefined;
323
- /**
324
- * The substitute elapsed time (in ms) used when a lag spike is detected.
325
- * Clamped to be at most `lagThreshold`.
326
- *
327
- * must be greater than or equal to 0, defaults to 33
328
- */
329
- adjustedLag?: number | undefined;
362
+ readonly fps?: number | undefined;
363
+ readonly lagThreshold?: number | undefined;
364
+ readonly adjustedLag?: number | undefined;
330
365
  }
331
366
  //#endregion
332
367
  //#region src/system.d.ts
333
368
  interface SpringSystemOptions extends TickerOptions {
334
369
  debug?: boolean | undefined;
370
+ reducedMotion?: 'user' | 'always' | 'never' | undefined;
335
371
  }
336
372
  interface SpringSystem {
337
373
  createSpring(position: SpringPosition, config?: SpringConfig): Spring;
338
- createSpring2D(position: Spring2DPosition, config?: SpringConfig): Spring2D;
339
- /** Advance all springs by `dt` milliseconds, without affecting internal timing. */
374
+ createSpringObject<T extends object>(value: T & Shape<T>, config?: ConfigShape<T>): SpringObject<T>;
340
375
  advance(dt: number): void;
341
- /** Start the animation loop. */
342
376
  start(): void;
343
- /** Stop the animation loop. */
344
377
  stop(): void;
345
- /** Whether the animation loop is currently running. */
346
378
  readonly running: boolean;
379
+ readonly reducedMotion: boolean;
347
380
  fps: number;
348
381
  lagThreshold: number;
349
382
  adjustedLag: number;
350
383
  }
351
384
  declare function createSpringSystem(options?: SpringSystemOptions): SpringSystem;
352
385
  //#endregion
353
- export { defineSpring as _, Spring2D as a, Spring2DWithOffset as c, SpringPosition as d, SpringTarget as f, SpringState as g, SpringOptions as h, TickerOptions as i, Vector2 as l, SpringConfig as m, SpringSystemOptions as n, Spring2DPosition as o, SpringWithOffset as p, createSpringSystem as r, Spring2DTarget as s, SpringSystem as t, Spring as u };
386
+ export { SpringOptions as _, ConfigShape as a, Shape as c, SpringObjectWithOffset as d, Spring as f, SpringConfig as g, SpringWithOffset as h, TickerOptions as i, SpringObject as l, SpringTarget as m, SpringSystemOptions as n, PartialShape as o, SpringPosition as p, createSpringSystem as r, ReadonlyShape as s, SpringSystem as t, SpringObjectTarget as u, SpringState as v, defineSpring as y };