coily 0.14.0 → 0.15.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 CHANGED
@@ -41,15 +41,17 @@ defineSpring({ tension: 500, dampingRatio: 0.7 }) // damping derived
41
41
  defineSpring({ tension: 500, bounce: 0.3 }) // bounce = 1 - dampingRatio
42
42
  defineSpring({ duration: 750, dampingRatio: 1 }) // tuned to settle in ~750ms
43
43
  defineSpring({ duration: 750, bounce: 0.5 })
44
+ defineSpring({ tension: 500, bounce: 0.9, arrival: 'stop' }) // dead-stop at the target, no overshoot
44
45
  ```
45
46
 
46
47
  - **`tension`**: stiffness (> 0)
47
48
  - **`damping`**: friction (>= 0)
48
49
  - **`dampingRatio`**: 0 = undamped, < 1 = bouncy, 1 = critically damped, > 1 = overdamped
49
50
  - **`bounce`**: a friendlier alias for damping ratio, from -1 (overdamped) to 1 (max bounce)
50
- - **`duration`**: target settle time in ms. Assumes an initial displacement of 1. Pass `displacement` matching your animation range for accurate timing
51
+ - **`duration`**: settle time in ms — the spring rests at this time, within a frame (a bouncy config can rest up to one oscillation earlier). Assumes an initial displacement of 1. Pass `displacement` matching your animation range for accurate timing
51
52
  - **`mass`**: defaults to 1
52
53
  - **`precision`**: decimal places of the resting threshold (default 2). A spring is _resting_ once its remaining motion cannot reach half a unit in the last place (0.005 at the default). Coily never rounds values. Set `precision` to match your domain's resolution (see [PRECISION.md](https://github.com/tkofh/coily/blob/main/PRECISION.md))
54
+ - **`arrival`**: what the motion does when the value reaches the target. `'passthrough'` (default) swings through and settles; `'stop'` ends the motion exactly on the target the first time it gets there, however bouncy the config; a number between -1 and 1 scales the velocity at every crossing — negative values rebound. Crossings are solved exactly, never sampled frame by frame (see [PRECISION.md](https://github.com/tkofh/coily/blob/main/PRECISION.md))
53
55
 
54
56
  Without a config, springs are critically damped with a ~500ms settle time.
55
57
 
@@ -60,7 +62,7 @@ Without a config, springs are critically damped with a ~500ms settle time.
60
62
  - `spring.velocity`: current velocity, writable to fling
61
63
  - `spring.jumpTo(v)`: snap to a value with no animation
62
64
  - `spring.config`: assign a new `SpringDefinition`, or `null` to revert to the default
63
- - `spring.isResting`, `spring.timeRemaining`: settle state and estimated ms until rest
65
+ - `spring.isResting`, `spring.timeRemaining`: settle state and ms until rest — solved from the motion, not estimated (see [PRECISION.md](https://github.com/tkofh/coily/blob/main/PRECISION.md))
64
66
  - `spring.settled`: a promise that resolves when the spring next comes to rest (immediately if already resting). Retargeting mid-flight extends the wait; disposing resolves it. `await spring.settled` to sequence animations
65
67
  - `spring.onUpdate(cb)` / `onStart(cb)` / `onStop(cb)` / `onDispose(cb)`: subscribe. Each returns an unsubscribe function. `start` fires when the spring leaves rest, `stop` when it settles. The two always alternate, and retargeting mid-flight fires neither
66
68
  - `spring.dispose()`: release the spring (calling it twice is a no-op)
@@ -98,7 +100,11 @@ const magnitude = system.createSpring(mapSpring(point, ({ x, y }) => Math.hypot(
98
100
 
99
101
  A mapped value is a `SpringSource`, the contract `target` accepts and every `Spring` implements. A `CompositeSpring` is a source _of its shape_: `mapSpring` reads it, alone or at the leaves of a shape, but only scalar sources can be followed directly.
100
102
 
101
- Follow graphs may contain cycles: retargets never re-emit, so nothing loops within a frame. Mutual followers converge to a shared value. A cycle whose maps expand (`(v) => v + 10` in both directions) chases forever and never rests, keeping the system awake until you break the cycle.
103
+ Chains advance in dependency order: each frame, a spring moves after the springs it follows — whatever order anything was created or wired in — so a follower always chases its leader's current value rather than last frame's. Update events fire once per spring per frame, after every spring has moved, in that same leader-first order. A callback that reads another spring sees its final value for the frame, and a spring retargeted from inside a callback starts moving on the next frame.
104
+
105
+ Following is accurate within the frame, too: a follower integrates against the path its leader actually traveled, not a value sampled once at the frame boundary, and when a single frame carries more motion than the system's `couplingTolerance` allows (0.1 value units by default), the system splits that frame into internal sub-steps. Dropped frames and teleporting targets refine themselves; update events still fire once per frame. The result is that a chain keeps the same shape at 30fps as at 120fps — see https://github.com/tkofh/coily/blob/main/PRECISION.md for the model.
106
+
107
+ Follow graphs may contain cycles: retargets never re-emit, so nothing loops within a frame. Mutual followers converge to a shared value — the same value at any frame rate. A cycle has no order that puts every member after its leaders, so members advance in creation order and the edge that closes the loop chases one frame behind. A cycle whose maps expand (`(v) => v + 10` in both directions) chases forever and never rests, keeping the system awake until you break the cycle.
102
108
 
103
109
  ### Composites
104
110
 
@@ -0,0 +1,312 @@
1
+ //#region src/config.d.ts
2
+ /**
3
+ * A spring's instantaneous motion, measured relative to its target.
4
+ * `SpringDefinition.computeTimeRemaining` takes one; build it from a live
5
+ * spring as `{ position: spring.value - spring.target, velocity: spring.velocity }`.
6
+ */
7
+ interface SpringState {
8
+ /** Displacement from the target in value units. 0 means at the target. */
9
+ readonly position: number;
10
+ /** Rate of change of the displacement, in value units per second. */
11
+ readonly velocity: number;
12
+ }
13
+ interface BaseOptions {
14
+ /**
15
+ * Decimal places of the resting threshold. A spring rests once its
16
+ * remaining motion cannot reach half a unit in the last place —
17
+ * `0.5 * 10^-precision`, or 0.005 at the default.
18
+ *
19
+ * Values are never rounded; precision only decides rest. See
20
+ * https://github.com/tkofh/coily/blob/main/PRECISION.md.
21
+ *
22
+ * @default 2
23
+ */
24
+ readonly precision?: number | undefined;
25
+ /**
26
+ * What the motion does when the value reaches the target, as a
27
+ * multiplier applied to the velocity at every crossing.
28
+ *
29
+ * - `'passthrough'` — multiplier 1. The motion is untouched: the value
30
+ * swings through the target and settles as its damping dictates.
31
+ * - `'stop'` — multiplier 0. Motion ends at the target the first time
32
+ * the value gets there, with no overshoot, however bouncy the config.
33
+ * - A number between -1 and 1 sets the multiplier directly. Negative
34
+ * values rebound: `-0.75` reverses the motion with three quarters of
35
+ * its speed, at every return. Values between 0 and 1 pass through
36
+ * slowed.
37
+ *
38
+ * Crossings are solved from the motion's closed form, never sampled
39
+ * frame by frame, so a `'stop'` lands the value exactly on the target
40
+ * whatever the frame timing. See
41
+ * https://github.com/tkofh/coily/blob/main/PRECISION.md.
42
+ *
43
+ * @default 'passthrough'
44
+ */
45
+ readonly arrival?: 'passthrough' | 'stop' | number | undefined;
46
+ }
47
+ interface WithMass {
48
+ /**
49
+ * Mass of the moving value. Heavier springs accelerate more slowly and
50
+ * carry more momentum through the target. Must be greater than 0.
51
+ * @default 1
52
+ */
53
+ readonly mass?: number | undefined;
54
+ }
55
+ interface WithoutMass {
56
+ /**
57
+ * Mass is derived from the other parameters in this input shape
58
+ * and cannot be provided.
59
+ */
60
+ readonly mass?: undefined;
61
+ }
62
+ interface WithTension {
63
+ /**
64
+ * Spring stiffness. Higher tension pulls toward the target harder,
65
+ * making the whole motion faster. Must be greater than 0.
66
+ */
67
+ readonly tension: number;
68
+ }
69
+ interface WithDamping {
70
+ /**
71
+ * Friction strength. Higher damping bleeds off velocity faster and
72
+ * reduces bounce; at 0 the spring oscillates forever. Must be greater
73
+ * than or equal to 0.
74
+ */
75
+ readonly damping: number;
76
+ }
77
+ interface WithDampingRatio {
78
+ /**
79
+ * Damping as a fraction of critical damping — the character of the
80
+ * motion, independent of its speed. Below 1 the spring overshoots and
81
+ * bounces. At 1 it settles as fast as possible without overshooting.
82
+ * Above 1 it settles slower, still without overshooting. At 0 it never
83
+ * settles. Must be greater than or equal to 0.
84
+ */
85
+ readonly dampingRatio: number;
86
+ }
87
+ interface WithBounce {
88
+ /**
89
+ * Bounciness, converted to a damping ratio as `1 - bounce`. 0 settles
90
+ * as fast as possible without overshooting. Positive values overshoot
91
+ * and bounce; 1, maximum bounce, is clamped just short of undamped so
92
+ * the spring still settles. Negative values settle without bounce, more
93
+ * slowly. Must be between -1 and 1.
94
+ */
95
+ readonly bounce: number;
96
+ }
97
+ interface WithDuration {
98
+ /**
99
+ * Settle time in milliseconds. The spring is tuned so it rests at this
100
+ * time, assuming it starts `displacement` away from the target: rest
101
+ * lands within a frame of the requested duration, and a bouncy config
102
+ * can rest up to one oscillation earlier. Must be greater than 0.
103
+ */
104
+ readonly duration: number;
105
+ }
106
+ interface WithDisplacement {
107
+ /**
108
+ * The initial displacement the duration tuning assumes. Set it to your
109
+ * animation's range — 300 when animating 0 to 300 — so the settle
110
+ * timing holds; timing skews as the real displacement diverges from
111
+ * this value. Must not be 0.
112
+ * @default 1
113
+ */
114
+ readonly displacement?: number | undefined;
115
+ }
116
+ interface DirectOptions extends BaseOptions, WithMass, WithTension, WithDamping {}
117
+ interface TensionRatioOptions extends BaseOptions, WithMass, WithTension, WithDampingRatio {}
118
+ interface TensionBounceOptions extends BaseOptions, WithMass, WithTension, WithBounce {}
119
+ interface DampingRatioOptions extends BaseOptions, WithMass, WithDamping, WithDampingRatio {}
120
+ interface DampingBounceOptions extends BaseOptions, WithMass, WithDamping, WithBounce {}
121
+ interface TensionDampingRatioOptions extends BaseOptions, WithoutMass, WithTension, WithDamping, WithDampingRatio {}
122
+ interface TensionDampingBounceOptions extends BaseOptions, WithoutMass, WithTension, WithDamping, WithBounce {}
123
+ interface DurationOptions extends BaseOptions, WithMass, WithDampingRatio, WithDuration, WithDisplacement {}
124
+ interface BounceDurationOptions extends BaseOptions, WithMass, WithBounce, WithDuration, WithDisplacement {}
125
+ interface TensionDurationOptions extends BaseOptions, WithoutMass, WithTension, WithDampingRatio, WithDuration, WithDisplacement {}
126
+ interface TensionBounceDurationOptions extends BaseOptions, WithoutMass, WithTension, WithBounce, WithDuration, WithDisplacement {}
127
+ interface DampingDurationOptions extends BaseOptions, WithoutMass, WithDamping, WithDampingRatio, WithDuration, WithDisplacement {}
128
+ interface DampingBounceDurationOptions extends BaseOptions, WithoutMass, WithDamping, WithBounce, WithDuration, WithDisplacement {}
129
+ /** Every option key accepted by at least one `defineSpring` input shape. */
130
+ type SpringOptionKeys = 'mass' | 'tension' | 'damping' | 'dampingRatio' | 'bounce' | 'duration' | 'displacement' | 'precision' | 'arrival';
131
+ /**
132
+ * Marks every option key foreign to `T` as "absent or undefined", so mixing
133
+ * properties from different input shapes fails to type-check instead of
134
+ * silently resolving to an unintended shape at runtime.
135
+ */
136
+ type Exact<T> = T & { [K in Exclude<SpringOptionKeys, keyof T>]?: undefined; };
137
+ /**
138
+ * Every input `defineSpring` accepts: one of the documented parameter
139
+ * combinations, exactly as written — keys from different combinations
140
+ * don't mix.
141
+ */
142
+ type SpringDefinitionOptions = 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>;
143
+ /**
144
+ * Immutable, resolved spring parameters. Whatever `defineSpring` input
145
+ * shape produced it, a config carries concrete `mass`, `tension`,
146
+ * `damping`, and `precision`, plus the quantities derived from them.
147
+ * Instances are frozen and safe to share between springs; to change a
148
+ * spring's behavior, assign a new config via `spring.config`.
149
+ */
150
+ declare class SpringDefinition {
151
+ /** The config for springs created without one: critically damped, settling in about 500ms. */
152
+ static readonly default: SpringDefinition;
153
+ /** Mass of the moving value, as provided or derived. */
154
+ readonly mass: number;
155
+ /** Spring stiffness, as provided or derived. */
156
+ readonly tension: number;
157
+ /** Friction strength, as provided or derived. */
158
+ readonly damping: number;
159
+ /** Decimal places of the resting threshold — see `restingMagnitude`. */
160
+ readonly precision: number;
161
+ /**
162
+ * Velocity multiplier applied when the value crosses the target, as
163
+ * provided or resolved from its named form. 1 (`'passthrough'`) leaves
164
+ * the motion untouched, 0 (`'stop'`) ends it at the target, negative
165
+ * values rebound.
166
+ */
167
+ readonly arrival: number;
168
+ /** Oscillation rate with no damping: `sqrt(tension / mass)`, in radians per second. */
169
+ readonly naturalFrequency: number;
170
+ /** The damping at which bounce disappears: `2 * mass * naturalFrequency`. */
171
+ readonly criticalDamping: number;
172
+ /**
173
+ * `damping / criticalDamping`. Below 1 the spring overshoots and
174
+ * bounces, at 1 it settles fastest without overshooting, above 1 it
175
+ * settles slower.
176
+ */
177
+ readonly dampingRatio: number;
178
+ /** Resting threshold in value units: half a unit in the last `precision` place. */
179
+ readonly restingMagnitude: number;
180
+ constructor(input: SpringDefinitionOptions);
181
+ /**
182
+ * Computes when a spring with this config comes to rest from `state`,
183
+ * in ms.
184
+ *
185
+ * The time is solved from the motion's decay bound rather than
186
+ * estimated: the spring is resting at the first tick at or after it.
187
+ * An underdamped spring can also rest earlier — its rest amplitude
188
+ * pulses, and a frame that samples a dip inside the resting threshold
189
+ * rests there — so read the value as "no later than", tight in
190
+ * practice. See
191
+ * https://github.com/tkofh/coily/blob/main/PRECISION.md.
192
+ *
193
+ * Returns 0 when `state` is already inside the resting threshold.
194
+ * Returns Infinity when the motion never settles: a `dampingRatio` of
195
+ * 0 whose `arrival` neither stops nor slows it. When `arrival` is 0
196
+ * the result is capped at the first target crossing, where such a
197
+ * spring rests exactly; other multipliers fold their per-crossing
198
+ * velocity loss into the time.
199
+ */
200
+ computeTimeRemaining(state: SpringState): number;
201
+ }
202
+ /**
203
+ * Creates a config from direct physical parameters: you set stiffness
204
+ * and friction exactly.
205
+ */
206
+ declare function defineSpring(input: Exact<DirectOptions>): SpringDefinition;
207
+ /**
208
+ * Creates a config from stiffness and motion character. Damping is
209
+ * derived as `2 * dampingRatio * sqrt(mass * tension)`.
210
+ */
211
+ declare function defineSpring(input: Exact<TensionRatioOptions>): SpringDefinition;
212
+ /**
213
+ * Creates a config from stiffness and bounciness. Damping is derived to
214
+ * match the requested bounce, from -1 (no bounce, slow settle) to 1
215
+ * (maximum bounce).
216
+ */
217
+ declare function defineSpring(input: Exact<TensionBounceOptions>): SpringDefinition;
218
+ /**
219
+ * Creates a config from friction and motion character. Tension is
220
+ * derived as `damping^2 / (4 * dampingRatio^2 * mass)`; `dampingRatio`
221
+ * must be greater than 0.
222
+ */
223
+ declare function defineSpring(input: Exact<DampingRatioOptions>): SpringDefinition;
224
+ /**
225
+ * Creates a config from friction and bounciness. Tension is derived to
226
+ * match the requested bounce; `bounce` must be less than 1.
227
+ */
228
+ declare function defineSpring(input: Exact<DampingBounceOptions>): SpringDefinition;
229
+ /**
230
+ * Creates a config from all three physical knobs. Mass is derived as
231
+ * `damping^2 / (4 * dampingRatio^2 * tension)` and cannot be provided;
232
+ * `dampingRatio` must be greater than 0.
233
+ */
234
+ declare function defineSpring(input: Exact<TensionDampingRatioOptions>): SpringDefinition;
235
+ /**
236
+ * Creates a config from all three physical knobs. Mass is derived from
237
+ * tension, damping, and the requested bounce, and cannot be provided;
238
+ * `bounce` must be less than 1.
239
+ */
240
+ declare function defineSpring(input: Exact<TensionDampingBounceOptions>): SpringDefinition;
241
+ /**
242
+ * Tunes the spring to rest at `duration` milliseconds, with
243
+ * `dampingRatio` setting the motion's character. Tension and damping are
244
+ * both derived.
245
+ *
246
+ * The timing assumes the motion starts `displacement` (default 1) away
247
+ * from the target — pass a `displacement` matching your animation range
248
+ * for accurate timing.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * // Tuned for a 300px move; rests within 750ms
253
+ * defineSpring({ duration: 750, dampingRatio: 1, displacement: 300 })
254
+ * ```
255
+ */
256
+ declare function defineSpring(input: Exact<DurationOptions>): SpringDefinition;
257
+ /**
258
+ * Tunes the spring to rest at `duration` milliseconds, with
259
+ * `bounce` setting how oscillatory the settling motion is. Tension and
260
+ * damping are both derived.
261
+ *
262
+ * The timing assumes the motion starts `displacement` (default 1) away
263
+ * from the target — pass a `displacement` matching your animation range
264
+ * for accurate timing.
265
+ */
266
+ declare function defineSpring(input: Exact<BounceDurationOptions>): SpringDefinition;
267
+ /**
268
+ * Tunes a spring of the given stiffness to rest at `duration`
269
+ * milliseconds. Mass is derived from tension and the computed natural
270
+ * frequency, then damping from mass and `dampingRatio`; mass cannot be
271
+ * provided.
272
+ *
273
+ * The timing assumes the motion starts `displacement` (default 1) away
274
+ * from the target — pass a `displacement` matching your animation range
275
+ * for accurate timing.
276
+ */
277
+ declare function defineSpring(input: Exact<TensionDurationOptions>): SpringDefinition;
278
+ /**
279
+ * Tunes a spring of the given stiffness to rest at `duration`
280
+ * milliseconds, with `bounce` setting how oscillatory the settling motion
281
+ * is. Mass is derived from tension and the computed natural frequency,
282
+ * and cannot be provided.
283
+ *
284
+ * The timing assumes the motion starts `displacement` (default 1) away
285
+ * from the target — pass a `displacement` matching your animation range
286
+ * for accurate timing.
287
+ */
288
+ declare function defineSpring(input: Exact<TensionBounceDurationOptions>): SpringDefinition;
289
+ /**
290
+ * Tunes a spring of the given friction to rest at `duration`
291
+ * milliseconds. Mass is derived from damping, `dampingRatio`, and the
292
+ * computed natural frequency, then tension from mass; mass cannot be
293
+ * provided.
294
+ *
295
+ * The timing assumes the motion starts `displacement` (default 1) away
296
+ * from the target — pass a `displacement` matching your animation range
297
+ * for accurate timing.
298
+ */
299
+ declare function defineSpring(input: Exact<DampingDurationOptions>): SpringDefinition;
300
+ /**
301
+ * Tunes a spring of the given friction to rest at `duration`
302
+ * milliseconds, with `bounce` setting how oscillatory the settling motion
303
+ * is. Mass is derived from damping and the computed natural frequency,
304
+ * and cannot be provided.
305
+ *
306
+ * The timing assumes the motion starts `displacement` (default 1) away
307
+ * from the target — pass a `displacement` matching your animation range
308
+ * for accurate timing.
309
+ */
310
+ declare function defineSpring(input: Exact<DampingBounceDurationOptions>): SpringDefinition;
311
+ //#endregion
312
+ export { defineSpring as i, SpringDefinitionOptions as n, SpringState as r, SpringDefinition as t };
package/dist/css.d.ts ADDED
@@ -0,0 +1,175 @@
1
+ import { r as SpringState, t as SpringDefinition } from "./config-OOMMRdK8.js";
2
+ //#region src/css.d.ts
3
+ interface LinearEasingOptions {
4
+ /**
5
+ * Animation range the duration is tuned for, in value units. The easing
6
+ * shape is identical regardless; only the settle time scales with it.
7
+ * The keyframe helpers (`springToWaapi`, `springToCss`,
8
+ * `springToTransition`) default it to the largest move among their
9
+ * specs instead.
10
+ * @default 1
11
+ */
12
+ readonly displacement?: number;
13
+ /**
14
+ * Max output error of the piecewise-linear approximation, in progress
15
+ * units (0..1). Smaller keeps more stops.
16
+ * @default 0.0025
17
+ */
18
+ readonly maxError?: number;
19
+ /**
20
+ * Hard cap on generated duration, in ms, for near-undamped configs.
21
+ * @default 10000
22
+ */
23
+ readonly maxDuration?: number;
24
+ }
25
+ interface EasingBase {
26
+ /** A CSS `linear()` easing string. */
27
+ readonly easing: string;
28
+ /** Duration to pair the easing with, in ms. */
29
+ readonly duration: number;
30
+ /** Number of stops in the easing (diagnostic). */
31
+ readonly stops: number;
32
+ /** Worst reconstruction error vs the dense trajectory (diagnostic). */
33
+ readonly maxError: number;
34
+ }
35
+ /** The easing of a spring that comes to rest: play it once over `duration`. */
36
+ interface SettlingEasing extends EasingBase {
37
+ readonly mode: 'settle';
38
+ }
39
+ /**
40
+ * The easing of a spring that never rests — an undamped oscillation,
41
+ * expressed as a seamless loop. Animate the property between its two
42
+ * swing extremes (`from` and `2 * target - from`, target at the 50%
43
+ * midpoint) with `animation-iteration-count: infinite` and
44
+ * `animation-direction: alternate`. `duration` is one half period.
45
+ */
46
+ interface LoopingEasing extends EasingBase {
47
+ readonly mode: 'loop';
48
+ readonly direction: 'alternate';
49
+ readonly iterations: 'infinite';
50
+ }
51
+ type LinearEasing = SettlingEasing | LoopingEasing;
52
+ /**
53
+ * Turns a resolved spring config into a CSS `linear()` easing and the
54
+ * duration in ms to pair it with. A spring that settles returns a
55
+ * `'settle'` easing. A pure undamped config (`dampingRatio: 0` with
56
+ * passthrough `arrival`) has no friction and never settles, so it
57
+ * returns a `'loop'` easing for an infinite alternating animation.
58
+ */
59
+ declare function springToLinear(config: SpringDefinition, options?: LinearEasingOptions): LinearEasing;
60
+ /**
61
+ * Like `springToLinear`, but from a spring caught mid-flight rather than at
62
+ * rest: `state` carries both the displacement from the target (`position`)
63
+ * and the current `velocity`, so the easing continues the motion smoothly
64
+ * instead of restarting. Use it to regenerate an animation when its target
65
+ * changes — the interruption carries momentum instead of stalling. The
66
+ * from-rest shape trick doesn't apply here (the curve now depends on the
67
+ * velocity), so this is computed per interruption, not cached per config.
68
+ *
69
+ * Always a settling easing; `position` must be nonzero.
70
+ */
71
+ declare function springFromState(config: SpringDefinition, state: SpringState, options?: LinearEasingOptions): LinearEasing;
72
+ /**
73
+ * Evolves a spring `state` forward by `elapsedMs`, returning the new
74
+ * displacement and velocity. Pair it with a running `element.animate` — read
75
+ * the animation's `currentTime`, evolve the state it started from, and you
76
+ * have the exact live velocity the Web Animations API never exposes, ready
77
+ * to hand to `springFromState` on interruption.
78
+ */
79
+ declare function springStateAt(config: SpringDefinition, state: SpringState, elapsedMs: number): SpringState;
80
+ /** What to animate: a CSS property from one numeric value to another. */
81
+ interface PropertySpec {
82
+ /** The CSS property, e.g. `'opacity'`, `'transform'`, `'translate'`. */
83
+ readonly property: string;
84
+ /** Start value. */
85
+ readonly from: number;
86
+ /** Target value the spring is tuned toward. */
87
+ readonly to: number;
88
+ /**
89
+ * Unit appended to numbers, e.g. `'px'`, `'%'`, `'deg'`.
90
+ * @default ''
91
+ */
92
+ readonly unit?: string;
93
+ /**
94
+ * Formats an interpolated number into a property value, overriding
95
+ * `unit` — needed for wrapped values like `(v) => `translateX(${v}px)``.
96
+ */
97
+ readonly format?: (value: number) => string;
98
+ /**
99
+ * The property's current velocity, in its units per second. Set it to
100
+ * regenerate an interrupted animation from its live motion so it carries
101
+ * momentum instead of restarting from rest. Single-property only — a
102
+ * from-state easing depends on that property's velocity and can't be
103
+ * shared across properties.
104
+ */
105
+ readonly velocity?: number;
106
+ }
107
+ interface CssOptions extends LinearEasingOptions {
108
+ /**
109
+ * Name for the generated `@keyframes` rule.
110
+ * @default 'coily'
111
+ */
112
+ readonly name?: string;
113
+ }
114
+ /**
115
+ * Builds arguments for `element.animate(keyframes, options)`: two keyframes
116
+ * carrying the endpoint values, and options carrying the spring's `linear()`
117
+ * easing and duration. Pass an array of specs to drive several properties
118
+ * from one spring. A settling spring fills forwards; an undamped one repeats
119
+ * infinitely in alternating directions.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * const { keyframes, options } = springToWaapi(config, {
124
+ * property: 'translate',
125
+ * from: 0,
126
+ * to: 300,
127
+ * unit: 'px',
128
+ * })
129
+ * element.animate(keyframes, options)
130
+ * ```
131
+ */
132
+ declare function springToWaapi(config: SpringDefinition, spec: PropertySpec | PropertySpec[], options?: LinearEasingOptions): {
133
+ keyframes: Keyframe[];
134
+ options: KeyframeAnimationOptions;
135
+ };
136
+ /**
137
+ * Builds CSS text for the animation: a `@keyframes` rule and an `animation`
138
+ * shorthand value, driving one property or several from one spring. The
139
+ * `name` option (default `'coily'`) names the `@keyframes` rule and is
140
+ * referenced by the `animation` value.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * const { keyframes, animation } = springToCss(config, {
145
+ * property: 'translate',
146
+ * from: 0,
147
+ * to: 300,
148
+ * unit: 'px',
149
+ * })
150
+ * const style = document.createElement('style')
151
+ * style.textContent = keyframes
152
+ * document.head.append(style)
153
+ * element.style.animation = animation
154
+ * ```
155
+ */
156
+ declare function springToCss(config: SpringDefinition, spec: PropertySpec | PropertySpec[], options?: CssOptions): {
157
+ keyframes: string;
158
+ animation: string;
159
+ };
160
+ /**
161
+ * Builds a CSS `transition` value that springs a property change: set it on
162
+ * the element, then change the property (on `:hover`, a toggled class, a
163
+ * state attribute) to animate. Pass several specs for one `transition`
164
+ * across properties.
165
+ *
166
+ * Only settling springs — a transition can't loop. It also can't carry
167
+ * momentum: a change interrupted mid-flight restarts the spring from rest
168
+ * instead of reversing through its current velocity, so it stalls at the
169
+ * turn. For motion that's reversed often, drive a live `Spring` instead. The
170
+ * specs' `from`/`to` only tune the duration; the actual values live in your
171
+ * CSS rules.
172
+ */
173
+ declare function springToTransition(config: SpringDefinition, spec: PropertySpec | PropertySpec[], options?: LinearEasingOptions): string;
174
+ //#endregion
175
+ export { CssOptions, LinearEasing, LinearEasingOptions, LoopingEasing, PropertySpec, SettlingEasing, springFromState, springStateAt, springToCss, springToLinear, springToTransition, springToWaapi };