saccade 0.0.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,9 +27,48 @@ function App() {
27
27
 
28
28
  A floating panel appears in the corner. Use it to control speed, record, and scrub.
29
29
 
30
+ ## Slowing every animation library
31
+
32
+ Saccade slows anything driven by the standard time sources — CSS transitions,
33
+ CSS `@keyframes`, the Web Animations API, `requestAnimationFrame` loops, video
34
+ and audio, and JS libraries that read `Date.now`/`performance.now`/rAF such as
35
+ **Framer Motion**. To reach them all reliably you need two things:
36
+
37
+ ### 1. Install before your app code (recommended)
38
+
39
+ Libraries that cache a time function before saccade patches it never see
40
+ slow-mo. Because `<Saccade>` mounts inside React, its patches go in *after*
41
+ anything imported earlier. Import the side-effect entry **first** in your app
42
+ entry so the timing APIs are patched before any other module runs:
43
+
44
+ ```ts
45
+ // main.tsx — must be the first import
46
+ import 'saccade/install'
47
+
48
+ import { createRoot } from 'react-dom/client'
49
+ import { App } from './App'
50
+ // …
51
+ ```
52
+
53
+ This patches the same shared engine `<Saccade>` uses, so the panel still
54
+ controls everything. It's optional — without it, anything imported before
55
+ `<Saccade>` mounts may not slow down.
56
+
57
+ ### 2. Register GSAP (ES-module imports only)
58
+
59
+ GSAP is auto-detected when loaded as a global (UMD/CDN). When you `import` it as
60
+ an ES module, `window.gsap` is undefined, so hand saccade your instance once:
61
+
62
+ ```ts
63
+ import { gsap } from 'gsap'
64
+ import { getSharedEngine } from 'saccade'
65
+
66
+ getSharedEngine().registerGSAP(gsap)
67
+ ```
68
+
30
69
  ## Features
31
70
 
32
- - **Speed control** — Slow down or speed up all animations (CSS transitions, CSS animations, JS timers, `requestAnimationFrame`, video/audio)
71
+ - **Speed control** — Slow down or speed up all animations: CSS transitions, CSS `@keyframes`, the Web Animations API, `requestAnimationFrame`, JS timers, video/audio, GSAP, and Framer Motion
33
72
  - **Timeline recording** — Record interactions, then scrub through captured frames to inspect mid-transition states
34
73
  - **LLM export** — Copy structured animation state (properties, keyframes, easing, progress) as markdown for AI coding agents
35
74
  - **Shadow DOM isolation** — Panel styles never leak into your app
@@ -38,13 +77,14 @@ A floating panel appears in the corner. Use it to control speed, record, and scr
38
77
 
39
78
  ## How it works
40
79
 
41
- Saccade patches timing APIs (`setTimeout`, `setInterval`, `requestAnimationFrame`, `performance.now`, `Date.now`) to scale time by a configurable factor. During recording, it snapshots computed styles, attributes, and animation state every frame. In scrub mode, it replays those snapshots by applying inline styles directly to the DOM.
80
+ Saccade patches timing APIs (`setTimeout`, `setInterval`, `requestAnimationFrame`, `performance.now`, `Date.now`) to scale time by a configurable factor — this covers `requestAnimationFrame` loops and time-reading libraries like Framer Motion. CSS transitions, `@keyframes`, and Web Animations API animations are scaled via their `playbackRate`; GSAP via its global timeline `timeScale`. During recording, it snapshots computed styles, attributes, and animation state every frame. In scrub mode, it replays those snapshots by applying inline styles directly to the DOM.
42
81
 
43
82
  ## Props
44
83
 
45
84
  | Prop | Type | Default | Description |
46
85
  |------|------|---------|-------------|
47
86
  | `position` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `'bottom-left'` | Panel position |
87
+ | `engine` | `SaccadeEngine` | shared singleton | Engine the panel drives. Defaults to the process-wide shared engine, so app code (via `getSharedEngine()`) and the panel control the same instance. Pass your own only to isolate. |
48
88
 
49
89
  ## Core API
50
90
 
@@ -59,6 +99,13 @@ const engine = new SaccadeEngine()
59
99
  engine.setSpeed(0.25) // quarter speed
60
100
  engine.getSpeed()
61
101
 
102
+ // Patch timing APIs now, without changing speed (win the early-load race).
103
+ // setSpeed/startRecording also install on demand, so this is only needed up front.
104
+ engine.install()
105
+
106
+ // Register a module-imported GSAP instance (window.gsap fallback otherwise)
107
+ engine.registerGSAP(gsap)
108
+
62
109
  // Recording
63
110
  engine.startRecording()
64
111
  const capture = engine.stopRecording()
@@ -74,6 +121,22 @@ const markdown = engine.exportForLLM(500, 'active', 'standard')
74
121
  engine.destroy()
75
122
  ```
76
123
 
124
+ ### Shared engine
125
+
126
+ `new SaccadeEngine()` gives you an isolated engine. If you also render
127
+ `<Saccade>` and want app code to drive the same one the panel does, use the
128
+ process-wide singleton instead:
129
+
130
+ ```ts
131
+ import { getSharedEngine } from 'saccade' // or 'saccade/core'
132
+
133
+ const engine = getSharedEngine() // same instance <Saccade> uses by default
134
+ engine.setSpeed(0.5)
135
+ ```
136
+
137
+ `saccade/install` installs this shared engine, so importing it and calling
138
+ `getSharedEngine()` always refer to the same instance.
139
+
77
140
  ## React Hooks
78
141
 
79
142
  ```tsx