coily 0.12.2 → 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,75 +4,94 @@ 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
97
  static readonly default: SpringConfig;
@@ -83,7 +102,7 @@ declare class SpringConfig {
83
102
  readonly naturalFrequency: number;
84
103
  readonly criticalDamping: number;
85
104
  readonly dampingRatio: number;
86
- readonly precisionMultiplier: number;
105
+ /** Resting threshold in value units: half a unit in the last `precision` place. */
87
106
  readonly restingMagnitude: number;
88
107
  constructor(input: SpringOptions);
89
108
  /**
@@ -111,43 +130,43 @@ declare class SpringConfig {
111
130
  * Direct physical parameters. You control stiffness and friction exactly;
112
131
  * mass defaults to 1.
113
132
  */
114
- declare function defineSpring(input: DirectOptions): SpringConfig;
133
+ declare function defineSpring(input: Exact<DirectOptions>): SpringConfig;
115
134
  /**
116
135
  * Tension sets the stiffness; dampingRatio controls oscillation character
117
136
  * (0 = undamped, 1 = critically damped, >1 = overdamped).
118
137
  * Damping is derived as `2 * dampingRatio * sqrt(mass * tension)`.
119
138
  */
120
- declare function defineSpring(input: TensionRatioOptions): SpringConfig;
139
+ declare function defineSpring(input: Exact<TensionRatioOptions>): SpringConfig;
121
140
  /**
122
141
  * Tension sets the stiffness; bounce controls how oscillatory the spring is,
123
142
  * from -1 (overdamped, no oscillation) to 1 (maximum bounce).
124
143
  * Damping is derived to match the requested bounciness.
125
144
  */
126
- declare function defineSpring(input: TensionBounceOptions): SpringConfig;
145
+ declare function defineSpring(input: Exact<TensionBounceOptions>): SpringConfig;
127
146
  /**
128
147
  * Damping is given directly; dampingRatio is used to derive tension
129
148
  * as `damping² / (4 * dampingRatio² * mass)`.
130
149
  * dampingRatio must be greater than 0.
131
150
  */
132
- declare function defineSpring(input: DampingRatioOptions): SpringConfig;
151
+ declare function defineSpring(input: Exact<DampingRatioOptions>): SpringConfig;
133
152
  /**
134
153
  * Damping is given directly; bounce controls how oscillatory the spring is.
135
154
  * Tension is derived to match the requested bounciness.
136
155
  * bounce must be less than 1.
137
156
  */
138
- declare function defineSpring(input: DampingBounceOptions): SpringConfig;
157
+ declare function defineSpring(input: Exact<DampingBounceOptions>): SpringConfig;
139
158
  /**
140
159
  * All three physical knobs specified — mass is derived
141
160
  * as `damping² / (4 * dampingRatio² * tension)`.
142
161
  * dampingRatio must be greater than 0.
143
162
  */
144
- declare function defineSpring(input: TensionDampingRatioOptions): SpringConfig;
163
+ declare function defineSpring(input: Exact<TensionDampingRatioOptions>): SpringConfig;
145
164
  /**
146
165
  * All three physical knobs specified — mass is derived
147
166
  * from tension, damping, and the requested bounciness.
148
167
  * bounce must be less than 1.
149
168
  */
150
- declare function defineSpring(input: TensionDampingBounceOptions): SpringConfig;
169
+ declare function defineSpring(input: Exact<TensionDampingBounceOptions>): SpringConfig;
151
170
  /**
152
171
  * Duration-based configuration. The spring is tuned so that its envelope
153
172
  * decays to the resting threshold within the given duration.
@@ -155,7 +174,7 @@ declare function defineSpring(input: TensionDampingBounceOptions): SpringConfig;
155
174
  * to match your actual animation range for accurate timing.
156
175
  * Tension and damping are both derived from dampingRatio and duration.
157
176
  */
158
- declare function defineSpring(input: DurationOptions): SpringConfig;
177
+ declare function defineSpring(input: Exact<DurationOptions>): SpringConfig;
159
178
  /**
160
179
  * Duration-based configuration. The spring is tuned so that its envelope
161
180
  * decays to the resting threshold within the given duration.
@@ -164,14 +183,14 @@ declare function defineSpring(input: DurationOptions): SpringConfig;
164
183
  * Bounce controls how oscillatory the motion is while settling.
165
184
  * Tension and damping are both derived.
166
185
  */
167
- declare function defineSpring(input: BounceDurationOptions): SpringConfig;
186
+ declare function defineSpring(input: Exact<BounceDurationOptions>): SpringConfig;
168
187
  /**
169
188
  * Duration-based with a tension constraint. Mass is derived from tension
170
189
  * and the computed natural frequency; damping follows from mass and dampingRatio.
171
190
  * Duration assumes a displacement of 1 by default — provide `displacement`
172
191
  * to match your actual animation range for accurate timing.
173
192
  */
174
- declare function defineSpring(input: TensionDurationOptions): SpringConfig;
193
+ declare function defineSpring(input: Exact<TensionDurationOptions>): SpringConfig;
175
194
  /**
176
195
  * Duration-based with a tension constraint. Bounce controls how oscillatory
177
196
  * the motion is while settling. Mass is derived from tension and the
@@ -179,14 +198,14 @@ declare function defineSpring(input: TensionDurationOptions): SpringConfig;
179
198
  * Duration assumes a displacement of 1 by default — provide `displacement`
180
199
  * to match your actual animation range for accurate timing.
181
200
  */
182
- declare function defineSpring(input: TensionBounceDurationOptions): SpringConfig;
201
+ declare function defineSpring(input: Exact<TensionBounceDurationOptions>): SpringConfig;
183
202
  /**
184
203
  * Duration-based with a damping constraint. Mass is derived from damping,
185
204
  * dampingRatio, and the computed natural frequency; tension follows from mass.
186
205
  * Duration assumes a displacement of 1 by default — provide `displacement`
187
206
  * to match your actual animation range for accurate timing.
188
207
  */
189
- declare function defineSpring(input: DampingDurationOptions): SpringConfig;
208
+ declare function defineSpring(input: Exact<DampingDurationOptions>): SpringConfig;
190
209
  /**
191
210
  * Duration-based with a damping constraint. Bounce controls how oscillatory
192
211
  * the motion is while settling. Mass is derived from damping and the
@@ -194,11 +213,21 @@ declare function defineSpring(input: DampingDurationOptions): SpringConfig;
194
213
  * Duration assumes a displacement of 1 by default — provide `displacement`
195
214
  * to match your actual animation range for accurate timing.
196
215
  */
197
- 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
+ }
198
226
  //#endregion
199
227
  //#region src/motion.d.ts
200
228
  declare class Motion {
201
229
  #private;
230
+ _pass: number;
202
231
  constructor(config: SpringConfig, position: number, velocity: number);
203
232
  get position(): number;
204
233
  set position(value: number);
@@ -208,18 +237,25 @@ declare class Motion {
208
237
  get isResting(): boolean;
209
238
  configure(config: SpringConfig): void;
210
239
  tick(dt: number, emit?: boolean): void;
240
+ finish(): void;
211
241
  onUpdate(callback: () => void): () => void;
212
242
  onStart(callback: () => void): () => void;
213
243
  onStop(callback: () => void): () => void;
244
+ onDispose(callback: () => void): () => void;
214
245
  dispose(): void;
215
246
  }
216
247
  //#endregion
217
248
  //#region src/motion-set.d.ts
218
249
  declare class MotionSet {
219
250
  #private;
251
+ reduced: boolean;
252
+ onWake: (() => void) | null;
253
+ readonly flushes: FlushQueue;
220
254
  constructor(debug?: boolean);
255
+ get size(): number;
221
256
  add(motion: Motion): void;
222
257
  remove(motion: Motion): void;
258
+ finishAll(): void;
223
259
  tick(dt: number): void;
224
260
  }
225
261
  //#endregion
@@ -252,99 +288,99 @@ declare class Spring {
252
288
  set config(value: SpringConfig | null);
253
289
  get timeRemaining(): number;
254
290
  get isResting(): boolean;
291
+ get settled(): Promise<void>;
255
292
  jumpTo(value: number): void;
256
293
  dispose(): void;
257
294
  onUpdate(callback: () => void): () => void;
258
295
  onStart(callback: () => void): () => void;
259
296
  onStop(callback: () => void): () => void;
297
+ onDispose(callback: () => void): () => void;
260
298
  }
261
299
  //#endregion
262
- //#region src/vector2.d.ts
263
- interface Vector2 {
264
- x: number;
265
- y: number;
266
- }
267
- //#endregion
268
- //#region src/spring2d.d.ts
269
- interface Spring2DWithOffset {
270
- spring: Spring2D;
271
- offset?: Vector2 | undefined;
272
- }
273
- type Spring2DTarget = Vector2 | Spring2D | Spring2DWithOffset;
274
- interface DisplacedSpring2DPosition {
275
- target?: Spring2DTarget | undefined;
276
- 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;
277
336
  }
278
- type Spring2DPosition = Vector2 | DisplacedSpring2DPosition;
279
- declare class Spring2D {
337
+ type SpringObjectTarget<T extends object> = PartialShape<T> | SpringObject<T> | SpringObjectWithOffset<T>;
338
+ declare class SpringObject<in out T extends object> {
280
339
  #private;
281
- constructor(motions: MotionSet, position: Spring2DPosition, config?: SpringConfig);
282
- get target(): Vector2;
283
- set target(value: Spring2DTarget);
284
- get value(): Readonly<Vector2>;
285
- set value(value: Vector2);
286
- get velocity(): Readonly<Vector2>;
287
- 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>);
288
347
  get config(): SpringConfig | null;
289
- get mass(): number;
290
- get tension(): number;
291
- get damping(): number;
292
- get dampingRatio(): number;
293
- get precision(): number;
294
- set config(value: SpringConfig | null);
348
+ set config(value: ConfigShape<T>);
295
349
  get timeRemaining(): number;
296
350
  get isResting(): boolean;
297
- jumpTo(value: Vector2): void;
351
+ get settled(): Promise<void>;
352
+ jumpTo(value: PartialShape<T>): void;
298
353
  dispose(): void;
299
354
  onUpdate(callback: () => void): () => void;
300
355
  onStart(callback: () => void): () => void;
301
356
  onStop(callback: () => void): () => void;
357
+ onDispose(callback: () => void): () => void;
302
358
  }
303
359
  //#endregion
304
360
  //#region src/ticker.d.ts
305
361
  interface TickerOptions {
306
- /**
307
- * The target frames per second for the simulation loop
308
- *
309
- * must be greater than 0, defaults to 60
310
- */
311
- fps?: number | undefined;
312
- /**
313
- * The maximum elapsed time (in ms) before a frame is considered a lag spike
314
- * (e.g. from a backgrounded tab). When exceeded, `adjustedLag` is used instead
315
- * of the real elapsed time. Set to 0 to disable lag detection.
316
- *
317
- * must be greater than or equal to 0, defaults to 500
318
- */
319
- lagThreshold?: number | undefined;
320
- /**
321
- * The substitute elapsed time (in ms) used when a lag spike is detected.
322
- * Clamped to be at most `lagThreshold`.
323
- *
324
- * must be greater than or equal to 0, defaults to 33
325
- */
326
- adjustedLag?: number | undefined;
362
+ readonly fps?: number | undefined;
363
+ readonly lagThreshold?: number | undefined;
364
+ readonly adjustedLag?: number | undefined;
327
365
  }
328
366
  //#endregion
329
367
  //#region src/system.d.ts
330
368
  interface SpringSystemOptions extends TickerOptions {
331
369
  debug?: boolean | undefined;
370
+ reducedMotion?: 'user' | 'always' | 'never' | undefined;
332
371
  }
333
372
  interface SpringSystem {
334
373
  createSpring(position: SpringPosition, config?: SpringConfig): Spring;
335
- createSpring2D(position: Spring2DPosition, config?: SpringConfig): Spring2D;
336
- /** Advance all springs by `dt` milliseconds, without affecting internal timing. */
374
+ createSpringObject<T extends object>(value: T & Shape<T>, config?: ConfigShape<T>): SpringObject<T>;
337
375
  advance(dt: number): void;
338
- /** Start the animation loop. */
339
376
  start(): void;
340
- /** Stop the animation loop. */
341
377
  stop(): void;
342
- /** Whether the animation loop is currently running. */
343
378
  readonly running: boolean;
379
+ readonly reducedMotion: boolean;
344
380
  fps: number;
345
381
  lagThreshold: number;
346
382
  adjustedLag: number;
347
383
  }
348
384
  declare function createSpringSystem(options?: SpringSystemOptions): SpringSystem;
349
385
  //#endregion
350
- 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 };