@penner/responsive-easing 0.0.3 → 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.
@@ -0,0 +1,1721 @@
1
+ import { clampNormalized as C } from "@penner/smart-primitive";
2
+ import { amplitudeRatio as xt, dampingRate as Et, makeExpoEaseOut as mt, createVelocityFn as j, solveBackStrength as it, swim as kt, reverseEasingFn as Y, easingKit as D, backEaseIn as vt, backEaseInVelocity as lt } from "@penner/easing";
3
+ const ct = 1.70158, Mt = ct + 1, at = (e) => Mt * e * e * e - ct * e * e, rt = (e) => 3 * Mt * e * e - 2 * ct * e, tt = {
4
+ // Public id uses the new 'bounce' name
5
+ id: "bounce",
6
+ label: "Bounce (hard-surface)",
7
+ build({
8
+ joinTime: e,
9
+ bounces: t,
10
+ decayPct: a,
11
+ L: n = at,
12
+ Ld: o = rt
13
+ }) {
14
+ if (e < ut)
15
+ return {
16
+ p: (x) => C(x),
17
+ v: (x) => 1,
18
+ meta: { r: 0, finalPct: 0 }
19
+ };
20
+ if (e > Pt)
21
+ return {
22
+ p: (x) => x >= 1 ? 1 : n(x),
23
+ v: (x) => x >= 1 ? 0 : o(x),
24
+ meta: { r: 0, finalPct: 0 }
25
+ };
26
+ const r = Math.ceil(t), s = t - Math.floor(t);
27
+ let i;
28
+ if (t <= 1)
29
+ i = C(1 - a / 100);
30
+ else {
31
+ const h = C(
32
+ 1 - a / 100
33
+ );
34
+ h === 0 ? i = 0 : i = Math.pow(h, 1 / (2 * (t - 1)));
35
+ }
36
+ const l = (h) => n(h / e), d = (h) => o(h / e) / e, u = d(e), c = Math.abs(-i * u);
37
+ if (i === 0 || c === 0)
38
+ return {
39
+ p: (x) => x <= e ? l(x) : 1,
40
+ v: (x) => x <= e ? d(x) : 0,
41
+ meta: {
42
+ r: 0,
43
+ finalPct: 0,
44
+ g: 0,
45
+ edges: [e, 1]
46
+ }
47
+ };
48
+ const M = 1 - e, b = Math.floor(t), I = Math.abs(1 - i) < 1e-6 ? t : (1 - Math.pow(i, b)) / (1 - i) + s * Math.pow(i, b);
49
+ let g = 2 * c / M * I, p = 0;
50
+ const P = 50;
51
+ for (let h = 0; h <= P; h++) {
52
+ const w = h / P * e, x = l(w);
53
+ x < p && (p = x);
54
+ }
55
+ const O = 1 - p, f = c * c / (2 * g);
56
+ let E = c, V = !1, _ = 1;
57
+ if (f > O) {
58
+ E = Math.sqrt(2 * g * O), V = !0;
59
+ const h = Math.abs(1 - i) < 1e-6 ? t : (1 - Math.pow(i, b)) / (1 - i) + s * Math.pow(i, b), w = 2 * E * h / g;
60
+ _ = e + w, _ > 1 && (_ = 1);
61
+ }
62
+ const v = E, F = Array.from(
63
+ { length: r },
64
+ (h, w) => 2 * v * Math.pow(i, w) / g
65
+ ), k = [e];
66
+ F.forEach((h) => k.push(k[k.length - 1] + h)), V ? k[k.length - 1] = _ : k[k.length - 1] = 1;
67
+ const B = (h) => -v * Math.pow(i, h), N = (h) => {
68
+ if (h >= _)
69
+ return 1;
70
+ let w = k.findIndex(
71
+ (S, K) => K < k.length - 1 && h <= k[K + 1]
72
+ );
73
+ w < 0 && (w = r - 1);
74
+ const x = k[w], $ = h - x;
75
+ return 1 + (B(w) * $ + 0.5 * g * $ * $);
76
+ }, T = (h) => {
77
+ if (h >= _)
78
+ return 0;
79
+ let w = k.findIndex(
80
+ (A, S) => S < k.length - 1 && h <= k[S + 1]
81
+ );
82
+ w < 0 && (w = r - 1);
83
+ const x = k[w], $ = h - x;
84
+ return B(w) + g * $;
85
+ }, H = (h) => h <= e ? l(h) : N(h), m = (h) => h <= e ? d(h) : T(h), y = r <= 1 ? 100 : 100 * (1 - a / 100);
86
+ return {
87
+ p: H,
88
+ v: m,
89
+ meta: {
90
+ r: i,
91
+ finalPct: y,
92
+ g,
93
+ edges: k,
94
+ clamped: V,
95
+ settleTime: _
96
+ }
97
+ };
98
+ }
99
+ }, St = 12;
100
+ function Vt({
101
+ joinTime: e,
102
+ L: t = at,
103
+ Ld: a = rt,
104
+ bridge: n
105
+ }) {
106
+ const o = St;
107
+ n && n.joinHeight;
108
+ const r = n ? e + n.duration : e, s = 1 - r;
109
+ let i;
110
+ if (n)
111
+ i = n.joinHeight;
112
+ else {
113
+ const E = a(1) * (1 - e) + o * e;
114
+ Math.abs(E) < 1e-9 ? i = 0.5 : i = o * e / E, i = Math.max(0.01, Math.min(0.999, i));
115
+ }
116
+ const l = n ? 1 : i, d = l - 1, u = n ? n.velocity * s : i * a(1) * (1 - e) / e, c = u + o * d, M = (f) => {
117
+ if (f <= 0) return l;
118
+ if (f >= 1) return 1;
119
+ const E = Math.exp(-o * f);
120
+ return 1 + (d + c * f) * E;
121
+ }, b = (f) => {
122
+ if (f <= 0) return u;
123
+ if (f >= 1) return 0;
124
+ const E = Math.exp(-o * f);
125
+ return (c - o * (d + c * f)) * E;
126
+ }, I = n ? n.joinHeight : i, g = (f) => I * t(f / e), p = (f) => I / e * a(f / e);
127
+ return {
128
+ p: (f) => {
129
+ if (f <= 0) return 0;
130
+ if (f >= 1) return 1;
131
+ if (f <= e) return g(f);
132
+ if (n && f <= r)
133
+ return n.joinHeight + n.velocity * (f - e);
134
+ const E = (f - r) / s;
135
+ return M(E);
136
+ },
137
+ v: (f) => {
138
+ if (f <= 0 || f >= 1) return 0;
139
+ if (f <= e) return p(f);
140
+ if (n && f <= r)
141
+ return n.velocity;
142
+ const E = (f - r) / s;
143
+ return b(E) / s;
144
+ },
145
+ meta: {
146
+ r: 0,
147
+ finalPct: 0,
148
+ k: o,
149
+ B: 0,
150
+ P: i,
151
+ guard: "critically-damped",
152
+ useBridge: !!n
153
+ }
154
+ };
155
+ }
156
+ function wt(e, t, a, n) {
157
+ const o = C(a / 100), r = t + 0.5, s = xt(o, r), i = r, l = Math.PI * i, d = Et(i, s), u = 1 - e, c = e <= ut * 10, M = u > 0 ? l / u : l, b = u > 0 ? d / u : d, I = n(1);
158
+ let g;
159
+ if (c)
160
+ g = 0;
161
+ else {
162
+ const O = I / e, f = l, E = O * (1 - e) + f * e;
163
+ g = Math.abs(E) < 1e-9 ? 0.5 : f * e / E, g = Math.max(0.01, Math.min(0.999, g));
164
+ }
165
+ const p = c ? 0 : g * I / e, P = t <= 1 ? 100 : 100 * (1 - a / 100);
166
+ return { P: g, v0: p, r: s, N: i, w: M, g: b, alpha: u, finalPct: P };
167
+ }
168
+ function Bt({
169
+ joinTime: e,
170
+ bounces: t,
171
+ decayPct: a,
172
+ L: n = at,
173
+ Ld: o = rt
174
+ }) {
175
+ const r = wt(e, t, a, o), { r: s, g: i, alpha: l, finalPct: d } = r, u = o(1);
176
+ let c;
177
+ if (u > 1e-6) {
178
+ const y = Math.min(
179
+ l / (8 * Math.max(t, 1)),
180
+ l * 0.1
181
+ ), h = e / (e + u * y), x = t > 0 ? 0.5 * e * t * Math.PI / (u * l) : 0.5;
182
+ c = Math.min(h, x), c = Math.max(0.01, Math.min(0.999, c));
183
+ } else
184
+ c = r.P;
185
+ const M = c * u / e, b = t > 0 ? l / (2 * t + 1) : l, I = t > 0 ? l * 0.5 : l, g = 1e-6;
186
+ let p;
187
+ if (M > 1e-6) {
188
+ const y = (1 - c) / M;
189
+ p = Math.max(g, Math.min(I, y));
190
+ } else
191
+ p = Math.max(g, Math.min(I, b));
192
+ const P = p > 0 ? 2 * (1 - c - M * p) / (p * p) : 0, O = (y) => 0.5 * P * y * y + M * y + c, f = (y) => P * y + M, E = P * p + M, V = l - p, _ = V > 0 ? t * Math.PI / V : 0, v = _ > 0 ? E / _ : 0, F = (y) => 1 + v * Math.exp(-i * y) * Math.sin(_ * y), k = (y) => v * Math.exp(-i * y) * (_ * Math.cos(_ * y) - i * Math.sin(_ * y)), B = (y) => c * n(y / e), N = (y) => c / e * o(y / e), T = e + p;
193
+ return {
194
+ p: (y) => {
195
+ if (y <= 0) return 0;
196
+ if (y >= 1) return 1;
197
+ if (y <= e) return B(y);
198
+ if (y <= T) {
199
+ const w = y - e;
200
+ return O(w);
201
+ }
202
+ const h = y - T;
203
+ return F(h);
204
+ },
205
+ v: (y) => {
206
+ if (y <= 0 || y >= 1) return 0;
207
+ if (y <= e) return N(y);
208
+ if (y <= T) {
209
+ const w = y - e;
210
+ return f(w);
211
+ }
212
+ const h = y - T;
213
+ return k(h);
214
+ },
215
+ meta: { r: s, finalPct: d, k: i, B: _, P: c, guard: "quadratic-sine" }
216
+ };
217
+ }
218
+ const Nt = Bt, R = {
219
+ // Public id uses the new 'spring' name
220
+ id: "spring",
221
+ label: "Spring (phase-locked; bounce = half-cycle)",
222
+ /**
223
+ * Calculate the natural starting velocity for spring oscillations
224
+ *
225
+ * This is adaptive, blending the head's ending velocity with spring frequency
226
+ * to produce visually balanced bridges that respond to both the head's characteristics
227
+ * and the spring's oscillation rate.
228
+ *
229
+ * Strategy: Equal weight to head velocity and frequency (both at 1.0 by default)
230
+ * Formula: headVelocity * 1.0 + 1.0 * N^1.0 * 1.0 = headVelocity + N
231
+ */
232
+ getNaturalStartVelocity({ bounces: e, decayPct: t }, a, n) {
233
+ const o = e;
234
+ if (o <= 0)
235
+ return a(1);
236
+ let r;
237
+ if (o <= 1)
238
+ r = C(1 - t / 100);
239
+ else {
240
+ const M = C(
241
+ 1 - t / 100
242
+ );
243
+ M === 0 ? r = 0 : r = Math.pow(M, 1 / (o - 1));
244
+ }
245
+ if (r === 0) return 0;
246
+ const s = a(1), i = n?.headWeight ?? 1, l = n?.freqWeight ?? 1, d = n?.freqExponent ?? 1, u = n?.baseMultiplier ?? 1, c = Math.pow(o, d);
247
+ return s * i + u * c * l;
248
+ },
249
+ build({
250
+ joinTime: e,
251
+ bounces: t,
252
+ decayPct: a,
253
+ L: n = at,
254
+ Ld: o = rt,
255
+ bridge: r
256
+ }) {
257
+ if (e < ut)
258
+ return {
259
+ p: (h) => C(h),
260
+ v: (h) => 1,
261
+ meta: {
262
+ r: 0,
263
+ finalPct: 0,
264
+ k: 0,
265
+ B: 0,
266
+ P: 0
267
+ }
268
+ };
269
+ if (e > Pt)
270
+ return {
271
+ p: (h) => h >= 1 ? 1 : n(h),
272
+ v: (h) => h >= 1 ? 0 : o(h),
273
+ meta: {
274
+ r: 0,
275
+ finalPct: 0,
276
+ k: 0,
277
+ B: 0,
278
+ P: 1
279
+ }
280
+ };
281
+ if (t <= 0)
282
+ return Vt({ joinTime: e, L: n, Ld: o, bridge: r });
283
+ if (!r)
284
+ return Nt({ joinTime: e, bounces: t, decayPct: a, L: n, Ld: o });
285
+ let s;
286
+ if (t <= 1)
287
+ s = C(1 - a / 100);
288
+ else {
289
+ const m = C(
290
+ 1 - a / 100
291
+ );
292
+ m === 0 ? s = 0 : s = Math.pow(m, 1 / (t - 1));
293
+ }
294
+ const i = r ? r.joinHeight : 1, l = r ? e + r.duration : e;
295
+ if (s === 0) {
296
+ const m = (x) => i * n(x / e), y = (x) => i / e * o(x / e);
297
+ return {
298
+ p: (x) => x <= e ? m(x) : r && x <= l ? r.joinHeight + r.velocity * (x - e) : 1,
299
+ v: (x) => x <= e ? y(x) : r && x <= l ? r.velocity : 0,
300
+ meta: {
301
+ r: 0,
302
+ finalPct: 0,
303
+ k: 1 / 0,
304
+ B: 0,
305
+ P: i,
306
+ guard: "no-oscillation",
307
+ useBridge: !!r
308
+ }
309
+ };
310
+ }
311
+ const d = 1 - l, u = t <= 0 || d <= 0 ? 0 : t * Math.PI / d, c = s <= 0 ? 50 : u / Math.PI * -Math.log(s), M = (m) => Math.exp(-c * m) * Math.sin(u * m), b = (m) => Math.exp(-c * m) * (u * Math.cos(u * m) - c * Math.sin(u * m));
312
+ let I = "";
313
+ const g = Math.PI / (2 * u), p = Math.exp(-c * g), P = p > 1e-9 ? p : 1;
314
+ p <= 1e-9 && (I = "high-decay-fallback");
315
+ const O = (m) => M(d * m) / P, f = (m) => d * b(d * m) / P, E = () => !r || u === 0 ? 0 : r.joinHeight / e * o(1) * P / u, V = (m) => k + (1 - k) * m, _ = (m) => r ? 1 + E() * O(m) : V(m) + (1 - k) * O(m), v = (m) => r ? E() / (1 - l) * f(m) : (1 - k) * (1 + f(m)) / (1 - l), F = () => {
316
+ if (r) {
317
+ const m = f(0), y = 1 - l;
318
+ return Math.abs(m) < 1e-9 ? i : 1 - r.velocity * y / m;
319
+ } else {
320
+ const m = o(1), h = 1 + f(0);
321
+ return Math.abs(m * (1 - e) + h * e) < 1e-9 ? 0.5 : h * e / (m * (1 - e) + h * e);
322
+ }
323
+ }, k = F(), B = globalThis;
324
+ typeof B.__SPRING_TEST_HELPERS__ == "object" && (B.__SPRING_TEST_HELPERS__.calculateBridgeAmplitude = E, B.__SPRING_TEST_HELPERS__.calculateNonBridgeBaseline = V, B.__SPRING_TEST_HELPERS__.calculatePulsePosition = _, B.__SPRING_TEST_HELPERS__.calculatePulseVelocity = v, B.__SPRING_TEST_HELPERS__.calculateScalingFactor = F);
325
+ const N = (m) => {
326
+ if (m <= e)
327
+ return (r ? r.joinHeight : k) * n(m / e);
328
+ if (r && m <= l)
329
+ return r.joinHeight + r.velocity * (m - e);
330
+ const y = (m - l) / (1 - l);
331
+ return _(y);
332
+ }, T = (m) => {
333
+ if (m <= e)
334
+ return (r ? r.joinHeight : k) / e * o(m / e);
335
+ if (r && m <= l)
336
+ return r.velocity;
337
+ const y = (m - l) / (1 - l);
338
+ return v(y);
339
+ }, H = t <= 1 ? 100 : 100 * (1 - a / 100);
340
+ return {
341
+ p: N,
342
+ v: T,
343
+ meta: {
344
+ r: s,
345
+ finalPct: H,
346
+ k: c,
347
+ B: u,
348
+ P: k,
349
+ guard: I || "ok",
350
+ useBridge: !!r
351
+ }
352
+ };
353
+ }
354
+ }, dt = R;
355
+ function Ft(e, t, a, n) {
356
+ const o = Math.PI / 2, r = (A) => Math.abs(A) < 222e-17, s = (A) => {
357
+ const S = Math.sign(A), K = A * S;
358
+ return ((((-0.021641405 * K + 0.077981383) * K + -0.213301322) * K + o) * Math.sqrt(1 - K) - o) * S + o;
359
+ }, i = (A) => {
360
+ if (Math.abs(A) < 1) {
361
+ const S = A * A, K = S * A, Ot = K * S;
362
+ return A + K / 6 + Ot / 120;
363
+ }
364
+ return Math.sinh(A);
365
+ }, l = e - a, d = t - n, u = 3 * e, c = 3 * t, M = 3 * l + 1, b = -u - 3 * l, I = u, g = 3 * d + 1, p = -c - 3 * d, P = c, O = 1 / M, f = b * O, E = I * O, V = f / -3 * f + E, _ = f / 3, v = (2 * _ * _ - E) * _, F = Math.sign(V), k = Math.sign(b);
366
+ let B = 1, N = 1, T = 1, H, m, y;
367
+ if (r(M) && r(b))
368
+ H = 1, B = 1 / I, N = 0, m = 1, y = 0;
369
+ else if (r(M))
370
+ H = 2, B = k, N = -(I / (2 * b)), m = 1 / b, y = N * N;
371
+ else if (r(V))
372
+ H = 3, N = -_, m = O, y = -v;
373
+ else {
374
+ if (M < 0)
375
+ H = 4;
376
+ else if (V > 0)
377
+ H = 5;
378
+ else if (V < 0)
379
+ H = 6, T = k;
380
+ else
381
+ throw new Error("Invalid curve type");
382
+ B = -2 * F * T * Math.sqrt(Math.abs(V) / 3), N = -_, m = 3 * F * O / (V * B), y = 3 * F * (-v / V / B);
383
+ }
384
+ const h = g * B * B * B, w = (3 * g * N + p) * B * B, x = ((3 * g * N + 2 * p) * N + P) * B, $ = ((g * N + p) * N + P) * N;
385
+ return (A) => {
386
+ if (A <= 0) return 0;
387
+ if (A >= 1) return 1;
388
+ let S = m * A + y;
389
+ switch (H) {
390
+ case 1:
391
+ break;
392
+ case 2:
393
+ S = Math.sqrt(Math.max(0, S));
394
+ break;
395
+ case 3:
396
+ S = Math.cbrt(S);
397
+ break;
398
+ case 4:
399
+ S = Math.cos(
400
+ s(Math.max(-1, Math.min(1, S))) / 3 - 2.094395102393195
401
+ );
402
+ break;
403
+ case 5:
404
+ S = i(Math.log(S + Math.sqrt(S * S + 1)) / 3);
405
+ break;
406
+ case 6:
407
+ S = S >= 1 ? (
408
+ // Inlined fastAcosh: Math.acosh(phi) would be Math.log(phi + Math.sqrt(phi * phi - 1))
409
+ Math.cosh(Math.log(S + Math.sqrt(S * S - 1)) / 3)
410
+ ) : Math.cos(s(Math.max(-1, S)) / 3);
411
+ break;
412
+ default:
413
+ throw new Error("Invalid curve type");
414
+ }
415
+ return ((h * S + w) * S + x) * S + $;
416
+ };
417
+ }
418
+ function et(e, t, a, n) {
419
+ if (e < 0 || e > 1 || a < 0 || a > 1)
420
+ throw new Error("x1 & x2 must be in [0, 1]");
421
+ return e === t && a === n ? (o) => o : Ft(e, t, a, n);
422
+ }
423
+ function Ht(e, t) {
424
+ if (e <= 0) return 0;
425
+ if (e >= 1) return Number.POSITIVE_INFINITY;
426
+ if (t <= 1) return 0;
427
+ if (t - 1 < 1e-10) {
428
+ const n = e / (1 - e);
429
+ return Math.max(0, n * Math.pow(t - 1, 2));
430
+ }
431
+ const a = Math.pow((t - 1) / t, t - 1) / t;
432
+ return Math.pow(e, t) / (1 - e) * a;
433
+ }
434
+ function st(e, t) {
435
+ if (e <= 0 || t <= 1) return 0;
436
+ const a = e;
437
+ let n = 0, o = 1 - 1e-9;
438
+ for (let s = 0; s < 60; s++) {
439
+ const i = 0.5 * (n + o);
440
+ Ht(i, t) < a ? n = i : o = i;
441
+ }
442
+ const r = 0.5 * (n + o);
443
+ return r / (1 - r);
444
+ }
445
+ function At(e, t, a) {
446
+ const n = t;
447
+ if (a === 0 || n <= 1)
448
+ return Math.pow(e, Math.max(n, 0));
449
+ if (n - 1 < 1e-10)
450
+ return (a + 1) * e - a;
451
+ const r = Math.pow(e, n - 1) * ((a + 1) * e - a);
452
+ return r === 0 ? 0 : r;
453
+ }
454
+ function bt(e, t, a) {
455
+ const n = t;
456
+ return a === 0 || n <= 1 ? n * Math.pow(e, n - 1) : n - 1 < 1e-10 ? a + 1 : Math.abs(n - 2) < 1e-10 ? 2 * (a + 1) * e - a : e === 0 && n > 2 ? 0 : e === 0 && n <= 2 ? n * (a + 1) * Math.pow(1e-10, n - 1) : n * (a + 1) * Math.pow(e, n - 1) - a * (n - 1) * Math.pow(e, n - 2);
457
+ }
458
+ function Pe(e, t) {
459
+ if (t <= 0 || e <= 1) return 0;
460
+ const a = e, n = st(t, a);
461
+ return n <= 0 ? 0 : (a - 1) * n / (a * (n + 1));
462
+ }
463
+ function Oe(e) {
464
+ const t = e;
465
+ if (t <= 1)
466
+ return { u: 0.5, p: Math.pow(0.5, Math.max(t, 0)) };
467
+ const a = Math.pow(t, -1 / (t - 1));
468
+ return { u: a, p: Math.pow(a, t) };
469
+ }
470
+ function xe(e, t, a = 1.01, n = 10) {
471
+ if (e <= 0 || t <= 0 || t >= 1) return null;
472
+ const o = (d) => {
473
+ const u = st(e, d);
474
+ return u <= 0 ? 0 : (d - 1) * u / (d * (u + 1));
475
+ }, r = o(a), s = o(n);
476
+ if (t <= r && r > 0)
477
+ return a;
478
+ if (t >= s)
479
+ return n;
480
+ let i = a, l = n;
481
+ for (let d = 0; d < 50; d++) {
482
+ const u = 0.5 * (i + l), c = o(u);
483
+ if (Math.abs(c - t) < 1e-9)
484
+ return u;
485
+ c < t ? i = u : l = u;
486
+ }
487
+ return 0.5 * (i + l);
488
+ }
489
+ function Tt(e = 0.1) {
490
+ const t = it(e), a = (o) => {
491
+ const r = 1 - o;
492
+ return 1 - ((t + 1) * r * r * r - t * r * r);
493
+ }, n = (o) => {
494
+ const r = 1 - o;
495
+ return (t + 1) * 3 * r * r - t * 2 * r;
496
+ };
497
+ return {
498
+ id: "back-out",
499
+ label: `Back Out (${(e * 100).toFixed(0)}%)`,
500
+ easingFn: a,
501
+ velocityFn: n,
502
+ config: { overshoot: e }
503
+ };
504
+ }
505
+ function ot(e = 2) {
506
+ const t = Math.max(0.1, e);
507
+ return {
508
+ id: "power-out",
509
+ label: `Power Out (t^${t})`,
510
+ easingFn: (a) => {
511
+ const n = 1 - a;
512
+ return 1 - Math.pow(n, t);
513
+ },
514
+ velocityFn: (a) => {
515
+ const n = 1 - a;
516
+ return t * Math.pow(n, t - 1);
517
+ },
518
+ config: { exponent: t }
519
+ };
520
+ }
521
+ function Dt(e = 2, t = 0.1) {
522
+ const a = Math.max(0.1, e);
523
+ if (t <= 0 || a <= 1)
524
+ return ot(e);
525
+ const n = st(t, a), o = (s) => {
526
+ const i = 1 - s;
527
+ return n === 0 || a <= 1 ? 1 - Math.pow(i, a) : a - 1 < 1e-10 ? 1 - ((n + 1) * i - n) : 1 - Math.pow(i, a - 1) * ((n + 1) * i - n);
528
+ }, r = (s) => {
529
+ const i = 1 - s;
530
+ return bt(i, a, n);
531
+ };
532
+ return {
533
+ id: "power-back-out",
534
+ label: `Power Back Out (${(t * 100).toFixed(0)}%, n=${a.toFixed(2)})`,
535
+ easingFn: o,
536
+ velocityFn: r,
537
+ config: { exponent: a, overshoot: t, strength: n }
538
+ };
539
+ }
540
+ function Kt(e = 0.5, t = 0, a = 1, n = 0.5) {
541
+ const o = et(e, t, a, n), r = j(o, {
542
+ step: 1e-8,
543
+ boundarySample: 1e-3
544
+ });
545
+ return {
546
+ id: "bezier-out",
547
+ label: `Bezier (${e.toFixed(2)}, ${t.toFixed(2)}, ${a.toFixed(2)}, ${n.toFixed(2)})`,
548
+ easingFn: o,
549
+ velocityFn: r,
550
+ config: { x1: e, y1: t, x2: a, y2: n }
551
+ };
552
+ }
553
+ function Ct(e = 0.95) {
554
+ const t = Math.max(0, Math.min(1, e));
555
+ if (t === 0)
556
+ return {
557
+ id: "expo-out",
558
+ label: "Expo Out (linear)",
559
+ easingFn: (s) => s <= 0 ? 0 : s >= 1 ? 1 : s,
560
+ velocityFn: () => 1,
561
+ config: { decay: t }
562
+ };
563
+ if (t === 1)
564
+ return {
565
+ id: "expo-out",
566
+ label: "Expo Out (step)",
567
+ easingFn: (s) => s > 0 ? 1 : 0,
568
+ velocityFn: () => 0,
569
+ config: { decay: t }
570
+ };
571
+ const a = Math.log1p(-t), n = 1 / Math.expm1(a), o = mt(t), r = (s) => a * Math.exp(a * s) * n;
572
+ return {
573
+ id: "expo-out",
574
+ label: `Expo Out (${(t * 100).toFixed(0)}%)`,
575
+ easingFn: o,
576
+ velocityFn: r,
577
+ config: { decay: t }
578
+ };
579
+ }
580
+ const zt = {
581
+ back: Tt,
582
+ power: ot,
583
+ "power-back": Dt,
584
+ bezier: Kt,
585
+ expo: Ct
586
+ };
587
+ function Ee(e, t) {
588
+ const a = zt[e];
589
+ return e === "back" ? a(t?.overshoot ?? 0.1) : e === "power" ? a(t?.exponent ?? 2) : e === "power-back" ? a(t?.exponent ?? 2, t?.overshoot ?? 0.1) : e === "expo" ? a(t?.decay ?? 0.95) : a(
590
+ t?.x1 ?? 0.5,
591
+ t?.y1 ?? 0,
592
+ t?.x2 ?? 1,
593
+ t?.y2 ?? 0.5
594
+ );
595
+ }
596
+ function nt(e, t, a) {
597
+ let n;
598
+ Object.defineProperty(e, t, {
599
+ get: () => n ??= a(),
600
+ configurable: !0,
601
+ enumerable: !0
602
+ });
603
+ }
604
+ class J {
605
+ /** Immutable parameter object */
606
+ params;
607
+ constructor(t) {
608
+ this.params = Object.freeze({ ...t }), nt(this, "easeInVelocity", () => j(this.easeIn)), nt(this, "easeOutVelocity", () => j(this.easeOut));
609
+ }
610
+ /** Ease-out function — default: reverse of easeIn */
611
+ easeOut = (t) => 1 - this.easeIn(1 - t);
612
+ /** Velocity boundary for ease-out variant — default: reversed easeIn */
613
+ get easeOutBoundary() {
614
+ return {
615
+ start: this.easeInBoundary.end,
616
+ end: this.easeInBoundary.start
617
+ };
618
+ }
619
+ }
620
+ class G extends J {
621
+ static STROKES_KNOB = {
622
+ key: "strokes",
623
+ label: "Strokes",
624
+ type: "number",
625
+ default: 2,
626
+ min: 1,
627
+ max: 10,
628
+ step: 0.05,
629
+ isPrimary: !0
630
+ };
631
+ static EFFORT_KNOB = {
632
+ key: "effort",
633
+ label: "Effort",
634
+ type: "percent",
635
+ default: 0.4,
636
+ min: 0.05,
637
+ max: 0.95,
638
+ step: 0.01
639
+ };
640
+ static DRAG_KNOB = {
641
+ key: "drag",
642
+ label: "Drag",
643
+ type: "number",
644
+ default: 6,
645
+ min: 0.5,
646
+ max: 30,
647
+ step: 0.1
648
+ };
649
+ kind = "swim";
650
+ metadata = {
651
+ variants: { easeIn: !0, easeOut: !0 },
652
+ modes: { transition: !0, pulse: !1 }
653
+ };
654
+ knobSpecs = [
655
+ G.STROKES_KNOB,
656
+ G.EFFORT_KNOB,
657
+ G.DRAG_KNOB
658
+ ];
659
+ easeInBoundary = {
660
+ start: "zero",
661
+ end: "nonzero"
662
+ };
663
+ constructor(t) {
664
+ super(t);
665
+ const a = kt(t);
666
+ this.easeIn = (n) => a(n);
667
+ }
668
+ with(t) {
669
+ return new G({ ...this.params, ...t });
670
+ }
671
+ static create(t = {}) {
672
+ return new G({
673
+ strokes: t.strokes ?? 2,
674
+ effort: t.effort ?? 0.2,
675
+ drag: t.drag ?? 6
676
+ });
677
+ }
678
+ }
679
+ function Lt(e = 0.1) {
680
+ const t = it(e), a = t + 1;
681
+ return {
682
+ id: "back",
683
+ label: `Back (${(e * 100).toFixed(0)}% overshoot)`,
684
+ easingFn: (n) => n * n * (a * n - t),
685
+ velocityFn: (n) => n * (3 * a * n - 2 * t),
686
+ config: { overshoot: e, strength: t }
687
+ };
688
+ }
689
+ Lt(0.1);
690
+ function Jt(e, t, a) {
691
+ const n = Math.max(1e-3, Math.min(0.999, a));
692
+ return (o) => {
693
+ if (o <= 0 || o >= 1) return 0;
694
+ if (o <= n) {
695
+ const r = o / n;
696
+ return e(r);
697
+ } else {
698
+ const r = (o - n) / (1 - n);
699
+ return 1 - t(r);
700
+ }
701
+ };
702
+ }
703
+ function $t(e = {}) {
704
+ const { bounces: t = 4, decay: a = 90 } = e, n = Math.max(0.5, t), o = Math.max(0, 1 - a / 100), r = n <= 1 ? o : o === 0 ? 0 : Math.pow(o, 1 / (n - 1)), s = n * Math.PI, i = r <= 0 ? 50 : s / Math.PI * -Math.log(r), l = i / s, d = Math.exp(-i) * (Math.cos(s) + l * Math.sin(s));
705
+ return (u) => u <= 0 ? 1 : u >= 1 ? 0 : Math.exp(-i * u) * (Math.cos(s * u) + l * Math.sin(s * u)) - d * u;
706
+ }
707
+ function Gt(e = {}) {
708
+ const { bounces: t = 4, decay: a = 90 } = e, n = Math.max(1, Math.round(t)), o = Math.max(0, 1 - a / 100), r = n <= 1 ? Math.sqrt(o) : o === 0 ? 0 : Math.pow(o, 1 / (2 * (n - 1)));
709
+ if (r === 0)
710
+ return (c) => c <= 0 ? 1 : c >= 1 ? 0 : 1 - c * c;
711
+ const s = Math.abs(1 - r) < 1e-6 ? 1 + 2 * n : 1 + 2 * r * (1 - Math.pow(r, n)) / (1 - r), i = 2 * s * s, l = 1 / s, d = i * l, u = [0, l];
712
+ for (let c = 1; c <= n; c++) {
713
+ const M = 2 * Math.pow(r, c) * d / i;
714
+ u.push(u[u.length - 1] + M);
715
+ }
716
+ return u[u.length - 1] = 1, (c) => {
717
+ if (c <= 0) return 1;
718
+ if (c >= 1) return 0;
719
+ if (c <= l)
720
+ return 1 - 0.5 * i * c * c;
721
+ let M = 0;
722
+ for (let p = 1; p < u.length - 1; p++)
723
+ if (c <= u[p + 1]) {
724
+ M = p;
725
+ break;
726
+ }
727
+ M === 0 && (M = u.length - 2);
728
+ const I = Math.pow(r, M) * d, g = c - u[M];
729
+ return I * g - 0.5 * i * g * g;
730
+ };
731
+ }
732
+ function ht(e, t, a) {
733
+ const n = Math.max(1e-3, Math.min(0.999, a));
734
+ return (o) => {
735
+ if (o <= 0 || o >= 1) return 0;
736
+ if (o <= n) {
737
+ const r = o / n;
738
+ return e(r);
739
+ } else {
740
+ const r = (o - n) / (1 - n);
741
+ return t(r);
742
+ }
743
+ };
744
+ }
745
+ function ke(e, t) {
746
+ return {
747
+ isValid: !0,
748
+ point: {
749
+ x: 1 - e.x,
750
+ y: 1 - e.y
751
+ }
752
+ };
753
+ }
754
+ function ve(e, t) {
755
+ return {
756
+ isValid: !0,
757
+ point: {
758
+ x: 1 - e.x,
759
+ y: 1 - e.y
760
+ }
761
+ };
762
+ }
763
+ class W extends J {
764
+ static EXPONENT_KNOB = {
765
+ key: "exponent",
766
+ label: "Exponent",
767
+ type: "number",
768
+ default: 2,
769
+ min: 0.1,
770
+ max: 10,
771
+ step: 0.01,
772
+ isPrimary: !0
773
+ };
774
+ kind = "power";
775
+ metadata = {
776
+ variants: { easeIn: !0, easeOut: !0 },
777
+ modes: { transition: !0, pulse: !0 }
778
+ };
779
+ knobSpecs = [W.EXPONENT_KNOB];
780
+ constructor(t) {
781
+ super(t);
782
+ }
783
+ get easeInBoundary() {
784
+ return {
785
+ start: this.params.exponent > 1 ? "zero" : "nonzero",
786
+ end: "nonzero"
787
+ };
788
+ }
789
+ easeIn = (t) => Math.pow(t, this.params.exponent);
790
+ easeInVelocity = (t) => {
791
+ const a = this.params.exponent;
792
+ return a * Math.pow(t, a - 1);
793
+ };
794
+ // Analytical: d/du[1 - easeIn(1-u)] = easeInVelocity(1-u)
795
+ easeOutVelocity = (t) => this.easeInVelocity(1 - t);
796
+ with(t) {
797
+ return new W({
798
+ ...this.params,
799
+ ...t,
800
+ exponent: Math.max(0.1, t.exponent ?? this.params.exponent)
801
+ });
802
+ }
803
+ static create(t = {}) {
804
+ const a = Math.max(0.1, t.exponent ?? 2);
805
+ return new W({ exponent: a });
806
+ }
807
+ }
808
+ const Yt = 1e-4, Xt = 0.9999, qt = 0, Ut = 1;
809
+ function Wt(e) {
810
+ if (Number.isNaN(e))
811
+ return { atStart: !1, atEnd: !1 };
812
+ const t = Math.max(qt, Math.min(Ut, e));
813
+ return {
814
+ atStart: t <= Yt,
815
+ atEnd: t >= Xt
816
+ };
817
+ }
818
+ function ft(e) {
819
+ const { joinTime: t, headVelocityAtEnd: a, tailVelocityAtStart: n } = e;
820
+ if (t <= 0 || t >= 1)
821
+ return {
822
+ joinHeight: 0,
823
+ isValid: !1,
824
+ warning: `Invalid joinTime: ${t}. Must be in range (0, 1).`
825
+ };
826
+ if (a === 0)
827
+ return {
828
+ joinHeight: 0,
829
+ isValid: !1,
830
+ warning: `Invalid headVelocityAtEnd: ${a}. Must be non-zero.`
831
+ };
832
+ if (n <= 0)
833
+ return {
834
+ joinHeight: 0,
835
+ isValid: !1,
836
+ warning: `Invalid tailVelocityAtStart: ${n}. Must be positive.`
837
+ };
838
+ const o = a * (1 - t) + t * n;
839
+ if (Math.abs(o) < 1e-10)
840
+ return {
841
+ joinHeight: 0,
842
+ isValid: !1,
843
+ warning: "Denominator too close to zero. Cannot calculate join height."
844
+ };
845
+ const r = t * n / o;
846
+ let s;
847
+ return r < 0 ? s = `Join height is negative (${r.toFixed(4)}). This may indicate incompatible velocities.` : r > 1 ? a < 0 ? s = `Join height exceeds 1 (${r.toFixed(4)}) due to negative head slope. This creates a natural reflection/dip effect.` : s = `Join height exceeds 1 (${r.toFixed(4)}). This may cause overshoot beyond target.` : a < 0 && r <= 1 && (s = `Head ends with negative slope (${a.toFixed(4)}). Curve will dip below join height before tail recovers.`), {
848
+ joinHeight: r,
849
+ isValid: !0,
850
+ warning: s
851
+ };
852
+ }
853
+ function _t(e) {
854
+ const {
855
+ joinTime: t,
856
+ headVelocityAtEnd: a,
857
+ pulseNaturalStartVelocity: n,
858
+ isBounceStrategy: o
859
+ } = e;
860
+ if (o)
861
+ return {
862
+ isValid: !1,
863
+ failureReason: "bounce_tail_unsupported"
864
+ };
865
+ if (n <= 0)
866
+ return {
867
+ isValid: !1,
868
+ failureReason: "invalid_pulse_velocity"
869
+ };
870
+ const r = n;
871
+ let s = r * t / a;
872
+ s < 0 && (s = 1), s >= 1 && (s = 0.9999);
873
+ const l = (1 - s) / r;
874
+ return l <= 0 ? {
875
+ isValid: !1,
876
+ failureReason: "invalid_bridge_duration"
877
+ } : t + l >= 1 ? {
878
+ isValid: !1,
879
+ failureReason: "bridge_exceeds_timeline"
880
+ } : {
881
+ isValid: !0,
882
+ bridgeParams: {
883
+ joinHeight: s,
884
+ duration: l,
885
+ velocity: r
886
+ }
887
+ };
888
+ }
889
+ function Zt(e, t, a) {
890
+ return e !== void 0 && Number.isFinite(e) && e > 0 && t > 0 && a > 0;
891
+ }
892
+ function Qt(e, t, a, n) {
893
+ return t ? e * a / n : 0;
894
+ }
895
+ function Rt(e, t, a) {
896
+ const n = e;
897
+ return 1 / (1 / n + (a - a / n) + (1 - a) / t);
898
+ }
899
+ function jt(e) {
900
+ const {
901
+ joinTime: t,
902
+ headVelocityAtEnd: a,
903
+ tailVelocityAtStart: n,
904
+ maxSpeed: o,
905
+ naturalJoinHeight: r,
906
+ naturalJoinHeightIsValid: s
907
+ } = e;
908
+ if (Qt(
909
+ r,
910
+ s,
911
+ a,
912
+ t
913
+ ) <= o) return null;
914
+ const l = a, d = Rt(l, n, t), u = Math.max(o, Math.max(d, 1));
915
+ let c;
916
+ if (Math.abs(1 / l - 1) < 1e-9)
917
+ c = 0;
918
+ else {
919
+ const O = 1 / l - 1, f = 1 - 1 / n, E = 1 / u - 1 / n, V = t * O / (1 - t), _ = f - V;
920
+ let v;
921
+ Math.abs(_) < 1e-9 ? v = t : v = (E - V) / _, v = Math.max(t, Math.min(1 - 0.01, v)), c = t * (1 - v) / (1 - t), c = Math.max(0, Math.min(t, c));
922
+ }
923
+ const M = c > 0 ? u * c / l : 0, b = c > 0 ? t + (t - c) * (1 - t) / t : t + (1 - t) * (1 - 1 / (u * (1 / n))), I = Math.max(t, Math.min(1 - 0.01, b)), p = M + u * (t - c) + u * (I - t), P = 1 - I;
924
+ return p <= 0 || p >= 1 || P <= 0.01 ? null : {
925
+ cruiseSpeed: u,
926
+ tStar: c,
927
+ tC: I,
928
+ headHeight: M,
929
+ tailStartPos: p
930
+ };
931
+ }
932
+ function te(e, t, a) {
933
+ const { cruiseSpeed: n, tStar: o, tC: r, headHeight: s, tailStartPos: i } = e, l = 1 - r;
934
+ return (d) => {
935
+ if (d <= 0) return 0;
936
+ if (d >= 1) return 1;
937
+ if (o > 0 && d <= o) {
938
+ const u = d / o;
939
+ return s * t(u);
940
+ } else {
941
+ if (d <= r)
942
+ return (o > 0 ? s : 0) + n * (d - o);
943
+ {
944
+ const u = (d - r) / l;
945
+ return i + (1 - i) * a(u);
946
+ }
947
+ }
948
+ };
949
+ }
950
+ function ee(e) {
951
+ const {
952
+ joinTime: t,
953
+ headBounces: a,
954
+ headDecay: n,
955
+ tailBounces: o,
956
+ tailDecay: r,
957
+ springTailBuilder: s
958
+ } = e, i = s.build({
959
+ joinTime: 0.5,
960
+ bounces: a,
961
+ decayPct: n,
962
+ bridge: void 0
963
+ }), l = Y(i.p), d = (g) => l(g * 0.5), u = (g) => i.v(1 - g * 0.5) * 0.5, c = t, M = (g) => g <= 0 ? 0 : g >= t ? t : c * d(g / t), b = (g) => g <= 0 || g >= t ? 0 : c / t * u(g / t);
964
+ return s.build({
965
+ joinTime: t,
966
+ bounces: o,
967
+ decayPct: r,
968
+ L: M,
969
+ Ld: b,
970
+ bridge: void 0
971
+ }).p;
972
+ }
973
+ const ne = 10;
974
+ function ae(e) {
975
+ const { joinTime: t, headBounces: a, headDecay: n, tailBounces: o, tailDecay: r } = e;
976
+ if (t <= 0 || t >= 1)
977
+ return { easingFn: null };
978
+ if (a < 1 || o < 1)
979
+ return { easingFn: null };
980
+ const s = dt.build({
981
+ joinTime: 0.5,
982
+ bounces: a,
983
+ decayPct: n,
984
+ bridge: void 0
985
+ }), i = dt.build({
986
+ joinTime: 0.5,
987
+ bounces: o,
988
+ decayPct: r,
989
+ bridge: void 0
990
+ }), l = Y(s.p), d = (_) => l(_ * 0.5), u = ne, c = t, M = c / u, b = (1 - c) / u, I = t - M, g = t + b, p = 1 - g;
991
+ if (I <= 0 || M <= 0 || b <= 0 || p <= 0)
992
+ return { easingFn: null };
993
+ const P = 2 * I, O = 2 * p, f = d(1), E = i.p(0.5);
994
+ return {
995
+ easingFn: (_) => {
996
+ if (_ <= 0) return 0;
997
+ if (_ >= 1) return 1;
998
+ if (_ <= I) {
999
+ const v = _ / I;
1000
+ return P * d(v);
1001
+ } else if (_ <= t) {
1002
+ const v = P * f, F = (_ - I) / M;
1003
+ return v + (c - v) * F;
1004
+ } else if (_ <= g) {
1005
+ const v = 1 - O * (1 - E), F = (_ - t) / b;
1006
+ return c + (v - c) * F;
1007
+ } else {
1008
+ const v = (_ - g) / p, F = i.p(0.5 + v * 0.5);
1009
+ return 1 - O * (1 - F);
1010
+ }
1011
+ },
1012
+ diagnostics: {
1013
+ joinPosition: c,
1014
+ headBridgeDuration: M,
1015
+ tailBridgeDuration: b,
1016
+ headPulseDuration: I,
1017
+ tailPulseDuration: p,
1018
+ bridgeVelocity: u
1019
+ }
1020
+ };
1021
+ }
1022
+ function re() {
1023
+ return {
1024
+ easingFn: (e) => e,
1025
+ velocityFn: () => 1
1026
+ };
1027
+ }
1028
+ function se(e, t) {
1029
+ const { joinTime: a, pulseTail: n, useBridge: o = !0, bridgeTuning: r } = e;
1030
+ if (a <= 0 || a >= 1)
1031
+ throw new Error(`Invalid joinTime: ${a}. Must be in range (0, 1).`);
1032
+ if (n.bounces < 1)
1033
+ throw new Error(
1034
+ `Invalid pulse tail bounces: ${n.bounces}. Must be >= 1.`
1035
+ );
1036
+ const s = re(), i = 1 - a, l = t(n.strategy, {
1037
+ head: s.easingFn,
1038
+ headVelocityFn: s.velocityFn,
1039
+ join: i,
1040
+ bounces: n.bounces,
1041
+ decay: n.decay,
1042
+ useBridge: o,
1043
+ bridgeTuning: r
1044
+ });
1045
+ return Y(l);
1046
+ }
1047
+ function z(e) {
1048
+ return e.params;
1049
+ }
1050
+ function oe(e, t, a = {}) {
1051
+ const {
1052
+ joinTime: n = 0.5,
1053
+ movement: o = "transition",
1054
+ mirror: r = !1,
1055
+ useBridge: s = !0,
1056
+ bridgeTuning: i,
1057
+ allowGeneralizedBackTail: l = !1,
1058
+ maxSpeed: d
1059
+ } = a, u = {
1060
+ movement: o,
1061
+ headKind: e.kind,
1062
+ tailKind: t.kind,
1063
+ joinTime: n,
1064
+ mirror: r
1065
+ };
1066
+ return o === "pulse" ? ie(e, t, n, u) : ce(e, t, {
1067
+ joinTime: n,
1068
+ mirror: r,
1069
+ useBridge: s,
1070
+ bridgeTuning: i,
1071
+ allowGeneralizedBackTail: l,
1072
+ maxSpeed: d,
1073
+ meta: u
1074
+ });
1075
+ }
1076
+ function ie(e, t, a, n) {
1077
+ const r = (e.kind === "spring" ? W.create({
1078
+ exponent: z(e).bounces ?? 2
1079
+ }) : e).easeOut;
1080
+ let s;
1081
+ if (t.kind === "spring") {
1082
+ const { bounces: i, decay: l } = z(t);
1083
+ s = ht(
1084
+ r,
1085
+ $t({ bounces: i, decay: l * 100 }),
1086
+ a
1087
+ );
1088
+ } else if (t.kind === "bounce") {
1089
+ const { bounces: i, decay: l } = z(t);
1090
+ s = ht(
1091
+ r,
1092
+ Gt({ bounces: i, decay: l * 100 }),
1093
+ a
1094
+ );
1095
+ } else
1096
+ s = Jt(r, t.easeIn, a);
1097
+ return D(s, n);
1098
+ }
1099
+ function ce(e, t, a) {
1100
+ const { joinTime: n, mirror: o } = a, r = Wt(n);
1101
+ return r.atStart && !(t.kind === "spring" || t.kind === "bounce") ? D((s) => Math.max(0, Math.min(1, s)), a.meta) : r.atEnd ? D(e.easeIn, a.meta) : e.kind === "spring" ? ue(e, t, a) : t.kind === "spring" || t.kind === "bounce" ? le(e, t, a) : e.kind === "bezier" && t.kind === "bezier" ? de(e, t, a) : he(e, t, a);
1102
+ }
1103
+ function ue(e, t, a) {
1104
+ const { joinTime: n, useBridge: o, bridgeTuning: r } = a, s = z(e), i = s.bounces ?? 4, l = (s.decay ?? 0.95) * 100;
1105
+ if (t.kind === "spring") {
1106
+ const p = z(t), P = ae({
1107
+ joinTime: n,
1108
+ headBounces: i,
1109
+ headDecay: l,
1110
+ tailBounces: p.bounces,
1111
+ tailDecay: p.decay * 100
1112
+ });
1113
+ if (P.easingFn)
1114
+ return D(P.easingFn, a.meta);
1115
+ const O = ee({
1116
+ joinTime: n,
1117
+ headBounces: i,
1118
+ headDecay: l,
1119
+ tailBounces: p.bounces,
1120
+ tailDecay: p.decay * 100,
1121
+ springTailBuilder: R
1122
+ });
1123
+ return D(O, a.meta);
1124
+ }
1125
+ if (t.kind === "bounce") {
1126
+ const p = z(t), P = se(
1127
+ {
1128
+ joinTime: n,
1129
+ // TODO: springHead.decay uses tailParams — should it use headParams instead?
1130
+ // This path is currently disabled (spring head not exposed in Fuse app).
1131
+ // When re-enabling, verify whether the spring head's own decay should drive
1132
+ // the complementary curve, rather than mirroring the bounce tail's decay.
1133
+ springHead: { decay: p.decay * 100 },
1134
+ pulseTail: {
1135
+ strategy: tt,
1136
+ bounces: p.bounces,
1137
+ decay: p.decay * 100
1138
+ },
1139
+ useBridge: o,
1140
+ bridgeTuning: r
1141
+ },
1142
+ (O, f) => pt(O, f)
1143
+ );
1144
+ return D(P, a.meta);
1145
+ }
1146
+ const d = a.mirror ? Y(e.easeIn) : t.easeOut, u = a.mirror ? (p) => e.easeInVelocity(1 - p) : t.easeOutVelocity, c = Y(d), M = (p) => u(1 - p), b = 1 - n, I = pt(R, {
1147
+ head: c,
1148
+ headVelocityFn: M,
1149
+ joinTime: b,
1150
+ bounces: i,
1151
+ decay: l,
1152
+ useBridge: !0,
1153
+ bridgeTuning: r
1154
+ }), g = Y(I);
1155
+ return D(g, a.meta);
1156
+ }
1157
+ function le(e, t, a) {
1158
+ const { joinTime: n, useBridge: o, bridgeTuning: r } = a, s = z(t), i = s.bounces, l = s.decay * 100, d = (t.kind === "spring", t.constructor.tailStrategy), u = e.easeIn, c = e.easeInVelocity;
1159
+ let M;
1160
+ const b = t.kind === "spring";
1161
+ if (o && !b && d.getNaturalStartVelocity) {
1162
+ const g = d.getNaturalStartVelocity(
1163
+ { bounces: i, decayPct: l },
1164
+ c,
1165
+ r
1166
+ ), p = _t({
1167
+ joinTime: n,
1168
+ headVelocityAtEnd: c(1),
1169
+ pulseNaturalStartVelocity: g,
1170
+ isBounceStrategy: t.kind === "bounce"
1171
+ });
1172
+ p.isValid && (M = p.bridgeParams);
1173
+ }
1174
+ const I = d.build({
1175
+ joinTime: n,
1176
+ bounces: i,
1177
+ decayPct: l,
1178
+ L: u,
1179
+ Ld: c,
1180
+ bridge: M
1181
+ });
1182
+ return D(I.p, a.meta);
1183
+ }
1184
+ function de(e, t, a) {
1185
+ const { joinTime: n } = a, o = z(e), r = z(t), s = n, i = o.x1 * n, l = o.y1 * s, d = o.x2 * n, u = o.y2 * s, c = n, M = s;
1186
+ let b;
1187
+ Math.abs(c - d) < 1e-8 ? b = 1e8 : b = (M - u) / (c - d);
1188
+ const I = n + r.x1 * (1 - n), g = s + b * (I - n), p = n + r.x2 * (1 - n), P = s + r.y2 * (1 - s), O = i / n, f = l / s, E = d / n, V = u / s, _ = et(
1189
+ O,
1190
+ f,
1191
+ E,
1192
+ V
1193
+ ), v = (I - n) / (1 - n), F = (g - s) / (1 - s), k = (p - n) / (1 - n), B = (P - s) / (1 - s), N = et(
1194
+ v,
1195
+ F,
1196
+ k,
1197
+ B
1198
+ );
1199
+ return D((H) => {
1200
+ if (H <= 0) return 0;
1201
+ if (H >= 1) return 1;
1202
+ if (H <= n) {
1203
+ const m = H / n;
1204
+ return s * _(m);
1205
+ } else {
1206
+ const m = (H - n) / (1 - n);
1207
+ return s + (1 - s) * N(m);
1208
+ }
1209
+ }, a.meta);
1210
+ }
1211
+ function he(e, t, a) {
1212
+ const { joinTime: n, mirror: o, allowGeneralizedBackTail: r, maxSpeed: s } = a, i = e.easeIn, l = e.easeInVelocity;
1213
+ let d, u;
1214
+ o ? (d = Y(i), u = (P) => l(1 - P)) : (d = t.easeOut, u = t.easeOutVelocity);
1215
+ const c = l(1), M = u(0);
1216
+ if (Zt(s, c, M)) {
1217
+ const P = ft({
1218
+ joinTime: n,
1219
+ headVelocityAtEnd: c,
1220
+ tailVelocityAtStart: M
1221
+ }), O = jt({
1222
+ joinTime: n,
1223
+ headVelocityAtEnd: c,
1224
+ tailVelocityAtStart: M,
1225
+ maxSpeed: s,
1226
+ naturalJoinHeight: P.joinHeight,
1227
+ naturalJoinHeightIsValid: P.isValid
1228
+ });
1229
+ if (O) {
1230
+ const f = te(
1231
+ O,
1232
+ i,
1233
+ d
1234
+ );
1235
+ return D(f, a.meta);
1236
+ }
1237
+ }
1238
+ let b, I = !1, g = c;
1239
+ if (c < 0 && (t.kind === "power" || t.kind === "back"))
1240
+ b = 1, I = !0, g = c * (b / n);
1241
+ else {
1242
+ const P = ft({
1243
+ joinTime: n,
1244
+ headVelocityAtEnd: c,
1245
+ tailVelocityAtStart: M
1246
+ });
1247
+ if (!P.isValid)
1248
+ return D((f) => Math.max(0, Math.min(1, f)), a.meta);
1249
+ const O = P.joinHeight;
1250
+ b = Math.max(0, Math.min(1, O)), r && b >= 0.9999 && (t.kind === "power-back" || t.kind === "back" || t.kind === "power") && (I = !0, b = 1, g = c * (b / n));
1251
+ }
1252
+ return D((P) => {
1253
+ if (P <= 0) return 0;
1254
+ if (P >= 1) return 1;
1255
+ if (P <= n) {
1256
+ const O = P / n;
1257
+ return b * i(O);
1258
+ } else {
1259
+ const O = (P - n) / (1 - n);
1260
+ if (I) {
1261
+ const f = g * (1 - n), E = b, V = f, _ = (3 * (1 - E) - 2 * V) / (V - (1 - E));
1262
+ return (1 - V - E) * ((_ + 1) * O * O * O - _ * O * O) + V * O + E;
1263
+ } else
1264
+ return b + (1 - b) * d(O);
1265
+ }
1266
+ }, a.meta);
1267
+ }
1268
+ function pt(e, t) {
1269
+ const {
1270
+ head: a = (c) => c,
1271
+ headVelocityFn: n = () => 1,
1272
+ joinTime: o = 0.5,
1273
+ bounces: r = 4,
1274
+ decay: s = 95,
1275
+ useBridge: i = !0,
1276
+ bridgeTuning: l
1277
+ } = t;
1278
+ let d;
1279
+ if (i && e.getNaturalStartVelocity) {
1280
+ const c = e.getNaturalStartVelocity(
1281
+ { bounces: r, decayPct: s },
1282
+ n,
1283
+ l
1284
+ ), M = _t({
1285
+ joinTime: o,
1286
+ headVelocityAtEnd: n(1),
1287
+ pulseNaturalStartVelocity: c,
1288
+ isBounceStrategy: e === tt
1289
+ });
1290
+ M.isValid && (d = M.bridgeParams);
1291
+ }
1292
+ return e.build({
1293
+ joinTime: o,
1294
+ bounces: r,
1295
+ decayPct: s,
1296
+ L: a,
1297
+ Ld: n,
1298
+ bridge: d
1299
+ }).p;
1300
+ }
1301
+ class Z extends J {
1302
+ static OVERSHOOT_KNOB = {
1303
+ key: "overshoot",
1304
+ label: "Overshoot",
1305
+ type: "percent",
1306
+ default: 0.1,
1307
+ min: 0,
1308
+ max: 1,
1309
+ step: 0.01,
1310
+ isPrimary: !0
1311
+ };
1312
+ kind = "back";
1313
+ metadata = {
1314
+ variants: { easeIn: !0, easeOut: !0 },
1315
+ modes: { transition: !0, pulse: !0 }
1316
+ };
1317
+ knobSpecs = [Z.OVERSHOOT_KNOB];
1318
+ easeInBoundary = {
1319
+ start: "zero",
1320
+ end: "nonzero"
1321
+ };
1322
+ /** Cached strength parameter derived from overshoot */
1323
+ strength;
1324
+ constructor(t) {
1325
+ super(t), this.strength = it(t.overshoot);
1326
+ }
1327
+ easeIn = (t) => vt(t, this.strength);
1328
+ easeInVelocity = (t) => lt(t, this.strength);
1329
+ // Analytical: d/du[1 - easeIn(1-u)] = easeInVelocity(1-u)
1330
+ easeOutVelocity = (t) => lt(1 - t, this.strength);
1331
+ with(t) {
1332
+ return new Z({ ...this.params, ...t });
1333
+ }
1334
+ static create(t = {}) {
1335
+ const a = t.overshoot ?? 0.1;
1336
+ return new Z({ overshoot: a });
1337
+ }
1338
+ }
1339
+ class X extends J {
1340
+ static EXPONENT_KNOB = {
1341
+ key: "exponent",
1342
+ label: "Exponent",
1343
+ type: "number",
1344
+ default: 3,
1345
+ min: 0.1,
1346
+ max: 10,
1347
+ step: 0.01,
1348
+ isPrimary: !0
1349
+ };
1350
+ static OVERSHOOT_KNOB = {
1351
+ key: "overshoot",
1352
+ label: "Overshoot",
1353
+ type: "percent",
1354
+ default: 0,
1355
+ min: 0,
1356
+ max: 1,
1357
+ step: 0.01
1358
+ };
1359
+ kind = "power-back";
1360
+ metadata = {
1361
+ variants: { easeIn: !0, easeOut: !0 },
1362
+ modes: { transition: !0, pulse: !0 }
1363
+ };
1364
+ knobSpecs = [
1365
+ X.EXPONENT_KNOB,
1366
+ X.OVERSHOOT_KNOB
1367
+ ];
1368
+ /** Cached strength parameter derived from overshoot + exponent */
1369
+ strength;
1370
+ constructor(t) {
1371
+ super(t), this.strength = st(t.overshoot, t.exponent);
1372
+ }
1373
+ get easeInBoundary() {
1374
+ return {
1375
+ start: this.params.exponent > 2 || this.params.overshoot <= 0 ? "zero" : "nonzero",
1376
+ end: "nonzero"
1377
+ };
1378
+ }
1379
+ easeIn = (t) => At(t, this.params.exponent, this.strength);
1380
+ easeInVelocity = (t) => bt(t, this.params.exponent, this.strength);
1381
+ // Analytical: d/du[1 - easeIn(1-u)] = easeInVelocity(1-u)
1382
+ easeOutVelocity = (t) => this.easeInVelocity(1 - t);
1383
+ with(t) {
1384
+ return new X({
1385
+ ...this.params,
1386
+ ...t,
1387
+ exponent: Math.max(0.1, t.exponent ?? this.params.exponent)
1388
+ });
1389
+ }
1390
+ static create(t = {}) {
1391
+ const a = Math.max(0.1, t.exponent ?? 3), n = t.overshoot ?? 0.3;
1392
+ return new X({ exponent: a, overshoot: n });
1393
+ }
1394
+ }
1395
+ class L extends J {
1396
+ static X1_KNOB = {
1397
+ key: "x1",
1398
+ label: "X1",
1399
+ type: "number",
1400
+ default: 0.42,
1401
+ min: 0,
1402
+ max: 1,
1403
+ step: 0.01
1404
+ };
1405
+ static Y1_KNOB = {
1406
+ key: "y1",
1407
+ label: "Y1",
1408
+ type: "number",
1409
+ default: 0,
1410
+ min: -0.5,
1411
+ max: 1.5,
1412
+ step: 0.01
1413
+ };
1414
+ static X2_KNOB = {
1415
+ key: "x2",
1416
+ label: "X2",
1417
+ type: "number",
1418
+ default: 1,
1419
+ min: 0,
1420
+ max: 1,
1421
+ step: 0.01
1422
+ };
1423
+ static Y2_KNOB = {
1424
+ key: "y2",
1425
+ label: "Y2",
1426
+ type: "number",
1427
+ default: 1,
1428
+ min: -0.5,
1429
+ max: 1.5,
1430
+ step: 0.01
1431
+ };
1432
+ kind = "bezier";
1433
+ metadata = {
1434
+ variants: { easeIn: !0, easeOut: !0 },
1435
+ modes: { transition: !0, pulse: !0 }
1436
+ };
1437
+ knobSpecs = [
1438
+ L.X1_KNOB,
1439
+ L.Y1_KNOB,
1440
+ L.X2_KNOB,
1441
+ L.Y2_KNOB
1442
+ ];
1443
+ /** Both ends depend on control points — always nonzero */
1444
+ easeInBoundary = {
1445
+ start: "nonzero",
1446
+ end: "nonzero"
1447
+ };
1448
+ // Bezier is general-purpose — easeIn and easeOut are the same curve,
1449
+ // directly defined by the stored control points (no reversal).
1450
+ bezier = et(
1451
+ this.params.x1,
1452
+ this.params.y1,
1453
+ this.params.x2,
1454
+ this.params.y2
1455
+ );
1456
+ easeIn = (t) => this.bezier(t);
1457
+ easeOut = (t) => this.bezier(t);
1458
+ constructor(t) {
1459
+ super(t);
1460
+ const a = () => j(this.bezier, { boundarySample: 1e-3 });
1461
+ nt(this, "easeInVelocity", a), nt(this, "easeOutVelocity", a);
1462
+ }
1463
+ with(t) {
1464
+ return new L({ ...this.params, ...t });
1465
+ }
1466
+ static create(t = {}) {
1467
+ return new L({
1468
+ x1: t.x1 ?? 0.42,
1469
+ y1: t.y1 ?? 0,
1470
+ x2: t.x2 ?? 1,
1471
+ y2: t.y2 ?? 1
1472
+ });
1473
+ }
1474
+ }
1475
+ class Q extends J {
1476
+ static DECAY_KNOB = {
1477
+ key: "decay",
1478
+ label: "Decay",
1479
+ type: "percent",
1480
+ default: 0.95,
1481
+ min: 0.8,
1482
+ max: 0.999,
1483
+ step: 1e-3,
1484
+ isPrimary: !0
1485
+ };
1486
+ kind = "expo";
1487
+ metadata = {
1488
+ variants: { easeIn: !1, easeOut: !0 },
1489
+ modes: { transition: !0, pulse: !1 }
1490
+ };
1491
+ knobSpecs = [Q.DECAY_KNOB];
1492
+ easeInBoundary = {
1493
+ start: "nonzero",
1494
+ end: "nonzero"
1495
+ };
1496
+ /** Cached ease-out function and derivative constants */
1497
+ easeOutFn;
1498
+ negK;
1499
+ scale;
1500
+ d;
1501
+ constructor(t) {
1502
+ super(t), this.d = Math.max(0, Math.min(1, t.decay)), this.d === 0 ? (this.easeOutFn = (a) => Math.max(0, Math.min(1, a)), this.negK = 0, this.scale = 1) : this.d === 1 ? (this.easeOutFn = (a) => a > 0 ? 1 : 0, this.negK = -1 / 0, this.scale = 0) : (this.negK = Math.log1p(-this.d), this.scale = 1 / Math.expm1(this.negK), this.easeOutFn = mt(this.d));
1503
+ }
1504
+ /** easeIn is the reverse of easeOut (not natively supported, metadata.variants.easeIn = false) */
1505
+ easeIn = (t) => 1 - this.easeOutFn(1 - t);
1506
+ easeInVelocity = (t) => this.easeOutVelocityImpl(1 - t);
1507
+ easeOut = (t) => this.easeOutFn(t);
1508
+ easeOutVelocity = (t) => this.easeOutVelocityImpl(t);
1509
+ easeOutVelocityImpl(t) {
1510
+ return this.d === 0 ? 1 : this.d === 1 ? 0 : this.negK * Math.exp(this.negK * t) * this.scale;
1511
+ }
1512
+ with(t) {
1513
+ return new Q({ ...this.params, ...t });
1514
+ }
1515
+ static create(t = {}) {
1516
+ return new Q({ decay: t.decay ?? 0.95 });
1517
+ }
1518
+ }
1519
+ const fe = (e) => e, pe = (e) => 1, ye = 1e-4;
1520
+ class q extends J {
1521
+ static BOUNCES_KNOB = {
1522
+ key: "bounces",
1523
+ label: "Bounces",
1524
+ type: "number",
1525
+ default: 4,
1526
+ min: 0,
1527
+ max: 10,
1528
+ step: 1,
1529
+ isPrimary: !0
1530
+ };
1531
+ static DECAY_KNOB = {
1532
+ key: "decay",
1533
+ label: "Decay",
1534
+ type: "percent",
1535
+ default: 0.95,
1536
+ min: 0,
1537
+ max: 0.99,
1538
+ step: 0.01
1539
+ };
1540
+ kind = "spring";
1541
+ metadata = {
1542
+ variants: { easeIn: !1, easeOut: !0 },
1543
+ modes: { transition: !0, pulse: !0 }
1544
+ };
1545
+ knobSpecs = [
1546
+ q.BOUNCES_KNOB,
1547
+ q.DECAY_KNOB
1548
+ ];
1549
+ easeInBoundary = {
1550
+ start: "nonzero",
1551
+ end: "nonzero"
1552
+ };
1553
+ /** Cached standalone easeOut function built with minimal head defaults */
1554
+ builtP;
1555
+ builtV;
1556
+ constructor(t) {
1557
+ super(t);
1558
+ const a = R.build({
1559
+ joinTime: ye,
1560
+ bounces: t.bounces,
1561
+ decayPct: t.decay * 100,
1562
+ // TailBuildParams uses 0-100
1563
+ L: fe,
1564
+ Ld: pe
1565
+ });
1566
+ this.builtP = a.p, this.builtV = a.v;
1567
+ }
1568
+ /** easeIn is the reverse of easeOut (not natively supported) */
1569
+ easeIn = (t) => 1 - this.builtP(1 - t);
1570
+ easeInVelocity = (t) => this.builtV(1 - t);
1571
+ easeOut = (t) => this.builtP(t);
1572
+ easeOutVelocity = (t) => this.builtV(t);
1573
+ /** Access the underlying TailStrategy for full fuse composition */
1574
+ static get tailStrategy() {
1575
+ return R;
1576
+ }
1577
+ with(t) {
1578
+ return new q({ ...this.params, ...t });
1579
+ }
1580
+ static create(t = {}) {
1581
+ return new q({
1582
+ bounces: t.bounces ?? 4,
1583
+ decay: t.decay ?? 0.95
1584
+ });
1585
+ }
1586
+ }
1587
+ const ge = (e) => e, me = (e) => 1, Me = 1e-4;
1588
+ class U extends J {
1589
+ static BOUNCES_KNOB = {
1590
+ key: "bounces",
1591
+ label: "Bounces",
1592
+ type: "number",
1593
+ default: 4,
1594
+ min: 1,
1595
+ max: 10,
1596
+ step: 1,
1597
+ isPrimary: !0
1598
+ };
1599
+ static DECAY_KNOB = {
1600
+ key: "decay",
1601
+ label: "Decay",
1602
+ type: "percent",
1603
+ default: 0.95,
1604
+ min: 0,
1605
+ max: 0.99,
1606
+ step: 0.01
1607
+ };
1608
+ kind = "bounce";
1609
+ metadata = {
1610
+ variants: { easeIn: !1, easeOut: !0 },
1611
+ modes: { transition: !0, pulse: !0 }
1612
+ };
1613
+ knobSpecs = [
1614
+ U.BOUNCES_KNOB,
1615
+ U.DECAY_KNOB
1616
+ ];
1617
+ easeInBoundary = {
1618
+ start: "nonzero",
1619
+ end: "nonzero"
1620
+ };
1621
+ /** Cached standalone easeOut function built with minimal head defaults */
1622
+ builtP;
1623
+ builtV;
1624
+ constructor(t) {
1625
+ super(t);
1626
+ const a = tt.build({
1627
+ joinTime: Me,
1628
+ bounces: t.bounces,
1629
+ decayPct: t.decay * 100,
1630
+ L: ge,
1631
+ Ld: me
1632
+ });
1633
+ this.builtP = a.p, this.builtV = a.v;
1634
+ }
1635
+ easeIn = (t) => 1 - this.builtP(1 - t);
1636
+ easeInVelocity = (t) => this.builtV(1 - t);
1637
+ easeOut = (t) => this.builtP(t);
1638
+ easeOutVelocity = (t) => this.builtV(t);
1639
+ /** Access the underlying TailStrategy for full fuse composition */
1640
+ static get tailStrategy() {
1641
+ return tt;
1642
+ }
1643
+ with(t) {
1644
+ return new U({ ...this.params, ...t });
1645
+ }
1646
+ static create(t = {}) {
1647
+ return new U({
1648
+ bounces: t.bounces ?? 4,
1649
+ decay: t.decay ?? 0.95
1650
+ });
1651
+ }
1652
+ }
1653
+ const be = {
1654
+ power: W,
1655
+ back: Z,
1656
+ "power-back": X,
1657
+ bezier: L,
1658
+ expo: Q,
1659
+ spring: q,
1660
+ bounce: U,
1661
+ swim: G
1662
+ };
1663
+ function yt(e, t) {
1664
+ return be[e].create(t);
1665
+ }
1666
+ function gt(e) {
1667
+ const { kind: t, ...a } = e;
1668
+ return a;
1669
+ }
1670
+ function Se(e) {
1671
+ const {
1672
+ movement: t = "transition",
1673
+ head: a,
1674
+ tail: n,
1675
+ joinTime: o = 0.5,
1676
+ mirror: r = !1,
1677
+ useBridge: s,
1678
+ bridgeTuning: i,
1679
+ allowGeneralizedBackTail: l,
1680
+ maxSpeed: d
1681
+ } = e, u = yt(a.kind, gt(a)), c = yt(n.kind, gt(n));
1682
+ return oe(u, c, {
1683
+ movement: t,
1684
+ joinTime: o,
1685
+ mirror: r,
1686
+ useBridge: s,
1687
+ bridgeTuning: i,
1688
+ allowGeneralizedBackTail: l,
1689
+ maxSpeed: d
1690
+ });
1691
+ }
1692
+ const It = 1e-6, ut = It, Pt = 1 - It;
1693
+ function Ve(e, t, a = !1) {
1694
+ return !a && (t === "power-back" || t === "back" || t === "power") ? Math.min(1, e) : e;
1695
+ }
1696
+ function we(e, t, a = !1) {
1697
+ return !a && t === "power-back" ? Math.max(0, e) : e;
1698
+ }
1699
+ export {
1700
+ Z as BackRem,
1701
+ L as BezierRem,
1702
+ U as BounceRem,
1703
+ Q as ExpoRem,
1704
+ X as PowerBackRem,
1705
+ W as PowerRem,
1706
+ q as SpringRem,
1707
+ G as SwimRem,
1708
+ ve as calculateHeadP2FromTailP1,
1709
+ ke as calculateTailP1FromHeadP2,
1710
+ we as clampBezierY1ForHead,
1711
+ Ve as clampBezierY2ForTail,
1712
+ At as evalPowerBackIn,
1713
+ xe as findExponentForMinimumPosition,
1714
+ Se as fuse,
1715
+ yt as getEasingRem,
1716
+ Pe as getLocalMinimumPosition,
1717
+ Oe as getPowerCurveCanonicalPoint,
1718
+ Ee as getTailStrategy,
1719
+ st as solvePowerBackStrength
1720
+ };
1721
+ //# sourceMappingURL=index.es.js.map