hyperframes 0.3.0 → 0.3.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 (33) hide show
  1. package/dist/cli.js +7152 -6407
  2. package/dist/docs/{templates.md → examples.md} +2 -2
  3. package/dist/skills/gsap/SKILL.md +5 -16
  4. package/dist/skills/gsap/references/effects.md +7 -14
  5. package/dist/skills/hyperframes/SKILL.md +124 -43
  6. package/dist/skills/hyperframes/house-style.md +34 -93
  7. package/dist/skills/hyperframes/references/captions.md +2 -2
  8. package/dist/skills/hyperframes/references/css-patterns.md +36 -34
  9. package/dist/skills/hyperframes/references/transitions/catalog.md +4 -19
  10. package/dist/skills/hyperframes/references/transitions/css-other.md +0 -11
  11. package/dist/skills/hyperframes/references/transitions.md +53 -37
  12. package/dist/skills/hyperframes/references/{fonts.md → typography.md} +73 -32
  13. package/dist/skills/hyperframes/scripts/animation-map.mjs +596 -0
  14. package/dist/skills/hyperframes/scripts/contrast-report.mjs +335 -0
  15. package/dist/skills/hyperframes-cli/SKILL.md +1 -1
  16. package/dist/studio/assets/hyperframes-player-eEkqo7g7.js +198 -0
  17. package/dist/studio/assets/index-DZEa45DQ.css +1 -0
  18. package/dist/studio/assets/{index-QlToZFln.js → index-Pn53dCTs.js} +21 -21
  19. package/dist/studio/index.html +2 -2
  20. package/dist/templates/_shared/AGENTS.md +59 -0
  21. package/dist/templates/_shared/CLAUDE.md +7 -7
  22. package/package.json +1 -1
  23. package/dist/skills/gsap/references/frameworks.md +0 -56
  24. package/dist/skills/gsap/references/plugins.md +0 -194
  25. package/dist/skills/gsap/references/react.md +0 -80
  26. package/dist/skills/gsap/references/scrolltrigger.md +0 -147
  27. package/dist/skills/gsap/references/utils.md +0 -91
  28. package/dist/skills/hyperframes/references/examples.md +0 -146
  29. package/dist/skills/hyperframes/references/marker-highlight.md +0 -158
  30. package/dist/skills/hyperframes/references/transitions/shader-setup.md +0 -463
  31. package/dist/skills/hyperframes/references/transitions/shader-transitions.md +0 -329
  32. package/dist/studio/assets/hyperframes-player-Ba4c3ztZ.js +0 -198
  33. package/dist/studio/assets/index-DHr9yo58.css +0 -1
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>HyperFrames Studio</title>
7
- <script type="module" crossorigin src="/assets/index-QlToZFln.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-DHr9yo58.css">
7
+ <script type="module" crossorigin src="/assets/index-Pn53dCTs.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-DZEa45DQ.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -0,0 +1,59 @@
1
+ # HyperFrames Composition Project
2
+
3
+ ## Skills
4
+
5
+ This project uses AI agent skills for framework-specific patterns. Install them if not already present:
6
+
7
+ ```bash
8
+ npx skills add heygen-com/hyperframes # HyperFrames composition skills
9
+ npx skills add greensock/gsap-skills # GSAP animation skills
10
+ ```
11
+
12
+ Skills encode patterns like `window.__timelines` registration, `data-*` attribute semantics, and shader-compatible CSS rules that are not in generic web docs. Using them produces correct compositions from the start.
13
+
14
+ ## Commands
15
+
16
+ ```bash
17
+ npx hyperframes preview # preview in browser (studio editor)
18
+ npx hyperframes render # render to MP4
19
+ npx hyperframes lint # validate compositions (errors + warnings)
20
+ npx hyperframes lint --json # machine-readable output for CI
21
+ npx hyperframes docs <topic> # reference docs in terminal
22
+ ```
23
+
24
+ ## Project Structure
25
+
26
+ - `index.html` — main composition (root timeline)
27
+ - `compositions/` — sub-compositions referenced via `data-composition-src`
28
+ - `assets/` — media files (video, audio, images)
29
+ - `meta.json` — project metadata (id, name)
30
+ - `transcript.json` — whisper word-level transcript (if generated)
31
+
32
+ ## Linting — Always Run After Changes
33
+
34
+ After creating or editing any `.html` composition, run the linter before considering the task complete:
35
+
36
+ ```bash
37
+ npx hyperframes lint
38
+ ```
39
+
40
+ Fix all errors before presenting the result.
41
+
42
+ ## Key Rules
43
+
44
+ 1. Every timed element needs `data-start`, `data-duration`, and `data-track-index`
45
+ 2. Visible timed elements **must** have `class="clip"` — the framework uses this for visibility control
46
+ 3. GSAP timelines must be paused and registered on `window.__timelines`:
47
+ ```js
48
+ window.__timelines = window.__timelines || {};
49
+ window.__timelines["composition-id"] = gsap.timeline({ paused: true });
50
+ ```
51
+ 4. Videos use `muted` with a separate `<audio>` element for the audio track
52
+ 5. Sub-compositions use `data-composition-src="compositions/file.html"`
53
+ 6. Only deterministic logic — no `Date.now()`, no `Math.random()`, no network fetches
54
+
55
+ ## Documentation
56
+
57
+ Full docs: https://hyperframes.heygen.com/introduction
58
+
59
+ Machine-readable index for AI tools: https://hyperframes.heygen.com/llms.txt
@@ -2,13 +2,13 @@
2
2
 
3
3
  ## Skills — USE THESE FIRST
4
4
 
5
- **Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `class="clip"`, `window.__timelines`, `data-*` attributes) that are NOT in generic web docs. Skipping them produces broken compositions.
5
+ **Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
6
6
 
7
- | Skill | Command | When to use |
8
- | ------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------- |
9
- | **hyperframes** | `/hyperframes` | Creating or editing HTML compositions, captions, TTS, audio-reactive animation, marker highlights |
10
- | **hyperframes-cli** | `/hyperframes-cli` | CLI commands: init, lint, preview, render, transcribe, tts |
11
- | **gsap** | `/gsap` | GSAP animations — tweens, timelines, easing, ScrollTrigger, plugins, React/Vue/Svelte, performance optimization |
7
+ | Skill | Command | When to use |
8
+ | ------------------- | ------------------ | ------------------------------------------------------------------------------------------------- |
9
+ | **hyperframes** | `/hyperframes` | Creating or editing HTML compositions, captions, TTS, audio-reactive animation, marker highlights |
10
+ | **hyperframes-cli** | `/hyperframes-cli` | CLI commands: init, lint, preview, render, transcribe, tts |
11
+ | **gsap** | `/gsap` | GSAP animations for HyperFrames — tweens, timelines, easing, performance |
12
12
 
13
13
  > **Skills not available?** Ask the user to run `npx hyperframes skills` and restart their
14
14
  > agent session, or install manually: `npx skills add heygen-com/hyperframes` and
@@ -33,7 +33,7 @@ npx hyperframes docs <topic> # reference docs in terminal
33
33
  npx hyperframes docs <topic>
34
34
  ```
35
35
 
36
- Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `templates`, `troubleshooting`
36
+ Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
37
37
 
38
38
  **For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
39
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperframes",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "HyperFrames CLI — create, preview, and render HTML video compositions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,56 +0,0 @@
1
- # GSAP with Vue, Svelte, and Other Frameworks
2
-
3
- For **React**, see [react.md](react.md).
4
-
5
- ## Principles (All Frameworks)
6
-
7
- - **Create** tweens/ScrollTriggers **after** DOM is available (onMounted/onMount).
8
- - **Kill or revert** in unmount cleanup.
9
- - **Scope selectors** to component root via `gsap.context(callback, scope)`.
10
-
11
- ## Vue 3 (Composition API / script setup)
12
-
13
- ```javascript
14
- import { onMounted, onUnmounted, ref } from "vue";
15
- import { gsap } from "gsap";
16
-
17
- const container = ref(null);
18
- let ctx;
19
-
20
- onMounted(() => {
21
- ctx = gsap.context(() => {
22
- gsap.to(".box", { x: 100 });
23
- gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
24
- }, container.value);
25
- });
26
-
27
- onUnmounted(() => ctx?.revert());
28
- ```
29
-
30
- ## Svelte
31
-
32
- ```javascript
33
- import { onMount } from "svelte";
34
- import { gsap } from "gsap";
35
-
36
- let container;
37
- onMount(() => {
38
- const ctx = gsap.context(() => {
39
- gsap.to(".box", { x: 100 });
40
- }, container);
41
- return () => ctx.revert();
42
- });
43
- ```
44
-
45
- Use `bind:this={container}` for the root element ref.
46
-
47
- ## ScrollTrigger Cleanup
48
-
49
- ScrollTriggers inside `gsap.context()` are reverted by `ctx.revert()`. Call `ScrollTrigger.refresh()` after layout changes (nextTick in Vue, tick in Svelte).
50
-
51
- ## Do Not
52
-
53
- - Create tweens before the component is mounted.
54
- - Use selector strings without a scope.
55
- - Skip cleanup — always revert context on unmount.
56
- - Register plugins inside re-rendering component bodies.
@@ -1,194 +0,0 @@
1
- # GSAP Plugins
2
-
3
- Register each plugin once before use:
4
-
5
- ```javascript
6
- import gsap from "gsap";
7
- import { ScrollToPlugin } from "gsap/ScrollToPlugin";
8
- import { Flip } from "gsap/Flip";
9
- gsap.registerPlugin(ScrollToPlugin, Flip);
10
- ```
11
-
12
- ## Table of Contents
13
-
14
- - [ScrollToPlugin](#scrolltoplugin)
15
- - [ScrollSmoother](#scrollsmoother)
16
- - [Flip](#flip)
17
- - [Draggable + Inertia](#draggable)
18
- - [Observer](#observer)
19
- - [SplitText](#splittext)
20
- - [ScrambleText](#scrambletext)
21
- - [DrawSVG](#drawsvg)
22
- - [MorphSVG](#morphsvg)
23
- - [MotionPath](#motionpath)
24
- - [CustomEase / EasePack](#customeaseeasepak)
25
- - [Physics2D / PhysicsProps](#physics)
26
- - [GSDevTools](#gsdevtools)
27
- - [PixiPlugin](#pixiplugin)
28
-
29
- ---
30
-
31
- ## ScrollToPlugin
32
-
33
- Animate scroll position (window or scrollable element).
34
-
35
- ```javascript
36
- gsap.to(window, { scrollTo: { y: "#section", offsetY: 50 }, duration: 1 });
37
- gsap.to(scrollContainer, { scrollTo: { x: "max" }, duration: 1 });
38
- ```
39
-
40
- ## ScrollSmoother
41
-
42
- Smooth scroll wrapper. Requires ScrollTrigger + specific DOM structure (`#smooth-wrapper` > `#smooth-content`).
43
-
44
- ## Flip
45
-
46
- FLIP layout transitions: capture state, change DOM, animate from old to new.
47
-
48
- ```javascript
49
- const state = Flip.getState(".item");
50
- // change DOM (reorder, add/remove, change classes)
51
- Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
52
- ```
53
-
54
- Options: `absolute`, `nested`, `scale`, `simple`, `duration`, `ease`.
55
-
56
- ## Draggable
57
-
58
- Makes elements draggable/spinnable/throwable.
59
-
60
- ```javascript
61
- gsap.registerPlugin(Draggable, InertiaPlugin);
62
- Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
63
- Draggable.create(".knob", { type: "rotation" });
64
- ```
65
-
66
- Types: `"x"`, `"y"`, `"x,y"`, `"rotation"`, `"scroll"`. Options: `bounds`, `inertia`, `edgeResistance`, `cursor`, drag callbacks.
67
-
68
- ### Inertia (InertiaPlugin)
69
-
70
- Momentum after release with Draggable, or track velocity of any property:
71
-
72
- ```javascript
73
- InertiaPlugin.track(".box", "x");
74
- gsap.to(obj, { inertia: { x: "auto" } });
75
- ```
76
-
77
- ## Observer
78
-
79
- Normalized pointer/scroll input across devices. Use for swipe/gesture detection.
80
-
81
- ```javascript
82
- Observer.create({
83
- target: "#area",
84
- onUp: () => {},
85
- onDown: () => {},
86
- tolerance: 10,
87
- });
88
- ```
89
-
90
- ## SplitText
91
-
92
- Split text into chars, words, lines for per-unit animation.
93
-
94
- ```javascript
95
- const split = SplitText.create(".heading", { type: "words, chars" });
96
- gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03 });
97
- // later: split.revert()
98
- ```
99
-
100
- Key options: `type` (comma-separated: chars/words/lines), `charsClass`/`wordsClass`/`linesClass`, `aria` ("auto"/"hidden"/"none"), `autoSplit` + `onSplit(self)` for font-safe re-splitting, `mask` (lines/words/chars for reveal effects), `tag`, `ignore`, `smartWrap`, `propIndex`.
101
-
102
- Tips: Split only what's animated. For custom fonts, use `autoSplit: true` with `onSplit()`. Avoid `text-wrap: balance`.
103
-
104
- ## ScrambleText
105
-
106
- Scramble/glitch text effect.
107
-
108
- ```javascript
109
- gsap.to(".text", { scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 } });
110
- ```
111
-
112
- ## DrawSVG
113
-
114
- Animate SVG stroke reveal (stroke-dashoffset/dasharray). Element must have `stroke` and `stroke-width`.
115
-
116
- ```javascript
117
- gsap.from("#path", { drawSVG: 0, duration: 1 }); // nothing to full stroke
118
- gsap.to("#path", { drawSVG: "20% 80%", duration: 1 }); // partial segment
119
- ```
120
-
121
- `drawSVG` value = visible segment: `"start end"` in % or length. Single value (e.g. `0`) means start is 0.
122
-
123
- ## MorphSVG
124
-
125
- Morph one SVG shape into another. Handles different point counts.
126
-
127
- ```javascript
128
- MorphSVGPlugin.convertToPath("circle, rect, ellipse, line");
129
- gsap.to("#diamond", { morphSVG: "#lightning", duration: 1 });
130
- // object form: { shape, type: "rotational", shapeIndex, smooth, curveMode }
131
- ```
132
-
133
- Use `shapeIndex: "log"` to find optimal value. `type: "rotational"` avoids kinks.
134
-
135
- ## MotionPath
136
-
137
- Animate along an SVG path.
138
-
139
- ```javascript
140
- gsap.to(".dot", {
141
- motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5], autoRotate: true },
142
- });
143
- ```
144
-
145
- ## CustomEase/EasePack
146
-
147
- Custom curves beyond built-in eases:
148
-
149
- ```javascript
150
- const ease = CustomEase.create("name", ".17,.67,.83,.67");
151
- // or SVG path data for complex curves
152
- const hop = CustomEase.create("hop", "M0,0 C0,0 0.056,0.442 ...");
153
- ```
154
-
155
- EasePack adds SlowMo, RoughEase, ExpoScaleEase. CustomWiggle for oscillation. CustomBounce for configurable bounces.
156
-
157
- ## Physics
158
-
159
- ### Physics2D
160
-
161
- ```javascript
162
- gsap.to(".ball", { physics2D: { velocity: 250, angle: 80, gravity: 500 }, duration: 2 });
163
- ```
164
-
165
- ### PhysicsProps
166
-
167
- ```javascript
168
- gsap.to(".obj", {
169
- physicsProps: { x: { velocity: 100, end: 300 }, y: { velocity: -50, acceleration: 200 } },
170
- duration: 2,
171
- });
172
- ```
173
-
174
- ## GSDevTools
175
-
176
- Timeline scrubbing UI for development. **Do not ship to production.**
177
-
178
- ```javascript
179
- GSDevTools.create({ animation: tl });
180
- ```
181
-
182
- ## PixiPlugin
183
-
184
- Integrates GSAP with PixiJS display objects.
185
-
186
- ```javascript
187
- gsap.to(sprite, { pixi: { x: 200, scale: 1.5 }, duration: 1 });
188
- ```
189
-
190
- ## Do Not
191
-
192
- - Use a plugin without registering it first.
193
- - Ship GSDevTools to production.
194
- - Forget to revert SplitText instances on unmount.
@@ -1,80 +0,0 @@
1
- # GSAP with React
2
-
3
- ## Installation
4
-
5
- ```bash
6
- npm install gsap @gsap/react
7
- ```
8
-
9
- ## useGSAP() Hook (Preferred)
10
-
11
- ```javascript
12
- import { useGSAP } from "@gsap/react";
13
- gsap.registerPlugin(useGSAP);
14
-
15
- const containerRef = useRef(null);
16
- useGSAP(
17
- () => {
18
- gsap.to(".box", { x: 100 });
19
- },
20
- { scope: containerRef },
21
- );
22
- ```
23
-
24
- - Pass **scope** (ref) so selectors are scoped to the component.
25
- - Cleanup runs automatically on unmount.
26
- - Use **contextSafe** for callbacks created after useGSAP executes:
27
-
28
- ```javascript
29
- useGSAP(
30
- (context, contextSafe) => {
31
- const onClick = contextSafe(() => {
32
- gsap.to(ref.current, { rotation: 180 });
33
- });
34
- ref.current.addEventListener("click", onClick);
35
- return () => ref.current.removeEventListener("click", onClick);
36
- },
37
- { scope: container },
38
- );
39
- ```
40
-
41
- ## Dependency Array and revertOnUpdate
42
-
43
- ```javascript
44
- useGSAP(
45
- () => {
46
- /* gsap code */
47
- },
48
- {
49
- dependencies: [endX],
50
- scope: container,
51
- revertOnUpdate: true, // reverts + re-runs on dependency change
52
- },
53
- );
54
- ```
55
-
56
- ## gsap.context() in useEffect (Fallback)
57
-
58
- When @gsap/react isn't available:
59
-
60
- ```javascript
61
- useEffect(() => {
62
- const ctx = gsap.context(() => {
63
- gsap.to(".box", { x: 100 });
64
- }, containerRef);
65
- return () => ctx.revert();
66
- }, []);
67
- ```
68
-
69
- Always return `ctx.revert()` in cleanup.
70
-
71
- ## SSR (Next.js)
72
-
73
- GSAP runs in the browser. Keep all GSAP code inside useGSAP or useEffect.
74
-
75
- ## Do Not
76
-
77
- - Target by selector without a scope — always pass scope.
78
- - Skip cleanup — always revert context or kill tweens on unmount.
79
- - Run GSAP during SSR.
80
- - Register plugins inside components that re-render — register once at app level.
@@ -1,147 +0,0 @@
1
- # ScrollTrigger
2
-
3
- ## Registering
4
-
5
- ```javascript
6
- gsap.registerPlugin(ScrollTrigger);
7
- ```
8
-
9
- ## Basic Trigger
10
-
11
- ```javascript
12
- gsap.to(".box", {
13
- x: 500,
14
- scrollTrigger: {
15
- trigger: ".box",
16
- start: "top center",
17
- end: "bottom center",
18
- toggleActions: "play reverse play reverse",
19
- },
20
- });
21
- ```
22
-
23
- **start/end** format: `"triggerPosition viewportPosition"`. Examples: `"top top"`, `"center center"`, `"bottom 80%"`, numeric px `500`, relative `"+=300"`, `"+=100%"` (scroller height), `"max"`. Wrap in `clamp()` (v3.12+): `"clamp(top bottom)"`. Can be a function returning string/number.
24
-
25
- ## Key Config Options
26
-
27
- | Property | Type | Description |
28
- | ----------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
29
- | **trigger** | String/Element | Element whose position defines start. Required. |
30
- | **start** | String/Number/Function | When active. Default `"top bottom"` (or `"top top"` if pinned). |
31
- | **end** | String/Number/Function | When ends. Default `"bottom top"`. |
32
- | **endTrigger** | String/Element | Different element for end calculation. |
33
- | **scrub** | Boolean/Number | Link progress to scroll. `true` = direct; number = catch-up seconds. |
34
- | **toggleActions** | String | Four actions: onEnter, onLeave, onEnterBack, onLeaveBack. Values: play/pause/resume/reset/restart/complete/reverse/none. Default `"play none none none"`. |
35
- | **pin** | Boolean/String/Element | Pin element while active. `true` = pin trigger. Animate children, not the pinned element. |
36
- | **pinSpacing** | Boolean/String | Default `true` (adds spacer). `false` or `"margin"`. |
37
- | **horizontal** | Boolean | For horizontal scrolling. |
38
- | **scroller** | String/Element | Scroll container (default: viewport). |
39
- | **markers** | Boolean/Object | Dev markers. Remove in production. |
40
- | **once** | Boolean | Kill after end reached once. |
41
- | **snap** | Number/Array/Function/"labels"/Object | Snap to progress values. |
42
- | **containerAnimation** | Tween/Timeline | For fake horizontal scroll (see below). |
43
- | **toggleClass** | String/Object | Add/remove class when active. |
44
- | **onEnter/onLeave/onEnterBack/onLeaveBack** | Function | Callbacks; receive ScrollTrigger instance. |
45
- | **onUpdate/onToggle/onRefresh/onScrubComplete** | Function | Progress/state callbacks. |
46
-
47
- **Standalone** (no linked tween): `ScrollTrigger.create({...})` with callbacks.
48
-
49
- ## Scrub
50
-
51
- ```javascript
52
- scrollTrigger: { trigger: ".box", start: "top center", end: "bottom center", scrub: true }
53
- ```
54
-
55
- `scrub: true` = direct link; number (e.g. `1`) = smooth lag.
56
-
57
- ## Pinning
58
-
59
- ```javascript
60
- scrollTrigger: {
61
- trigger: ".section", start: "top top", end: "+=1000", pin: true, scrub: 1
62
- }
63
- ```
64
-
65
- ## Timeline + ScrollTrigger
66
-
67
- ```javascript
68
- const tl = gsap.timeline({
69
- scrollTrigger: { trigger: ".container", start: "top top", end: "+=2000", scrub: 1, pin: true },
70
- });
71
- tl.to(".a", { x: 100 }).to(".b", { y: 50 });
72
- ```
73
-
74
- ## ScrollTrigger.batch()
75
-
76
- Creates one ScrollTrigger per target, batches callbacks within a short interval. Good for staggered reveal of many elements.
77
-
78
- ```javascript
79
- ScrollTrigger.batch(".box", {
80
- onEnter: (elements) => gsap.to(elements, { opacity: 1, y: 0, stagger: 0.15 }),
81
- start: "top 80%",
82
- });
83
- ```
84
-
85
- Options: `interval` (batch window), `batchMax` (max per batch). Callbacks receive `(targets, scrollTriggers)`.
86
-
87
- ## Horizontal Scroll (containerAnimation)
88
-
89
- Pin a section, animate inner content's `x`/`xPercent` horizontally on vertical scroll:
90
-
91
- 1. Pin the section
92
- 2. Animate inner content with **ease: "none"** (required)
93
- 3. Attach ScrollTrigger with pin + scrub
94
- 4. Use `containerAnimation` on nested triggers
95
-
96
- ```javascript
97
- const scrollTween = gsap.to(scrollingEl, {
98
- xPercent: () => Math.max(0, window.innerWidth - scrollingEl.offsetWidth),
99
- ease: "none",
100
- scrollTrigger: {
101
- trigger: scrollingEl,
102
- pin: scrollingEl.parentNode,
103
- start: "top top",
104
- end: "+=1000",
105
- },
106
- });
107
-
108
- gsap.to(".nested", {
109
- y: 100,
110
- scrollTrigger: { containerAnimation: scrollTween, trigger: ".wrapper", start: "left center" },
111
- });
112
- ```
113
-
114
- Pinning and snapping unavailable on containerAnimation-based ScrollTriggers.
115
-
116
- ## ScrollTrigger.scrollerProxy()
117
-
118
- Override scroll position reading for third-party smooth-scroll libraries. Call `ScrollTrigger.update` when the scroller updates.
119
-
120
- ```javascript
121
- ScrollTrigger.scrollerProxy(document.body, {
122
- scrollTop(value) {
123
- if (arguments.length) scrollbar.scrollTop = value;
124
- return scrollbar.scrollTop;
125
- },
126
- getBoundingClientRect() {
127
- return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
128
- },
129
- });
130
- scrollbar.addListener(ScrollTrigger.update);
131
- ```
132
-
133
- ## Refresh and Cleanup
134
-
135
- - `ScrollTrigger.refresh()` — recalculate after DOM/layout changes. Auto on resize (200ms debounce).
136
- - Create ScrollTriggers top-to-bottom or set `refreshPriority`.
137
- - Kill instances when removing elements: `ScrollTrigger.getAll().forEach(t => t.kill())` or `ScrollTrigger.getById("id")?.kill()`.
138
-
139
- ## Do Not
140
-
141
- - Put ScrollTrigger on child tweens inside a timeline — put on the timeline.
142
- - Nest ScrollTriggered animations inside a parent timeline.
143
- - Use scrub and toggleActions together (scrub wins).
144
- - Use an ease other than "none" on the horizontal animation with containerAnimation.
145
- - Leave markers in production.
146
- - Create triggers in random order without refreshPriority.
147
- - Forget refresh() after layout changes.
@@ -1,91 +0,0 @@
1
- # gsap.utils
2
-
3
- Pure helpers on `gsap.utils`. No registration needed.
4
-
5
- **Function form:** Most utils accept the value as the last argument. Omit it to get a reusable function: `gsap.utils.clamp(0, 100)(150)`. Exception: `random()` — pass `true` as the last argument for a reusable function.
6
-
7
- ## Clamping and Ranges
8
-
9
- ### clamp(min, max, value?)
10
-
11
- ```javascript
12
- gsap.utils.clamp(0, 100, 150); // 100
13
- let c = gsap.utils.clamp(0, 100);
14
- c(150); // 100
15
- ```
16
-
17
- ### mapRange(inMin, inMax, outMin, outMax, value?)
18
-
19
- ```javascript
20
- gsap.utils.mapRange(0, 1, 0, 360, 0.5); // 180
21
- let m = gsap.utils.mapRange(0, 100, 0, 500);
22
- m(50); // 250
23
- ```
24
-
25
- ### normalize(min, max, value?)
26
-
27
- Returns 0-1 for the range.
28
-
29
- ```javascript
30
- gsap.utils.normalize(0, 100, 50); // 0.5
31
- ```
32
-
33
- ### interpolate(start, end, progress?)
34
-
35
- Numbers, colors, or objects with matching keys.
36
-
37
- ```javascript
38
- gsap.utils.interpolate(0, 100, 0.5); // 50
39
- gsap.utils.interpolate("#ff0000", "#0000ff", 0.5); // mid color
40
- ```
41
-
42
- ## Random and Snap
43
-
44
- ### random(min, max[, snap, returnFunction]) / random(array[, returnFunction])
45
-
46
- ```javascript
47
- gsap.utils.random(-100, 100);
48
- gsap.utils.random(0, 500, 5); // snapped to 5
49
- let fn = gsap.utils.random(-200, 500, 10, true);
50
- fn(); // reusable
51
- gsap.utils.random(["red", "blue"]); // pick one
52
- ```
53
-
54
- **String form in tweens:** `x: "random(-100, 100, 5)"`.
55
-
56
- ### snap(snapTo, value?)
57
-
58
- ```javascript
59
- gsap.utils.snap(10, 23); // 20
60
- gsap.utils.snap([0, 100, 200], 150); // nearest
61
- ```
62
-
63
- ### shuffle(array)
64
-
65
- Returns shuffled copy.
66
-
67
- ### distribute(config)
68
-
69
- Returns a function assigning values by position. Config: `base`, `amount`/`each`, `from`, `grid`, `axis`, `ease`.
70
-
71
- ```javascript
72
- gsap.to(".class", { scale: gsap.utils.distribute({ base: 0.5, amount: 2.5, from: "center" }) });
73
- ```
74
-
75
- ## Units and Parsing
76
-
77
- - **getUnit(value)** — `gsap.utils.getUnit("100px")` → `"px"`
78
- - **unitize(value, unit)** — `gsap.utils.unitize(100, "px")` → `"100px"`
79
- - **splitColor(color, returnHSL?)** — `gsap.utils.splitColor("red")` → `[255, 0, 0]`. Pass `true` for HSL.
80
-
81
- ## Arrays and Collections
82
-
83
- - **selector(scope)** — scoped selector: `gsap.utils.selector(ref)(".box")`
84
- - **toArray(value, scope?)** — convert selector/NodeList/element to array
85
- - **pipe(...fns)** — compose: `pipe(f1, f2)(value)` = `f2(f1(value))`
86
- - **wrap(min, max, value?)** — cyclic wrap: `wrap(0, 360, 370)` → `10`
87
- - **wrapYoyo(min, max, value?)** — bounce wrap: `wrapYoyo(0, 100, 150)` → `50`
88
-
89
- ## Do Not
90
-
91
- - Assume mapRange/normalize handle units — they work on numbers. Use getUnit/unitize.