@vysmo/easings 0.1.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.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +368 -0
  3. package/dist/builders/anticipate.d.ts +20 -0
  4. package/dist/builders/anticipate.d.ts.map +1 -0
  5. package/dist/builders/anticipate.js +52 -0
  6. package/dist/builders/anticipate.js.map +1 -0
  7. package/dist/builders/bezier.d.ts +7 -0
  8. package/dist/builders/bezier.d.ts.map +1 -0
  9. package/dist/builders/bezier.js +69 -0
  10. package/dist/builders/bezier.js.map +1 -0
  11. package/dist/builders/breathe.d.ts +11 -0
  12. package/dist/builders/breathe.d.ts.map +1 -0
  13. package/dist/builders/breathe.js +14 -0
  14. package/dist/builders/breathe.js.map +1 -0
  15. package/dist/builders/custom.d.ts +13 -0
  16. package/dist/builders/custom.d.ts.map +1 -0
  17. package/dist/builders/custom.js +40 -0
  18. package/dist/builders/custom.js.map +1 -0
  19. package/dist/builders/expoScale.d.ts +13 -0
  20. package/dist/builders/expoScale.d.ts.map +1 -0
  21. package/dist/builders/expoScale.js +27 -0
  22. package/dist/builders/expoScale.js.map +1 -0
  23. package/dist/builders/gravity.d.ts +12 -0
  24. package/dist/builders/gravity.d.ts.map +1 -0
  25. package/dist/builders/gravity.js +11 -0
  26. package/dist/builders/gravity.js.map +1 -0
  27. package/dist/builders/index.d.ts +12 -0
  28. package/dist/builders/index.d.ts.map +1 -0
  29. package/dist/builders/index.js +12 -0
  30. package/dist/builders/index.js.map +1 -0
  31. package/dist/builders/rough.d.ts +17 -0
  32. package/dist/builders/rough.d.ts.map +1 -0
  33. package/dist/builders/rough.js +62 -0
  34. package/dist/builders/rough.js.map +1 -0
  35. package/dist/builders/slow.d.ts +16 -0
  36. package/dist/builders/slow.d.ts.map +1 -0
  37. package/dist/builders/slow.js +59 -0
  38. package/dist/builders/slow.js.map +1 -0
  39. package/dist/builders/spring-presets.d.ts +48 -0
  40. package/dist/builders/spring-presets.d.ts.map +1 -0
  41. package/dist/builders/spring-presets.js +19 -0
  42. package/dist/builders/spring-presets.js.map +1 -0
  43. package/dist/builders/spring.d.ts +12 -0
  44. package/dist/builders/spring.d.ts.map +1 -0
  45. package/dist/builders/spring.js +46 -0
  46. package/dist/builders/spring.js.map +1 -0
  47. package/dist/builders/wiggle.d.ts +9 -0
  48. package/dist/builders/wiggle.d.ts.map +1 -0
  49. package/dist/builders/wiggle.js +23 -0
  50. package/dist/builders/wiggle.js.map +1 -0
  51. package/dist/css.d.ts +40 -0
  52. package/dist/css.d.ts.map +1 -0
  53. package/dist/css.js +71 -0
  54. package/dist/css.js.map +1 -0
  55. package/dist/define.d.ts +12 -0
  56. package/dist/define.d.ts.map +1 -0
  57. package/dist/define.js +31 -0
  58. package/dist/define.js.map +1 -0
  59. package/dist/easings/back.d.ts +8 -0
  60. package/dist/easings/back.d.ts.map +1 -0
  61. package/dist/easings/back.js +20 -0
  62. package/dist/easings/back.js.map +1 -0
  63. package/dist/easings/bounce.d.ts +4 -0
  64. package/dist/easings/bounce.d.ts.map +1 -0
  65. package/dist/easings/bounce.js +21 -0
  66. package/dist/easings/bounce.js.map +1 -0
  67. package/dist/easings/circ.d.ts +4 -0
  68. package/dist/easings/circ.d.ts.map +1 -0
  69. package/dist/easings/circ.js +7 -0
  70. package/dist/easings/circ.js.map +1 -0
  71. package/dist/easings/elastic.d.ts +9 -0
  72. package/dist/easings/elastic.d.ts.map +1 -0
  73. package/dist/easings/elastic.js +33 -0
  74. package/dist/easings/elastic.js.map +1 -0
  75. package/dist/easings/expo.d.ts +4 -0
  76. package/dist/easings/expo.d.ts.map +1 -0
  77. package/dist/easings/expo.js +11 -0
  78. package/dist/easings/expo.js.map +1 -0
  79. package/dist/easings/index.d.ts +11 -0
  80. package/dist/easings/index.d.ts.map +1 -0
  81. package/dist/easings/index.js +11 -0
  82. package/dist/easings/index.js.map +1 -0
  83. package/dist/easings/linear.d.ts +3 -0
  84. package/dist/easings/linear.d.ts.map +1 -0
  85. package/dist/easings/linear.js +4 -0
  86. package/dist/easings/linear.js.map +1 -0
  87. package/dist/easings/power.d.ts +25 -0
  88. package/dist/easings/power.d.ts.map +1 -0
  89. package/dist/easings/power.js +29 -0
  90. package/dist/easings/power.js.map +1 -0
  91. package/dist/easings/sine.d.ts +4 -0
  92. package/dist/easings/sine.d.ts.map +1 -0
  93. package/dist/easings/sine.js +6 -0
  94. package/dist/easings/sine.js.map +1 -0
  95. package/dist/easings/smooth.d.ts +4 -0
  96. package/dist/easings/smooth.d.ts.map +1 -0
  97. package/dist/easings/smooth.js +21 -0
  98. package/dist/easings/smooth.js.map +1 -0
  99. package/dist/easings/steps.d.ts +8 -0
  100. package/dist/easings/steps.d.ts.map +1 -0
  101. package/dist/easings/steps.js +16 -0
  102. package/dist/easings/steps.js.map +1 -0
  103. package/dist/index.d.ts +10 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +8 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/modifiers/blend.d.ts +13 -0
  108. package/dist/modifiers/blend.d.ts.map +1 -0
  109. package/dist/modifiers/blend.js +21 -0
  110. package/dist/modifiers/blend.js.map +1 -0
  111. package/dist/modifiers/chain.d.ts +18 -0
  112. package/dist/modifiers/chain.d.ts.map +1 -0
  113. package/dist/modifiers/chain.js +40 -0
  114. package/dist/modifiers/chain.js.map +1 -0
  115. package/dist/modifiers/index.d.ts +7 -0
  116. package/dist/modifiers/index.d.ts.map +1 -0
  117. package/dist/modifiers/index.js +7 -0
  118. package/dist/modifiers/index.js.map +1 -0
  119. package/dist/modifiers/mirror.d.ts +8 -0
  120. package/dist/modifiers/mirror.d.ts.map +1 -0
  121. package/dist/modifiers/mirror.js +14 -0
  122. package/dist/modifiers/mirror.js.map +1 -0
  123. package/dist/modifiers/reverse.d.ts +4 -0
  124. package/dist/modifiers/reverse.d.ts.map +1 -0
  125. package/dist/modifiers/reverse.js +6 -0
  126. package/dist/modifiers/reverse.js.map +1 -0
  127. package/dist/modifiers/slice.d.ts +11 -0
  128. package/dist/modifiers/slice.d.ts.map +1 -0
  129. package/dist/modifiers/slice.js +28 -0
  130. package/dist/modifiers/slice.js.map +1 -0
  131. package/dist/modifiers/yoyo.d.ts +8 -0
  132. package/dist/modifiers/yoyo.d.ts.map +1 -0
  133. package/dist/modifiers/yoyo.js +10 -0
  134. package/dist/modifiers/yoyo.js.map +1 -0
  135. package/dist/parse.d.ts +14 -0
  136. package/dist/parse.d.ts.map +1 -0
  137. package/dist/parse.js +108 -0
  138. package/dist/parse.js.map +1 -0
  139. package/dist/reduced-motion.d.ts +17 -0
  140. package/dist/reduced-motion.d.ts.map +1 -0
  141. package/dist/reduced-motion.js +24 -0
  142. package/dist/reduced-motion.js.map +1 -0
  143. package/dist/types.d.ts +8 -0
  144. package/dist/types.d.ts.map +1 -0
  145. package/dist/types.js +2 -0
  146. package/dist/types.js.map +1 -0
  147. package/package.json +63 -0
  148. package/src/__tests__/anticipate-variants.test.ts +58 -0
  149. package/src/__tests__/builders.test.ts +349 -0
  150. package/src/__tests__/contract.test.ts +47 -0
  151. package/src/__tests__/css.test.ts +93 -0
  152. package/src/__tests__/easings.bench.ts +66 -0
  153. package/src/__tests__/endpoint-correctness.test.ts +170 -0
  154. package/src/__tests__/modifiers.test.ts +134 -0
  155. package/src/__tests__/parametric.test.ts +148 -0
  156. package/src/__tests__/parse.test.ts +71 -0
  157. package/src/__tests__/property.test.ts +110 -0
  158. package/src/__tests__/reduced-motion.test.ts +66 -0
  159. package/src/__tests__/slice.test.ts +38 -0
  160. package/src/__tests__/spring-presets.test.ts +48 -0
  161. package/src/__tests__/ssr.test.ts +62 -0
  162. package/src/__tests__/types-check.ts +104 -0
  163. package/src/builders/anticipate.ts +66 -0
  164. package/src/builders/bezier.ts +71 -0
  165. package/src/builders/breathe.ts +31 -0
  166. package/src/builders/custom.ts +43 -0
  167. package/src/builders/expoScale.ts +30 -0
  168. package/src/builders/gravity.ts +27 -0
  169. package/src/builders/index.ts +24 -0
  170. package/src/builders/rough.ts +83 -0
  171. package/src/builders/slow.ts +72 -0
  172. package/src/builders/spring-presets.ts +20 -0
  173. package/src/builders/spring.ts +61 -0
  174. package/src/builders/wiggle.ts +40 -0
  175. package/src/css.ts +79 -0
  176. package/src/define.ts +49 -0
  177. package/src/easings/back.ts +24 -0
  178. package/src/easings/bounce.ts +23 -0
  179. package/src/easings/circ.ts +9 -0
  180. package/src/easings/elastic.ts +52 -0
  181. package/src/easings/expo.ts +9 -0
  182. package/src/easings/index.ts +35 -0
  183. package/src/easings/linear.ts +4 -0
  184. package/src/easings/power.ts +38 -0
  185. package/src/easings/sine.ts +7 -0
  186. package/src/easings/smooth.ts +25 -0
  187. package/src/easings/steps.ts +25 -0
  188. package/src/index.ts +9 -0
  189. package/src/modifiers/blend.ts +24 -0
  190. package/src/modifiers/chain.ts +63 -0
  191. package/src/modifiers/index.ts +6 -0
  192. package/src/modifiers/mirror.ts +14 -0
  193. package/src/modifiers/reverse.ts +7 -0
  194. package/src/modifiers/slice.ts +29 -0
  195. package/src/modifiers/yoyo.ts +15 -0
  196. package/src/parse.ts +167 -0
  197. package/src/reduced-motion.ts +26 -0
  198. package/src/types.ts +8 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maesto LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,368 @@
1
+ # @vysmo/easings
2
+
3
+ 22 easing families (linear, power1–4, sine, circ, expo, smooth, back, elastic, bounce, steps, bezier, spring, rough, wiggle, slow, anticipate, expoScale, gravity, breathe) + composition modifiers (chain, reverse, mirror, yoyo, blend, slice). Pure math, zero deps. CSS export via `toCSSLinear` / `toCSSBezier`; reduced-motion helpers; GSAP-style string parser.
4
+
5
+ [Live curves explorer](https://vysmo.com/easings) · [Source](https://github.com/vysmodev)
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @vysmo/easings
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ In JavaScript — pass any easing as the `ease` option:
16
+
17
+ ```ts
18
+ import { animate } from "@vysmo/animations";
19
+ import { power2Out } from "@vysmo/easings";
20
+
21
+ animate({
22
+ from: 0,
23
+ to: 1,
24
+ duration: 600,
25
+ ease: power2Out,
26
+ onUpdate: (v) => element.style.opacity = String(v),
27
+ });
28
+ ```
29
+
30
+ In CSS — bake any easing into a `linear()` string:
31
+
32
+ ```ts
33
+ import { toCSSLinear } from "@vysmo/easings/css";
34
+ import { spring } from "@vysmo/easings";
35
+
36
+ const ease = spring.with({ stiffness: 220, damping: 18 });
37
+
38
+ document.documentElement.style.setProperty(
39
+ "--ease-pop",
40
+ toCSSLinear(ease, 32),
41
+ );
42
+ ```
43
+
44
+ Every export is just a `(t: number) => number` (an `EasingFn`). Use with `animate()`, your own rAF loop, baked to CSS, or anything that takes an easing function. Parametric easings like `spring.with({ ... })` and `bezier(0.25, 0.1, 0.25, 1)` return the same shape — see the catalog below for every option.
45
+
46
+ ## Catalog
47
+
48
+ <!-- catalog:start -->
49
+
50
+ Every shipped easing with its variants and parameters. The catalog mirrors the playground at [vysmo.com/easings/docs#catalog](https://vysmo.com/easings/docs#catalog). Categorisation tracks the authoring shape — Core (constant curves), Parametric (curves with `.with({ ... })`), Builder (factory functions).
51
+
52
+ ### Core
53
+
54
+ #### `linear`
55
+
56
+ No easing — constant velocity.
57
+
58
+ **Export:** `linear`
59
+
60
+ #### `power1`
61
+
62
+ Quadratic (t²). Mildest power curve.
63
+
64
+ **Variants:** `power1In` · `power1Out` · `power1InOut`
65
+
66
+ #### `power2 (cubic)`
67
+
68
+ Cubic (t³). Workhorse default — CSS's ease is close to power2.out.
69
+
70
+ **Variants:** `power2In` · `power2Out` · `power2InOut`
71
+
72
+ #### `power3 (quart)`
73
+
74
+ Quartic (t⁴). More pronounced easing.
75
+
76
+ **Variants:** `power3In` · `power3Out` · `power3InOut`
77
+
78
+ #### `power4 (quint)`
79
+
80
+ Quintic (t⁵). Dramatic acceleration.
81
+
82
+ **Variants:** `power4In` · `power4Out` · `power4InOut`
83
+
84
+ #### `sine`
85
+
86
+ Sinusoidal (cos/sin-based). Soft and natural.
87
+
88
+ **Variants:** `sineIn` · `sineOut` · `sineInOut`
89
+
90
+ #### `circ`
91
+
92
+ Circular arc. Sharp at one end, flat at the other.
93
+
94
+ **Variants:** `circIn` · `circOut` · `circInOut`
95
+
96
+ #### `expo`
97
+
98
+ Exponential (2^). Extreme — near-zero until the last moments, or vice versa.
99
+
100
+ **Variants:** `expoIn` · `expoOut` · `expoInOut`
101
+
102
+ #### `smooth`
103
+
104
+ Hermite smoothstep (3t² - 2t³). Zero velocity at both endpoints — smoother joins than power2.inOut for chained animations.
105
+
106
+ **Variants:** `smoothIn` · `smoothOut` · `smoothInOut`
107
+
108
+ ### Parametric
109
+
110
+ #### `back`
111
+
112
+ Overshoots the target then returns. Classic 'pull-back' motion.
113
+
114
+ **Variants:** `backIn` · `backOut` · `backInOut`
115
+
116
+ | Prop | Type | Default | Values |
117
+ |---|---|---|---|
118
+ | `overshoot` | number | `1.70158` | 0 – 5, step 0.01 |
119
+
120
+ #### `elastic`
121
+
122
+ Spring-like oscillation. Two knobs: amplitude (peak height) and period (frequency).
123
+
124
+ **Variants:** `elasticIn` · `elasticOut` · `elasticInOut`
125
+
126
+ | Prop | Type | Default | Values |
127
+ |---|---|---|---|
128
+ | `amplitude` | number | `1` | 0.1 – 5, step 0.01 |
129
+ | `period` | number | `0.3` | 0.05 – 1, step 0.01 |
130
+
131
+ #### `bounce`
132
+
133
+ Ball-drop pattern. Four decaying bounces.
134
+
135
+ **Variants:** `bounceIn` · `bounceOut` · `bounceInOut`
136
+
137
+ #### `steps`
138
+
139
+ Discrete staircase. CSS-compatible step positions.
140
+
141
+ **Export:** `steps`
142
+
143
+ | Prop | Type | Default | Values |
144
+ |---|---|---|---|
145
+ | `count` | number | `5` | 1 – 30, step 1 |
146
+ | `position` | enum | `end` | `end` · `start` · `none` |
147
+
148
+ ### Builder
149
+
150
+ #### `bezier`
151
+
152
+ CSS cubic-bezier. Paste a cubic-bezier() value from CSS or design tools.
153
+
154
+ **Export:** `bezier`
155
+
156
+ | Prop | Type | Default | Values |
157
+ |---|---|---|---|
158
+ | `p1x` | number | `0.42` | 0 – 1, step 0.01 |
159
+ | `p1y` | number | `0` | -2 – 2, step 0.01 |
160
+ | `p2x` | number | `0.58` | 0 – 1, step 0.01 |
161
+ | `p2y` | number | `1` | -2 – 2, step 0.01 |
162
+
163
+ #### `spring`
164
+
165
+ Physics-based spring. Stiffness × damping × mass = feel.
166
+
167
+ **Export:** `spring`
168
+
169
+ | Prop | Type | Default | Values |
170
+ |---|---|---|---|
171
+ | `stiffness` | number | `170` | 10 – 1000, step 5 |
172
+ | `damping` | number | `26` | 1 – 100, step 1 |
173
+ | `mass` | number | `1` | 0.1 – 10, step 0.1 |
174
+ | `velocity` | number | `0` | -20 – 20, step 0.5 |
175
+
176
+ #### `rough`
177
+
178
+ Jittery noise layered on a base curve. Great for gritty / handheld feel.
179
+
180
+ **Export:** `rough`
181
+
182
+ | Prop | Type | Default | Values |
183
+ |---|---|---|---|
184
+ | `strength` | number | `0.15` | 0 – 0.5, step 0.01 |
185
+ | `points` | number | `20` | 5 – 60, step 1 |
186
+ | `taper` | enum | `both` | `none` · `in` · `out` · `both` |
187
+ | `seed` | number | `42` | 1 – 999, step 1 |
188
+
189
+ #### `wiggle`
190
+
191
+ Oscillates between -1 and 1 across [0, 1]. For shake / vibration effects.
192
+
193
+ **Export:** `wiggle`
194
+
195
+ | Prop | Type | Default | Values |
196
+ |---|---|---|---|
197
+ | `wiggles` | number | `10` | 1 – 30, step 1 |
198
+ | `type` | enum | `easeOut` | `easeOut` · `easeInOut` · `anticipate` · `uniform` |
199
+
200
+ #### `slow`
201
+
202
+ Linear middle section flanked by power-eased edges. For slow-motion feel.
203
+
204
+ **Export:** `slow`
205
+
206
+ | Prop | Type | Default | Values |
207
+ |---|---|---|---|
208
+ | `linearRatio` | number | `0.7` | 0 – 1, step 0.01 |
209
+ | `power` | number | `0.7` | 0 – 5, step 0.1 |
210
+
211
+ #### `anticipate`
212
+
213
+ Character-animation wind-up: dips backward (in), overshoots past target (out), or both (inOut). Framer Motion style.
214
+
215
+ **Variants:** `anticipateIn` · `anticipateOut` · `anticipateInOut`
216
+
217
+ | Prop | Type | Default | Values |
218
+ |---|---|---|---|
219
+ | `overshoot` | number | `1.525` | 0 – 5, step 0.01 |
220
+
221
+ #### `expoScale`
222
+
223
+ Maps [0, 1] for scale animations crossing large ratios (e.g. 0.1→100) so motion feels even.
224
+
225
+ **Export:** `expoScale`
226
+
227
+ | Prop | Type | Default | Values |
228
+ |---|---|---|---|
229
+ | `startScale` | number | `1` | 0.01 – 100, step 0.1 |
230
+ | `endScale` | number | `100` | 0.01 – 1000, step 1 |
231
+
232
+ #### `gravity`
233
+
234
+ Continuously parameterised power-in. weight=0 floats (linear), weight=1 ≈ Earth fall (power2.in), higher = leaden. One knob instead of picking between named power curves.
235
+
236
+ **Export:** `gravity`
237
+
238
+ | Prop | Type | Default | Values |
239
+ |---|---|---|---|
240
+ | `weight` | number | `1` | 0 – 3, step 0.05 |
241
+
242
+ #### `breathe`
243
+
244
+ Continuous oscillation in [0, 1]. cycles=0.5 = single inhale (0 → 1). cycles=1 = inhale + exhale. For idle / ambient animations on opacity, scale, anything in [0, 1].
245
+
246
+ **Export:** `breathe`
247
+
248
+ | Prop | Type | Default | Values |
249
+ |---|---|---|---|
250
+ | `cycles` | number | `1` | 0.5 – 8, step 0.5 |
251
+
252
+ <!-- catalog:end -->
253
+
254
+ Spring presets shipped: `gentleSpring`, `wobblySpring`, `stiffSpring`, `slowSpring`, `molassesSpring` — all built on `spring.with(...)`. The power family also exposes GSAP-compatible aliases: `quadIn/Out/InOut`, `cubicIn/Out/InOut`, `quartIn/Out/InOut`, `quintIn/Out/InOut`.
255
+
256
+ ## Composition modifiers
257
+
258
+ ```ts
259
+ import {
260
+ reverse, mirror, yoyo, chain, blend, slice,
261
+ power2Out, sineInOut, bounceOut,
262
+ } from "@vysmo/easings";
263
+
264
+ reverse(power2Out); // play it backwards
265
+ mirror(power2Out); // half forward, half reversed
266
+ yoyo(sineInOut); // out then back — one full oscillation
267
+ blend(power2Out, sineInOut, 0.5); // 50/50 mix at every t
268
+ slice(power2Out, 0.2, 0.8); // use only the middle 60% of the curve
269
+
270
+ // chain takes an array of segments; each segment owns its own ease + duration.
271
+ chain([
272
+ { ease: power2Out, duration: 0.4 },
273
+ { ease: sineInOut, duration: 0.4 },
274
+ { ease: bounceOut, duration: 0.2 },
275
+ ]);
276
+ ```
277
+
278
+ All modifiers return a fresh `EasingFn` — composable, side-effect-free.
279
+
280
+ ## CSS export
281
+
282
+ ```ts
283
+ import { toCSSLinear, toCSSBezier, toCSSKeyframes, spring } from "@vysmo/easings";
284
+
285
+ // CSS `linear()` function — sample any EasingFn into a CSS-compatible curve.
286
+ // Second arg is the sample count (positional; default 40).
287
+ const css = toCSSLinear(spring.with({ stiffness: 100, damping: 10 }), 24);
288
+ // → "linear(0, 0.0123 4.17%, …)"
289
+
290
+ // Cubic-bezier control points → CSS cubic-bezier() exactly.
291
+ toCSSBezier(0.25, 0.1, 0.25, 1);
292
+ // → "cubic-bezier(0.25, 0.1, 0.25, 1)"
293
+
294
+ // Sample as @keyframes percentages for full-fidelity CSS animations.
295
+ // Signature: (name, property, valueForProgress, ease, samples?)
296
+ toCSSKeyframes(
297
+ "pop",
298
+ "transform",
299
+ (p) => `scale(${1 + p * 0.5})`,
300
+ spring.with({ stiffness: 200 }),
301
+ );
302
+ ```
303
+
304
+ ## Reduced-motion helpers
305
+
306
+ ```ts
307
+ import { prefersReducedMotion, respectReducedMotion, power2Out, linear } from "@vysmo/easings";
308
+
309
+ const ease = respectReducedMotion(power2Out, linear);
310
+ // → returns linear when prefers-reduced-motion is set, power2Out otherwise
311
+
312
+ if (prefersReducedMotion()) { /* skip the animation entirely */ }
313
+ ```
314
+
315
+ ## GSAP-style string parser
316
+
317
+ ```ts
318
+ import { parseEasing } from "@vysmo/easings/parse";
319
+
320
+ parseEasing("power2.out"); // → power2Out
321
+ parseEasing("back.out(2)"); // → backOut.with({ overshoot: 2 })
322
+ parseEasing("elastic.out(1.2, 0.4)"); // → elasticOut.with({ amplitude, period })
323
+ parseEasing("steps(5, start)"); // → steps(5, "start")
324
+ parseEasing("cubic-bezier(0.42, 0, 0.58, 1)"); // → bezier(0.42, 0, 0.58, 1)
325
+ ```
326
+
327
+ Useful when easings come from data (presets, JSON, AI agents, etc.) rather than source code.
328
+
329
+ ## Defining your own
330
+
331
+ ```ts
332
+ import { defineEasing, defineParametricEasing } from "@vysmo/easings";
333
+
334
+ // Simple curve
335
+ export const easeWithDefaults = defineEasing("my-ease", (t) => 1 - Math.pow(1 - t, 5));
336
+
337
+ // Parametric (callable with defaults; .with(...) returns a tuned variant)
338
+ export const customSpring = defineParametricEasing(
339
+ "my-spring",
340
+ { stiffness: 100 },
341
+ ({ stiffness }) => (t) => 1 - Math.pow(1 - t, stiffness / 50),
342
+ );
343
+ ```
344
+
345
+ Endpoints are clamped exact (t ≤ 0 → 0, t ≥ 1 → 1) by default. Disable for `steps("start")`-style curves with `{ exactEndpoints: false }`.
346
+
347
+ ## Subpath imports
348
+
349
+ Tree-shake what you ship by importing from subpaths:
350
+
351
+ ```ts
352
+ import { parseEasing } from "@vysmo/easings/parse";
353
+ import { toCSSLinear } from "@vysmo/easings/css";
354
+ import { prefersReducedMotion } from "@vysmo/easings/reduced-motion";
355
+ ```
356
+
357
+ `/parse` pulls in the registry; `/css` pulls in the CSS converters; `/reduced-motion` pulls in the media-query helper. The main entry tree-shakes cleanly when you only import a curve or two.
358
+
359
+ ## Characteristics
360
+
361
+ - **Pure math.** No DOM, no rAF, no global state. Runs in Node, browser, web workers, deno, bun.
362
+ - **Zero runtime dependencies.**
363
+ - **Tree-shakable.** Importing one curve ships ~0.2 KB gzipped.
364
+ - **Endpoint-correct.** All catalog curves clear `f(0) === 0` and `f(1) === 1`. Property-tested across the catalog.
365
+
366
+ ## License
367
+
368
+ MIT.
@@ -0,0 +1,20 @@
1
+ export type AnticipateParams = {
2
+ /** Depth of the backward dip before the forward motion. Default 1.525 (Framer Motion default). */
3
+ overshoot: number;
4
+ };
5
+ /**
6
+ * Character-animation-style anticipation: wind-up before the forward motion.
7
+ *
8
+ * - `anticipateIn` (formerly just `anticipate`): dip at start, smooth arrival.
9
+ * - `anticipateOut`: smooth departure, overshoot dip near the end.
10
+ * - `anticipateInOut`: dip at start AND overshoot near the end (wind-up + follow-through).
11
+ *
12
+ * The second half of `anticipateIn` uses a power-n ease where n matches the
13
+ * first-half slope at t=0.5, giving C¹ continuity regardless of overshoot.
14
+ */
15
+ export declare const anticipateIn: import("../types.js").ParametricEasing<AnticipateParams>;
16
+ export declare const anticipateOut: import("../types.js").ParametricEasing<AnticipateParams>;
17
+ export declare const anticipateInOut: import("../types.js").ParametricEasing<AnticipateParams>;
18
+ /** Alias for `anticipateIn` (Framer Motion's default shape). */
19
+ export declare const anticipate: import("../types.js").ParametricEasing<AnticipateParams>;
20
+ //# sourceMappingURL=anticipate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anticipate.d.ts","sourceRoot":"","sources":["../../src/builders/anticipate.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kGAAkG;IAClG,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAyCF;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,0DAAuE,CAAC;AACjG,eAAO,MAAM,aAAa,0DAAyE,CAAC;AACpG,eAAO,MAAM,eAAe,0DAI3B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,UAAU,0DAAe,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { defineParametricEasing } from "../define.js";
2
+ const DEFAULTS = { overshoot: 1.525 };
3
+ function anticipateInBuild({ overshoot: s }) {
4
+ const n = Math.max(1, s + 3);
5
+ return (t) => {
6
+ if (t < 0.5) {
7
+ const p = t * 2;
8
+ return 0.5 * (p * p * ((s + 1) * p - s));
9
+ }
10
+ const p = t * 2 - 1;
11
+ return 0.5 + 0.5 * (1 - (1 - p) ** n);
12
+ };
13
+ }
14
+ function anticipateOutBuild({ overshoot: s }) {
15
+ const n = Math.max(1, s + 3);
16
+ return (t) => {
17
+ if (t < 0.5) {
18
+ const p = t * 2;
19
+ return 0.5 * (p ** n);
20
+ }
21
+ const u = 1 - t;
22
+ const p = u * 2;
23
+ return 1 - 0.5 * (p * p * ((s + 1) * p - s));
24
+ };
25
+ }
26
+ function anticipateInOutBuild({ overshoot: s }) {
27
+ return (t) => {
28
+ if (t < 0.5) {
29
+ const p = t * 2;
30
+ return 0.5 * (p * p * ((s + 1) * p - s));
31
+ }
32
+ const u = 1 - t;
33
+ const p = u * 2;
34
+ return 1 - 0.5 * (p * p * ((s + 1) * p - s));
35
+ };
36
+ }
37
+ /**
38
+ * Character-animation-style anticipation: wind-up before the forward motion.
39
+ *
40
+ * - `anticipateIn` (formerly just `anticipate`): dip at start, smooth arrival.
41
+ * - `anticipateOut`: smooth departure, overshoot dip near the end.
42
+ * - `anticipateInOut`: dip at start AND overshoot near the end (wind-up + follow-through).
43
+ *
44
+ * The second half of `anticipateIn` uses a power-n ease where n matches the
45
+ * first-half slope at t=0.5, giving C¹ continuity regardless of overshoot.
46
+ */
47
+ export const anticipateIn = defineParametricEasing("anticipate.in", DEFAULTS, anticipateInBuild);
48
+ export const anticipateOut = defineParametricEasing("anticipate.out", DEFAULTS, anticipateOutBuild);
49
+ export const anticipateInOut = defineParametricEasing("anticipate.inOut", DEFAULTS, anticipateInOutBuild);
50
+ /** Alias for `anticipateIn` (Framer Motion's default shape). */
51
+ export const anticipate = anticipateIn;
52
+ //# sourceMappingURL=anticipate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anticipate.js","sourceRoot":"","sources":["../../src/builders/anticipate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAOtD,MAAM,QAAQ,GAAqB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAExD,SAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,CAAC,EAAoB;IAC3D,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,CAAS,EAAE,EAAE;QACnB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,CAAC,EAAoB;IAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,CAAS,EAAE,EAAE;QACnB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACxB,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAE,SAAS,EAAE,CAAC,EAAoB;IAC9D,OAAO,CAAC,CAAS,EAAE,EAAE;QACnB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,sBAAsB,CAAC,eAAe,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AACjG,MAAM,CAAC,MAAM,aAAa,GAAG,sBAAsB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AACpG,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CACnD,kBAAkB,EAClB,QAAQ,EACR,oBAAoB,CACrB,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EasingFn } from "../types.js";
2
+ export declare function bezier(p1x: number, p1y: number, p2x: number, p2y: number): EasingFn;
3
+ export declare const bezierEase: EasingFn;
4
+ export declare const bezierEaseIn: EasingFn;
5
+ export declare const bezierEaseOut: EasingFn;
6
+ export declare const bezierEaseInOut: EasingFn;
7
+ //# sourceMappingURL=bezier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bezier.d.ts","sourceRoot":"","sources":["../../src/builders/bezier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgD5C,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAgBnF;AAED,eAAO,MAAM,UAAU,UAA6B,CAAC;AACrD,eAAO,MAAM,YAAY,UAAwB,CAAC;AAClD,eAAO,MAAM,aAAa,UAAwB,CAAC;AACnD,eAAO,MAAM,eAAe,UAA2B,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { defineEasing } from "../define.js";
2
+ const NEWTON_ITERATIONS = 8;
3
+ const NEWTON_MIN_SLOPE = 1e-6;
4
+ const SUBDIVISION_PRECISION = 1e-7;
5
+ const SUBDIVISION_MAX_ITERATIONS = 32;
6
+ function a(c1, c2) {
7
+ return 1 - 3 * c2 + 3 * c1;
8
+ }
9
+ function b(c1, c2) {
10
+ return 3 * c2 - 6 * c1;
11
+ }
12
+ function c(c1) {
13
+ return 3 * c1;
14
+ }
15
+ function sampleCurve(t, A, B, C) {
16
+ return ((A * t + B) * t + C) * t;
17
+ }
18
+ function sampleDerivative(t, A, B, C) {
19
+ return (3 * A * t + 2 * B) * t + C;
20
+ }
21
+ function solveCurveX(x, ax, bx, cx) {
22
+ let t = x;
23
+ for (let i = 0; i < NEWTON_ITERATIONS; i++) {
24
+ const slope = sampleDerivative(t, ax, bx, cx);
25
+ if (Math.abs(slope) < NEWTON_MIN_SLOPE)
26
+ break;
27
+ const currentX = sampleCurve(t, ax, bx, cx) - x;
28
+ t -= currentX / slope;
29
+ }
30
+ let lo = 0;
31
+ let hi = 1;
32
+ t = x;
33
+ if (t < lo)
34
+ return lo;
35
+ if (t > hi)
36
+ return hi;
37
+ for (let i = 0; i < SUBDIVISION_MAX_ITERATIONS; i++) {
38
+ const currentX = sampleCurve(t, ax, bx, cx);
39
+ if (Math.abs(currentX - x) < SUBDIVISION_PRECISION)
40
+ return t;
41
+ if (currentX < x)
42
+ lo = t;
43
+ else
44
+ hi = t;
45
+ t = (lo + hi) / 2;
46
+ }
47
+ return t;
48
+ }
49
+ export function bezier(p1x, p1y, p2x, p2y) {
50
+ if (p1x < 0 || p1x > 1 || p2x < 0 || p2x > 1) {
51
+ throw new RangeError(`bezier: control point x coordinates must be in [0, 1]; got p1x=${p1x}, p2x=${p2x}`);
52
+ }
53
+ const ax = a(p1x, p2x);
54
+ const bx = b(p1x, p2x);
55
+ const cx = c(p1x);
56
+ const ay = a(p1y, p2y);
57
+ const by = b(p1y, p2y);
58
+ const cy = c(p1y);
59
+ const linear = p1x === p1y && p2x === p2y;
60
+ const name = `bezier(${p1x}, ${p1y}, ${p2x}, ${p2y})`;
61
+ if (linear)
62
+ return defineEasing(name, (t) => t);
63
+ return defineEasing(name, (t) => sampleCurve(solveCurveX(t, ax, bx, cx), ay, by, cy));
64
+ }
65
+ export const bezierEase = bezier(0.25, 0.1, 0.25, 1);
66
+ export const bezierEaseIn = bezier(0.42, 0, 1, 1);
67
+ export const bezierEaseOut = bezier(0, 0, 0.58, 1);
68
+ export const bezierEaseInOut = bezier(0.42, 0, 0.58, 1);
69
+ //# sourceMappingURL=bezier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bezier.js","sourceRoot":"","sources":["../../src/builders/bezier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type BreatheParams = {
2
+ /**
3
+ * Number of in-out breath cycles across [0, 1]. 0.5 = single inhale
4
+ * (0 → 1). 1 = inhale + exhale (0 → 1 → 0). 2 = two full cycles. The
5
+ * curve oscillates in [0, 1] so it maps cleanly to opacity / scale /
6
+ * any normalised animatable.
7
+ */
8
+ cycles: number;
9
+ };
10
+ export declare const breathe: import("../types.js").ParametricEasing<BreatheParams>;
11
+ //# sourceMappingURL=breathe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breathe.d.ts","sourceRoot":"","sources":["../../src/builders/breathe.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAYF,eAAO,MAAM,OAAO,uDAQnB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { defineParametricEasing } from "../define.js";
2
+ const DEFAULTS = { cycles: 1 };
3
+ const TAU = Math.PI * 2;
4
+ // (1 - cos(τ·c·t)) / 2 — cosine wave shifted into [0, 1]. Distinct from
5
+ // `wiggle` (which oscillates [-1, 1] for shake/vibration); breathe
6
+ // stays positive and is intended for idle/ambient animations.
7
+ //
8
+ // exactEndpoints: false — for cycles ≠ 0.5n, the natural curve doesn't
9
+ // land at 1 at t=1, and clamping defeats the rhythmic intent.
10
+ export const breathe = defineParametricEasing("breathe", DEFAULTS, ({ cycles }) => {
11
+ const c = Math.max(0, cycles);
12
+ return (t) => (1 - Math.cos(TAU * c * t)) / 2;
13
+ }, { exactEndpoints: false });
14
+ //# sourceMappingURL=breathe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breathe.js","sourceRoot":"","sources":["../../src/builders/breathe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAYtD,MAAM,QAAQ,GAAkB,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAE9C,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAExB,wEAAwE;AACxE,mEAAmE;AACnE,8DAA8D;AAC9D,EAAE;AACF,uEAAuE;AACvE,8DAA8D;AAC9D,MAAM,CAAC,MAAM,OAAO,GAAG,sBAAsB,CAC3C,SAAS,EACT,QAAQ,EACR,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACb,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC,EACD,EAAE,cAAc,EAAE,KAAK,EAAE,CAC1B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { EasingFn } from "../types.js";
2
+ export type CustomPoint = readonly [x: number, y: number];
3
+ /**
4
+ * Build an easing from a sequence of (x, y) control points, interpolated
5
+ * linearly between them. Use for hand-drawn curves, exported visualiser
6
+ * data, or any non-analytic easing shape.
7
+ *
8
+ * Points must be in ascending x order with x in [0, 1]. Endpoints are
9
+ * clamped to (0, 0) and (1, 1) by the framework — provide those points
10
+ * explicitly if you want to see the un-clamped curve.
11
+ */
12
+ export declare function custom(points: ReadonlyArray<CustomPoint>): EasingFn;
13
+ //# sourceMappingURL=custom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/builders/custom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,QAAQ,CA4BnE"}
@@ -0,0 +1,40 @@
1
+ import { defineEasing } from "../define.js";
2
+ /**
3
+ * Build an easing from a sequence of (x, y) control points, interpolated
4
+ * linearly between them. Use for hand-drawn curves, exported visualiser
5
+ * data, or any non-analytic easing shape.
6
+ *
7
+ * Points must be in ascending x order with x in [0, 1]. Endpoints are
8
+ * clamped to (0, 0) and (1, 1) by the framework — provide those points
9
+ * explicitly if you want to see the un-clamped curve.
10
+ */
11
+ export function custom(points) {
12
+ if (points.length < 2) {
13
+ throw new RangeError(`custom: at least 2 points required; got ${points.length}`);
14
+ }
15
+ for (let i = 1; i < points.length; i++) {
16
+ const prev = points[i - 1];
17
+ const curr = points[i];
18
+ if (curr[0] < prev[0]) {
19
+ throw new RangeError(`custom: points must be sorted by ascending x; got ${prev[0]} then ${curr[0]} at index ${i}`);
20
+ }
21
+ }
22
+ const name = `custom(${points.length} points)`;
23
+ return defineEasing(name, (t) => {
24
+ if (t <= points[0][0])
25
+ return points[0][1];
26
+ for (let i = 1; i < points.length; i++) {
27
+ const [x1, y1] = points[i];
28
+ if (t <= x1) {
29
+ const [x0, y0] = points[i - 1];
30
+ const span = x1 - x0;
31
+ if (span === 0)
32
+ return y1;
33
+ const u = (t - x0) / span;
34
+ return y0 + (y1 - y0) * u;
35
+ }
36
+ }
37
+ return points[points.length - 1][1];
38
+ });
39
+ }
40
+ //# sourceMappingURL=custom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/builders/custom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAK5C;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAC,MAAkC;IACvD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,2CAA2C,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACxB,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,UAAU,CAClB,qDAAqD,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,MAAM,CAAC,MAAM,UAAU,CAAC;IAC/C,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QAC9B,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACZ,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;gBACrB,IAAI,IAAI,KAAK,CAAC;oBAAE,OAAO,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;gBAC1B,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC"}