@n-uf/motion 26.11.2 → 26.11.3
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/CHANGELOG.md +22 -0
- package/README.md +56 -4
- package/dist/{chunk-LCTGXGOI.js → chunk-6W5KW7XQ.js} +150 -1
- package/dist/chunk-6W5KW7XQ.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -1
- package/dist/testing.d.ts +87 -0
- package/dist/testing.js +93 -0
- package/dist/testing.js.map +1 -0
- package/dist/values.d.ts +128 -5
- package/dist/values.js +13 -1
- package/package.json +5 -1
- package/dist/chunk-LCTGXGOI.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
Versions are calendar versions, `YY.M.R` (year, month of the release, counter
|
|
4
4
|
within the month), the same scheme as `@n-uf/hypr-tiling`.
|
|
5
5
|
|
|
6
|
+
## 26.11.3
|
|
7
|
+
|
|
8
|
+
- New in `values/`: the window motion rules, the one motion model for
|
|
9
|
+
hypr-tiling and pdf-n-uf's surface.
|
|
10
|
+
- `createSettle(initial, { omega?, restDelta? })` and `settleValue(loop, …)`:
|
|
11
|
+
the curve for moving to a new place. A critically damped spring whose
|
|
12
|
+
velocity is set on every new target to `omega · distance` toward it, so it
|
|
13
|
+
follows `distance · e^(−omega·t)` from wherever it is drawn: front-loaded
|
|
14
|
+
(90 % in `ln(10)/omega` s), and it never passes its target, on position
|
|
15
|
+
or size, however often it is retargeted. A velocity set by hand toward
|
|
16
|
+
the target is capped at that speed; one away from it is kept. Tempos in
|
|
17
|
+
`SETTLE_TEMPO` (`calm` 20, `default` 25, `quick` 37 per second).
|
|
18
|
+
- `settle.hold(value)`: what a pointer owns sits exactly under it, at rest;
|
|
19
|
+
the next target launches from there.
|
|
20
|
+
- `reveal(drawn, target)`: draw a gliding window without stretching its
|
|
21
|
+
content (move, frame at the drawn size, clip the content laid out at the
|
|
22
|
+
target size). `popIn(progress, from = 0.87)`: uniform open and close.
|
|
23
|
+
- New entry `@n-uf/motion/testing`: frame-sampled checks of those rules
|
|
24
|
+
(`checkNoOvershoot`, `checkMonotonic`, `checkNoJumps`, `checkHeld`,
|
|
25
|
+
`checkContentScale`, `checkTempo`), each returning `{ ok, failures }`.
|
|
26
|
+
- Nothing existing changes behaviour.
|
|
27
|
+
|
|
6
28
|
## 26.11.2
|
|
7
29
|
|
|
8
30
|
- A two-finger pan is no longer taken for a pinch. One finger's event arrives
|
package/README.md
CHANGED
|
@@ -21,15 +21,19 @@ npm i @n-uf/motion
|
|
|
21
21
|
recomputes only what depends on it, and effects can run once per frame.
|
|
22
22
|
- **values/**: springs and tweens over numbers, points, rects and vectors,
|
|
23
23
|
stepped by the clock, with velocity that carries over a retarget, settle
|
|
24
|
-
detection and a reduced-motion switch
|
|
24
|
+
detection and a reduced-motion switch; and the window motion rules:
|
|
25
|
+
`settle` (one fast-then-gentle curve that never passes its target), hold
|
|
26
|
+
(what a pointer owns sits exactly under it) and `reveal` (glide a window
|
|
27
|
+
without stretching its content).
|
|
25
28
|
- **gestures/**: a recogniser that turns pointer, wheel and trackpad events
|
|
26
29
|
(plain objects) into one gesture stream (click or drag, double click, long
|
|
27
30
|
press, pinch, scroll, zoom, recovery from lost releases), a frame coalescer,
|
|
28
31
|
and a dwell (spring-load) machine.
|
|
29
32
|
|
|
30
|
-
One package,
|
|
33
|
+
One package, seven entries: `@n-uf/motion` (everything in the core), its four
|
|
31
34
|
folders on their own (`@n-uf/motion/clock`, `/signals`, `/values`,
|
|
32
|
-
`/gestures`),
|
|
35
|
+
`/gestures`), `@n-uf/motion/testing` (frame-sampled checks of the motion
|
|
36
|
+
rules, for tests and browser specs), and `@n-uf/motion/browser`, the clock on
|
|
33
37
|
`requestAnimationFrame` and the reduced-motion media query. The core entries
|
|
34
38
|
touch no host; importing several of them still gives one signal graph.
|
|
35
39
|
|
|
@@ -155,6 +159,54 @@ rect.set({ x: 300, y: 40, width: 240, height: 100 });
|
|
|
155
159
|
clock.runUntilIdle(); // settled at { x: 300, y: 40, width: 240, height: 100 }
|
|
156
160
|
```
|
|
157
161
|
|
|
162
|
+
### Window motion: settle, hold, reveal
|
|
163
|
+
|
|
164
|
+
Three rules make windows move the way a tiling window manager feels smooth
|
|
165
|
+
(Hyprland is the reference): what the pointer holds is glued to it, everything
|
|
166
|
+
else moves on one front-loaded curve that never passes its target, and content
|
|
167
|
+
is never stretched.
|
|
168
|
+
|
|
169
|
+
| | |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `createSettle(initial, { omega?, restDelta? })` | The one curve for moving to a new place. On a new target every component gets the velocity `omega · distance` toward it from wherever it is drawn, so it follows `distance · e^(−omega·t)`: 90 % in `ln(10)/omega` s, then it eases in, and never passes the target (no overshoot on position, no wobble on size), however often it is retargeted. A velocity set by hand toward the target is capped at that speed; one away from it is kept, and the value turns around without crossing. |
|
|
172
|
+
| `SETTLE_TEMPO` | `{ calm: 20, default: 25, quick: 37 }` (1/s): 90 % in 115, 92 or 62 ms. |
|
|
173
|
+
| `settle.hold(value)` | Hold: put the value exactly there, at rest (same as `jumpTo`). Call it on each pointer move; the next `setTarget` launches from there. |
|
|
174
|
+
| `settleValue(loop, initial, { omega?, restDelta?, phase?, reducedMotion? })` | The settle on a frame loop. Hold it with `mv.jump(rect)`. |
|
|
175
|
+
| `reveal(drawn, target)` | How to draw a window gliding at `drawn` whose content is laid out at `target`: move the element by `dx, dy`, draw the frame (chrome) at `width × height`, clip the content by `clipRight, clipBottom`. No scale, no layout per frame. |
|
|
176
|
+
| `popIn(progress, from = 0.87)` | Opening and closing: a uniform scale about the centre plus opacity. Drive `progress` with a settle on a number with `{ restDelta: 0.001 }` (the default 0.1 is for pixels) or a tween. |
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import { createFakeClock, createFrameLoop, settleValue } from "@n-uf/motion";
|
|
180
|
+
|
|
181
|
+
const clock = createFakeClock();
|
|
182
|
+
const loop = createFrameLoop({ clock });
|
|
183
|
+
const win = settleValue(loop, { x: 0, y: 0, width: 400, height: 300 });
|
|
184
|
+
win.set({ x: 400, y: 0, width: 200, height: 300 }); // a reflow: position and size arrive together
|
|
185
|
+
clock.frame();
|
|
186
|
+
win.set({ x: 300, y: 0, width: 300, height: 300 }); // retargeted mid-flight: on from where it is drawn
|
|
187
|
+
clock.runUntilIdle();
|
|
188
|
+
console.log(win.value); // { x: 300, y: 0, width: 300, height: 300 }, never past it on the way
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## testing/
|
|
192
|
+
|
|
193
|
+
`@n-uf/motion/testing` checks recorded frames against the rules. Record what
|
|
194
|
+
was drawn each frame (on the fake clock, or in a browser spec once per
|
|
195
|
+
animation frame) and ask:
|
|
196
|
+
|
|
197
|
+
| | |
|
|
198
|
+
|---|---|
|
|
199
|
+
| `checkNoOvershoot(samples, from, to, tolerance?)` | Every component stays between its start and end: no overshoot, no size wobble. |
|
|
200
|
+
| `checkMonotonic(samples, to, tolerance?)` | The distance to the target never grows: no bounce, no restart backwards. |
|
|
201
|
+
| `checkNoJumps(samples, omega, slack?)` | No frame moves further than a settle at `omega` could: catches snaps and restarts from an old place. Sample times are the stepped time (the loop's `delta`s), not wall-clock timestamps. |
|
|
202
|
+
| `checkHeld(samples, tolerance?)` | A held rect is where the pointer puts it, every frame. |
|
|
203
|
+
| `checkContentScale(samples, { uniformOnly?, tolerance? })` | Content's transform is never non-uniform (stretched); with `uniformOnly: false`, never scaled at all. |
|
|
204
|
+
| `checkTempo(samples, from, to, t90, tolerance?, startT?)` | 90 % of the way within `t90` ms of `startT` (default: the first sample, so record the frame the move began); returns the measured time too. |
|
|
205
|
+
|
|
206
|
+
Each returns `{ ok, failures }`, a failure naming the frame and component.
|
|
207
|
+
The motion lab in the [n-uf/motion repository](https://github.com/n-uf/motion)
|
|
208
|
+
(`apps/lab`) runs them on every move.
|
|
209
|
+
|
|
158
210
|
## gestures/
|
|
159
211
|
|
|
160
212
|
| | |
|
|
@@ -202,7 +254,7 @@ their own.
|
|
|
202
254
|
|
|
203
255
|
Everything runs on `createFakeClock()`: frames, timers, springs and machine
|
|
204
256
|
deadlines move only when the test moves the clock, so motion is exact and
|
|
205
|
-
repeatable.
|
|
257
|
+
repeatable. `@n-uf/motion/testing` (above) checks the frames you record.
|
|
206
258
|
|
|
207
259
|
## Benchmarks
|
|
208
260
|
|
|
@@ -393,6 +393,146 @@ function createTween(initial, config = {}) {
|
|
|
393
393
|
return new TweenAnimator(initial, config);
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
// src/values/settle.ts
|
|
397
|
+
var SETTLE_TEMPO = { calm: 20, default: 25, quick: 37 };
|
|
398
|
+
var SETTLE_DEFAULTS = { omega: SETTLE_TEMPO.default, restDelta: 0.1 };
|
|
399
|
+
function positive2(name, value) {
|
|
400
|
+
if (!(value > 0) || !Number.isFinite(value)) throw new RangeError(`settle: ${name} must be a finite number > 0, got ${value}`);
|
|
401
|
+
return value;
|
|
402
|
+
}
|
|
403
|
+
var SettleAnimator = class {
|
|
404
|
+
layout;
|
|
405
|
+
x;
|
|
406
|
+
v;
|
|
407
|
+
goal;
|
|
408
|
+
omega;
|
|
409
|
+
restDelta;
|
|
410
|
+
settled = true;
|
|
411
|
+
cachedValue = null;
|
|
412
|
+
constructor(initial, config) {
|
|
413
|
+
this.layout = layoutOf(initial);
|
|
414
|
+
this.x = new Float64Array(this.layout.size);
|
|
415
|
+
this.v = new Float64Array(this.layout.size);
|
|
416
|
+
this.goal = new Float64Array(this.layout.size);
|
|
417
|
+
writeComponents(initial, this.x);
|
|
418
|
+
writeComponents(initial, this.goal);
|
|
419
|
+
this.omega = positive2("omega", config.omega ?? SETTLE_DEFAULTS.omega);
|
|
420
|
+
this.restDelta = positive2("restDelta", config.restDelta ?? SETTLE_DEFAULTS.restDelta);
|
|
421
|
+
}
|
|
422
|
+
get value() {
|
|
423
|
+
if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);
|
|
424
|
+
return this.cachedValue;
|
|
425
|
+
}
|
|
426
|
+
get velocity() {
|
|
427
|
+
return makeValue(this.layout, this.v);
|
|
428
|
+
}
|
|
429
|
+
get target() {
|
|
430
|
+
return makeValue(this.layout, this.goal);
|
|
431
|
+
}
|
|
432
|
+
check(value, what) {
|
|
433
|
+
if (!sameLayout(layoutOf(value), this.layout)) {
|
|
434
|
+
throw new TypeError(`settle: ${what} has a different shape than the settle's value`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/** The launch/clamp/carry rule on component `i`: `launch` for a new target, else clamp or carry. */
|
|
438
|
+
rule(i, launch) {
|
|
439
|
+
const d = this.x[i] - this.goal[i];
|
|
440
|
+
const v = this.v[i];
|
|
441
|
+
const limit = d === 0 ? 0 : -this.omega * d;
|
|
442
|
+
if (launch) {
|
|
443
|
+
this.v[i] = limit;
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (d === 0) return;
|
|
447
|
+
if (d * v > 0) return;
|
|
448
|
+
if (Math.abs(v) > Math.abs(limit)) this.v[i] = limit;
|
|
449
|
+
}
|
|
450
|
+
updateSettled() {
|
|
451
|
+
for (let i = 0; i < this.x.length; i++) {
|
|
452
|
+
if (this.x[i] !== this.goal[i] || this.v[i] !== 0) {
|
|
453
|
+
this.settled = false;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
this.settled = true;
|
|
458
|
+
}
|
|
459
|
+
setTarget(target) {
|
|
460
|
+
this.check(target, "the target");
|
|
461
|
+
writeComponents(target, this.goal);
|
|
462
|
+
for (let i = 0; i < this.x.length; i++) this.rule(i, true);
|
|
463
|
+
this.updateSettled();
|
|
464
|
+
}
|
|
465
|
+
setVelocity(velocity) {
|
|
466
|
+
this.check(velocity, "the velocity");
|
|
467
|
+
writeComponents(velocity, this.v);
|
|
468
|
+
for (let i = 0; i < this.x.length; i++) this.rule(i, false);
|
|
469
|
+
this.updateSettled();
|
|
470
|
+
}
|
|
471
|
+
jumpTo(value) {
|
|
472
|
+
this.check(value, "the value");
|
|
473
|
+
writeComponents(value, this.x);
|
|
474
|
+
writeComponents(value, this.goal);
|
|
475
|
+
this.v.fill(0);
|
|
476
|
+
this.cachedValue = null;
|
|
477
|
+
this.settled = true;
|
|
478
|
+
}
|
|
479
|
+
hold(value) {
|
|
480
|
+
this.jumpTo(value);
|
|
481
|
+
}
|
|
482
|
+
snap() {
|
|
483
|
+
this.x.set(this.goal);
|
|
484
|
+
this.v.fill(0);
|
|
485
|
+
this.cachedValue = null;
|
|
486
|
+
this.settled = true;
|
|
487
|
+
}
|
|
488
|
+
configure(config) {
|
|
489
|
+
if (config.omega !== void 0) this.omega = positive2("omega", config.omega);
|
|
490
|
+
if (config.restDelta !== void 0) this.restDelta = positive2("restDelta", config.restDelta);
|
|
491
|
+
for (let i = 0; i < this.x.length; i++) this.rule(i, false);
|
|
492
|
+
}
|
|
493
|
+
step(dtMs) {
|
|
494
|
+
if (this.settled) return false;
|
|
495
|
+
if (!(dtMs > 0)) return true;
|
|
496
|
+
const w = this.omega;
|
|
497
|
+
const t = dtMs / 1e3;
|
|
498
|
+
const e = Math.exp(-w * t);
|
|
499
|
+
const { x, v, goal, restDelta } = this;
|
|
500
|
+
const restSpeed = w * restDelta * 1.000001;
|
|
501
|
+
let resting = true;
|
|
502
|
+
for (let i = 0; i < x.length; i++) {
|
|
503
|
+
const d = x[i] - goal[i];
|
|
504
|
+
const b = v[i] + w * d;
|
|
505
|
+
const nd = e * (d + b * t);
|
|
506
|
+
v[i] = e * (v[i] - w * b * t);
|
|
507
|
+
x[i] = goal[i] + nd;
|
|
508
|
+
const near = Math.max(restDelta, 4 * Number.EPSILON * Math.abs(goal[i]));
|
|
509
|
+
if (resting && (Math.abs(nd) > near || Math.abs(v[i]) > Math.max(restSpeed, w * near))) resting = false;
|
|
510
|
+
}
|
|
511
|
+
this.cachedValue = null;
|
|
512
|
+
if (resting) this.snap();
|
|
513
|
+
return !this.settled;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
function createSettle(initial, config = {}) {
|
|
517
|
+
return new SettleAnimator(initial, config);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// src/values/reveal.ts
|
|
521
|
+
function reveal(drawn, target) {
|
|
522
|
+
return {
|
|
523
|
+
dx: drawn.x - target.x,
|
|
524
|
+
dy: drawn.y - target.y,
|
|
525
|
+
width: Math.max(0, drawn.width),
|
|
526
|
+
height: Math.max(0, drawn.height),
|
|
527
|
+
clipRight: Math.max(0, target.width - drawn.width),
|
|
528
|
+
clipBottom: Math.max(0, target.height - drawn.height)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function popIn(progress, from = 0.87) {
|
|
532
|
+
const p = Math.min(1, Math.max(0, progress));
|
|
533
|
+
return { scale: from + (1 - from) * p, opacity: p };
|
|
534
|
+
}
|
|
535
|
+
|
|
396
536
|
// src/values/motion-value.ts
|
|
397
537
|
var Motion = class {
|
|
398
538
|
loop;
|
|
@@ -530,6 +670,9 @@ function motionValue(loop, animator, options = {}) {
|
|
|
530
670
|
function springValue(loop, initial, options = {}) {
|
|
531
671
|
return motionValue(loop, createSpring(initial, options), options);
|
|
532
672
|
}
|
|
673
|
+
function settleValue(loop, initial, options = {}) {
|
|
674
|
+
return motionValue(loop, createSettle(initial, options), options);
|
|
675
|
+
}
|
|
533
676
|
function tweenValue(loop, initial, options = {}) {
|
|
534
677
|
return motionValue(loop, createTween(initial, options), options);
|
|
535
678
|
}
|
|
@@ -549,8 +692,14 @@ export {
|
|
|
549
692
|
springStep,
|
|
550
693
|
createSpring,
|
|
551
694
|
createTween,
|
|
695
|
+
SETTLE_TEMPO,
|
|
696
|
+
SETTLE_DEFAULTS,
|
|
697
|
+
createSettle,
|
|
698
|
+
reveal,
|
|
699
|
+
popIn,
|
|
552
700
|
motionValue,
|
|
553
701
|
springValue,
|
|
702
|
+
settleValue,
|
|
554
703
|
tweenValue
|
|
555
704
|
};
|
|
556
|
-
//# sourceMappingURL=chunk-
|
|
705
|
+
//# sourceMappingURL=chunk-6W5KW7XQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/values/easing.ts","../src/shapes.ts","../src/values/spring.ts","../src/values/tween.ts","../src/values/settle.ts","../src/values/reveal.ts","../src/values/motion-value.ts"],"sourcesContent":["/** Maps progress in [0, 1] to eased progress (0 at 0, 1 at 1). */\nexport type Easing = (progress: number) => number;\n\n/** No easing. */\nexport const linear: Easing = (t) => t;\n\nconst EPSILON = 1e-7;\n\n/**\n * The CSS `cubic-bezier(x1, y1, x2, y2)` curve as a function, solved\n * numerically (Newton steps, then bisection). `x1` and `x2` must be in [0, 1].\n */\nexport function cubicBezier(x1: number, y1: number, x2: number, y2: number): Easing {\n if (!(x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1)) {\n throw new RangeError(`cubicBezier: x1 and x2 must be in [0, 1], got ${x1} and ${x2}`);\n }\n if (x1 === y1 && x2 === y2) return linear;\n const cx = 3 * x1;\n const bx = 3 * (x2 - x1) - cx;\n const ax = 1 - cx - bx;\n const cy = 3 * y1;\n const by = 3 * (y2 - y1) - cy;\n const ay = 1 - cy - by;\n const sampleX = (t: number): number => ((ax * t + bx) * t + cx) * t;\n const sampleY = (t: number): number => ((ay * t + by) * t + cy) * t;\n const slopeX = (t: number): number => (3 * ax * t + 2 * bx) * t + cx;\n const solveX = (x: number): number => {\n let t = x;\n for (let i = 0; i < 8; i++) {\n const error = sampleX(t) - x;\n if (Math.abs(error) < EPSILON) return t;\n const slope = slopeX(t);\n if (Math.abs(slope) < 1e-6) break;\n t -= error / slope;\n }\n let low = 0;\n let high = 1;\n t = x;\n for (let i = 0; i < 40; i++) {\n const value = sampleX(t);\n if (Math.abs(value - x) < EPSILON) return t;\n if (x > value) low = t;\n else high = t;\n t = (low + high) / 2;\n }\n return t;\n };\n return (progress) => (progress <= 0 ? 0 : progress >= 1 ? 1 : sampleY(solveX(progress)));\n}\n\n/** CSS `ease`. */\nexport const ease: Easing = /* @__PURE__ */ cubicBezier(0.25, 0.1, 0.25, 1);\n/** CSS `ease-in`. */\nexport const easeIn: Easing = /* @__PURE__ */ cubicBezier(0.42, 0, 1, 1);\n/** CSS `ease-out`. */\nexport const easeOut: Easing = /* @__PURE__ */ cubicBezier(0, 0, 0.58, 1);\n/** CSS `ease-in-out`. */\nexport const easeInOut: Easing = /* @__PURE__ */ cubicBezier(0.42, 0, 0.58, 1);\n/** Cubic ease-out: fast start, gentle stop. The tween default. */\nexport const easeOutCubic: Easing = (t) => 1 - (1 - t) ** 3;\n/** Cubic ease-in-out. */\nexport const easeInOutCubic: Easing = (t) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2);\n","/** A point or a 2D vector. */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** An axis-aligned rectangle. */\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Any number of components. */\nexport type Vector = readonly number[];\n\n/** The value shapes springs and tweens move: plain numbers, nothing else. */\nexport type Animatable = number | Point | Rect | Vector;\n\n/** The shape type of an {@link Animatable}: literal numbers widen to `number`. */\nexport type Widen<T> = T extends number\n ? number\n : T extends Vector\n ? Vector\n : T extends Rect\n ? Rect\n : T extends Point\n ? Point\n : never;\n\nconst SCALAR = 0;\nconst VECTOR = 1;\nconst POINT = 2;\nconst RECT = 3;\n\n/** How a shape maps onto a flat list of numbers. Internal to values/. */\nexport interface Layout {\n readonly kind: typeof SCALAR | typeof VECTOR | typeof POINT | typeof RECT;\n readonly size: number;\n}\n\nconst SCALAR_LAYOUT: Layout = { kind: SCALAR, size: 1 };\nconst POINT_LAYOUT: Layout = { kind: POINT, size: 2 };\nconst RECT_LAYOUT: Layout = { kind: RECT, size: 4 };\n\nexport function layoutOf(value: Animatable): Layout {\n if (typeof value === \"number\") return SCALAR_LAYOUT;\n if (Array.isArray(value)) return { kind: VECTOR, size: value.length };\n if (\"width\" in value) return RECT_LAYOUT;\n return POINT_LAYOUT;\n}\n\nexport function sameLayout(a: Layout, b: Layout): boolean {\n return a.kind === b.kind && a.size === b.size;\n}\n\n/** Copy `value`'s components into `out`. */\nexport function writeComponents(value: Animatable, out: Float64Array): void {\n if (typeof value === \"number\") {\n out[0] = value;\n } else if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) out[i] = value[i]!;\n } else if (\"width\" in value) {\n out[0] = value.x;\n out[1] = value.y;\n out[2] = value.width;\n out[3] = value.height;\n } else {\n const point = value as Point;\n out[0] = point.x;\n out[1] = point.y;\n }\n}\n\n/** A fresh value of `layout`'s shape from `components`. */\nexport function makeValue(layout: Layout, components: Float64Array): Animatable {\n switch (layout.kind) {\n case SCALAR:\n return components[0]!;\n case POINT:\n return { x: components[0]!, y: components[1]! };\n case RECT:\n return { x: components[0]!, y: components[1]!, width: components[2]!, height: components[3]! };\n default:\n return Array.from(components);\n }\n}\n\n/** Component-wise equality of two values of the same shape. */\nexport function shapeEquals(a: Animatable, b: Animatable): boolean {\n if (typeof a === \"number\" || typeof b === \"number\") return a === b;\n if (Array.isArray(a) || Array.isArray(b)) {\n const u = a as Vector;\n const v = b as Vector;\n if (u.length !== v.length) return false;\n for (let i = 0; i < u.length; i++) if (u[i] !== v[i]) return false;\n return true;\n }\n const p = a as Partial<Rect>;\n const q = b as Partial<Rect>;\n return p.x === q.x && p.y === q.y && p.width === q.width && p.height === q.height;\n}\n","import type { Animatable, Layout, Widen } from \"../shapes\";\nimport { layoutOf, makeValue, sameLayout, writeComponents } from \"../shapes\";\nimport type { Animator } from \"./animator\";\n\n/**\n * Spring settings. Time is in milliseconds everywhere in the API; the physics\n * runs in seconds, so velocity is in units per second.\n */\nexport interface SpringConfig {\n /** Spring constant k. Higher is snappier. Default 300. */\n readonly stiffness?: number;\n /** Damping coefficient c. When set it wins over `dampingRatio`. */\n readonly damping?: number;\n /**\n * Damping as a fraction of critical damping: 1 is critical (the fastest\n * approach with no overshoot), below 1 overshoots and rings, above 1 is\n * sluggish. Default 1.\n */\n readonly dampingRatio?: number;\n /** Mass m. Default 1. */\n readonly mass?: number;\n /** Distance from the target that counts as arrived. Default 0.1 (tuned for pixels). */\n readonly restDelta?: number;\n /** Speed, in units per second, that counts as stopped. Default 1 (tuned for pixels). */\n readonly restSpeed?: number;\n}\n\n/** A {@link SpringConfig} with every field resolved. */\nexport interface SpringParams {\n readonly stiffness: number;\n readonly damping: number;\n readonly dampingRatio: number;\n readonly mass: number;\n readonly restDelta: number;\n readonly restSpeed: number;\n}\n\n/** Defaults of {@link SpringConfig}: critically damped. */\nexport const SPRING_DEFAULTS: SpringParams = {\n stiffness: 300,\n damping: 2 * Math.sqrt(300),\n dampingRatio: 1,\n mass: 1,\n restDelta: 0.1,\n restSpeed: 1,\n};\n\nfunction positive(name: string, value: number): number {\n if (!(value > 0) || !Number.isFinite(value)) throw new RangeError(`spring: ${name} must be a finite number > 0, got ${value}`);\n return value;\n}\n\n/** Resolve a {@link SpringConfig} over the defaults. Throws on a non-positive field. */\nexport function resolveSpring(config: SpringConfig = {}): SpringParams {\n const stiffness = positive(\"stiffness\", config.stiffness ?? SPRING_DEFAULTS.stiffness);\n const mass = positive(\"mass\", config.mass ?? SPRING_DEFAULTS.mass);\n const critical = 2 * Math.sqrt(stiffness * mass);\n const damping = positive(\n config.damping !== undefined ? \"damping\" : \"dampingRatio\",\n config.damping ?? (config.dampingRatio ?? SPRING_DEFAULTS.dampingRatio) * critical,\n );\n return {\n stiffness,\n damping,\n dampingRatio: damping / critical,\n mass,\n restDelta: positive(\"restDelta\", config.restDelta ?? SPRING_DEFAULTS.restDelta),\n restSpeed: positive(\"restSpeed\", config.restSpeed ?? SPRING_DEFAULTS.restSpeed),\n };\n}\n\nconst UNDERDAMPED = 0;\nconst CRITICAL = 1;\nconst OVERDAMPED = 2;\n\n/** The closed-form solution's constants for one set of params. */\ninterface Solver {\n readonly mode: typeof UNDERDAMPED | typeof CRITICAL | typeof OVERDAMPED;\n readonly omega: number;\n readonly decay: number;\n readonly omegaD: number;\n readonly r1: number;\n readonly r2: number;\n}\n\nfunction solverFor(params: SpringParams): Solver {\n const omega = Math.sqrt(params.stiffness / params.mass);\n const zeta = params.dampingRatio;\n if (Math.abs(zeta - 1) < 1e-6) return { mode: CRITICAL, omega, decay: omega, omegaD: 0, r1: 0, r2: 0 };\n if (zeta < 1) {\n return { mode: UNDERDAMPED, omega, decay: zeta * omega, omegaD: omega * Math.sqrt(1 - zeta * zeta), r1: 0, r2: 0 };\n }\n const root = Math.sqrt(zeta * zeta - 1);\n return { mode: OVERDAMPED, omega, decay: 0, omegaD: 0, r1: -omega * (zeta - root), r2: -omega * (zeta + root) };\n}\n\n/**\n * Advance one component exactly: displacement `d0` from the target and\n * velocity `v0` (per second) after `t` seconds. Writes into out[0], out[1].\n * Exact for any `t`, so the curve doesn't depend on the frame rate.\n */\nfunction advance(solver: Solver, d0: number, v0: number, t: number, out: Float64Array): void {\n if (solver.mode === CRITICAL) {\n const w = solver.omega;\n const e = Math.exp(-w * t);\n const b = v0 + w * d0;\n out[0] = e * (d0 + b * t);\n out[1] = e * (v0 - w * b * t);\n } else if (solver.mode === UNDERDAMPED) {\n const a = solver.decay;\n const wd = solver.omegaD;\n const e = Math.exp(-a * t);\n const cos = Math.cos(wd * t);\n const sin = Math.sin(wd * t);\n out[0] = e * (d0 * cos + ((v0 + a * d0) / wd) * sin);\n out[1] = e * (v0 * cos - ((a * v0 + solver.omega * solver.omega * d0) / wd) * sin);\n } else {\n const { r1, r2 } = solver;\n const c2 = (v0 - r1 * d0) / (r2 - r1);\n const c1 = d0 - c2;\n const e1 = Math.exp(r1 * t);\n const e2 = Math.exp(r2 * t);\n out[0] = c1 * e1 + c2 * e2;\n out[1] = c1 * r1 * e1 + c2 * r2 * e2;\n }\n}\n\n/** A scalar spring's position and velocity (units per second). */\nexport interface SpringState {\n readonly value: number;\n readonly velocity: number;\n}\n\n/**\n * One pure spring step for a scalar: where `state` is after `dtMs` heading for\n * `target`. Doesn't settle or snap; {@link createSpring} does that.\n */\nexport function springStep(state: SpringState, target: number, params: SpringParams, dtMs: number): SpringState {\n const out = new Float64Array(2);\n advance(solverFor(params), state.value - target, state.velocity, dtMs / 1000, out);\n return { value: target + out[0]!, velocity: out[1]! };\n}\n\n/** A spring over any {@link Animatable} shape, stepped by hand or by `motionValue`. */\nexport interface Spring<T> extends Animator<T> {\n /** The resolved settings. */\n readonly params: SpringParams;\n /** Set the velocity in units per second (a gesture's release velocity). */\n setVelocity(velocity: T): void;\n /** Change settings mid-flight; position and velocity carry on. */\n configure(config: SpringConfig): void;\n}\n\nclass SpringAnimator implements Spring<Animatable> {\n readonly layout: Layout;\n readonly x: Float64Array;\n readonly v: Float64Array;\n readonly goal: Float64Array;\n readonly scratch = new Float64Array(2);\n config: SpringConfig;\n params: SpringParams;\n solver: Solver;\n settled = true;\n cachedValue: Animatable | null = null;\n\n constructor(initial: Animatable, config: SpringConfig) {\n this.layout = layoutOf(initial);\n const size = this.layout.size;\n this.x = new Float64Array(size);\n this.v = new Float64Array(size);\n this.goal = new Float64Array(size);\n writeComponents(initial, this.x);\n writeComponents(initial, this.goal);\n this.config = config;\n this.params = resolveSpring(config);\n this.solver = solverFor(this.params);\n }\n\n get value(): Animatable {\n if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);\n return this.cachedValue;\n }\n\n get velocity(): Animatable {\n return makeValue(this.layout, this.v);\n }\n\n get target(): Animatable {\n return makeValue(this.layout, this.goal);\n }\n\n check(value: Animatable, what: string): void {\n if (!sameLayout(layoutOf(value), this.layout)) {\n throw new TypeError(`spring: ${what} has a different shape than the spring's value`);\n }\n }\n\n /** At rest exactly when on the target and not moving. */\n updateSettled(): void {\n for (let i = 0; i < this.x.length; i++) {\n if (this.x[i] !== this.goal[i] || this.v[i] !== 0) {\n this.settled = false;\n return;\n }\n }\n this.settled = true;\n }\n\n setTarget(target: Animatable): void {\n this.check(target, \"the target\");\n writeComponents(target, this.goal);\n // Position and velocity stay as they are: a retarget carries the motion on.\n this.updateSettled();\n }\n\n setVelocity(velocity: Animatable): void {\n this.check(velocity, \"the velocity\");\n writeComponents(velocity, this.v);\n this.updateSettled();\n }\n\n jumpTo(value: Animatable): void {\n this.check(value, \"the value\");\n writeComponents(value, this.x);\n writeComponents(value, this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n snap(): void {\n this.x.set(this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n configure(config: SpringConfig): void {\n this.config = { ...this.config, ...config };\n this.params = resolveSpring(this.config);\n this.solver = solverFor(this.params);\n }\n\n step(dtMs: number): boolean {\n if (this.settled) return false;\n if (!(dtMs > 0)) return true;\n const t = dtMs / 1000;\n const { x, v, goal, scratch } = this;\n const { restDelta, restSpeed } = this.params;\n let resting = true;\n for (let i = 0; i < x.length; i++) {\n advance(this.solver, x[i]! - goal[i]!, v[i]!, t, scratch);\n x[i] = goal[i]! + scratch[0]!;\n v[i] = scratch[1]!;\n if (resting && (Math.abs(scratch[0]!) > restDelta || Math.abs(scratch[1]!) > restSpeed)) resting = false;\n }\n this.cachedValue = null;\n if (resting) this.snap();\n return !this.settled;\n }\n}\n\n/**\n * A spring starting at rest on `initial`. `initial` fixes the shape: a\n * number, a vector (array), a point `{ x, y }` or a rect `{ x, y, width,\n * height }`; targets and velocities must have the same shape.\n */\nexport function createSpring<T extends Animatable>(initial: T, config: SpringConfig = {}): Spring<Widen<T>> {\n return new SpringAnimator(initial, config) as unknown as Spring<Widen<T>>;\n}\n","import type { Animatable, Layout, Widen } from \"../shapes\";\nimport { layoutOf, makeValue, sameLayout, writeComponents } from \"../shapes\";\nimport type { Animator } from \"./animator\";\nimport { easeOutCubic, type Easing } from \"./easing\";\n\n/** Tween settings. */\nexport interface TweenConfig {\n /** Length of a run in ms. Default 250. 0 jumps to the target on the next step. */\n readonly duration?: number;\n /** Easing of the run. Default {@link easeOutCubic}. */\n readonly easing?: Easing;\n}\n\n/** A tween over any {@link Animatable} shape. */\nexport interface Tween<T> extends Animator<T> {\n /** Run progress in [0, 1]. */\n readonly progress: number;\n /** Change duration or easing; applies from the next target. */\n configure(config: TweenConfig): void;\n}\n\nclass TweenAnimator implements Tween<Animatable> {\n readonly layout: Layout;\n readonly x: Float64Array;\n readonly from: Float64Array;\n readonly goal: Float64Array;\n duration: number;\n easing: Easing;\n elapsed = 0;\n settled = true;\n cachedValue: Animatable | null = null;\n\n constructor(initial: Animatable, config: TweenConfig) {\n this.layout = layoutOf(initial);\n const size = this.layout.size;\n this.x = new Float64Array(size);\n this.from = new Float64Array(size);\n this.goal = new Float64Array(size);\n writeComponents(initial, this.x);\n writeComponents(initial, this.from);\n writeComponents(initial, this.goal);\n this.duration = 250;\n this.easing = easeOutCubic;\n this.configure(config);\n }\n\n get value(): Animatable {\n if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);\n return this.cachedValue;\n }\n\n get target(): Animatable {\n return makeValue(this.layout, this.goal);\n }\n\n get progress(): number {\n if (this.settled) return 1;\n return this.duration <= 0 ? 0 : Math.min(1, this.elapsed / this.duration);\n }\n\n /** The eased curve's slope at the current progress, as units per second. */\n get velocity(): Animatable {\n const out = new Float64Array(this.layout.size);\n if (!this.settled && this.duration > 0) {\n const p = this.progress;\n const h = 1e-3;\n const lo = Math.max(0, p - h);\n const hi = Math.min(1, p + h);\n const slope = (this.easing(hi) - this.easing(lo)) / (hi - lo);\n const perSecond = (slope / this.duration) * 1000;\n for (let i = 0; i < out.length; i++) out[i] = (this.goal[i]! - this.from[i]!) * perSecond;\n }\n return makeValue(this.layout, out);\n }\n\n configure(config: TweenConfig): void {\n if (config.duration !== undefined) {\n if (!(config.duration >= 0) || !Number.isFinite(config.duration)) {\n throw new RangeError(`tween: duration must be a finite number >= 0, got ${config.duration}`);\n }\n this.duration = config.duration;\n }\n if (config.easing !== undefined) this.easing = config.easing;\n }\n\n check(value: Animatable, what: string): void {\n if (!sameLayout(layoutOf(value), this.layout)) {\n throw new TypeError(`tween: ${what} has a different shape than the tween's value`);\n }\n }\n\n setTarget(target: Animatable): void {\n this.check(target, \"the target\");\n writeComponents(target, this.goal);\n // A new run starts from wherever the value is now (no jump).\n this.from.set(this.x);\n this.elapsed = 0;\n this.settled = true;\n for (let i = 0; i < this.x.length; i++) {\n if (this.x[i] !== this.goal[i]) {\n this.settled = false;\n break;\n }\n }\n }\n\n jumpTo(value: Animatable): void {\n this.check(value, \"the value\");\n writeComponents(value, this.x);\n writeComponents(value, this.from);\n writeComponents(value, this.goal);\n this.cachedValue = null;\n this.settled = true;\n }\n\n snap(): void {\n this.x.set(this.goal);\n this.from.set(this.goal);\n this.cachedValue = null;\n this.settled = true;\n }\n\n step(dtMs: number): boolean {\n if (this.settled) return false;\n this.elapsed += Math.max(0, dtMs);\n const p = this.duration <= 0 ? 1 : Math.min(1, this.elapsed / this.duration);\n if (p >= 1) {\n this.snap();\n return false;\n }\n const eased = this.easing(p);\n for (let i = 0; i < this.x.length; i++) {\n this.x[i] = this.from[i]! + (this.goal[i]! - this.from[i]!) * eased;\n }\n this.cachedValue = null;\n return true;\n }\n}\n\n/**\n * A tween starting at rest on `initial` (same shapes as `createSpring`).\n * Velocity doesn't carry over a retarget: a new target starts a new run from\n * the current value. Use a spring where motion must stay continuous.\n */\nexport function createTween<T extends Animatable>(initial: T, config: TweenConfig = {}): Tween<Widen<T>> {\n return new TweenAnimator(initial, config) as unknown as Tween<Widen<T>>;\n}\n","import type { Animatable, Layout, Widen } from \"../shapes\";\nimport { layoutOf, makeValue, sameLayout, writeComponents } from \"../shapes\";\nimport type { Animator } from \"./animator\";\n\n/**\n * Tempos for {@link createSettle}, in 1/s: a settle covers 90 % of the way in\n * ln(10)/omega seconds and is within 1 % in twice that.\n *\n * - `calm` 20: 90 % in 115 ms, done in 230 ms.\n * - `default` 25: 90 % in 92 ms, done in 184 ms.\n * - `quick` 37: 90 % in 62 ms, done in 124 ms (a fast Hyprland setup).\n */\nexport const SETTLE_TEMPO = { calm: 20, default: 25, quick: 37 } as const;\n\n/** Settings of {@link createSettle}. */\nexport interface SettleConfig {\n /** The tempo in 1/s (see {@link SETTLE_TEMPO}). Higher is faster. Default 25. */\n readonly omega?: number;\n /** Distance from the target that counts as arrived. Default 0.1 (tuned for pixels). */\n readonly restDelta?: number;\n}\n\n/**\n * The one curve for things that move to a new place: a window's rect between\n * layout targets, a drawer, a camera. Fast at the start, gentle at the end,\n * and it never passes its target.\n *\n * It is a critically damped spring (stiffness omega², damping 2·omega) with\n * one rule on its velocity, per component:\n *\n * - **Launch.** On a new target, each component gets the velocity\n * omega · distance toward it, from wherever it is drawn: standing still,\n * moving toward it, or moving away (it turns at once rather than drifting\n * further first). From there the spring follows `distance · e^(−omega·t)`\n * exactly: most of the move happens at once, the rest eases in.\n * - **Clamp.** That speed is also the most it may have toward the target, so a\n * velocity set by hand (`setVelocity`, a fling) toward the target is capped\n * there instead of shooting past.\n * - **Carry.** A velocity set by hand away from the target is kept, and the\n * value turns around; a critically damped spring turning around never\n * crosses the target either.\n *\n * So after a new target every component goes straight from where it is drawn\n * to the target and never past it: no overshoot on position, no wobble on\n * size, whatever the retargets. A new target starts from the drawn value,\n * never from the old start.\n *\n * Holding (a pointer owns the value): call `hold(value)` on each move. The\n * value sits exactly there, at rest; the next `setTarget` launches from it.\n */\nexport interface Settle<T> extends Animator<T> {\n /** The tempo in 1/s. */\n readonly omega: number;\n /** Put the value at `value`, at rest, with it as the target: a held value follows its owner 1:1. Same as `jumpTo`. */\n hold(value: T): void;\n /** Set the velocity (units per second); a component moving toward the target is clamped as in the launch rule. */\n setVelocity(velocity: T): void;\n /** Change the tempo or rest distance mid-flight; the value and velocity carry on, re-clamped. */\n configure(config: SettleConfig): void;\n}\n\n/** Defaults of {@link SettleConfig}. */\nexport const SETTLE_DEFAULTS = { omega: SETTLE_TEMPO.default, restDelta: 0.1 } as const;\n\nfunction positive(name: string, value: number): number {\n if (!(value > 0) || !Number.isFinite(value)) throw new RangeError(`settle: ${name} must be a finite number > 0, got ${value}`);\n return value;\n}\n\nclass SettleAnimator implements Settle<Animatable> {\n readonly layout: Layout;\n readonly x: Float64Array;\n readonly v: Float64Array;\n readonly goal: Float64Array;\n omega: number;\n restDelta: number;\n settled = true;\n cachedValue: Animatable | null = null;\n\n constructor(initial: Animatable, config: SettleConfig) {\n this.layout = layoutOf(initial);\n this.x = new Float64Array(this.layout.size);\n this.v = new Float64Array(this.layout.size);\n this.goal = new Float64Array(this.layout.size);\n writeComponents(initial, this.x);\n writeComponents(initial, this.goal);\n this.omega = positive(\"omega\", config.omega ?? SETTLE_DEFAULTS.omega);\n this.restDelta = positive(\"restDelta\", config.restDelta ?? SETTLE_DEFAULTS.restDelta);\n }\n\n get value(): Animatable {\n if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);\n return this.cachedValue;\n }\n\n get velocity(): Animatable {\n return makeValue(this.layout, this.v);\n }\n\n get target(): Animatable {\n return makeValue(this.layout, this.goal);\n }\n\n check(value: Animatable, what: string): void {\n if (!sameLayout(layoutOf(value), this.layout)) {\n throw new TypeError(`settle: ${what} has a different shape than the settle's value`);\n }\n }\n\n /** The launch/clamp/carry rule on component `i`: `launch` for a new target, else clamp or carry. */\n rule(i: number, launch: boolean): void {\n const d = this.x[i]! - this.goal[i]!;\n const v = this.v[i]!;\n const limit = d === 0 ? 0 : -this.omega * d;\n if (launch) {\n this.v[i] = limit;\n return;\n }\n if (d === 0) return;\n // Moving away from the target (d and v the same sign): carry.\n if (d * v > 0) return;\n // Moving toward it: no faster than a launch from here.\n if (Math.abs(v) > Math.abs(limit)) this.v[i] = limit;\n }\n\n updateSettled(): void {\n for (let i = 0; i < this.x.length; i++) {\n if (this.x[i] !== this.goal[i] || this.v[i] !== 0) {\n this.settled = false;\n return;\n }\n }\n this.settled = true;\n }\n\n setTarget(target: Animatable): void {\n this.check(target, \"the target\");\n writeComponents(target, this.goal);\n for (let i = 0; i < this.x.length; i++) this.rule(i, true);\n this.updateSettled();\n }\n\n setVelocity(velocity: Animatable): void {\n this.check(velocity, \"the velocity\");\n writeComponents(velocity, this.v);\n for (let i = 0; i < this.x.length; i++) this.rule(i, false);\n this.updateSettled();\n }\n\n jumpTo(value: Animatable): void {\n this.check(value, \"the value\");\n writeComponents(value, this.x);\n writeComponents(value, this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n hold(value: Animatable): void {\n this.jumpTo(value);\n }\n\n snap(): void {\n this.x.set(this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n configure(config: SettleConfig): void {\n if (config.omega !== undefined) this.omega = positive(\"omega\", config.omega);\n if (config.restDelta !== undefined) this.restDelta = positive(\"restDelta\", config.restDelta);\n for (let i = 0; i < this.x.length; i++) this.rule(i, false);\n }\n\n step(dtMs: number): boolean {\n if (this.settled) return false;\n if (!(dtMs > 0)) return true;\n const w = this.omega;\n const t = dtMs / 1000;\n const e = Math.exp(-w * t);\n const { x, v, goal, restDelta } = this;\n // At rest when every component is within restDelta and no faster than a launch from there would be.\n const restSpeed = w * restDelta * 1.000001;\n let resting = true;\n for (let i = 0; i < x.length; i++) {\n // The exact critically damped step: d(t) = e^(−wt)·(d + b·t), b = v + w·d.\n const d = x[i]! - goal[i]!;\n const b = v[i]! + w * d;\n const nd = e * (d + b * t);\n v[i] = e * (v[i]! - w * b * t);\n x[i] = goal[i]! + nd;\n // Within a few float steps of the goal counts as arrived too: a restDelta finer than that would never be met.\n const near = Math.max(restDelta, 4 * Number.EPSILON * Math.abs(goal[i]!));\n if (resting && (Math.abs(nd) > near || Math.abs(v[i]!) > Math.max(restSpeed, w * near))) resting = false;\n }\n this.cachedValue = null;\n if (resting) this.snap();\n return !this.settled;\n }\n}\n\n/**\n * A settle starting at rest on `initial` (a number, a vector, a point or a\n * rect; targets and velocities must have the same shape). See {@link Settle}.\n */\nexport function createSettle<T extends Animatable>(initial: T, config: SettleConfig = {}): Settle<Widen<T>> {\n return new SettleAnimator(initial, config) as unknown as Settle<Widen<T>>;\n}\n","import type { Rect } from \"../shapes\";\n\n/**\n * How to draw a window whose rect is gliding without stretching its content.\n *\n * The content is laid out once at the target size and never scaled. The\n * window's element sits at its target in the layout; to draw it at the\n * gliding rect:\n *\n * - move the element by (`dx`, `dy`), so its top-left corner is the drawn rect's;\n * - draw the frame (background, border, shadow) at `width` × `height`: the drawn size;\n * - clip the content by `clipRight` and `clipBottom` so it fits a frame\n * smaller than the target (CSS: `clip-path: inset(0 clipRight clipBottom 0)`).\n *\n * A window that shrinks shows a band of its own background closing in at the\n * right and bottom; one that grows reveals content already laid out at its\n * new size. Text is never stretched. One transform and one clip per frame, no\n * layout per frame.\n */\nexport interface RevealFrame {\n /** Move the element (laid out at the target) right by this much. */\n readonly dx: number;\n /** Move the element (laid out at the target) down by this much. */\n readonly dy: number;\n /** The frame's width: the drawn rect's. */\n readonly width: number;\n /** The frame's height: the drawn rect's. */\n readonly height: number;\n /** Clip this much off the content's right edge (0 when the frame is at least as wide as the target). */\n readonly clipRight: number;\n /** Clip this much off the content's bottom edge (0 when the frame is at least as tall as the target). */\n readonly clipBottom: number;\n}\n\n/** The {@link RevealFrame} for content laid out at `target` and drawn at `drawn`. */\nexport function reveal(drawn: Rect, target: Rect): RevealFrame {\n return {\n dx: drawn.x - target.x,\n dy: drawn.y - target.y,\n width: Math.max(0, drawn.width),\n height: Math.max(0, drawn.height),\n clipRight: Math.max(0, target.width - drawn.width),\n clipBottom: Math.max(0, target.height - drawn.height),\n };\n}\n\n/** A uniform pop-in (or pop-out, run backwards): scale about the centre and opacity. */\nexport interface PopIn {\n /** Scale about the window's centre: the same on both axes, so nothing is stretched. */\n readonly scale: number;\n readonly opacity: number;\n}\n\n/**\n * Opening and closing: the window grows from `from` of its size to full, about\n * its centre, while fading in. `progress` runs 0 to 1 (take it from a settle\n * on a number with `{ restDelta: 0.001 }`, since the default 0.1 is tuned for\n * pixels and would snap the last 10 %; or from a tween); closing runs it from\n * 1 to 0. Hyprland's default is `popin 87%`.\n */\nexport function popIn(progress: number, from = 0.87): PopIn {\n const p = Math.min(1, Math.max(0, progress));\n return { scale: from + (1 - from) * p, opacity: p };\n}\n","import type { FrameInfo, FrameLoop, Phase } from \"../clock/frame-loop\";\nimport type { Animatable, Widen } from \"../shapes\";\nimport { shapeEquals } from \"../shapes\";\nimport { batch, effect, signal, untracked, type ReadonlySignal, type Signal } from \"../signals/signals\";\nimport type { Animator } from \"./animator\";\nimport { createSettle, type Settle, type SettleConfig } from \"./settle\";\nimport { createSpring, type Spring, type SpringConfig } from \"./spring\";\nimport { createTween, type Tween, type TweenConfig } from \"./tween\";\n\n/** Options of {@link motionValue}. */\nexport interface MotionOptions {\n /**\n * The frame phase that steps the value. Default `\"layout\"`: it steps after\n * that phase's one-shot tasks, so a target set in input, update or layout\n * moves the value in the same frame, and `write` sees the new value.\n */\n readonly phase?: Phase;\n /**\n * The reduced-motion switch: while it is (or returns) `true`, every new\n * target is reached at once, and a value in flight snaps on its next frame.\n * A function is read on each `set` and each frame, so it can read a signal\n * or a media query.\n */\n readonly reducedMotion?: boolean | (() => boolean);\n}\n\n/** Options of {@link MotionValue.set}. */\nexport interface SetOptions<T> {\n /** Start with this velocity (units per second), e.g. a gesture's release velocity. Springs and settles (a settle caps it toward the target); tweens ignore it. */\n readonly velocity?: T;\n}\n\n/**\n * An animated value on a frame loop. Reading `value` inside a computed or an\n * effect tracks it; it changes once per frame while moving and the loop goes\n * idle when it settles.\n */\nexport interface MotionValue<T, A extends Animator<unknown> = Animator<T>> extends ReadonlySignal<T> {\n /** Where the value is heading. */\n readonly target: T;\n /** The current velocity, units per second. */\n readonly velocity: T;\n /** Whether it is moving (reactive). */\n readonly moving: boolean;\n /** The spring, settle or tween underneath. Change it through this value (`jump`, not the animator's `hold`), so the signal and the loop follow. */\n readonly animator: A;\n /** Head for `target`; a spring keeps its velocity, a settle launches from where it is drawn, a tween restarts. */\n set(target: T, options?: SetOptions<T>): void;\n /** Put the value at `value` at once, at rest. */\n jump(value: T): void;\n /** Finish now: put the value on its target, at rest. */\n snap(): void;\n /**\n * Keep heading for whatever `source` returns. `source` is tracked like an\n * effect, and re-read in this value's phase at most once per frame. Returns\n * a stop function.\n */\n follow(source: () => T): () => void;\n /**\n * Call `listener` each time the value comes to rest: on the frame it\n * settles, or at once when `set` (under reduced motion), `snap` or `jump`\n * leaves it at rest. Returns an unsubscribe function.\n */\n onSettle(listener: (value: T) => void): () => void;\n /** Stop stepping, drop listeners and follows. */\n dispose(): void;\n}\n\nclass Motion<T> implements MotionValue<T> {\n readonly loop: FrameLoop;\n readonly animator: Animator<T>;\n readonly phase: Phase;\n readonly reduced: () => boolean;\n readonly current: Signal<T>;\n readonly movingSignal: Signal<boolean>;\n readonly listeners = new Set<(value: T) => void>();\n readonly follows = new Set<() => void>();\n stop: (() => void) | null = null;\n disposed = false;\n\n constructor(loop: FrameLoop, animator: Animator<T>, options: MotionOptions) {\n this.loop = loop;\n this.animator = animator;\n this.phase = options.phase ?? \"layout\";\n const reducedMotion = options.reducedMotion ?? false;\n this.reduced = typeof reducedMotion === \"function\" ? reducedMotion : () => reducedMotion;\n this.current = signal(animator.value, {\n equals: shapeEquals as (a: T, b: T) => boolean,\n });\n this.movingSignal = signal(false);\n if (!animator.settled) this.start();\n }\n\n get value(): T {\n return this.current.value;\n }\n\n peek(): T {\n return this.current.peek();\n }\n\n get target(): T {\n return this.animator.target;\n }\n\n get velocity(): T {\n return this.animator.velocity;\n }\n\n get moving(): boolean {\n return this.movingSignal.value;\n }\n\n readonly tick = (frame: FrameInfo): boolean => {\n if (this.reduced()) this.animator.snap();\n else this.animator.step(frame.delta);\n if (!this.animator.settled) {\n this.current.value = this.animator.value;\n return true;\n }\n this.stop = null;\n this.rest();\n return false;\n };\n\n start(): void {\n if (this.stop !== null || this.disposed) return;\n this.stop = this.loop.repeat(this.phase, this.tick);\n this.movingSignal.value = true;\n }\n\n halt(): void {\n if (this.stop === null) return;\n this.stop();\n this.stop = null;\n }\n\n /** Publish the resting value and tell the listeners. */\n rest(): void {\n batch(() => {\n this.current.value = this.animator.value;\n this.movingSignal.value = false;\n });\n const value = this.animator.value;\n for (const listener of Array.from(this.listeners)) listener(value);\n }\n\n set(target: T, options?: SetOptions<T>): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.setTarget(target);\n if (options?.velocity !== undefined) this.animator.setVelocity?.(options.velocity);\n if (this.reduced()) this.animator.snap();\n if (this.animator.settled) {\n this.halt();\n this.rest();\n } else {\n this.start();\n }\n });\n }\n\n jump(value: T): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.jumpTo(value);\n this.halt();\n this.rest();\n });\n }\n\n snap(): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.snap();\n this.halt();\n this.rest();\n });\n }\n\n follow(source: () => T): () => void {\n if (this.disposed) return () => {};\n const dispose = effect(\n () => {\n const target = source();\n this.set(target);\n },\n { schedule: this.loop.scheduler(this.phase) },\n );\n const stop = (): void => {\n dispose();\n this.follows.delete(stop);\n };\n this.follows.add(stop);\n return stop;\n }\n\n onSettle(listener: (value: T) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.halt();\n for (const stop of Array.from(this.follows)) stop();\n this.listeners.clear();\n this.movingSignal.value = false;\n }\n}\n\n/** The value type an animator moves. */\nexport type AnimatorValue<A> = A extends Animator<infer T> ? T : never;\n\n/** Step `animator` on `loop` while it moves, and expose it as a signal. */\nexport function motionValue<A extends Animator<unknown>>(\n loop: FrameLoop,\n animator: A,\n options: MotionOptions = {},\n): MotionValue<AnimatorValue<A>, A> {\n return new Motion(loop, animator, options) as unknown as MotionValue<AnimatorValue<A>, A>;\n}\n\n/** A spring-driven {@link MotionValue}: `createSpring` plus `motionValue`. */\nexport function springValue<T extends Animatable>(\n loop: FrameLoop,\n initial: T,\n options: SpringConfig & MotionOptions = {},\n): MotionValue<Widen<T>, Spring<Widen<T>>> {\n return motionValue(loop, createSpring(initial, options), options) as MotionValue<Widen<T>, Spring<Widen<T>>>;\n}\n\n/**\n * A settle-driven {@link MotionValue}: `createSettle` plus `motionValue`. The\n * one curve for things moving to a new place (see {@link Settle}). To hold it\n * to a pointer, `jump` it on each move; the next `set` launches from there.\n */\nexport function settleValue<T extends Animatable>(\n loop: FrameLoop,\n initial: T,\n options: SettleConfig & MotionOptions = {},\n): MotionValue<Widen<T>, Settle<Widen<T>>> {\n return motionValue(loop, createSettle(initial, options), options) as MotionValue<Widen<T>, Settle<Widen<T>>>;\n}\n\n/** A tween-driven {@link MotionValue}: `createTween` plus `motionValue`. */\nexport function tweenValue<T extends Animatable>(\n loop: FrameLoop,\n initial: T,\n options: TweenConfig & MotionOptions = {},\n): MotionValue<Widen<T>, Tween<Widen<T>>> {\n return motionValue(loop, createTween(initial, options), options) as MotionValue<Widen<T>, Tween<Widen<T>>>;\n}\n"],"mappings":";;;;;;;;AAIO,IAAM,SAAiB,CAAC,MAAM;AAErC,IAAM,UAAU;AAMT,SAAS,YAAY,IAAY,IAAY,IAAY,IAAoB;AAClF,MAAI,EAAE,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,IAAI;AAC/C,UAAM,IAAI,WAAW,iDAAiD,EAAE,QAAQ,EAAE,EAAE;AAAA,EACtF;AACA,MAAI,OAAO,MAAM,OAAO,GAAI,QAAO;AACnC,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,KAAK,KAAK,MAAM;AAC3B,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,KAAK,KAAK,MAAM;AAC3B,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,UAAU,CAAC,QAAwB,KAAK,IAAI,MAAM,IAAI,MAAM;AAClE,QAAM,UAAU,CAAC,QAAwB,KAAK,IAAI,MAAM,IAAI,MAAM;AAClE,QAAM,SAAS,CAAC,OAAuB,IAAI,KAAK,IAAI,IAAI,MAAM,IAAI;AAClE,QAAM,SAAS,CAAC,MAAsB;AACpC,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,QAAQ,QAAQ,CAAC,IAAI;AAC3B,UAAI,KAAK,IAAI,KAAK,IAAI,QAAS,QAAO;AACtC,YAAM,QAAQ,OAAO,CAAC;AACtB,UAAI,KAAK,IAAI,KAAK,IAAI,KAAM;AAC5B,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,MAAM;AACV,QAAI,OAAO;AACX,QAAI;AACJ,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,KAAK,IAAI,QAAQ,CAAC,IAAI,QAAS,QAAO;AAC1C,UAAI,IAAI,MAAO,OAAM;AAAA,UAChB,QAAO;AACZ,WAAK,MAAM,QAAQ;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACA,SAAO,CAAC,aAAc,YAAY,IAAI,IAAI,YAAY,IAAI,IAAI,QAAQ,OAAO,QAAQ,CAAC;AACxF;AAGO,IAAM,OAA+B,4BAAY,MAAM,KAAK,MAAM,CAAC;AAEnE,IAAM,SAAiC,4BAAY,MAAM,GAAG,GAAG,CAAC;AAEhE,IAAM,UAAkC,4BAAY,GAAG,GAAG,MAAM,CAAC;AAEjE,IAAM,YAAoC,4BAAY,MAAM,GAAG,MAAM,CAAC;AAEtE,IAAM,eAAuB,CAAC,MAAM,KAAK,IAAI,MAAM;AAEnD,IAAM,iBAAyB,CAAC,MAAO,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI;;;AC9BhG,IAAM,SAAS;AACf,IAAM,SAAS;AACf,IAAM,QAAQ;AACd,IAAM,OAAO;AAQb,IAAM,gBAAwB,EAAE,MAAM,QAAQ,MAAM,EAAE;AACtD,IAAM,eAAuB,EAAE,MAAM,OAAO,MAAM,EAAE;AACpD,IAAM,cAAsB,EAAE,MAAM,MAAM,MAAM,EAAE;AAE3C,SAAS,SAAS,OAA2B;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,OAAO;AACpE,MAAI,WAAW,MAAO,QAAO;AAC7B,SAAO;AACT;AAEO,SAAS,WAAW,GAAW,GAAoB;AACxD,SAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;AAC3C;AAGO,SAAS,gBAAgB,OAAmB,KAAyB;AAC1E,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,IAAI;AAAA,EACX,WAAW,MAAM,QAAQ,KAAK,GAAG;AAC/B,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,KAAI,CAAC,IAAI,MAAM,CAAC;AAAA,EACzD,WAAW,WAAW,OAAO;AAC3B,QAAI,CAAC,IAAI,MAAM;AACf,QAAI,CAAC,IAAI,MAAM;AACf,QAAI,CAAC,IAAI,MAAM;AACf,QAAI,CAAC,IAAI,MAAM;AAAA,EACjB,OAAO;AACL,UAAM,QAAQ;AACd,QAAI,CAAC,IAAI,MAAM;AACf,QAAI,CAAC,IAAI,MAAM;AAAA,EACjB;AACF;AAGO,SAAS,UAAU,QAAgB,YAAsC;AAC9E,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,WAAW,CAAC;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,WAAW,CAAC,GAAI,GAAG,WAAW,CAAC,EAAG;AAAA,IAChD,KAAK;AACH,aAAO,EAAE,GAAG,WAAW,CAAC,GAAI,GAAG,WAAW,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,QAAQ,WAAW,CAAC,EAAG;AAAA,IAC/F;AACE,aAAO,MAAM,KAAK,UAAU;AAAA,EAChC;AACF;AAGO,SAAS,YAAY,GAAe,GAAwB;AACjE,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,MAAM;AACjE,MAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;AACxC,UAAM,IAAI;AACV,UAAM,IAAI;AACV,QAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAK,KAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAG,QAAO;AAC7D,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,QAAM,IAAI;AACV,SAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE;AAC7E;;;AChEO,IAAM,kBAAgC;AAAA,EAC3C,WAAW;AAAA,EACX,SAAS,IAAI,KAAK,KAAK,GAAG;AAAA,EAC1B,cAAc;AAAA,EACd,MAAM;AAAA,EACN,WAAW;AAAA,EACX,WAAW;AACb;AAEA,SAAS,SAAS,MAAc,OAAuB;AACrD,MAAI,EAAE,QAAQ,MAAM,CAAC,OAAO,SAAS,KAAK,EAAG,OAAM,IAAI,WAAW,WAAW,IAAI,qCAAqC,KAAK,EAAE;AAC7H,SAAO;AACT;AAGO,SAAS,cAAc,SAAuB,CAAC,GAAiB;AACrE,QAAM,YAAY,SAAS,aAAa,OAAO,aAAa,gBAAgB,SAAS;AACrF,QAAM,OAAO,SAAS,QAAQ,OAAO,QAAQ,gBAAgB,IAAI;AACjE,QAAM,WAAW,IAAI,KAAK,KAAK,YAAY,IAAI;AAC/C,QAAM,UAAU;AAAA,IACd,OAAO,YAAY,SAAY,YAAY;AAAA,IAC3C,OAAO,YAAY,OAAO,gBAAgB,gBAAgB,gBAAgB;AAAA,EAC5E;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAc,UAAU;AAAA,IACxB;AAAA,IACA,WAAW,SAAS,aAAa,OAAO,aAAa,gBAAgB,SAAS;AAAA,IAC9E,WAAW,SAAS,aAAa,OAAO,aAAa,gBAAgB,SAAS;AAAA,EAChF;AACF;AAEA,IAAM,cAAc;AACpB,IAAM,WAAW;AACjB,IAAM,aAAa;AAYnB,SAAS,UAAU,QAA8B;AAC/C,QAAM,QAAQ,KAAK,KAAK,OAAO,YAAY,OAAO,IAAI;AACtD,QAAM,OAAO,OAAO;AACpB,MAAI,KAAK,IAAI,OAAO,CAAC,IAAI,KAAM,QAAO,EAAE,MAAM,UAAU,OAAO,OAAO,OAAO,QAAQ,GAAG,IAAI,GAAG,IAAI,EAAE;AACrG,MAAI,OAAO,GAAG;AACZ,WAAO,EAAE,MAAM,aAAa,OAAO,OAAO,OAAO,OAAO,QAAQ,QAAQ,KAAK,KAAK,IAAI,OAAO,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AAAA,EACnH;AACA,QAAM,OAAO,KAAK,KAAK,OAAO,OAAO,CAAC;AACtC,SAAO,EAAE,MAAM,YAAY,OAAO,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,OAAO,OAAO,IAAI,CAAC,SAAS,OAAO,MAAM;AAChH;AAOA,SAAS,QAAQ,QAAgB,IAAY,IAAY,GAAW,KAAyB;AAC3F,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;AACzB,UAAM,IAAI,KAAK,IAAI;AACnB,QAAI,CAAC,IAAI,KAAK,KAAK,IAAI;AACvB,QAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI;AAAA,EAC7B,WAAW,OAAO,SAAS,aAAa;AACtC,UAAM,IAAI,OAAO;AACjB,UAAM,KAAK,OAAO;AAClB,UAAM,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;AACzB,UAAM,MAAM,KAAK,IAAI,KAAK,CAAC;AAC3B,UAAM,MAAM,KAAK,IAAI,KAAK,CAAC;AAC3B,QAAI,CAAC,IAAI,KAAK,KAAK,OAAQ,KAAK,IAAI,MAAM,KAAM;AAChD,QAAI,CAAC,IAAI,KAAK,KAAK,OAAQ,IAAI,KAAK,OAAO,QAAQ,OAAO,QAAQ,MAAM,KAAM;AAAA,EAChF,OAAO;AACL,UAAM,EAAE,IAAI,GAAG,IAAI;AACnB,UAAM,MAAM,KAAK,KAAK,OAAO,KAAK;AAClC,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK,IAAI,KAAK,CAAC;AAC1B,UAAM,KAAK,KAAK,IAAI,KAAK,CAAC;AAC1B,QAAI,CAAC,IAAI,KAAK,KAAK,KAAK;AACxB,QAAI,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,EACpC;AACF;AAYO,SAAS,WAAW,OAAoB,QAAgB,QAAsB,MAA2B;AAC9G,QAAM,MAAM,IAAI,aAAa,CAAC;AAC9B,UAAQ,UAAU,MAAM,GAAG,MAAM,QAAQ,QAAQ,MAAM,UAAU,OAAO,KAAM,GAAG;AACjF,SAAO,EAAE,OAAO,SAAS,IAAI,CAAC,GAAI,UAAU,IAAI,CAAC,EAAG;AACtD;AAYA,IAAM,iBAAN,MAAmD;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,IAAI,aAAa,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAiC;AAAA,EAEjC,YAAY,SAAqB,QAAsB;AACrD,SAAK,SAAS,SAAS,OAAO;AAC9B,UAAM,OAAO,KAAK,OAAO;AACzB,SAAK,IAAI,IAAI,aAAa,IAAI;AAC9B,SAAK,IAAI,IAAI,aAAa,IAAI;AAC9B,SAAK,OAAO,IAAI,aAAa,IAAI;AACjC,oBAAgB,SAAS,KAAK,CAAC;AAC/B,oBAAgB,SAAS,KAAK,IAAI;AAClC,SAAK,SAAS;AACd,SAAK,SAAS,cAAc,MAAM;AAClC,SAAK,SAAS,UAAU,KAAK,MAAM;AAAA,EACrC;AAAA,EAEA,IAAI,QAAoB;AACtB,QAAI,KAAK,gBAAgB,KAAM,MAAK,cAAc,UAAU,KAAK,QAAQ,KAAK,CAAC;AAC/E,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAuB;AACzB,WAAO,UAAU,KAAK,QAAQ,KAAK,CAAC;AAAA,EACtC;AAAA,EAEA,IAAI,SAAqB;AACvB,WAAO,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAAA,EAEA,MAAM,OAAmB,MAAoB;AAC3C,QAAI,CAAC,WAAW,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG;AAC7C,YAAM,IAAI,UAAU,WAAW,IAAI,gDAAgD;AAAA,IACrF;AAAA,EACF;AAAA;AAAA,EAGA,gBAAsB;AACpB,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,KAAK;AACtC,UAAI,KAAK,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,MAAM,GAAG;AACjD,aAAK,UAAU;AACf;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,QAA0B;AAClC,SAAK,MAAM,QAAQ,YAAY;AAC/B,oBAAgB,QAAQ,KAAK,IAAI;AAEjC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,YAAY,UAA4B;AACtC,SAAK,MAAM,UAAU,cAAc;AACnC,oBAAgB,UAAU,KAAK,CAAC;AAChC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,OAAO,OAAyB;AAC9B,SAAK,MAAM,OAAO,WAAW;AAC7B,oBAAgB,OAAO,KAAK,CAAC;AAC7B,oBAAgB,OAAO,KAAK,IAAI;AAChC,SAAK,EAAE,KAAK,CAAC;AACb,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAa;AACX,SAAK,EAAE,IAAI,KAAK,IAAI;AACpB,SAAK,EAAE,KAAK,CAAC;AACb,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,QAA4B;AACpC,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AAC1C,SAAK,SAAS,cAAc,KAAK,MAAM;AACvC,SAAK,SAAS,UAAU,KAAK,MAAM;AAAA,EACrC;AAAA,EAEA,KAAK,MAAuB;AAC1B,QAAI,KAAK,QAAS,QAAO;AACzB,QAAI,EAAE,OAAO,GAAI,QAAO;AACxB,UAAM,IAAI,OAAO;AACjB,UAAM,EAAE,GAAG,GAAG,MAAM,QAAQ,IAAI;AAChC,UAAM,EAAE,WAAW,UAAU,IAAI,KAAK;AACtC,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,cAAQ,KAAK,QAAQ,EAAE,CAAC,IAAK,KAAK,CAAC,GAAI,EAAE,CAAC,GAAI,GAAG,OAAO;AACxD,QAAE,CAAC,IAAI,KAAK,CAAC,IAAK,QAAQ,CAAC;AAC3B,QAAE,CAAC,IAAI,QAAQ,CAAC;AAChB,UAAI,YAAY,KAAK,IAAI,QAAQ,CAAC,CAAE,IAAI,aAAa,KAAK,IAAI,QAAQ,CAAC,CAAE,IAAI,WAAY,WAAU;AAAA,IACrG;AACA,SAAK,cAAc;AACnB,QAAI,QAAS,MAAK,KAAK;AACvB,WAAO,CAAC,KAAK;AAAA,EACf;AACF;AAOO,SAAS,aAAmC,SAAY,SAAuB,CAAC,GAAqB;AAC1G,SAAO,IAAI,eAAe,SAAS,MAAM;AAC3C;;;ACxPA,IAAM,gBAAN,MAAiD;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAiC;AAAA,EAEjC,YAAY,SAAqB,QAAqB;AACpD,SAAK,SAAS,SAAS,OAAO;AAC9B,UAAM,OAAO,KAAK,OAAO;AACzB,SAAK,IAAI,IAAI,aAAa,IAAI;AAC9B,SAAK,OAAO,IAAI,aAAa,IAAI;AACjC,SAAK,OAAO,IAAI,aAAa,IAAI;AACjC,oBAAgB,SAAS,KAAK,CAAC;AAC/B,oBAAgB,SAAS,KAAK,IAAI;AAClC,oBAAgB,SAAS,KAAK,IAAI;AAClC,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,IAAI,QAAoB;AACtB,QAAI,KAAK,gBAAgB,KAAM,MAAK,cAAc,UAAU,KAAK,QAAQ,KAAK,CAAC;AAC/E,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAqB;AACvB,WAAO,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAAA,EAEA,IAAI,WAAmB;AACrB,QAAI,KAAK,QAAS,QAAO;AACzB,WAAO,KAAK,YAAY,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,QAAQ;AAAA,EAC1E;AAAA;AAAA,EAGA,IAAI,WAAuB;AACzB,UAAM,MAAM,IAAI,aAAa,KAAK,OAAO,IAAI;AAC7C,QAAI,CAAC,KAAK,WAAW,KAAK,WAAW,GAAG;AACtC,YAAM,IAAI,KAAK;AACf,YAAM,IAAI;AACV,YAAM,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;AAC5B,YAAM,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;AAC5B,YAAM,SAAS,KAAK,OAAO,EAAE,IAAI,KAAK,OAAO,EAAE,MAAM,KAAK;AAC1D,YAAM,YAAa,QAAQ,KAAK,WAAY;AAC5C,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,KAAK,KAAK,KAAK,CAAC,IAAK,KAAK,KAAK,CAAC,KAAM;AAAA,IAClF;AACA,WAAO,UAAU,KAAK,QAAQ,GAAG;AAAA,EACnC;AAAA,EAEA,UAAU,QAA2B;AACnC,QAAI,OAAO,aAAa,QAAW;AACjC,UAAI,EAAE,OAAO,YAAY,MAAM,CAAC,OAAO,SAAS,OAAO,QAAQ,GAAG;AAChE,cAAM,IAAI,WAAW,qDAAqD,OAAO,QAAQ,EAAE;AAAA,MAC7F;AACA,WAAK,WAAW,OAAO;AAAA,IACzB;AACA,QAAI,OAAO,WAAW,OAAW,MAAK,SAAS,OAAO;AAAA,EACxD;AAAA,EAEA,MAAM,OAAmB,MAAoB;AAC3C,QAAI,CAAC,WAAW,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG;AAC7C,YAAM,IAAI,UAAU,UAAU,IAAI,+CAA+C;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,UAAU,QAA0B;AAClC,SAAK,MAAM,QAAQ,YAAY;AAC/B,oBAAgB,QAAQ,KAAK,IAAI;AAEjC,SAAK,KAAK,IAAI,KAAK,CAAC;AACpB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,KAAK;AACtC,UAAI,KAAK,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,GAAG;AAC9B,aAAK,UAAU;AACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,OAAyB;AAC9B,SAAK,MAAM,OAAO,WAAW;AAC7B,oBAAgB,OAAO,KAAK,CAAC;AAC7B,oBAAgB,OAAO,KAAK,IAAI;AAChC,oBAAgB,OAAO,KAAK,IAAI;AAChC,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAa;AACX,SAAK,EAAE,IAAI,KAAK,IAAI;AACpB,SAAK,KAAK,IAAI,KAAK,IAAI;AACvB,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAK,MAAuB;AAC1B,QAAI,KAAK,QAAS,QAAO;AACzB,SAAK,WAAW,KAAK,IAAI,GAAG,IAAI;AAChC,UAAM,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,QAAQ;AAC3E,QAAI,KAAK,GAAG;AACV,WAAK,KAAK;AACV,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,KAAK,OAAO,CAAC;AAC3B,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,KAAK;AACtC,WAAK,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,KAAM,KAAK,KAAK,CAAC,IAAK,KAAK,KAAK,CAAC,KAAM;AAAA,IAChE;AACA,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AACF;AAOO,SAAS,YAAkC,SAAY,SAAsB,CAAC,GAAoB;AACvG,SAAO,IAAI,cAAc,SAAS,MAAM;AAC1C;;;ACtIO,IAAM,eAAe,EAAE,MAAM,IAAI,SAAS,IAAI,OAAO,GAAG;AAkDxD,IAAM,kBAAkB,EAAE,OAAO,aAAa,SAAS,WAAW,IAAI;AAE7E,SAASA,UAAS,MAAc,OAAuB;AACrD,MAAI,EAAE,QAAQ,MAAM,CAAC,OAAO,SAAS,KAAK,EAAG,OAAM,IAAI,WAAW,WAAW,IAAI,qCAAqC,KAAK,EAAE;AAC7H,SAAO;AACT;AAEA,IAAM,iBAAN,MAAmD;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAiC;AAAA,EAEjC,YAAY,SAAqB,QAAsB;AACrD,SAAK,SAAS,SAAS,OAAO;AAC9B,SAAK,IAAI,IAAI,aAAa,KAAK,OAAO,IAAI;AAC1C,SAAK,IAAI,IAAI,aAAa,KAAK,OAAO,IAAI;AAC1C,SAAK,OAAO,IAAI,aAAa,KAAK,OAAO,IAAI;AAC7C,oBAAgB,SAAS,KAAK,CAAC;AAC/B,oBAAgB,SAAS,KAAK,IAAI;AAClC,SAAK,QAAQA,UAAS,SAAS,OAAO,SAAS,gBAAgB,KAAK;AACpE,SAAK,YAAYA,UAAS,aAAa,OAAO,aAAa,gBAAgB,SAAS;AAAA,EACtF;AAAA,EAEA,IAAI,QAAoB;AACtB,QAAI,KAAK,gBAAgB,KAAM,MAAK,cAAc,UAAU,KAAK,QAAQ,KAAK,CAAC;AAC/E,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAuB;AACzB,WAAO,UAAU,KAAK,QAAQ,KAAK,CAAC;AAAA,EACtC;AAAA,EAEA,IAAI,SAAqB;AACvB,WAAO,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAAA,EAEA,MAAM,OAAmB,MAAoB;AAC3C,QAAI,CAAC,WAAW,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG;AAC7C,YAAM,IAAI,UAAU,WAAW,IAAI,gDAAgD;AAAA,IACrF;AAAA,EACF;AAAA;AAAA,EAGA,KAAK,GAAW,QAAuB;AACrC,UAAM,IAAI,KAAK,EAAE,CAAC,IAAK,KAAK,KAAK,CAAC;AAClC,UAAM,IAAI,KAAK,EAAE,CAAC;AAClB,UAAM,QAAQ,MAAM,IAAI,IAAI,CAAC,KAAK,QAAQ;AAC1C,QAAI,QAAQ;AACV,WAAK,EAAE,CAAC,IAAI;AACZ;AAAA,IACF;AACA,QAAI,MAAM,EAAG;AAEb,QAAI,IAAI,IAAI,EAAG;AAEf,QAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,EAAG,MAAK,EAAE,CAAC,IAAI;AAAA,EACjD;AAAA,EAEA,gBAAsB;AACpB,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,KAAK;AACtC,UAAI,KAAK,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,MAAM,GAAG;AACjD,aAAK,UAAU;AACf;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,QAA0B;AAClC,SAAK,MAAM,QAAQ,YAAY;AAC/B,oBAAgB,QAAQ,KAAK,IAAI;AACjC,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,IAAK,MAAK,KAAK,GAAG,IAAI;AACzD,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,YAAY,UAA4B;AACtC,SAAK,MAAM,UAAU,cAAc;AACnC,oBAAgB,UAAU,KAAK,CAAC;AAChC,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,IAAK,MAAK,KAAK,GAAG,KAAK;AAC1D,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,OAAO,OAAyB;AAC9B,SAAK,MAAM,OAAO,WAAW;AAC7B,oBAAgB,OAAO,KAAK,CAAC;AAC7B,oBAAgB,OAAO,KAAK,IAAI;AAChC,SAAK,EAAE,KAAK,CAAC;AACb,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAK,OAAyB;AAC5B,SAAK,OAAO,KAAK;AAAA,EACnB;AAAA,EAEA,OAAa;AACX,SAAK,EAAE,IAAI,KAAK,IAAI;AACpB,SAAK,EAAE,KAAK,CAAC;AACb,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,QAA4B;AACpC,QAAI,OAAO,UAAU,OAAW,MAAK,QAAQA,UAAS,SAAS,OAAO,KAAK;AAC3E,QAAI,OAAO,cAAc,OAAW,MAAK,YAAYA,UAAS,aAAa,OAAO,SAAS;AAC3F,aAAS,IAAI,GAAG,IAAI,KAAK,EAAE,QAAQ,IAAK,MAAK,KAAK,GAAG,KAAK;AAAA,EAC5D;AAAA,EAEA,KAAK,MAAuB;AAC1B,QAAI,KAAK,QAAS,QAAO;AACzB,QAAI,EAAE,OAAO,GAAI,QAAO;AACxB,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,OAAO;AACjB,UAAM,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;AACzB,UAAM,EAAE,GAAG,GAAG,MAAM,UAAU,IAAI;AAElC,UAAM,YAAY,IAAI,YAAY;AAClC,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AAEjC,YAAM,IAAI,EAAE,CAAC,IAAK,KAAK,CAAC;AACxB,YAAM,IAAI,EAAE,CAAC,IAAK,IAAI;AACtB,YAAM,KAAK,KAAK,IAAI,IAAI;AACxB,QAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAK,IAAI,IAAI;AAC5B,QAAE,CAAC,IAAI,KAAK,CAAC,IAAK;AAElB,YAAM,OAAO,KAAK,IAAI,WAAW,IAAI,OAAO,UAAU,KAAK,IAAI,KAAK,CAAC,CAAE,CAAC;AACxE,UAAI,YAAY,KAAK,IAAI,EAAE,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC,CAAE,IAAI,KAAK,IAAI,WAAW,IAAI,IAAI,GAAI,WAAU;AAAA,IACrG;AACA,SAAK,cAAc;AACnB,QAAI,QAAS,MAAK,KAAK;AACvB,WAAO,CAAC,KAAK;AAAA,EACf;AACF;AAMO,SAAS,aAAmC,SAAY,SAAuB,CAAC,GAAqB;AAC1G,SAAO,IAAI,eAAe,SAAS,MAAM;AAC3C;;;AC7KO,SAAS,OAAO,OAAa,QAA2B;AAC7D,SAAO;AAAA,IACL,IAAI,MAAM,IAAI,OAAO;AAAA,IACrB,IAAI,MAAM,IAAI,OAAO;AAAA,IACrB,OAAO,KAAK,IAAI,GAAG,MAAM,KAAK;AAAA,IAC9B,QAAQ,KAAK,IAAI,GAAG,MAAM,MAAM;AAAA,IAChC,WAAW,KAAK,IAAI,GAAG,OAAO,QAAQ,MAAM,KAAK;AAAA,IACjD,YAAY,KAAK,IAAI,GAAG,OAAO,SAAS,MAAM,MAAM;AAAA,EACtD;AACF;AAgBO,SAAS,MAAM,UAAkB,OAAO,MAAa;AAC1D,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;AAC3C,SAAO,EAAE,OAAO,QAAQ,IAAI,QAAQ,GAAG,SAAS,EAAE;AACpD;;;ACKA,IAAM,SAAN,MAA0C;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,oBAAI,IAAwB;AAAA,EACxC,UAAU,oBAAI,IAAgB;AAAA,EACvC,OAA4B;AAAA,EAC5B,WAAW;AAAA,EAEX,YAAY,MAAiB,UAAuB,SAAwB;AAC1E,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,QAAQ,QAAQ,SAAS;AAC9B,UAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,SAAK,UAAU,OAAO,kBAAkB,aAAa,gBAAgB,MAAM;AAC3E,SAAK,UAAU,OAAO,SAAS,OAAO;AAAA,MACpC,QAAQ;AAAA,IACV,CAAC;AACD,SAAK,eAAe,OAAO,KAAK;AAChC,QAAI,CAAC,SAAS,QAAS,MAAK,MAAM;AAAA,EACpC;AAAA,EAEA,IAAI,QAAW;AACb,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,OAAU;AACR,WAAO,KAAK,QAAQ,KAAK;AAAA,EAC3B;AAAA,EAEA,IAAI,SAAY;AACd,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,IAAI,WAAc;AAChB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAES,OAAO,CAAC,UAA8B;AAC7C,QAAI,KAAK,QAAQ,EAAG,MAAK,SAAS,KAAK;AAAA,QAClC,MAAK,SAAS,KAAK,MAAM,KAAK;AACnC,QAAI,CAAC,KAAK,SAAS,SAAS;AAC1B,WAAK,QAAQ,QAAQ,KAAK,SAAS;AACnC,aAAO;AAAA,IACT;AACA,SAAK,OAAO;AACZ,SAAK,KAAK;AACV,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,SAAS,QAAQ,KAAK,SAAU;AACzC,SAAK,OAAO,KAAK,KAAK,OAAO,KAAK,OAAO,KAAK,IAAI;AAClD,SAAK,aAAa,QAAQ;AAAA,EAC5B;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,SAAS,KAAM;AACxB,SAAK,KAAK;AACV,SAAK,OAAO;AAAA,EACd;AAAA;AAAA,EAGA,OAAa;AACX,UAAM,MAAM;AACV,WAAK,QAAQ,QAAQ,KAAK,SAAS;AACnC,WAAK,aAAa,QAAQ;AAAA,IAC5B,CAAC;AACD,UAAM,QAAQ,KAAK,SAAS;AAC5B,eAAW,YAAY,MAAM,KAAK,KAAK,SAAS,EAAG,UAAS,KAAK;AAAA,EACnE;AAAA,EAEA,IAAI,QAAW,SAA+B;AAC5C,QAAI,KAAK,SAAU;AACnB,cAAU,MAAM;AACd,WAAK,SAAS,UAAU,MAAM;AAC9B,UAAI,SAAS,aAAa,OAAW,MAAK,SAAS,cAAc,QAAQ,QAAQ;AACjF,UAAI,KAAK,QAAQ,EAAG,MAAK,SAAS,KAAK;AACvC,UAAI,KAAK,SAAS,SAAS;AACzB,aAAK,KAAK;AACV,aAAK,KAAK;AAAA,MACZ,OAAO;AACL,aAAK,MAAM;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,KAAK,OAAgB;AACnB,QAAI,KAAK,SAAU;AACnB,cAAU,MAAM;AACd,WAAK,SAAS,OAAO,KAAK;AAC1B,WAAK,KAAK;AACV,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,SAAU;AACnB,cAAU,MAAM;AACd,WAAK,SAAS,KAAK;AACnB,WAAK,KAAK;AACV,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,QAA6B;AAClC,QAAI,KAAK,SAAU,QAAO,MAAM;AAAA,IAAC;AACjC,UAAM,UAAU;AAAA,MACd,MAAM;AACJ,cAAM,SAAS,OAAO;AACtB,aAAK,IAAI,MAAM;AAAA,MACjB;AAAA,MACA,EAAE,UAAU,KAAK,KAAK,UAAU,KAAK,KAAK,EAAE;AAAA,IAC9C;AACA,UAAM,OAAO,MAAY;AACvB,cAAQ;AACR,WAAK,QAAQ,OAAO,IAAI;AAAA,IAC1B;AACA,SAAK,QAAQ,IAAI,IAAI;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,UAA0C;AACjD,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAChB,SAAK,KAAK;AACV,eAAW,QAAQ,MAAM,KAAK,KAAK,OAAO,EAAG,MAAK;AAClD,SAAK,UAAU,MAAM;AACrB,SAAK,aAAa,QAAQ;AAAA,EAC5B;AACF;AAMO,SAAS,YACd,MACA,UACA,UAAyB,CAAC,GACQ;AAClC,SAAO,IAAI,OAAO,MAAM,UAAU,OAAO;AAC3C;AAGO,SAAS,YACd,MACA,SACA,UAAwC,CAAC,GACA;AACzC,SAAO,YAAY,MAAM,aAAa,SAAS,OAAO,GAAG,OAAO;AAClE;AAOO,SAAS,YACd,MACA,SACA,UAAwC,CAAC,GACA;AACzC,SAAO,YAAY,MAAM,aAAa,SAAS,OAAO,GAAG,OAAO;AAClE;AAGO,SAAS,WACd,MACA,SACA,UAAuC,CAAC,GACA;AACxC,SAAO,YAAY,MAAM,YAAY,SAAS,OAAO,GAAG,OAAO;AACjE;","names":["positive"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export { C as ClockPort, F as FrameSource, T as TimerSource } from './port-CmlUc
|
|
|
2
2
|
export { FakeClock, FakeClockOptions, createFakeClock } from './clock.js';
|
|
3
3
|
export { F as FrameInfo, a as FrameLoop, b as FrameLoopOptions, c as FrameStats, d as FrameTask, P as PHASES, e as Phase, R as RepeatingTask, S as ScheduleOptions, f as createFrameLoop } from './frame-loop-C88dc9xw.js';
|
|
4
4
|
export { EffectCleanup, EffectOptions, Equals, ReadonlySignal, Signal, SignalOptions, batch, computed, effect, isSignal, signal, untracked } from './signals.js';
|
|
5
|
-
export { Animator, AnimatorValue, Easing, MotionOptions, MotionValue, SPRING_DEFAULTS, SetOptions, Spring, SpringConfig, SpringParams, SpringState, Tween, TweenConfig, createSpring, createTween, cubicBezier, ease, easeIn, easeInOut, easeInOutCubic, easeOut, easeOutCubic, linear, motionValue, resolveSpring, springStep, springValue, tweenValue } from './values.js';
|
|
5
|
+
export { Animator, AnimatorValue, Easing, MotionOptions, MotionValue, PopIn, RevealFrame, SETTLE_DEFAULTS, SETTLE_TEMPO, SPRING_DEFAULTS, SetOptions, Settle, SettleConfig, Spring, SpringConfig, SpringParams, SpringState, Tween, TweenConfig, createSettle, createSpring, createTween, cubicBezier, ease, easeIn, easeInOut, easeInOutCubic, easeOut, easeOutCubic, linear, motionValue, popIn, resolveSpring, reveal, settleValue, springStep, springValue, tweenValue } from './values.js';
|
|
6
6
|
export { CancelReason, CoalescerOptions, DWELL_DEFAULTS, DWELL_IDLE, Deadline, DwellConfig, DwellInput, DwellMachineOptions, DwellState, FrameCoalescer, InputGesture, InputGestureType, Machine, MachineOptions, ModifierDrag, ModifierKey, Modifiers, NO_MODIFIERS, Platform, PointerKind, RECOGNIZER_DEFAULTS, RawInputEvent, RawPointerEvent, RawPointerType, RawSafariGestureEvent, RawWheelEvent, Recognizer, RecognizerOptions, RecognizerTimers, SurfacePointer, WHEEL_DEFAULTS, WHEEL_PAN_DEFAULTS, WheelIntent, WheelOptions, WheelPanOptions, classifyWheel, createDwellMachine, createFrameCoalescer, createMachine, createRecognizer, dampWheelPan, defaultDragModifier, dwellDeadline, dwellReducer, isHeld, modHeld, platformButton, resolveDragModifier, toModifiers, wheelDeltaPx } from './gestures.js';
|
|
7
7
|
export { A as Animatable, P as Point, R as Rect, V as Vector, W as Widen, s as shapeEquals } from './shapes-EbQlwbCu.js';
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,10 @@ import {
|
|
|
5
5
|
} from "./chunk-BVPVUJ42.js";
|
|
6
6
|
import "./chunk-FQNHO2VT.js";
|
|
7
7
|
import {
|
|
8
|
+
SETTLE_DEFAULTS,
|
|
9
|
+
SETTLE_TEMPO,
|
|
8
10
|
SPRING_DEFAULTS,
|
|
11
|
+
createSettle,
|
|
9
12
|
createSpring,
|
|
10
13
|
createTween,
|
|
11
14
|
cubicBezier,
|
|
@@ -17,12 +20,15 @@ import {
|
|
|
17
20
|
easeOutCubic,
|
|
18
21
|
linear,
|
|
19
22
|
motionValue,
|
|
23
|
+
popIn,
|
|
20
24
|
resolveSpring,
|
|
25
|
+
reveal,
|
|
26
|
+
settleValue,
|
|
21
27
|
shapeEquals,
|
|
22
28
|
springStep,
|
|
23
29
|
springValue,
|
|
24
30
|
tweenValue
|
|
25
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6W5KW7XQ.js";
|
|
26
32
|
import {
|
|
27
33
|
DWELL_DEFAULTS,
|
|
28
34
|
DWELL_IDLE,
|
|
@@ -60,6 +66,8 @@ export {
|
|
|
60
66
|
NO_MODIFIERS,
|
|
61
67
|
PHASES,
|
|
62
68
|
RECOGNIZER_DEFAULTS,
|
|
69
|
+
SETTLE_DEFAULTS,
|
|
70
|
+
SETTLE_TEMPO,
|
|
63
71
|
SPRING_DEFAULTS,
|
|
64
72
|
WHEEL_DEFAULTS,
|
|
65
73
|
WHEEL_PAN_DEFAULTS,
|
|
@@ -72,6 +80,7 @@ export {
|
|
|
72
80
|
createFrameLoop,
|
|
73
81
|
createMachine,
|
|
74
82
|
createRecognizer,
|
|
83
|
+
createSettle,
|
|
75
84
|
createSpring,
|
|
76
85
|
createTween,
|
|
77
86
|
cubicBezier,
|
|
@@ -92,8 +101,11 @@ export {
|
|
|
92
101
|
modHeld,
|
|
93
102
|
motionValue,
|
|
94
103
|
platformButton,
|
|
104
|
+
popIn,
|
|
95
105
|
resolveDragModifier,
|
|
96
106
|
resolveSpring,
|
|
107
|
+
reveal,
|
|
108
|
+
settleValue,
|
|
97
109
|
shapeEquals,
|
|
98
110
|
signal,
|
|
99
111
|
springStep,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { R as Rect } from './shapes-EbQlwbCu.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Frame-sampled checks of the motion rules: record what was drawn on each
|
|
5
|
+
* frame (in a unit test on the fake clock, or in a browser spec reading the
|
|
6
|
+
* page each animation frame) and ask whether the motion kept the rules.
|
|
7
|
+
*
|
|
8
|
+
* Every check returns `{ ok, failures }`; a failure names the frame (its time)
|
|
9
|
+
* and the component, so a spec can print it. Pixel tolerances default to half
|
|
10
|
+
* a pixel.
|
|
11
|
+
*/
|
|
12
|
+
/** One drawn frame: the time in ms and the rect on screen. */
|
|
13
|
+
interface RectSample {
|
|
14
|
+
readonly t: number;
|
|
15
|
+
readonly rect: Rect;
|
|
16
|
+
}
|
|
17
|
+
/** A drawn frame with the target the motion was heading for at that frame. */
|
|
18
|
+
interface TargetSample extends RectSample {
|
|
19
|
+
readonly target: Rect;
|
|
20
|
+
}
|
|
21
|
+
/** A drawn frame with where a pointer-held rect should be. */
|
|
22
|
+
interface HeldSample extends RectSample {
|
|
23
|
+
readonly expected: Rect;
|
|
24
|
+
}
|
|
25
|
+
/** A drawn frame of content's transform: the matrix's x and y scale (CSS matrix `a` and `d`). */
|
|
26
|
+
interface ScaleSample {
|
|
27
|
+
readonly t: number;
|
|
28
|
+
readonly a: number;
|
|
29
|
+
readonly d: number;
|
|
30
|
+
}
|
|
31
|
+
/** What a check found. */
|
|
32
|
+
interface CheckResult {
|
|
33
|
+
readonly ok: boolean;
|
|
34
|
+
readonly failures: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
/** {@link checkTempo}'s result: also the measured time to 90 %. */
|
|
37
|
+
interface TempoResult extends CheckResult {
|
|
38
|
+
/** Ms from the start to the first sample 90 % of the way; null if it never got there or there was no move. */
|
|
39
|
+
readonly t90: number | null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* No overshoot: between `from` and `to`, every component of every frame stays
|
|
43
|
+
* between its start and end value (plus `tolerance`). Run it per move; size
|
|
44
|
+
* (`width`, `height`) passing is "no wobble".
|
|
45
|
+
*/
|
|
46
|
+
declare function checkNoOvershoot(samples: readonly RectSample[], from: Rect, to: Rect, tolerance?: number): CheckResult;
|
|
47
|
+
/**
|
|
48
|
+
* Monotonic settle: per component, the distance to `to` never grows beyond
|
|
49
|
+
* the closest it has been so far (plus `tolerance`, once: a slow drift away
|
|
50
|
+
* fails too). A bounce or a restart backwards fails it.
|
|
51
|
+
*/
|
|
52
|
+
declare function checkMonotonic(samples: readonly RectSample[], to: Rect, tolerance?: number): CheckResult;
|
|
53
|
+
/**
|
|
54
|
+
* No jumps: no frame moves a component further than a settle at `omega`
|
|
55
|
+
* could in that frame's time, measured against the larger of the distances to
|
|
56
|
+
* the target before and after (plus `slack` px). A snap, a restart from an old
|
|
57
|
+
* place or a teleport fails it; a settle, however often retargeted, passes.
|
|
58
|
+
* Leave held frames out (a pointer may move anything any distance).
|
|
59
|
+
*
|
|
60
|
+
* Sample times must be the time the motion was stepped by (the frame loop's
|
|
61
|
+
* `delta`s summed, as `FrameInfo.delta` hands them out: 1000/60 for the first
|
|
62
|
+
* frame after idle, clamped to 64 ms), not wall-clock timestamps; and `slack`
|
|
63
|
+
* must cover the final snap, so keep it above the settle's `restDelta`.
|
|
64
|
+
*/
|
|
65
|
+
declare function checkNoJumps(samples: readonly TargetSample[], omega: number, slack?: number): CheckResult;
|
|
66
|
+
/** Held 1:1: on every frame the drawn rect is where the pointer puts it (within `tolerance`). */
|
|
67
|
+
declare function checkHeld(samples: readonly HeldSample[], tolerance?: number): CheckResult;
|
|
68
|
+
/**
|
|
69
|
+
* Content never stretched: the content's transform scales x and y by the same
|
|
70
|
+
* factor (within `tolerance`). With `uniformOnly: false` (default true) it must
|
|
71
|
+
* also be 1, i.e. not scaled at all: use that for glides, the default for
|
|
72
|
+
* open and close.
|
|
73
|
+
*/
|
|
74
|
+
declare function checkContentScale(samples: readonly ScaleSample[], options?: {
|
|
75
|
+
uniformOnly?: boolean;
|
|
76
|
+
tolerance?: number;
|
|
77
|
+
}): CheckResult;
|
|
78
|
+
/**
|
|
79
|
+
* Tempo: the move from `from` to `to` is 90 % done (by its largest component)
|
|
80
|
+
* within `t90` ms, give or take `tolerance` (a fraction, default 0.25).
|
|
81
|
+
* Time counts from `startT`: when the move began (the frame its target was
|
|
82
|
+
* set, its rect still `from`). It defaults to the first sample's time, so
|
|
83
|
+
* either pass it or record that frame first.
|
|
84
|
+
*/
|
|
85
|
+
declare function checkTempo(samples: readonly RectSample[], from: Rect, to: Rect, t90: number, tolerance?: number, startT?: number): TempoResult;
|
|
86
|
+
|
|
87
|
+
export { type CheckResult, type HeldSample, type RectSample, type ScaleSample, type TargetSample, type TempoResult, checkContentScale, checkHeld, checkMonotonic, checkNoJumps, checkNoOvershoot, checkTempo };
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/testing/checks.ts
|
|
2
|
+
var KEYS = ["x", "y", "width", "height"];
|
|
3
|
+
var result = (failures) => ({ ok: failures.length === 0, failures });
|
|
4
|
+
var fmt = (n) => (Math.round(n * 100) / 100).toString();
|
|
5
|
+
function checkNoOvershoot(samples, from, to, tolerance = 0.5) {
|
|
6
|
+
const failures = [];
|
|
7
|
+
for (const s of samples) {
|
|
8
|
+
for (const k of KEYS) {
|
|
9
|
+
const lo = Math.min(from[k], to[k]) - tolerance;
|
|
10
|
+
const hi = Math.max(from[k], to[k]) + tolerance;
|
|
11
|
+
const v = s.rect[k];
|
|
12
|
+
if (v < lo || v > hi) failures.push(`t=${fmt(s.t)} ${k}=${fmt(v)} outside [${fmt(lo + tolerance)}, ${fmt(hi - tolerance)}]`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return result(failures);
|
|
16
|
+
}
|
|
17
|
+
function checkMonotonic(samples, to, tolerance = 0.5) {
|
|
18
|
+
const failures = [];
|
|
19
|
+
const closest = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const s of samples) {
|
|
21
|
+
for (const k of KEYS) {
|
|
22
|
+
const off = Math.abs(s.rect[k] - to[k]);
|
|
23
|
+
const best = closest.get(k);
|
|
24
|
+
if (best !== void 0 && off > best + tolerance) failures.push(`t=${fmt(s.t)} ${k} moved away from its target: ${fmt(best)} \u2192 ${fmt(off)} px off`);
|
|
25
|
+
if (best === void 0 || off < best) closest.set(k, off);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return result(failures);
|
|
29
|
+
}
|
|
30
|
+
function checkNoJumps(samples, omega, slack = 1) {
|
|
31
|
+
const failures = [];
|
|
32
|
+
for (let i = 1; i < samples.length; i++) {
|
|
33
|
+
const a = samples[i - 1];
|
|
34
|
+
const b = samples[i];
|
|
35
|
+
const dt = Math.max(0, b.t - a.t) / 1e3;
|
|
36
|
+
const reach = 1 - Math.exp(-omega * dt);
|
|
37
|
+
for (const k of KEYS) {
|
|
38
|
+
const step = Math.abs(b.rect[k] - a.rect[k]);
|
|
39
|
+
const far = Math.max(Math.abs(a.rect[k] - a.target[k]), Math.abs(a.rect[k] - b.target[k]));
|
|
40
|
+
const limit = far * reach * 1.05 + slack;
|
|
41
|
+
if (step > limit) failures.push(`t=${fmt(b.t)} ${k} jumped ${fmt(step)} px in ${fmt(b.t - a.t)} ms (at most ${fmt(limit)})`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result(failures);
|
|
45
|
+
}
|
|
46
|
+
function checkHeld(samples, tolerance = 0.5) {
|
|
47
|
+
const failures = [];
|
|
48
|
+
for (const s of samples) {
|
|
49
|
+
for (const k of KEYS) {
|
|
50
|
+
const off = Math.abs(s.rect[k] - s.expected[k]);
|
|
51
|
+
if (off > tolerance) failures.push(`t=${fmt(s.t)} ${k} is ${fmt(off)} px from the pointer's place`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result(failures);
|
|
55
|
+
}
|
|
56
|
+
function checkContentScale(samples, options = {}) {
|
|
57
|
+
const tolerance = options.tolerance ?? 1e-3;
|
|
58
|
+
const uniformOnly = options.uniformOnly ?? true;
|
|
59
|
+
const failures = [];
|
|
60
|
+
for (const s of samples) {
|
|
61
|
+
if (Math.abs(s.a - s.d) > tolerance) failures.push(`t=${fmt(s.t)} content stretched: scale ${fmt(s.a)} \xD7 ${fmt(s.d)}`);
|
|
62
|
+
else if (!uniformOnly && (Math.abs(s.a - 1) > tolerance || Math.abs(s.d - 1) > tolerance)) failures.push(`t=${fmt(s.t)} content scaled by ${fmt(s.a)}`);
|
|
63
|
+
}
|
|
64
|
+
return result(failures);
|
|
65
|
+
}
|
|
66
|
+
function checkTempo(samples, from, to, t90, tolerance = 0.25, startT = samples[0]?.t ?? 0) {
|
|
67
|
+
let key = "x";
|
|
68
|
+
for (const k of KEYS) if (Math.abs(to[k] - from[k]) > Math.abs(to[key] - from[key])) key = k;
|
|
69
|
+
const span = to[key] - from[key];
|
|
70
|
+
if (span === 0) return { ok: true, failures: [], t90: null };
|
|
71
|
+
let measured = null;
|
|
72
|
+
for (const s of samples) {
|
|
73
|
+
if ((s.rect[key] - from[key]) / span >= 0.9) {
|
|
74
|
+
measured = s.t - startT;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const failures = [];
|
|
79
|
+
if (measured === null) failures.push(`never got 90 % of the way (${key})`);
|
|
80
|
+
else if (measured < t90 * (1 - tolerance) || measured > t90 * (1 + tolerance)) {
|
|
81
|
+
failures.push(`90 % after ${fmt(measured)} ms, expected ${fmt(t90)} ms \xB1 ${Math.round(tolerance * 100)} %`);
|
|
82
|
+
}
|
|
83
|
+
return { ok: failures.length === 0, failures, t90: measured };
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
checkContentScale,
|
|
87
|
+
checkHeld,
|
|
88
|
+
checkMonotonic,
|
|
89
|
+
checkNoJumps,
|
|
90
|
+
checkNoOvershoot,
|
|
91
|
+
checkTempo
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/testing/checks.ts"],"sourcesContent":["import type { Rect } from \"../shapes\";\n\n/**\n * Frame-sampled checks of the motion rules: record what was drawn on each\n * frame (in a unit test on the fake clock, or in a browser spec reading the\n * page each animation frame) and ask whether the motion kept the rules.\n *\n * Every check returns `{ ok, failures }`; a failure names the frame (its time)\n * and the component, so a spec can print it. Pixel tolerances default to half\n * a pixel.\n */\n\n/** One drawn frame: the time in ms and the rect on screen. */\nexport interface RectSample {\n readonly t: number;\n readonly rect: Rect;\n}\n\n/** A drawn frame with the target the motion was heading for at that frame. */\nexport interface TargetSample extends RectSample {\n readonly target: Rect;\n}\n\n/** A drawn frame with where a pointer-held rect should be. */\nexport interface HeldSample extends RectSample {\n readonly expected: Rect;\n}\n\n/** A drawn frame of content's transform: the matrix's x and y scale (CSS matrix `a` and `d`). */\nexport interface ScaleSample {\n readonly t: number;\n readonly a: number;\n readonly d: number;\n}\n\n/** What a check found. */\nexport interface CheckResult {\n readonly ok: boolean;\n readonly failures: readonly string[];\n}\n\n/** {@link checkTempo}'s result: also the measured time to 90 %. */\nexport interface TempoResult extends CheckResult {\n /** Ms from the start to the first sample 90 % of the way; null if it never got there or there was no move. */\n readonly t90: number | null;\n}\n\nconst KEYS = [\"x\", \"y\", \"width\", \"height\"] as const;\ntype Key = (typeof KEYS)[number];\n\nconst result = (failures: string[]): CheckResult => ({ ok: failures.length === 0, failures });\nconst fmt = (n: number): string => (Math.round(n * 100) / 100).toString();\n\n/**\n * No overshoot: between `from` and `to`, every component of every frame stays\n * between its start and end value (plus `tolerance`). Run it per move; size\n * (`width`, `height`) passing is \"no wobble\".\n */\nexport function checkNoOvershoot(samples: readonly RectSample[], from: Rect, to: Rect, tolerance = 0.5): CheckResult {\n const failures: string[] = [];\n for (const s of samples) {\n for (const k of KEYS) {\n const lo = Math.min(from[k], to[k]) - tolerance;\n const hi = Math.max(from[k], to[k]) + tolerance;\n const v = s.rect[k];\n if (v < lo || v > hi) failures.push(`t=${fmt(s.t)} ${k}=${fmt(v)} outside [${fmt(lo + tolerance)}, ${fmt(hi - tolerance)}]`);\n }\n }\n return result(failures);\n}\n\n/**\n * Monotonic settle: per component, the distance to `to` never grows beyond\n * the closest it has been so far (plus `tolerance`, once: a slow drift away\n * fails too). A bounce or a restart backwards fails it.\n */\nexport function checkMonotonic(samples: readonly RectSample[], to: Rect, tolerance = 0.5): CheckResult {\n const failures: string[] = [];\n const closest = new Map<Key, number>();\n for (const s of samples) {\n for (const k of KEYS) {\n const off = Math.abs(s.rect[k] - to[k]);\n const best = closest.get(k);\n if (best !== undefined && off > best + tolerance) failures.push(`t=${fmt(s.t)} ${k} moved away from its target: ${fmt(best)} → ${fmt(off)} px off`);\n if (best === undefined || off < best) closest.set(k, off);\n }\n }\n return result(failures);\n}\n\n/**\n * No jumps: no frame moves a component further than a settle at `omega`\n * could in that frame's time, measured against the larger of the distances to\n * the target before and after (plus `slack` px). A snap, a restart from an old\n * place or a teleport fails it; a settle, however often retargeted, passes.\n * Leave held frames out (a pointer may move anything any distance).\n *\n * Sample times must be the time the motion was stepped by (the frame loop's\n * `delta`s summed, as `FrameInfo.delta` hands them out: 1000/60 for the first\n * frame after idle, clamped to 64 ms), not wall-clock timestamps; and `slack`\n * must cover the final snap, so keep it above the settle's `restDelta`.\n */\nexport function checkNoJumps(samples: readonly TargetSample[], omega: number, slack = 1): CheckResult {\n const failures: string[] = [];\n for (let i = 1; i < samples.length; i++) {\n const a = samples[i - 1]!;\n const b = samples[i]!;\n const dt = Math.max(0, b.t - a.t) / 1000;\n const reach = 1 - Math.exp(-omega * dt);\n for (const k of KEYS) {\n const step = Math.abs(b.rect[k] - a.rect[k]);\n const far = Math.max(Math.abs(a.rect[k] - a.target[k]), Math.abs(a.rect[k] - b.target[k]));\n const limit = far * reach * 1.05 + slack;\n if (step > limit) failures.push(`t=${fmt(b.t)} ${k} jumped ${fmt(step)} px in ${fmt(b.t - a.t)} ms (at most ${fmt(limit)})`);\n }\n }\n return result(failures);\n}\n\n/** Held 1:1: on every frame the drawn rect is where the pointer puts it (within `tolerance`). */\nexport function checkHeld(samples: readonly HeldSample[], tolerance = 0.5): CheckResult {\n const failures: string[] = [];\n for (const s of samples) {\n for (const k of KEYS) {\n const off = Math.abs(s.rect[k] - s.expected[k]);\n if (off > tolerance) failures.push(`t=${fmt(s.t)} ${k} is ${fmt(off)} px from the pointer's place`);\n }\n }\n return result(failures);\n}\n\n/**\n * Content never stretched: the content's transform scales x and y by the same\n * factor (within `tolerance`). With `uniformOnly: false` (default true) it must\n * also be 1, i.e. not scaled at all: use that for glides, the default for\n * open and close.\n */\nexport function checkContentScale(samples: readonly ScaleSample[], options: { uniformOnly?: boolean; tolerance?: number } = {}): CheckResult {\n const tolerance = options.tolerance ?? 1e-3;\n const uniformOnly = options.uniformOnly ?? true;\n const failures: string[] = [];\n for (const s of samples) {\n if (Math.abs(s.a - s.d) > tolerance) failures.push(`t=${fmt(s.t)} content stretched: scale ${fmt(s.a)} × ${fmt(s.d)}`);\n else if (!uniformOnly && (Math.abs(s.a - 1) > tolerance || Math.abs(s.d - 1) > tolerance)) failures.push(`t=${fmt(s.t)} content scaled by ${fmt(s.a)}`);\n }\n return result(failures);\n}\n\n/**\n * Tempo: the move from `from` to `to` is 90 % done (by its largest component)\n * within `t90` ms, give or take `tolerance` (a fraction, default 0.25).\n * Time counts from `startT`: when the move began (the frame its target was\n * set, its rect still `from`). It defaults to the first sample's time, so\n * either pass it or record that frame first.\n */\nexport function checkTempo(\n samples: readonly RectSample[],\n from: Rect,\n to: Rect,\n t90: number,\n tolerance = 0.25,\n startT: number = samples[0]?.t ?? 0,\n): TempoResult {\n let key: Key = \"x\";\n for (const k of KEYS) if (Math.abs(to[k] - from[k]) > Math.abs(to[key] - from[key])) key = k;\n const span = to[key] - from[key];\n if (span === 0) return { ok: true, failures: [], t90: null };\n let measured: number | null = null;\n for (const s of samples) {\n if ((s.rect[key] - from[key]) / span >= 0.9) {\n measured = s.t - startT;\n break;\n }\n }\n const failures: string[] = [];\n if (measured === null) failures.push(`never got 90 % of the way (${key})`);\n else if (measured < t90 * (1 - tolerance) || measured > t90 * (1 + tolerance)) {\n failures.push(`90 % after ${fmt(measured)} ms, expected ${fmt(t90)} ms ± ${Math.round(tolerance * 100)} %`);\n }\n return { ok: failures.length === 0, failures, t90: measured };\n}\n"],"mappings":"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","names":[]}
|
package/dist/values.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as Animatable, W as Widen } from './shapes-EbQlwbCu.js';
|
|
1
|
+
import { A as Animatable, W as Widen, R as Rect } from './shapes-EbQlwbCu.js';
|
|
2
2
|
import { e as Phase, a as FrameLoop } from './frame-loop-C88dc9xw.js';
|
|
3
3
|
import { ReadonlySignal } from './signals.js';
|
|
4
4
|
import './port-CmlUctqx.js';
|
|
@@ -133,6 +133,123 @@ interface Tween<T> extends Animator<T> {
|
|
|
133
133
|
*/
|
|
134
134
|
declare function createTween<T extends Animatable>(initial: T, config?: TweenConfig): Tween<Widen<T>>;
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Tempos for {@link createSettle}, in 1/s: a settle covers 90 % of the way in
|
|
138
|
+
* ln(10)/omega seconds and is within 1 % in twice that.
|
|
139
|
+
*
|
|
140
|
+
* - `calm` 20: 90 % in 115 ms, done in 230 ms.
|
|
141
|
+
* - `default` 25: 90 % in 92 ms, done in 184 ms.
|
|
142
|
+
* - `quick` 37: 90 % in 62 ms, done in 124 ms (a fast Hyprland setup).
|
|
143
|
+
*/
|
|
144
|
+
declare const SETTLE_TEMPO: {
|
|
145
|
+
readonly calm: 20;
|
|
146
|
+
readonly default: 25;
|
|
147
|
+
readonly quick: 37;
|
|
148
|
+
};
|
|
149
|
+
/** Settings of {@link createSettle}. */
|
|
150
|
+
interface SettleConfig {
|
|
151
|
+
/** The tempo in 1/s (see {@link SETTLE_TEMPO}). Higher is faster. Default 25. */
|
|
152
|
+
readonly omega?: number;
|
|
153
|
+
/** Distance from the target that counts as arrived. Default 0.1 (tuned for pixels). */
|
|
154
|
+
readonly restDelta?: number;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The one curve for things that move to a new place: a window's rect between
|
|
158
|
+
* layout targets, a drawer, a camera. Fast at the start, gentle at the end,
|
|
159
|
+
* and it never passes its target.
|
|
160
|
+
*
|
|
161
|
+
* It is a critically damped spring (stiffness omega², damping 2·omega) with
|
|
162
|
+
* one rule on its velocity, per component:
|
|
163
|
+
*
|
|
164
|
+
* - **Launch.** On a new target, each component gets the velocity
|
|
165
|
+
* omega · distance toward it, from wherever it is drawn: standing still,
|
|
166
|
+
* moving toward it, or moving away (it turns at once rather than drifting
|
|
167
|
+
* further first). From there the spring follows `distance · e^(−omega·t)`
|
|
168
|
+
* exactly: most of the move happens at once, the rest eases in.
|
|
169
|
+
* - **Clamp.** That speed is also the most it may have toward the target, so a
|
|
170
|
+
* velocity set by hand (`setVelocity`, a fling) toward the target is capped
|
|
171
|
+
* there instead of shooting past.
|
|
172
|
+
* - **Carry.** A velocity set by hand away from the target is kept, and the
|
|
173
|
+
* value turns around; a critically damped spring turning around never
|
|
174
|
+
* crosses the target either.
|
|
175
|
+
*
|
|
176
|
+
* So after a new target every component goes straight from where it is drawn
|
|
177
|
+
* to the target and never past it: no overshoot on position, no wobble on
|
|
178
|
+
* size, whatever the retargets. A new target starts from the drawn value,
|
|
179
|
+
* never from the old start.
|
|
180
|
+
*
|
|
181
|
+
* Holding (a pointer owns the value): call `hold(value)` on each move. The
|
|
182
|
+
* value sits exactly there, at rest; the next `setTarget` launches from it.
|
|
183
|
+
*/
|
|
184
|
+
interface Settle<T> extends Animator<T> {
|
|
185
|
+
/** The tempo in 1/s. */
|
|
186
|
+
readonly omega: number;
|
|
187
|
+
/** Put the value at `value`, at rest, with it as the target: a held value follows its owner 1:1. Same as `jumpTo`. */
|
|
188
|
+
hold(value: T): void;
|
|
189
|
+
/** Set the velocity (units per second); a component moving toward the target is clamped as in the launch rule. */
|
|
190
|
+
setVelocity(velocity: T): void;
|
|
191
|
+
/** Change the tempo or rest distance mid-flight; the value and velocity carry on, re-clamped. */
|
|
192
|
+
configure(config: SettleConfig): void;
|
|
193
|
+
}
|
|
194
|
+
/** Defaults of {@link SettleConfig}. */
|
|
195
|
+
declare const SETTLE_DEFAULTS: {
|
|
196
|
+
readonly omega: 25;
|
|
197
|
+
readonly restDelta: 0.1;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* A settle starting at rest on `initial` (a number, a vector, a point or a
|
|
201
|
+
* rect; targets and velocities must have the same shape). See {@link Settle}.
|
|
202
|
+
*/
|
|
203
|
+
declare function createSettle<T extends Animatable>(initial: T, config?: SettleConfig): Settle<Widen<T>>;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* How to draw a window whose rect is gliding without stretching its content.
|
|
207
|
+
*
|
|
208
|
+
* The content is laid out once at the target size and never scaled. The
|
|
209
|
+
* window's element sits at its target in the layout; to draw it at the
|
|
210
|
+
* gliding rect:
|
|
211
|
+
*
|
|
212
|
+
* - move the element by (`dx`, `dy`), so its top-left corner is the drawn rect's;
|
|
213
|
+
* - draw the frame (background, border, shadow) at `width` × `height`: the drawn size;
|
|
214
|
+
* - clip the content by `clipRight` and `clipBottom` so it fits a frame
|
|
215
|
+
* smaller than the target (CSS: `clip-path: inset(0 clipRight clipBottom 0)`).
|
|
216
|
+
*
|
|
217
|
+
* A window that shrinks shows a band of its own background closing in at the
|
|
218
|
+
* right and bottom; one that grows reveals content already laid out at its
|
|
219
|
+
* new size. Text is never stretched. One transform and one clip per frame, no
|
|
220
|
+
* layout per frame.
|
|
221
|
+
*/
|
|
222
|
+
interface RevealFrame {
|
|
223
|
+
/** Move the element (laid out at the target) right by this much. */
|
|
224
|
+
readonly dx: number;
|
|
225
|
+
/** Move the element (laid out at the target) down by this much. */
|
|
226
|
+
readonly dy: number;
|
|
227
|
+
/** The frame's width: the drawn rect's. */
|
|
228
|
+
readonly width: number;
|
|
229
|
+
/** The frame's height: the drawn rect's. */
|
|
230
|
+
readonly height: number;
|
|
231
|
+
/** Clip this much off the content's right edge (0 when the frame is at least as wide as the target). */
|
|
232
|
+
readonly clipRight: number;
|
|
233
|
+
/** Clip this much off the content's bottom edge (0 when the frame is at least as tall as the target). */
|
|
234
|
+
readonly clipBottom: number;
|
|
235
|
+
}
|
|
236
|
+
/** The {@link RevealFrame} for content laid out at `target` and drawn at `drawn`. */
|
|
237
|
+
declare function reveal(drawn: Rect, target: Rect): RevealFrame;
|
|
238
|
+
/** A uniform pop-in (or pop-out, run backwards): scale about the centre and opacity. */
|
|
239
|
+
interface PopIn {
|
|
240
|
+
/** Scale about the window's centre: the same on both axes, so nothing is stretched. */
|
|
241
|
+
readonly scale: number;
|
|
242
|
+
readonly opacity: number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Opening and closing: the window grows from `from` of its size to full, about
|
|
246
|
+
* its centre, while fading in. `progress` runs 0 to 1 (take it from a settle
|
|
247
|
+
* on a number with `{ restDelta: 0.001 }`, since the default 0.1 is tuned for
|
|
248
|
+
* pixels and would snap the last 10 %; or from a tween); closing runs it from
|
|
249
|
+
* 1 to 0. Hyprland's default is `popin 87%`.
|
|
250
|
+
*/
|
|
251
|
+
declare function popIn(progress: number, from?: number): PopIn;
|
|
252
|
+
|
|
136
253
|
/** Options of {@link motionValue}. */
|
|
137
254
|
interface MotionOptions {
|
|
138
255
|
/**
|
|
@@ -151,7 +268,7 @@ interface MotionOptions {
|
|
|
151
268
|
}
|
|
152
269
|
/** Options of {@link MotionValue.set}. */
|
|
153
270
|
interface SetOptions<T> {
|
|
154
|
-
/** Start with this velocity (units per second), e.g. a gesture's release velocity. Springs
|
|
271
|
+
/** Start with this velocity (units per second), e.g. a gesture's release velocity. Springs and settles (a settle caps it toward the target); tweens ignore it. */
|
|
155
272
|
readonly velocity?: T;
|
|
156
273
|
}
|
|
157
274
|
/**
|
|
@@ -166,9 +283,9 @@ interface MotionValue<T, A extends Animator<unknown> = Animator<T>> extends Read
|
|
|
166
283
|
readonly velocity: T;
|
|
167
284
|
/** Whether it is moving (reactive). */
|
|
168
285
|
readonly moving: boolean;
|
|
169
|
-
/** The spring or tween underneath. */
|
|
286
|
+
/** The spring, settle or tween underneath. Change it through this value (`jump`, not the animator's `hold`), so the signal and the loop follow. */
|
|
170
287
|
readonly animator: A;
|
|
171
|
-
/** Head for `target`; a spring keeps its velocity. */
|
|
288
|
+
/** Head for `target`; a spring keeps its velocity, a settle launches from where it is drawn, a tween restarts. */
|
|
172
289
|
set(target: T, options?: SetOptions<T>): void;
|
|
173
290
|
/** Put the value at `value` at once, at rest. */
|
|
174
291
|
jump(value: T): void;
|
|
@@ -195,7 +312,13 @@ type AnimatorValue<A> = A extends Animator<infer T> ? T : never;
|
|
|
195
312
|
declare function motionValue<A extends Animator<unknown>>(loop: FrameLoop, animator: A, options?: MotionOptions): MotionValue<AnimatorValue<A>, A>;
|
|
196
313
|
/** A spring-driven {@link MotionValue}: `createSpring` plus `motionValue`. */
|
|
197
314
|
declare function springValue<T extends Animatable>(loop: FrameLoop, initial: T, options?: SpringConfig & MotionOptions): MotionValue<Widen<T>, Spring<Widen<T>>>;
|
|
315
|
+
/**
|
|
316
|
+
* A settle-driven {@link MotionValue}: `createSettle` plus `motionValue`. The
|
|
317
|
+
* one curve for things moving to a new place (see {@link Settle}). To hold it
|
|
318
|
+
* to a pointer, `jump` it on each move; the next `set` launches from there.
|
|
319
|
+
*/
|
|
320
|
+
declare function settleValue<T extends Animatable>(loop: FrameLoop, initial: T, options?: SettleConfig & MotionOptions): MotionValue<Widen<T>, Settle<Widen<T>>>;
|
|
198
321
|
/** A tween-driven {@link MotionValue}: `createTween` plus `motionValue`. */
|
|
199
322
|
declare function tweenValue<T extends Animatable>(loop: FrameLoop, initial: T, options?: TweenConfig & MotionOptions): MotionValue<Widen<T>, Tween<Widen<T>>>;
|
|
200
323
|
|
|
201
|
-
export { type Animator, type AnimatorValue, type Easing, type MotionOptions, type MotionValue, SPRING_DEFAULTS, type SetOptions, type Spring, type SpringConfig, type SpringParams, type SpringState, type Tween, type TweenConfig, createSpring, createTween, cubicBezier, ease, easeIn, easeInOut, easeInOutCubic, easeOut, easeOutCubic, linear, motionValue, resolveSpring, springStep, springValue, tweenValue };
|
|
324
|
+
export { type Animator, type AnimatorValue, type Easing, type MotionOptions, type MotionValue, type PopIn, type RevealFrame, SETTLE_DEFAULTS, SETTLE_TEMPO, SPRING_DEFAULTS, type SetOptions, type Settle, type SettleConfig, type Spring, type SpringConfig, type SpringParams, type SpringState, type Tween, type TweenConfig, createSettle, createSpring, createTween, cubicBezier, ease, easeIn, easeInOut, easeInOutCubic, easeOut, easeOutCubic, linear, motionValue, popIn, resolveSpring, reveal, settleValue, springStep, springValue, tweenValue };
|
package/dist/values.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
SETTLE_DEFAULTS,
|
|
3
|
+
SETTLE_TEMPO,
|
|
2
4
|
SPRING_DEFAULTS,
|
|
5
|
+
createSettle,
|
|
3
6
|
createSpring,
|
|
4
7
|
createTween,
|
|
5
8
|
cubicBezier,
|
|
@@ -11,14 +14,20 @@ import {
|
|
|
11
14
|
easeOutCubic,
|
|
12
15
|
linear,
|
|
13
16
|
motionValue,
|
|
17
|
+
popIn,
|
|
14
18
|
resolveSpring,
|
|
19
|
+
reveal,
|
|
20
|
+
settleValue,
|
|
15
21
|
springStep,
|
|
16
22
|
springValue,
|
|
17
23
|
tweenValue
|
|
18
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-6W5KW7XQ.js";
|
|
19
25
|
import "./chunk-OOKRBVMB.js";
|
|
20
26
|
export {
|
|
27
|
+
SETTLE_DEFAULTS,
|
|
28
|
+
SETTLE_TEMPO,
|
|
21
29
|
SPRING_DEFAULTS,
|
|
30
|
+
createSettle,
|
|
22
31
|
createSpring,
|
|
23
32
|
createTween,
|
|
24
33
|
cubicBezier,
|
|
@@ -30,7 +39,10 @@ export {
|
|
|
30
39
|
easeOutCubic,
|
|
31
40
|
linear,
|
|
32
41
|
motionValue,
|
|
42
|
+
popIn,
|
|
33
43
|
resolveSpring,
|
|
44
|
+
reveal,
|
|
45
|
+
settleValue,
|
|
34
46
|
springStep,
|
|
35
47
|
springValue,
|
|
36
48
|
tweenValue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n-uf/motion",
|
|
3
|
-
"version": "26.11.
|
|
3
|
+
"version": "26.11.3",
|
|
4
4
|
"description": "One frame loop with an injected clock, fine-grained signals, springs and tweens, and a DOM-free gesture recogniser. No DOM, no framework.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"animation",
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
"types": "./dist/gestures.d.ts",
|
|
58
58
|
"default": "./dist/gestures.js"
|
|
59
59
|
},
|
|
60
|
+
"./testing": {
|
|
61
|
+
"types": "./dist/testing.d.ts",
|
|
62
|
+
"default": "./dist/testing.js"
|
|
63
|
+
},
|
|
60
64
|
"./browser": {
|
|
61
65
|
"types": "./dist/browser.d.ts",
|
|
62
66
|
"default": "./dist/browser.js"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/values/easing.ts","../src/shapes.ts","../src/values/spring.ts","../src/values/tween.ts","../src/values/motion-value.ts"],"sourcesContent":["/** Maps progress in [0, 1] to eased progress (0 at 0, 1 at 1). */\nexport type Easing = (progress: number) => number;\n\n/** No easing. */\nexport const linear: Easing = (t) => t;\n\nconst EPSILON = 1e-7;\n\n/**\n * The CSS `cubic-bezier(x1, y1, x2, y2)` curve as a function, solved\n * numerically (Newton steps, then bisection). `x1` and `x2` must be in [0, 1].\n */\nexport function cubicBezier(x1: number, y1: number, x2: number, y2: number): Easing {\n if (!(x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1)) {\n throw new RangeError(`cubicBezier: x1 and x2 must be in [0, 1], got ${x1} and ${x2}`);\n }\n if (x1 === y1 && x2 === y2) return linear;\n const cx = 3 * x1;\n const bx = 3 * (x2 - x1) - cx;\n const ax = 1 - cx - bx;\n const cy = 3 * y1;\n const by = 3 * (y2 - y1) - cy;\n const ay = 1 - cy - by;\n const sampleX = (t: number): number => ((ax * t + bx) * t + cx) * t;\n const sampleY = (t: number): number => ((ay * t + by) * t + cy) * t;\n const slopeX = (t: number): number => (3 * ax * t + 2 * bx) * t + cx;\n const solveX = (x: number): number => {\n let t = x;\n for (let i = 0; i < 8; i++) {\n const error = sampleX(t) - x;\n if (Math.abs(error) < EPSILON) return t;\n const slope = slopeX(t);\n if (Math.abs(slope) < 1e-6) break;\n t -= error / slope;\n }\n let low = 0;\n let high = 1;\n t = x;\n for (let i = 0; i < 40; i++) {\n const value = sampleX(t);\n if (Math.abs(value - x) < EPSILON) return t;\n if (x > value) low = t;\n else high = t;\n t = (low + high) / 2;\n }\n return t;\n };\n return (progress) => (progress <= 0 ? 0 : progress >= 1 ? 1 : sampleY(solveX(progress)));\n}\n\n/** CSS `ease`. */\nexport const ease: Easing = /* @__PURE__ */ cubicBezier(0.25, 0.1, 0.25, 1);\n/** CSS `ease-in`. */\nexport const easeIn: Easing = /* @__PURE__ */ cubicBezier(0.42, 0, 1, 1);\n/** CSS `ease-out`. */\nexport const easeOut: Easing = /* @__PURE__ */ cubicBezier(0, 0, 0.58, 1);\n/** CSS `ease-in-out`. */\nexport const easeInOut: Easing = /* @__PURE__ */ cubicBezier(0.42, 0, 0.58, 1);\n/** Cubic ease-out: fast start, gentle stop. The tween default. */\nexport const easeOutCubic: Easing = (t) => 1 - (1 - t) ** 3;\n/** Cubic ease-in-out. */\nexport const easeInOutCubic: Easing = (t) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2);\n","/** A point or a 2D vector. */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** An axis-aligned rectangle. */\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Any number of components. */\nexport type Vector = readonly number[];\n\n/** The value shapes springs and tweens move: plain numbers, nothing else. */\nexport type Animatable = number | Point | Rect | Vector;\n\n/** The shape type of an {@link Animatable}: literal numbers widen to `number`. */\nexport type Widen<T> = T extends number\n ? number\n : T extends Vector\n ? Vector\n : T extends Rect\n ? Rect\n : T extends Point\n ? Point\n : never;\n\nconst SCALAR = 0;\nconst VECTOR = 1;\nconst POINT = 2;\nconst RECT = 3;\n\n/** How a shape maps onto a flat list of numbers. Internal to values/. */\nexport interface Layout {\n readonly kind: typeof SCALAR | typeof VECTOR | typeof POINT | typeof RECT;\n readonly size: number;\n}\n\nconst SCALAR_LAYOUT: Layout = { kind: SCALAR, size: 1 };\nconst POINT_LAYOUT: Layout = { kind: POINT, size: 2 };\nconst RECT_LAYOUT: Layout = { kind: RECT, size: 4 };\n\nexport function layoutOf(value: Animatable): Layout {\n if (typeof value === \"number\") return SCALAR_LAYOUT;\n if (Array.isArray(value)) return { kind: VECTOR, size: value.length };\n if (\"width\" in value) return RECT_LAYOUT;\n return POINT_LAYOUT;\n}\n\nexport function sameLayout(a: Layout, b: Layout): boolean {\n return a.kind === b.kind && a.size === b.size;\n}\n\n/** Copy `value`'s components into `out`. */\nexport function writeComponents(value: Animatable, out: Float64Array): void {\n if (typeof value === \"number\") {\n out[0] = value;\n } else if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) out[i] = value[i]!;\n } else if (\"width\" in value) {\n out[0] = value.x;\n out[1] = value.y;\n out[2] = value.width;\n out[3] = value.height;\n } else {\n const point = value as Point;\n out[0] = point.x;\n out[1] = point.y;\n }\n}\n\n/** A fresh value of `layout`'s shape from `components`. */\nexport function makeValue(layout: Layout, components: Float64Array): Animatable {\n switch (layout.kind) {\n case SCALAR:\n return components[0]!;\n case POINT:\n return { x: components[0]!, y: components[1]! };\n case RECT:\n return { x: components[0]!, y: components[1]!, width: components[2]!, height: components[3]! };\n default:\n return Array.from(components);\n }\n}\n\n/** Component-wise equality of two values of the same shape. */\nexport function shapeEquals(a: Animatable, b: Animatable): boolean {\n if (typeof a === \"number\" || typeof b === \"number\") return a === b;\n if (Array.isArray(a) || Array.isArray(b)) {\n const u = a as Vector;\n const v = b as Vector;\n if (u.length !== v.length) return false;\n for (let i = 0; i < u.length; i++) if (u[i] !== v[i]) return false;\n return true;\n }\n const p = a as Partial<Rect>;\n const q = b as Partial<Rect>;\n return p.x === q.x && p.y === q.y && p.width === q.width && p.height === q.height;\n}\n","import type { Animatable, Layout, Widen } from \"../shapes\";\nimport { layoutOf, makeValue, sameLayout, writeComponents } from \"../shapes\";\nimport type { Animator } from \"./animator\";\n\n/**\n * Spring settings. Time is in milliseconds everywhere in the API; the physics\n * runs in seconds, so velocity is in units per second.\n */\nexport interface SpringConfig {\n /** Spring constant k. Higher is snappier. Default 300. */\n readonly stiffness?: number;\n /** Damping coefficient c. When set it wins over `dampingRatio`. */\n readonly damping?: number;\n /**\n * Damping as a fraction of critical damping: 1 is critical (the fastest\n * approach with no overshoot), below 1 overshoots and rings, above 1 is\n * sluggish. Default 1.\n */\n readonly dampingRatio?: number;\n /** Mass m. Default 1. */\n readonly mass?: number;\n /** Distance from the target that counts as arrived. Default 0.1 (tuned for pixels). */\n readonly restDelta?: number;\n /** Speed, in units per second, that counts as stopped. Default 1 (tuned for pixels). */\n readonly restSpeed?: number;\n}\n\n/** A {@link SpringConfig} with every field resolved. */\nexport interface SpringParams {\n readonly stiffness: number;\n readonly damping: number;\n readonly dampingRatio: number;\n readonly mass: number;\n readonly restDelta: number;\n readonly restSpeed: number;\n}\n\n/** Defaults of {@link SpringConfig}: critically damped. */\nexport const SPRING_DEFAULTS: SpringParams = {\n stiffness: 300,\n damping: 2 * Math.sqrt(300),\n dampingRatio: 1,\n mass: 1,\n restDelta: 0.1,\n restSpeed: 1,\n};\n\nfunction positive(name: string, value: number): number {\n if (!(value > 0) || !Number.isFinite(value)) throw new RangeError(`spring: ${name} must be a finite number > 0, got ${value}`);\n return value;\n}\n\n/** Resolve a {@link SpringConfig} over the defaults. Throws on a non-positive field. */\nexport function resolveSpring(config: SpringConfig = {}): SpringParams {\n const stiffness = positive(\"stiffness\", config.stiffness ?? SPRING_DEFAULTS.stiffness);\n const mass = positive(\"mass\", config.mass ?? SPRING_DEFAULTS.mass);\n const critical = 2 * Math.sqrt(stiffness * mass);\n const damping = positive(\n config.damping !== undefined ? \"damping\" : \"dampingRatio\",\n config.damping ?? (config.dampingRatio ?? SPRING_DEFAULTS.dampingRatio) * critical,\n );\n return {\n stiffness,\n damping,\n dampingRatio: damping / critical,\n mass,\n restDelta: positive(\"restDelta\", config.restDelta ?? SPRING_DEFAULTS.restDelta),\n restSpeed: positive(\"restSpeed\", config.restSpeed ?? SPRING_DEFAULTS.restSpeed),\n };\n}\n\nconst UNDERDAMPED = 0;\nconst CRITICAL = 1;\nconst OVERDAMPED = 2;\n\n/** The closed-form solution's constants for one set of params. */\ninterface Solver {\n readonly mode: typeof UNDERDAMPED | typeof CRITICAL | typeof OVERDAMPED;\n readonly omega: number;\n readonly decay: number;\n readonly omegaD: number;\n readonly r1: number;\n readonly r2: number;\n}\n\nfunction solverFor(params: SpringParams): Solver {\n const omega = Math.sqrt(params.stiffness / params.mass);\n const zeta = params.dampingRatio;\n if (Math.abs(zeta - 1) < 1e-6) return { mode: CRITICAL, omega, decay: omega, omegaD: 0, r1: 0, r2: 0 };\n if (zeta < 1) {\n return { mode: UNDERDAMPED, omega, decay: zeta * omega, omegaD: omega * Math.sqrt(1 - zeta * zeta), r1: 0, r2: 0 };\n }\n const root = Math.sqrt(zeta * zeta - 1);\n return { mode: OVERDAMPED, omega, decay: 0, omegaD: 0, r1: -omega * (zeta - root), r2: -omega * (zeta + root) };\n}\n\n/**\n * Advance one component exactly: displacement `d0` from the target and\n * velocity `v0` (per second) after `t` seconds. Writes into out[0], out[1].\n * Exact for any `t`, so the curve doesn't depend on the frame rate.\n */\nfunction advance(solver: Solver, d0: number, v0: number, t: number, out: Float64Array): void {\n if (solver.mode === CRITICAL) {\n const w = solver.omega;\n const e = Math.exp(-w * t);\n const b = v0 + w * d0;\n out[0] = e * (d0 + b * t);\n out[1] = e * (v0 - w * b * t);\n } else if (solver.mode === UNDERDAMPED) {\n const a = solver.decay;\n const wd = solver.omegaD;\n const e = Math.exp(-a * t);\n const cos = Math.cos(wd * t);\n const sin = Math.sin(wd * t);\n out[0] = e * (d0 * cos + ((v0 + a * d0) / wd) * sin);\n out[1] = e * (v0 * cos - ((a * v0 + solver.omega * solver.omega * d0) / wd) * sin);\n } else {\n const { r1, r2 } = solver;\n const c2 = (v0 - r1 * d0) / (r2 - r1);\n const c1 = d0 - c2;\n const e1 = Math.exp(r1 * t);\n const e2 = Math.exp(r2 * t);\n out[0] = c1 * e1 + c2 * e2;\n out[1] = c1 * r1 * e1 + c2 * r2 * e2;\n }\n}\n\n/** A scalar spring's position and velocity (units per second). */\nexport interface SpringState {\n readonly value: number;\n readonly velocity: number;\n}\n\n/**\n * One pure spring step for a scalar: where `state` is after `dtMs` heading for\n * `target`. Doesn't settle or snap; {@link createSpring} does that.\n */\nexport function springStep(state: SpringState, target: number, params: SpringParams, dtMs: number): SpringState {\n const out = new Float64Array(2);\n advance(solverFor(params), state.value - target, state.velocity, dtMs / 1000, out);\n return { value: target + out[0]!, velocity: out[1]! };\n}\n\n/** A spring over any {@link Animatable} shape, stepped by hand or by `motionValue`. */\nexport interface Spring<T> extends Animator<T> {\n /** The resolved settings. */\n readonly params: SpringParams;\n /** Set the velocity in units per second (a gesture's release velocity). */\n setVelocity(velocity: T): void;\n /** Change settings mid-flight; position and velocity carry on. */\n configure(config: SpringConfig): void;\n}\n\nclass SpringAnimator implements Spring<Animatable> {\n readonly layout: Layout;\n readonly x: Float64Array;\n readonly v: Float64Array;\n readonly goal: Float64Array;\n readonly scratch = new Float64Array(2);\n config: SpringConfig;\n params: SpringParams;\n solver: Solver;\n settled = true;\n cachedValue: Animatable | null = null;\n\n constructor(initial: Animatable, config: SpringConfig) {\n this.layout = layoutOf(initial);\n const size = this.layout.size;\n this.x = new Float64Array(size);\n this.v = new Float64Array(size);\n this.goal = new Float64Array(size);\n writeComponents(initial, this.x);\n writeComponents(initial, this.goal);\n this.config = config;\n this.params = resolveSpring(config);\n this.solver = solverFor(this.params);\n }\n\n get value(): Animatable {\n if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);\n return this.cachedValue;\n }\n\n get velocity(): Animatable {\n return makeValue(this.layout, this.v);\n }\n\n get target(): Animatable {\n return makeValue(this.layout, this.goal);\n }\n\n check(value: Animatable, what: string): void {\n if (!sameLayout(layoutOf(value), this.layout)) {\n throw new TypeError(`spring: ${what} has a different shape than the spring's value`);\n }\n }\n\n /** At rest exactly when on the target and not moving. */\n updateSettled(): void {\n for (let i = 0; i < this.x.length; i++) {\n if (this.x[i] !== this.goal[i] || this.v[i] !== 0) {\n this.settled = false;\n return;\n }\n }\n this.settled = true;\n }\n\n setTarget(target: Animatable): void {\n this.check(target, \"the target\");\n writeComponents(target, this.goal);\n // Position and velocity stay as they are: a retarget carries the motion on.\n this.updateSettled();\n }\n\n setVelocity(velocity: Animatable): void {\n this.check(velocity, \"the velocity\");\n writeComponents(velocity, this.v);\n this.updateSettled();\n }\n\n jumpTo(value: Animatable): void {\n this.check(value, \"the value\");\n writeComponents(value, this.x);\n writeComponents(value, this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n snap(): void {\n this.x.set(this.goal);\n this.v.fill(0);\n this.cachedValue = null;\n this.settled = true;\n }\n\n configure(config: SpringConfig): void {\n this.config = { ...this.config, ...config };\n this.params = resolveSpring(this.config);\n this.solver = solverFor(this.params);\n }\n\n step(dtMs: number): boolean {\n if (this.settled) return false;\n if (!(dtMs > 0)) return true;\n const t = dtMs / 1000;\n const { x, v, goal, scratch } = this;\n const { restDelta, restSpeed } = this.params;\n let resting = true;\n for (let i = 0; i < x.length; i++) {\n advance(this.solver, x[i]! - goal[i]!, v[i]!, t, scratch);\n x[i] = goal[i]! + scratch[0]!;\n v[i] = scratch[1]!;\n if (resting && (Math.abs(scratch[0]!) > restDelta || Math.abs(scratch[1]!) > restSpeed)) resting = false;\n }\n this.cachedValue = null;\n if (resting) this.snap();\n return !this.settled;\n }\n}\n\n/**\n * A spring starting at rest on `initial`. `initial` fixes the shape: a\n * number, a vector (array), a point `{ x, y }` or a rect `{ x, y, width,\n * height }`; targets and velocities must have the same shape.\n */\nexport function createSpring<T extends Animatable>(initial: T, config: SpringConfig = {}): Spring<Widen<T>> {\n return new SpringAnimator(initial, config) as unknown as Spring<Widen<T>>;\n}\n","import type { Animatable, Layout, Widen } from \"../shapes\";\nimport { layoutOf, makeValue, sameLayout, writeComponents } from \"../shapes\";\nimport type { Animator } from \"./animator\";\nimport { easeOutCubic, type Easing } from \"./easing\";\n\n/** Tween settings. */\nexport interface TweenConfig {\n /** Length of a run in ms. Default 250. 0 jumps to the target on the next step. */\n readonly duration?: number;\n /** Easing of the run. Default {@link easeOutCubic}. */\n readonly easing?: Easing;\n}\n\n/** A tween over any {@link Animatable} shape. */\nexport interface Tween<T> extends Animator<T> {\n /** Run progress in [0, 1]. */\n readonly progress: number;\n /** Change duration or easing; applies from the next target. */\n configure(config: TweenConfig): void;\n}\n\nclass TweenAnimator implements Tween<Animatable> {\n readonly layout: Layout;\n readonly x: Float64Array;\n readonly from: Float64Array;\n readonly goal: Float64Array;\n duration: number;\n easing: Easing;\n elapsed = 0;\n settled = true;\n cachedValue: Animatable | null = null;\n\n constructor(initial: Animatable, config: TweenConfig) {\n this.layout = layoutOf(initial);\n const size = this.layout.size;\n this.x = new Float64Array(size);\n this.from = new Float64Array(size);\n this.goal = new Float64Array(size);\n writeComponents(initial, this.x);\n writeComponents(initial, this.from);\n writeComponents(initial, this.goal);\n this.duration = 250;\n this.easing = easeOutCubic;\n this.configure(config);\n }\n\n get value(): Animatable {\n if (this.cachedValue === null) this.cachedValue = makeValue(this.layout, this.x);\n return this.cachedValue;\n }\n\n get target(): Animatable {\n return makeValue(this.layout, this.goal);\n }\n\n get progress(): number {\n if (this.settled) return 1;\n return this.duration <= 0 ? 0 : Math.min(1, this.elapsed / this.duration);\n }\n\n /** The eased curve's slope at the current progress, as units per second. */\n get velocity(): Animatable {\n const out = new Float64Array(this.layout.size);\n if (!this.settled && this.duration > 0) {\n const p = this.progress;\n const h = 1e-3;\n const lo = Math.max(0, p - h);\n const hi = Math.min(1, p + h);\n const slope = (this.easing(hi) - this.easing(lo)) / (hi - lo);\n const perSecond = (slope / this.duration) * 1000;\n for (let i = 0; i < out.length; i++) out[i] = (this.goal[i]! - this.from[i]!) * perSecond;\n }\n return makeValue(this.layout, out);\n }\n\n configure(config: TweenConfig): void {\n if (config.duration !== undefined) {\n if (!(config.duration >= 0) || !Number.isFinite(config.duration)) {\n throw new RangeError(`tween: duration must be a finite number >= 0, got ${config.duration}`);\n }\n this.duration = config.duration;\n }\n if (config.easing !== undefined) this.easing = config.easing;\n }\n\n check(value: Animatable, what: string): void {\n if (!sameLayout(layoutOf(value), this.layout)) {\n throw new TypeError(`tween: ${what} has a different shape than the tween's value`);\n }\n }\n\n setTarget(target: Animatable): void {\n this.check(target, \"the target\");\n writeComponents(target, this.goal);\n // A new run starts from wherever the value is now (no jump).\n this.from.set(this.x);\n this.elapsed = 0;\n this.settled = true;\n for (let i = 0; i < this.x.length; i++) {\n if (this.x[i] !== this.goal[i]) {\n this.settled = false;\n break;\n }\n }\n }\n\n jumpTo(value: Animatable): void {\n this.check(value, \"the value\");\n writeComponents(value, this.x);\n writeComponents(value, this.from);\n writeComponents(value, this.goal);\n this.cachedValue = null;\n this.settled = true;\n }\n\n snap(): void {\n this.x.set(this.goal);\n this.from.set(this.goal);\n this.cachedValue = null;\n this.settled = true;\n }\n\n step(dtMs: number): boolean {\n if (this.settled) return false;\n this.elapsed += Math.max(0, dtMs);\n const p = this.duration <= 0 ? 1 : Math.min(1, this.elapsed / this.duration);\n if (p >= 1) {\n this.snap();\n return false;\n }\n const eased = this.easing(p);\n for (let i = 0; i < this.x.length; i++) {\n this.x[i] = this.from[i]! + (this.goal[i]! - this.from[i]!) * eased;\n }\n this.cachedValue = null;\n return true;\n }\n}\n\n/**\n * A tween starting at rest on `initial` (same shapes as `createSpring`).\n * Velocity doesn't carry over a retarget: a new target starts a new run from\n * the current value. Use a spring where motion must stay continuous.\n */\nexport function createTween<T extends Animatable>(initial: T, config: TweenConfig = {}): Tween<Widen<T>> {\n return new TweenAnimator(initial, config) as unknown as Tween<Widen<T>>;\n}\n","import type { FrameInfo, FrameLoop, Phase } from \"../clock/frame-loop\";\nimport type { Animatable, Widen } from \"../shapes\";\nimport { shapeEquals } from \"../shapes\";\nimport { batch, effect, signal, untracked, type ReadonlySignal, type Signal } from \"../signals/signals\";\nimport type { Animator } from \"./animator\";\nimport { createSpring, type Spring, type SpringConfig } from \"./spring\";\nimport { createTween, type Tween, type TweenConfig } from \"./tween\";\n\n/** Options of {@link motionValue}. */\nexport interface MotionOptions {\n /**\n * The frame phase that steps the value. Default `\"layout\"`: it steps after\n * that phase's one-shot tasks, so a target set in input, update or layout\n * moves the value in the same frame, and `write` sees the new value.\n */\n readonly phase?: Phase;\n /**\n * The reduced-motion switch: while it is (or returns) `true`, every new\n * target is reached at once, and a value in flight snaps on its next frame.\n * A function is read on each `set` and each frame, so it can read a signal\n * or a media query.\n */\n readonly reducedMotion?: boolean | (() => boolean);\n}\n\n/** Options of {@link MotionValue.set}. */\nexport interface SetOptions<T> {\n /** Start with this velocity (units per second), e.g. a gesture's release velocity. Springs only. */\n readonly velocity?: T;\n}\n\n/**\n * An animated value on a frame loop. Reading `value` inside a computed or an\n * effect tracks it; it changes once per frame while moving and the loop goes\n * idle when it settles.\n */\nexport interface MotionValue<T, A extends Animator<unknown> = Animator<T>> extends ReadonlySignal<T> {\n /** Where the value is heading. */\n readonly target: T;\n /** The current velocity, units per second. */\n readonly velocity: T;\n /** Whether it is moving (reactive). */\n readonly moving: boolean;\n /** The spring or tween underneath. */\n readonly animator: A;\n /** Head for `target`; a spring keeps its velocity. */\n set(target: T, options?: SetOptions<T>): void;\n /** Put the value at `value` at once, at rest. */\n jump(value: T): void;\n /** Finish now: put the value on its target, at rest. */\n snap(): void;\n /**\n * Keep heading for whatever `source` returns. `source` is tracked like an\n * effect, and re-read in this value's phase at most once per frame. Returns\n * a stop function.\n */\n follow(source: () => T): () => void;\n /**\n * Call `listener` each time the value comes to rest: on the frame it\n * settles, or at once when `set` (under reduced motion), `snap` or `jump`\n * leaves it at rest. Returns an unsubscribe function.\n */\n onSettle(listener: (value: T) => void): () => void;\n /** Stop stepping, drop listeners and follows. */\n dispose(): void;\n}\n\nclass Motion<T> implements MotionValue<T> {\n readonly loop: FrameLoop;\n readonly animator: Animator<T>;\n readonly phase: Phase;\n readonly reduced: () => boolean;\n readonly current: Signal<T>;\n readonly movingSignal: Signal<boolean>;\n readonly listeners = new Set<(value: T) => void>();\n readonly follows = new Set<() => void>();\n stop: (() => void) | null = null;\n disposed = false;\n\n constructor(loop: FrameLoop, animator: Animator<T>, options: MotionOptions) {\n this.loop = loop;\n this.animator = animator;\n this.phase = options.phase ?? \"layout\";\n const reducedMotion = options.reducedMotion ?? false;\n this.reduced = typeof reducedMotion === \"function\" ? reducedMotion : () => reducedMotion;\n this.current = signal(animator.value, {\n equals: shapeEquals as (a: T, b: T) => boolean,\n });\n this.movingSignal = signal(false);\n if (!animator.settled) this.start();\n }\n\n get value(): T {\n return this.current.value;\n }\n\n peek(): T {\n return this.current.peek();\n }\n\n get target(): T {\n return this.animator.target;\n }\n\n get velocity(): T {\n return this.animator.velocity;\n }\n\n get moving(): boolean {\n return this.movingSignal.value;\n }\n\n readonly tick = (frame: FrameInfo): boolean => {\n if (this.reduced()) this.animator.snap();\n else this.animator.step(frame.delta);\n if (!this.animator.settled) {\n this.current.value = this.animator.value;\n return true;\n }\n this.stop = null;\n this.rest();\n return false;\n };\n\n start(): void {\n if (this.stop !== null || this.disposed) return;\n this.stop = this.loop.repeat(this.phase, this.tick);\n this.movingSignal.value = true;\n }\n\n halt(): void {\n if (this.stop === null) return;\n this.stop();\n this.stop = null;\n }\n\n /** Publish the resting value and tell the listeners. */\n rest(): void {\n batch(() => {\n this.current.value = this.animator.value;\n this.movingSignal.value = false;\n });\n const value = this.animator.value;\n for (const listener of Array.from(this.listeners)) listener(value);\n }\n\n set(target: T, options?: SetOptions<T>): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.setTarget(target);\n if (options?.velocity !== undefined) this.animator.setVelocity?.(options.velocity);\n if (this.reduced()) this.animator.snap();\n if (this.animator.settled) {\n this.halt();\n this.rest();\n } else {\n this.start();\n }\n });\n }\n\n jump(value: T): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.jumpTo(value);\n this.halt();\n this.rest();\n });\n }\n\n snap(): void {\n if (this.disposed) return;\n untracked(() => {\n this.animator.snap();\n this.halt();\n this.rest();\n });\n }\n\n follow(source: () => T): () => void {\n if (this.disposed) return () => {};\n const dispose = effect(\n () => {\n const target = source();\n this.set(target);\n },\n { schedule: this.loop.scheduler(this.phase) },\n );\n const stop = (): void => {\n dispose();\n this.follows.delete(stop);\n };\n this.follows.add(stop);\n return stop;\n }\n\n onSettle(listener: (value: T) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.halt();\n for (const stop of Array.from(this.follows)) stop();\n this.listeners.clear();\n this.movingSignal.value = false;\n }\n}\n\n/** The value type an animator moves. */\nexport type AnimatorValue<A> = A extends Animator<infer T> ? T : never;\n\n/** Step `animator` on `loop` while it moves, and expose it as a signal. */\nexport function motionValue<A extends Animator<unknown>>(\n loop: FrameLoop,\n animator: A,\n options: MotionOptions = {},\n): MotionValue<AnimatorValue<A>, A> {\n return new Motion(loop, animator, options) as unknown as MotionValue<AnimatorValue<A>, A>;\n}\n\n/** A spring-driven {@link MotionValue}: `createSpring` plus `motionValue`. */\nexport function springValue<T extends Animatable>(\n loop: FrameLoop,\n initial: T,\n options: SpringConfig & MotionOptions = {},\n): MotionValue<Widen<T>, Spring<Widen<T>>> {\n return motionValue(loop, createSpring(initial, options), options) as MotionValue<Widen<T>, Spring<Widen<T>>>;\n}\n\n/** A tween-driven {@link MotionValue}: `createTween` plus `motionValue`. */\nexport function tweenValue<T extends Animatable>(\n loop: FrameLoop,\n initial: T,\n options: TweenConfig & MotionOptions = {},\n): MotionValue<Widen<T>, Tween<Widen<T>>> {\n return motionValue(loop, createTween(initial, options), options) as MotionValue<Widen<T>, Tween<Widen<T>>>;\n}\n"],"mappings":"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","names":[]}
|