versioncam 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE.md +105 -0
  3. package/README.md +463 -0
  4. package/bin/versioncam.js +29 -0
  5. package/dist/.types-render/render-page/draw.d.ts +28 -0
  6. package/dist/.types-render/render-page/main.d.ts +24 -0
  7. package/dist/.types-render/render-page/theme.d.ts +37 -0
  8. package/dist/app-server.d.ts +59 -0
  9. package/dist/app-server.js +328 -0
  10. package/dist/app-server.js.map +1 -0
  11. package/dist/cli/app.d.ts +13 -0
  12. package/dist/cli/app.js +21 -0
  13. package/dist/cli/app.js.map +1 -0
  14. package/dist/cli/commands/check.d.ts +8 -0
  15. package/dist/cli/commands/check.js +51 -0
  16. package/dist/cli/commands/check.js.map +1 -0
  17. package/dist/cli/commands/doctor.d.ts +8 -0
  18. package/dist/cli/commands/doctor.js +130 -0
  19. package/dist/cli/commands/doctor.js.map +1 -0
  20. package/dist/cli/commands/dsl.d.ts +16 -0
  21. package/dist/cli/commands/dsl.js +22 -0
  22. package/dist/cli/commands/dsl.js.map +1 -0
  23. package/dist/cli/commands/frame.d.ts +8 -0
  24. package/dist/cli/commands/frame.js +72 -0
  25. package/dist/cli/commands/frame.js.map +1 -0
  26. package/dist/cli/commands/init.d.ts +23 -0
  27. package/dist/cli/commands/init.js +109 -0
  28. package/dist/cli/commands/init.js.map +1 -0
  29. package/dist/cli/commands/inspect.d.ts +1 -0
  30. package/dist/cli/commands/inspect.js +32 -0
  31. package/dist/cli/commands/inspect.js.map +1 -0
  32. package/dist/cli/commands/install.d.ts +33 -0
  33. package/dist/cli/commands/install.js +66 -0
  34. package/dist/cli/commands/install.js.map +1 -0
  35. package/dist/cli/commands/login.d.ts +10 -0
  36. package/dist/cli/commands/login.js +49 -0
  37. package/dist/cli/commands/login.js.map +1 -0
  38. package/dist/cli/commands/measure.d.ts +1 -0
  39. package/dist/cli/commands/measure.js +36 -0
  40. package/dist/cli/commands/measure.js.map +1 -0
  41. package/dist/cli/commands/open-app.d.ts +14 -0
  42. package/dist/cli/commands/open-app.js +45 -0
  43. package/dist/cli/commands/open-app.js.map +1 -0
  44. package/dist/cli/commands/preview.d.ts +8 -0
  45. package/dist/cli/commands/preview.js +55 -0
  46. package/dist/cli/commands/preview.js.map +1 -0
  47. package/dist/cli/commands/record.d.ts +10 -0
  48. package/dist/cli/commands/record.js +86 -0
  49. package/dist/cli/commands/record.js.map +1 -0
  50. package/dist/cli/commands/render.d.ts +1 -0
  51. package/dist/cli/commands/render.js +93 -0
  52. package/dist/cli/commands/render.js.map +1 -0
  53. package/dist/cli/commands/review.d.ts +6 -0
  54. package/dist/cli/commands/review.js +89 -0
  55. package/dist/cli/commands/review.js.map +1 -0
  56. package/dist/cli/commands/sheet.d.ts +1 -0
  57. package/dist/cli/commands/sheet.js +48 -0
  58. package/dist/cli/commands/sheet.js.map +1 -0
  59. package/dist/cli/commands/stability.d.ts +14 -0
  60. package/dist/cli/commands/stability.js +110 -0
  61. package/dist/cli/commands/stability.js.map +1 -0
  62. package/dist/cli/main.d.ts +2 -0
  63. package/dist/cli/main.js +69 -0
  64. package/dist/cli/main.js.map +1 -0
  65. package/dist/cli/usage.d.ts +10 -0
  66. package/dist/cli/usage.js +46 -0
  67. package/dist/cli/usage.js.map +1 -0
  68. package/dist/config.d.ts +250 -0
  69. package/dist/config.js +154 -0
  70. package/dist/config.js.map +1 -0
  71. package/dist/core/camera.d.ts +30 -0
  72. package/dist/core/camera.js +94 -0
  73. package/dist/core/camera.js.map +1 -0
  74. package/dist/core/compose.d.ts +38 -0
  75. package/dist/core/compose.js +81 -0
  76. package/dist/core/compose.js.map +1 -0
  77. package/dist/core/cursor.d.ts +38 -0
  78. package/dist/core/cursor.js +103 -0
  79. package/dist/core/cursor.js.map +1 -0
  80. package/dist/core/easing.d.ts +15 -0
  81. package/dist/core/easing.js +33 -0
  82. package/dist/core/easing.js.map +1 -0
  83. package/dist/core/loop.d.ts +30 -0
  84. package/dist/core/loop.js +96 -0
  85. package/dist/core/loop.js.map +1 -0
  86. package/dist/core/motion-defaults.d.ts +61 -0
  87. package/dist/core/motion-defaults.js +62 -0
  88. package/dist/core/motion-defaults.js.map +1 -0
  89. package/dist/core/rng.d.ts +13 -0
  90. package/dist/core/rng.js +27 -0
  91. package/dist/core/rng.js.map +1 -0
  92. package/dist/core/sse.d.ts +15 -0
  93. package/dist/core/sse.js +16 -0
  94. package/dist/core/sse.js.map +1 -0
  95. package/dist/core/timeline.d.ts +146 -0
  96. package/dist/core/timeline.js +81 -0
  97. package/dist/core/timeline.js.map +1 -0
  98. package/dist/core/timing.d.ts +31 -0
  99. package/dist/core/timing.js +29 -0
  100. package/dist/core/timing.js.map +1 -0
  101. package/dist/core/typing.d.ts +12 -0
  102. package/dist/core/typing.js +35 -0
  103. package/dist/core/typing.js.map +1 -0
  104. package/dist/driver/clip.d.ts +71 -0
  105. package/dist/driver/clip.js +120 -0
  106. package/dist/driver/clip.js.map +1 -0
  107. package/dist/driver/compare.d.ts +34 -0
  108. package/dist/driver/compare.js +40 -0
  109. package/dist/driver/compare.js.map +1 -0
  110. package/dist/driver/gate.d.ts +36 -0
  111. package/dist/driver/gate.js +27 -0
  112. package/dist/driver/gate.js.map +1 -0
  113. package/dist/driver/launch.d.ts +43 -0
  114. package/dist/driver/launch.js +47 -0
  115. package/dist/driver/launch.js.map +1 -0
  116. package/dist/driver/page-hooks.d.ts +72 -0
  117. package/dist/driver/page-hooks.js +129 -0
  118. package/dist/driver/page-hooks.js.map +1 -0
  119. package/dist/driver/reports.d.ts +34 -0
  120. package/dist/driver/reports.js +42 -0
  121. package/dist/driver/reports.js.map +1 -0
  122. package/dist/driver/session.d.ts +285 -0
  123. package/dist/driver/session.js +773 -0
  124. package/dist/driver/session.js.map +1 -0
  125. package/dist/driver/settle.d.ts +41 -0
  126. package/dist/driver/settle.js +82 -0
  127. package/dist/driver/settle.js.map +1 -0
  128. package/dist/env.d.ts +11 -0
  129. package/dist/env.js +41 -0
  130. package/dist/env.js.map +1 -0
  131. package/dist/fixtures.d.ts +13 -0
  132. package/dist/fixtures.js +13 -0
  133. package/dist/fixtures.js.map +1 -0
  134. package/dist/index.d.ts +30 -0
  135. package/dist/index.js +16 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/inspect/inspect.d.ts +70 -0
  138. package/dist/inspect/inspect.js +176 -0
  139. package/dist/inspect/inspect.js.map +1 -0
  140. package/dist/inspect/measure.d.ts +40 -0
  141. package/dist/inspect/measure.js +107 -0
  142. package/dist/inspect/measure.js.map +1 -0
  143. package/dist/loader.d.ts +28 -0
  144. package/dist/loader.js +143 -0
  145. package/dist/loader.js.map +1 -0
  146. package/dist/page/assets/index-DUom5amc.js +1 -0
  147. package/dist/page/index.html +18 -0
  148. package/dist/render/encode.d.ts +40 -0
  149. package/dist/render/encode.js +183 -0
  150. package/dist/render/encode.js.map +1 -0
  151. package/dist/render/ffmpeg.d.ts +13 -0
  152. package/dist/render/ffmpeg.js +72 -0
  153. package/dist/render/ffmpeg.js.map +1 -0
  154. package/dist/render/presentation.d.ts +19 -0
  155. package/dist/render/presentation.js +27 -0
  156. package/dist/render/presentation.js.map +1 -0
  157. package/dist/render/render.d.ts +59 -0
  158. package/dist/render/render.js +144 -0
  159. package/dist/render/render.js.map +1 -0
  160. package/dist/render/sampling.d.ts +47 -0
  161. package/dist/render/sampling.js +129 -0
  162. package/dist/render/sampling.js.map +1 -0
  163. package/dist/render/sequence.d.ts +24 -0
  164. package/dist/render/sequence.js +105 -0
  165. package/dist/render/sequence.js.map +1 -0
  166. package/dist/render/serve.d.ts +35 -0
  167. package/dist/render/serve.js +124 -0
  168. package/dist/render/serve.js.map +1 -0
  169. package/dist/review/review.d.ts +54 -0
  170. package/dist/review/review.js +229 -0
  171. package/dist/review/review.js.map +1 -0
  172. package/dist/scene.d.ts +23 -0
  173. package/dist/scene.js +2 -0
  174. package/dist/scene.js.map +1 -0
  175. package/dsl.md +119 -0
  176. package/package.json +76 -0
  177. package/plugin/.claude-plugin/plugin.json +9 -0
  178. package/plugin/README.md +105 -0
  179. package/plugin/agents/versioncam-reviewer.md +63 -0
  180. package/plugin/skills/versioncam/SKILL.md +235 -0
  181. package/plugin/skills/versioncam/authoring.md +226 -0
  182. package/plugin/skills/versioncam/onboarding.md +199 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { CameraKey, Rect } from "./timeline.js";
2
+ export type Viewport = {
3
+ width: number;
4
+ height: number;
5
+ };
6
+ export type ZoomOptions = {
7
+ /** Padding around the target, as a fraction of its size. */
8
+ pad?: number;
9
+ /**
10
+ * Hard ceiling on magnification. Above the ratio of capture DPR to output
11
+ * scale the image is being upscaled, and the whole point of capturing at
12
+ * DPR 2 is that a zoom stays sharp.
13
+ */
14
+ maxScale?: number;
15
+ };
16
+ export declare function clampRect(rect: Rect, viewport: Viewport): Rect;
17
+ /**
18
+ * The camera rectangle that frames `target`: padded, fitted to the viewport's
19
+ * aspect (the output frame has the viewport's shape, so anything else would
20
+ * letterbox), capped in magnification, and kept inside the captured area.
21
+ */
22
+ export declare function zoomRect(target: Rect, viewport: Viewport, options?: ZoomOptions): Rect;
23
+ /** The magnification a camera rectangle represents. */
24
+ export declare function scaleOf(rect: Rect, viewport: Viewport): number;
25
+ /**
26
+ * Where the camera is at time `t`. A key's `ease` describes how the camera
27
+ * reaches it from the previous key: `minjerk` glides, `hold` stays put and
28
+ * then cuts.
29
+ */
30
+ export declare function evalCamera(keys: CameraKey[], t: number): Rect;
@@ -0,0 +1,94 @@
1
+ import { clamp, lerp, minjerk } from "./easing.js";
2
+ const DEFAULT_PAD = 0.12;
3
+ const DEFAULT_MAX_SCALE = 1.65;
4
+ export function clampRect(rect, viewport) {
5
+ const w = Math.min(rect.w, viewport.width);
6
+ const h = Math.min(rect.h, viewport.height);
7
+ return {
8
+ x: clamp(rect.x, 0, viewport.width - w),
9
+ y: clamp(rect.y, 0, viewport.height - h),
10
+ w,
11
+ h,
12
+ };
13
+ }
14
+ /**
15
+ * The camera rectangle that frames `target`: padded, fitted to the viewport's
16
+ * aspect (the output frame has the viewport's shape, so anything else would
17
+ * letterbox), capped in magnification, and kept inside the captured area.
18
+ */
19
+ export function zoomRect(target, viewport, options = {}) {
20
+ const pad = options.pad ?? DEFAULT_PAD;
21
+ const maxScale = options.maxScale ?? DEFAULT_MAX_SCALE;
22
+ const aspect = viewport.width / viewport.height;
23
+ const centerX = target.x + target.w / 2;
24
+ const centerY = target.y + target.h / 2;
25
+ let w = target.w * (1 + 2 * pad);
26
+ let h = target.h * (1 + 2 * pad);
27
+ // Grow the deficient axis rather than shrinking the other, so the target
28
+ // never gets cropped by the aspect fit.
29
+ if (w / h < aspect)
30
+ w = h * aspect;
31
+ else
32
+ h = w / aspect;
33
+ const minWidth = viewport.width / maxScale;
34
+ if (w < minWidth) {
35
+ w = minWidth;
36
+ h = w / aspect;
37
+ }
38
+ if (w > viewport.width) {
39
+ w = viewport.width;
40
+ h = viewport.height;
41
+ }
42
+ return clampRect({ x: centerX - w / 2, y: centerY - h / 2, w, h }, viewport);
43
+ }
44
+ /** The magnification a camera rectangle represents. */
45
+ export function scaleOf(rect, viewport) {
46
+ return viewport.width / rect.w;
47
+ }
48
+ /**
49
+ * Interpolate one camera framing towards another.
50
+ *
51
+ * The size moves geometrically and the centre linearly. Interpolating width
52
+ * linearly is the usual reason a zoom feels wrong: going from 1440 wide to 780
53
+ * wide, the first half of the move changes the magnification by 1.22x and the
54
+ * second half by 1.51x, so a zoom that is mathematically even reads as rushing
55
+ * into the target and then crawling. In log space each equal step multiplies
56
+ * the scale by the same factor, which is what the eye actually reads as
57
+ * constant speed.
58
+ */
59
+ function interpolateRect(a, b, u) {
60
+ const cxA = a.x + a.w / 2;
61
+ const cyA = a.y + a.h / 2;
62
+ const cxB = b.x + b.w / 2;
63
+ const cyB = b.y + b.h / 2;
64
+ const w = a.w * Math.pow(b.w / a.w, u);
65
+ const h = a.h * Math.pow(b.h / a.h, u);
66
+ const cx = lerp(cxA, cxB, u);
67
+ const cy = lerp(cyA, cyB, u);
68
+ return { x: cx - w / 2, y: cy - h / 2, w, h };
69
+ }
70
+ /**
71
+ * Where the camera is at time `t`. A key's `ease` describes how the camera
72
+ * reaches it from the previous key: `minjerk` glides, `hold` stays put and
73
+ * then cuts.
74
+ */
75
+ export function evalCamera(keys, t) {
76
+ if (keys.length === 0) {
77
+ throw new Error("evalCamera called with no keys");
78
+ }
79
+ if (t <= keys[0].t)
80
+ return keys[0].rect;
81
+ for (let i = 1; i < keys.length; i += 1) {
82
+ const prev = keys[i - 1];
83
+ const next = keys[i];
84
+ if (t >= next.t)
85
+ continue;
86
+ if (next.ease === "hold")
87
+ return prev.rect;
88
+ const span = next.t - prev.t;
89
+ const u = span <= 0 ? 1 : (t - prev.t) / span;
90
+ return interpolateRect(prev.rect, next.rect, minjerk(u));
91
+ }
92
+ return keys[keys.length - 1].rect;
93
+ }
94
+ //# sourceMappingURL=camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/core/camera.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Rect, Vec2 } from "./timeline.js";
2
+ /**
3
+ * Mapping from the captured page into the output frame.
4
+ *
5
+ * Three spaces are in play and confusing them is the easiest way to get a
6
+ * cursor that drifts away from what it is clicking:
7
+ *
8
+ * - **viewport space** — CSS pixels, what the timeline stores.
9
+ * - **state space** — pixels inside a captured PNG: viewport × dpr.
10
+ * - **output space** — pixels in the rendered video frame.
11
+ *
12
+ * `camera` is a rectangle in viewport space; `frameArea` is where the app
13
+ * image is drawn in output space. Everything else follows from those two.
14
+ */
15
+ export declare function sourceToOutput(point: Vec2, camera: Rect, frameArea: Rect): Vec2;
16
+ export declare function rectToOutput(rect: Rect, camera: Rect, frameArea: Rect): Rect;
17
+ /** The source rectangle to read out of a state image, in state pixels. */
18
+ export declare function cameraToStatePixels(camera: Rect, dpr: number): Rect;
19
+ /**
20
+ * Fit a viewport-shaped image into `canvas` with `padding` (a fraction of the
21
+ * smaller canvas dimension) around it. This is the rounded "device frame" the
22
+ * app sits in.
23
+ */
24
+ export declare function fitFrameArea(canvas: {
25
+ width: number;
26
+ height: number;
27
+ }, viewport: {
28
+ width: number;
29
+ height: number;
30
+ }, padding: number): Rect;
31
+ /**
32
+ * Opacity of the *new* state during a crossfade that starts at `cutFrame` and
33
+ * lasts `length` frames. Frame `cutFrame` itself is already partly faded, so
34
+ * a cut never shows a duplicated still.
35
+ */
36
+ export declare function crossfadeAlpha(frame: number, cutFrame: number, length: number): number;
37
+ /** Linear fade in/out envelope, in seconds, for captions and highlights. */
38
+ export declare function fadeEnvelope(t: number, t0: number, t1: number, fade: number): number;
@@ -0,0 +1,81 @@
1
+ import { clamp01 } from "./easing.js";
2
+ /**
3
+ * Mapping from the captured page into the output frame.
4
+ *
5
+ * Three spaces are in play and confusing them is the easiest way to get a
6
+ * cursor that drifts away from what it is clicking:
7
+ *
8
+ * - **viewport space** — CSS pixels, what the timeline stores.
9
+ * - **state space** — pixels inside a captured PNG: viewport × dpr.
10
+ * - **output space** — pixels in the rendered video frame.
11
+ *
12
+ * `camera` is a rectangle in viewport space; `frameArea` is where the app
13
+ * image is drawn in output space. Everything else follows from those two.
14
+ */
15
+ export function sourceToOutput(point, camera, frameArea) {
16
+ const scale = frameArea.w / camera.w;
17
+ return [
18
+ frameArea.x + (point[0] - camera.x) * scale,
19
+ frameArea.y + (point[1] - camera.y) * scale,
20
+ ];
21
+ }
22
+ export function rectToOutput(rect, camera, frameArea) {
23
+ const scale = frameArea.w / camera.w;
24
+ return {
25
+ x: frameArea.x + (rect.x - camera.x) * scale,
26
+ y: frameArea.y + (rect.y - camera.y) * scale,
27
+ w: rect.w * scale,
28
+ h: rect.h * scale,
29
+ };
30
+ }
31
+ /** The source rectangle to read out of a state image, in state pixels. */
32
+ export function cameraToStatePixels(camera, dpr) {
33
+ return {
34
+ x: camera.x * dpr,
35
+ y: camera.y * dpr,
36
+ w: camera.w * dpr,
37
+ h: camera.h * dpr,
38
+ };
39
+ }
40
+ /**
41
+ * Fit a viewport-shaped image into `canvas` with `padding` (a fraction of the
42
+ * smaller canvas dimension) around it. This is the rounded "device frame" the
43
+ * app sits in.
44
+ */
45
+ export function fitFrameArea(canvas, viewport, padding) {
46
+ const inset = Math.min(canvas.width, canvas.height) * padding;
47
+ const availableW = canvas.width - inset * 2;
48
+ const availableH = canvas.height - inset * 2;
49
+ const aspect = viewport.width / viewport.height;
50
+ let w = availableW;
51
+ let h = w / aspect;
52
+ if (h > availableH) {
53
+ h = availableH;
54
+ w = h * aspect;
55
+ }
56
+ return {
57
+ x: (canvas.width - w) / 2,
58
+ y: (canvas.height - h) / 2,
59
+ w,
60
+ h,
61
+ };
62
+ }
63
+ /**
64
+ * Opacity of the *new* state during a crossfade that starts at `cutFrame` and
65
+ * lasts `length` frames. Frame `cutFrame` itself is already partly faded, so
66
+ * a cut never shows a duplicated still.
67
+ */
68
+ export function crossfadeAlpha(frame, cutFrame, length) {
69
+ if (length <= 0)
70
+ return 1;
71
+ return clamp01((frame - cutFrame + 1) / length);
72
+ }
73
+ /** Linear fade in/out envelope, in seconds, for captions and highlights. */
74
+ export function fadeEnvelope(t, t0, t1, fade) {
75
+ if (t <= t0 || t >= t1)
76
+ return 0;
77
+ if (fade <= 0)
78
+ return 1;
79
+ return Math.min(clamp01((t - t0) / fade), clamp01((t1 - t) / fade));
80
+ }
81
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { CursorTrack, Rect, Vec2 } from "./timeline.js";
2
+ import type { CursorSegment } from "./timeline.js";
3
+ /** Straight-line distance between two points. */
4
+ export declare function distance(a: Vec2, b: Vec2): number;
5
+ /**
6
+ * Fitts's law, loosely: a move takes longer the further it goes and the
7
+ * smaller the thing it is aiming at. Without this every move takes the same
8
+ * time and the cursor reads as a machine — a nudge to an adjacent button
9
+ * should not take as long as a sweep across the window.
10
+ *
11
+ * Returns milliseconds.
12
+ */
13
+ export declare function moveDuration(dist: number, targetSize: number): number;
14
+ /**
15
+ * Where inside a box to aim. Dead centre every time is another machine tell,
16
+ * so land within the middle ~quarter but never exactly on the middle.
17
+ */
18
+ export declare function targetPoint(box: Rect, rng: () => number): Vec2;
19
+ export type PlanMoveOptions = {
20
+ /** Smallest dimension of the target, for the Fitts term. */
21
+ targetSize?: number;
22
+ /** Override the computed duration, in milliseconds. */
23
+ duration?: number;
24
+ };
25
+ /**
26
+ * A single move, as a quadratic Bézier with a slight perpendicular bow.
27
+ * People do not move a mouse in straight lines; a small arc is the cheapest
28
+ * convincing correction, and its direction alternates by seed so repeated
29
+ * moves along the same axis do not all curve the same way.
30
+ */
31
+ export declare function planMove(from: Vec2, to: Vec2, t0: number, rng: () => number, options?: PlanMoveOptions): CursorSegment;
32
+ /**
33
+ * Where the cursor is at time `t`. Before the track starts it sits at the
34
+ * first known position; after it ends, at the last.
35
+ */
36
+ export declare function evalCursor(track: CursorTrack, t: number): Vec2;
37
+ /** Where the cursor ends up once the whole track has played. */
38
+ export declare function cursorEnd(track: CursorTrack, fallback: Vec2): Vec2;
@@ -0,0 +1,103 @@
1
+ import { clamp, minjerk } from "./easing.js";
2
+ import { jitter } from "./rng.js";
3
+ /** Straight-line distance between two points. */
4
+ export function distance(a, b) {
5
+ return Math.hypot(b[0] - a[0], b[1] - a[1]);
6
+ }
7
+ /**
8
+ * Fitts's law, loosely: a move takes longer the further it goes and the
9
+ * smaller the thing it is aiming at. Without this every move takes the same
10
+ * time and the cursor reads as a machine — a nudge to an adjacent button
11
+ * should not take as long as a sweep across the window.
12
+ *
13
+ * Returns milliseconds.
14
+ */
15
+ export function moveDuration(dist, targetSize) {
16
+ const size = Math.max(targetSize, MIN_TARGET_SIZE);
17
+ const raw = 250 + 120 * Math.log2(dist / size + 1);
18
+ return clamp(raw, 300, 900);
19
+ }
20
+ const MIN_TARGET_SIZE = 24;
21
+ const ARC_MIN = 0.05;
22
+ const ARC_MAX = 0.1;
23
+ /**
24
+ * Where inside a box to aim. Dead centre every time is another machine tell,
25
+ * so land within the middle ~quarter but never exactly on the middle.
26
+ */
27
+ export function targetPoint(box, rng) {
28
+ return [
29
+ box.x + box.w / 2 + jitter(rng, 0.12 * box.w),
30
+ box.y + box.h / 2 + jitter(rng, 0.12 * box.h),
31
+ ];
32
+ }
33
+ /**
34
+ * A single move, as a quadratic Bézier with a slight perpendicular bow.
35
+ * People do not move a mouse in straight lines; a small arc is the cheapest
36
+ * convincing correction, and its direction alternates by seed so repeated
37
+ * moves along the same axis do not all curve the same way.
38
+ */
39
+ export function planMove(from, to, t0, rng, options = {}) {
40
+ const dist = distance(from, to);
41
+ const durationMs = options.duration ??
42
+ moveDuration(dist, options.targetSize ?? MIN_TARGET_SIZE);
43
+ const mid = [(from[0] + to[0]) / 2, (from[1] + to[1]) / 2];
44
+ let ctrl = mid;
45
+ if (dist > 0) {
46
+ const arc = ARC_MIN + rng() * (ARC_MAX - ARC_MIN);
47
+ const sign = rng() < 0.5 ? -1 : 1;
48
+ // Unit normal to the travel direction.
49
+ const nx = -(to[1] - from[1]) / dist;
50
+ const ny = (to[0] - from[0]) / dist;
51
+ const offset = dist * arc * sign;
52
+ ctrl = [mid[0] + nx * offset, mid[1] + ny * offset];
53
+ }
54
+ return {
55
+ kind: "move",
56
+ t0,
57
+ t1: t0 + durationMs / 1000,
58
+ from,
59
+ to,
60
+ ctrl,
61
+ ease: "minjerk",
62
+ };
63
+ }
64
+ function bezier(from, ctrl, to, u) {
65
+ const inv = 1 - u;
66
+ const a = inv * inv;
67
+ const b = 2 * inv * u;
68
+ const c = u * u;
69
+ return [
70
+ a * from[0] + b * ctrl[0] + c * to[0],
71
+ a * from[1] + b * ctrl[1] + c * to[1],
72
+ ];
73
+ }
74
+ /**
75
+ * Where the cursor is at time `t`. Before the track starts it sits at the
76
+ * first known position; after it ends, at the last.
77
+ */
78
+ export function evalCursor(track, t) {
79
+ if (track.length === 0)
80
+ return [0, 0];
81
+ const first = track[0];
82
+ if (t <= first.t0)
83
+ return first.kind === "move" ? first.from : first.at;
84
+ for (const step of track) {
85
+ if (t > step.t1)
86
+ continue;
87
+ if (step.kind === "hold")
88
+ return step.at;
89
+ const span = step.t1 - step.t0;
90
+ const u = span <= 0 ? 1 : (t - step.t0) / span;
91
+ return bezier(step.from, step.ctrl, step.to, minjerk(u));
92
+ }
93
+ const last = track[track.length - 1];
94
+ return last.kind === "move" ? last.to : last.at;
95
+ }
96
+ /** Where the cursor ends up once the whole track has played. */
97
+ export function cursorEnd(track, fallback) {
98
+ if (track.length === 0)
99
+ return fallback;
100
+ const last = track[track.length - 1];
101
+ return last.kind === "move" ? last.to : last.at;
102
+ }
103
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/core/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Minimum-jerk: the standard model of a human reaching movement.
3
+ *
4
+ * x(u) = 10u³ − 15u⁴ + 6u⁵
5
+ *
6
+ * Its first *and* second derivatives vanish at both ends, so motion starts
7
+ * and stops without a visible corner. This is the difference between a cursor
8
+ * that looks like a person moved it and one that looks like a tween — and the
9
+ * reason the recorder does not use CSS-style cubic-bezier easings, whose
10
+ * acceleration is discontinuous at the endpoints.
11
+ */
12
+ export declare function minjerk(u: number): number;
13
+ export declare function clamp01(u: number): number;
14
+ export declare function clamp(value: number, min: number, max: number): number;
15
+ export declare function lerp(a: number, b: number, u: number): number;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Minimum-jerk: the standard model of a human reaching movement.
3
+ *
4
+ * x(u) = 10u³ − 15u⁴ + 6u⁵
5
+ *
6
+ * Its first *and* second derivatives vanish at both ends, so motion starts
7
+ * and stops without a visible corner. This is the difference between a cursor
8
+ * that looks like a person moved it and one that looks like a tween — and the
9
+ * reason the recorder does not use CSS-style cubic-bezier easings, whose
10
+ * acceleration is discontinuous at the endpoints.
11
+ */
12
+ export function minjerk(u) {
13
+ const c = clamp01(u);
14
+ return c * c * c * (10 + c * (-15 + 6 * c));
15
+ }
16
+ export function clamp01(u) {
17
+ if (u <= 0)
18
+ return 0;
19
+ if (u >= 1)
20
+ return 1;
21
+ return u;
22
+ }
23
+ export function clamp(value, min, max) {
24
+ if (value <= min)
25
+ return min;
26
+ if (value >= max)
27
+ return max;
28
+ return value;
29
+ }
30
+ export function lerp(a, b, u) {
31
+ return a + (b - a) * u;
32
+ }
33
+ //# sourceMappingURL=easing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"easing.js","sourceRoot":"","sources":["../../src/core/easing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IAC3D,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAC7B,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAClD,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Rect, Vec2 } from "./timeline.js";
2
+ /**
3
+ * A lasso stroke. Authored as a handful of points and smoothed into a closed
4
+ * loop, because a polygon drawn by hand has no straight edges and no corners
5
+ * — a four-point polygon played back verbatim looks like a selection
6
+ * rectangle, not a lasso.
7
+ */
8
+ /**
9
+ * Uniform closed Catmull-Rom through `points`. The curve passes through every
10
+ * control point, which is what makes authoring by fractions predictable.
11
+ */
12
+ export declare function catmullRomClosed(points: Vec2[], samplesPerSegment: number): Vec2[];
13
+ export type LoopPlanner = (box: Rect, rng: () => number) => Vec2[];
14
+ export type LoopOptions = {
15
+ samplesPerSegment?: number;
16
+ /** Radial wobble as a fraction of the box size. */
17
+ jitter?: number;
18
+ };
19
+ /**
20
+ * Author a lasso as fractions of the target's box, so the same stroke lands
21
+ * on the same part of the map after a layout change.
22
+ */
23
+ export declare function loop(fractions: readonly (readonly [number, number])[], options?: LoopOptions): LoopPlanner;
24
+ /**
25
+ * Resample a path so consecutive points are equally spaced, then walk it with
26
+ * an easing. A raw Catmull-Rom is parameterised by segment, not by distance,
27
+ * so playing it back directly speeds up and slows down at every control
28
+ * point — visible as a stutter in the stroke.
29
+ */
30
+ export declare function resampleByArcLength(path: Vec2[], count: number): Vec2[];
@@ -0,0 +1,96 @@
1
+ import { jitter } from "./rng.js";
2
+ /**
3
+ * A lasso stroke. Authored as a handful of points and smoothed into a closed
4
+ * loop, because a polygon drawn by hand has no straight edges and no corners
5
+ * — a four-point polygon played back verbatim looks like a selection
6
+ * rectangle, not a lasso.
7
+ */
8
+ /**
9
+ * Uniform closed Catmull-Rom through `points`. The curve passes through every
10
+ * control point, which is what makes authoring by fractions predictable.
11
+ */
12
+ export function catmullRomClosed(points, samplesPerSegment) {
13
+ if (points.length < 3)
14
+ return [...points];
15
+ const out = [];
16
+ const n = points.length;
17
+ for (let i = 0; i < n; i += 1) {
18
+ const p0 = points[(i - 1 + n) % n];
19
+ const p1 = points[i];
20
+ const p2 = points[(i + 1) % n];
21
+ const p3 = points[(i + 2) % n];
22
+ for (let s = 0; s < samplesPerSegment; s += 1) {
23
+ const t = s / samplesPerSegment;
24
+ const t2 = t * t;
25
+ const t3 = t2 * t;
26
+ out.push([
27
+ 0.5 *
28
+ (2 * p1[0] +
29
+ (-p0[0] + p2[0]) * t +
30
+ (2 * p0[0] - 5 * p1[0] + 4 * p2[0] - p3[0]) * t2 +
31
+ (-p0[0] + 3 * p1[0] - 3 * p2[0] + p3[0]) * t3),
32
+ 0.5 *
33
+ (2 * p1[1] +
34
+ (-p0[1] + p2[1]) * t +
35
+ (2 * p0[1] - 5 * p1[1] + 4 * p2[1] - p3[1]) * t2 +
36
+ (-p0[1] + 3 * p1[1] - 3 * p2[1] + p3[1]) * t3),
37
+ ]);
38
+ }
39
+ }
40
+ // Close the ring explicitly so callers can draw it without special-casing.
41
+ out.push(out[0]);
42
+ return out;
43
+ }
44
+ /**
45
+ * Author a lasso as fractions of the target's box, so the same stroke lands
46
+ * on the same part of the map after a layout change.
47
+ */
48
+ export function loop(fractions, options = {}) {
49
+ const samplesPerSegment = options.samplesPerSegment ?? 16;
50
+ const wobble = options.jitter ?? 0.01;
51
+ return (box, rng) => {
52
+ const points = fractions.map(([fx, fy]) => [
53
+ box.x + fx * box.w + jitter(rng, wobble * box.w),
54
+ box.y + fy * box.h + jitter(rng, wobble * box.h),
55
+ ]);
56
+ return catmullRomClosed(points, samplesPerSegment);
57
+ };
58
+ }
59
+ /**
60
+ * Resample a path so consecutive points are equally spaced, then walk it with
61
+ * an easing. A raw Catmull-Rom is parameterised by segment, not by distance,
62
+ * so playing it back directly speeds up and slows down at every control
63
+ * point — visible as a stutter in the stroke.
64
+ */
65
+ export function resampleByArcLength(path, count) {
66
+ if (path.length === 0)
67
+ return [];
68
+ if (count <= 1)
69
+ return [path[0]];
70
+ const cumulative = [0];
71
+ for (let i = 1; i < path.length; i += 1) {
72
+ const dx = path[i][0] - path[i - 1][0];
73
+ const dy = path[i][1] - path[i - 1][1];
74
+ cumulative.push(cumulative[i - 1] + Math.hypot(dx, dy));
75
+ }
76
+ const total = cumulative[cumulative.length - 1];
77
+ if (total === 0)
78
+ return new Array(count).fill(path[0]);
79
+ const out = [];
80
+ let cursor = 1;
81
+ for (let i = 0; i < count; i += 1) {
82
+ const target = (i / (count - 1)) * total;
83
+ while (cursor < cumulative.length - 1 && cumulative[cursor] < target) {
84
+ cursor += 1;
85
+ }
86
+ const spanStart = cumulative[cursor - 1];
87
+ const spanEnd = cumulative[cursor];
88
+ const span = spanEnd - spanStart;
89
+ const u = span <= 0 ? 0 : (target - spanStart) / span;
90
+ const a = path[cursor - 1];
91
+ const b = path[cursor];
92
+ out.push([a[0] + (b[0] - a[0]) * u, a[1] + (b[1] - a[1]) * u]);
93
+ }
94
+ return out;
95
+ }
96
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/core/loop.ts"],"names":[],"mappings":"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"}