coily 0.15.0 → 0.16.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.
- package/README.md +131 -55
- package/dist/{config-OOMMRdK8.d.ts → config-B8M2xp26.d.ts} +103 -120
- package/dist/css.d.ts +85 -57
- package/dist/css.js +58 -34
- package/dist/index.d.ts +3 -3
- package/dist/index.js +98 -65
- package/dist/nuxt.d.ts +20 -19
- package/dist/nuxt.js +15 -5
- package/dist/{solver-CVXOTDkZ.js → solver-CAXuxdKj.js} +22 -14
- package/dist/system-C7PbI4L0.d.ts +1213 -0
- package/dist/{system-Br_cPnaN.js → system-WejqGkfv.js} +1948 -1216
- package/dist/vue.d.ts +224 -129
- package/dist/vue.js +161 -41
- package/package.json +1 -1
- package/dist/system-Du_fXXmO.d.ts +0 -940
|
@@ -0,0 +1,1213 @@
|
|
|
1
|
+
import { t as SpringDefinition } from "./config-B8M2xp26.js";
|
|
2
|
+
//#region src/flush-queue.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Defers callbacks while inside a batch or tick. At depth 0, `request`
|
|
5
|
+
* runs the callback immediately. Otherwise it queues the callback, once
|
|
6
|
+
* per callback, until the outermost exit. Composite springs use it to
|
|
7
|
+
* merge per-channel events into composite ones.
|
|
8
|
+
*/
|
|
9
|
+
declare class FlushQueue {
|
|
10
|
+
#private;
|
|
11
|
+
request(callback: () => void): void;
|
|
12
|
+
batch(fn: () => void): void;
|
|
13
|
+
enter(): void;
|
|
14
|
+
exit(): void;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/motion.d.ts
|
|
18
|
+
/**
|
|
19
|
+
* Something the system advances frame by frame: a spring's `SpringMotion`
|
|
20
|
+
* or a ramp's `RampMotion`. `MotionSet` ticks motions and `FollowGraph`
|
|
21
|
+
* orders them through the members declared here. Owners keep their motion
|
|
22
|
+
* in a private field, so none of this reaches the public api.
|
|
23
|
+
*
|
|
24
|
+
* A tick runs in two phases. Every moving motion first advances silently,
|
|
25
|
+
* so followers recouple against frame-current values. Then each motion
|
|
26
|
+
* that advanced delivers its events in `endFrame`.
|
|
27
|
+
*/
|
|
28
|
+
declare abstract class Motion {
|
|
29
|
+
/**
|
|
30
|
+
* Creation order across every kind of motion. The lower id goes first
|
|
31
|
+
* wherever motions need a deterministic order and nothing else decides.
|
|
32
|
+
*/
|
|
33
|
+
readonly id: number;
|
|
34
|
+
/**
|
|
35
|
+
* The last ordered pass that advanced the motion, written by
|
|
36
|
+
* `MotionSet`, so a motion queued twice in one pass advances once.
|
|
37
|
+
*/
|
|
38
|
+
pass: number;
|
|
39
|
+
/**
|
|
40
|
+
* The last ordered frame that advanced the motion, written by
|
|
41
|
+
* `MotionSet`. Sub-steps share one frame, and the first advance in it
|
|
42
|
+
* queues the motion for `endFrame`.
|
|
43
|
+
*/
|
|
44
|
+
frame: number;
|
|
45
|
+
/**
|
|
46
|
+
* Dependency rank, written by `FollowGraph`. Motions in the follow
|
|
47
|
+
* graph count up from 0, leaders before followers. -1 marks a motion
|
|
48
|
+
* outside the graph.
|
|
49
|
+
*/
|
|
50
|
+
rank: number;
|
|
51
|
+
/**
|
|
52
|
+
* The edge this motion follows through, or null. `FollowGraph` writes
|
|
53
|
+
* it. Only a spring follows.
|
|
54
|
+
*/
|
|
55
|
+
edge: FollowEdge | null;
|
|
56
|
+
/**
|
|
57
|
+
* The edges that read this motion, or null when none do. `FollowGraph`
|
|
58
|
+
* rebuilds them with the ranks, so they can lag a mid-pass edge change
|
|
59
|
+
* until the next recompute. The tick tolerates stale entries.
|
|
60
|
+
*/
|
|
61
|
+
followers: FollowEdge[] | null;
|
|
62
|
+
/** Whether the motion has stopped moving. `MotionSet` drops it once true. */
|
|
63
|
+
abstract get isResting(): boolean;
|
|
64
|
+
/** The current velocity, in value units per second. */
|
|
65
|
+
abstract get velocity(): number;
|
|
66
|
+
/** The current acceleration, in value units per second squared. */
|
|
67
|
+
abstract get acceleration(): number;
|
|
68
|
+
/** Advances by `h` seconds and emits nothing. Events wait for `endFrame`. */
|
|
69
|
+
abstract advance(h: number): void;
|
|
70
|
+
/** Delivers the frame's events, after every motion has advanced. */
|
|
71
|
+
abstract endFrame(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Applies a change of the system's reduced-motion setting, which
|
|
74
|
+
* `MotionSet.reduced` already holds. A motion whose purpose is
|
|
75
|
+
* `'nonmotion'` ignores it.
|
|
76
|
+
*/
|
|
77
|
+
abstract applyReducedMotion(reduced: boolean): void;
|
|
78
|
+
/**
|
|
79
|
+
* How far the motion sits from steady tracking. A follower's `plan`
|
|
80
|
+
* reads it from its leader as the sub-step controller's shock signal.
|
|
81
|
+
* A motion that nothing can knock off its course returns 0.
|
|
82
|
+
*/
|
|
83
|
+
abstract manifoldDeviation(): number;
|
|
84
|
+
/**
|
|
85
|
+
* Whether the motion's slope changes at a known moment within the next
|
|
86
|
+
* `dt` seconds. Planning from history can't foresee that, so a
|
|
87
|
+
* follower's `plan` demands the sub-step cap on that frame.
|
|
88
|
+
*/
|
|
89
|
+
abstract kinksWithin(dt: number): boolean;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/follow-graph.d.ts
|
|
93
|
+
/**
|
|
94
|
+
* The sub-step controller's history of one followed value: its last
|
|
95
|
+
* observed value, `delta`, and `curvature`.
|
|
96
|
+
*/
|
|
97
|
+
declare class TargetTrail {
|
|
98
|
+
#private;
|
|
99
|
+
constructor(value: number);
|
|
100
|
+
/** The change between the last two observed values. */
|
|
101
|
+
get delta(): number;
|
|
102
|
+
/** The latest `delta` minus the one before it. 0 while the value moves in a straight line. */
|
|
103
|
+
get curvature(): number;
|
|
104
|
+
/** Records this frame's value and returns the change since the last one. */
|
|
105
|
+
observe(value: number): number;
|
|
106
|
+
/** Restarts the trail at `value` without recording a change. */
|
|
107
|
+
anchor(value: number): void;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* One follow relationship: the motion that retargets, the motions it
|
|
111
|
+
* reads, how to re-anchor it, and the sub-step controller's per-edge
|
|
112
|
+
* state. `Spring` registers one when it follows a source with resolvable
|
|
113
|
+
* motions, and unregisters it on unfollow and dispose.
|
|
114
|
+
*/
|
|
115
|
+
interface FollowEdge {
|
|
116
|
+
/** The motion that retargets when its leaders advance. */
|
|
117
|
+
readonly follower: Motion;
|
|
118
|
+
/** The distinct motions behind the followed source, per `resolveLeaderMotions`. */
|
|
119
|
+
readonly leaders: readonly Motion[];
|
|
120
|
+
/**
|
|
121
|
+
* Whether the follower shares a Tarjan SCC with any leader, self-follow
|
|
122
|
+
* included. `FollowGraph` writes it on recompute. A cyclic edge stays on
|
|
123
|
+
* ZOH (zero-order hold) and never arms a slope, because FOH (first-order
|
|
124
|
+
* hold) destabilizes cycles that are stable under ZOH.
|
|
125
|
+
*/
|
|
126
|
+
cyclic: boolean;
|
|
127
|
+
/** The follower's target as `plan` observes it once per frame. */
|
|
128
|
+
readonly trail: TargetTrail;
|
|
129
|
+
/**
|
|
130
|
+
* Re-anchors the follower to the followed source's current value before
|
|
131
|
+
* an advance of `h` seconds (the internal tick unit). A reduced-motion
|
|
132
|
+
* jump rests the follower on the new target and emits nothing. Its
|
|
133
|
+
* `endFrame` delivers the events in the settle sweep. An acyclic edge
|
|
134
|
+
* with passthrough arrival and `h > 0` retargets and arms the follower's
|
|
135
|
+
* slope at the delta over `h`, so the advance integrates against the
|
|
136
|
+
* leader's motion. Every other edge retargets exactly as the
|
|
137
|
+
* leader-update handler does (finite guard, rebase).
|
|
138
|
+
*/
|
|
139
|
+
recouple(h: number): void;
|
|
140
|
+
/**
|
|
141
|
+
* Refreshes the estimator from the follower's current target and
|
|
142
|
+
* returns the edge's unclamped sub-step demand for a frame of `dt`
|
|
143
|
+
* seconds. The caller clamps the max over edges. Runs no user code:
|
|
144
|
+
* history comes from `trail`, freshness from leader motion state. Call
|
|
145
|
+
* it at most once per edge per frame, before any motion advances.
|
|
146
|
+
*/
|
|
147
|
+
plan(dt: number): number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The follow graph: one edge per following motion, and a cached
|
|
151
|
+
* dependency rank over every motion the edges touch. `MotionSet` owns
|
|
152
|
+
* one. This class writes `edge`, `followers`, and `rank` onto the
|
|
153
|
+
* motions, where the tick reads them.
|
|
154
|
+
*/
|
|
155
|
+
declare class FollowGraph {
|
|
156
|
+
#private;
|
|
157
|
+
/** Whether no edges are registered. The tick then skips all ordering work. */
|
|
158
|
+
get isEmpty(): boolean;
|
|
159
|
+
/** Every registered edge, current as of the last `ensureOrder`. */
|
|
160
|
+
get edges(): readonly FollowEdge[];
|
|
161
|
+
/**
|
|
162
|
+
* Registers `edge`, replacing any edge with the same follower: a
|
|
163
|
+
* spring follows at most one source at a time.
|
|
164
|
+
*/
|
|
165
|
+
addEdge(edge: FollowEdge): void;
|
|
166
|
+
/** Drops the edge whose follower is `follower`, if one is registered. */
|
|
167
|
+
removeEdge(follower: Motion): void;
|
|
168
|
+
/**
|
|
169
|
+
* Recomputes ranks if an edge was added or removed since the last call.
|
|
170
|
+
* Afterward, motions the graph touches rank up from 0, every leader
|
|
171
|
+
* before its followers, and motions outside it hold -1. Cycle members
|
|
172
|
+
* rank in ascending creation id. Ranks depend on graph structure and
|
|
173
|
+
* creation order, never on wiring order.
|
|
174
|
+
*/
|
|
175
|
+
ensureOrder(): void;
|
|
176
|
+
}
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/motion-set.d.ts
|
|
179
|
+
/**
|
|
180
|
+
* The set of motions the tick advances. A motion leaves when it rests and
|
|
181
|
+
* re-enters on any write that disturbs it. A ramp is in the set only
|
|
182
|
+
* while something watches it frame by frame. `onWake` fires when the set
|
|
183
|
+
* becomes non-empty, waking a sleeping ticker.
|
|
184
|
+
*/
|
|
185
|
+
declare class MotionSet {
|
|
186
|
+
#private;
|
|
187
|
+
reduced: boolean;
|
|
188
|
+
onWake: (() => void) | null;
|
|
189
|
+
/**
|
|
190
|
+
* The coupling error budget, in value units: the local per-frame error
|
|
191
|
+
* the sub-step controller targets on each follow edge, floored by the
|
|
192
|
+
* follower's resting magnitude. `SpringSystem` validates and exposes it
|
|
193
|
+
* as the `couplingTolerance` option and property.
|
|
194
|
+
*/
|
|
195
|
+
couplingTolerance: number;
|
|
196
|
+
readonly flushes: FlushQueue;
|
|
197
|
+
/** Follow edges registered by following springs, with the dependency rank over their motions. */
|
|
198
|
+
readonly graph: FollowGraph;
|
|
199
|
+
/**
|
|
200
|
+
* Motions a reduced-motion change must reach while out of the tick: a
|
|
201
|
+
* `'motion'` ramp that moves on the clock unwatched, or one holding
|
|
202
|
+
* still under reduced motion. Each member keeps its membership current.
|
|
203
|
+
*/
|
|
204
|
+
readonly reducible: Set<Motion>;
|
|
205
|
+
/**
|
|
206
|
+
* Returns the idle wall time, in seconds, the clock has not counted yet.
|
|
207
|
+
* Null when no ticker counts idle time. The ticker installs it, and
|
|
208
|
+
* moves the total in with `credit` on its first frame after starting or
|
|
209
|
+
* waking, and when it stops.
|
|
210
|
+
*/
|
|
211
|
+
idleTime: (() => number) | null;
|
|
212
|
+
constructor(debug?: boolean);
|
|
213
|
+
get size(): number;
|
|
214
|
+
/**
|
|
215
|
+
* The system clock in seconds, which ramps read their position from. It
|
|
216
|
+
* moves only forward: by each tick's `dt` when the advance phase ends,
|
|
217
|
+
* and by idle wall time while the ticker sleeps. Wall time is read once
|
|
218
|
+
* per microtask checkpoint, so the clock holds still through
|
|
219
|
+
* synchronous code.
|
|
220
|
+
*/
|
|
221
|
+
get time(): number;
|
|
222
|
+
/**
|
|
223
|
+
* The id of the tick whose advance phase is running, or 0 between
|
|
224
|
+
* phases. A ramp steps a cached value through the sub-steps of the
|
|
225
|
+
* phase and reads its anchor formula everywhere else.
|
|
226
|
+
*/
|
|
227
|
+
get advancing(): number;
|
|
228
|
+
/** Adds idle wall time to the clock, in seconds. */
|
|
229
|
+
credit(seconds: number): void;
|
|
230
|
+
add(motion: Motion): void;
|
|
231
|
+
remove(motion: Motion): void;
|
|
232
|
+
/**
|
|
233
|
+
* Whether the motion is in the set. A motion that rests mid-pass leaves
|
|
234
|
+
* before its own `endFrame`, so motions ask here rather than track it.
|
|
235
|
+
*/
|
|
236
|
+
has(motion: Motion): boolean;
|
|
237
|
+
/**
|
|
238
|
+
* Applies a reduced-motion change to the `reducible` registry first,
|
|
239
|
+
* because a ramp's jump retargets its followers, then to every moving
|
|
240
|
+
* motion, leaders before followers. A motion reached twice changes once.
|
|
241
|
+
*/
|
|
242
|
+
setReduced(reduced: boolean): void;
|
|
243
|
+
tick(dt: number): void;
|
|
244
|
+
}
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/spring-source.d.ts
|
|
247
|
+
/**
|
|
248
|
+
* The property key that brands a `SpringSource` and holds the api its
|
|
249
|
+
* followers read. It is a registry symbol
|
|
250
|
+
* (`Symbol.for('coily/spring-source')`), so one copy of coily
|
|
251
|
+
* recognizes sources from another when a bundle duplicates the library.
|
|
252
|
+
*/
|
|
253
|
+
declare const SpringSourceSymbol: unique symbol;
|
|
254
|
+
/**
|
|
255
|
+
* What a source exposes to its followers, held under `SpringSourceSymbol`
|
|
256
|
+
* on the source object. Followers read `value` on every update and
|
|
257
|
+
* detach on dispose.
|
|
258
|
+
*/
|
|
259
|
+
interface SpringSourceApi<T = number> {
|
|
260
|
+
/** The current value, in value units. */
|
|
261
|
+
readonly value: T;
|
|
262
|
+
/** Subscribes to value changes. Returns an unsubscribe function. */
|
|
263
|
+
onUpdate(callback: () => void): () => void;
|
|
264
|
+
/** Subscribes to the source being released. Returns an unsubscribe function. */
|
|
265
|
+
onDispose(callback: () => void): () => void;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* A live value of type `T` that a spring can animate toward or derive
|
|
269
|
+
* from. Assign a scalar source (`T = number`, the default) to
|
|
270
|
+
* `Spring.target`, and the spring tracks it with its momentum intact.
|
|
271
|
+
*
|
|
272
|
+
* Every `Spring` and `Ramp` is a `SpringSource`, and every
|
|
273
|
+
* `CompositeSpring` is a `SpringSource` of its value shape. `mapSpring`,
|
|
274
|
+
* `velocityOf`, `accelerationOf`, and `targetOf` derive new sources from
|
|
275
|
+
* existing ones. Use the type to name such a value in your own
|
|
276
|
+
* signatures.
|
|
277
|
+
*/
|
|
278
|
+
interface SpringSource<T = number> {
|
|
279
|
+
readonly [SpringSourceSymbol]: SpringSourceApi<T>;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Compile-time validation of a shape of sources: every leaf must be a
|
|
283
|
+
* `SpringSource`, and every branch a plain object or array with at least
|
|
284
|
+
* one leaf. `mapSpring` takes `sources: T & SourceShape<T>`, so an
|
|
285
|
+
* invalid leaf errors on that property, not on the whole argument. The
|
|
286
|
+
* check is structural only, and the runtime validation repeats it for
|
|
287
|
+
* untyped callers. It rejects optional and `undefined`-typed leaves.
|
|
288
|
+
*/
|
|
289
|
+
type SourceShape<T> = 0 extends 1 & T ? T : T extends SpringSource<unknown> ? SpringSource<unknown> : 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 : SourceShape<T[K]>; } : never;
|
|
290
|
+
/**
|
|
291
|
+
* The value shape a shape of sources produces: the same nesting, with
|
|
292
|
+
* every `SpringSource` leaf replaced by its value. A scalar spring leaf
|
|
293
|
+
* becomes `number`, and a composite leaf becomes its read-only value
|
|
294
|
+
* shape. This is what `map` receives when you give `mapSpring` a shape.
|
|
295
|
+
*/
|
|
296
|
+
type SourceValues<T> = T extends SpringSource<infer V> ? V : { readonly [K in keyof T]: SourceValues<T[K]>; };
|
|
297
|
+
/**
|
|
298
|
+
* Derives a source from another by a pure function of its value.
|
|
299
|
+
* `mapSpring(leader, (v) => v + 10)` follows 10 above the leader, and
|
|
300
|
+
* `(v) => -v` mirrors it. Like any `SpringSource`, the result can be
|
|
301
|
+
* mapped again, used as a leaf of a shape map, or followed by several
|
|
302
|
+
* springs at once.
|
|
303
|
+
*
|
|
304
|
+
* The result is a stateless view, not a spring. It holds no
|
|
305
|
+
* subscriptions and needs no disposal. `map` runs on every read, and
|
|
306
|
+
* each follower reads on every source update, so `map` must be pure.
|
|
307
|
+
* Nothing re-evaluates it when anything other than `source` changes.
|
|
308
|
+
* Mapping a mapped source extends its pipeline instead of wrapping it,
|
|
309
|
+
* so a chain costs one function call per map.
|
|
310
|
+
*/
|
|
311
|
+
declare function mapSpring(source: SpringSource, map: (value: number) => number): SpringSource;
|
|
312
|
+
/**
|
|
313
|
+
* Derives a scalar source from several channels by a pure function of
|
|
314
|
+
* their values. `sources` is a single non-scalar source such as a
|
|
315
|
+
* `CompositeSpring`, or a shape: a plain object or array with
|
|
316
|
+
* `SpringSource` leaves, nested to any depth. `map` receives the
|
|
317
|
+
* matching values. For a shape, that is each leaf's current number
|
|
318
|
+
* (`mapSpring({ x, y }, ({ x, y }) => Math.hypot(x, y))`). For a
|
|
319
|
+
* composite, it is the live value shape
|
|
320
|
+
* (`mapSpring(point, ({ x, y }) => Math.hypot(x, y))`). An invalid leaf
|
|
321
|
+
* throws with its path (`position.z`).
|
|
322
|
+
*
|
|
323
|
+
* The result is a stateless view, not a spring. It holds no
|
|
324
|
+
* subscriptions and needs no disposal. `map` runs on every read, and
|
|
325
|
+
* each follower reads on every source update, so `map` must be pure.
|
|
326
|
+
* Every call hands it the same live mirror, refreshed in place, so `map`
|
|
327
|
+
* must not keep what it receives. The mapped source is released with the
|
|
328
|
+
* first of its sources, and followers then detach and keep their current
|
|
329
|
+
* target.
|
|
330
|
+
*/
|
|
331
|
+
declare function mapSpring<const T extends object>(sources: T & SourceShape<T>, map: (values: SourceValues<T>) => number): SpringSource;
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/kinematic-source.d.ts
|
|
334
|
+
/**
|
|
335
|
+
* A `SpringSourceApi` whose value is in motion, so it also reports
|
|
336
|
+
* `velocity` and `acceleration`. A `Spring`, a `CompositeSpring`, and a
|
|
337
|
+
* `Ramp` report both exactly, from the model that moves the value. A
|
|
338
|
+
* source you write yourself can report them if it tracks a value in
|
|
339
|
+
* motion. A `mapSpring` result cannot, since it holds no motion of its
|
|
340
|
+
* own. `velocityOf` and `accelerationOf` read this slot.
|
|
341
|
+
*/
|
|
342
|
+
interface KinematicSourceApi<T = number> extends SpringSourceApi<T> {
|
|
343
|
+
/** The rate `value` is changing, in value units per second. */
|
|
344
|
+
readonly velocity: T;
|
|
345
|
+
/** The rate `velocity` is changing, in value units per second squared. */
|
|
346
|
+
readonly acceleration: T;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* A `SpringSource` whose value is in motion, so it also carries
|
|
350
|
+
* `velocity` and `acceleration`. Every `Spring`, `CompositeSpring`, and
|
|
351
|
+
* `Ramp` is one, and `velocityOf` and `accelerationOf` accept these. A
|
|
352
|
+
* plain `SpringSource`, such as a `mapSpring` result, is not assignable.
|
|
353
|
+
*/
|
|
354
|
+
interface KinematicSource<T = number> extends SpringSource<T> {
|
|
355
|
+
readonly [SpringSourceSymbol]: KinematicSourceApi<T>;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* A `KinematicSourceApi` that also reports `target`, where its motion is
|
|
359
|
+
* heading. A `Spring`, a `CompositeSpring`, and a `Ramp` carry it, and
|
|
360
|
+
* `targetOf` reads it.
|
|
361
|
+
*/
|
|
362
|
+
interface TargetedSourceApi<T = number> extends KinematicSourceApi<T> {
|
|
363
|
+
/** The value the motion is heading toward, in value units. */
|
|
364
|
+
readonly target: T;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* A `KinematicSource` that also carries the `target` its motion is heading
|
|
368
|
+
* toward: every `Spring`, `CompositeSpring`, and `Ramp`, and the Vue refs
|
|
369
|
+
* that wrap them. `targetOf` accepts these. A `mapSpring` result is not
|
|
370
|
+
* assignable, because a value derivation has no target.
|
|
371
|
+
*/
|
|
372
|
+
interface TargetedSource<T = number> extends KinematicSource<T> {
|
|
373
|
+
readonly [SpringSourceSymbol]: TargetedSourceApi<T>;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Derives a source that reads another source's velocity: the rate its
|
|
377
|
+
* value changes, in value units per second. Speed-driven effects then
|
|
378
|
+
* use the same tools as everything else. A spring can follow it
|
|
379
|
+
* (`blur.target = velocityOf(motion)`), and a map can shape it
|
|
380
|
+
* (`mapSpring(velocityOf(motion), (v) => 1 + Math.abs(v) * 0.001)` for
|
|
381
|
+
* squash and stretch). A scalar source yields a scalar velocity. A
|
|
382
|
+
* `CompositeSpring` yields a velocity of its own shape, which you map to
|
|
383
|
+
* a scalar as you would its value.
|
|
384
|
+
*
|
|
385
|
+
* The result is a stateless view that holds no subscriptions and needs
|
|
386
|
+
* no disposal. Each read reports the source's current velocity. It
|
|
387
|
+
* updates when the source does and is released with it, and followers
|
|
388
|
+
* then detach and keep their current target.
|
|
389
|
+
*
|
|
390
|
+
* Only a `Spring`, a `CompositeSpring`, a `Ramp`, or a Vue ref that wraps
|
|
391
|
+
* one qualifies. A `mapSpring` result has no velocity, and `velocityOf`
|
|
392
|
+
* rejects it at the type level and at runtime. Take `velocityOf` of the
|
|
393
|
+
* spring the map reads instead.
|
|
394
|
+
*/
|
|
395
|
+
declare function velocityOf<T>(source: KinematicSource<T>): SpringSource<T>;
|
|
396
|
+
/**
|
|
397
|
+
* Derives a source that reads another source's acceleration: the rate
|
|
398
|
+
* its velocity changes, in value units per second squared. On a spring it
|
|
399
|
+
* is largest just after a retarget and near the far end of each swing,
|
|
400
|
+
* and passes through zero where a swing moves fastest. A spring can
|
|
401
|
+
* follow it, and a map can turn it into an impact flash or a jelly wobble
|
|
402
|
+
* (`mapSpring(accelerationOf(motion), (a) => Math.min(1, Math.abs(a) * 1e-4))`).
|
|
403
|
+
* A scalar source yields a scalar acceleration. A `CompositeSpring`
|
|
404
|
+
* yields an acceleration of its own shape, which you map to a scalar as
|
|
405
|
+
* you would its value. A `Ramp`'s acceleration is always 0.
|
|
406
|
+
*
|
|
407
|
+
* The result is a stateless view that holds no subscriptions and needs
|
|
408
|
+
* no disposal. Each read reports the source's current acceleration. It
|
|
409
|
+
* updates when the source does and is released with it, and followers
|
|
410
|
+
* then detach and keep their current target.
|
|
411
|
+
*
|
|
412
|
+
* Only a `Spring`, a `CompositeSpring`, a `Ramp`, or a Vue ref that wraps
|
|
413
|
+
* one qualifies. A `mapSpring` result has no acceleration, and
|
|
414
|
+
* `accelerationOf` rejects it at the type level and at runtime. Take
|
|
415
|
+
* `accelerationOf` of the spring the map reads instead.
|
|
416
|
+
*/
|
|
417
|
+
declare function accelerationOf<T>(source: KinematicSource<T>): SpringSource<T>;
|
|
418
|
+
/**
|
|
419
|
+
* Derives a source that reads a spring's or ramp's target: where it is
|
|
420
|
+
* heading, not where it is. Pair it with the source in a `mapSpring`
|
|
421
|
+
* shape to measure against the destination, such as remaining travel,
|
|
422
|
+
* progress, or a lead that anticipates the move. A `Spring` or a bounded
|
|
423
|
+
* `Ramp` yields a scalar target that a spring can follow. An endless
|
|
424
|
+
* `Ramp` yields `Infinity` or `-Infinity`, and a spring that follows it
|
|
425
|
+
* throws. A `CompositeSpring` yields a target of its own shape, which you
|
|
426
|
+
* map to a scalar as you would its value.
|
|
427
|
+
*
|
|
428
|
+
* ```ts
|
|
429
|
+
* const system = createSpringSystem()
|
|
430
|
+
* const body = system.createSpring(0)
|
|
431
|
+
* // The eyes look ahead by the body's remaining travel, capped at 20.
|
|
432
|
+
* const lead = mapSpring({ value: body, target: targetOf(body) }, ({ value, target }) =>
|
|
433
|
+
* Math.max(-20, Math.min(20, target - value)),
|
|
434
|
+
* )
|
|
435
|
+
* const eyes = system.createSpring(lead)
|
|
436
|
+
*
|
|
437
|
+
* body.target = 100
|
|
438
|
+
* system.advance(100)
|
|
439
|
+
* eyes.target // 20: the body still has more than 20 to go
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* The result is a stateless view that holds no subscriptions and needs
|
|
443
|
+
* no disposal. Each read reports the spring's current target. It updates
|
|
444
|
+
* when the spring does, but assigning `target` emits nothing by itself,
|
|
445
|
+
* so followers pick up a new target on the next frame, when the spring
|
|
446
|
+
* starts toward it. Under reduced motion, a `'motion'` spring jumps to
|
|
447
|
+
* its new target and notifies followers at once. The view is released
|
|
448
|
+
* with the spring, and followers then detach and keep their current
|
|
449
|
+
* target.
|
|
450
|
+
*
|
|
451
|
+
* Only a `Spring`, a `CompositeSpring`, a `Ramp`, or a Vue ref that wraps
|
|
452
|
+
* one has a target. `targetOf` rejects a `mapSpring` result at the type
|
|
453
|
+
* level and at runtime.
|
|
454
|
+
*/
|
|
455
|
+
declare function targetOf<T>(spring: TargetedSource<T>): SpringSource<T>;
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region src/spring.d.ts
|
|
458
|
+
/**
|
|
459
|
+
* What a spring can animate toward. A number is a fixed target. A
|
|
460
|
+
* `SpringSource` (another spring, or a value derived from one with
|
|
461
|
+
* `mapSpring`) is a live value that the spring follows.
|
|
462
|
+
*/
|
|
463
|
+
type SpringTarget = number | SpringSource;
|
|
464
|
+
/**
|
|
465
|
+
* What a spring animates, which decides whether reduced motion applies.
|
|
466
|
+
* `'motion'` moves something on screen, such as position, scale, or
|
|
467
|
+
* rotation, and snaps to its target under reduced motion. `'nonmotion'`
|
|
468
|
+
* moves nothing, such as a cross-fade, a color, a blur, or a number that
|
|
469
|
+
* never reaches the screen, and keeps animating under reduced motion.
|
|
470
|
+
* Fixed at creation. Read it back from `Spring.purpose`.
|
|
471
|
+
*/
|
|
472
|
+
type Purpose = 'motion' | 'nonmotion';
|
|
473
|
+
/**
|
|
474
|
+
* One animated number, driven toward its target with damped spring
|
|
475
|
+
* motion. Create springs with `SpringSystem.createSpring`. A spring moves
|
|
476
|
+
* only when its system advances it.
|
|
477
|
+
*
|
|
478
|
+
* Reads return the exact, unrounded simulated state. Numeric writes
|
|
479
|
+
* (`target`, `value`, `velocity`, `jumpTo`) throw on `NaN` or an
|
|
480
|
+
* infinity. See https://github.com/tkofh/coily/blob/main/PRECISION.md
|
|
481
|
+
* for the numerical contract.
|
|
482
|
+
*/
|
|
483
|
+
declare class Spring implements TargetedSource {
|
|
484
|
+
#private;
|
|
485
|
+
/** Brands the spring as a `TargetedSource` whose api is the spring itself. */
|
|
486
|
+
get [SpringSourceSymbol](): TargetedSourceApi<number>;
|
|
487
|
+
constructor(motions: MotionSet, value: number, config?: SpringDefinition, purpose?: Purpose);
|
|
488
|
+
/**
|
|
489
|
+
* The value the spring is animating toward. While following a source,
|
|
490
|
+
* reads return the source's value as of its last update.
|
|
491
|
+
*
|
|
492
|
+
* Assignment accepts any `SpringTarget`:
|
|
493
|
+
* - A number retargets smoothly, keeping the current value and velocity.
|
|
494
|
+
* It also ends any following.
|
|
495
|
+
* - A `SpringSource` (a `Spring`, or a value derived with `mapSpring`)
|
|
496
|
+
* makes this spring follow the source's live value.
|
|
497
|
+
*
|
|
498
|
+
* Under reduced motion, retargets apply instantly unless `purpose` is
|
|
499
|
+
* `'nonmotion'`.
|
|
500
|
+
*/
|
|
501
|
+
get target(): number;
|
|
502
|
+
set target(value: SpringTarget);
|
|
503
|
+
/**
|
|
504
|
+
* The current animated value: the target plus the remaining
|
|
505
|
+
* displacement.
|
|
506
|
+
*
|
|
507
|
+
* Writing displaces the spring. It keeps its target, springs back from
|
|
508
|
+
* the written value, and notifies update listeners synchronously.
|
|
509
|
+
* Writing the current value is a no-op. Under reduced motion, a write
|
|
510
|
+
* jumps value and target together unless `purpose` is `'nonmotion'`.
|
|
511
|
+
*/
|
|
512
|
+
get value(): number;
|
|
513
|
+
set value(value: number);
|
|
514
|
+
/**
|
|
515
|
+
* The current velocity, in value units per second.
|
|
516
|
+
*
|
|
517
|
+
* Writing flings the spring from its current value, and it settles back
|
|
518
|
+
* to the target. Under reduced motion, the write is ignored unless
|
|
519
|
+
* `purpose` is `'nonmotion'`.
|
|
520
|
+
*/
|
|
521
|
+
get velocity(): number;
|
|
522
|
+
set velocity(value: number);
|
|
523
|
+
/**
|
|
524
|
+
* The current acceleration, in value units per second squared.
|
|
525
|
+
* Read-only, because stiffness and friction derive it from the current
|
|
526
|
+
* displacement and velocity. To fling the spring, write `velocity`.
|
|
527
|
+
*/
|
|
528
|
+
get acceleration(): number;
|
|
529
|
+
/**
|
|
530
|
+
* What the spring animates, fixed at creation. Under reduced motion, a
|
|
531
|
+
* `'motion'` spring snaps to its target and a `'nonmotion'` spring keeps
|
|
532
|
+
* animating. See `Purpose`.
|
|
533
|
+
*/
|
|
534
|
+
get purpose(): Purpose;
|
|
535
|
+
/**
|
|
536
|
+
* The spring's `SpringDefinition`: the one it was created with or last
|
|
537
|
+
* assigned, otherwise `SpringDefinition.default`. Following a source
|
|
538
|
+
* never changes it.
|
|
539
|
+
*
|
|
540
|
+
* Assigning reconfigures the spring in place, keeping value and
|
|
541
|
+
* velocity, so mid-flight changes stay smooth. `null` reverts to the
|
|
542
|
+
* default.
|
|
543
|
+
*/
|
|
544
|
+
get config(): SpringDefinition;
|
|
545
|
+
/** The config's mass. */
|
|
546
|
+
get mass(): number;
|
|
547
|
+
/** The config's tension (stiffness). */
|
|
548
|
+
get tension(): number;
|
|
549
|
+
/** The config's damping (friction). */
|
|
550
|
+
get damping(): number;
|
|
551
|
+
/** The config's damping ratio. */
|
|
552
|
+
get dampingRatio(): number;
|
|
553
|
+
/** The config's precision: decimal places of the resting threshold. */
|
|
554
|
+
get precision(): number;
|
|
555
|
+
/** The config's arrival multiplier, applied to the velocity at each target crossing. */
|
|
556
|
+
get arrival(): number;
|
|
557
|
+
set config(value: SpringDefinition | null);
|
|
558
|
+
/**
|
|
559
|
+
* The time until the spring rests, in ms, solved from the motion: 0
|
|
560
|
+
* while resting, `Infinity` when it never settles. The spring rests at
|
|
561
|
+
* the first tick at or after this time. A bouncy spring can rest up to
|
|
562
|
+
* one oscillation earlier, when a frame samples a low point of the
|
|
563
|
+
* bounce. With `arrival: 0`, the time is capped at the first target
|
|
564
|
+
* crossing, exact to the ms.
|
|
565
|
+
*/
|
|
566
|
+
get timeRemaining(): number;
|
|
567
|
+
/**
|
|
568
|
+
* Whether the spring's remaining motion is inside its resting
|
|
569
|
+
* threshold. Resting springs cost nothing until the next write. See
|
|
570
|
+
* https://github.com/tkofh/coily/blob/main/PRECISION.md for the rest
|
|
571
|
+
* test.
|
|
572
|
+
*/
|
|
573
|
+
get isResting(): boolean;
|
|
574
|
+
/**
|
|
575
|
+
* A promise that resolves when the spring next rests or is disposed.
|
|
576
|
+
* It is already resolved while the spring rests and after dispose.
|
|
577
|
+
* Retargeting mid-flight extends the wait.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* spring.target = 300
|
|
582
|
+
* await spring.settled
|
|
583
|
+
* // the spring is at 300 and resting
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
get settled(): Promise<void>;
|
|
587
|
+
/**
|
|
588
|
+
* Snaps target and value to `value` and zeroes the velocity, with no
|
|
589
|
+
* animation. Listeners fire synchronously: `update`, plus `stop` if the
|
|
590
|
+
* spring was moving.
|
|
591
|
+
*/
|
|
592
|
+
jumpTo(value: number): void;
|
|
593
|
+
/**
|
|
594
|
+
* Releases the spring permanently. It stops following, detaches
|
|
595
|
+
* followers (each keeps its current target), resolves `settled`, and
|
|
596
|
+
* notifies dispose listeners. Calling it again is a no-op.
|
|
597
|
+
*
|
|
598
|
+
* A disposed spring keeps its final value readable. Writes throw.
|
|
599
|
+
*/
|
|
600
|
+
dispose(): void;
|
|
601
|
+
/**
|
|
602
|
+
* Subscribes to value changes: every tick the spring moves, plus
|
|
603
|
+
* synchronous `value` writes and `jumpTo` calls. Returns an unsubscribe
|
|
604
|
+
* function.
|
|
605
|
+
*/
|
|
606
|
+
onUpdate(callback: () => void): () => void;
|
|
607
|
+
/**
|
|
608
|
+
* Subscribes to the spring leaving rest. `start` and `stop` always
|
|
609
|
+
* alternate, and retargeting mid-flight fires neither. Returns an
|
|
610
|
+
* unsubscribe function.
|
|
611
|
+
*/
|
|
612
|
+
onStart(callback: () => void): () => void;
|
|
613
|
+
/**
|
|
614
|
+
* Subscribes to the spring coming to rest, whether by settling or by
|
|
615
|
+
* `jumpTo`. Always alternates with `start`. Returns an unsubscribe
|
|
616
|
+
* function.
|
|
617
|
+
*/
|
|
618
|
+
onStop(callback: () => void): () => void;
|
|
619
|
+
/** Subscribes to `dispose`, which fires once. Returns an unsubscribe function. */
|
|
620
|
+
onDispose(callback: () => void): () => void;
|
|
621
|
+
}
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region src/composite-spring.d.ts
|
|
624
|
+
/**
|
|
625
|
+
* Compile-time validation of a value shape: every channel must be a `number`,
|
|
626
|
+
* every branch a plain object or array with at least one channel. Used as
|
|
627
|
+
* `value: T & Shape<T>` so an invalid channel errors on that property rather
|
|
628
|
+
* than on the whole argument. It is purely structural, so interfaces
|
|
629
|
+
* satisfy it without index signatures, and runtime validation mirrors it
|
|
630
|
+
* for untyped callers. Optional and `undefined`-typed channels
|
|
631
|
+
* are rejected: a channel that may be absent would make two springs of the
|
|
632
|
+
* same declared shape structurally incompatible at runtime.
|
|
633
|
+
*/
|
|
634
|
+
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;
|
|
635
|
+
/**
|
|
636
|
+
* A partial view of a value shape: the same nesting with any subset of the
|
|
637
|
+
* numeric channels present. A write leaves absent or `undefined` channels
|
|
638
|
+
* unchanged.
|
|
639
|
+
*/
|
|
640
|
+
type PartialShape<T> = T extends number ? number : { readonly [K in keyof T]?: PartialShape<T[K]> | undefined; };
|
|
641
|
+
/**
|
|
642
|
+
* A deep-readonly view of a value shape. Composite reads (`target`, `value`,
|
|
643
|
+
* `velocity`, `acceleration`) return the spring's live mirror objects, and
|
|
644
|
+
* every read refreshes them in place, so their channels are typed read-only.
|
|
645
|
+
*/
|
|
646
|
+
type ReadonlyShape<T> = T extends number ? number : { readonly [K in keyof T]: ReadonlyShape<T[K]>; };
|
|
647
|
+
/**
|
|
648
|
+
* Configuration for a composite spring: a single `SpringDefinition` applied to every
|
|
649
|
+
* channel, or an object mirroring the value shape with configs at any level.
|
|
650
|
+
* A config at a subtree applies to every channel below it.
|
|
651
|
+
* `null` reverts to the default config.
|
|
652
|
+
* Configs are always `SpringDefinition` instances (from `defineSpring`), so a
|
|
653
|
+
* plain object is unambiguously a config shape and any non-config leaf it
|
|
654
|
+
* reaches is an error.
|
|
655
|
+
*/
|
|
656
|
+
type ConfigShape<T> = SpringDefinition | null | (T extends number ? never : { readonly [K in keyof T]?: ConfigShape<T[K]> | undefined; });
|
|
657
|
+
/**
|
|
658
|
+
* What each channel of a composite spring animates: a single `Purpose`
|
|
659
|
+
* for every channel, or a shape mirroring the value with purposes at any
|
|
660
|
+
* level. A purpose at a subtree covers every channel below it, and a
|
|
661
|
+
* channel that no purpose reaches defaults to `'motion'`. The purposes
|
|
662
|
+
* are fixed when the spring is created. See `Purpose`.
|
|
663
|
+
*/
|
|
664
|
+
type PurposeShape<T> = Purpose | (T extends number ? never : { readonly [K in keyof T]?: PurposeShape<T[K]> | undefined; });
|
|
665
|
+
/**
|
|
666
|
+
* A partial target shape: the same nesting as the value with any subset
|
|
667
|
+
* of the channels present, each taking a number to animate toward or a
|
|
668
|
+
* scalar `SpringSource` to follow. A write leaves absent or `undefined`
|
|
669
|
+
* channels unchanged.
|
|
670
|
+
*/
|
|
671
|
+
type TargetShape<T> = T extends number ? number | SpringSource : { readonly [K in keyof T]?: TargetShape<T[K]> | undefined; };
|
|
672
|
+
/**
|
|
673
|
+
* What a composite spring can animate toward: a partial shape mixing
|
|
674
|
+
* numbers and scalar `SpringSource`s per channel, or another composite
|
|
675
|
+
* spring of the same shape to follow channel by channel.
|
|
676
|
+
*/
|
|
677
|
+
type CompositeSpringTarget<T extends object> = TargetShape<T> | CompositeSpring<T>;
|
|
678
|
+
/**
|
|
679
|
+
* A composite spring over a fixed numeric shape: a nested plain object
|
|
680
|
+
* or array whose leaves are all numbers. Each leaf runs an independent
|
|
681
|
+
* spring, called a channel. Targets, values, velocities, and configs read
|
|
682
|
+
* and write as shapes, writes can name any subset of the channels, and
|
|
683
|
+
* events coalesce across channels. Create one with
|
|
684
|
+
* `SpringSystem.createSpring`.
|
|
685
|
+
*
|
|
686
|
+
* A composite spring is a `SpringSource` of its value shape. Springs
|
|
687
|
+
* follow only scalar sources, so use `mapSpring` to derive one from the
|
|
688
|
+
* composite, alone or at the leaves of a shape.
|
|
689
|
+
*
|
|
690
|
+
* A write that names an unknown channel or gives one a non-finite value
|
|
691
|
+
* throws with the channel's path (`position.z`) and changes nothing.
|
|
692
|
+
*/
|
|
693
|
+
declare class CompositeSpring<in out T extends object> implements TargetedSource<ReadonlyShape<T>> {
|
|
694
|
+
#private;
|
|
695
|
+
/** Brands the composite as a `TargetedSource` whose api is the composite itself. */
|
|
696
|
+
get [SpringSourceSymbol](): TargetedSourceApi<ReadonlyShape<T>>;
|
|
697
|
+
constructor(motions: MotionSet, value: T & Shape<T>, config?: ConfigShape<T>, purpose?: PurposeShape<T>);
|
|
698
|
+
/**
|
|
699
|
+
* The value each channel is animating toward, as a read-only mirror of
|
|
700
|
+
* the shape. The mirror is reused and refreshed in place on each read,
|
|
701
|
+
* so read it fresh instead of holding it across frames.
|
|
702
|
+
*
|
|
703
|
+
* Assignment accepts a `CompositeSpringTarget`:
|
|
704
|
+
* - A partial shape retargets the channels it names, each to a number
|
|
705
|
+
* or to a scalar `SpringSource` to follow, such as a `Spring` or a
|
|
706
|
+
* `mapSpring` result. Naming a channel detaches it from any leader.
|
|
707
|
+
* - A `CompositeSpring` of the same shape becomes the leader, and each
|
|
708
|
+
* channel follows the matching leader channel.
|
|
709
|
+
*
|
|
710
|
+
* Unknown channels throw with their path. Under reduced motion,
|
|
711
|
+
* retargets apply instantly, except on channels whose `purpose` is
|
|
712
|
+
* `'nonmotion'`.
|
|
713
|
+
*/
|
|
714
|
+
get target(): ReadonlyShape<T>;
|
|
715
|
+
set target(value: CompositeSpringTarget<T>);
|
|
716
|
+
/**
|
|
717
|
+
* The current animated value of every channel, as a read-only mirror of
|
|
718
|
+
* the shape. The mirror is reused and refreshed in place on each read,
|
|
719
|
+
* so read it fresh instead of holding it across frames.
|
|
720
|
+
*
|
|
721
|
+
* Assignment displaces the channels a partial shape names. Each keeps
|
|
722
|
+
* its target and springs back from the written value. The write fires
|
|
723
|
+
* one coalesced `update` synchronously. Under reduced motion, the named
|
|
724
|
+
* channels jump to the written values, targets included, except on
|
|
725
|
+
* channels whose `purpose` is `'nonmotion'`.
|
|
726
|
+
*/
|
|
727
|
+
get value(): ReadonlyShape<T>;
|
|
728
|
+
set value(value: PartialShape<T>);
|
|
729
|
+
/**
|
|
730
|
+
* The current velocity of every channel in value units per second, as a
|
|
731
|
+
* read-only mirror of the shape. The mirror is reused and refreshed in
|
|
732
|
+
* place on each read.
|
|
733
|
+
*
|
|
734
|
+
* Assignment flings the channels a partial shape names. Under reduced
|
|
735
|
+
* motion, writes are ignored, except on channels whose `purpose` is
|
|
736
|
+
* `'nonmotion'`.
|
|
737
|
+
*/
|
|
738
|
+
get velocity(): ReadonlyShape<T>;
|
|
739
|
+
set velocity(value: PartialShape<T>);
|
|
740
|
+
/**
|
|
741
|
+
* The current acceleration of every channel in value units per second
|
|
742
|
+
* squared, as a read-only mirror of the shape. The mirror is reused and
|
|
743
|
+
* refreshed in place on each read. To fling channels, write `velocity`.
|
|
744
|
+
*/
|
|
745
|
+
get acceleration(): ReadonlyShape<T>;
|
|
746
|
+
/**
|
|
747
|
+
* The shared config when every channel resolves to the same
|
|
748
|
+
* `SpringDefinition`, and `null` when they differ.
|
|
749
|
+
*
|
|
750
|
+
* Assignment accepts a `ConfigShape`: one config for every channel,
|
|
751
|
+
* `null` to revert every channel to the default, or a shape mirroring
|
|
752
|
+
* the value whose configs each cover their subtree. Non-config leaves
|
|
753
|
+
* throw with their path. Assigning a `null` read back reverts every
|
|
754
|
+
* channel to the default rather than restoring the mix.
|
|
755
|
+
*/
|
|
756
|
+
get config(): SpringDefinition | null;
|
|
757
|
+
set config(value: ConfigShape<T>);
|
|
758
|
+
/**
|
|
759
|
+
* The shared purpose when every channel resolves to the same `Purpose`,
|
|
760
|
+
* and `null` when they differ. The purposes are fixed when the spring is
|
|
761
|
+
* created. A `'nonmotion'` channel opts out of reduced motion. See
|
|
762
|
+
* `Purpose`.
|
|
763
|
+
*/
|
|
764
|
+
get purpose(): Purpose | null;
|
|
765
|
+
/** The largest `timeRemaining` across channels, in ms. */
|
|
766
|
+
get timeRemaining(): number;
|
|
767
|
+
/** Whether every channel is resting. */
|
|
768
|
+
get isResting(): boolean;
|
|
769
|
+
/**
|
|
770
|
+
* A promise that resolves when every channel next rests. It is already
|
|
771
|
+
* resolved while the composite rests or after dispose. Retargeting any
|
|
772
|
+
* channel mid-flight extends the wait, and disposing resolves it.
|
|
773
|
+
*/
|
|
774
|
+
get settled(): Promise<void>;
|
|
775
|
+
/**
|
|
776
|
+
* Snaps the channels a partial shape names to the given values with no
|
|
777
|
+
* animation, setting both target and value. Fires one `update`
|
|
778
|
+
* synchronously, plus `stop` if the jump leaves every channel resting.
|
|
779
|
+
*/
|
|
780
|
+
jumpTo(value: PartialShape<T>): void;
|
|
781
|
+
/**
|
|
782
|
+
* Releases every channel permanently. Each channel stops following, and
|
|
783
|
+
* its followers detach and keep their current targets. `settled`
|
|
784
|
+
* resolves and dispose listeners fire. Calling it again is a no-op.
|
|
785
|
+
* Afterward, final values stay readable and writes throw.
|
|
786
|
+
*/
|
|
787
|
+
dispose(): void;
|
|
788
|
+
/**
|
|
789
|
+
* Subscribes to coalesced value changes. `update` fires at most once per
|
|
790
|
+
* tick, after every channel advances, and once per synchronous write that
|
|
791
|
+
* moves a channel, such as a `value` write or `jumpTo`. Returns an
|
|
792
|
+
* unsubscribe function.
|
|
793
|
+
*/
|
|
794
|
+
onUpdate(callback: () => void): () => void;
|
|
795
|
+
/**
|
|
796
|
+
* Subscribes to the composite leaving rest. `start` fires when a channel
|
|
797
|
+
* starts to move and no other channel was moving. It always alternates
|
|
798
|
+
* with `stop`. Returns an unsubscribe function.
|
|
799
|
+
*/
|
|
800
|
+
onStart(callback: () => void): () => void;
|
|
801
|
+
/**
|
|
802
|
+
* Subscribes to the composite coming to rest. `stop` fires when every
|
|
803
|
+
* channel rests, after that tick's final `update`. It always alternates
|
|
804
|
+
* with `start`. Returns an unsubscribe function.
|
|
805
|
+
*/
|
|
806
|
+
onStop(callback: () => void): () => void;
|
|
807
|
+
/** Subscribes to `dispose`, which fires once. Returns an unsubscribe function. */
|
|
808
|
+
onDispose(callback: () => void): () => void;
|
|
809
|
+
}
|
|
810
|
+
//#endregion
|
|
811
|
+
//#region src/ramp.d.ts
|
|
812
|
+
/** Options for `SpringSystem.createRamp`. */
|
|
813
|
+
interface RampOptions {
|
|
814
|
+
/**
|
|
815
|
+
* The ramp's speed, in value units per second. Must be finite and
|
|
816
|
+
* >= 0. A rate of 0 rests the ramp where it is.
|
|
817
|
+
*/
|
|
818
|
+
rate: number;
|
|
819
|
+
/**
|
|
820
|
+
* Where the ramp heads. `Infinity` or `-Infinity` makes it endless in
|
|
821
|
+
* that direction.
|
|
822
|
+
* @default the starting value, so the ramp starts at rest
|
|
823
|
+
*/
|
|
824
|
+
target?: number | undefined;
|
|
825
|
+
/**
|
|
826
|
+
* What the ramp drives, which decides whether reduced motion applies.
|
|
827
|
+
* Under reduced motion, a `'motion'` ramp jumps to a bounded target and
|
|
828
|
+
* holds still on an endless one. A `'nonmotion'` ramp, such as a clock
|
|
829
|
+
* for logic, keeps moving. Fixed for the ramp's life. See `Purpose`.
|
|
830
|
+
* @default 'motion'
|
|
831
|
+
*/
|
|
832
|
+
purpose?: Purpose | undefined;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* A value that moves toward its target at a fixed speed, in a straight
|
|
836
|
+
* line, and stops there. Create ramps with `SpringSystem.createRamp`.
|
|
837
|
+
*
|
|
838
|
+
* A ramp is a `SpringSource`, so a spring can follow it. With the
|
|
839
|
+
* default `arrival`, the spring integrates against the ramp's steady
|
|
840
|
+
* motion exactly, where a target assigned once per frame would reach it
|
|
841
|
+
* as a staircase. With any other `arrival`, the spring holds the target
|
|
842
|
+
* still within each of a frame's sub-steps, one stair per sub-step.
|
|
843
|
+
* Typical uses are an endless spin, a heading that turns at a capped
|
|
844
|
+
* speed, and a clock in ms mapped into a shape with `mapSpring`.
|
|
845
|
+
*
|
|
846
|
+
* ```ts
|
|
847
|
+
* const system = createSpringSystem()
|
|
848
|
+
* const sweep = system.createRamp(0, { rate: 270, target: Infinity })
|
|
849
|
+
* const ring = system.createSpring(sweep, defineSpring({ duration: 300, dampingRatio: 1 }))
|
|
850
|
+
*
|
|
851
|
+
* system.advance(1000)
|
|
852
|
+
* sweep.value // 270
|
|
853
|
+
* ```
|
|
854
|
+
*
|
|
855
|
+
* A ramp costs nothing per frame unless something watches it: an
|
|
856
|
+
* `onUpdate` listener, a following spring, or, on a bounded ramp, an
|
|
857
|
+
* `onStop` listener or a pending `settled`. An unwatched ramp still
|
|
858
|
+
* moves, and a read reports where it is.
|
|
859
|
+
*
|
|
860
|
+
* Ramps move on the system clock. It counts frame time, `advance` calls,
|
|
861
|
+
* and the time a started system spends asleep, and stops while the
|
|
862
|
+
* system is stopped. A sleeping system skips the time the page is
|
|
863
|
+
* hidden. An awake system gets no frames in a hidden tab, so the hidden
|
|
864
|
+
* spell counts as one frame on return: `adjustedLag` ms if it lasted
|
|
865
|
+
* longer than `lagThreshold`, in full otherwise or with lag clamping off.
|
|
866
|
+
*
|
|
867
|
+
* The clock holds still through synchronous code, so every read in one
|
|
868
|
+
* event handler or render sees the same moment. A ramp created and read
|
|
869
|
+
* with no `await` in between reads its starting value.
|
|
870
|
+
*
|
|
871
|
+
* Under reduced motion, a `'motion'` ramp jumps to a bounded target, and
|
|
872
|
+
* an endless one holds still until reduced motion turns off, then
|
|
873
|
+
* resumes. A `'nonmotion'` ramp keeps moving.
|
|
874
|
+
*/
|
|
875
|
+
declare class Ramp implements TargetedSource {
|
|
876
|
+
#private;
|
|
877
|
+
/** Brands the ramp as a `TargetedSource` whose api is the ramp itself. */
|
|
878
|
+
get [SpringSourceSymbol](): TargetedSourceApi<number>;
|
|
879
|
+
constructor(motions: MotionSet, from: number, options: RampOptions);
|
|
880
|
+
/**
|
|
881
|
+
* The current value.
|
|
882
|
+
*
|
|
883
|
+
* Assignment accepts a finite number. It moves the ramp there at once,
|
|
884
|
+
* keeping its target and rate, and notifies update listeners
|
|
885
|
+
* synchronously. Writing the
|
|
886
|
+
* current value does nothing. Under reduced motion, a `'motion'` ramp
|
|
887
|
+
* with a bounded target rests at the written value, which becomes its
|
|
888
|
+
* target too.
|
|
889
|
+
*/
|
|
890
|
+
get value(): number;
|
|
891
|
+
set value(value: number);
|
|
892
|
+
/**
|
|
893
|
+
* Where the ramp is heading, or `Infinity` or `-Infinity` for an
|
|
894
|
+
* endless ramp.
|
|
895
|
+
*
|
|
896
|
+
* Assignment accepts any number but `NaN`, and sends the ramp toward the
|
|
897
|
+
* new target at its current rate.
|
|
898
|
+
* It emits `start` if the ramp was resting, and no `update`, since the
|
|
899
|
+
* value has not moved. Under reduced motion, a `'motion'` ramp jumps to
|
|
900
|
+
* a bounded target, notifying update listeners, and holds still toward
|
|
901
|
+
* an endless one.
|
|
902
|
+
*/
|
|
903
|
+
get target(): number;
|
|
904
|
+
set target(target: number);
|
|
905
|
+
/**
|
|
906
|
+
* The ramp's speed, in value units per second.
|
|
907
|
+
*
|
|
908
|
+
* Assignment accepts any finite number >= 0 and applies from the
|
|
909
|
+
* current value on. A rate of 0 rests the ramp where it is.
|
|
910
|
+
*/
|
|
911
|
+
get rate(): number;
|
|
912
|
+
set rate(rate: number);
|
|
913
|
+
/**
|
|
914
|
+
* The current velocity, in value units per second. It is `rate`
|
|
915
|
+
* signed toward the target while the ramp moves, and 0 at rest.
|
|
916
|
+
*/
|
|
917
|
+
get velocity(): number;
|
|
918
|
+
/** Always 0, since a ramp moves at a constant speed. */
|
|
919
|
+
get acceleration(): number;
|
|
920
|
+
/**
|
|
921
|
+
* What the ramp drives, `'motion'` or `'nonmotion'`, fixed when the
|
|
922
|
+
* ramp was created. A `'nonmotion'` ramp ignores reduced motion. See
|
|
923
|
+
* `Purpose`.
|
|
924
|
+
*/
|
|
925
|
+
get purpose(): Purpose;
|
|
926
|
+
/**
|
|
927
|
+
* Whether the ramp is still: at its target, at a rate of 0, held under
|
|
928
|
+
* reduced motion, or disposed.
|
|
929
|
+
*/
|
|
930
|
+
get isResting(): boolean;
|
|
931
|
+
/**
|
|
932
|
+
* The time until the ramp reaches its target, in ms. It is 0 at rest,
|
|
933
|
+
* and `Infinity` while the ramp moves toward an endless target.
|
|
934
|
+
*/
|
|
935
|
+
get timeRemaining(): number;
|
|
936
|
+
/**
|
|
937
|
+
* A promise that resolves when the ramp next comes to rest. Already
|
|
938
|
+
* resolved while the ramp rests and after dispose. A pending
|
|
939
|
+
* `settled` keeps a bounded ramp in the frame loop, so the promise
|
|
940
|
+
* resolves on the frame the ramp arrives.
|
|
941
|
+
*
|
|
942
|
+
* ```ts
|
|
943
|
+
* ramp.target = 100
|
|
944
|
+
* await ramp.settled
|
|
945
|
+
* // the ramp is at 100
|
|
946
|
+
* ```
|
|
947
|
+
*/
|
|
948
|
+
get settled(): Promise<void>;
|
|
949
|
+
/**
|
|
950
|
+
* Rests the ramp at `value`, which becomes both its value and target.
|
|
951
|
+
* Notifies update listeners synchronously, and emits `stop` if the ramp
|
|
952
|
+
* was moving.
|
|
953
|
+
*/
|
|
954
|
+
jumpTo(value: number): void;
|
|
955
|
+
/**
|
|
956
|
+
* Releases the ramp permanently. It stops where it is, `settled`
|
|
957
|
+
* resolves, and dispose listeners run. Followers detach and keep their
|
|
958
|
+
* current target. Calling it again does nothing.
|
|
959
|
+
*
|
|
960
|
+
* The final value stays readable, and writes throw.
|
|
961
|
+
*/
|
|
962
|
+
dispose(): void;
|
|
963
|
+
/**
|
|
964
|
+
* Subscribes to value changes: every frame the ramp moves, plus
|
|
965
|
+
* synchronous `value` writes, `jumpTo` calls, and reduced-motion jumps.
|
|
966
|
+
* A subscribed listener keeps the ramp in the frame loop. Returns an
|
|
967
|
+
* unsubscribe function.
|
|
968
|
+
*/
|
|
969
|
+
onUpdate(callback: () => void): () => void;
|
|
970
|
+
/**
|
|
971
|
+
* Subscribes to the ramp leaving rest. `start` and `stop` alternate.
|
|
972
|
+
* Returns an unsubscribe function.
|
|
973
|
+
*/
|
|
974
|
+
onStart(callback: () => void): () => void;
|
|
975
|
+
/**
|
|
976
|
+
* Subscribes to the ramp coming to rest: arriving at its target,
|
|
977
|
+
* `jumpTo`, a rate of 0, or holding under reduced motion. A subscribed
|
|
978
|
+
* listener keeps a bounded ramp in the frame loop, so the event fires
|
|
979
|
+
* on the frame it arrives. Returns an unsubscribe function.
|
|
980
|
+
*/
|
|
981
|
+
onStop(callback: () => void): () => void;
|
|
982
|
+
/** Subscribes to `dispose`, which fires once. Returns an unsubscribe function. */
|
|
983
|
+
onDispose(callback: () => void): () => void;
|
|
984
|
+
}
|
|
985
|
+
//#endregion
|
|
986
|
+
//#region src/ticker.d.ts
|
|
987
|
+
/** Frame timing options for a spring system. */
|
|
988
|
+
interface TickerOptions {
|
|
989
|
+
/**
|
|
990
|
+
* Frame-rate cap, in frames per second. 0 means uncapped: one tick per
|
|
991
|
+
* displayed frame, at whatever rate the screen runs. Capped ticks land
|
|
992
|
+
* on whole display frames near the requested rate, and each receives
|
|
993
|
+
* the true elapsed time. Must be >= 0.
|
|
994
|
+
* @default 0
|
|
995
|
+
*/
|
|
996
|
+
readonly fps?: number | undefined;
|
|
997
|
+
/**
|
|
998
|
+
* The longest frame gap, in ms, that counts as a normal frame. A longer
|
|
999
|
+
* gap, such as a backgrounded tab or a blocking task, is lag, and the
|
|
1000
|
+
* ticker replaces it with `adjustedLag` so springs do not teleport. 0
|
|
1001
|
+
* disables lag clamping and reads back as 0. Must be >= 0.
|
|
1002
|
+
* @default 500
|
|
1003
|
+
*/
|
|
1004
|
+
readonly lagThreshold?: number | undefined;
|
|
1005
|
+
/**
|
|
1006
|
+
* The elapsed time, in ms, that replaces a lagging frame, capped at
|
|
1007
|
+
* `lagThreshold` ms. It reads back as given, even above `lagThreshold`.
|
|
1008
|
+
* Must be >= 0.
|
|
1009
|
+
* @default 33
|
|
1010
|
+
*/
|
|
1011
|
+
readonly adjustedLag?: number | undefined;
|
|
1012
|
+
}
|
|
1013
|
+
//#endregion
|
|
1014
|
+
//#region src/system.d.ts
|
|
1015
|
+
/**
|
|
1016
|
+
* Per-spring options for `SpringSystem.createSpring`, separate from the
|
|
1017
|
+
* physical `config`.
|
|
1018
|
+
*/
|
|
1019
|
+
interface SpringOptions {
|
|
1020
|
+
/**
|
|
1021
|
+
* What the spring animates. Under reduced motion, a `'motion'` spring
|
|
1022
|
+
* snaps to its target and a `'nonmotion'` spring (a cross-fade, a color,
|
|
1023
|
+
* a blur) keeps animating. Fixed for the spring's life. See `Purpose`.
|
|
1024
|
+
* @default 'motion'
|
|
1025
|
+
*/
|
|
1026
|
+
purpose?: Purpose | undefined;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Per-spring options for a composite `SpringSystem.createSpring`, separate
|
|
1030
|
+
* from the physical `config`.
|
|
1031
|
+
*/
|
|
1032
|
+
interface CompositeSpringOptions<T extends object> {
|
|
1033
|
+
/**
|
|
1034
|
+
* What each channel animates, which decides its reduced-motion behavior.
|
|
1035
|
+
* Give one `Purpose` for every channel, or a shape mirroring the value
|
|
1036
|
+
* with purposes at any level. A subtree's purpose covers every channel
|
|
1037
|
+
* below it, and unreached channels default to `'motion'`. Fixed for the
|
|
1038
|
+
* spring's life. See `PurposeShape`.
|
|
1039
|
+
* @default 'motion'
|
|
1040
|
+
*/
|
|
1041
|
+
purpose?: PurposeShape<T> | undefined;
|
|
1042
|
+
}
|
|
1043
|
+
interface SpringSystemOptions extends TickerOptions {
|
|
1044
|
+
/**
|
|
1045
|
+
* How far a spring can trail a source it follows within one frame, in
|
|
1046
|
+
* the value's own units. Frames that would exceed it split into internal
|
|
1047
|
+
* sub-steps (at most 8), keeping followed chains accurate through slow
|
|
1048
|
+
* frames and sudden retargets. Smaller is tighter and costs more solver
|
|
1049
|
+
* work, but never finer than the follower's resting precision. Listeners
|
|
1050
|
+
* still fire once per frame, and springs that follow nothing are
|
|
1051
|
+
* unaffected.
|
|
1052
|
+
* @default 0.1
|
|
1053
|
+
*/
|
|
1054
|
+
couplingTolerance?: number | undefined;
|
|
1055
|
+
/**
|
|
1056
|
+
* Logs the count of active motions to the console after each frame
|
|
1057
|
+
* where it changed.
|
|
1058
|
+
* @default false
|
|
1059
|
+
*/
|
|
1060
|
+
debug?: boolean | undefined;
|
|
1061
|
+
/**
|
|
1062
|
+
* When reduced motion applies, making `'motion'` springs and ramps jump
|
|
1063
|
+
* to their targets instead of animating. `'user'` follows the OS
|
|
1064
|
+
* prefers-reduced-motion setting live, and a switch to reduced finishes
|
|
1065
|
+
* in-flight motion at once. `'always'` and `'never'` force one behavior.
|
|
1066
|
+
* @default 'user'
|
|
1067
|
+
*/
|
|
1068
|
+
reducedMotion?: 'user' | 'always' | 'never' | undefined;
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Owns springs and ramps and advances them over time. Create one with
|
|
1072
|
+
* `createSpringSystem`. Then either `start()` it to animate on real
|
|
1073
|
+
* frames, or call `advance` yourself for manual stepping.
|
|
1074
|
+
*/
|
|
1075
|
+
interface SpringSystem {
|
|
1076
|
+
/**
|
|
1077
|
+
* Creates a spring at rest at `value`. Without `config`, the spring
|
|
1078
|
+
* uses the default: critically damped, settling in about 500 ms. To
|
|
1079
|
+
* follow a source from creation, pass it in place of `value`.
|
|
1080
|
+
*
|
|
1081
|
+
* `options.purpose` marks what the spring animates: `'nonmotion'`
|
|
1082
|
+
* keeps animating under reduced motion, `'motion'` (the default) snaps.
|
|
1083
|
+
*/
|
|
1084
|
+
createSpring(value: number, config?: SpringDefinition, options?: SpringOptions): Spring;
|
|
1085
|
+
/**
|
|
1086
|
+
* Creates a spring that already follows `source`, which can be any
|
|
1087
|
+
* scalar `SpringSource`: a `Spring`, a `Ramp`, or a value derived with
|
|
1088
|
+
* `mapSpring`, `velocityOf`, `accelerationOf`, or `targetOf`. Passing
|
|
1089
|
+
* a composite source throws, so derive a scalar from it with
|
|
1090
|
+
* `mapSpring`. The spring starts at the source's current value, the same
|
|
1091
|
+
* as creating it there and assigning `source` to its `target`.
|
|
1092
|
+
*
|
|
1093
|
+
* `options.purpose` marks what the spring animates: `'nonmotion'`
|
|
1094
|
+
* keeps animating under reduced motion, `'motion'` (the default) snaps.
|
|
1095
|
+
*/
|
|
1096
|
+
createSpring(source: SpringSource, config?: SpringDefinition, options?: SpringOptions): Spring;
|
|
1097
|
+
/**
|
|
1098
|
+
* Creates a composite spring over a numeric shape: a plain object or
|
|
1099
|
+
* array, nested arbitrarily, whose leaves are all numbers. Each leaf
|
|
1100
|
+
* becomes an independently sprung channel.
|
|
1101
|
+
*
|
|
1102
|
+
* `config` applies per channel: a single `SpringDefinition` for every
|
|
1103
|
+
* channel, or a shape mirroring the value with configs at any level.
|
|
1104
|
+
* `options.purpose` marks reduced-motion behavior the same way, per
|
|
1105
|
+
* channel. A `'nonmotion'` channel keeps animating.
|
|
1106
|
+
*/
|
|
1107
|
+
createSpring<T extends object>(value: T & Shape<T>, config?: ConfigShape<T>, options?: CompositeSpringOptions<T>): CompositeSpring<T>;
|
|
1108
|
+
/**
|
|
1109
|
+
* Creates a ramp at `from`: a value that moves in a straight line toward
|
|
1110
|
+
* `options.target` at `options.rate` value units per second, then stops.
|
|
1111
|
+
* Without a target it starts at rest, and `Infinity` or `-Infinity`
|
|
1112
|
+
* makes it endless. A spring following a ramp with the default `arrival`
|
|
1113
|
+
* integrates its steady motion exactly, not a per-frame staircase.
|
|
1114
|
+
*
|
|
1115
|
+
* ```ts
|
|
1116
|
+
* // An endless spin at 270 deg/s, with a spring lagging behind it.
|
|
1117
|
+
* const sweep = system.createRamp(0, { rate: 270, target: Infinity })
|
|
1118
|
+
* const ring = system.createSpring(sweep)
|
|
1119
|
+
*
|
|
1120
|
+
* // A clock: 0 to 600 over 600 ms, mapped into a pulse.
|
|
1121
|
+
* const clock = system.createRamp(0, { rate: 1000, target: 600 })
|
|
1122
|
+
* const pulse = system.createSpring(mapSpring(clock, (ms) => Math.sin((Math.PI * ms) / 600)))
|
|
1123
|
+
* ```
|
|
1124
|
+
*
|
|
1125
|
+
* Under reduced motion, a `'motion'` ramp (the default `purpose`) jumps
|
|
1126
|
+
* to a bounded target and holds still on an endless one. A `'nonmotion'`
|
|
1127
|
+
* ramp keeps moving.
|
|
1128
|
+
*/
|
|
1129
|
+
createRamp(from: number, options: RampOptions): Ramp;
|
|
1130
|
+
/**
|
|
1131
|
+
* Advances every moving spring and ramp by `dt` ms, for manual stepping
|
|
1132
|
+
* in place of `start()`: tests, custom loops, offline rendering. Throws
|
|
1133
|
+
* unless `dt` is finite and >= 0.
|
|
1134
|
+
*/
|
|
1135
|
+
advance(dt: number): void;
|
|
1136
|
+
/**
|
|
1137
|
+
* Begins animating on real frames: one tick per displayed frame, through
|
|
1138
|
+
* `requestAnimationFrame` in the browser and a `setTimeout` fallback
|
|
1139
|
+
* elsewhere. An idle system sleeps, scheduling no frames while every
|
|
1140
|
+
* spring rests and no ramp advances with the frame loop. Throws after
|
|
1141
|
+
* `dispose`.
|
|
1142
|
+
*/
|
|
1143
|
+
start(): void;
|
|
1144
|
+
/** Stops animating. Springs and ramps hold their state until `start` or `advance`. */
|
|
1145
|
+
stop(): void;
|
|
1146
|
+
/**
|
|
1147
|
+
* Whether the system is between `start()` and `stop()`. Sleeping while
|
|
1148
|
+
* idle still counts as running.
|
|
1149
|
+
*/
|
|
1150
|
+
readonly running: boolean;
|
|
1151
|
+
/**
|
|
1152
|
+
* Stops the system for good and removes the page listeners it added at
|
|
1153
|
+
* creation: visibility and, with `reducedMotion: 'user'`, the media
|
|
1154
|
+
* query. Dispose a system you no longer need. `useSpringSystem` disposes
|
|
1155
|
+
* the system it creates on unmount. Calling it again is a no-op.
|
|
1156
|
+
*
|
|
1157
|
+
* After dispose, `start()` throws. `advance` still steps the springs
|
|
1158
|
+
* and ramps, and `reducedMotion` no longer follows the user setting.
|
|
1159
|
+
*/
|
|
1160
|
+
dispose(): void;
|
|
1161
|
+
/**
|
|
1162
|
+
* Whether reduced motion is on, per the `reducedMotion` option and, in
|
|
1163
|
+
* `'user'` mode, the live OS setting. While on, `'motion'` springs and
|
|
1164
|
+
* ramps jump instead of animating, and `'nonmotion'` ones still animate.
|
|
1165
|
+
* Read it to gate decorative effects of your own.
|
|
1166
|
+
*/
|
|
1167
|
+
readonly reducedMotion: boolean;
|
|
1168
|
+
/**
|
|
1169
|
+
* How far a spring can trail a source it follows within one frame, in
|
|
1170
|
+
* the value's own units. See the `couplingTolerance` option.
|
|
1171
|
+
* Assignment accepts any finite number >= 0 and applies from the next
|
|
1172
|
+
* frame. 0 means as fine as the follower's resting precision allows.
|
|
1173
|
+
*/
|
|
1174
|
+
couplingTolerance: number;
|
|
1175
|
+
/**
|
|
1176
|
+
* Frame-rate cap, in frames per second. 0 means uncapped: one tick per
|
|
1177
|
+
* displayed frame, whatever rate the screen runs at. Capped ticks land
|
|
1178
|
+
* on whole display frames and receive the true elapsed time. Assignment
|
|
1179
|
+
* accepts any number >= 0.
|
|
1180
|
+
*/
|
|
1181
|
+
fps: number;
|
|
1182
|
+
/**
|
|
1183
|
+
* Frame gap, in ms, above which the system treats the gap as lag (a
|
|
1184
|
+
* backgrounded tab, a blocking task) and replaces it with `adjustedLag`,
|
|
1185
|
+
* so springs do not teleport when frames resume. Assignment accepts any
|
|
1186
|
+
* number >= 0, and 0 disables lag clamping.
|
|
1187
|
+
*/
|
|
1188
|
+
lagThreshold: number;
|
|
1189
|
+
/**
|
|
1190
|
+
* The elapsed ms that replaces a lagging frame's gap. A frame uses at
|
|
1191
|
+
* most `lagThreshold` ms of it. Reads return the value last set, even
|
|
1192
|
+
* above `lagThreshold`. Assignment accepts any number >= 0.
|
|
1193
|
+
*/
|
|
1194
|
+
adjustedLag: number;
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Creates a spring system: the entry point of the library.
|
|
1198
|
+
*
|
|
1199
|
+
* @example
|
|
1200
|
+
* ```ts
|
|
1201
|
+
* const system = createSpringSystem()
|
|
1202
|
+
* system.start()
|
|
1203
|
+
*
|
|
1204
|
+
* const spring = system.createSpring(0)
|
|
1205
|
+
* spring.onUpdate(() => {
|
|
1206
|
+
* element.style.translate = `${spring.value}px 0`
|
|
1207
|
+
* })
|
|
1208
|
+
* spring.target = 300
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
declare function createSpringSystem(options?: SpringSystemOptions): SpringSystem;
|
|
1212
|
+
//#endregion
|
|
1213
|
+
export { SpringSourceSymbol as A, accelerationOf as C, SourceValues as D, SourceShape as E, SpringSource as O, TargetedSourceApi as S, velocityOf as T, Spring as _, createSpringSystem as a, KinematicSourceApi as b, CompositeSpring as c, PartialShape as d, PurposeShape as f, Purpose as g, TargetShape as h, SpringSystemOptions as i, mapSpring as j, SpringSourceApi as k, CompositeSpringTarget as l, Shape as m, SpringOptions as n, Ramp as o, ReadonlyShape as p, SpringSystem as r, RampOptions as s, CompositeSpringOptions as t, ConfigShape as u, SpringTarget as v, targetOf as w, TargetedSource as x, KinematicSource as y };
|