coily 0.13.1 → 0.14.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
@@ -2,9 +2,9 @@
2
2
 
3
3
  Simulate values using spring physics.
4
4
 
5
- Coily animates numbers — and whole numeric shapes — with damped spring motion. Each frame is computed from the closed-form solution of the spring equation — underdamped, critically damped, or overdamped — rather than numerical integration, so motion doesn't accumulate error and springs can be retargeted mid-flight without losing momentum.
5
+ Coily animates numbers and whole numeric shapes with damped spring motion. It computes each frame from the closed-form solution of the spring equation (underdamped, critically damped, or overdamped) rather than numerical integration, so motion doesn't accumulate error and you can retarget a spring mid-flight without losing momentum.
6
6
 
7
- The core has zero dependencies and runs anywhere (it falls back from `requestAnimationFrame` to `setTimeout` outside the browser). Vue and Nuxt integrations ship as separate entry points; `vue` and `@nuxt/kit` are optional peer dependencies.
7
+ The core has zero dependencies and runs anywhere (it falls back from `requestAnimationFrame` to `setTimeout` outside the browser). Vue and Nuxt integrations ship as separate entry points, with `vue` and `@nuxt/kit` as optional peer dependencies.
8
8
 
9
9
  ## Install
10
10
 
@@ -33,7 +33,7 @@ spring.target = 300
33
33
 
34
34
  ## Configuring springs
35
35
 
36
- `defineSpring` accepts several input shapes; whatever you leave out is derived:
36
+ `defineSpring` accepts several input shapes and derives whatever you leave out:
37
37
 
38
38
  ```ts
39
39
  defineSpring({ tension: 500, damping: 40 }) // direct physical parameters
@@ -43,79 +43,107 @@ defineSpring({ duration: 750, dampingRatio: 1 }) // tuned to settle in ~750ms
43
43
  defineSpring({ duration: 750, bounce: 0.5 })
44
44
  ```
45
45
 
46
- - **`tension`** — stiffness (> 0)
47
- - **`damping`** — friction (≥ 0)
48
- - **`dampingRatio`** — 0 = undamped, < 1 = bouncy, 1 = critically damped, > 1 = overdamped
49
- - **`bounce`** — friendlier alias for damping ratio: −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
- - **`mass`** — defaults to 1
52
- - **`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. Values are never rounded; set precision to match your domain's resolution (see [PRECISION.md](https://github.com/tkofh/coily/blob/main/PRECISION.md))
46
+ - **`tension`**: stiffness (> 0)
47
+ - **`damping`**: friction (>= 0)
48
+ - **`dampingRatio`**: 0 = undamped, < 1 = bouncy, 1 = critically damped, > 1 = overdamped
49
+ - **`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
+ - **`mass`**: defaults to 1
52
+ - **`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))
53
53
 
54
54
  Without a config, springs are critically damped with a ~500ms settle time.
55
55
 
56
56
  ## Spring API
57
57
 
58
- - `spring.target` — set to animate toward a new value
59
- - `spring.value` — current value; writable to displace the spring
60
- - `spring.velocity` — current velocity; writable to fling
61
- - `spring.jumpTo(v)` — snap to a value with no animation
62
- - `spring.config` — assign a new `SpringConfig`, or `null` to revert to the default (or the leader's, if following)
63
- - `spring.isResting`, `spring.timeRemaining` — settle state and estimated ms until rest
64
- - `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
- - `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
- - `spring.dispose()` — release the spring (calling it twice is a no-op)
58
+ - `spring.target`: set to animate toward a new value
59
+ - `spring.value`: current value, writable to displace the spring
60
+ - `spring.velocity`: current velocity, writable to fling
61
+ - `spring.jumpTo(v)`: snap to a value with no animation
62
+ - `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
64
+ - `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
+ - `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
+ - `spring.dispose()`: release the spring (calling it twice is a no-op)
67
67
 
68
68
  ### Chaining
69
69
 
70
- A spring can follow another spring's live value instead of a fixed number:
70
+ A spring can follow another spring's live value instead of a fixed number: assign a spring to `target`, or pass one straight to `createSpring` to follow from birth. `mapSpring` derives new followable values from existing ones (offsets, mirrors, clamps, any pure function of the value):
71
71
 
72
72
  ```ts
73
73
  const leader = system.createSpring(0)
74
- const follower = system.createSpring({ target: leader })
75
- const trailing = system.createSpring({ target: { spring: leader, offset: 20 } })
74
+
75
+ const follower = system.createSpring(leader)
76
+ const trailing = system.createSpring(mapSpring(leader, (v) => v + 20))
77
+ const mirrored = system.createSpring(mapSpring(leader, (v) => -v))
76
78
  ```
77
79
 
78
- Followers inherit the leader's config unless given their own. Assigning a number to `target` unfollows.
80
+ A follower's config is its own: following changes what a spring chases, never how it moves. To match a leader's feel, pass its config at creation — `system.createSpring(leader, leader.config)` — or share a `defineSpring` constant. Assigning a number to `target` unfollows.
81
+
82
+ `mapSpring` also combines several springs: pass a shape (a plain object or array with springs at the leaves, nested arbitrarily) and a function of their values:
83
+
84
+ ```ts
85
+ const x = system.createSpring(0)
86
+ const y = system.createSpring(0)
79
87
 
80
- ### Objects
88
+ const distance = system.createSpring(mapSpring({ x, y }, ({ x, y }) => Math.hypot(x, y)))
89
+ ```
81
90
 
82
- `system.createSpringObject(value, config?)` springs over any numeric shape — a plain object or array whose leaves are all numbers, nested arbitrarily. Each leaf becomes an independent channel behind one composite API:
91
+ Composite springs (below) are sources of their whole value shape, so one map can derive a scalar from every channel at once:
83
92
 
84
93
  ```ts
85
- const spring = system.createSpringObject({ position: { x: 0, y: 0 }, opacity: 1 })
94
+ const point = system.createSpring({ x: 3, y: 4 })
95
+
96
+ const magnitude = system.createSpring(mapSpring(point, ({ x, y }) => Math.hypot(x, y)))
97
+ ```
98
+
99
+ 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.
86
100
 
87
- spring.target = { position: { x: 100 } } // partial — other channels are left alone
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.
102
+
103
+ ### Composites
104
+
105
+ `createSpring` also takes any numeric shape: a plain object or array whose leaves are all numbers, nested arbitrarily. Each leaf becomes an independent channel behind one composite API, a `CompositeSpring`:
106
+
107
+ ```ts
108
+ const spring = system.createSpring({ position: { x: 0, y: 0 }, opacity: 1 })
109
+
110
+ spring.target = { position: { x: 100 } } // a partial target leaves other channels alone
88
111
  spring.value // { position: { x, y }, opacity } — a stable, read-only mirror
89
112
  ```
90
113
 
91
- The shape is fixed at creation, and unknown channels throw with their path (`position.z`). `value`, `velocity`, and `jumpTo` take the same partial shapes. Composite events are coalesced: `update` fires at most once per frame with every channel in its final per-frame state, and `stop` always lands after that frame's final `update`. `settled` and reduced motion compose channel-wise.
114
+ The shape is fixed at creation, and unknown channels throw with their path (`position.z`). `value`, `velocity`, and `jumpTo` take the same partial shapes. Composites coalesce their events: `update` fires at most once per frame with every channel in its final per-frame state, and `stop` always lands after that frame's final `update`. `settled` and reduced motion compose channel-wise.
92
115
 
93
- Shapes are validated at compile time too (the `Shape` type — interfaces like your own `Vector2` work without index signatures): non-numeric, optional, or `undefined`-typed channels are rejected where they're declared.
116
+ The `Shape` type validates shapes at compile time too (interfaces like your own `Vector2` work without index signatures) and rejects non-numeric, optional, or `undefined`-typed channels where they're declared.
94
117
 
95
- Configs apply per channel. Pass a single `SpringConfig` for every channel, or a shape mirroring the value with configs (or `null` to revert) at any level — a config at a subtree covers every channel below it:
118
+ Configs apply per channel. Pass a single `SpringDefinition` for every channel, or a shape mirroring the value with configs (or `null` to revert) at any level. A config at a subtree covers every channel below it:
96
119
 
97
120
  ```ts
98
121
  spring.config = { position: stiff, opacity: defineSpring({ duration: 300, dampingRatio: 1 }) }
99
122
  ```
100
123
 
101
- Configs are `SpringConfig` instances — build them with `defineSpring`. Unlike the scalar `useSpring` above, config positions here don't accept bare option objects: a plain object is always a per-channel shape, so any non-config leaf it reaches throws with its path.
124
+ Configs are `SpringDefinition` instances, built with `defineSpring`. Config positions don't accept bare option objects: a plain object is always a per-channel shape, so any non-config leaf it reaches throws with its path.
102
125
 
103
- Spring objects chain channel-wise. Assign another spring object of the exact same shape (optionally with a partial offset shape), and a partial numeric target detaches only the channels it names:
126
+ Composite springs chain channel-wise. Assign another composite spring of the exact same shape to follow it whole, or name channels individually: each channel of a partial target takes a number or a scalar `SpringSource`. While following, a partial target detaches only the channels it names:
104
127
 
105
128
  ```ts
106
129
  follower.target = leader
107
- trailing.target = { spring: leader, offset: { position: { x: 20 } } }
130
+
131
+ // or mix numbers and live sources per channel
132
+ follower.target = {
133
+ opacity: 0.5,
134
+ position: { x: mapSpring(leader, ({ position }) => -position.x) },
135
+ }
108
136
  ```
109
137
 
110
138
  ## Reduced motion
111
139
 
112
- Coily respects `prefers-reduced-motion` by default. When it's active, springs snap to their targets instead of animating: retargets and value writes apply instantly, velocity impulses are ignored, and springs created displaced start at their target. Events stay coherent — one `update` per change, no `start`/`stop`, and `settled` resolves immediately — so code written against the animated path keeps working.
140
+ Coily respects `prefers-reduced-motion` by default. When it's active, springs snap to their targets instead of animating: retargets and value writes apply instantly, and springs ignore velocity impulses. Events stay coherent (one `update` per change, no `start`/`stop`, and `settled` resolves immediately), so code written against the animated path keeps working.
113
141
 
114
- Control it with the `reducedMotion` system option: `'user'` (default — follow the OS setting, including live changes, which finish in-flight animations instantly), `'always'`, or `'never'`. Read `system.reducedMotion` to gate purely decorative effects (particles, flourishes) in your own code.
142
+ Control it with the `reducedMotion` system option: `'always'`, `'never'`, or the default `'user'`, which follows the OS setting — a live change finishes in-flight animations instantly. Read `system.reducedMotion` to gate decorative effects (particles, flourishes) in your own code.
115
143
 
116
144
  ## Vue
117
145
 
118
- Call `useSpringSystem()` once near the root of your app. It returns the spring system provided by this component or an ancestor; if none exists, it creates one, provides it to descendants, and starts/stops it with the component lifecycle. It's idempotent, and options apply only when a system is actually created:
146
+ Call `useSpringSystem()` once near the root of your app. It returns the spring system provided by this component or an ancestor. If none exists, it creates one, provides it to descendants, and starts/stops it with the component lifecycle. It's idempotent, and options apply only when a system is created:
119
147
 
120
148
  ```ts
121
149
  import { useSpringSystem } from 'coily/vue'
@@ -140,13 +168,15 @@ const x = useSpring(target, { duration: 500, bounce: 0.3 })
140
168
  </template>
141
169
  ```
142
170
 
143
- `useSpring` returns a `SpringRef`: a writable ref of the animated value with `velocity`, `isResting`, and `timeRemaining` refs plus `jumpTo()` attached. The target can be a ref, a getter, or another `SpringRef` (which chains the springs). Options are also reactive — swap configs and the spring reconfigures in place.
171
+ `useSpring` returns a `SpringRef`: a writable ref of the animated value with `velocity`, `isResting`, and `timeRemaining` refs plus `jumpTo()` attached. The target can be a ref, a getter, or another `SpringRef` (which chains the springs). Options are also reactive: swap configs and the spring reconfigures in place.
172
+
173
+ A `SpringRef` is also a `SpringSource`, and `useSpring` follows any source: chain through `mapSpring` (`useSpring(mapSpring({ x, y }, ({ x, y }) => Math.hypot(x, y)))`), or pass a getter of a source to switch leaders reactively (`useSpring(() => (split.value ? left : right))`). Following bypasses Vue reactivity — followers subscribe to the backing spring directly — so an effect or getter never gains a dependency on a leader's animation.
144
174
 
145
- Numeric shapes work the same way: pass a record or array (plain, ref, or getter) and get a `SpringObjectRef`. Reads are the deep-readonly composite value, writes take partial shapes, options accept reactive per-channel config shapes, and passing another `SpringObjectRef` follows it channel-wise. Deeply reactive targets retarget on nested mutation. For several _independent_ scalar springs, map over the targets — composables are loop-safe: `targets.map((t) => useSpring(t))`.
175
+ Numeric shapes work the same way: pass a record or array (plain, ref, or getter) and get a `CompositeSpringRef`. Reads are the deep-readonly composite value, writes take partial shapes, options accept reactive per-channel config shapes, and passing another `CompositeSpringRef` follows it channel-wise. Deeply reactive targets retarget on nested mutation. For several _independent_ scalar springs, map over the targets (composables are loop-safe): `targets.map((t) => useSpring(t))`.
146
176
 
147
177
  There's also a renderless `<SpringValue :target="n">` component exposing `{ value, velocity, isResting, timeRemaining, jumpTo }` through its default slot.
148
178
 
149
- For imperative work — a dynamic set of springs created and disposed at arbitrary times (particles, per-item effects) — `useSpringPool()` returns `createSpring`/`createSpringObject` bound to the provided system. Every spring created through the pool is disposed automatically when the component's scope is torn down, so leaked motions are structurally impossible; disposing a spring manually before that is fine.
179
+ `useSpringPool()` covers imperative work: a dynamic set of springs created and disposed at arbitrary times (particles, per-item effects). It returns `createSpring` bound to the provided system. The pool disposes every spring created through it when the component's scope is torn down, so leaked motions are structurally impossible. Disposing a spring manually before that is fine.
150
180
 
151
181
  ## Nuxt
152
182
 
@@ -164,7 +194,7 @@ The module provides a spring system for the whole app (started on the client), a
164
194
 
165
195
  ## Timing
166
196
 
167
- The built-in ticker advances springs once per displayed frame, so motion is as smooth as the screen it runs on — 60Hz, 120Hz, or adaptive sync. The loop sleeps while every spring is at rest (an idle system schedules no frames) and wakes on the next write. Set `fps` (option/property) to cap the rate; caps are paced to whole display frames, and each tick still receives the true elapsed time. Large frame gaps — e.g. returning from a backgrounded tab — are clamped via `lagThreshold` (default 500ms) and `adjustedLag` (default 33ms), so springs don't teleport. For manual stepping, skip `system.start()` and call `system.advance(dtMs)` yourself.
197
+ The built-in ticker advances springs once per displayed frame, so motion is as smooth as the screen it runs on: 60Hz, 120Hz, or adaptive sync. The loop sleeps while every spring is at rest (an idle system schedules no frames) and wakes on the next write. Set `fps` (option/property) to cap the rate: capped ticks land on whole display frames and still receive the true elapsed time. The ticker clamps large frame gaps (e.g. returning from a backgrounded tab) via `lagThreshold` (default 500ms) and `adjustedLag` (default 33ms), so springs don't teleport. For manual stepping, skip `system.start()` and call `system.advance(dtMs)` yourself.
168
198
 
169
199
  ## License
170
200
 
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as SpringOptions, a as ConfigShape, c as Shape, d as SpringObjectWithOffset, f as Spring, g as SpringConfig, h as SpringWithOffset, i as TickerOptions, l as SpringObject, m as SpringTarget, n as SpringSystemOptions, o as PartialShape, p as SpringPosition, r as createSpringSystem, s as ReadonlyShape, t as SpringSystem, u as SpringObjectTarget, v as SpringState, y as defineSpring } from "./system-86fsXJN_.js";
2
- export { type ConfigShape, type PartialShape, type ReadonlyShape, type Shape, type Spring, type SpringConfig, type SpringObject, type SpringObjectTarget, type SpringObjectWithOffset, type SpringOptions, type SpringPosition, type SpringState, type SpringSystem, type SpringSystemOptions, type SpringTarget, type SpringWithOffset, type TickerOptions, createSpringSystem, defineSpring };
1
+ import { C as SpringDefinitionOptions, S as SpringDefinition, T as defineSpring, _ as accelerationOf, a as createSpringSystem, b as SpringSourceSymbol, c as ConfigShape, g as KinematicSource, h as SpringTarget, i as SpringSystemOptions, m as Spring, n as SpringOptions, o as CompositeSpring, p as Purpose, r as SpringSystem, s as CompositeSpringTarget, t as CompositeSpringOptions, u as PurposeShape, v as velocityOf, w as SpringState, x as mapSpring, y as SpringSource } from "./system-Ci-R4RaI.js";
2
+ export { type CompositeSpring, type CompositeSpringOptions, type CompositeSpringTarget, type ConfigShape, type KinematicSource, type Purpose, type PurposeShape, type Spring, type SpringDefinition, type SpringDefinitionOptions, type SpringOptions, type SpringSource, SpringSourceSymbol, type SpringState, type SpringSystem, type SpringSystemOptions, type SpringTarget, accelerationOf, createSpringSystem, defineSpring, mapSpring, velocityOf };
package/dist/index.js CHANGED
@@ -1,2 +1,78 @@
1
- import { r as defineSpring, t as createSpringSystem } from "./system-Csho09XW.js";
2
- export { createSpringSystem, defineSpring };
1
+ import { i as mapSpring, n as SpringSourceSymbol, o as defineSpring, r as isSpringSource, s as invariant, t as createSpringSystem } from "./system-BXxAHM2a.js";
2
+ //#region src/kinematic-source.ts
3
+ function isKinematicSource(value) {
4
+ if (!isSpringSource(value)) return false;
5
+ const api = value[SpringSourceSymbol];
6
+ return "velocity" in api && "acceleration" in api;
7
+ }
8
+ const NOT_KINEMATIC = "expected a source in motion (a Spring or CompositeSpring); a value derived with mapSpring has neither velocity nor acceleration";
9
+ /**
10
+ * Derives a source from another's velocity — the rate its value changes,
11
+ * in value units per second. `velocityOf(motion)` is a source that reads
12
+ * `motion`'s current velocity, so speed-driven effects fall out of the
13
+ * same follow and `mapSpring` machinery as everything else: a spring can
14
+ * follow it (`blur.target = velocityOf(motion)`) and a map can shape it
15
+ * (`mapSpring(velocityOf(motion), (v) => 1 + Math.abs(v) * 0.001)` for
16
+ * squash and stretch). A scalar source yields a scalar velocity a spring
17
+ * can follow; a `CompositeSpring` or shape yields a velocity of the same
18
+ * shape, mapped to a scalar the way the composite itself is.
19
+ *
20
+ * The result is a stateless view, not a spring: it holds no
21
+ * subscriptions and needs no disposal, and reads report the source's
22
+ * current velocity on the fly. It updates when the source does and is
23
+ * released with it — followers detach then, keeping their current
24
+ * target, as they would from a disposed spring.
25
+ *
26
+ * Only a source in motion qualifies — a `Spring` or a `CompositeSpring`.
27
+ * A value derived with `mapSpring` has no velocity (its rate of change
28
+ * would need the derivative of the map), so it is rejected at the type
29
+ * level and at runtime; take `velocityOf` of the spring the map reads
30
+ * instead.
31
+ */
32
+ function velocityOf(source) {
33
+ invariant(isKinematicSource(source), NOT_KINEMATIC);
34
+ const api = source[SpringSourceSymbol];
35
+ return Object.freeze({ [SpringSourceSymbol]: Object.freeze({
36
+ get value() {
37
+ return api.velocity;
38
+ },
39
+ onUpdate: (callback) => api.onUpdate(callback),
40
+ onDispose: (callback) => api.onDispose(callback)
41
+ }) });
42
+ }
43
+ /**
44
+ * Derives a source from another's acceleration — the rate its velocity
45
+ * changes, in value units per second squared. `accelerationOf(motion)`
46
+ * spikes when `motion` is pushed hardest and passes through zero at the
47
+ * peak of a swing, so force-driven effects fall out of the same follow
48
+ * and `mapSpring` machinery: a spring can follow it, and a map can turn
49
+ * it into an impact flash or a jelly wobble
50
+ * (`mapSpring(accelerationOf(motion), (a) => Math.min(1, Math.abs(a) * 1e-4))`).
51
+ * A scalar source yields a scalar acceleration; a `CompositeSpring` or
52
+ * shape yields an acceleration of the same shape, mapped to a scalar the
53
+ * way the composite itself is.
54
+ *
55
+ * The result is a stateless view, not a spring: it holds no
56
+ * subscriptions and needs no disposal, and reads report the source's
57
+ * current acceleration on the fly. It updates when the source does and
58
+ * is released with it, followers detaching then as from a disposed
59
+ * spring.
60
+ *
61
+ * Only a source in motion qualifies — a `Spring` or a `CompositeSpring`.
62
+ * A value derived with `mapSpring` has no acceleration, so it is rejected
63
+ * at the type level and at runtime; take `accelerationOf` of the spring
64
+ * the map reads instead.
65
+ */
66
+ function accelerationOf(source) {
67
+ invariant(isKinematicSource(source), NOT_KINEMATIC);
68
+ const api = source[SpringSourceSymbol];
69
+ return Object.freeze({ [SpringSourceSymbol]: Object.freeze({
70
+ get value() {
71
+ return api.acceleration;
72
+ },
73
+ onUpdate: (callback) => api.onUpdate(callback),
74
+ onDispose: (callback) => api.onDispose(callback)
75
+ }) });
76
+ }
77
+ //#endregion
78
+ export { SpringSourceSymbol, accelerationOf, createSpringSystem, defineSpring, mapSpring, velocityOf };
package/dist/nuxt.d.ts CHANGED
@@ -1,12 +1,50 @@
1
1
  import { NuxtModule } from "@nuxt/schema";
2
2
  //#region src/vue/nuxt.d.ts
3
+ /**
4
+ * Options for the `coily` key in `nuxt.config`, passed to the app-wide
5
+ * spring system the module creates.
6
+ */
3
7
  interface CoilyModuleOptions {
8
+ /**
9
+ * Log active motion counts to the console whenever they change.
10
+ * @default false
11
+ */
4
12
  debug?: boolean;
13
+ /**
14
+ * Frame-rate cap. 0 means uncapped: one tick per displayed frame.
15
+ * Capped ticks land on whole display frames and receive the true
16
+ * elapsed time.
17
+ * @default 0
18
+ */
5
19
  fps?: number;
20
+ /**
21
+ * Frame gap in milliseconds above which the gap is treated as lag and
22
+ * replaced with `adjustedLag`, so springs don't teleport when frames
23
+ * resume. 0 disables lag clamping.
24
+ * @default 500
25
+ */
6
26
  lagThreshold?: number;
27
+ /**
28
+ * The elapsed milliseconds a lagging frame is replaced with. Clamped
29
+ * to at most `lagThreshold`.
30
+ * @default 33
31
+ */
7
32
  adjustedLag?: number;
33
+ /**
34
+ * When springs snap to their targets instead of animating: `'user'`
35
+ * follows the OS prefers-reduced-motion setting, including live
36
+ * changes; `'always'` and `'never'` force one behavior.
37
+ * @default 'user'
38
+ */
8
39
  reducedMotion?: 'user' | 'always' | 'never';
9
40
  }
41
+ /**
42
+ * The Nuxt module: creates an app-wide spring system (started on the
43
+ * client), auto-imports the composables and helpers `useSpring`,
44
+ * `useSpringSystem`, `useSpringPool`, `defineSpring`, `mapSpring`,
45
+ * `velocityOf`, and `accelerationOf`, and registers the `SpringValue`
46
+ * component. Types are left out — they would be noise in most apps.
47
+ */
10
48
  declare const coilyModule: NuxtModule;
11
49
  //#endregion
12
50
  export { CoilyModuleOptions, coilyModule as default };
package/dist/nuxt.js CHANGED
@@ -21,6 +21,13 @@ export default defineNuxtPlugin((nuxtApp) => {
21
21
  })
22
22
  })`;
23
23
  }
24
+ /**
25
+ * The Nuxt module: creates an app-wide spring system (started on the
26
+ * client), auto-imports the composables and helpers `useSpring`,
27
+ * `useSpringSystem`, `useSpringPool`, `defineSpring`, `mapSpring`,
28
+ * `velocityOf`, and `accelerationOf`, and registers the `SpringValue`
29
+ * component. Types are left out — they would be noise in most apps.
30
+ */
24
31
  const coilyModule = defineNuxtModule({
25
32
  meta: {
26
33
  name: "coily",
@@ -48,28 +55,20 @@ const coilyModule = defineNuxtModule({
48
55
  name: "useSpringPool"
49
56
  },
50
57
  {
51
- from: "coily/vue",
52
- name: "SpringRef",
53
- type: true
54
- },
55
- {
56
- from: "coily/vue",
57
- name: "SpringObjectRef",
58
- type: true
58
+ from: "coily",
59
+ name: "defineSpring"
59
60
  },
60
61
  {
61
- from: "coily/vue",
62
- name: "SpringPool",
63
- type: true
62
+ from: "coily",
63
+ name: "mapSpring"
64
64
  },
65
65
  {
66
66
  from: "coily",
67
- name: "defineSpring"
67
+ name: "velocityOf"
68
68
  },
69
69
  {
70
70
  from: "coily",
71
- name: "SpringConfig",
72
- type: true
71
+ name: "accelerationOf"
73
72
  }
74
73
  ]);
75
74
  addComponent({